From af0c41e162725b0edcd6c3d066a2dbef05a3b896 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 7 Jul 2013 23:54:11 +0200 Subject: Remove old demuxers Delete demux_avi, demux_asf, demux_mpg, demux_ts. libavformat does better than them (except in rare corner cases), and the demuxers have a bad influence on the rest of the code. Often they don't output proper packets, and require additional audio and video parsing. Most work only in --no-correct-pts mode. Remove them to facilitate further cleanups. --- demux/demux.c | 140 +--------------------------------------------------------- 1 file changed, 2 insertions(+), 138 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index a5d3211b0a..3f5851e5b6 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -55,18 +55,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; @@ -86,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 @@ -234,7 +216,6 @@ static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, .stream_type = type, .id = id, .demuxer = demuxer, - .asf_seq = -1, }; return ds; } @@ -357,34 +338,6 @@ 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); @@ -610,9 +563,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; @@ -716,65 +667,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; @@ -783,11 +675,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; @@ -1019,22 +906,6 @@ 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); @@ -1099,14 +970,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; } -- cgit v1.2.3 From aac5d758c5a60f13162bc2b500618389bfd92602 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 00:13:53 +0200 Subject: demux: remove audio parser The audio parser was needed only by the "old" demuxers, and demux_rawaudio. All other demuxers output already parsed packets. demux_rawaudio is usually for raw audio, so using a parser with it doesn't usually make sense. But you can also force it to read compressed formats with fixed packet sizes, in which case the parser would have been used. This use case is probably broken now, but you will be able to do the same thing with libavformat demuxers. --- audio/decode/ad_lavc.c | 11 +++----- audio/decode/ad_spdif.c | 20 ++------------ demux/demux.c | 70 ------------------------------------------------- demux/demux.h | 3 --- demux/demux_rawaudio.c | 1 - demux/stheader.h | 4 --- 6 files changed, 5 insertions(+), 104 deletions(-) (limited to 'demux/demux.c') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index b5a4ee1ef8..2495012e47 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -344,7 +344,6 @@ static int control(sh_audio_t *sh, int cmd, void *arg) switch (cmd) { case ADCTRL_RESYNC_STREAM: avcodec_flush_buffers(ctx->avctx); - ds_clear_parser(sh->ds); ctx->previous_data_left = 0; ctx->output_left = 0; return CONTROL_TRUE; @@ -384,10 +383,7 @@ static int decode_new_packet(struct sh_audio *sh) if (!mpkt) { assert(!priv->previous_data_left); start = NULL; - insize = 0; - ds_parse(sh->ds, &start, &insize, pts, 0); - if (insize <= 0) - return -1; // error or EOF + return -1; // error or EOF } else { assert(mpkt->len >= priv->previous_data_left); if (!priv->previous_data_left) { @@ -396,8 +392,7 @@ static int decode_new_packet(struct sh_audio *sh) } insize = priv->previous_data_left; start = mpkt->buffer + mpkt->len - priv->previous_data_left; - int consumed = ds_parse(sh->ds, &start, &insize, pts, 0); - priv->previous_data_left -= consumed; + priv->previous_data_left -= insize; priv->previous_data_left = FFMAX(priv->previous_data_left, 0); } @@ -420,7 +415,7 @@ static int decode_new_packet(struct sh_audio *sh) return -1; } // The "insize >= ret" test is sanity check against decoder overreads - if (!sh->parser && insize >= ret) + if (insize >= ret) priv->previous_data_left = insize - ret; if (!got_frame) return 0; diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 1314110062..49b7d9a0d8 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -132,20 +132,8 @@ static int init(sh_audio_t *sh, const char *decoder) pts = MP_NOPTS_VALUE; x = 0; } - ds_parse(sh->ds, &start, &x, pts, 0); srate = 48000; //fake value bps = 768000/8; //fake value - if (x && sh->avctx) { // we have parser and large enough buffer - if (sh->avctx->sample_rate < 44100) { - mp_msg(MSGT_DECAUDIO,MSGL_INFO, - "This stream sample_rate[%d Hz] may be broken. " - "Force reset 48000Hz.\n", - sh->avctx->sample_rate); - srate = 48000; //fake value - } else - srate = sh->avctx->sample_rate; - bps = sh->avctx->bit_rate/8; - } sh->ds->buffer_pos -= in_size; int num_channels = 0; @@ -239,14 +227,10 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, break; x = ds_get_packet_pts(sh->ds, &start, &pts); if (x <= 0) { - x = 0; - ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); - if (x == 0) - continue; // END_NOT_FOUND - in_size = x; + continue; // END_NOT_FOUND } else { in_size = x; - consumed = ds_parse(sh->ds, &start, &x, pts, 0); + consumed = x; if (x == 0) { mp_msg(MSGT_DECAUDIO,MSGL_V, "start[%p] in_size[%d] consumed[%d] x[%d].\n", diff --git a/demux/demux.c b/demux/demux.c index 3f5851e5b6..9d02abc8f1 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; @@ -370,7 +368,6 @@ static void free_sh_audio(demuxer_t *demuxer, int id) 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); } @@ -467,73 +464,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) { diff --git a/demux/demux.h b/demux/demux.h index df73ddd4ee..a478e58409 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -292,9 +292,6 @@ int ds_get_packet_pts(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, - int64_t pos); -void ds_clear_parser(struct demux_stream *sh); struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, int file_format, int aid, int vid, int sid, diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 3cd2500e03..b680a77888 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -70,7 +70,6 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { demuxer->audio->id = 0; demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; - sh_audio->needs_parsing = 1; return demuxer; } diff --git a/demux/stheader.h b/demux/stheader.h index 475d063637..511e959c30 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -117,10 +117,6 @@ typedef struct sh_audio { unsigned char *codecdata; int codecdata_len; int pts_bytes; // bytes output by decoder after last known pts - /* things needed for parsing */ - bool needs_parsing; - struct AVCodecContext *avctx; - struct AVCodecParserContext *parser; } sh_audio_t; typedef struct sh_video { -- cgit v1.2.3 From c4f33d784a058325b26ba82f34c43dab0cb19dc8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 00:35:04 +0200 Subject: demux: remove some old stream header functions --- demux/demux.c | 36 ------------------------------------ demux/demux_mf.c | 3 ++- demux/demux_mng.c | 3 ++- demux/demux_rawaudio.c | 4 +++- demux/demux_rawvideo.c | 4 +++- demux/stheader.h | 5 ----- stream/tv.c | 6 ++++-- 7 files changed, 14 insertions(+), 47 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 9d02abc8f1..6506677275 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -343,24 +343,6 @@ static void free_sh_sub(sh_sub_t *sh) 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) { sh_audio_t *sh = demuxer->a_streams[id]; @@ -371,24 +353,6 @@ static void free_sh_audio(demuxer_t *demuxer, int id) free_sh_stream(sh->gsh); } -sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid) -{ - 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]; -} - static void free_sh_video(sh_video_t *sh) { mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh); diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 127ee8474e..7e2757e155 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -206,7 +206,8 @@ static demuxer_t* demux_open_mf(demuxer_t* demuxer){ demuxer->movi_end = mf->nr_of_files - 1; // create a new video stream header - sh_video = new_sh_video(demuxer, 0); + struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); + sh_video = sh->video; // make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it) demuxer->video->sh = sh_video; diff --git a/demux/demux_mng.c b/demux/demux_mng.c index bd86b3e3b8..4b2077d31f 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -423,7 +423,8 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) } // create a new video stream header - sh_video = new_sh_video(demuxer, 0); + struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); + sh_video = sh->video; // Make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it). diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index b680a77888..5f47efe936 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -44,13 +44,15 @@ const m_option_t demux_rawaudio_opts[] = { static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { + struct sh_stream *sh; sh_audio_t* sh_audio; WAVEFORMATEX* w; if ((format & AF_FORMAT_SPECIAL_MASK) != 0) return NULL; - sh_audio = new_sh_audio(demuxer,0); + sh = new_sh_stream(demuxer, STREAM_AUDIO); + sh_audio = sh->audio; sh_audio->gsh->codec = "mp-pcm"; sh_audio->format = format; sh_audio->wf = w = malloc(sizeof(*w)); diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 1a09b8308a..c0b3b1980d 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -57,6 +57,7 @@ const m_option_t demux_rawvideo_opts[] = { static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { + struct sh_stream *sh; sh_video_t* sh_video; if(!width || !height){ @@ -113,7 +114,8 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { imgsize = width * height * bpp / 8; } - sh_video = new_sh_video(demuxer,0); + sh = new_sh_stream(demuxer, STREAM_VIDEO); + sh_video = sh->video; sh_video->gsh->codec=decoder; sh_video->format=imgfmt; sh_video->fps=fps; diff --git a/demux/stheader.h b/demux/stheader.h index 511e959c30..68b9076b88 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -161,11 +161,6 @@ typedef struct sh_sub { } sh_sub_t; // demuxer.c: -#define new_sh_audio(d, i) new_sh_audio_aid(d, i, i) -struct sh_audio *new_sh_audio_aid(struct demuxer *demuxer, int id, int aid); -#define new_sh_video(d, i) new_sh_video_vid(d, i, i) -struct sh_video *new_sh_video_vid(struct demuxer *demuxer, int id, int vid); -#define new_sh_sub(d, i) new_sh_sub_sid(d, i, i) struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type); // video.c: diff --git a/stream/tv.c b/stream/tv.c index 1fcb13037d..83a0052563 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -708,7 +708,8 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer) funcs = tvh->functions; demuxer->priv=tvh; - sh_video = new_sh_video(demuxer, 0); + struct sh_stream *sh_v = new_sh_stream(demuxer, STREAM_VIDEO); + sh_video = sh_v->video; /* get IMAGE FORMAT */ int fourcc; @@ -786,7 +787,8 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer) goto no_audio; } - sh_audio = new_sh_audio(demuxer, 0); + struct sh_stream *sh_a = new_sh_stream(demuxer, STREAM_AUDIO); + sh_audio = sh_a->audio; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, &sh_audio->samplerate); -- cgit v1.2.3 From 50808bab8db030acd07433e58465d1e71bca2269 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 01:02:45 +0200 Subject: demux: merge functions --- demux/demux.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 6506677275..4068f616cf 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -267,22 +267,25 @@ 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, + .stream_index = demuxer->num_streams, .opts = demuxer->opts, }); MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); @@ -321,17 +324,6 @@ 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) { } -- cgit v1.2.3 From 05ae5afd6249af9770eb1e55104fbd4f510c2342 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 01:26:13 +0200 Subject: demux: remove separate arrays for audio/video/sub streams, simplify These separate arrays were used by the old demuxers and are not needed anymore. We can simplify track switching as well. One interesting thing is that stream/tv.c (which is a demuxer) won't respect --no-audio anymore. It will probably work as expected, but it will still open an audio device etc. - this is because track selection is now always done with the runtime track switching mechanism. Maybe the TV code could be updated to do proper runtime switching, but I can't test this stuff. --- core/command.c | 8 ++--- core/mplayer.c | 15 ++++---- demux/demux.c | 94 +++++++++++++------------------------------------- demux/demux.h | 11 +----- demux/demux_lavf.c | 6 ++-- demux/demux_mf.c | 3 -- demux/demux_mkv.c | 8 ++--- demux/demux_mng.c | 5 --- demux/demux_rawaudio.c | 8 ++--- demux/demux_rawvideo.c | 7 ++-- demux/stheader.h | 2 -- stream/tv.c | 12 ------- 12 files changed, 45 insertions(+), 134 deletions(-) (limited to 'demux/demux.c') diff --git a/core/command.c b/core/command.c index 80f6f5d9d2..fb21d7bc41 100644 --- a/core/command.c +++ b/core/command.c @@ -566,13 +566,13 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: angle = demuxer_set_angle(demuxer, *(int *)arg); if (angle >= 0) { - struct sh_video *sh_video = demuxer->video->sh; + struct sh_stream *sh_video = demuxer->video->gsh; if (sh_video) - resync_video_stream(sh_video); + resync_video_stream(sh_video->video); - struct sh_audio *sh_audio = demuxer->audio->sh; + struct sh_stream *sh_audio = demuxer->audio->gsh; if (sh_audio) - resync_audio_stream(sh_audio); + resync_audio_stream(sh_audio->audio); } return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: { diff --git a/core/mplayer.c b/core/mplayer.c index 16277d2e60..78fb8c9a8e 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -375,7 +375,7 @@ static double get_main_demux_pts(struct MPContext *mpctx) if (mpctx->demuxer) { for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->sh && main_new_pos == MP_NOPTS_VALUE) { + if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) { demux_fill_buffer(mpctx->demuxer, ds); if (ds->first) main_new_pos = ds->first->pts; @@ -445,11 +445,11 @@ static void preselect_demux_streams(struct MPContext *mpctx) static void uninit_subs(struct demuxer *demuxer) { - for (int i = 0; i < MAX_S_STREAMS; i++) { - struct sh_sub *sh = demuxer->s_streams[i]; - if (sh) { - sub_destroy(sh->dec_sub); - sh->dec_sub = NULL; + for (int i = 0; i < demuxer->num_streams; i++) { + struct sh_stream *sh = demuxer->streams[i]; + if (sh->sub) { + sub_destroy(sh->sub->dec_sub); + sh->sub->dec_sub = NULL; } } } @@ -1938,9 +1938,6 @@ static void reinit_subs(struct MPContext *mpctx) // which makes the demuxer create the sh_stream, and contains the first // subtitle event. - // demux_mpg - maps IDs directly to the logical stream number - track->demuxer->sub->id = track->demuxer_id; - // demux_lavf - IDs are essentially random, have to use MPEG IDs int id = map_id_to_demuxer(track->demuxer, track->type, track->demuxer_id); diff --git a/demux/demux.c b/demux/demux.c index 4068f616cf..1d91920054 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -207,12 +207,11 @@ 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, }; return ds; @@ -248,9 +247,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; @@ -285,7 +284,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) .demuxer = demuxer, .index = demuxer->num_streams, .demuxer_id = demuxer_id, // may be overwritten by demuxer - .stream_index = demuxer->num_streams, .opts = demuxer->opts, }); MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); @@ -296,7 +294,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) sht->opts = sh->opts; sht->ds = demuxer->video; sh->video = sht; - demuxer->v_streams[sh->stream_index] = sht; break; } case STREAM_AUDIO: { @@ -307,7 +304,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) sht->samplesize = 2; sht->sample_format = AF_FORMAT_S16_NE; sh->audio = sht; - demuxer->a_streams[sh->stream_index] = sht; break; } case STREAM_SUB: { @@ -316,7 +312,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) sht->opts = sh->opts; sht->ds = demuxer->sub; sh->sub = sht; - demuxer->s_streams[sh->stream_index] = sht; break; } default: assert(false); @@ -324,51 +319,41 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) return sh; } -static void free_sh_stream(struct sh_stream *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); } -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); - free_sh_stream(sh->gsh); } static void free_sh_video(sh_video_t *sh) { - mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh); free(sh->bih); - free_sh_stream(sh->gsh); +} + +static void free_sh_stream(struct sh_stream *sh) +{ + 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); @@ -535,9 +520,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) @@ -1015,48 +998,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, diff --git a/demux/demux.h b/demux/demux.h index 3d632a92c6..93cf680bae 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -107,16 +107,12 @@ typedef struct demux_stream { demux_packet_t *first; // read to current buffer from here demux_packet_t *last; // append new packets from input stream to here demux_packet_t *current; // needed for refcounting of the buffer - int id; // stream ID (for multiple audio/video streams) struct demuxer *demuxer; // parent demuxer structure (stream handler) // ---- stream header ---- - void *sh; // points to sh_audio or sh_video + struct sh_stream *gsh; } demux_stream_t; #define MAX_SH_STREAMS 256 -#define MAX_A_STREAMS MAX_SH_STREAMS -#define MAX_V_STREAMS MAX_SH_STREAMS -#define MAX_S_STREAMS MAX_SH_STREAMS struct demuxer; @@ -220,11 +216,6 @@ typedef struct demuxer { struct demux_stream *video; // video buffer/demuxer struct demux_stream *sub; // dvd subtitle buffer/demuxer - // stream headers: - struct sh_audio *a_streams[MAX_SH_STREAMS]; - struct sh_video *v_streams[MAX_SH_STREAMS]; - struct sh_sub *s_streams[MAX_SH_STREAMS]; - struct sh_stream **streams; int num_streams; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 466ab7537b..aad1edfcde 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -658,11 +658,11 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds) AVStream *st = priv->avfc->streams[pkt->stream_index]; struct sh_stream *stream = priv->streams[pkt->stream_index]; - if (stream && stream->type == STREAM_SUB && demux->sub->id < 0 && + if (stream && stream->type == STREAM_SUB && !demux->sub->gsh && stream->demuxer_id == priv->autoselect_sub) { priv->autoselect_sub = -1; - demux->sub->id = stream->stream_index; + demux->sub->gsh = stream; } if (!demuxer_stream_is_selected(demux, stream)) { @@ -809,7 +809,7 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) } case DEMUXER_CTRL_AUTOSELECT_SUBTITLE: { - demuxer->sub->id = -1; + demuxer->sub->gsh = NULL; priv->autoselect_sub = *((int *)arg); return DEMUXER_CTRL_OK; } diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 7e2757e155..8435c36f37 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -208,9 +208,6 @@ static demuxer_t* demux_open_mf(demuxer_t* demuxer){ // create a new video stream header struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh->video; - // make sure the demuxer knows about the new video stream header - // (even though new_sh_video() ought to take care of it) - demuxer->video->sh = sh_video; sh_video->gsh->codec = probe_format(mf); if (!sh_video->gsh->codec) { diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 724bf6255b..b00c115ef2 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1962,9 +1962,8 @@ static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, } else dp->pts = real_fix_timestamp(dp->buffer, timestamp, - ((sh_video_t *) demuxer->video->sh)->bih-> - biCompression, &track->rv_kf_base, - &track->rv_kf_pts, NULL); + demuxer->video->gsh->video->bih->biCompression, + &track->rv_kf_base, &track->rv_kf_pts, NULL); dp->pos = demuxer->filepos; dp->keyframe = keyframe; @@ -2047,8 +2046,7 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, if (track->sub_packet_cnt == 0) track->audio_filepos = demuxer->filepos; if (++(track->sub_packet_cnt) == sph) { - int apk_usize = - ((sh_audio_t *) demuxer->audio->sh)->wf->nBlockAlign; + int apk_usize = demuxer->audio->gsh->audio->wf->nBlockAlign; track->sub_packet_cnt = 0; // Release all the audio packets for (x = 0; x < sph * w / apk_usize; x++) { diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 4b2077d31f..1f73399902 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -426,11 +426,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh->video; - // Make sure the demuxer knows about the new video stream header - // (even though new_sh_video() ought to take care of it). - // (Thanks to demux_gif.c for this.) - demuxer->video->sh = sh_video; - // Make sure that the video demuxer stream header knows about its // parent video demuxer stream (this is getting wacky), or else // video_read_properties() will choke. diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 5f47efe936..50e4e4a68b 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -69,15 +69,11 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { demuxer->movi_start = demuxer->stream->start_pos; demuxer->movi_end = demuxer->stream->end_pos; - demuxer->audio->id = 0; - demuxer->audio->sh = sh_audio; - sh_audio->ds = demuxer->audio; - return demuxer; } static int demux_rawaudio_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { - sh_audio_t* sh_audio = demuxer->audio->sh; + sh_audio_t* sh_audio = demuxer->audio->gsh->audio; int l = sh_audio->wf->nAvgBytesPerSec; int64_t spos = stream_tell(demuxer->stream); demux_packet_t* dp; @@ -98,7 +94,7 @@ static int demux_rawaudio_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { static void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ stream_t* s = demuxer->stream; - sh_audio_t* sh_audio = demuxer->audio->sh; + sh_audio_t* sh_audio = demuxer->audio->gsh->audio; int64_t base,pos; base = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s); diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index c0b3b1980d..6834bfb23a 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -127,14 +127,11 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { demuxer->movi_start = demuxer->stream->start_pos; demuxer->movi_end = demuxer->stream->end_pos; - demuxer->video->sh = sh_video; - sh_video->ds = demuxer->video; - return demuxer; } static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { - sh_video_t* sh = demuxer->video->sh; + sh_video_t* sh = demuxer->video->gsh->video; int64_t pos; if(demuxer->stream->eof) return 0; if(ds!=demuxer->video) return 0; @@ -145,7 +142,7 @@ static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ stream_t* s = demuxer->stream; - sh_video_t* sh_video = demuxer->video->sh; + sh_video_t* sh_video = demuxer->video->gsh->video; int64_t pos; pos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s); diff --git a/demux/stheader.h b/demux/stheader.h index a4ae0b28bb..b2dc2018d2 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -42,8 +42,6 @@ struct sh_stream { struct demuxer *demuxer; // Index into demuxer->streams. int index; - // Index into stream array (currently one array per type, e.g. a_streams). - int stream_index; // Demuxer/format specific ID. Corresponds to the stream IDs as encoded in // some file formats (e.g. MPEG), or an index chosen by demux.c. int demuxer_id; diff --git a/stream/tv.c b/stream/tv.c index 83a0052563..e5768a350a 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -739,20 +739,12 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer) tvh->tv_param->noaudio = 1; } - /* disable TV audio if -nosound is present */ - if (!demuxer->audio || demuxer->audio->id == -2) { - tvh->tv_param->noaudio = 1; - } - /* set width */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); /* set height */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); - demuxer->video->sh = sh_video; - sh_video->ds = demuxer->video; - demuxer->video->id = 0; demuxer->seekable = 0; /* here comes audio init */ @@ -818,10 +810,6 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer) mp_tmsg(MSGT_DECVIDEO, MSGL_V, " TV audio: %d channels, %d bits, %d Hz\n", sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, sh_audio->wf->nSamplesPerSec); - - demuxer->audio->sh = sh_audio; - sh_audio->ds = demuxer->audio; - demuxer->audio->id = 0; } no_audio: -- cgit v1.2.3 From 73c76de91edbf8a55eb725196ff54583e3428510 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 01:37:30 +0200 Subject: demux: simplify demux_open() calls The demux_open as well as demux_open_withparams calls don't use the stream selection parameters anymore, so remove them everywhere. Completes the previous commit. --- core/mplayer.c | 11 +---------- core/timeline/tl_cue.c | 12 ++---------- core/timeline/tl_edl.c | 3 --- core/timeline/tl_matroska.c | 3 +-- demux/demux.c | 27 +++++++++------------------ demux/demux.h | 6 ++---- 6 files changed, 15 insertions(+), 47 deletions(-) (limited to 'demux/demux.c') diff --git a/core/mplayer.c b/core/mplayer.c index 78fb8c9a8e..019d37081d 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -3890,20 +3890,12 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, stream_enable_cache_percent(&stream, stream_cache, opts->stream_cache_min_percent, opts->stream_cache_seek_min_percent); - // deal with broken demuxers: preselect streams - int vs = -2, as = -2, ss = -2; - switch (filter) { - case STREAM_VIDEO: vs = -1; break; - case STREAM_AUDIO: as = -1; break; - case STREAM_SUB: ss = -1; break; - } - vs = -1; // avi can't go without video struct demuxer_params params = { .ass_library = mpctx->ass_library, // demux_libass requires it }; struct demuxer *demuxer = demux_open_withparams(&mpctx->opts, stream, format, demuxer_name, - as, vs, ss, filename, ¶ms); + filename, ¶ms); if (!demuxer) { free_stream(stream); goto err_out; @@ -4219,7 +4211,6 @@ goto_reopen_demuxer: ; mpctx->audio_delay = opts->audio_delay; mpctx->demuxer = demux_open(opts, mpctx->stream, file_format, - opts->audio_id, opts->video_id, opts->sub_id, mpctx->filename); mpctx->master_demuxer = mpctx->demuxer; diff --git a/core/timeline/tl_cue.c b/core/timeline/tl_cue.c index d9160e0b8e..a965cfd877 100644 --- a/core/timeline/tl_cue.c +++ b/core/timeline/tl_cue.c @@ -192,11 +192,7 @@ static bool try_open(struct MPContext *mpctx, char *filename) struct stream *s = open_stream(filename, &mpctx->opts, &format); if (!s) return false; - struct demuxer *d = demux_open(&mpctx->opts, s, format, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, - filename); + struct demuxer *d = demux_open(&mpctx->opts, s, format, filename); // Since .bin files are raw PCM data with no headers, we have to explicitly // open them. Also, try to avoid to open files that are most likely not .bin // files, as that would only play noise. Checking the file extension is @@ -205,11 +201,7 @@ static bool try_open(struct MPContext *mpctx, char *filename) // CD sector size (2352 bytes) if (!d && bstr_case_endswith(bfilename, bstr0(".bin"))) { mp_msg(MSGT_CPLAYER, MSGL_WARN, "CUE: Opening as BIN file!\n"); - d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_RAWAUDIO, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, - filename); + d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_RAWAUDIO, filename); } if (d) { add_source(mpctx, d); diff --git a/core/timeline/tl_edl.c b/core/timeline/tl_edl.c index 5ec04ac716..0303956513 100644 --- a/core/timeline/tl_edl.c +++ b/core/timeline/tl_edl.c @@ -360,9 +360,6 @@ void build_edl_timeline(struct MPContext *mpctx) if (!s) goto openfail; struct demuxer *d = demux_open(&mpctx->opts, s, format, - mpctx->opts.audio_id, - mpctx->opts.video_id, - mpctx->opts.sub_id, edl_ids[i].filename); if (!d) { free_stream(s); diff --git a/core/timeline/tl_matroska.c b/core/timeline/tl_matroska.c index 11fcc67583..6752b5ff4c 100644 --- a/core/timeline/tl_matroska.c +++ b/core/timeline/tl_matroska.c @@ -117,8 +117,7 @@ static struct demuxer *open_demuxer(struct stream *stream, struct MPContext *mpctx, char *filename, struct demuxer_params *params) { return demux_open_withparams(&mpctx->opts, stream, - DEMUXER_TYPE_MATROSKA, NULL, mpctx->opts.audio_id, - mpctx->opts.video_id, mpctx->opts.sub_id, filename, params); + DEMUXER_TYPE_MATROSKA, NULL, filename, params); } static int enable_cache(struct MPContext *mpctx, struct stream **stream, diff --git a/demux/demux.c b/demux/demux.c index 1d91920054..073a7a2bb6 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -236,7 +236,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; @@ -687,15 +687,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); @@ -748,8 +746,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); @@ -758,8 +755,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; @@ -781,15 +777,13 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, 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; } @@ -801,8 +795,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; } @@ -810,8 +803,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; } @@ -821,11 +813,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) diff --git a/demux/demux.h b/demux/demux.h index 93cf680bae..aa36d2f224 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -280,13 +280,11 @@ struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last); double ds_get_next_pts(struct demux_stream *ds); struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, - int file_format, int aid, int vid, int sid, - char *filename); + int file_format, char *filename); 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); void demux_flush(struct demuxer *demuxer); -- cgit v1.2.3 From 32ad3138445dbf4ac16199ced2ad239a1a8c4e3f Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 8 Jul 2013 23:18:31 +0200 Subject: demux: remove some more minor unused things --- demux/demux.c | 8 -------- demux/demux.h | 6 ------ demux/demux_mng.c | 1 - demux/stheader.h | 1 - 4 files changed, 16 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index c21e249dca..b143c702c0 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -197,8 +197,6 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) new->pts = dp->pts; new->duration = dp->duration; new->stream_pts = dp->stream_pts; - new->pos = dp->pos; - new->keyframe = dp->keyframe; return new; } @@ -243,11 +241,9 @@ static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, struct demuxer *d = talloc_zero(NULL, struct demuxer); d->stream = stream; d->stream_pts = MP_NOPTS_VALUE; - d->reference_clock = MP_NOPTS_VALUE; d->movi_start = stream->start_pos; d->movi_end = stream->end_pos; d->seekable = 1; - d->synced = 0; d->filepos = -1; d->audio = new_demuxer_stream(d, STREAM_AUDIO); d->video = new_demuxer_stream(d, STREAM_VIDEO); @@ -475,9 +471,6 @@ int ds_fill_buffer(demux_stream_t *ds) ds->buffer = p->buffer; ds->buffer_pos = 0; ds->buffer_size = p->len; - ds->pos = p->pos; - ds->dpos += p->len; // !!! - ++ds->pack_no; if (p->pts != MP_NOPTS_VALUE) { ds->pts = p->pts; ds->pts_bytes = 0; @@ -485,7 +478,6 @@ int ds_fill_buffer(demux_stream_t *ds) ds->pts_bytes += p->len; // !!! if (p->stream_pts != MP_NOPTS_VALUE) demux->stream_pts = p->stream_pts; - ds->keyframe = p->keyframe; // unlink packet: ds->bytes -= p->len; ds->current = p; diff --git a/demux/demux.h b/demux/demux.h index aa36d2f224..84ed95ceb2 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -96,10 +96,6 @@ typedef struct demux_stream { double pts; // current buffer's pts int pts_bytes; // number of bytes read after last pts stamp int eof; // end of demuxed stream? (true if all buffer empty) - int64_t pos; // position in the input stream (file) - int64_t dpos; // position in the demuxed stream - int pack_no; // serial number of packet - bool keyframe; // keyframe flag of current packet //--------------- int fill_count; // number of unsuccessful tries to get a packet int packs; // number of packets in buffer @@ -189,9 +185,7 @@ typedef struct demuxer { int64_t movi_end; struct stream *stream; double stream_pts; // current stream pts, if applicable (e.g. dvd) - double reference_clock; char *filename; // Needed by avs_check_file - int synced; // stream synced (used by mpeg) enum demuxer_type type; /* Normally the file_format field is just a copy of the type field above. * There are 2 exceptions I noticed. Internal demux_avi may force diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 1f73399902..76b742f019 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -346,7 +346,6 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer, // Set position and timing information in demuxer video and demuxer packet. // - Time must be time of next frame and always be > 0 for the variable // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. - demuxer->video->dpos++; dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS; dp->pos = stream_tell(demuxer->stream); ds_add_packet(demuxer->video, dp); diff --git a/demux/stheader.h b/demux/stheader.h index 628a2b73f2..15c55fdeda 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -116,7 +116,6 @@ typedef struct sh_audio { typedef struct sh_video { SH_COMMON - double i_pts; // PTS for the _next_ I/P frame (internal mpeg demuxing) float next_frame_time; double last_pts; double buffered_pts[32]; -- cgit v1.2.3 From b096269af5649124ead4dfe060cccf56a56876b3 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 9 Jul 2013 00:03:14 +0200 Subject: demux: remove ds_read_packet() --- demux/demux.c | 13 ------------- demux/demux.h | 2 -- demux/demux_rawvideo.c | 21 +++++++++++++++------ 3 files changed, 15 insertions(+), 21 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index b143c702c0..f0cb28ab1d 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -403,19 +403,6 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) ds->demuxer->video->packs); } -void ds_read_packet(demux_stream_t *ds, stream_t *stream, int len, - double pts, int64_t pos, bool keyframe) -{ - demux_packet_t *dp = new_demux_packet(len); - len = stream_read(stream, dp->buffer, len); - resize_demux_packet(dp, len); - dp->pts = pts; - dp->pos = pos; - dp->keyframe = keyframe; - // append packet to DS stream: - ds_add_packet(ds, dp); -} - static bool demux_check_queue_full(demuxer_t *demux) { int apacks = demux->audio ? demux->audio->packs : 0; diff --git a/demux/demux.h b/demux/demux.h index 84ed95ceb2..eb5de265b3 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -254,8 +254,6 @@ void free_demuxer(struct demuxer *demuxer); 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); int demux_fill_buffer(struct demuxer *demux, struct demux_stream *ds); int ds_fill_buffer(struct demux_stream *ds); diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 6834bfb23a..a4eaaa2a8c 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -131,12 +131,21 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { } static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { - sh_video_t* sh = demuxer->video->gsh->video; - int64_t pos; - if(demuxer->stream->eof) return 0; - if(ds!=demuxer->video) return 0; - pos = stream_tell(demuxer->stream); - ds_read_packet(ds,demuxer->stream,imgsize,(pos/imgsize)*sh->frametime,pos,0x10); + int64_t spos = stream_tell(demuxer->stream); + demux_packet_t* dp; + int size; + + if(demuxer->stream->eof) + return 0; + + dp = new_demux_packet(imgsize); + dp->pos = (spos - demuxer->movi_start); + dp->pts = dp->pos / (float)(imgsize); + + size = stream_read(demuxer->stream, dp->buffer, imgsize); + resize_demux_packet(dp, size); + ds_add_packet(ds, dp); + return 1; } -- cgit v1.2.3 From a5224836293ac02bd13f688cfc848aae6818e963 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:10:33 +0200 Subject: demux: remove facility for partial packet reads Partial packet reads were needed because the video/audio parsers were working on top of them. So it could happen that a parser read a part of a packet, and returned that to the decoder. With libavformat/libavcodec, packets are already parsed, and everything is much simpler. Most of the simplifications in ad_spdif could have been done earlier. Remove some other stuff as well, like the questionable slave mode start time reporting (could be replaced by proper code, but we don't bother). Remove the unused skip_audio_frame() functionality as well (it was used by old demuxers). Some functions become private to demux.c, like demux_fill_buffer(). Introduce new packet read functions, which have simpler semantics. Packets returned from them are owned by the caller, and all packets in the demux.c packet queue are considered unread. Remove special code that dropped subtitle packets with size 0. This used to be needed because it caused special cases in the old code. --- audio/decode/ad.h | 3 - audio/decode/ad_lavc.c | 7 +- audio/decode/ad_mpg123.c | 16 ++--- audio/decode/ad_spdif.c | 59 +++------------- audio/decode/dec_audio.c | 11 --- core/mplayer.c | 86 ++++++++--------------- demux/demux.c | 178 ++++++++++++++++------------------------------- demux/demux.h | 28 +++----- demux/demux_mng.c | 15 +--- demux/demux_rawvideo.c | 1 - sub/dec_sub.c | 5 +- 11 files changed, 126 insertions(+), 283 deletions(-) (limited to 'demux/demux.c') diff --git a/audio/decode/ad.h b/audio/decode/ad.h index 1f45e88f98..1c8a211f5b 100644 --- a/audio/decode/ad.h +++ b/audio/decode/ad.h @@ -44,7 +44,4 @@ extern const ad_functions_t * const mpcodecs_ad_drivers[]; #define ADCTRL_RESYNC_STREAM 1 // resync, called after seeking -// fallback if ADCTRL_SKIP not implemented: ds_fill_buffer(sh_audio->ds); -#define ADCTRL_SKIP_FRAME 2 // skip block/frame, called while seeking - #endif /* MPLAYER_AD_H */ diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index c311bc2cb8..d197bed072 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -372,10 +372,12 @@ static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; - struct demux_packet *mpkt = ds_get_packet2(sh->ds, false); + struct demux_packet *mpkt = demux_read_packet(sh->gsh); if (!mpkt) return -1; // error or EOF + int in_len = mpkt->len; + AVPacket pkt; mp_set_av_packet(&pkt, mpkt); @@ -385,6 +387,7 @@ static int decode_new_packet(struct sh_audio *sh) } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); + talloc_free(mpkt); // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) return 0; @@ -408,7 +411,7 @@ static int decode_new_packet(struct sh_audio *sh) } else { priv->output = priv->avframe->data[0]; } - mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", mpkt->len, + mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", in_len, priv->output_left); return 0; } diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c index 08739b7f4b..8d97468e06 100644 --- a/audio/decode/ad_mpg123.c +++ b/audio/decode/ad_mpg123.c @@ -217,27 +217,25 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) /* Feed the decoder. This will only fire from the second round on. */ if (ret == MPG123_NEED_MORE) { - int incount; - double pts; - unsigned char *inbuf; /* Feed more input data. */ - incount = ds_get_packet_pts(sh->ds, &inbuf, &pts); - if (incount <= 0) + struct demux_packet *pkt = demux_read_packet(sh->gsh); + if (!pkt) break; /* Apparently that's it. EOF. */ /* Next bytes from that presentation time. */ - if (pts != MP_NOPTS_VALUE) { - sh->pts = pts; + if (pkt->pts != MP_NOPTS_VALUE) { + sh->pts = pkt->pts; sh->pts_bytes = 0; } #ifdef AD_MPG123_FRAMEWISE /* Have to use mpg123_feed() to avoid decoding here. */ - ret = mpg123_feed(con->handle, inbuf, incount); + ret = mpg123_feed(con->handle, pkt->buffer, pkt->len); #else /* Do not use mpg123_feed(), added in later libmpg123 versions. */ - ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL); + ret = mpg123_decode(con->handle, pkt->buffer, pkt->len, NULL, 0, NULL); #endif + talloc_free(pkt); if (ret == MPG123_ERR) break; } diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 49b7d9a0d8..f4fc430208 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -84,9 +84,7 @@ static int codecs[] = { static int init(sh_audio_t *sh, const char *decoder) { - int x, in_size, srate, bps, *dtshd_rate; - unsigned char *start; - double pts; + int srate, bps, *dtshd_rate; AVFormatContext *lavf_ctx = NULL; AVStream *stream = NULL; const AVOption *opt = NULL; @@ -125,16 +123,8 @@ static int init(sh_audio_t *sh, const char *decoder) goto fail; } - // get sample_rate & bitrate from parser - x = ds_get_packet_pts(sh->ds, &start, &pts); - in_size = x; - if (x <= 0) { - pts = MP_NOPTS_VALUE; - x = 0; - } srate = 48000; //fake value bps = 768000/8; //fake value - sh->ds->buffer_pos -= in_size; int num_channels = 0; switch (lavf_ctx->streams[0]->codec->codec_id) { @@ -214,42 +204,24 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, struct spdifContext *spdif_ctx = sh->context; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; AVPacket pkt; - double pts; - int ret, in_size, consumed, x; - unsigned char *start = NULL; - consumed = spdif_ctx->out_buffer_len = 0; + spdif_ctx->out_buffer_len = 0; spdif_ctx->out_buffer_size = maxlen; spdif_ctx->out_buffer = buf; while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen && spdif_ctx->out_buffer_len < minlen) { - if (sh->ds->eof) + struct demux_packet *mpkt = demux_read_packet(sh->gsh); + if (!mpkt) break; - x = ds_get_packet_pts(sh->ds, &start, &pts); - if (x <= 0) { - continue; // END_NOT_FOUND - } else { - in_size = x; - consumed = x; - if (x == 0) { - mp_msg(MSGT_DECAUDIO,MSGL_V, - "start[%p] in_size[%d] consumed[%d] x[%d].\n", - start, in_size, consumed, x); - continue; // END_NOT_FOUND - } - sh->ds->buffer_pos -= in_size - consumed; - } - av_init_packet(&pkt); - pkt.data = start; - pkt.size = x; - mp_msg(MSGT_DECAUDIO,MSGL_V, - "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", - start, pkt.size, in_size, consumed, x); - if (pts != MP_NOPTS_VALUE) { - sh->pts = pts; + mp_set_av_packet(&pkt, mpkt); + mp_msg(MSGT_DECAUDIO,MSGL_V, "pkt.data[%p] pkt.size[%d]\n", + pkt.data, pkt.size); + if (mpkt->pts != MP_NOPTS_VALUE) { + sh->pts = mpkt->pts; sh->pts_bytes = 0; } - ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); + int ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); + talloc_free(mpkt); if (ret < 0) break; } @@ -259,15 +231,6 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, static int control(sh_audio_t *sh, int cmd, void *arg) { - unsigned char *start; - double pts; - - switch (cmd) { - case ADCTRL_RESYNC_STREAM: - case ADCTRL_SKIP_FRAME: - ds_get_packet_pts(sh->ds, &start, &pts); - return CONTROL_TRUE; - } return CONTROL_UNKNOWN; } diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 1bf217de80..8c80a0b119 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -365,14 +365,3 @@ void resync_audio_stream(sh_audio_t *sh_audio) return; sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); } - -void skip_audio_frame(sh_audio_t *sh_audio) -{ - if (!sh_audio->initialized) - return; - if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL) - == CONTROL_TRUE) - return; - // default skip code: - ds_fill_buffer(sh_audio->ds); // skip block -} diff --git a/core/mplayer.c b/core/mplayer.c index 217e99ed5c..0d07b518d8 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -288,8 +288,6 @@ static void print_stream(struct MPContext *mpctx, struct track *t) static void print_file_properties(struct MPContext *mpctx, const char *filename) { - double start_pts = MP_NOPTS_VALUE; - double video_start_pts = MP_NOPTS_VALUE; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILENAME=%s\n", filename); if (mpctx->sh_video) { @@ -310,7 +308,6 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) "ID_VIDEO_FPS=%5.3f\n", mpctx->sh_video->fps); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect); - video_start_pts = ds_get_next_pts(mpctx->sh_video->ds); } if (mpctx->sh_audio) { /* Assume FOURCC if all bytes >= 0x20 (' ') */ @@ -326,17 +323,7 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) "ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels.num); - start_pts = ds_get_next_pts(mpctx->sh_audio->ds); } - if (video_start_pts != MP_NOPTS_VALUE) { - if (start_pts == MP_NOPTS_VALUE || !mpctx->sh_audio || - (mpctx->sh_video && video_start_pts < start_pts)) - start_pts = video_start_pts; - } - if (start_pts != MP_NOPTS_VALUE) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=%.2f\n", start_pts); - else - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=unknown\n"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_LENGTH=%.2f\n", get_time_length(mpctx)); int chapter_count = get_chapter_count(mpctx); @@ -375,11 +362,8 @@ static double get_main_demux_pts(struct MPContext *mpctx) if (mpctx->demuxer) { for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) { - demux_fill_buffer(mpctx->demuxer, ds); - if (ds->first) - main_new_pos = ds->first->pts; - } + if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) + main_new_pos = demux_get_next_pts(ds->gsh); } } return main_new_pos; @@ -1703,14 +1687,14 @@ static double written_audio_pts(struct MPContext *mpctx) // ratio is not constant for every audio packet or if it is constant // but not accurately known in sh_audio->i_bps. - a_pts = d_audio->pts; + a_pts = d_audio->last_pts; if (a_pts == MP_NOPTS_VALUE) return a_pts; // ds_tell_pts returns bytes read after last timestamp from // demuxing layer if (sh_audio->i_bps) - a_pts += ds_tell_pts(d_audio) / (double)sh_audio->i_bps; + a_pts += d_audio->last_pts_bytes / (double)sh_audio->i_bps; } // Now a_pts hopefully holds the pts for end of audio from decoder. // Substract data in buffers between decoder and audio out. @@ -1783,15 +1767,14 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) double curpts_s = refpts_s + opts->sub_delay; if (!track->preloaded) { - struct demux_stream *d_sub = sh_sub->ds; bool non_interleaved = is_non_interleaved(mpctx, track); while (1) { - if (non_interleaved) - ds_get_next_pts(d_sub); - if (!d_sub->first) + if (!non_interleaved && !demux_has_packet(sh_sub->gsh)) + break; + double subpts_s = demux_get_next_pts(sh_sub->gsh); + if (!demux_has_packet(sh_sub->gsh)) break; - double subpts_s = ds_get_next_pts(d_sub); if (subpts_s > curpts_s) { mp_dbg(MSGT_CPLAYER, MSGL_DBG2, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", @@ -1803,11 +1786,12 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) if (non_interleaved && subpts_s > curpts_s + 1) break; } - struct demux_packet *pkt = ds_get_packet_sub(d_sub); + struct demux_packet *pkt = demux_read_packet(sh_sub->gsh); mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f " "duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, pkt->len); sub_decode(dec_sub, pkt); + talloc_free(pkt); } } @@ -2465,28 +2449,24 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) } -static int video_read_frame(sh_video_t *sh_video, - unsigned char **start, int force_fps) +static struct demux_packet *video_read_frame(struct MPContext *mpctx) { + sh_video_t *sh_video = mpctx->sh_video; demux_stream_t *d_video = sh_video->ds; demuxer_t *demuxer = d_video->demuxer; - float pts1 = d_video->pts; - int in_size = 0; - - *start = NULL; + float pts1 = d_video->last_pts; - // frame-based file formats: (AVI,ASF,MOV) - in_size = ds_get_packet(d_video, start); - if (in_size < 0) - return -1; // EOF + struct demux_packet *pkt = demux_read_packet(sh_video->gsh); + if (!pkt) + return NULL; // EOF float frame_time = sh_video->frametime; // override frame_time for variable/unknown FPS formats: - if (!force_fps) { - double next_pts = ds_get_next_pts(d_video); - double d = next_pts == MP_NOPTS_VALUE ? d_video->pts - pts1 - : next_pts - d_video->pts; + if (!mpctx->opts.force_fps) { + double next_pts = demux_get_next_pts(sh_video->gsh); + double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1 + : next_pts - d_video->last_pts; if (d >= 0) { if (demuxer->file_format == DEMUXER_TYPE_TV) { if (d > 0) { @@ -2501,10 +2481,10 @@ static int video_read_frame(sh_video_t *sh_video, } } - sh_video->pts = d_video->pts; + sh_video->pts = d_video->last_pts; sh_video->next_frame_time = frame_time; - return in_size; + return pkt; } static double update_video_nocorrect_pts(struct MPContext *mpctx) @@ -2518,15 +2498,11 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) break; if (filter_output_queued_frame(mpctx)) break; - unsigned char *packet = NULL; frame_time = sh_video->next_frame_time; if (mpctx->restart_playback) frame_time = 0; - int in_size = 0; - while (!in_size) - in_size = video_read_frame(sh_video, - &packet, mpctx->opts.force_fps); - if (in_size < 0) + struct demux_packet *pkt = video_read_frame(mpctx); + if (!pkt) return -1; if (mpctx->sh_audio) mpctx->delay -= frame_time; @@ -2534,13 +2510,9 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) update_fps(mpctx); int framedrop_type = check_framedrop(mpctx, frame_time); - struct demux_packet pkt = {0}; - if (sh_video->ds->current) - pkt = *sh_video->ds->current; - pkt.buffer = packet; - pkt.len = in_size; - void *decoded_frame = decode_video(sh_video, &pkt, framedrop_type, + void *decoded_frame = decode_video(sh_video, pkt, framedrop_type, sh_video->pts); + talloc_free(pkt); if (decoded_frame) { filter_video(mpctx, decoded_frame); } @@ -2599,12 +2571,13 @@ static double update_video(struct MPContext *mpctx, double endpts) pts = MP_NOPTS_VALUE; struct demux_packet *pkt; while (1) { - pkt = ds_get_packet2(mpctx->sh_video->ds, false); + pkt = demux_read_packet(mpctx->sh_video->gsh); if (!pkt || pkt->len) break; /* Packets with size 0 are assumed to not correspond to frames, * but to indicate the absence of a frame in formats like AVI * that must have packets at fixed timecode intervals. */ + talloc_free(pkt); } if (pkt) pts = pkt->pts; @@ -2616,6 +2589,7 @@ static double update_video(struct MPContext *mpctx, double endpts) 1 : check_framedrop(mpctx, sh_video->frametime); struct mp_image *decoded_frame = decode_video(sh_video, pkt, framedrop_type, pts); + talloc_free(pkt); if (decoded_frame) { determine_frame_pts(mpctx); filter_video(mpctx, decoded_frame); @@ -2773,7 +2747,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac) // Not all demuxers set d_video->pts during seek, so this value // (which was used by at least vobsub code below) may be completely // wrong (probably 0). - mpctx->sh_video->pts = mpctx->sh_video->ds->pts + mpctx->video_offset; + mpctx->sh_video->pts = mpctx->sh_video->ds->last_pts + mpctx->video_offset; mpctx->video_pts = mpctx->sh_video->pts; } diff --git a/demux/demux.c b/demux/demux.c index f0cb28ab1d..16adfeb795 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -375,26 +375,16 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) { - // demux API can't handle 0-sized packets, but at least some vobsubs - // generate them. Skipping them seems to work fine. Not skipping them will - // stop demuxing with external vobsubs. See FATE sub/vobsub.{idx,sub} at - // pts=185.91. - if (dp->len == 0 && ds->stream_type == STREAM_SUB) { - mp_dbg(MSGT_DEMUXER, MSGL_INFO, "Discarding empty subtitle packet.\n"); - free_demux_packet(dp); - return; - } - // append packet to DS stream: ++ds->packs; ds->bytes += dp->len; - if (ds->last) { + if (ds->tail) { // next packet in stream - ds->last->next = dp; - ds->last = dp; + ds->tail->next = dp; + ds->tail = dp; } else { // first packet in stream - ds->first = ds->last = dp; + ds->head = ds->tail = dp; } mp_dbg(MSGT_DEMUXER, MSGL_DBG2, "DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n", @@ -440,38 +430,18 @@ int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds) // return value: // 0 = EOF // 1 = successful -int ds_fill_buffer(demux_stream_t *ds) +static int ds_get_packets(demux_stream_t *ds) { + if (!ds) + return 0; demuxer_t *demux = ds->demuxer; - if (ds->current) - free_demux_packet(ds->current); - ds->current = NULL; - mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_fill_buffer (%s) called\n", + mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_get_packets (%s) called\n", ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" : ds == demux->sub ? "d_sub" : "unknown"); while (1) { int apacks = demux->audio ? demux->audio->packs : 0; int vpacks = demux->video ? demux->video->packs : 0; if (ds->packs) { - demux_packet_t *p = ds->first; - // copy useful data: - ds->buffer = p->buffer; - ds->buffer_pos = 0; - ds->buffer_size = p->len; - if (p->pts != MP_NOPTS_VALUE) { - ds->pts = p->pts; - ds->pts_bytes = 0; - } - ds->pts_bytes += p->len; // !!! - if (p->stream_pts != MP_NOPTS_VALUE) - demux->stream_pts = p->stream_pts; - // unlink packet: - ds->bytes -= p->len; - ds->current = p; - ds->first = p->next; - if (!ds->first) - ds->last = NULL; - --ds->packs; /* The code below can set ds->eof to 1 when another stream runs * out of buffer space. That makes sense because in that situation * the calling code should not count on being able to demux more @@ -497,7 +467,7 @@ int ds_fill_buffer(demux_stream_t *ds) if (!demux_fill_buffer(demux, ds)) { mp_dbg(MSGT_DEMUXER, MSGL_DBG2, - "ds_fill_buffer()->demux_fill_buffer() failed\n"); + "ds_get_packets()->demux_fill_buffer() failed\n"); break; // EOF } @@ -508,10 +478,8 @@ int ds_fill_buffer(demux_stream_t *ds) ds->fill_count++; } } - ds->buffer_pos = ds->buffer_size = 0; - ds->buffer = NULL; mp_msg(MSGT_DEMUXER, MSGL_V, - "ds_fill_buffer: EOF reached (stream: %s) \n", + "ds_get_packets: EOF reached (stream: %s) \n", ds == demux->audio ? "audio" : "video"); ds->eof = 1; return 0; @@ -519,100 +487,76 @@ int ds_fill_buffer(demux_stream_t *ds) void ds_free_packs(demux_stream_t *ds) { - demux_packet_t *dp = ds->first; + demux_packet_t *dp = ds->head; while (dp) { demux_packet_t *dn = dp->next; free_demux_packet(dp); dp = dn; } - ds->first = ds->last = NULL; + ds->head = ds->tail = NULL; ds->packs = 0; // !!!!! ds->bytes = 0; - if (ds->current) - free_demux_packet(ds->current); - ds->current = NULL; - ds->buffer = NULL; - ds->buffer_pos = ds->buffer_size; - ds->pts = MP_NOPTS_VALUE; - ds->pts_bytes = 0; -} - -int ds_get_packet(demux_stream_t *ds, unsigned char **start) -{ - int len; - if (ds->buffer_pos >= ds->buffer_size) { - if (!ds_fill_buffer(ds)) { - // EOF - *start = NULL; - return -1; - } - } - len = ds->buffer_size - ds->buffer_pos; - *start = &ds->buffer[ds->buffer_pos]; - ds->buffer_pos += len; - return len; + ds->last_pts = MP_NOPTS_VALUE; + ds->last_pts_bytes = 0; } -int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts) +static struct demux_stream *ds_from_sh(struct sh_stream *sh) { - int len; - *pts = MP_NOPTS_VALUE; - len = ds_get_packet(ds, start); - if (len < 0) - return len; - // Return pts unless this read starts from the middle of a packet - if (len == ds->buffer_pos) - *pts = ds->current->pts; - return len; + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + if (sh->demuxer->ds[n]->gsh == sh) + return sh->demuxer->ds[n]; + } + return NULL; } -struct demux_packet *ds_get_packet_sub(demux_stream_t *ds) -{ - if (ds->buffer_pos >= ds->buffer_size) { - if (!ds->packs) - return NULL; // no sub - if (!ds_fill_buffer(ds)) - return NULL; // EOF - } - if (ds->buffer_pos < ds->buffer_size) { - ds->current->buffer += ds->buffer_pos; - ds->buffer_size -= ds->buffer_pos; +// Read a packet from the given stream. The returned packet belongs to the +// caller, who has to free it with talloc_free(). Might block. Returns NULL +// on EOF. +struct demux_packet *demux_read_packet(struct sh_stream *sh) +{ + struct demux_stream *ds = ds_from_sh(sh); + if (ds) { + ds_get_packets(ds); + struct demux_packet *pkt = ds->head; + if (pkt) { + ds->head = pkt->next; + pkt->next = NULL; + if (!ds->head) + ds->tail = NULL; + ds->bytes -= pkt->len; + ds->packs--; + + if (pkt->pts != MP_NOPTS_VALUE) { + ds->last_pts = pkt->pts; + ds->last_pts_bytes = 0; + } else { + ds->last_pts_bytes += pkt->len; + } + + if (pkt->stream_pts != MP_NOPTS_VALUE) + sh->demuxer->stream_pts = pkt->stream_pts; + + return pkt; + } } - ds->buffer_pos = ds->buffer_size; - return ds->current; + return NULL; } -struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last) +// 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) { - 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; + struct demux_stream *ds = ds_from_sh(sh); + ds_get_packets(ds); + return ds && ds->head ? ds->head->pts : MP_NOPTS_VALUE; } -double ds_get_next_pts(demux_stream_t *ds) +// Return whether a packet is queued. Never blocks, never forces any reads. +bool demux_has_packet(struct sh_stream *sh) { - demuxer_t *demux = ds->demuxer; - // if we have not read from the "current" packet, consider it - // as the next, otherwise we never get the pts for the first packet. - while (!ds->first && (!ds->current || ds->buffer_pos)) { - if (demux_check_queue_full(demux)) - return MP_NOPTS_VALUE; - if (!demux_fill_buffer(demux, ds)) - return MP_NOPTS_VALUE; - } - // take pts from "current" if we never read from it. - if (ds->current && !ds->buffer_pos) - return ds->current->pts; - return ds->first->pts; + struct demux_stream *ds = ds_from_sh(sh); + return ds && ds->head; } // ==================================================================== diff --git a/demux/demux.h b/demux/demux.h index eb5de265b3..fade7533e9 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -90,19 +90,15 @@ enum timestamp_type { 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); - double pts; // current buffer's pts - int pts_bytes; // number of bytes read after last pts stamp + double last_pts; // pts of the last packet that was read + int last_pts_bytes; // number of bytes read after last pts stamp int eof; // end of demuxed stream? (true if all buffer empty) //--------------- int fill_count; // number of unsuccessful tries to get a packet int packs; // number of packets in buffer int bytes; // total bytes of packets in buffer - demux_packet_t *first; // read to current buffer from here - demux_packet_t *last; // append new packets from input stream to here - demux_packet_t *current; // needed for refcounting of the buffer + struct demux_packet *head; + struct demux_packet *tail; struct demuxer *demuxer; // parent demuxer structure (stream handler) // ---- stream header ---- struct sh_stream *gsh; @@ -256,20 +252,12 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, void ds_add_packet(struct demux_stream *ds, struct demux_packet *dp); int demux_fill_buffer(struct demuxer *demux, struct demux_stream *ds); -int ds_fill_buffer(struct demux_stream *ds); - -static inline int ds_tell_pts(struct demux_stream *ds) -{ - return (ds->pts_bytes - ds->buffer_size) + ds->buffer_pos; -} 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); -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); + +struct demux_packet *demux_read_packet(struct sh_stream *sh); +double demux_get_next_pts(struct sh_stream *sh); +bool demux_has_packet(struct sh_stream *sh); struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, int file_format, char *filename); diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 76b742f019..6dc0e352e8 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -37,14 +37,6 @@ #define MNG_SUPPORT_DISPLAY #include -/** - * \brief some small fixed start time > 0 - * - * Start time must be > 0 for the variable frame time mechanism - * (GIF, MATROSKA, MNG) in video.c to work for the first frame. - */ -#define MNG_START_PTS 0.01f - /** * \brief private context structure * @@ -346,7 +338,7 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer, // Set position and timing information in demuxer video and demuxer packet. // - Time must be time of next frame and always be > 0 for the variable // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. - dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS; + dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f; dp->pos = stream_tell(demuxer->stream); ds_add_packet(demuxer->video, dp); @@ -447,11 +439,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) sh_video->bih->biBitCount = 32; sh_video->bih->biPlanes = 1; - // Set start time to something > 0. - // - This is required for the variable frame time mechanism - // (GIF, MATROSKA, MNG) in video.c to work for the first frame. - sh_video->ds->pts = MNG_START_PTS; - // set private data in demuxer and return demuxer demuxer->priv = mng_priv; return demuxer; diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index a4eaaa2a8c..787bd0c064 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -164,7 +164,6 @@ static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float aud pos/=imgsize; stream_seek(s,pos*imgsize); //sh_video->timer=pos * sh_video->frametime; - demuxer->video->pts = pos * sh_video->frametime; // printf("demux_rawvideo: streamtell=%d\n",(int)stream_tell(demuxer->stream)); } diff --git a/sub/dec_sub.c b/sub/dec_sub.c index fb7e5e4a2a..4351cf60a0 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -380,12 +380,12 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh) preprocess = 1; for (;;) { - ds_get_next_pts(sh->ds); - struct demux_packet *pkt = ds_get_packet_sub(sh->ds); + struct demux_packet *pkt = demux_read_packet(sh->gsh); if (!pkt) break; if (preprocess) { decode_chain(sub->sd, preprocess, pkt); + talloc_free(pkt); while (1) { pkt = get_decoded_packet(sub->sd[preprocess - 1]); if (!pkt) @@ -394,6 +394,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh) } } else { add_packet(subs, pkt); + talloc_free(pkt); } } -- cgit v1.2.3 From fa74be880c27b350615f62dd4a0d6a32be56c60e Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:17:05 +0200 Subject: tv: add hack in preparation of demux_stream removal Currently, all demuxer fill_buffer functions have a demux_stream parameter. We want to remove that, but the TV code still depends on it. Add a hack to remove that dependency. The problem with the TV code is that reading video and audio frames blocks, so in order to avoid a deadlock, you should read either of them only if the decoder actually requests new data. --- demux/demux.c | 7 +++++++ demux/demux.h | 1 + stream/tv.c | 21 +++++++++++++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 16adfeb795..df68d4ead7 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -559,6 +559,13 @@ bool demux_has_packet(struct sh_stream *sh) return ds && ds->head; } +// Same as demux_has_packet, but to be called internally by demuxers, as +// opposed to the user of the demuxer. +bool demuxer_stream_has_packets_queued(struct demuxer *d, struct sh_stream *stream) +{ + return demux_has_packet(stream); +} + // ==================================================================== void demuxer_help(void) diff --git a/demux/demux.h b/demux/demux.h index fade7533e9..4d4d861b7d 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -317,6 +317,7 @@ struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, enum stream_type t, int id); bool demuxer_stream_is_selected(struct demuxer *d, struct sh_stream *stream); +bool demuxer_stream_has_packets_queued(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, diff --git a/stream/tv.c b/stream/tv.c index 72b67b7f9e..0f09bb3448 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -215,10 +215,23 @@ static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds) tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv); demux_packet_t* dp; unsigned int len=0; + struct sh_stream *want_audio = NULL, *want_video = NULL; + + for (int n = 0; n < demux->num_streams; n++) { + struct sh_stream *sh = demux->streams[n]; + if (!demuxer_stream_has_packets_queued(demux, sh) && + demuxer_stream_is_selected(demux, sh)) + { + if (sh->type == STREAM_AUDIO) + want_audio = sh; + if (sh->type == STREAM_VIDEO) + want_video = sh; + } + } /* ================== ADD AUDIO PACKET =================== */ - if (ds==demux->audio && tvh->tv_param->noaudio == 0 && + if (want_audio && tvh->tv_param->noaudio == 0 && tvh->functions->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { @@ -227,19 +240,19 @@ static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds) dp=new_demux_packet(len); dp->keyframe = true; dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len); - ds_add_packet(demux->audio,dp); + demuxer_add_packet(demux, want_audio, dp); } /* ================== ADD VIDEO PACKET =================== */ - if (ds==demux->video && tvh->functions->control(tvh->priv, + if (want_video && tvh->functions->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE) { len = tvh->functions->get_video_framesize(tvh->priv); dp=new_demux_packet(len); dp->keyframe = true; dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len); - ds_add_packet(demux->video,dp); + demuxer_add_packet(demux, want_video, dp); } if (tvh->tv_param->scan) tv_scan(tvh); -- cgit v1.2.3 From 6ede485e4b2ea1093e84d8589a1c321fe8a8462a Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:17:51 +0200 Subject: core: don't access demux_stream outside of demux.c, make it private Generally remove all accesses to demux_stream from all the code, except inside of demux.c. Make it completely private to demux.c. This simplifies the code because it removes an extra concept. In demux.c it is reduced to a simple packet queue. There were other uses of demux_stream, but they were removed or are removed with this commit. Remove the extra "ds" argument to demux fill_buffer callback. It was used by demux_avi and the TV pseudo-demuxer only. Remove usage of d_video->last_pts from the no-correct-pts code. This field contains the last PTS retrieved after a packet that is not NOPTS. We can easily get this value manually because we read the packets ourselves. Reuse sh_video->last_pts to store the packet PTS values. It was used only by the correct-pts code before, and like d_video->last_pts, it is reset on seek. The behavior should be exactly the same. --- core/command.c | 10 +++--- core/mplayer.c | 32 +++++++++-------- demux/demux.c | 95 +++++++++++++++++++++++++++---------------------- demux/demux.h | 24 ++----------- demux/demux_lavf.c | 2 +- demux/demux_mf.c | 10 ++---- demux/demux_mkv.c | 10 +++--- demux/demux_mng.c | 12 ++----- demux/demux_rawaudio.c | 9 ++--- demux/demux_rawvideo.c | 10 +++--- demux/demux_subreader.c | 2 +- demux/stheader.h | 2 -- stream/tv.c | 2 +- 13 files changed, 97 insertions(+), 123 deletions(-) (limited to 'demux/demux.c') diff --git a/core/command.c b/core/command.c index 5a68a228bc..cba9ef5a9a 100644 --- a/core/command.c +++ b/core/command.c @@ -566,13 +566,11 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: angle = demuxer_set_angle(demuxer, *(int *)arg); if (angle >= 0) { - struct sh_stream *sh_video = demuxer->video->gsh; - if (sh_video) - resync_video_stream(sh_video->video); + if (mpctx->sh_video) + resync_video_stream(mpctx->sh_video); - struct sh_stream *sh_audio = demuxer->audio->gsh; - if (sh_audio) - resync_audio_stream(sh_audio->audio); + if (mpctx->sh_audio) + resync_audio_stream(mpctx->sh_audio); } return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: { diff --git a/core/mplayer.c b/core/mplayer.c index 00d9ad91ac..f5dbfb4e41 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -360,10 +360,9 @@ static double get_main_demux_pts(struct MPContext *mpctx) { double main_new_pos = MP_NOPTS_VALUE; if (mpctx->demuxer) { - for (int type = 0; type < STREAM_TYPE_COUNT; type++) { - struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) - main_new_pos = demux_get_next_pts(ds->gsh); + for (int n = 0; n < mpctx->demuxer->num_streams; n++) { + if (main_new_pos == MP_NOPTS_VALUE) + main_new_pos = demux_get_next_pts(mpctx->demuxer->streams[n]); } } return main_new_pos; @@ -1789,7 +1788,9 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time) { struct MPOpts *opts = &mpctx->opts; // check for frame-drop: - if (mpctx->sh_audio && !mpctx->ao->untimed && !mpctx->sh_audio->ds->eof) { + if (mpctx->sh_audio && !mpctx->ao->untimed && + !demux_stream_eof(mpctx->sh_audio->gsh)) + { float delay = opts->playback_speed * ao_get_delay(mpctx->ao); float d = delay - mpctx->delay; // we should avoid dropping too many frames in sequence unless we @@ -2205,7 +2206,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return -1; } else if (res == ASYNC_PLAY_DONE) return 0; - else if (mpctx->sh_audio->ds->eof) + else if (demux_stream_eof(mpctx->sh_audio->gsh)) audio_eof = true; } @@ -2338,7 +2339,7 @@ int reinit_video_chain(struct MPContext *mpctx) vo_update_window_title(mpctx); - if (stream_control(mpctx->sh_video->ds->demuxer->stream, + if (stream_control(mpctx->sh_video->gsh->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) mpctx->sh_video->stream_aspect = ar; @@ -2438,21 +2439,23 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame) static struct demux_packet *video_read_frame(struct MPContext *mpctx) { sh_video_t *sh_video = mpctx->sh_video; - demux_stream_t *d_video = sh_video->ds; - demuxer_t *demuxer = d_video->demuxer; - float pts1 = d_video->last_pts; + demuxer_t *demuxer = sh_video->gsh->demuxer; + float pts1 = sh_video->last_pts; struct demux_packet *pkt = demux_read_packet(sh_video->gsh); if (!pkt) return NULL; // EOF + if (pkt->pts != MP_NOPTS_VALUE) + sh_video->last_pts = pkt->pts; + float frame_time = sh_video->frametime; // override frame_time for variable/unknown FPS formats: if (!mpctx->opts.force_fps) { double next_pts = demux_get_next_pts(sh_video->gsh); - double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1 - : next_pts - d_video->last_pts; + double d = next_pts == MP_NOPTS_VALUE ? sh_video->last_pts - pts1 + : next_pts - sh_video->last_pts; if (d >= 0) { if (demuxer->file_format == DEMUXER_TYPE_TV) { if (d > 0) { @@ -2467,8 +2470,7 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) } } - sh_video->pts = d_video->last_pts; - + sh_video->pts = sh_video->last_pts; sh_video->next_frame_time = frame_time; return pkt; } @@ -2515,7 +2517,7 @@ static void determine_frame_pts(struct MPContext *mpctx) if (opts->user_pts_assoc_mode) sh_video->pts_assoc_mode = opts->user_pts_assoc_mode; else if (sh_video->pts_assoc_mode == 0) { - if (mpctx->sh_video->ds->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS + if (mpctx->sh_video->gsh->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS && sh_video->codec_reordered_pts != MP_NOPTS_VALUE) sh_video->pts_assoc_mode = 1; else diff --git a/demux/demux.c b/demux/demux.c index df68d4ead7..fe60cce669 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -17,6 +17,7 @@ * with MPlayer; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#define DEMUX_PRIV(x) x #include #include @@ -88,6 +89,20 @@ const demuxer_desc_t *const demuxer_list[] = { NULL }; +typedef struct demux_stream { + enum stream_type stream_type; + int eof; // end of demuxed stream? (true if all buffer empty) +//--------------- + int fill_count; // number of unsuccessful tries to get a packet + int packs; // number of packets in buffer + int bytes; // total bytes of packets in buffer + struct demux_packet *head; + struct demux_packet *tail; + struct demuxer *demuxer; // parent demuxer structure (stream handler) +// ---- stream header ---- + struct sh_stream *gsh; +} demux_stream_t; + static void add_stream_chapters(struct demuxer *demuxer); static int packet_destroy(void *ptr) @@ -200,6 +215,19 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) return new; } +static void ds_free_packs(demux_stream_t *ds) +{ + demux_packet_t *dp = ds->head; + while (dp) { + demux_packet_t *dn = dp->next; + free_demux_packet(dp); + dp = dn; + } + ds->head = ds->tail = NULL; + ds->packs = 0; // !!!!! + ds->bytes = 0; +} + static void free_demuxer_stream(struct demux_stream *ds) { ds_free_packs(ds); @@ -290,7 +318,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) struct sh_video *sht = talloc_zero(demuxer, struct sh_video); sht->gsh = sh; sht->opts = sh->opts; - sht->ds = demuxer->video; sh->video = sht; break; } @@ -298,7 +325,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) struct sh_audio *sht = talloc_zero(demuxer, struct sh_audio); sht->gsh = sh; sht->opts = sh->opts; - sht->ds = demuxer->audio; sht->samplesize = 2; sht->sample_format = AF_FORMAT_S16_NE; sh->audio = sht; @@ -308,7 +334,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) struct sh_sub *sht = talloc_zero(demuxer, struct sh_sub); sht->gsh = sh; sht->opts = sh->opts; - sht->ds = demuxer->sub; sh->sub = sht; break; } @@ -360,20 +385,7 @@ void free_demuxer(demuxer_t *demuxer) talloc_free(demuxer); } -// 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 (!dp || !demuxer_stream_is_selected(demuxer, stream)) { - free_demux_packet(dp); - return 0; - } else { - ds_add_packet(demuxer->ds[stream->type], dp); - return 1; - } -} - -void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +static void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) { // append packet to DS stream: ++ds->packs; @@ -393,6 +405,19 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) ds->demuxer->video->packs); } +// 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 (!dp || !demuxer_stream_is_selected(demuxer, stream)) { + free_demux_packet(dp); + return 0; + } else { + ds_add_packet(demuxer->ds[stream->type], dp); + return 1; + } +} + static bool demux_check_queue_full(demuxer_t *demux) { int apacks = demux->audio ? demux->audio->packs : 0; @@ -421,10 +446,9 @@ static bool demux_check_queue_full(demuxer_t *demux) // 0 = EOF or no stream found or invalid type // 1 = successfully read a packet -int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds) +static int demux_fill_buffer(demuxer_t *demux) { - // Note: parameter 'ds' can be NULL! - return demux->desc->fill_buffer ? demux->desc->fill_buffer(demux, ds) : 0; + return demux->desc->fill_buffer ? demux->desc->fill_buffer(demux) : 0; } // return value: @@ -465,7 +489,7 @@ static int ds_get_packets(demux_stream_t *ds) if (demux_check_queue_full(demux)) break; - if (!demux_fill_buffer(demux, ds)) { + if (!demux_fill_buffer(demux)) { mp_dbg(MSGT_DEMUXER, MSGL_DBG2, "ds_get_packets()->demux_fill_buffer() failed\n"); break; // EOF @@ -485,21 +509,6 @@ static int ds_get_packets(demux_stream_t *ds) return 0; } -void ds_free_packs(demux_stream_t *ds) -{ - demux_packet_t *dp = ds->head; - while (dp) { - demux_packet_t *dn = dp->next; - free_demux_packet(dp); - dp = dn; - } - ds->head = ds->tail = NULL; - ds->packs = 0; // !!!!! - ds->bytes = 0; - ds->last_pts = MP_NOPTS_VALUE; - ds->last_pts_bytes = 0; -} - static struct demux_stream *ds_from_sh(struct sh_stream *sh) { for (int n = 0; n < STREAM_TYPE_COUNT; n++) { @@ -526,13 +535,6 @@ struct demux_packet *demux_read_packet(struct sh_stream *sh) ds->bytes -= pkt->len; ds->packs--; - if (pkt->pts != MP_NOPTS_VALUE) { - ds->last_pts = pkt->pts; - ds->last_pts_bytes = 0; - } else { - ds->last_pts_bytes += pkt->len; - } - if (pkt->stream_pts != MP_NOPTS_VALUE) sh->demuxer->stream_pts = pkt->stream_pts; @@ -566,6 +568,13 @@ bool demuxer_stream_has_packets_queued(struct demuxer *d, struct sh_stream *stre return demux_has_packet(stream); } +// Return whether EOF was returned with an earlier packet read. +bool demux_stream_eof(struct sh_stream *sh) +{ + struct demux_stream *ds = ds_from_sh(sh); + return !ds || ds->eof; +} + // ==================================================================== void demuxer_help(void) diff --git a/demux/demux.h b/demux/demux.h index 4d4d861b7d..a3e48a24f3 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -88,22 +88,6 @@ enum timestamp_type { // demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead #define MP_INPUT_BUFFER_PADDING_SIZE 16 -typedef struct demux_stream { - enum stream_type stream_type; - double last_pts; // pts of the last packet that was read - int last_pts_bytes; // number of bytes read after last pts stamp - int eof; // end of demuxed stream? (true if all buffer empty) -//--------------- - int fill_count; // number of unsuccessful tries to get a packet - int packs; // number of packets in buffer - int bytes; // total bytes of packets in buffer - struct demux_packet *head; - struct demux_packet *tail; - struct demuxer *demuxer; // parent demuxer structure (stream handler) -// ---- stream header ---- - struct sh_stream *gsh; -} demux_stream_t; - #define MAX_SH_STREAMS 256 struct demuxer; @@ -126,7 +110,7 @@ typedef struct demuxer_desc { // Mandatory if safe_check == 1, else optional int (*check_file)(struct demuxer *demuxer); /// Get packets from file, return 0 on eof. Mandatory - int (*fill_buffer)(struct demuxer *demuxer, struct demux_stream *ds); + int (*fill_buffer)(struct demuxer *demuxer); /// Open the demuxer, return demuxer on success, NULL on failure struct demuxer *(*open)(struct demuxer *demuxer); // Optional /// Close the demuxer @@ -249,15 +233,11 @@ void free_demuxer(struct demuxer *demuxer); 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); - -int demux_fill_buffer(struct demuxer *demux, struct demux_stream *ds); - -void ds_free_packs(struct demux_stream *ds); struct demux_packet *demux_read_packet(struct sh_stream *sh); double demux_get_next_pts(struct sh_stream *sh); bool demux_has_packet(struct sh_stream *sh); +bool demux_stream_eof(struct sh_stream *sh); struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, int file_format, char *filename); diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index ea8a82c403..aa3b6c24f2 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -637,7 +637,7 @@ static int destroy_avpacket(void *pkt) return 0; } -static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds) +static int demux_lavf_fill_buffer(demuxer_t *demux) { lavf_priv_t *priv = demux->priv; demux_packet_t *dp; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 8435c36f37..491a91bccf 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -61,7 +61,8 @@ static void demux_seek_mf(demuxer_t *demuxer,float rel_seek_secs,float audio_del // return value: // 0 = EOF or no stream found // 1 = successfully read a packet -static int demux_mf_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){ +static int demux_mf_fill_buffer(demuxer_t *demuxer) +{ mf_t *mf = demuxer->priv; if (mf->curr_frame >= mf->nr_of_files) return 0; @@ -85,7 +86,7 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){ dp->pts = mf->curr_frame / mf->sh->fps; dp->pos = mf->curr_frame; dp->keyframe = true; - ds_add_packet(demuxer->video, dp); + demuxer_add_packet(demuxer, demuxer->streams[0], dp); } talloc_free(data.start); } @@ -215,11 +216,6 @@ static demuxer_t* demux_open_mf(demuxer_t* demuxer){ goto error; } - // make sure that the video demuxer stream header knows about its - // parent video demuxer stream (this is getting wacky), or else - // video_read_properties() will choke - sh_video->ds = demuxer->video; - sh_video->disp_w = 0; sh_video->disp_h = 0; sh_video->fps = mf_fps; diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index b00c115ef2..7b674c9465 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1962,7 +1962,7 @@ static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, } else dp->pts = real_fix_timestamp(dp->buffer, timestamp, - demuxer->video->gsh->video->bih->biCompression, + track->stream->video->bih->biCompression, &track->rv_kf_base, &track->rv_kf_pts, NULL); dp->pos = demuxer->filepos; dp->keyframe = keyframe; @@ -2046,7 +2046,7 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, if (track->sub_packet_cnt == 0) track->audio_filepos = demuxer->filepos; if (++(track->sub_packet_cnt) == sph) { - int apk_usize = demuxer->audio->gsh->audio->wf->nBlockAlign; + int apk_usize = track->stream->audio->wf->nBlockAlign; track->sub_packet_cnt = 0; // Release all the audio packets for (x = 0; x < sph * w / apk_usize; x++) { @@ -2465,7 +2465,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block) } } -static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) +static int demux_mkv_fill_buffer(demuxer_t *demuxer) { for (;;) { int res; @@ -2657,7 +2657,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, : 0; mkv_d->a_skip_to_keyframe = 1; - demux_mkv_fill_buffer(demuxer, NULL); + demux_mkv_fill_buffer(demuxer); } else if ((demuxer->movi_end <= 0) || !(flags & SEEK_ABSOLUTE)) mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n"); else { @@ -2696,7 +2696,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, mkv_d->skip_to_timecode = index->timecode * mkv_d->tc_scale; mkv_d->a_skip_to_keyframe = 1; - demux_mkv_fill_buffer(demuxer, NULL); + demux_mkv_fill_buffer(demuxer); } } diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 6dc0e352e8..22299ea17b 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -272,11 +272,9 @@ static int demux_mng_check_file(demuxer_t *demuxer) /** * \brief MPlayer callback: Fill buffer from MNG stream. * \param[in] demuxer demuxer structure - * \param[in] ds demuxer stream * \return \p 1 on success, \p 0 on error */ -static int demux_mng_fill_buffer(demuxer_t * demuxer, - demux_stream_t * ds) +static int demux_mng_fill_buffer(demuxer_t * demuxer) { mng_priv_t * mng_priv = demuxer->priv; mng_handle h_mng = mng_priv->h_mng; @@ -340,7 +338,7 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer, // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f; dp->pos = stream_tell(demuxer->stream); - ds_add_packet(demuxer->video, dp); + demuxer_add_packet(demuxer, demuxer->streams[0], dp); return 1; } @@ -417,12 +415,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh->video; - // Make sure that the video demuxer stream header knows about its - // parent video demuxer stream (this is getting wacky), or else - // video_read_properties() will choke. - // (Thanks to demux_gif.c for this.) - sh_video->ds = demuxer->video; - // set format of pixels in video packets sh_video->gsh->codec = "rawvideo"; sh_video->format = MP_FOURCC_RGB32; diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 50e4e4a68b..74134743a0 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -72,8 +72,9 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { return demuxer; } -static int demux_rawaudio_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { - sh_audio_t* sh_audio = demuxer->audio->gsh->audio; +static int demux_rawaudio_fill_buffer(demuxer_t* demuxer) +{ + sh_audio_t* sh_audio = demuxer->streams[0]->audio; int l = sh_audio->wf->nAvgBytesPerSec; int64_t spos = stream_tell(demuxer->stream); demux_packet_t* dp; @@ -87,14 +88,14 @@ static int demux_rawaudio_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { l = stream_read(demuxer->stream,dp->buffer,l); resize_demux_packet(dp, l); - ds_add_packet(ds,dp); + demuxer_add_packet(demuxer, demuxer->streams[0], dp); return 1; } static void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ stream_t* s = demuxer->stream; - sh_audio_t* sh_audio = demuxer->audio->gsh->audio; + sh_audio_t* sh_audio = demuxer->streams[0]->audio; int64_t base,pos; base = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s); diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 787bd0c064..6fc25639ca 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -130,7 +130,8 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { return demuxer; } -static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { +static int demux_rawvideo_fill_buffer(demuxer_t* demuxer) +{ int64_t spos = stream_tell(demuxer->stream); demux_packet_t* dp; int size; @@ -144,27 +145,24 @@ static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) { size = stream_read(demuxer->stream, dp->buffer, imgsize); resize_demux_packet(dp, size); - ds_add_packet(ds, dp); + demuxer_add_packet(demuxer, demuxer->streams[0], dp); return 1; } static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ stream_t* s = demuxer->stream; - sh_video_t* sh_video = demuxer->video->gsh->video; int64_t pos; pos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s); if(flags & SEEK_FACTOR) pos += ((demuxer->movi_end - demuxer->movi_start)*rel_seek_secs); else - pos += (rel_seek_secs*sh_video->i_bps); + pos += (rel_seek_secs*fps*imgsize); if(pos < 0) pos = 0; if(demuxer->movi_end && pos > demuxer->movi_end) pos = (demuxer->movi_end-imgsize); pos/=imgsize; stream_seek(s,pos*imgsize); - //sh_video->timer=pos * sh_video->frametime; -// printf("demux_rawvideo: streamtell=%d\n",(int)stream_tell(demuxer->stream)); } diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index ca03e73c33..ce69218e50 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1358,7 +1358,7 @@ static int d_check_file(struct demuxer *demuxer) return DEMUXER_TYPE_SUBREADER; } -static int d_fill_buffer(struct demuxer *demuxer, struct demux_stream *ds) +static int d_fill_buffer(struct demuxer *demuxer) { struct priv *p = demuxer->priv; struct demux_packet *dp = demux_packet_list_fill(p->pkts, p->num_pkts, diff --git a/demux/stheader.h b/demux/stheader.h index 447cacfc02..6b01d24a58 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -70,11 +70,9 @@ struct sh_stream { struct MPOpts *opts; }; - #define SH_COMMON \ struct sh_stream *gsh; \ struct MPOpts *opts; \ - struct demux_stream *ds; \ /* usually a FourCC, exact meaning depends on gsh->format */ \ unsigned int format; \ int initialized; \ diff --git a/stream/tv.c b/stream/tv.c index 0f09bb3448..93c50fb36a 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -210,7 +210,7 @@ static void tv_scan(tvi_handle_t *tvh) */ /* fill demux->video and demux->audio */ -static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds) +static int demux_tv_fill_buffer(demuxer_t *demux) { tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv); demux_packet_t* dp; -- cgit v1.2.3 From 06281848de53153266d8d4639bbc98e12505994b Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:20:25 +0200 Subject: demux: refactor --- demux/demux.c | 261 ++++++++++++++++++++++++++----------------------------- demux/demux.h | 7 -- demux/stheader.h | 3 + 3 files changed, 126 insertions(+), 145 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index fe60cce669..3e2c7bb52e 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -89,22 +89,32 @@ const demuxer_desc_t *const demuxer_list[] = { NULL }; -typedef struct demux_stream { - enum stream_type stream_type; +struct demux_stream { + int selected; // user wants packets from this stream int eof; // end of demuxed stream? (true if all buffer empty) -//--------------- int fill_count; // number of unsuccessful tries to get a packet int packs; // number of packets in buffer int bytes; // total bytes of packets in buffer struct demux_packet *head; struct demux_packet *tail; - struct demuxer *demuxer; // parent demuxer structure (stream handler) -// ---- stream header ---- - struct sh_stream *gsh; -} demux_stream_t; +}; static void add_stream_chapters(struct demuxer *demuxer); +static void ds_free_packs(struct demux_stream *ds) +{ + demux_packet_t *dp = ds->head; + while (dp) { + demux_packet_t *dn = dp->next; + free_demux_packet(dp); + dp = dn; + } + ds->head = ds->tail = NULL; + ds->packs = 0; // !!!!! + ds->bytes = 0; + ds->eof = 0; +} + static int packet_destroy(void *ptr) { struct demux_packet *dp = ptr; @@ -215,36 +225,6 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) return new; } -static void ds_free_packs(demux_stream_t *ds) -{ - demux_packet_t *dp = ds->head; - while (dp) { - demux_packet_t *dn = dp->next; - free_demux_packet(dp); - dp = dn; - } - ds->head = ds->tail = NULL; - ds->packs = 0; // !!!!! - ds->bytes = 0; -} - -static void free_demuxer_stream(struct demux_stream *ds) -{ - ds_free_packs(ds); - free(ds); -} - -static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, - enum stream_type type) -{ - demux_stream_t *ds = malloc(sizeof(demux_stream_t)); - *ds = (demux_stream_t) { - .stream_type = type, - .demuxer = demuxer, - }; - return ds; -} - /** * Get demuxer description structure for a given demuxer type * @@ -273,12 +253,6 @@ static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, d->movi_end = stream->end_pos; d->seekable = 1; d->filepos = -1; - 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; d->type = type; d->opts = opts; if (type) @@ -305,13 +279,15 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) demuxer_id++; } - struct sh_stream *sh = talloc_struct(demuxer, struct sh_stream, { + struct sh_stream *sh = talloc_ptrtype(demuxer, sh); + *sh = (struct sh_stream) { .type = type, .demuxer = demuxer, .index = demuxer->num_streams, .demuxer_id = demuxer_id, // may be overwritten by demuxer .opts = demuxer->opts, - }); + .ds = talloc_zero(sh, struct demux_stream), + }; MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); switch (sh->type) { case STREAM_VIDEO: { @@ -360,6 +336,8 @@ static void free_sh_video(sh_video_t *sh) static void free_sh_stream(struct sh_stream *sh) { + ds_free_packs(sh->ds); + switch (sh->type) { case STREAM_AUDIO: free_sh_audio(sh->audio); break; case STREAM_VIDEO: free_sh_video(sh->video); break; @@ -377,71 +355,99 @@ void free_demuxer(demuxer_t *demuxer) // free streams: 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); - free_demuxer_stream(demuxer->sub); free(demuxer->filename); talloc_free(demuxer); } -static void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +static const char *stream_type_name(enum stream_type type) { - // append packet to DS stream: - ++ds->packs; - ds->bytes += dp->len; - if (ds->tail) { - // next packet in stream - ds->tail->next = dp; - ds->tail = dp; - } else { - // first packet in stream - ds->head = ds->tail = dp; + switch (type) { + case STREAM_VIDEO: return "video"; + case STREAM_AUDIO: return "audio"; + case STREAM_SUB: return "sub"; + default: return "unknown"; } - mp_dbg(MSGT_DEMUXER, MSGL_DBG2, - "DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n", - (ds == ds->demuxer->audio) ? "d_audio" : "d_video", dp->len, - dp->pts, (unsigned int) dp->pos, ds->demuxer->audio->packs, - ds->demuxer->video->packs); +} + +static int count_packs(struct demuxer *demux, enum stream_type type) +{ + int c = 0; + for (int n = 0; n < demux->num_streams; n++) + c += demux->streams[n]->type == type ? demux->streams[n]->ds->packs : 0; + return c; +} + +static int count_bytes(struct demuxer *demux, enum stream_type type) +{ + int c = 0; + for (int n = 0; n < demux->num_streams; n++) + c += demux->streams[n]->type == type ? demux->streams[n]->ds->bytes : 0; + return c; } // 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 (!dp || !demuxer_stream_is_selected(demuxer, stream)) { - free_demux_packet(dp); + struct demux_stream *ds = stream ? stream->ds : NULL; + if (!ds || !ds->selected) { + talloc_free(dp); return 0; + } + + ds->packs++; + ds->bytes += dp->len; + if (ds->tail) { + // next packet in stream + ds->tail->next = dp; + ds->tail = dp; } else { - ds_add_packet(demuxer->ds[stream->type], dp); - return 1; + // first packet in stream + ds->head = ds->tail = dp; } + mp_dbg(MSGT_DEMUXER, MSGL_DBG2, + "DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%"PRIu64" " + "[packs: A=%d V=%d S=%d]\n", stream_type_name(stream->type), + dp->len, dp->pts, dp->pos, count_packs(demuxer, STREAM_AUDIO), + count_packs(demuxer, STREAM_VIDEO), count_packs(demuxer, STREAM_SUB)); + return 1; } static bool demux_check_queue_full(demuxer_t *demux) { - int apacks = demux->audio ? demux->audio->packs : 0; - int abytes = demux->audio ? demux->audio->bytes : 0; - int vpacks = demux->video ? demux->video->packs : 0; - int vbytes = demux->video ? demux->video->bytes : 0; + for (int n = 0; n < demux->num_streams; n++) { + struct sh_stream *sh = demux->streams[n]; + if (sh->ds->packs > MAX_PACKS || sh->ds->bytes > MAX_PACK_BYTES) + goto overflow; + } + return false; - if (apacks < MAX_PACKS && abytes < MAX_PACK_BYTES && - vpacks < MAX_PACKS && vbytes < MAX_PACK_BYTES) - return false; +overflow: if (!demux->warned_queue_overflow) { mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many packets in the demuxer " "packet queue (video: %d packets in %d bytes, audio: %d " - "packets in %d bytes).\n", vpacks, vbytes, apacks, abytes); + "packets in %d bytes, sub: %d packets in %d bytes).\n", + count_packs(demux, STREAM_VIDEO), count_bytes(demux, STREAM_VIDEO), + count_packs(demux, STREAM_AUDIO), count_bytes(demux, STREAM_AUDIO), + count_packs(demux, STREAM_SUB), count_bytes(demux, STREAM_SUB)); mp_tmsg(MSGT_DEMUXER, MSGL_HINT, "Maybe you are playing a non-" "interleaved stream/file or the codec failed?\n"); } - demux->warned_queue_overflow = true; - return true; } +static bool need_coverart_hack(struct demuxer *demux) +{ + for (int n = 0; n < demux->num_streams; n++) { + struct sh_stream *sh = demux->streams[n]; + if (sh->attached_picture && sh->ds->selected) + return true; + } + return false; +} + // return value: // 0 = EOF or no stream found or invalid type // 1 = successfully read a packet @@ -451,21 +457,14 @@ static int demux_fill_buffer(demuxer_t *demux) return demux->desc->fill_buffer ? demux->desc->fill_buffer(demux) : 0; } -// return value: -// 0 = EOF -// 1 = successful -static int ds_get_packets(demux_stream_t *ds) +static void ds_get_packets(struct sh_stream *sh) { - if (!ds) - return 0; - demuxer_t *demux = ds->demuxer; + struct demux_stream *ds = sh->ds; + demuxer_t *demux = sh->demuxer; mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_get_packets (%s) called\n", - ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" : - ds == demux->sub ? "d_sub" : "unknown"); + stream_type_name(sh->type)); while (1) { - int apacks = demux->audio ? demux->audio->packs : 0; - int vpacks = demux->video ? demux->video->packs : 0; - if (ds->packs) { + if (ds->head) { /* The code below can set ds->eof to 1 when another stream runs * out of buffer space. That makes sense because in that situation * the calling code should not count on being able to demux more @@ -475,7 +474,7 @@ static int ds_get_packets(demux_stream_t *ds) * weird behavior. */ ds->eof = 0; ds->fill_count = 0; - return 1; + return; } // avoid buffering too far ahead in e.g. badly interleaved files // or when one stream is shorter, without breaking large audio @@ -489,33 +488,20 @@ static int ds_get_packets(demux_stream_t *ds) if (demux_check_queue_full(demux)) break; - if (!demux_fill_buffer(demux)) { - mp_dbg(MSGT_DEMUXER, MSGL_DBG2, - "ds_get_packets()->demux_fill_buffer() failed\n"); + int apacks = count_packs(demux, STREAM_AUDIO); + int vpacks = count_packs(demux, STREAM_VIDEO); + + if (!demux_fill_buffer(demux)) break; // EOF - } - 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) - ds->fill_count++; + if (need_coverart_hack(demux)) { + ds->fill_count += count_packs(demux, STREAM_AUDIO) - apacks; + ds->fill_count += count_packs(demux, STREAM_VIDEO) - vpacks; } } - mp_msg(MSGT_DEMUXER, MSGL_V, - "ds_get_packets: EOF reached (stream: %s) \n", - ds == demux->audio ? "audio" : "video"); + mp_msg(MSGT_DEMUXER, MSGL_V, "ds_get_packets: EOF reached (stream: %s)\n", + stream_type_name(sh->type)); ds->eof = 1; - return 0; -} - -static struct demux_stream *ds_from_sh(struct sh_stream *sh) -{ - for (int n = 0; n < STREAM_TYPE_COUNT; n++) { - if (sh->demuxer->ds[n]->gsh == sh) - return sh->demuxer->ds[n]; - } - return NULL; } // Read a packet from the given stream. The returned packet belongs to the @@ -523,9 +509,9 @@ static struct demux_stream *ds_from_sh(struct sh_stream *sh) // on EOF. struct demux_packet *demux_read_packet(struct sh_stream *sh) { - struct demux_stream *ds = ds_from_sh(sh); + struct demux_stream *ds = sh ? sh->ds : NULL; if (ds) { - ds_get_packets(ds); + ds_get_packets(sh); struct demux_packet *pkt = ds->head; if (pkt) { ds->head = pkt->next; @@ -549,16 +535,18 @@ struct demux_packet *demux_read_packet(struct sh_stream *sh) // packets from the queue. double demux_get_next_pts(struct sh_stream *sh) { - struct demux_stream *ds = ds_from_sh(sh); - ds_get_packets(ds); - return ds && ds->head ? ds->head->pts : MP_NOPTS_VALUE; + if (sh) { + ds_get_packets(sh); + if (sh->ds->head) + return sh->ds->head->pts; + } + return MP_NOPTS_VALUE; } // Return whether a packet is queued. Never blocks, never forces any reads. bool demux_has_packet(struct sh_stream *sh) { - struct demux_stream *ds = ds_from_sh(sh); - return ds && ds->head; + return sh && sh->ds->head; } // Same as demux_has_packet, but to be called internally by demuxers, as @@ -571,8 +559,7 @@ bool demuxer_stream_has_packets_queued(struct demuxer *d, struct sh_stream *stre // Return whether EOF was returned with an earlier packet read. bool demux_stream_eof(struct sh_stream *sh) { - struct demux_stream *ds = ds_from_sh(sh); - return !ds || ds->eof; + return !sh || sh->ds->eof; } // ==================================================================== @@ -762,9 +749,9 @@ struct demuxer *demux_open(struct MPOpts *opts, stream_t *vs, int file_format, void demux_flush(demuxer_t *demuxer) { - ds_free_packs(demuxer->video); - ds_free_packs(demuxer->audio); - ds_free_packs(demuxer->sub); + for (int n = 0; n < demuxer->num_streams; n++) + ds_free_packs(demuxer->streams[n]->ds); + demuxer->warned_queue_overflow = false; } int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, @@ -780,10 +767,6 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, // clear demux buffers: demux_flush(demuxer); - demuxer->video->eof = 0; - demuxer->audio->eof = 0; - demuxer->sub->eof = 0; - demuxer->warned_queue_overflow = false; /* HACK: assume any demuxer used with these streams can cope with * the stream layer suddenly seeking to a different position under it @@ -931,18 +914,20 @@ 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 / none are selected - if (demuxer->ds[type]->gsh == stream) - return; - - demuxer->ds[type]->gsh = stream; - - ds_free_packs(demuxer->ds[type]); - demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); + for (int n = 0; n < demuxer->num_streams; n++) { + struct sh_stream *cur = demuxer->streams[n]; + bool select = cur == stream; + if (cur->type == type && cur->ds->selected != select) { + cur->ds->selected = select; + ds_free_packs(cur->ds); + 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]->gsh == stream; + return stream && stream->ds->selected; } int demuxer_add_attachment(demuxer_t *demuxer, struct bstr name, diff --git a/demux/demux.h b/demux/demux.h index a3e48a24f3..2b3a998289 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -183,13 +183,6 @@ typedef struct demuxer { enum timestamp_type timestamp_type; bool warned_queue_overflow; - 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 - struct sh_stream **streams; int num_streams; diff --git a/demux/stheader.h b/demux/stheader.h index 6b01d24a58..9898d8be33 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -68,6 +68,9 @@ struct sh_stream { // shouldn't exist type of stuff struct MPOpts *opts; + + // Internal to demux.c + struct demux_stream *ds; }; #define SH_COMMON \ -- cgit v1.2.3 From e5544e2da38522674edb1eb5d4cfdf179c4328db Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:22:24 +0200 Subject: demux: improve DVD sub auto-selection hack The code touched by this commit makes sure that DVD subtitle tracks known by libdvdread but not known by demux_lavf can be selected and displayed properly. These subtitle tracks have the first packet some time late in the packet stream, so that libavformat won't immediately recognize them, and will add the track as soon as the first packet is seen during normal demuxing. demux_mpg used to handle this elegantly: you just set the MPEG ID of the stream you wanted. demux_lavf couldn't do this, so it was emulated with a DEMUXER_CTRL. This commit changes it so that new streams are selected by default (if autoselect is enabled), and the playloop simply can take appropriate action before the lower layer throws away the first packet. This also changes the demux_lavf behavior that subtitle packets are always demuxed, even if not needed. (They were immediately thrown away, so there was no advantage to this.) Further, this adds the ability to demux.c to deal with demuxing more than one stream of a kind at once. (Though currently it's not useful.) --- core/mplayer.c | 26 ++++++++------------------ demux/demux.c | 28 +++++++++++++++++++++------- demux/demux.h | 5 ++++- demux/demux_lavf.c | 20 ++++---------------- 4 files changed, 37 insertions(+), 42 deletions(-) (limited to 'demux/demux.c') diff --git a/core/mplayer.c b/core/mplayer.c index 275795defb..2cc4659eef 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -913,12 +913,6 @@ static int map_id_from_demuxer(struct demuxer *d, enum stream_type type, int id) id = id & 0x1F; return id; } -static int map_id_to_demuxer(struct demuxer *d, enum stream_type type, int id) -{ - if (d->stream->uncached_type == STREAMTYPE_DVD && type == STREAM_SUB) - id = id | 0x20; - return id; -} static struct track *add_stream_track(struct MPContext *mpctx, struct sh_stream *stream, @@ -937,7 +931,9 @@ static struct track *add_stream_track(struct MPContext *mpctx, track->stream = stream; track->demuxer_id = stream->demuxer_id; // Initialize lazily selected track - if (track == mpctx->current_track[STREAM_SUB]) + bool selected = track == mpctx->current_track[STREAM_SUB]; + demuxer_select_track(track->demuxer, stream, selected); + if (selected) reinit_subs(mpctx); return track; } @@ -973,6 +969,8 @@ static struct track *add_stream_track(struct MPContext *mpctx, track->lang = talloc_strdup(track, req.name); } + demuxer_select_track(track->demuxer, stream, false); + return track; } @@ -1004,6 +1002,7 @@ static void add_dvd_tracks(struct MPContext *mpctx) track->lang = talloc_strdup(track, req.name); } } + demuxer_enable_autoselect(demuxer); #endif } @@ -1885,18 +1884,9 @@ static void reinit_subs(struct MPContext *mpctx) mpctx->sh_sub->dec_sub = sub_create(opts); assert(track->demuxer); - if (!track->stream) { - // Lazily added DVD track - we must not miss the first subtitle packet, - // which makes the demuxer create the sh_stream, and contains the first - // subtitle event. - - // demux_lavf - IDs are essentially random, have to use MPEG IDs - int id = map_id_to_demuxer(track->demuxer, track->type, - track->demuxer_id); - demux_control(track->demuxer, DEMUXER_CTRL_AUTOSELECT_SUBTITLE, &id); - + // Lazily added DVD track - will be created on first sub packet + if (!track->stream) return; - } mpctx->initialized_flags |= INITIALIZED_SUB; diff --git a/demux/demux.c b/demux/demux.c index 3e2c7bb52e..f0652fba4d 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -315,6 +315,9 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) } default: assert(false); } + + sh->ds->selected = demuxer->stream_autoselect; + return sh; } @@ -913,18 +916,29 @@ 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 / none are selected for (int n = 0; n < demuxer->num_streams; n++) { struct sh_stream *cur = demuxer->streams[n]; - bool select = cur == stream; - if (cur->type == type && cur->ds->selected != select) { - cur->ds->selected = select; - ds_free_packs(cur->ds); - demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); - } + if (cur->type == type) + demuxer_select_track(demuxer, cur, cur == stream); + } +} + +void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, + bool selected) +{ + // don't flush buffers if stream is already selected / unselected + if (stream->ds->selected != selected) { + stream->ds->selected = selected; + ds_free_packs(stream->ds); + demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); } } +void demuxer_enable_autoselect(struct demuxer *demuxer) +{ + demuxer->stream_autoselect = true; +} + bool demuxer_stream_is_selected(struct demuxer *d, struct sh_stream *stream) { return stream && stream->ds->selected; diff --git a/demux/demux.h b/demux/demux.h index 2b3a998289..d75c8f0d12 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -77,7 +77,6 @@ enum timestamp_type { #define DEMUXER_CTRL_SWITCH_VIDEO 14 #define DEMUXER_CTRL_IDENTIFY_PROGRAM 15 #define DEMUXER_CTRL_CORRECT_PTS 16 -#define DEMUXER_CTRL_AUTOSELECT_SUBTITLE 17 #define SEEK_ABSOLUTE (1 << 0) #define SEEK_FACTOR (1 << 1) @@ -185,6 +184,7 @@ typedef struct demuxer { struct sh_stream **streams; int num_streams; + bool stream_autoselect; int num_editions; int edition; @@ -255,6 +255,9 @@ int demux_control(struct demuxer *demuxer, int cmd, void *arg); void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, struct sh_stream *stream); +void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, + bool selected); +void demuxer_enable_autoselect(struct demuxer *demuxer); int demuxer_type_by_filename(char *filename); diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index ce7c274e4b..f7ef5dda1a 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -73,7 +73,6 @@ typedef struct lavf_priv { AVFormatContext *avfc; AVIOContext *pb; uint8_t buffer[BIO_BUFFER_SIZE]; - int autoselect_sub; int64_t last_pts; struct sh_stream **streams; // NULL for unknown streams int num_streams; @@ -196,7 +195,6 @@ static int lavf_check_file(demuxer_t *demuxer) assert(!demuxer->priv); demuxer->priv = talloc_zero(NULL, lavf_priv_t); priv = demuxer->priv; - priv->autoselect_sub = -1; priv->filename = s->url; if (!priv->filename) { @@ -427,7 +425,6 @@ static void handle_stream(demuxer_t *demuxer, int i) memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); sh_sub->extradata_len = codec->extradata_size; } - st->discard = AVDISCARD_DEFAULT; break; } case AVMEDIA_TYPE_ATTACHMENT: { @@ -463,6 +460,9 @@ static void handle_stream(demuxer_t *demuxer, int i) if (lang && lang->value) sh->lang = talloc_strdup(sh, lang->value); } + + bool selected = demuxer_stream_is_selected(demuxer, sh); + st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL; } // Add any new streams that might have been added @@ -657,13 +657,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux) AVStream *st = priv->avfc->streams[pkt->stream_index]; struct sh_stream *stream = priv->streams[pkt->stream_index]; - if (stream && stream->type == STREAM_SUB && - stream->demuxer_id == priv->autoselect_sub) - { - priv->autoselect_sub = -1; - demuxer_switch_track(demux, STREAM_SUB, stream); - } - if (!demuxer_stream_is_selected(demux, stream)) { talloc_free(pkt); return 1; @@ -799,18 +792,13 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) for (int n = 0; n < priv->num_streams; n++) { struct sh_stream *stream = priv->streams[n]; AVStream *st = priv->avfc->streams[n]; - if (stream && stream->type != STREAM_SUB) { + if (stream) { bool selected = demuxer_stream_is_selected(demuxer, stream); st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL; } } return DEMUXER_CTRL_OK; } - case DEMUXER_CTRL_AUTOSELECT_SUBTITLE: - { - priv->autoselect_sub = *((int *)arg); - return DEMUXER_CTRL_OK; - } case DEMUXER_CTRL_IDENTIFY_PROGRAM: { demux_program_t *prog = arg; -- cgit v1.2.3 From 4cda1d113e0d9d34d7c39cf3d8861c7079f965d8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 19:23:56 +0200 Subject: core: completely change handling of attached picture pseudo video Before this commit, we tried to play along with libavformat and tried to pretend that attached pictures are video streams with a single frame, and that the frame magically appeared at the seek position when seeking. The playback core would then switch to a mode where the video has ended, and the "remaining" audio is played. This didn't work very well: - we needed a hack in demux.c, because we tried to read more packets in order to find the "next" video frame (libavformat doesn't tell us if a stream has ended) - switching the video stream didn't work, because we can't tell libavformat to send the packet again - seeking and resuming after was hacky (for some reason libavformat sets the returned packet's PTS to that of the previously returned audio packet in generic code not related to attached pictures, and this happened to work) - if the user did something stupid and e.g. inserted a deinterlacer by default, a picture was never displayed, only an inactive VO window) - same when using a command that reconfigured the VO (like switching aspect or video filters) - hr-seek didn't work For this reason, handle attached pictures as separate case with a separate video decoding function, which doesn't read packets. Also, do not synchronize audio to video start in this case. --- core/mp_core.h | 3 +++ core/mplayer.c | 65 ++++++++++++++++++++++++++++++++++++++++-------------- demux/demux.c | 28 ----------------------- demux/demux_lavf.c | 13 ++++++----- demux/stheader.h | 4 +++- 5 files changed, 63 insertions(+), 50 deletions(-) (limited to 'demux/demux.c') diff --git a/core/mp_core.h b/core/mp_core.h index b9c835e497..6bd51cb85c 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -172,6 +172,9 @@ typedef struct MPContext { /* We're starting playback from scratch or after a seek. Show first * video frame immediately and reinitialize sync. */ bool restart_playback; + /* Set if audio should be timed to start with video frame after seeking, + * not set when e.g. playing cover art */ + bool sync_audio_to_video; /* After playback restart (above) or audio stream change, adjust audio * stream by cutting samples or adding silence at the beginning to make * audio playback position match video position. */ diff --git a/core/mplayer.c b/core/mplayer.c index 2cc4659eef..026af6a989 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -467,6 +467,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mpctx->sh_video) uninit_video(mpctx->sh_video); cleanup_demux_stream(mpctx, STREAM_VIDEO); + mpctx->sync_audio_to_video = false; } if (mask & INITIALIZED_DEMUXER) { @@ -946,7 +947,7 @@ static struct track *add_stream_track(struct MPContext *mpctx, .demuxer_id = stream->demuxer_id, .title = stream->title, .default_track = stream->default_track, - .attached_picture = stream->attached_picture, + .attached_picture = stream->attached_picture != NULL, .lang = stream->lang, .under_timeline = under_timeline, .demuxer = stream->demuxer, @@ -1134,7 +1135,7 @@ static void print_status(struct MPContext *mpctx) saddf(&line, " x%4.2f", opts->playback_speed); // A-V sync - if (mpctx->sh_audio && sh_video) { + if (mpctx->sh_audio && sh_video && mpctx->sync_audio_to_video) { if (mpctx->last_av_difference != MP_NOPTS_VALUE) saddf(&line, " A-V:%7.3f", mpctx->last_av_difference); else @@ -2173,7 +2174,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) playsize = ao_get_space(ao); // Coming here with hrseek_active still set means audio-only - if (!mpctx->sh_video) + if (!mpctx->sh_video || !mpctx->sync_audio_to_video) mpctx->syncing_audio = false; if (!opts->initial_audio_sync || !modifiable_audio_format) { mpctx->syncing_audio = false; @@ -2353,6 +2354,7 @@ int reinit_video_chain(struct MPContext *mpctx) sh_video->num_buffered_pts = 0; sh_video->next_frame_time = 0; mpctx->restart_playback = true; + mpctx->sync_audio_to_video = !sh_video->gsh->attached_picture; mpctx->delay = 0; mpctx->vo_pts_history_seek_ts++; @@ -2365,6 +2367,7 @@ err_out: cleanup_demux_stream(mpctx, STREAM_VIDEO); no_video: mpctx->current_track[STREAM_VIDEO] = NULL; + mpctx->sync_audio_to_video = false; mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Video: no video\n"); return 0; } @@ -2416,6 +2419,15 @@ static bool filter_output_queued_frame(struct MPContext *mpctx) return !!img; } +static bool load_next_vo_frame(struct MPContext *mpctx, bool eof) +{ + if (vo_get_buffered_frame(mpctx->video_out, eof) >= 0) + return true; + if (filter_output_queued_frame(mpctx)) + return true; + return false; +} + static void filter_video(struct MPContext *mpctx, struct mp_image *frame) { struct sh_video *sh_video = mpctx->sh_video; @@ -2467,12 +2479,9 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; double frame_time = 0; - struct vo *video_out = mpctx->video_out; while (1) { // In nocorrect-pts mode there is no way to properly time these frames - if (vo_get_buffered_frame(video_out, 0) >= 0) - break; - if (filter_output_queued_frame(mpctx)) + if (load_next_vo_frame(mpctx, false)) break; frame_time = sh_video->next_frame_time; if (mpctx->restart_playback) @@ -2497,6 +2506,23 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) return frame_time; } +static double update_video_attached_pic(struct MPContext *mpctx) +{ + struct sh_video *sh_video = mpctx->sh_video; + + // Try to decode the picture multiple times, until it is displayed. + if (mpctx->video_out->hasframe) + return -1; + + struct mp_image *decoded_frame = + decode_video(sh_video, sh_video->gsh->attached_picture, 0, 0); + if (decoded_frame) + filter_video(mpctx, decoded_frame); + load_next_vo_frame(mpctx, true); + mpctx->sh_video->pts = MP_NOPTS_VALUE; + return 0; +} + static void determine_frame_pts(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; @@ -2537,15 +2563,16 @@ static double update_video(struct MPContext *mpctx, double endpts) if (!mpctx->opts.correct_pts) return update_video_nocorrect_pts(mpctx); + if (sh_video->gsh->attached_picture) + return update_video_attached_pic(mpctx); + double pts; while (1) { - if (vo_get_buffered_frame(video_out, false) >= 0) - break; - if (filter_output_queued_frame(mpctx)) + if (load_next_vo_frame(mpctx, false)) break; pts = MP_NOPTS_VALUE; - struct demux_packet *pkt; + struct demux_packet *pkt = NULL; while (1) { pkt = demux_read_packet(mpctx->sh_video->gsh); if (!pkt || pkt->len) @@ -2570,7 +2597,7 @@ static double update_video(struct MPContext *mpctx, double endpts) determine_frame_pts(mpctx); filter_video(mpctx, decoded_frame); } else if (!pkt) { - if (vo_get_buffered_frame(video_out, true) < 0) + if (!load_next_vo_frame(mpctx, true)) return -1; } break; @@ -2580,6 +2607,8 @@ static double update_video(struct MPContext *mpctx, double endpts) return 0; pts = video_out->next_pts; + if (sh_video->gsh->attached_picture) + pts = mpctx->last_seek_pts; if (pts == MP_NOPTS_VALUE) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "Video pts after filters MISSING\n"); // Try to use decoder pts from before filters @@ -3458,10 +3487,12 @@ static void run_playloop(struct MPContext *mpctx) mpctx->time_frame -= get_relative_time(mpctx); } if (mpctx->restart_playback) { - mpctx->syncing_audio = true; - if (mpctx->sh_audio) - fill_audio_out_buffers(mpctx, endpts); - mpctx->restart_playback = false; + if (mpctx->sync_audio_to_video) { + mpctx->syncing_audio = true; + if (mpctx->sh_audio) + fill_audio_out_buffers(mpctx, endpts); + mpctx->restart_playback = false; + } mpctx->time_frame = 0; get_relative_time(mpctx); } @@ -3473,6 +3504,8 @@ static void run_playloop(struct MPContext *mpctx) break; } // video + video_left &= mpctx->sync_audio_to_video; // force no-video semantics + if (mpctx->sh_audio && (mpctx->restart_playback ? !video_left : mpctx->ao->untimed && (mpctx->delay <= 0 || !video_left))) { diff --git a/demux/demux.c b/demux/demux.c index f0652fba4d..1ae4137e62 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -92,7 +92,6 @@ const demuxer_desc_t *const demuxer_list[] = { struct demux_stream { int selected; // user wants packets from this stream int eof; // end of demuxed stream? (true if all buffer empty) - int fill_count; // number of unsuccessful tries to get a packet int packs; // number of packets in buffer int bytes; // total bytes of packets in buffer struct demux_packet *head; @@ -441,16 +440,6 @@ overflow: return true; } -static bool need_coverart_hack(struct demuxer *demux) -{ - for (int n = 0; n < demux->num_streams; n++) { - struct sh_stream *sh = demux->streams[n]; - if (sh->attached_picture && sh->ds->selected) - return true; - } - return false; -} - // return value: // 0 = EOF or no stream found or invalid type // 1 = successfully read a packet @@ -476,31 +465,14 @@ static void ds_get_packets(struct sh_stream *sh) * despite the eof flag then it's better to clear it to avoid * weird behavior. */ ds->eof = 0; - ds->fill_count = 0; return; } - // avoid buffering too far ahead in e.g. badly interleaved files - // or when one stream is shorter, without breaking large audio - // delay with well interleaved files. - // This needs to be enough for at least 1 second of packets - // since libavformat mov demuxer does not try to interleave - // with more than 1s precision. - if (ds->fill_count > 80) - break; if (demux_check_queue_full(demux)) break; - int apacks = count_packs(demux, STREAM_AUDIO); - int vpacks = count_packs(demux, STREAM_VIDEO); - if (!demux_fill_buffer(demux)) break; // EOF - - if (need_coverart_hack(demux)) { - ds->fill_count += count_packs(demux, STREAM_AUDIO) - apacks; - ds->fill_count += count_packs(demux, STREAM_VIDEO) - vpacks; - } } mp_msg(MSGT_DEMUXER, MSGL_V, "ds_get_packets: EOF reached (stream: %s)\n", stream_type_name(sh->type)); diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 385cd23006..3f330332e3 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -351,7 +351,8 @@ static void select_tracks(struct demuxer *demuxer, int start) for (int n = start; n < priv->num_streams; n++) { struct sh_stream *stream = priv->streams[n]; AVStream *st = priv->avfc->streams[n]; - bool selected = stream && demuxer_stream_is_selected(demuxer, stream); + bool selected = stream && demuxer_stream_is_selected(demuxer, stream) && + !stream->attached_picture; st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL; } } @@ -388,8 +389,12 @@ static void handle_stream(demuxer_t *demuxer, int i) break; sh_video_t *sh_video = sh->video; - if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) - sh_video->gsh->attached_picture = true; + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) { + sh->attached_picture = new_demux_packet_from(st->attached_pic.data, + st->attached_pic.size); + sh->attached_picture->pts = 0; + talloc_steal(sh, sh->attached_picture); + } sh_video->format = codec->codec_tag; sh_video->disp_w = codec->width; @@ -679,8 +684,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux) dp->avpacket = pkt; int64_t ts = priv->use_dts ? pkt->dts : pkt->pts; - if (ts == AV_NOPTS_VALUE && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - ts = 0; if (ts != AV_NOPTS_VALUE) { dp->pts = ts * av_q2d(st->time_base); priv->last_pts = dp->pts * AV_TIME_BASE; diff --git a/demux/stheader.h b/demux/stheader.h index 0d94607fa2..2ca4bd0bae 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -61,7 +61,9 @@ struct sh_stream { char *title; char *lang; // language code bool default_track; // container default track flag - bool attached_picture; // stream is a picture (such as album art) + + // stream is a picture (such as album art) + struct demux_packet *attached_picture; // Human readable description of the running decoder, or NULL char *decoder_desc; -- cgit v1.2.3 From 3a7fa5b186fc130c159b072cb86194644f9876fb Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 20:05:43 +0200 Subject: demux: allow passing NULL as packet to demuxer_add_packet() demux_subreader relied on this. --- demux/demux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 1ae4137e62..3cd23a4b42 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -392,7 +392,7 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, demux_packet_t *dp) { struct demux_stream *ds = stream ? stream->ds : NULL; - if (!ds || !ds->selected) { + if (!dp || !ds || !ds->selected) { talloc_free(dp); return 0; } -- cgit v1.2.3 From d17d2fdc7c536821b3fea8c4a37c0ad09fc487db Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 20:08:12 +0200 Subject: demux: change signature of open functions, cleanups Preparation for redoing the open functions. --- demux/demux.c | 21 ++++++++------------- demux/demux.h | 16 ++++++---------- demux/demux_cue.c | 10 +++++----- demux/demux_edl.c | 8 ++++---- demux/demux_lavf.c | 48 ++++++++++++++++++++++++------------------------ demux/demux_libass.c | 10 +++++----- demux/demux_mf.c | 37 +++++++++++++++++++------------------ demux/demux_mkv.c | 33 ++++++++++++++++----------------- demux/demux_mng.c | 49 ++++++++++++++++++++++--------------------------- demux/demux_rawaudio.c | 27 ++++++++++++--------------- demux/demux_rawvideo.c | 30 +++++++++++++----------------- demux/demux_subreader.c | 6 +++--- stream/tv.c | 34 +++++++++++++++------------------- 13 files changed, 152 insertions(+), 177 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 3cd23a4b42..64fee955ed 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -72,7 +72,7 @@ const demuxer_desc_t *const demuxer_list[] = { #ifdef CONFIG_TV &demuxer_desc_tv, #endif -#ifdef CONFIG_LIBASS +#ifdef CONFIG_ASS &demuxer_desc_libass, #endif &demuxer_desc_matroska, @@ -594,16 +594,14 @@ static struct demuxer *open_given_type(struct MPOpts *opts, struct demuxer_params *params) { struct demuxer *demuxer; - int fformat; + int fformat = desc->type; mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s\n", desc->name); demuxer = new_demuxer(opts, stream, desc->type, filename); demuxer->params = params; - if (desc->check_file) - fformat = desc->check_file(demuxer); - else - fformat = desc->type; - if (force) - fformat = desc->type; + if (!force) { + if (desc->check_file) + fformat = desc->check_file(demuxer) >= 0 ? fformat : 0; + } if (fformat == 0) goto fail; if (fformat == desc->type) { @@ -614,15 +612,12 @@ static struct demuxer *open_given_type(struct MPOpts *opts, mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n", desc->shortdesc); if (demuxer->desc->open) { - struct demuxer *demux2 = demuxer->desc->open(demuxer); - if (!demux2) { + int ret = demuxer->desc->open(demuxer); + if (ret < 0) { mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Opening as detected format " "\"%s\" failed.\n", desc->shortdesc); goto fail; } - /* At least demux_mov can return a demux_demuxers instance - * from open() instead of the original fed in. */ - demuxer = demux2; } demuxer->file_format = fformat; if (stream_manages_timeline(demuxer->stream)) { diff --git a/demux/demux.h b/demux/demux.h index 3b0d6d5956..c43f0282fb 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -105,19 +105,15 @@ typedef struct demuxer_desc { // If 1 detection is safe and fast, do it before file extension check int safe_check; - // Check if can demux the file, return DEMUXER_TYPE_xxx on success - // Mandatory if safe_check == 1, else optional + // Return 0 on success, otherwise -1 int (*check_file)(struct demuxer *demuxer); - /// Get packets from file, return 0 on eof. Mandatory - int (*fill_buffer)(struct demuxer *demuxer); - /// Open the demuxer, return demuxer on success, NULL on failure - struct demuxer *(*open)(struct demuxer *demuxer); // Optional - /// Close the demuxer - void (*close)(struct demuxer *demuxer); // Optional - // Seek. Optional + // Open the demuxer, return 0 on success, otherwise -1 + int (*open)(struct demuxer *demuxer); + // The following functions are all optional + int (*fill_buffer)(struct demuxer *demuxer); // 0 on EOF, otherwise 1 + void (*close)(struct demuxer *demuxer); void (*seek)(struct demuxer *demuxer, float rel_seek_secs, float audio_delay, int flags); - // Various control functions. Optional int (*control)(struct demuxer *demuxer, int cmd, void *arg); } demuxer_desc_t; diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 073fa9d336..43ef910868 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -35,16 +35,16 @@ static int try_open_file(struct demuxer *demuxer) char buf[PROBE_SIZE]; int len = stream_read(s, buf, sizeof(buf)); if (len <= 0) - return 0; + return -1; if (!mp_probe_cue((struct bstr) { buf, len })) - return 0; + return -1; stream_seek(s, 0); demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) - return 0; + return -1; if (!mp_probe_cue((struct bstr) { buf, len })) - return 0; - return DEMUXER_TYPE_CUE; + return -1; + return 0; } const struct demuxer_desc demuxer_desc_cue = { diff --git a/demux/demux_edl.c b/demux/demux_edl.c index c35137ffb2..44fa824193 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -30,14 +30,14 @@ static int try_open_file(struct demuxer *demuxer) const int len = sizeof(header) - 1; char buf[len]; if (stream_read(s, buf, len) < len) - return 0; + return -1; if (strncmp(buf, header, len)) - return 0; + return -1; stream_seek(s, 0); demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) - return 0; - return DEMUXER_TYPE_EDL; + return -1; + return 0; } const struct demuxer_desc demuxer_desc_edl = { diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 3f330332e3..0e7690f606 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -211,7 +211,7 @@ static int lavf_check_file(demuxer_t *demuxer) if (!sep) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "Must specify filename in 'format:filename' form\n"); - return 0; + return -1; } avdevice_format = talloc_strndup(priv, priv->filename, sep - priv->filename); @@ -238,12 +238,12 @@ static int lavf_check_file(demuxer_t *demuxer) if (format) { if (strcmp(format, "help") == 0) { list_formats(); - return 0; + return -1; } priv->avif = av_find_input_format(format); if (!priv->avif) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "Unknown lavf format %s\n", format); - return 0; + return -1; } mp_msg(MSGT_DEMUX, MSGL_INFO, "Forced lavf %s demuxer\n", priv->avif->long_name); @@ -297,7 +297,7 @@ static int lavf_check_file(demuxer_t *demuxer) if (!priv->avif) { mp_msg(MSGT_HEADER, MSGL_V, "No format found, try lowering probescore.\n"); - return 0; + return -1; } success: @@ -306,7 +306,7 @@ success: if (!demuxer->filetype) demuxer->filetype = priv->avif->name; - return DEMUXER_TYPE_LAVF; + return 0; } static bool matches_avinputformat_name(struct lavf_priv *priv, @@ -493,7 +493,7 @@ static void add_metadata(demuxer_t *demuxer, AVDictionary *metadata) demux_info_add(demuxer, t->key, t->value); } -static demuxer_t *demux_open_lavf(demuxer_t *demuxer) +static int demux_open_lavf(demuxer_t *demuxer) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; @@ -505,7 +505,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer) // do not allow forcing the demuxer if (!priv->avif) - return NULL; + return -1; stream_seek(demuxer->stream, 0); @@ -548,7 +548,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer) mp_msg(MSGT_HEADER, MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", lavfdopts->avopt); - return NULL; + return -1; } } @@ -567,14 +567,14 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer) if (avformat_open_input(&avfc, priv->filename, priv->avif, NULL) < 0) { mp_msg(MSGT_HEADER, MSGL_ERR, "LAVF_header: avformat_open_input() failed\n"); - return NULL; + return -1; } priv->avfc = avfc; if (avformat_find_stream_info(avfc, NULL) < 0) { mp_msg(MSGT_HEADER, MSGL_ERR, "LAVF_header: av_find_stream_info() failed\n"); - return NULL; + return -1; } mp_msg(MSGT_HEADER, MSGL_V, "demux_lavf: avformat_find_stream_info() " @@ -640,7 +640,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer) #endif demuxer->accurate_seek = !priv->seek_by_bytes; - return demuxer; + return 0; } static int destroy_avpacket(void *pkt) @@ -899,17 +899,17 @@ static void demux_close_lavf(demuxer_t *demuxer) const demuxer_desc_t demuxer_desc_lavf = { - "libavformat demuxer", - "lavf", - "libavformat", - "Michael Niedermayer", - "supports many formats, requires libavformat", - DEMUXER_TYPE_LAVF, - 1, - lavf_check_file, - demux_lavf_fill_buffer, - demux_open_lavf, - demux_close_lavf, - demux_seek_lavf, - demux_lavf_control + .info = "libavformat demuxer", + .name = "lavf", + .shortdesc = "libavformat", + .author = "Michael Niedermayer", + .comment = "supports many formats, requires libavformat", + .type = DEMUXER_TYPE_LAVF, + .safe_check = 1, + .check_file = lavf_check_file, + .fill_buffer = demux_lavf_fill_buffer, + .open = demux_open_lavf, + .close = demux_close_lavf, + .seek = demux_seek_lavf, + .control = demux_lavf_control, }; diff --git a/demux/demux_libass.c b/demux/demux_libass.c index cbc85b3abe..4dadb42b89 100644 --- a/demux/demux_libass.c +++ b/demux/demux_libass.c @@ -41,7 +41,7 @@ static int d_check_file(struct demuxer *demuxer) // library handles mismatch, so make sure everything uses a global handle. ASS_Library *lib = demuxer->params ? demuxer->params->ass_library : NULL; if (!lib) - return 0; + return -1; // Probe by loading a part of the beginning of the file with libass. // Incomplete scripts are usually ok, and we hope libass is not verbose @@ -64,7 +64,7 @@ static int d_check_file(struct demuxer *demuxer) talloc_free(cbuf.start); talloc_free(buf.start); if (!track) - return 0; + return -1; ass_free_track(track); // Actually load the full thing. @@ -73,7 +73,7 @@ static int d_check_file(struct demuxer *demuxer) if (!buf.start) { mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " "larger than 100 MB: %s\n", demuxer->filename); - return 0; + return -1; } cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, MP_ICONV_VERBOSE); if (cbuf.start == NULL) @@ -83,7 +83,7 @@ static int d_check_file(struct demuxer *demuxer) talloc_free(cbuf.start); talloc_free(buf.start); if (!track) - return 0; + return -1; track->name = strdup(demuxer->filename); @@ -96,7 +96,7 @@ static int d_check_file(struct demuxer *demuxer) sh->sub->track = track; sh->codec = "ass"; - return DEMUXER_TYPE_LIBASS; + return 0; } static void d_close(struct demuxer *demuxer) diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 7465ddeae8..3a72558208 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -187,14 +187,15 @@ static mf_t *open_mf(demuxer_t *demuxer) static int demux_check_file(demuxer_t *demuxer) { if (demuxer->stream->type == STREAMTYPE_MF) - return DEMUXER_TYPE_MF; + return 0; mf_t *mf = open_mf(demuxer); bool ok = mf && probe_format(mf); free_mf(mf); - return ok ? DEMUXER_TYPE_MF : 0; + return ok ? 0 : -1; } -static demuxer_t* demux_open_mf(demuxer_t* demuxer){ +static int demux_open_mf(demuxer_t* demuxer) +{ sh_video_t *sh_video = NULL; mf_t *mf = open_mf(demuxer); @@ -223,11 +224,11 @@ static demuxer_t* demux_open_mf(demuxer_t* demuxer){ mf->sh = sh_video; demuxer->priv=(void*)mf; - return demuxer; + return 0; error: free_mf(mf); - return NULL; + return -1; } static void demux_close_mf(demuxer_t* demuxer) { @@ -253,17 +254,17 @@ static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) { } const demuxer_desc_t demuxer_desc_mf = { - "mf demuxer", - "mf", - "MF", - "?", - "multiframe?, pictures demuxer", - DEMUXER_TYPE_MF, - 1, - demux_check_file, - demux_mf_fill_buffer, - demux_open_mf, - demux_close_mf, - demux_seek_mf, - demux_control_mf + .info = "mf demuxer", + .name = "mf", + .shortdesc = "MF", + .author = "?", + .comment = "multiframe?, pictures demuxer", + .type = DEMUXER_TYPE_MF, + .safe_check = 1, + .check_file = demux_check_file, + .fill_buffer = demux_mf_fill_buffer, + .open = demux_open_mf, + .close = demux_close_mf, + .seek = demux_seek_mf, + .control = demux_control_mf, }; diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 0d174639c7..a60172cce9 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1759,11 +1759,11 @@ static int demux_mkv_open(demuxer_t *demuxer) stream_seek(s, s->start_pos); if (!read_ebml_header(demuxer)) - return 0; + return -1; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n"); if (!read_mkv_segment_header(demuxer)) - return 0; + return -1; mkv_d = talloc_zero(demuxer, struct mkv_demuxer); demuxer->priv = mkv_d; @@ -1788,7 +1788,7 @@ static int demux_mkv_open(demuxer_t *demuxer) } int res = read_header_element(demuxer, id, 0); if (res <= -2) - return 0; + return -1; if (res < 0) break; } @@ -1805,7 +1805,7 @@ static int demux_mkv_open(demuxer_t *demuxer) demuxer->accurate_seek = true; - return DEMUXER_TYPE_MATROSKA; + return 0; } static bool bstr_read_u8(bstr *buffer, uint8_t *out_u8) @@ -2718,17 +2718,16 @@ static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg) } const demuxer_desc_t demuxer_desc_matroska = { - "Matroska demuxer", - "mkv", - "Matroska", - "Aurelien Jacobs", - "", - DEMUXER_TYPE_MATROSKA, - 1, // safe autodetect - demux_mkv_open, - demux_mkv_fill_buffer, - NULL, - mkv_free, - demux_mkv_seek, - demux_mkv_control + .info = "Matroska demuxer", + .name = "mkv", + .shortdesc = "Matroska", + .author = "Aurelien Jacobs", + .comment = "", + .type = DEMUXER_TYPE_MATROSKA, + .safe_check = 1, // safe autodetect + .check_file = demux_mkv_open, + .fill_buffer = demux_mkv_fill_buffer, + .close = mkv_free, + .seek = demux_mkv_seek, + .control = demux_mkv_control }; diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 34fdf521b5..824a668868 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -263,10 +263,10 @@ static int demux_mng_check_file(demuxer_t *demuxer) { char buf[4]; if (stream_read(demuxer->stream, buf, 4) != 4) - return 0; + return -1; if (memcmp(buf, "\x8AMNG", 4)) - return 0; - return DEMUXER_TYPE_MNG; + return -1; + return 0; } /** @@ -343,12 +343,7 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer) return 1; } -/** - * \brief MPlayer callback: Open MNG stream. - * \param[in] demuxer demuxer structure - * \return demuxer structure on success, \p NULL on error - */ -static demuxer_t * demux_mng_open(demuxer_t * demuxer) +static int demux_mng_open(demuxer_t * demuxer) { mng_priv_t * mng_priv; mng_handle h_mng; @@ -368,7 +363,7 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not initialize MNG image instance\n"); free(mng_priv); - return NULL; + return -1; } // MNG image handle into private data @@ -388,7 +383,7 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) "demux_mng: could not set MNG callbacks\n"); mng_cleanup(&h_mng); free(mng_priv); - return NULL; + return -1; } // start reading MNG data @@ -399,7 +394,7 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) "mng_retcode %d\n", mng_ret); mng_cleanup(&h_mng); free(mng_priv); - return NULL; + return -1; } // check that MNG header is processed now @@ -408,7 +403,7 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) "demux_mng: internal error: header not processed\n"); mng_cleanup(&h_mng); free(mng_priv); - return NULL; + return -1; } // create a new video stream header @@ -432,7 +427,7 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer) // set private data in demuxer and return demuxer demuxer->priv = mng_priv; - return demuxer; + return 0; } /** @@ -569,17 +564,17 @@ static int demux_mng_control(demuxer_t * demuxer, int cmd, void * arg) } const demuxer_desc_t demuxer_desc_mng = { - "MNG demuxer", - "mng", - "MNG", - "Stefan Schuermans ", - "MNG files, using libmng", - DEMUXER_TYPE_MNG, - 0, // unsafe autodetect (only checking magic at beginning of stream) - demux_mng_check_file, - demux_mng_fill_buffer, - demux_mng_open, - demux_mng_close, - demux_mng_seek, - demux_mng_control + .info = "MNG demuxer", + .name = "mng", + .shortdesc = "MNG", + .author = "Stefan Schuermans ", + .comment = "MNG files, using libmng", + .type = DEMUXER_TYPE_MNG, + .safe_check = 0, // unsafe autodetect (only checking magic at beginning of stream) + .check_file = demux_mng_check_file, + .fill_buffer = demux_mng_fill_buffer, + .open = demux_mng_open, + .close = demux_mng_close, + .seek = demux_mng_seek, + .control = demux_mng_control, }; diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 74134743a0..13bbbb341a 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -43,13 +43,13 @@ const m_option_t demux_rawaudio_opts[] = { }; -static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { +static int demux_rawaudio_open(demuxer_t* demuxer) { struct sh_stream *sh; sh_audio_t* sh_audio; WAVEFORMATEX* w; if ((format & AF_FORMAT_SPECIAL_MASK) != 0) - return NULL; + return -1; sh = new_sh_stream(demuxer, STREAM_AUDIO); sh_audio = sh->audio; @@ -69,7 +69,7 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) { demuxer->movi_start = demuxer->stream->start_pos; demuxer->movi_end = demuxer->stream->end_pos; - return demuxer; + return 0; } static int demux_rawaudio_fill_buffer(demuxer_t* demuxer) @@ -110,16 +110,13 @@ static void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,float aud } const demuxer_desc_t demuxer_desc_rawaudio = { - "Raw audio demuxer", - "rawaudio", - "rawaudio", - "?", - "", - DEMUXER_TYPE_RAWAUDIO, - 0, // no autodetect - NULL, - demux_rawaudio_fill_buffer, - demux_rawaudio_open, - NULL, - demux_rawaudio_seek, + .info = "Raw audio demuxer", + .name = "rawaudio", + .shortdesc = "rawaudio", + .author = "?", + .comment = "", + .type = DEMUXER_TYPE_RAWAUDIO, + .fill_buffer = demux_rawaudio_fill_buffer, + .open = demux_rawaudio_open, + .seek = demux_rawaudio_seek, }; diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 4340362192..488c13bdec 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -56,13 +56,13 @@ const m_option_t demux_rawvideo_opts[] = { }; -static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { +static int demux_rawvideo_open(demuxer_t* demuxer) { struct sh_stream *sh; sh_video_t* sh_video; if(!width || !height){ mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: width or height not specified!\n"); - return 0; + return -1; } const char *decoder = "rawvideo"; @@ -109,7 +109,7 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { } if (!bpp) { mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: img size not specified and unknown format!\n"); - return 0; + return -1; } imgsize = width * height * bpp / 8; } @@ -126,7 +126,7 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) { demuxer->movi_start = demuxer->stream->start_pos; demuxer->movi_end = demuxer->stream->end_pos; - return demuxer; + return 0; } static int demux_rawvideo_fill_buffer(demuxer_t* demuxer) @@ -166,17 +166,13 @@ static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float aud const demuxer_desc_t demuxer_desc_rawvideo = { - "Raw video demuxer", - "rawvideo", - "rawvideo", - "?", - "", - DEMUXER_TYPE_RAWVIDEO, - 0, // no autodetect - NULL, - demux_rawvideo_fill_buffer, - demux_rawvideo_open, - NULL, - demux_rawvideo_seek, - NULL + .info = "Raw video demuxer", + .name = "rawvideo", + .shortdesc = "rawvideo", + .author = "?", + .comment = "", + .type = DEMUXER_TYPE_RAWVIDEO, + .fill_buffer = demux_rawvideo_fill_buffer, + .open = demux_rawvideo_open, + .seek = demux_rawvideo_seek, }; diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index ce69218e50..7758aa968c 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1336,11 +1336,11 @@ static int d_check_file(struct demuxer *demuxer) free_stream(ps); if (!res) - return 0; + return -1; sub_data *sd = sub_read_file(demuxer->stream, &sr); if (!sd) - return 0; + return -1; struct priv *p = talloc_zero(demuxer, struct priv); demuxer->priv = p; @@ -1355,7 +1355,7 @@ static int d_check_file(struct demuxer *demuxer) demuxer->accurate_seek = true; - return DEMUXER_TYPE_SUBREADER; + return 0; } static int d_fill_buffer(struct demuxer *demuxer) diff --git a/stream/tv.c b/stream/tv.c index 2c930781bc..aa5383402f 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -701,7 +701,7 @@ static int tv_uninit(tvi_handle_t *tvh) return res; } -static demuxer_t* demux_open_tv(demuxer_t *demuxer) +static int demux_open_tv(demuxer_t *demuxer) { tvi_handle_t *tvh; sh_video_t *sh_video; @@ -709,14 +709,14 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer) const tvi_functions_t *funcs; demuxer->priv=NULL; - if(!(tvh=tv_begin(demuxer->stream->priv))) return NULL; - if (!tvh->functions->init(tvh->priv)) return NULL; + if(!(tvh=tv_begin(demuxer->stream->priv))) return -1; + if (!tvh->functions->init(tvh->priv)) return -1; tvh->demuxer = demuxer; if (!open_tv(tvh)){ tv_uninit(tvh); - return NULL; + return -1; } funcs = tvh->functions; demuxer->priv=tvh; @@ -827,7 +827,7 @@ no_audio: if(!(funcs->start(tvh->priv))){ // start failed :( tv_uninit(tvh); - return NULL; + return -1; } /* set color eq */ @@ -840,7 +840,7 @@ no_audio: if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) mp_msg(MSGT_TV,MSGL_WARN,"Unable to set gain control!\n"); - return demuxer; + return 0; } static void demux_close_tv(demuxer_t *demuxer) @@ -1094,17 +1094,13 @@ int tv_step_chanlist(tvi_handle_t *tvh) } demuxer_desc_t demuxer_desc_tv = { - "Tv card demuxer", - "tv", - "TV", - "Alex Beregszaszi, Charles R. Henrich", - "?", - DEMUXER_TYPE_TV, - 0, // no autodetect - NULL, - demux_tv_fill_buffer, - demux_open_tv, - demux_close_tv, - NULL, - NULL + .info = "Tv card demuxer", + .name = "tv", + .shortdesc = "TV", + .author = "Alex Beregszaszi, Charles R. Henrich", + .comment = "?", + .type = DEMUXER_TYPE_TV, + .fill_buffer = demux_tv_fill_buffer, + .open = demux_open_tv, + .close = demux_close_tv, }; -- cgit v1.2.3 From 52c3eb69765a0d1070bf240353095c8ff546765b Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Jul 2013 21:10:42 +0200 Subject: core: change open_stream and demux_open signature This removes the dependency on DEMUXER_TYPE_* and the file_format parameter from the stream open functions. Remove some of the playlist handling code. It looks like this was needed only for loading linked mov files with demux_mov (which was removed long ago). Delete a minor bit of dead network-related code from stream.c as well. --- core/asxparser.c | 3 +-- core/encode_lavc.c | 2 +- core/input/input.c | 2 +- core/mplayer.c | 34 ++++------------------------------ core/playlist_parser.c | 5 +---- core/timeline/tl_cue.c | 7 +++---- core/timeline/tl_edl.c | 7 ++----- core/timeline/tl_matroska.c | 17 ++++------------- demux/demux.c | 40 ++++++++++++++++------------------------ demux/demux.h | 9 ++------- demux/demux_mf.c | 2 +- stream/stream.c | 42 ++++++++++-------------------------------- stream/stream.h | 7 +++---- stream/stream_avdevice.c | 4 ++-- stream/stream_bluray.c | 3 +-- stream/stream_cdda.c | 4 ++-- stream/stream_dvb.c | 4 ++-- stream/stream_dvd.c | 7 ++++--- stream/stream_file.c | 3 ++- stream/stream_lavf.c | 10 +++++----- stream/stream_memory.c | 2 +- stream/stream_mf.c | 4 ++-- stream/stream_null.c | 3 ++- stream/stream_pvr.c | 2 +- stream/stream_radio.c | 5 +++-- stream/stream_smb.c | 3 ++- stream/stream_tv.c | 4 ++-- stream/stream_vcd.c | 5 +++-- video/out/gl_lcms.c | 2 +- 29 files changed, 84 insertions(+), 158 deletions(-) (limited to 'demux/demux.c') diff --git a/core/asxparser.c b/core/asxparser.c index 17ce6b3e8c..0fc10eb059 100644 --- a/core/asxparser.c +++ b/core/asxparser.c @@ -451,7 +451,6 @@ asx_parse_ref(ASX_Parser_t* parser, char** attribs) { static void asx_parse_entryref(ASX_Parser_t* parser,char* buffer,char** _attribs) { char *href; stream_t* stream; - int f=DEMUXER_TYPE_UNKNOWN; if(parser->deep > 0) return; @@ -461,7 +460,7 @@ static void asx_parse_entryref(ASX_Parser_t* parser,char* buffer,char** _attribs asx_warning_attrib_required(parser,"ENTRYREF" ,"HREF" ); return; } - stream=open_stream(href,0,&f); + stream=stream_open(href, NULL); if(!stream) { mp_msg(MSGT_PLAYTREE,MSGL_WARN,"Can't open playlist %s\n",href); free(href); diff --git a/core/encode_lavc.c b/core/encode_lavc.c index 9fada7de58..75e57a2443 100644 --- a/core/encode_lavc.c +++ b/core/encode_lavc.c @@ -397,7 +397,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx, buf[sizeof(buf) - 1] = 0; if (value_has_flag(de ? de->value : "", "pass2")) { - if (!(*bytebuf = open_stream(buf, NULL, NULL))) { + if (!(*bytebuf = stream_open(buf, NULL))) { mp_msg(MSGT_ENCODE, MSGL_WARN, "%s: could not open '%s', " "disabling 2-pass encoding at pass 2\n", prefix, buf); stream->codec->flags &= ~CODEC_FLAG_PASS2; diff --git a/core/input/input.c b/core/input/input.c index e87d9bb560..e736c6486d 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -1969,7 +1969,7 @@ static int parse_config_file(struct input_ctx *ictx, char *file, bool warn) "Input config file %s not found.\n", file); return 0; } - stream_t *s = open_stream(file, NULL, NULL); + stream_t *s = stream_open(file, NULL); if (!s) { mp_msg(MSGT_INPUT, MSGL_ERR, "Can't open input config file %s.\n", file); return 0; diff --git a/core/mplayer.c b/core/mplayer.c index 026af6a989..73108d8d34 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -3882,11 +3882,10 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, struct MPOpts *opts = &mpctx->opts; if (!filename) return NULL; - int format = 0; char *disp_filename = filename; if (strncmp(disp_filename, "memory://", 9) == 0) disp_filename = "memory://"; // avoid noise - struct stream *stream = open_stream(filename, &mpctx->opts, &format); + struct stream *stream = stream_open(filename, &mpctx->opts); if (!stream) goto err_out; stream_enable_cache_percent(&stream, stream_cache, @@ -3896,8 +3895,7 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, .ass_library = mpctx->ass_library, // demux_libass requires it }; struct demuxer *demuxer = - demux_open_withparams(&mpctx->opts, stream, format, demuxer_name, - filename, ¶ms); + demux_open(stream, demuxer_name, ¶ms, &mpctx->opts); if (!demuxer) { free_stream(stream); goto err_out; @@ -4156,36 +4154,13 @@ static void play_current_file(struct MPContext *mpctx) } stream_filename = mpctx->resolve_result->url; } - int file_format = DEMUXER_TYPE_UNKNOWN; - mpctx->stream = open_stream(stream_filename, opts, &file_format); + mpctx->stream = stream_open(stream_filename, opts); if (!mpctx->stream) { // error... demux_was_interrupted(mpctx); goto terminate_playback; } mpctx->initialized_flags |= INITIALIZED_STREAM; - if (file_format == DEMUXER_TYPE_PLAYLIST) { - mp_msg(MSGT_CPLAYER, MSGL_ERR, "\nThis looks like a playlist, but " - "playlist support will not be used automatically.\n" - "mpv's playlist code is unsafe and should only be used with " - "trusted sources.\nPlayback will probably fail.\n\n"); -#if 0 - // Handle playlist - mp_msg(MSGT_CPLAYER, MSGL_WARN, "Parsing playlist %s...\n", - mpctx->filename); - bool empty = true; - struct playlist *pl = playlist_parse(mpctx->stream); - if (pl) { - empty = pl->first == NULL; - playlist_transfer_entries(mpctx->playlist, pl); - talloc_free(pl); - } - if (empty) - mp_msg(MSGT_CPLAYER, MSGL_ERR, "Playlist was invalid or empty!\n"); - mpctx->stop_play = PT_NEXT_ENTRY; - goto terminate_playback; -#endif - } mpctx->stream->start_pos += opts->seek_to_byte; if (opts->stream_dump && opts->stream_dump[0]) { @@ -4212,8 +4187,7 @@ goto_reopen_demuxer: ; mpctx->audio_delay = opts->audio_delay; - mpctx->demuxer = demux_open(opts, mpctx->stream, file_format, - mpctx->filename); + mpctx->demuxer = demux_open(mpctx->stream, NULL, NULL, opts); mpctx->master_demuxer = mpctx->demuxer; if (!mpctx->demuxer) { diff --git a/core/playlist_parser.c b/core/playlist_parser.c index 67d58024c1..59d5123be6 100644 --- a/core/playlist_parser.c +++ b/core/playlist_parser.c @@ -699,10 +699,7 @@ err_out: struct playlist *playlist_parse_file(const char *file) { - stream_t *stream; - int f=DEMUXER_TYPE_PLAYLIST; - - stream = open_stream(file, 0, &f); + stream_t *stream = stream_open(file, NULL); if(!stream) { mp_msg(MSGT_PLAYTREE,MSGL_ERR, "Error while opening playlist file %s: %s\n", diff --git a/core/timeline/tl_cue.c b/core/timeline/tl_cue.c index a965cfd877..1953f46116 100644 --- a/core/timeline/tl_cue.c +++ b/core/timeline/tl_cue.c @@ -188,11 +188,10 @@ static bool try_open(struct MPContext *mpctx, char *filename) || bstrcasecmp(bstr0(mpctx->demuxer->filename), bfilename) == 0) return false; - int format = 0; - struct stream *s = open_stream(filename, &mpctx->opts, &format); + struct stream *s = stream_open(filename, &mpctx->opts); if (!s) return false; - struct demuxer *d = demux_open(&mpctx->opts, s, format, filename); + struct demuxer *d = demux_open(s, NULL, NULL, &mpctx->opts); // Since .bin files are raw PCM data with no headers, we have to explicitly // open them. Also, try to avoid to open files that are most likely not .bin // files, as that would only play noise. Checking the file extension is @@ -201,7 +200,7 @@ static bool try_open(struct MPContext *mpctx, char *filename) // CD sector size (2352 bytes) if (!d && bstr_case_endswith(bfilename, bstr0(".bin"))) { mp_msg(MSGT_CPLAYER, MSGL_WARN, "CUE: Opening as BIN file!\n"); - d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_RAWAUDIO, filename); + d = demux_open(s, "rawaudio", NULL, &mpctx->opts); } if (d) { add_source(mpctx, d); diff --git a/core/timeline/tl_edl.c b/core/timeline/tl_edl.c index 0303956513..6096d03b6a 100644 --- a/core/timeline/tl_edl.c +++ b/core/timeline/tl_edl.c @@ -354,13 +354,10 @@ void build_edl_timeline(struct MPContext *mpctx) mpctx->num_sources = 1; for (int i = 0; i < num_sources; i++) { - int format = 0; - struct stream *s = open_stream(edl_ids[i].filename, &mpctx->opts, - &format); + struct stream *s = stream_open(edl_ids[i].filename, &mpctx->opts); if (!s) goto openfail; - struct demuxer *d = demux_open(&mpctx->opts, s, format, - edl_ids[i].filename); + struct demuxer *d = demux_open(s, NULL, NULL, &mpctx->opts); if (!d) { free_stream(s); openfail: diff --git a/core/timeline/tl_matroska.c b/core/timeline/tl_matroska.c index 6752b5ff4c..614ce0d6b7 100644 --- a/core/timeline/tl_matroska.c +++ b/core/timeline/tl_matroska.c @@ -113,13 +113,6 @@ static char **find_files(const char *original_file, const char *suffix) return results; } -static struct demuxer *open_demuxer(struct stream *stream, - struct MPContext *mpctx, char *filename, struct demuxer_params *params) -{ - return demux_open_withparams(&mpctx->opts, stream, - DEMUXER_TYPE_MATROSKA, NULL, filename, params); -} - static int enable_cache(struct MPContext *mpctx, struct stream **stream, struct demuxer **demuxer, struct demuxer_params *params) { @@ -133,8 +126,7 @@ static int enable_cache(struct MPContext *mpctx, struct stream **stream, free_demuxer(*demuxer); free_stream(*stream); - int format = 0; - *stream = open_stream(filename, &mpctx->opts, &format); + *stream = stream_open(filename, &mpctx->opts); if (!*stream) { talloc_free(filename); return -1; @@ -145,7 +137,7 @@ static int enable_cache(struct MPContext *mpctx, struct stream **stream, opts->stream_cache_min_percent, opts->stream_cache_seek_min_percent); - *demuxer = open_demuxer(*stream, mpctx, filename, params); + *demuxer = demux_open(*stream, "mkv", params, &mpctx->opts); if (!*demuxer) { talloc_free(filename); free_stream(*stream); @@ -167,11 +159,10 @@ static bool check_file_seg(struct MPContext *mpctx, struct demuxer **sources, .matroska_wanted_segment = segment, .matroska_was_valid = &was_valid, }; - int format = 0; - struct stream *s = open_stream(filename, &mpctx->opts, &format); + struct stream *s = stream_open(filename, &mpctx->opts); if (!s) return false; - struct demuxer *d = open_demuxer(s, mpctx, filename, ¶ms); + struct demuxer *d = demux_open(s, "mkv", ¶ms, &mpctx->opts); if (!d) { free_stream(s); diff --git a/demux/demux.c b/demux/demux.c index 64fee955ed..5a0e05d48f 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -242,8 +242,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, - char *filename) +static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type) { struct demuxer *d = talloc_zero(NULL, struct demuxer); d->stream = stream; @@ -259,8 +258,8 @@ static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, mp_msg(MSGT_DEMUXER, MSGL_ERR, "BUG! Invalid demuxer type in new_demuxer(), " "big troubles ahead.\n"); - if (filename) // Filename hack for avs_check_file - d->filename = strdup(filename); + if (stream->url) + d->filename = strdup(stream->url); stream_seek(stream, stream->start_pos); return d; } @@ -590,13 +589,12 @@ 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, - char *filename, struct demuxer_params *params) { struct demuxer *demuxer; int fformat = desc->type; mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s\n", desc->name); - demuxer = new_demuxer(opts, stream, desc->type, filename); + demuxer = new_demuxer(opts, stream, desc->type); demuxer->params = params; if (!force) { if (desc->check_file) @@ -644,20 +642,20 @@ 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, filename, params); + return open_given_type(opts, desc, stream, false, params); } fail: free_demuxer(demuxer); return NULL; } -struct demuxer *demux_open_withparams(struct MPOpts *opts, - struct stream *stream, int file_format, - char *force_format, char *filename, - struct demuxer_params *params) +struct demuxer *demux_open(struct stream *stream, char *force_format, + struct demuxer_params *params, struct MPOpts *opts) { struct demuxer *demuxer = NULL; const struct demuxer_desc *desc; + if (!force_format) + force_format = opts->demuxer_name; int force = 0; int demuxer_type; @@ -666,6 +664,7 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, force_format); return NULL; } + int file_format = 0; if (demuxer_type) file_format = demuxer_type; @@ -675,13 +674,13 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, if (!desc) // should only happen with obsolete -demuxer 99 numeric format return NULL; - return open_given_type(opts, desc, stream, force, filename, params); + return open_given_type(opts, desc, stream, force, 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, filename, params); + demuxer = open_given_type(opts, desc, stream, false, params); if (demuxer) return demuxer; } @@ -690,10 +689,10 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, // Ok. We're over the stable detectable fileformats, the next ones are // a bit fuzzy. So by default (extension_parsing==1) try extension-based // detection first: - if (filename && opts->extension_parsing == 1) { - desc = get_demuxer_desc_from_type(demuxer_type_by_filename(filename)); + if (stream->url && opts->extension_parsing == 1) { + desc = get_demuxer_desc_from_type(demuxer_type_by_filename(stream->url)); if (desc) - demuxer = open_given_type(opts, desc, stream, false, filename, params); + demuxer = open_given_type(opts, desc, stream, false, params); if (demuxer) return demuxer; } @@ -701,7 +700,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, filename, params); + demuxer = open_given_type(opts, desc, stream, false, params); if (demuxer) return demuxer; } @@ -710,13 +709,6 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, return NULL; } -struct demuxer *demux_open(struct MPOpts *opts, stream_t *vs, int file_format, - char *filename) -{ - return demux_open_withparams(opts, vs, file_format, opts->demuxer_name, - filename, NULL); -} - void demux_flush(demuxer_t *demuxer) { for (int n = 0; n < demuxer->num_streams; n++) diff --git a/demux/demux.h b/demux/demux.h index c43f0282fb..f64a02dce1 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -230,13 +230,8 @@ bool demux_stream_eof(struct sh_stream *sh); struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type); -struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, - int file_format, char *filename); - -struct demuxer *demux_open_withparams(struct MPOpts *opts, - struct stream *stream, int file_format, - char *force_format, char *filename, - struct demuxer_params *params); +struct demuxer *demux_open(struct stream *stream, char *force_format, + struct demuxer_params *params, struct MPOpts *opts); void demux_flush(struct demuxer *demuxer); int demux_seek(struct demuxer *demuxer, float rel_seek_secs, float audio_delay, diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 3a72558208..5e3469a0f1 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -74,7 +74,7 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer) if (!stream) { char *filename = mf->names[mf->curr_frame]; if (filename) - stream = open_stream(filename, demuxer->opts, NULL); + stream = stream_open(filename, demuxer->opts); } if (stream) { diff --git a/stream/stream.c b/stream/stream.c index 3dc25d7880..32ae0047be 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -131,10 +131,8 @@ static stream_t *new_stream(size_t min_size); static int stream_seek_unbuffered(stream_t *s, int64_t newpos); static stream_t *open_stream_plugin(const stream_info_t *sinfo, - const char *filename, - int mode, struct MPOpts *options, - int *file_format, int *ret, - char **redirected_url) + const char *filename, int mode, + struct MPOpts *options, int *ret) { void *arg = NULL; stream_t *s; @@ -162,7 +160,7 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo, s->url = strdup(filename); s->flags = 0; s->mode = mode; - *ret = sinfo->open(s, mode, arg, file_format); + *ret = sinfo->open(s, mode, arg); if ((*ret) != STREAM_OK) { free(s->url); talloc_free(s); @@ -201,21 +199,14 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo, static stream_t *open_stream_full(const char *filename, int mode, - struct MPOpts *options, int *file_format) + struct MPOpts *options) { int i, j, l, r; const stream_info_t *sinfo; stream_t *s; - char *redirected_url = NULL; assert(filename); - int dummy; - if (!file_format) - file_format = &dummy; - - *file_format = DEMUXER_TYPE_UNKNOWN; - for (i = 0; auto_open_streams[i]; i++) { sinfo = auto_open_streams[i]; if (!sinfo->protocols) { @@ -230,22 +221,10 @@ static stream_t *open_stream_full(const char *filename, int mode, if ((l == 0 && !strstr(filename, "://")) || ((strncasecmp(sinfo->protocols[j], filename, l) == 0) && (strncmp("://", filename + l, 3) == 0))) { - *file_format = DEMUXER_TYPE_UNKNOWN; - s = - open_stream_plugin(sinfo, filename, mode, options, - file_format, - &r, - &redirected_url); + s = open_stream_plugin(sinfo, filename, mode, options, &r); if (s) return s; - if (r == STREAM_REDIRECTED && redirected_url) { - mp_msg(MSGT_OPEN, MSGL_V, "[%s] open %s redirected to %s\n", - sinfo->info, filename, redirected_url); - s = open_stream_full(redirected_url, mode, options, - file_format); - free(redirected_url); - return s; - } else if (r != STREAM_UNSUPPORTED) { + if (r != STREAM_UNSUPPORTED) { mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s.\n", filename); return NULL; @@ -259,15 +238,14 @@ static stream_t *open_stream_full(const char *filename, int mode, return NULL; } -stream_t *open_stream(const char *filename, struct MPOpts *options, - int *file_format) +struct stream *stream_open(const char *filename, struct MPOpts *options) { - return open_stream_full(filename, STREAM_READ, options, file_format); + return open_stream_full(filename, STREAM_READ, options); } stream_t *open_output_stream(const char *filename, struct MPOpts *options) { - return open_stream_full(filename, STREAM_WRITE, options, NULL); + return open_stream_full(filename, STREAM_WRITE, options); } static int stream_reconnect(stream_t *s) @@ -655,7 +633,7 @@ int stream_check_interrupt(int time) stream_t *open_memory_stream(void *data, int len) { assert(len >= 0); - stream_t *s = open_stream("memory://", NULL, NULL); + stream_t *s = stream_open("memory://", NULL); assert(s); stream_control(s, STREAM_CTRL_SET_CONTENTS, &(bstr){data, len}); return s; diff --git a/stream/stream.h b/stream/stream.h index 149618ccd6..0d7e02ed4d 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -70,7 +70,6 @@ #define MP_STREAM_SEEK_FW 4 #define MP_STREAM_SEEK (MP_STREAM_SEEK_BW | MP_STREAM_SEEK_FW) -#define STREAM_REDIRECTED -2 #define STREAM_UNSUPPORTED -1 #define STREAM_ERROR 0 #define STREAM_OK 1 @@ -121,7 +120,7 @@ typedef struct stream_info_st { const char *author; const char *comment; // opts is set from ->opts - int (*open)(struct stream *st, int mode, void *opts, int *file_format); + int (*open)(struct stream *st, int mode, void *opts); const char *protocols[MAX_STREAM_PROTOCOLS]; const void *opts; int opts_url; /* If this is 1 we will parse the url as an option string @@ -158,6 +157,7 @@ typedef struct stream { void *priv; // used for DVD, TV, RTSP etc char *url; // strdup() of filename/url char *mime_type; // when HTTP streaming is used + char *demuxer; // request demuxer to be used char *lavf_type; // name of expected demuxer type for lavf struct MPOpts *opts; @@ -278,8 +278,7 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, int stream_control(stream_t *s, int cmd, void *arg); void stream_update_size(stream_t *s); void free_stream(stream_t *s); -stream_t *open_stream(const char *filename, struct MPOpts *options, - int *file_format); +struct stream *stream_open(const char *filename, struct MPOpts *options); stream_t *open_output_stream(const char *filename, struct MPOpts *options); stream_t *open_memory_stream(void *data, int len); struct demux_stream; diff --git a/stream/stream_avdevice.c b/stream/stream_avdevice.c index e26d5a9060..bd342e1b10 100644 --- a/stream/stream_avdevice.c +++ b/stream/stream_avdevice.c @@ -26,15 +26,15 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len) return -1; } -static int open_f(stream_t *stream, int mode, void *opts, int *file_format) +static int open_f(stream_t *stream, int mode, void *opts) { if (mode != STREAM_READ) return STREAM_ERROR; stream->fill_buffer = fill_buffer; stream->type = STREAMTYPE_AVDEVICE; + stream->demuxer = "lavf"; - *file_format = DEMUXER_TYPE_LAVF; return STREAM_OK; } diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c index 64d1856873..131813dbb2 100644 --- a/stream/stream_bluray.c +++ b/stream/stream_bluray.c @@ -291,8 +291,7 @@ static int bluray_stream_control(stream_t *s, int cmd, void *arg) return STREAM_UNSUPPORTED; } -static int bluray_stream_open(stream_t *s, int mode, - void *opts, int *file_format) +static int bluray_stream_open(stream_t *s, int mode, void *opts) { struct stream_priv_s *p = opts; struct bluray_priv_s *b; diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c index 4e45e51a07..f5b36a9419 100644 --- a/stream/stream_cdda.c +++ b/stream/stream_cdda.c @@ -333,7 +333,7 @@ static int control(stream_t *stream, int cmd, void *arg) return STREAM_UNSUPPORTED; } -static int open_cdda(stream_t *st, int m, void *opts, int *file_format) +static int open_cdda(stream_t *st, int m, void *opts) { struct cdda_params *p = (struct cdda_params *)opts; int mode = p->paranoia_mode; @@ -479,7 +479,7 @@ static int open_cdda(stream_t *st, int m, void *opts, int *file_format) st->control = control; st->close = close_cdda; - *file_format = DEMUXER_TYPE_RAWAUDIO; + st->demuxer = "rawaudio"; m_struct_free(&stream_opts, opts); diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 77c0523eb2..8fabfb4fc1 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -659,7 +659,7 @@ static int dvb_streaming_start(stream_t *stream, struct stream_priv_s *opts, int -static int dvb_open(stream_t *stream, int mode, void *opts, int *file_format) +static int dvb_open(stream_t *stream, int mode, void *opts) { // I don't force the file format bacause, although it's almost always TS, // there are some providers that stream an IP multicast with M$ Mpeg4 inside @@ -739,7 +739,7 @@ static int dvb_open(stream_t *stream, int mode, void *opts, int *file_format) stream->close = dvbin_close; m_struct_free(&stream_opts, opts); - *file_format = DEMUXER_TYPE_LAVF; // TS + stream->demuxer = "lavf:mpegts"; return STREAM_OK; } diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index bf9cb9d4c7..b8161d16fa 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -745,7 +745,8 @@ static int control(stream_t *stream,int cmd,void* arg) } -static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { +static int open_s(stream_t *stream,int mode, void* opts) +{ struct stream_priv_s* p = (struct stream_priv_s*)opts; int k; @@ -1059,7 +1060,7 @@ fail: return STREAM_UNSUPPORTED; } -static int ifo_stream_open (stream_t *stream, int mode, void *opts, int *file_format) +static int ifo_stream_open (stream_t *stream, int mode, void *opts) { char* filename; struct stream_priv_s *spriv; @@ -1085,7 +1086,7 @@ static int ifo_stream_open (stream_t *stream, int mode, void *opts, int *file_fo free(stream->url); stream->url=strdup("dvd://"); - return open_s(stream, mode, spriv, file_format); + return open_s(stream, mode, spriv); } const stream_info_t stream_info_dvd = { diff --git a/stream/stream_file.c b/stream/stream_file.c index 924eb31dad..79ebbb3eef 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -110,7 +110,8 @@ static int control(stream_t *s, int cmd, void *arg) { return STREAM_UNSUPPORTED; } -static int open_f(stream_t *stream,int mode, void* opts, int* file_format) { +static int open_f(stream_t *stream,int mode, void* opts) +{ int f; mode_t m = 0; int64_t len; diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index 48d5e9d173..8a146a986d 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -33,7 +33,7 @@ #include "core/bstr.h" #include "core/mp_talloc.h" -static int open_f(stream_t *stream, int mode, void *opts, int *file_format); +static int open_f(stream_t *stream, int mode, void *opts); static char **read_icy(stream_t *stream); static int fill_buffer(stream_t *s, char *buffer, int max_len) @@ -115,7 +115,7 @@ static int control(stream_t *s, int cmd, void *arg) // avio doesn't seem to support this - emulate it by reopening close_f(s); s->priv = NULL; - return open_f(s, STREAM_READ, NULL, &(int) {0}); + return open_f(s, STREAM_READ, NULL); } } return STREAM_UNSUPPORTED; @@ -132,7 +132,7 @@ static bool mp_avio_has_opts(AVIOContext *avio) static const char * const prefix[] = { "lavf://", "ffmpeg://" }; -static int open_f(stream_t *stream, int mode, void *opts, int *file_format) +static int open_f(stream_t *stream, int mode, void *opts) { int flags = 0; AVIOContext *avio = NULL; @@ -163,7 +163,7 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format) * stream layer. demux_lavf will do all the real work. */ stream->seek = NULL; - *file_format = DEMUXER_TYPE_LAVF; + stream->demuxer = "lavf"; stream->lavf_type = "rtsp"; return STREAM_OK; } @@ -216,7 +216,7 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format) char *rtmp[] = {"rtmp:", "rtmpt:", "rtmpe:", "rtmpte:", "rtmps:"}; for (int i = 0; i < FF_ARRAY_ELEMS(rtmp); i++) if (!strncmp(filename, rtmp[i], strlen(rtmp[i]))) { - *file_format = DEMUXER_TYPE_LAVF; + stream->demuxer = "lavf"; stream->lavf_type = "flv"; } stream->priv = avio; diff --git a/stream/stream_memory.c b/stream/stream_memory.c index 0994e0816f..3616972cc5 100644 --- a/stream/stream_memory.c +++ b/stream/stream_memory.c @@ -54,7 +54,7 @@ static int control(stream_t *s, int cmd, void *arg) return STREAM_UNSUPPORTED; } -static int open_f(stream_t *stream, int mode, void* opts, int* file_format) +static int open_f(stream_t *stream, int mode, void* opts) { stream->type = STREAMTYPE_MEMORY; diff --git a/stream/stream_mf.c b/stream/stream_mf.c index 9b8b47188a..eef5d6fc4d 100644 --- a/stream/stream_mf.c +++ b/stream/stream_mf.c @@ -29,10 +29,10 @@ #include "demux/demux.h" static int -mf_stream_open (stream_t *stream, int mode, void *opts, int *file_format) +mf_stream_open (stream_t *stream, int mode, void *opts) { stream->type = STREAMTYPE_MF; - *file_format = DEMUXER_TYPE_MF; + stream->demuxer = "lavf"; return STREAM_OK; } diff --git a/stream/stream_null.c b/stream/stream_null.c index 5465702be8..c1965e6bd0 100644 --- a/stream/stream_null.c +++ b/stream/stream_null.c @@ -23,7 +23,8 @@ #include "stream.h" -static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { +static int open_s(stream_t *stream,int mode, void* opts) +{ stream->type = STREAMTYPE_DUMMY; return 1; diff --git a/stream/stream_pvr.c b/stream/stream_pvr.c index aeea46cf62..165a67ad37 100644 --- a/stream/stream_pvr.c +++ b/stream/stream_pvr.c @@ -1555,7 +1555,7 @@ pvr_stream_read (stream_t *stream, char *buffer, int size) } static int -pvr_stream_open (stream_t *stream, int mode, void *opts, int *file_format) +pvr_stream_open (stream_t *stream, int mode, void *opts) { struct v4l2_capability vcap; struct v4l2_ext_controls ctrls; diff --git a/stream/stream_radio.c b/stream/stream_radio.c index fae9be43d1..7e54cd4274 100644 --- a/stream/stream_radio.c +++ b/stream/stream_radio.c @@ -824,7 +824,8 @@ static const radio_driver_t* radio_drivers[]={ * Stream initialization * \return STREAM_OK if success, STREAM_ERROR otherwise */ -static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { +static int open_s(stream_t *stream,int mode, void* opts) +{ radio_priv_t* priv; float frequency=0; int i; @@ -875,7 +876,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { stream->type = STREAMTYPE_RADIO; /* using rawaudio demuxer */ - *file_format = DEMUXER_TYPE_RAWAUDIO; + stream->demuxer = "lavf"; stream->flags = STREAM_READ; priv->radio_fd=-1; diff --git a/stream/stream_smb.c b/stream/stream_smb.c index 33b13f7a11..b1ebaecd00 100644 --- a/stream/stream_smb.c +++ b/stream/stream_smb.c @@ -115,7 +115,8 @@ static void close_f(stream_t *s){ smbc_close(s->fd); } -static int open_f (stream_t *stream, int mode, void *opts, int* file_format) { +static int open_f (stream_t *stream, int mode, void *opts) +{ char *filename; mode_t m = 0; int64_t len; diff --git a/stream/stream_tv.c b/stream/stream_tv.c index 595657dc43..eacdabd705 100644 --- a/stream/stream_tv.c +++ b/stream/stream_tv.c @@ -97,13 +97,13 @@ tv_stream_close (stream_t *stream) stream->priv=NULL; } static int -tv_stream_open (stream_t *stream, int mode, void *opts, int *file_format) +tv_stream_open (stream_t *stream, int mode, void *opts) { stream->type = STREAMTYPE_TV; stream->priv = opts; stream->close=tv_stream_close; - *file_format = DEMUXER_TYPE_TV; + stream->demuxer = "tv"; return STREAM_OK; } diff --git a/stream/stream_vcd.c b/stream/stream_vcd.c index a459d6c880..fbbae12266 100644 --- a/stream/stream_vcd.c +++ b/stream/stream_vcd.c @@ -133,7 +133,8 @@ static void close_s(stream_t *stream) { free(stream->priv); } -static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { +static int open_s(stream_t *stream,int mode, void* opts) +{ struct stream_priv_s* p = opts; int ret,ret2,f,sect,tmp; mp_vcd_priv_t* vcd; @@ -232,7 +233,7 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { stream->seek = seek; stream->control = control; stream->close = close_s; - *file_format = DEMUXER_TYPE_LAVF; // mpegps + stream->demuxer = "lavf"; // mpegps ( or "vcd"?) m_struct_free(&stream_opts,opts); return STREAM_OK; diff --git a/video/out/gl_lcms.c b/video/out/gl_lcms.c index 69f7c7fa12..f7e418f1d1 100644 --- a/video/out/gl_lcms.c +++ b/video/out/gl_lcms.c @@ -85,7 +85,7 @@ static void lcms2_error_handler(cmsContext ctx, cmsUInt32Number code, static struct bstr load_file(void *talloc_ctx, const char *filename) { struct bstr res = {0}; - stream_t *s = open_stream(filename, NULL, NULL); + stream_t *s = stream_open(filename, NULL); if (s) { res = stream_read_complete(s, talloc_ctx, 1000000000); free_stream(s); -- cgit v1.2.3 From 3269bd178020c5d821e8b2d1fd807a38d63e93ce Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Jul 2013 21:58:11 +0200 Subject: demux: rewrite probing and demuxer initialization Get rid of the strange and messy reliance on DEMUXER_TYPE_ constants. Instead of having two open functions for the demuxer callbacks (which somehow are both optional, but you can also decide to implement both...), just have one function. This function takes a parameter that tells the demuxer how strictly it should check for the file headers. This is a nice simplification and allows more flexibility. Remove the file extension code. This literally did nothing (anymore). Change demux_lavf so that we check our other builtin demuxers first before libavformat tries to guess by file extension. --- DOCS/man/en/options.rst | 6 -- Makefile | 1 - core/mplayer.c | 6 +- core/options.c | 2 - core/options.h | 1 - core/timeline/tl_matroska.c | 2 +- demux/demux.c | 220 ++++++++++++++------------------------------ demux/demux.h | 50 ++++------ demux/demux_cue.c | 23 +++-- demux/demux_edl.c | 23 ++--- demux/demux_lavf.c | 18 ++-- demux/demux_libass.c | 61 ++++++------ demux/demux_mf.c | 77 +++++++--------- demux/demux_mkv.c | 5 +- demux/demux_mng.c | 31 +++---- demux/demux_rawaudio.c | 7 +- demux/demux_rawvideo.c | 7 +- demux/demux_subreader.c | 9 +- demux/extension.c | 101 -------------------- stream/stream_dvb.c | 3 +- stream/stream_mf.c | 2 +- stream/tv.c | 5 +- 22 files changed, 223 insertions(+), 437 deletions(-) delete mode 100644 demux/extension.c (limited to 'demux/demux.c') diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index d891766f6b..a6e5fee7ed 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -690,12 +690,6 @@ Stop at given absolute time. Use ``--length`` if the time should be relative to ``--start``. See ``--start`` for valid option values and examples. -``--no-extbased``, ``--extbased`` - ``--no-extbased`` disables extension-based demuxer selection. By default, - when the file type (demuxer) cannot be detected reliably (the file has no - header or it is not reliable enough), the filename extension is used to - select the demuxer. Always falls back on content-based demuxer selection. - ``--field-dominance=`` Set first field for interlaced content. Useful for deinterlacers that double the framerate: ``--vf=yadif=1`` and ``--vo=vdpau:deint``. diff --git a/Makefile b/Makefile index 3e0af2d55e..a1de600dcc 100644 --- a/Makefile +++ b/Makefile @@ -196,7 +196,6 @@ SOURCES = talloc.c \ demux/demux_rawaudio.c \ demux/demux_rawvideo.c \ demux/ebml.c \ - demux/extension.c \ demux/mf.c \ osdep/io.c \ osdep/numcores.c \ diff --git a/core/mplayer.c b/core/mplayer.c index ecaa9dd10b..de6b4132fd 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2297,9 +2297,9 @@ int reinit_video_chain(struct MPContext *mpctx) goto no_video; } - mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X " + mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] fourcc:0x%X " "size:%dx%d fps:%5.3f\n", - mpctx->master_demuxer->file_format, mpctx->sh_video->format, + mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, mpctx->sh_video->fps); if (opts->force_fps) @@ -2459,7 +2459,7 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) double d = next_pts == MP_NOPTS_VALUE ? sh_video->last_pts - pts1 : next_pts - sh_video->last_pts; if (d >= 0) { - if (demuxer->file_format == DEMUXER_TYPE_TV) { + if (demuxer->type == DEMUXER_TYPE_TV) { if (d > 0) sh_video->fps = 1.0f / d; frame_time = d; diff --git a/core/options.c b/core/options.c index d676cb4948..2298d112b8 100644 --- a/core/options.c +++ b/core/options.c @@ -399,7 +399,6 @@ const m_option_t mp_opts[] = { OPT_STRING("demuxer", demuxer_name, 0), OPT_STRING("audio-demuxer", audio_demuxer_name, 0), OPT_STRING("sub-demuxer", sub_demuxer_name, 0), - OPT_FLAG("extbased", extension_parsing, 0), {"mf", (void *) mfopts_conf, CONF_TYPE_SUBCONFIG, 0,0,0, NULL}, #ifdef CONFIG_RADIO @@ -777,7 +776,6 @@ const struct MPOpts mp_default_opts = { .sub_visibility = 1, .sub_pos = 100, .sub_speed = 1.0, - .extension_parsing = 1, .audio_output_channels = MP_CHMAP_INIT_STEREO, .audio_output_format = -1, // AF_FORMAT_UNKNOWN .playback_speed = 1., diff --git a/core/options.h b/core/options.h index d46435bf9e..345835656b 100644 --- a/core/options.h +++ b/core/options.h @@ -152,7 +152,6 @@ typedef struct MPOpts { char *demuxer_name; char *audio_demuxer_name; char *sub_demuxer_name; - int extension_parsing; int mkv_subtitle_preroll; struct image_writer_opts *screenshot_image_opts; diff --git a/core/timeline/tl_matroska.c b/core/timeline/tl_matroska.c index 614ce0d6b7..f01160b60e 100644 --- a/core/timeline/tl_matroska.c +++ b/core/timeline/tl_matroska.c @@ -168,7 +168,7 @@ static bool check_file_seg(struct MPContext *mpctx, struct demuxer **sources, free_stream(s); return was_valid; } - if (d->file_format == DEMUXER_TYPE_MATROSKA) { + if (d->type == DEMUXER_TYPE_MATROSKA) { for (int i = 1; i < num_sources; i++) { if (sources[i]) continue; diff --git a/demux/demux.c b/demux/demux.c index 5a0e05d48f..61e0f2e9ef 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -224,46 +224,6 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) return new; } -/** - * Get demuxer description structure for a given demuxer type - * - * @param file_format type of the demuxer - * @return structure for the demuxer, NULL if not found - */ -static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format) -{ - int i; - - for (i = 0; demuxer_list[i]; i++) - if (file_format == demuxer_list[i]->type) - return demuxer_list[i]; - - return NULL; -} - - -static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type) -{ - struct demuxer *d = talloc_zero(NULL, struct demuxer); - d->stream = stream; - d->stream_pts = MP_NOPTS_VALUE; - d->movi_start = stream->start_pos; - d->movi_end = stream->end_pos; - d->seekable = 1; - d->filepos = -1; - d->type = type; - d->opts = opts; - if (type) - if (!(d->desc = get_demuxer_desc_from_type(type))) - mp_msg(MSGT_DEMUXER, MSGL_ERR, - "BUG! Invalid demuxer type in new_demuxer(), " - "big troubles ahead.\n"); - if (stream->url) - d->filename = strdup(stream->url); - stream_seek(stream, stream->start_pos); - return d; -} - struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) { if (demuxer->num_streams > MAX_SH_STREAMS) { @@ -356,7 +316,6 @@ void free_demuxer(demuxer_t *demuxer) // free streams: for (int n = 0; n < demuxer->num_streams; n++) free_sh_stream(demuxer->streams[n]); - free(demuxer->filename); talloc_free(demuxer); } @@ -546,8 +505,6 @@ void demuxer_help(void) mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer: info: (comment)\n"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXERS\n"); for (i = 0; demuxer_list[i]; i++) { - if (demuxer_list[i]->type >= DEMUXER_TYPE_END) // internal type - continue; if (demuxer_list[i]->comment && strlen(demuxer_list[i]->comment)) mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s (%s)\n", demuxer_list[i]->name, demuxer_list[i]->info, @@ -558,66 +515,51 @@ void demuxer_help(void) } } - -/** - * Get demuxer type for a given demuxer name - * - * @param demuxer_name string with demuxer name of demuxer number - * @param force will be set if demuxer should be forced. - * May be NULL. - * @return DEMUXER_TYPE_xxx, -1 if error or not found - */ -static int get_demuxer_type_from_name(char *demuxer_name, int *force) -{ - if (!demuxer_name || !demuxer_name[0]) - return DEMUXER_TYPE_UNKNOWN; - if (force) - *force = demuxer_name[0] == '+'; - if (demuxer_name[0] == '+') - demuxer_name = &demuxer_name[1]; - for (int i = 0; demuxer_list[i]; i++) { - if (demuxer_list[i]->type >= DEMUXER_TYPE_END) - // Can't select special demuxers from commandline - continue; - if (strcmp(demuxer_name, demuxer_list[i]->name) == 0) - return demuxer_list[i]->type; +static const char *d_level(enum demux_check level) +{ + switch (level) { + case DEMUX_CHECK_FORCE: return "force"; + case DEMUX_CHECK_UNSAFE: return "unsafe"; + case DEMUX_CHECK_REQUEST:return "request"; + case DEMUX_CHECK_NORMAL: return "normal"; } - - return -1; + abort(); } static struct demuxer *open_given_type(struct MPOpts *opts, const struct demuxer_desc *desc, - struct stream *stream, bool force, - struct demuxer_params *params) -{ - struct demuxer *demuxer; - int fformat = desc->type; - mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s\n", desc->name); - demuxer = new_demuxer(opts, stream, desc->type); - demuxer->params = params; - if (!force) { - if (desc->check_file) - fformat = desc->check_file(demuxer) >= 0 ? fformat : 0; - } - if (fformat == 0) - goto fail; - if (fformat == desc->type) { + struct stream *stream, + struct demuxer_params *params, + enum demux_check check) +{ + struct demuxer *demuxer = talloc_ptrtype(NULL, demuxer); + *demuxer = (struct demuxer) { + .desc = desc, + .type = desc->type, + .stream = stream, + .stream_pts = MP_NOPTS_VALUE, + .movi_start = stream->start_pos, + .movi_end = stream->end_pos, + .seekable = 1, + .filepos = -1, + .opts = opts, + .filename = talloc_strdup(demuxer, stream->url), + }; + demuxer->params = params; // temporary during open() + stream_seek(stream, stream->start_pos); + + mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s (force-level: %s)\n", + desc->name, d_level(check)); + + int ret = demuxer->desc->open(demuxer, check); + if (ret >= 0) { + demuxer->params = NULL; if (demuxer->filetype) mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s (%s)\n", demuxer->filetype, desc->shortdesc); else mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n", desc->shortdesc); - if (demuxer->desc->open) { - int ret = demuxer->desc->open(demuxer); - if (ret < 0) { - mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Opening as detected format " - "\"%s\" failed.\n", desc->shortdesc); - goto fail; - } - } - demuxer->file_format = fformat; if (stream_manages_timeline(demuxer->stream)) { // Incorrect, but fixes some behavior with DVD/BD demuxer->ts_resets_possible = false; @@ -628,81 +570,55 @@ static struct demuxer *open_given_type(struct MPOpts *opts, demuxer_sort_chapters(demuxer); demux_info_update(demuxer); return demuxer; - } else { - // demux_mov can return playlist instead of mov - if (fformat == DEMUXER_TYPE_PLAYLIST) - return demuxer; // handled in mplayer.c - /* Internal MPEG PS demuxer check can return other MPEG subtypes - * which don't have their own checks; recurse to try opening as - * the returned type instead. */ - free_demuxer(demuxer); - desc = get_demuxer_desc_from_type(fformat); - if (!desc) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, - "BUG: recursion to nonexistent file format\n"); - return NULL; - } - return open_given_type(opts, desc, stream, false, params); } - fail: + free_demuxer(demuxer); return NULL; } +static const int d_normal[] = {DEMUX_CHECK_NORMAL, DEMUX_CHECK_UNSAFE, -1}; +static const int d_request[] = {DEMUX_CHECK_REQUEST, -1}; +static const int d_force[] = {DEMUX_CHECK_FORCE, -1}; + struct demuxer *demux_open(struct stream *stream, char *force_format, struct demuxer_params *params, struct MPOpts *opts) { - struct demuxer *demuxer = NULL; - const struct demuxer_desc *desc; + const int *check_levels = d_normal; + const struct demuxer_desc *check_desc = NULL; + if (!force_format) force_format = opts->demuxer_name; + if (!force_format) + force_format = stream->demuxer; - int force = 0; - int demuxer_type; - if ((demuxer_type = get_demuxer_type_from_name(force_format, &force)) < 0) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, "Demuxer %s does not exist.\n", - force_format); - return NULL; - } - int file_format = 0; - if (demuxer_type) - file_format = demuxer_type; - - // 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 + if (force_format && force_format[0]) { + check_levels = d_request; + if (force_format[0] == '+') { + force_format += 1; + check_levels = d_force; + } + for (int n = 0; demuxer_list[n]; n++) { + if (strcmp(demuxer_list[n]->name, force_format) == 0) + check_desc = demuxer_list[n]; + } + if (!check_desc) { + mp_msg(MSGT_DEMUXER, MSGL_ERR, "Demuxer %s does not exist.\n", + force_format); return NULL; - return open_given_type(opts, desc, stream, force, 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, params); - if (demuxer) - return demuxer; } } - // Ok. We're over the stable detectable fileformats, the next ones are - // a bit fuzzy. So by default (extension_parsing==1) try extension-based - // detection first: - if (stream->url && opts->extension_parsing == 1) { - desc = get_demuxer_desc_from_type(demuxer_type_by_filename(stream->url)); - if (desc) - demuxer = open_given_type(opts, desc, stream, false, params); - if (demuxer) - return demuxer; - } - - // 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, params); - if (demuxer) - return demuxer; + // Test demuxers from first to last, one pass for each check_levels[] entry + for (int pass = 0; check_levels[pass] != -1; pass++) { + enum demux_check level = check_levels[pass]; + for (int n = 0; demuxer_list[n]; n++) { + const struct demuxer_desc *desc = demuxer_list[n]; + if (!check_desc || desc == check_desc) { + struct demuxer *demuxer = open_given_type(opts, desc, stream, + params, level); + if (demuxer) + return demuxer; + } } } diff --git a/demux/demux.h b/demux/demux.h index f64a02dce1..34ff9fd596 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -36,24 +36,11 @@ struct MPOpts; #define MAX_PACK_BYTES 0x8000000 // 128 MiB enum demuxer_type { - DEMUXER_TYPE_UNKNOWN = 0, + DEMUXER_TYPE_GENERIC = 0, DEMUXER_TYPE_TV, - DEMUXER_TYPE_MF, - DEMUXER_TYPE_RAWAUDIO, - DEMUXER_TYPE_RAWVIDEO, DEMUXER_TYPE_MATROSKA, - DEMUXER_TYPE_LAVF, - 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). */ - DEMUXER_TYPE_END, - - DEMUXER_TYPE_PLAYLIST, }; enum timestamp_type { @@ -84,6 +71,22 @@ enum timestamp_type { #define SEEK_BACKWARD (1 << 3) #define SEEK_SUBPREROLL (1 << 4) +// Strictness of the demuxer open format check. +// demux.c will try by default: NORMAL, UNSAFE (in this order) +// Using "-demuxer format" will try REQUEST +// Using "-demuxer +format" will try FORCE +// REQUEST can be used as special value for raw demuxers which have no file +// header check; then they should fail if check!=FORCE && check!=REQUEST. +// +// In general, the list is sorted from weakest check to normal check. +// You can use relation operators to compare the check level. +enum demux_check { + DEMUX_CHECK_FORCE, // force format if possible + DEMUX_CHECK_UNSAFE, // risky/fuzzy detection + DEMUX_CHECK_REQUEST,// requested by user or stream implementation + DEMUX_CHECK_NORMAL, // normal, safe detection +}; + // demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead #define MP_INPUT_BUFFER_PADDING_SIZE 16 @@ -101,14 +104,10 @@ typedef struct demuxer_desc { const char *author; // Demuxer author(s) const char *comment; // Comment, printed with -demuxer help - enum demuxer_type type; - // If 1 detection is safe and fast, do it before file extension check - int safe_check; + enum demuxer_type type; // optional // Return 0 on success, otherwise -1 - int (*check_file)(struct demuxer *demuxer); - // Open the demuxer, return 0 on success, otherwise -1 - int (*open)(struct demuxer *demuxer); + int (*open)(struct demuxer *demuxer, enum demux_check check); // The following functions are all optional int (*fill_buffer)(struct demuxer *demuxer); // 0 on EOF, otherwise 1 void (*close)(struct demuxer *demuxer); @@ -160,15 +159,8 @@ typedef struct demuxer { int64_t movi_end; struct stream *stream; double stream_pts; // current stream pts, if applicable (e.g. dvd) - char *filename; // Needed by avs_check_file + char *filename; // same as stream->url enum demuxer_type type; - /* Normally the file_format field is just a copy of the type field above. - * There are 2 exceptions I noticed. Internal demux_avi may force - * ->type to DEMUXER_TYPE_AVI_[NI|NINI] while leaving ->file_format at - * DEMUXER_TYPE_AVI. Internal demux_mov may set ->type to - * DEMUXER_TYPE_PLAYLIST and also return that from the check function - * or not (looks potentially buggy). */ - enum demuxer_type file_format; int seekable; // flag /* Set if using absolute seeks for small movements is OK (no pts resets * that would make pts ambigious, preferably supports back/forward flags */ @@ -252,8 +244,6 @@ void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, bool selected); void demuxer_enable_autoselect(struct demuxer *demuxer); -int demuxer_type_by_filename(char *filename); - void demuxer_help(void); int demuxer_add_attachment(struct demuxer *demuxer, struct bstr name, diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 43ef910868..db2f40ea57 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -29,21 +29,21 @@ bool mp_probe_cue(struct bstr s); #define PROBE_SIZE 512 -static int try_open_file(struct demuxer *demuxer) +static int try_open_file(struct demuxer *demuxer, enum demux_check check) { struct stream *s = demuxer->stream; - char buf[PROBE_SIZE]; - int len = stream_read(s, buf, sizeof(buf)); - if (len <= 0) - return -1; - if (!mp_probe_cue((struct bstr) { buf, len })) - return -1; - stream_seek(s, 0); + if (check >= DEMUX_CHECK_UNSAFE) { + char buf[PROBE_SIZE]; + int len = stream_read(s, buf, sizeof(buf)); + if (len <= 0) + return -1; + if (!mp_probe_cue((struct bstr) { buf, len })) + return -1; + stream_seek(s, 0); + } demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return -1; - if (!mp_probe_cue((struct bstr) { buf, len })) - return -1; return 0; } @@ -54,6 +54,5 @@ const struct demuxer_desc demuxer_desc_cue = { .author = "Uoti Urpala", .comment = "", .type = DEMUXER_TYPE_CUE, - .safe_check = true, - .check_file = try_open_file, // no separate .open + .open = try_open_file, }; diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 44fa824193..0f4bf06dbf 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -23,17 +23,19 @@ #include "demux.h" #include "stream/stream.h" -static int try_open_file(struct demuxer *demuxer) +static int try_open_file(struct demuxer *demuxer, enum demux_check check) { struct stream *s = demuxer->stream; - const char header[] = "mplayer EDL file"; - const int len = sizeof(header) - 1; - char buf[len]; - if (stream_read(s, buf, len) < len) - return -1; - if (strncmp(buf, header, len)) - return -1; - stream_seek(s, 0); + if (check >= DEMUX_CHECK_UNSAFE) { + const char header[] = "mplayer EDL file"; + const int len = sizeof(header) - 1; + char buf[len]; + if (stream_read(s, buf, len) < len) + return -1; + if (strncmp(buf, header, len)) + return -1; + stream_seek(s, 0); + } demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return -1; @@ -47,6 +49,5 @@ const struct demuxer_desc demuxer_desc_edl = { .author = "Uoti Urpala", .comment = "", .type = DEMUXER_TYPE_EDL, - .safe_check = true, - .check_file = try_open_file, // no separate .open + .open = try_open_file, }; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 0e7690f606..88587f8ce0 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -185,7 +185,7 @@ static char *remove_prefix(char *s, const char **prefixes) static const char *prefixes[] = {"ffmpeg://", "lavf://", "avdevice://", "av://", NULL}; -static int lavf_check_file(demuxer_t *demuxer) +static int lavf_check_file(demuxer_t *demuxer, enum demux_check check) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; @@ -258,7 +258,8 @@ static int lavf_check_file(demuxer_t *demuxer) min_probe = lavfdopts->probescore; AVProbeData avpd = { - .filename = priv->filename, + // Disable file-extension matching with normal checks + .filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : NULL, .buf_size = 0, .buf = av_mallocz(PROBE_BUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE), }; @@ -493,18 +494,20 @@ static void add_metadata(demuxer_t *demuxer, AVDictionary *metadata) demux_info_add(demuxer, t->key, t->value); } -static int demux_open_lavf(demuxer_t *demuxer) +static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; AVFormatContext *avfc; AVDictionaryEntry *t = NULL; - lavf_priv_t *priv = demuxer->priv; float analyze_duration = 0; int i; - // do not allow forcing the demuxer - if (!priv->avif) + if (lavf_check_file(demuxer, check) < 0) + return -1; + + lavf_priv_t *priv = demuxer->priv; + if (!priv) return -1; stream_seek(demuxer->stream, 0); @@ -904,9 +907,6 @@ const demuxer_desc_t demuxer_desc_lavf = { .shortdesc = "libavformat", .author = "Michael Niedermayer", .comment = "supports many formats, requires libavformat", - .type = DEMUXER_TYPE_LAVF, - .safe_check = 1, - .check_file = lavf_check_file, .fill_buffer = demux_lavf_fill_buffer, .open = demux_open_lavf, .close = demux_close_lavf, diff --git a/demux/demux_libass.c b/demux/demux_libass.c index 4dadb42b89..24e1b9e114 100644 --- a/demux/demux_libass.c +++ b/demux/demux_libass.c @@ -33,7 +33,7 @@ struct priv { ASS_Track *track; }; -static int d_check_file(struct demuxer *demuxer) +static int d_check_file(struct demuxer *demuxer, enum demux_check check) { const char *user_cp = demuxer->opts->sub_cp; struct stream *s = demuxer->stream; @@ -43,42 +43,45 @@ static int d_check_file(struct demuxer *demuxer) if (!lib) return -1; - // Probe by loading a part of the beginning of the file with libass. - // Incomplete scripts are usually ok, and we hope libass is not verbose - // when dealing with (from its perspective) completely broken binary - // garbage. - - bstr buf = stream_peek(s, PROBE_SIZE); - // Older versions of libass will overwrite the input buffer, and despite - // passing length, expect a 0 termination. - void *tmp = talloc_size(NULL, buf.len + 1); - memcpy(tmp, buf.start, buf.len); - buf.start = tmp; - buf.start[buf.len] = '\0'; - bstr cbuf = - mp_charset_guess_and_conv_to_utf8(buf, user_cp, MP_ICONV_ALLOW_CUTOFF); - if (cbuf.start == NULL) - cbuf = buf; - ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); - if (cbuf.start != buf.start) - talloc_free(cbuf.start); - talloc_free(buf.start); - if (!track) - return -1; - ass_free_track(track); + if (check >= DEMUX_CHECK_UNSAFE) { + // Probe by loading a part of the beginning of the file with libass. + // Incomplete scripts are usually ok, and we hope libass is not verbose + // when dealing with (from its perspective) completely broken binary + // garbage. + + bstr buf = stream_peek(s, PROBE_SIZE); + // Older versions of libass will overwrite the input buffer, and despite + // passing length, expect a 0 termination. + void *tmp = talloc_size(NULL, buf.len + 1); + memcpy(tmp, buf.start, buf.len); + buf.start = tmp; + buf.start[buf.len] = '\0'; + bstr cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, + MP_ICONV_ALLOW_CUTOFF); + if (cbuf.start == NULL) + cbuf = buf; + ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); + if (cbuf.start != buf.start) + talloc_free(cbuf.start); + talloc_free(buf.start); + if (!track) + return -1; + ass_free_track(track); + } // Actually load the full thing. - buf = stream_read_complete(s, NULL, 100000000); + bstr buf = stream_read_complete(s, NULL, 100000000); if (!buf.start) { mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " "larger than 100 MB: %s\n", demuxer->filename); return -1; } - cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, MP_ICONV_VERBOSE); + bstr cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, + MP_ICONV_VERBOSE); if (cbuf.start == NULL) cbuf = buf; - track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); + ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); if (cbuf.start != buf.start) talloc_free(cbuf.start); talloc_free(buf.start); @@ -114,8 +117,6 @@ const struct demuxer_desc demuxer_desc_libass = { .shortdesc = "ASS/SSA subtitles (libass)", .author = "", .comment = "", - .safe_check = 1, - .type = DEMUXER_TYPE_LIBASS, - .check_file = d_check_file, + .open = d_check_file, .close = d_close, }; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 5e3469a0f1..33747f12d7 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -149,9 +149,9 @@ static const struct { {0} }; -static const char *probe_format(mf_t *mf) +static const char *probe_format(mf_t *mf, enum demux_check check) { - if (mf->nr_of_files < 1) + if (check > DEMUX_CHECK_REQUEST) return NULL; char *type = mf_type; if (!type || !type[0]) { @@ -159,47 +159,42 @@ static const char *probe_format(mf_t *mf) if (p) type = p + 1; } - if (!type || !type[0]) - return NULL; - int i; - for (i = 0; type2format[i].type; i++) { - if (strcasecmp(type, type2format[i].type) == 0) - break; + for (int i = 0; type2format[i].type; i++) { + if (type && strcasecmp(type, type2format[i].type) == 0) + return type2format[i].codec; } - return type2format[i].codec; -} - -static mf_t *open_mf(demuxer_t *demuxer) -{ - if (!demuxer->stream->url) - return NULL; - - if (strncmp(demuxer->stream->url, "mf://", 5) == 0) { - return open_mf_pattern(demuxer->stream->url + 5); - } else { - mf_t *mf = open_mf_single(demuxer->stream->url); - mf->streams = calloc(1, sizeof(struct stream *)); - mf->streams[0] = demuxer->stream; - return mf; + if (check == DEMUX_CHECK_REQUEST) { + if (!mf_type) { + mp_msg(MSGT_DEMUX, MSGL_ERR, + "[demux_mf] file type was not set! (try --mf-type=ext)\n"); + } else { + mp_msg(MSGT_DEMUX, MSGL_ERR, + "[demux_mf] --mf-type set to an unknown codec!\n"); + } } + return NULL; } -static int demux_check_file(demuxer_t *demuxer) -{ - if (demuxer->stream->type == STREAMTYPE_MF) - return 0; - mf_t *mf = open_mf(demuxer); - bool ok = mf && probe_format(mf); - free_mf(mf); - return ok ? 0 : -1; -} - -static int demux_open_mf(demuxer_t* demuxer) +static int demux_open_mf(demuxer_t* demuxer, enum demux_check check) { sh_video_t *sh_video = NULL; + mf_t *mf; + + if (strncmp(demuxer->stream->url, "mf://", 5) == 0 && + demuxer->stream->type == STREAMTYPE_MF) + { + mf = open_mf_pattern(demuxer->stream->url + 5); + } else { + mf = open_mf_single(demuxer->stream->url); + mf->streams = calloc(1, sizeof(struct stream *)); + mf->streams[0] = demuxer->stream; + } + + if (!mf || mf->nr_of_files < 1) + goto error; - mf_t *mf = open_mf(demuxer); - if (!mf) + const char *codec = probe_format(mf, check); + if (!codec) goto error; mf->curr_frame = 0; @@ -211,12 +206,7 @@ static int demux_open_mf(demuxer_t* demuxer) struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh->video; - sh_video->gsh->codec = probe_format(mf); - if (!sh_video->gsh->codec) { - mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! (try -mf type=ext)\n" ); - goto error; - } - + sh_video->gsh->codec = codec; sh_video->disp_w = 0; sh_video->disp_h = 0; sh_video->fps = mf_fps; @@ -259,9 +249,6 @@ const demuxer_desc_t demuxer_desc_mf = { .shortdesc = "MF", .author = "?", .comment = "multiframe?, pictures demuxer", - .type = DEMUXER_TYPE_MF, - .safe_check = 1, - .check_file = demux_check_file, .fill_buffer = demux_mf_fill_buffer, .open = demux_open_mf, .close = demux_close_mf, diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index a60172cce9..efc4c8f989 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1751,7 +1751,7 @@ static int read_mkv_segment_header(demuxer_t *demuxer) return 0; } -static int demux_mkv_open(demuxer_t *demuxer) +static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) { stream_t *s = demuxer->stream; mkv_demuxer_t *mkv_d; @@ -2724,8 +2724,7 @@ const demuxer_desc_t demuxer_desc_matroska = { .author = "Aurelien Jacobs", .comment = "", .type = DEMUXER_TYPE_MATROSKA, - .safe_check = 1, // safe autodetect - .check_file = demux_mkv_open, + .open = demux_mkv_open, .fill_buffer = demux_mkv_fill_buffer, .close = mkv_free, .seek = demux_mkv_seek, diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 824a668868..6c5bbc2e45 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -254,21 +254,6 @@ static mng_bool demux_mng_settimer(mng_handle h_mng, mng_uint32 msecs) return MNG_TRUE; } -/** - * \brief MPlayer callback: Check if stream contains MNG data. - * \param[in] demuxer demuxer structure - * \return demuxer type constant, \p 0 if unknown - */ -static int demux_mng_check_file(demuxer_t *demuxer) -{ - char buf[4]; - if (stream_read(demuxer->stream, buf, 4) != 4) - return -1; - if (memcmp(buf, "\x8AMNG", 4)) - return -1; - return 0; -} - /** * \brief MPlayer callback: Fill buffer from MNG stream. * \param[in] demuxer demuxer structure @@ -343,13 +328,24 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer) return 1; } -static int demux_mng_open(demuxer_t * demuxer) +static int demux_mng_open(demuxer_t * demuxer, enum demux_check check) { mng_priv_t * mng_priv; mng_handle h_mng; mng_retcode mng_ret; sh_video_t * sh_video; + if (check > DEMUX_CHECK_REQUEST) + return -1; // check too unsafe + if (check > DEMUX_CHECK_FORCE) { + char buf[4]; + if (stream_read(demuxer->stream, buf, 4) != 4) + return -1; + if (memcmp(buf, "\x8AMNG", 4)) + return -1; + stream_seek(demuxer->stream, demuxer->stream->start_pos); + } + // create private data structure mng_priv = calloc(1, sizeof(mng_priv_t)); @@ -569,9 +565,6 @@ const demuxer_desc_t demuxer_desc_mng = { .shortdesc = "MNG", .author = "Stefan Schuermans ", .comment = "MNG files, using libmng", - .type = DEMUXER_TYPE_MNG, - .safe_check = 0, // unsafe autodetect (only checking magic at beginning of stream) - .check_file = demux_mng_check_file, .fill_buffer = demux_mng_fill_buffer, .open = demux_mng_open, .close = demux_mng_close, diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 13bbbb341a..83a89e7c1c 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -43,11 +43,15 @@ const m_option_t demux_rawaudio_opts[] = { }; -static int demux_rawaudio_open(demuxer_t* demuxer) { +static int demux_rawaudio_open(demuxer_t* demuxer, enum demux_check check) +{ struct sh_stream *sh; sh_audio_t* sh_audio; WAVEFORMATEX* w; + if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) + return -1; + if ((format & AF_FORMAT_SPECIAL_MASK) != 0) return -1; @@ -115,7 +119,6 @@ const demuxer_desc_t demuxer_desc_rawaudio = { .shortdesc = "rawaudio", .author = "?", .comment = "", - .type = DEMUXER_TYPE_RAWAUDIO, .fill_buffer = demux_rawaudio_fill_buffer, .open = demux_rawaudio_open, .seek = demux_rawaudio_seek, diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 488c13bdec..9f670f2879 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -56,10 +56,14 @@ const m_option_t demux_rawvideo_opts[] = { }; -static int demux_rawvideo_open(demuxer_t* demuxer) { +static int demux_rawvideo_open(demuxer_t* demuxer, enum demux_check check) +{ struct sh_stream *sh; sh_video_t* sh_video; + if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) + return -1; + if(!width || !height){ mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: width or height not specified!\n"); return -1; @@ -171,7 +175,6 @@ const demuxer_desc_t demuxer_desc_rawvideo = { .shortdesc = "rawvideo", .author = "?", .comment = "", - .type = DEMUXER_TYPE_RAWVIDEO, .fill_buffer = demux_rawvideo_fill_buffer, .open = demux_rawvideo_open, .seek = demux_rawvideo_seek, diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index 7758aa968c..24604978d5 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1326,8 +1326,11 @@ static struct stream *read_probe_stream(struct stream *s, int max) #define PROBE_SIZE FFMIN(32 * 1024, STREAM_MAX_BUFFER_SIZE) -static int d_check_file(struct demuxer *demuxer) +static int d_open_file(struct demuxer *demuxer, enum demux_check check) { + if (check > DEMUX_CHECK_REQUEST) + return -1; + struct stream *ps = read_probe_stream(demuxer->stream, PROBE_SIZE); struct subreader sr; @@ -1393,9 +1396,7 @@ const struct demuxer_desc demuxer_desc_subreader = { .shortdesc = "Deprecated Subreader", .author = "", .comment = "", - .type = DEMUXER_TYPE_SUBREADER, - .safe_check = 1, - .check_file = d_check_file, + .open = d_open_file, .fill_buffer = d_fill_buffer, .seek = d_seek, .control = d_control, diff --git a/demux/extension.c b/demux/extension.c deleted file mode 100644 index 30cb592b9f..0000000000 --- a/demux/extension.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include - -#include "config.h" - -#include "stream/stream.h" -#include "demux.h" - -/* - * An autodetection based on the extension is not a good idea, but we don't care ;-) - * - * You should not add anything here where autodetection can be easily fixed except in - * order to speed up auto-detection, in particular for formats that are often streamed. - * In particular you should not normally add any DEMUXER_TYPE_LAVF, adding the - * format to preferred_list in demux/demuxer_lavf.c will usually achieve - * the same effect in a much more reliable way. - */ -static struct { - const char *extension; - int demuxer_type; -} extensions_table[] = { - { "vob", DEMUXER_TYPE_LAVF }, - { "m2v", DEMUXER_TYPE_LAVF }, - { "avi", DEMUXER_TYPE_LAVF }, - { "asx", DEMUXER_TYPE_LAVF }, - { "asf", DEMUXER_TYPE_LAVF }, - { "wmv", DEMUXER_TYPE_LAVF }, - { "wma", DEMUXER_TYPE_LAVF }, - { "rm", DEMUXER_TYPE_LAVF }, - { "rmvb", DEMUXER_TYPE_LAVF }, - { "ra", DEMUXER_TYPE_LAVF }, - { "y4m", DEMUXER_TYPE_LAVF }, - { "mp3", DEMUXER_TYPE_LAVF }, - { "wav", DEMUXER_TYPE_LAVF }, - { "flac", DEMUXER_TYPE_LAVF }, - { "fla", DEMUXER_TYPE_LAVF }, - { "ogg", DEMUXER_TYPE_LAVF }, - { "ogm", DEMUXER_TYPE_LAVF }, -// { "pls", DEMUXER_TYPE_PLAYLIST }, -// { "m3u", DEMUXER_TYPE_PLAYLIST }, - { "xm", DEMUXER_TYPE_LAVF }, - { "mod", DEMUXER_TYPE_LAVF }, - { "s3m", DEMUXER_TYPE_LAVF }, - { "it", DEMUXER_TYPE_LAVF }, - { "mid", DEMUXER_TYPE_LAVF }, - { "midi", DEMUXER_TYPE_LAVF }, - { "nsv", DEMUXER_TYPE_LAVF }, - { "nsa", DEMUXER_TYPE_LAVF }, - { "mpc", DEMUXER_TYPE_LAVF }, - { "302", DEMUXER_TYPE_LAVF }, - { "264", DEMUXER_TYPE_LAVF }, - { "26l", DEMUXER_TYPE_LAVF }, - { "ac3", DEMUXER_TYPE_LAVF }, - { "ape", DEMUXER_TYPE_LAVF }, - { "apl", DEMUXER_TYPE_LAVF }, - { "eac3",DEMUXER_TYPE_LAVF }, - { "mac", DEMUXER_TYPE_LAVF }, - { "str", DEMUXER_TYPE_LAVF }, - { "cdg", DEMUXER_TYPE_LAVF }, - -// At least the following are hacks against broken autodetection -// that should not be there - -}; - -int demuxer_type_by_filename(char* filename){ - int i; - char* extension=strrchr(filename,'.'); - mp_msg(MSGT_OPEN, MSGL_V, "Searching demuxer type for filename %s ext: %s\n",filename,extension); - if(extension) { - ++extension; -// mp_msg(MSGT_CPLAYER,MSGL_DBG2,"Extension: %s\n", extension ); - // Look for the extension in the extensions table - for( i=0 ; i<(sizeof(extensions_table)/sizeof(extensions_table[0])) ; i++ ) { - if( !strcasecmp(extension, extensions_table[i].extension) ) { - mp_msg(MSGT_OPEN, MSGL_V, "Trying demuxer %d based on filename extension\n",extensions_table[i].demuxer_type); - return extensions_table[i].demuxer_type; - } - } - } - return DEMUXER_TYPE_UNKNOWN; -} diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 8fabfb4fc1..3847e26c75 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -739,7 +739,8 @@ static int dvb_open(stream_t *stream, int mode, void *opts) stream->close = dvbin_close; m_struct_free(&stream_opts, opts); - stream->demuxer = "lavf:mpegts"; + stream->demuxer = "lavf"; + stream->lavf_type = "mpegts"; return STREAM_OK; } diff --git a/stream/stream_mf.c b/stream/stream_mf.c index eef5d6fc4d..9354005ae4 100644 --- a/stream/stream_mf.c +++ b/stream/stream_mf.c @@ -32,7 +32,7 @@ static int mf_stream_open (stream_t *stream, int mode, void *opts) { stream->type = STREAMTYPE_MF; - stream->demuxer = "lavf"; + stream->demuxer = "mf"; return STREAM_OK; } diff --git a/stream/tv.c b/stream/tv.c index aa5383402f..9ddf3771ed 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -701,13 +701,16 @@ static int tv_uninit(tvi_handle_t *tvh) return res; } -static int demux_open_tv(demuxer_t *demuxer) +static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) { tvi_handle_t *tvh; sh_video_t *sh_video; sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; + if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV) + return -1; + demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv))) return -1; if (!tvh->functions->init(tvh->priv)) return -1; -- cgit v1.2.3 From 6c414f8c7a66ce3bb0c2446cb7fb0fb802a9e98b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Jul 2013 22:12:02 +0200 Subject: demux: remove useless author/comment fields Same deal as with previous commit. --- demux/demux.c | 17 +++++------------ demux/demux.h | 5 +---- demux/demux_cue.c | 7 +++---- demux/demux_edl.c | 7 +++---- demux/demux_lavf.c | 5 +---- demux/demux_libass.c | 5 +---- demux/demux_mf.c | 5 +---- demux/demux_mkv.c | 5 +---- demux/demux_mng.c | 5 +---- demux/demux_rawaudio.c | 5 +---- demux/demux_rawvideo.c | 5 +---- demux/demux_subreader.c | 5 +---- stream/tv.c | 5 +---- 13 files changed, 21 insertions(+), 60 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 61e0f2e9ef..836c945bc4 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -309,8 +309,6 @@ static void free_sh_stream(struct sh_stream *sh) void free_demuxer(demuxer_t *demuxer) { - 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: @@ -502,16 +500,11 @@ void demuxer_help(void) int i; mp_msg(MSGT_DEMUXER, MSGL_INFO, "Available demuxers:\n"); - mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer: info: (comment)\n"); + mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer: info:\n"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXERS\n"); for (i = 0; demuxer_list[i]; i++) { - if (demuxer_list[i]->comment && strlen(demuxer_list[i]->comment)) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s (%s)\n", - demuxer_list[i]->name, demuxer_list[i]->info, - demuxer_list[i]->comment); - else - mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s\n", - demuxer_list[i]->name, demuxer_list[i]->info); + mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s\n", + demuxer_list[i]->name, demuxer_list[i]->desc); } } @@ -556,10 +549,10 @@ static struct demuxer *open_given_type(struct MPOpts *opts, demuxer->params = NULL; if (demuxer->filetype) mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s (%s)\n", - demuxer->filetype, desc->shortdesc); + demuxer->filetype, desc->desc); else mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n", - desc->shortdesc); + desc->desc); if (stream_manages_timeline(demuxer->stream)) { // Incorrect, but fixes some behavior with DVD/BD demuxer->ts_resets_possible = false; diff --git a/demux/demux.h b/demux/demux.h index 34ff9fd596..3f193fa72e 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -98,11 +98,8 @@ struct demuxer; * Demuxer description structure */ typedef struct demuxer_desc { - const char *info; // What is it (long name and/or description) const char *name; // Demuxer name, used with -demuxer switch - const char *shortdesc; // Description printed at demuxer detection - const char *author; // Demuxer author(s) - const char *comment; // Comment, printed with -demuxer help + const char *desc; // Displayed to user enum demuxer_type type; // optional diff --git a/demux/demux_cue.c b/demux/demux_cue.c index db2f40ea57..4d2c03dcce 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -1,6 +1,8 @@ /* * This file is part of MPlayer. * + * Original author: Uoti Urpala + * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -48,11 +50,8 @@ static int try_open_file(struct demuxer *demuxer, enum demux_check check) } const struct demuxer_desc demuxer_desc_cue = { - .info = "CUE file demuxer", .name = "cue", - .shortdesc = "CUE", - .author = "Uoti Urpala", - .comment = "", + .desc = "CUE sheet", .type = DEMUXER_TYPE_CUE, .open = try_open_file, }; diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 0f4bf06dbf..5c6afa2d9b 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -1,6 +1,8 @@ /* * This file is part of MPlayer. * + * Original author: Uoti Urpala + * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -43,11 +45,8 @@ static int try_open_file(struct demuxer *demuxer, enum demux_check check) } const struct demuxer_desc demuxer_desc_edl = { - .info = "EDL file demuxer", .name = "edl", - .shortdesc = "EDL", - .author = "Uoti Urpala", - .comment = "", + .desc = "mplayer2 edit decision list", .type = DEMUXER_TYPE_EDL, .open = try_open_file, }; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 88587f8ce0..e788b5b77c 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -902,11 +902,8 @@ static void demux_close_lavf(demuxer_t *demuxer) const demuxer_desc_t demuxer_desc_lavf = { - .info = "libavformat demuxer", .name = "lavf", - .shortdesc = "libavformat", - .author = "Michael Niedermayer", - .comment = "supports many formats, requires libavformat", + .desc = "libavformat", .fill_buffer = demux_lavf_fill_buffer, .open = demux_open_lavf, .close = demux_close_lavf, diff --git a/demux/demux_libass.c b/demux/demux_libass.c index 24e1b9e114..1dc8e92eb0 100644 --- a/demux/demux_libass.c +++ b/demux/demux_libass.c @@ -112,11 +112,8 @@ static void d_close(struct demuxer *demuxer) } const struct demuxer_desc demuxer_desc_libass = { - .info = "Read subtitles with libass", .name = "libass", - .shortdesc = "ASS/SSA subtitles (libass)", - .author = "", - .comment = "", + .desc = "ASS/SSA subtitles (libass)", .open = d_check_file, .close = d_close, }; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 33747f12d7..5c92476c82 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -244,11 +244,8 @@ static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) { } const demuxer_desc_t demuxer_desc_mf = { - .info = "mf demuxer", .name = "mf", - .shortdesc = "MF", - .author = "?", - .comment = "multiframe?, pictures demuxer", + .desc = "image files (mf)", .fill_buffer = demux_mf_fill_buffer, .open = demux_open_mf, .close = demux_close_mf, diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index efc4c8f989..3fb57423a8 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -2718,11 +2718,8 @@ static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg) } const demuxer_desc_t demuxer_desc_matroska = { - .info = "Matroska demuxer", .name = "mkv", - .shortdesc = "Matroska", - .author = "Aurelien Jacobs", - .comment = "", + .desc = "Matroska", .type = DEMUXER_TYPE_MATROSKA, .open = demux_mkv_open, .fill_buffer = demux_mkv_fill_buffer, diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 6c5bbc2e45..ea82ab257f 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -560,11 +560,8 @@ static int demux_mng_control(demuxer_t * demuxer, int cmd, void * arg) } const demuxer_desc_t demuxer_desc_mng = { - .info = "MNG demuxer", .name = "mng", - .shortdesc = "MNG", - .author = "Stefan Schuermans ", - .comment = "MNG files, using libmng", + .desc = "MNG", .fill_buffer = demux_mng_fill_buffer, .open = demux_mng_open, .close = demux_mng_close, diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 83a89e7c1c..54e7b1b939 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -114,11 +114,8 @@ static void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,float aud } const demuxer_desc_t demuxer_desc_rawaudio = { - .info = "Raw audio demuxer", .name = "rawaudio", - .shortdesc = "rawaudio", - .author = "?", - .comment = "", + .desc = "Uncompressed audio", .fill_buffer = demux_rawaudio_fill_buffer, .open = demux_rawaudio_open, .seek = demux_rawaudio_seek, diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 9f670f2879..dc0c3aaee8 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -170,11 +170,8 @@ static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float aud const demuxer_desc_t demuxer_desc_rawvideo = { - .info = "Raw video demuxer", .name = "rawvideo", - .shortdesc = "rawvideo", - .author = "?", - .comment = "", + .desc = "Uncompressed video", .fill_buffer = demux_rawvideo_fill_buffer, .open = demux_rawvideo_open, .seek = demux_rawvideo_seek, diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index 24604978d5..084d7857d9 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1391,11 +1391,8 @@ static int d_control(struct demuxer *demuxer, int cmd, void *arg) } const struct demuxer_desc demuxer_desc_subreader = { - .info = "Deprecated MPlayer subtitle reader", .name = "subreader", - .shortdesc = "Deprecated Subreader", - .author = "", - .comment = "", + .desc = "Deprecated MPlayer subreader", .open = d_open_file, .fill_buffer = d_fill_buffer, .seek = d_seek, diff --git a/stream/tv.c b/stream/tv.c index 9ddf3771ed..9b1f8024e4 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -1097,11 +1097,8 @@ int tv_step_chanlist(tvi_handle_t *tvh) } demuxer_desc_t demuxer_desc_tv = { - .info = "Tv card demuxer", .name = "tv", - .shortdesc = "TV", - .author = "Alex Beregszaszi, Charles R. Henrich", - .comment = "?", + .desc = "TV card demuxer", .type = DEMUXER_TYPE_TV, .fill_buffer = demux_tv_fill_buffer, .open = demux_open_tv, -- cgit v1.2.3 From 6c1e9e4a45d92216a1433ed73ba8f2e09529ca19 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Jul 2013 22:26:15 +0200 Subject: demux: make claiming accurate seek the default Enables hr-seek for raw audio/video demuxers. --- demux/demux.c | 1 + demux/demux_mkv.c | 2 -- demux/demux_mng.c | 3 +++ demux/demux_subreader.c | 2 -- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 836c945bc4..1783f92c96 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -534,6 +534,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts, .movi_start = stream->start_pos, .movi_end = stream->end_pos, .seekable = 1, + .accurate_seek = true, .filepos = -1, .opts = opts, .filename = talloc_strdup(demuxer, stream->url), diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 69ace3b4db..76b7c1d059 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1803,8 +1803,6 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) demuxer->seekable = 1; } - demuxer->accurate_seek = true; - return 0; } diff --git a/demux/demux_mng.c b/demux/demux_mng.c index ea82ab257f..f6cb66302c 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -421,6 +421,9 @@ static int demux_mng_open(demuxer_t * demuxer, enum demux_check check) sh_video->bih->biBitCount = 32; sh_video->bih->biPlanes = 1; + // weirdly broken + demuxer->accurate_seek = false; + // set private data in demuxer and return demuxer demuxer->priv = mng_priv; return 0; diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index 9f7af4e365..6cbea0d8ec 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1356,8 +1356,6 @@ static int d_open_file(struct demuxer *demuxer, enum demux_check check) add_sub_data(demuxer, sd); subdata_free(sd); - demuxer->accurate_seek = true; - return 0; } -- cgit v1.2.3