diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-12-30 00:53:08 +0200 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-12-30 00:56:10 +0200 |
commit | d46b86bc7c39082b26ec71aa16431f3275d836ff (patch) | |
tree | 035da87ed658f7d75c0eba5a5d4de5462a4c8ddd /libmpdemux | |
parent | a06b32b64e91082c11f747e2910f10a4afd3dfa9 (diff) | |
parent | 3e8f2815c19703f5cb6f75db2910234d499d9676 (diff) | |
download | mpv-d46b86bc7c39082b26ec71aa16431f3275d836ff.tar.bz2 mpv-d46b86bc7c39082b26ec71aa16431f3275d836ff.tar.xz |
Merge svn changes up to r30136
Ignore another broken correct-pts change in 30134.
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/aviheader.c | 1 | ||||
-rw-r--r-- | libmpdemux/demux_mpg.c | 1 | ||||
-rw-r--r-- | libmpdemux/demux_ts.c | 1 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 136 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 1 | ||||
-rw-r--r-- | libmpdemux/extension.c | 11 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 48 |
7 files changed, 172 insertions, 27 deletions
diff --git a/libmpdemux/aviheader.c b/libmpdemux/aviheader.c index 230e769fe0..a57f55997e 100644 --- a/libmpdemux/aviheader.c +++ b/libmpdemux/aviheader.c @@ -219,6 +219,7 @@ while(1){ mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "aviheader", stream_id); memcpy(&sh_audio->audio,&h,sizeof(h)); sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate; + sh_audio->needs_parsing = 1; } last_fccType=h.fccType; last_fccHandler=h.fccHandler; diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c index 3d74a0592b..8f6220be8f 100644 --- a/libmpdemux/demux_mpg.c +++ b/libmpdemux/demux_mpg.c @@ -270,6 +270,7 @@ static void new_audio_stream(demuxer_t *demux, int aid){ sh_audio_t* sh_a; new_sh_audio(demux,aid); sh_a = (sh_audio_t*)demux->a_streams[aid]; + sh_a->needs_parsing = 1; switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) case 0x00: sh_a->format=0x50;break; // mpeg case 0xA0: sh_a->format=0x10001;break; // dvd pcm diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c index c7966da9ba..af9e2109f4 100644 --- a/libmpdemux/demux_ts.c +++ b/libmpdemux/demux_ts.c @@ -305,6 +305,7 @@ static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es) if(sh) { const char *lang = pid_lang_from_pmt(priv, es->pid); + sh->needs_parsing = 1; sh->format = IS_AUDIO(es->type) ? es->type : es->subtype; sh->ds = demuxer->audio; diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 564655609f..78c18e7640 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -52,6 +52,13 @@ #endif #endif +// This is quite experimental, in particular it will mess up the pts values +// in the queue - on the other hand it might fix some issues like generating +// broken files with mencoder and stream copy. +// Better leave it disabled for now, if we find no use for it this code should +// just be removed again. +#define PARSE_ON_ADD 0 + void resync_video_stream(sh_video_t *sh_video); void resync_audio_stream(sh_audio_t *sh_audio); @@ -276,6 +283,10 @@ static void free_sh_sub(sh_sub_t *sh) ass_free_track(sh->ass_track); #endif free(sh->lang); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -314,6 +325,10 @@ void free_sh_audio(demuxer_t *demuxer, int id) free(sh->wf); free(sh->codecdata); free(sh->lang); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -343,6 +358,10 @@ 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); +#ifdef CONFIG_LIBAVCODEC + av_parser_close(sh->parser); + av_freep(&sh->avctx); +#endif free(sh); } @@ -396,7 +415,7 @@ void free_demuxer(demuxer_t *demuxer) } -void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +static void ds_add_packet_internal(demux_stream_t *ds, demux_packet_t *dp) { // append packet to DS stream: ++ds->packs; @@ -416,6 +435,109 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) ds->demuxer->video->packs); } +#ifdef CONFIG_LIBAVCODEC +static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, unsigned format) +{ + enum CodecID codec_id = CODEC_ID_NONE; + extern int avcodec_initialized; + if (!avcodec_initialized) { + avcodec_init(); + avcodec_register_all(); + avcodec_initialized = 1; + } + switch (format) { + case 0x2000: + case 0x332D6361: + case 0x332D4341: + case MKTAG('d', 'n', 'e', 't'): + case MKTAG('s', 'a', 'c', '3'): + codec_id = CODEC_ID_AC3; + break; + case MKTAG('E', 'A', 'C', '3'): + codec_id = CODEC_ID_EAC3; + break; + case 0x2001: + case 0x86: + codec_id = CODEC_ID_DTS; + break; + case 0x55: + case 0x5500736d: + case MKTAG('.', 'm', 'p', '3'): + case MKTAG('M', 'P', 'E', ' '): + case MKTAG('L', 'A', 'M', 'E'): + codec_id = CODEC_ID_MP3; + break; + case 0x50: + case MKTAG('.', 'm', 'p', '2'): + case MKTAG('.', 'm', 'p', '1'): + codec_id = CODEC_ID_MP2; + break; + } + if (codec_id != CODEC_ID_NONE) { + *avctx = avcodec_alloc_context(); + if (!*avctx) + return; + *parser = av_parser_init(codec_id); + if (!*parser) + av_freep(avctx); + } +} + +static void get_parser(sh_common_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->format); + sh->avctx = *avctx; + sh->parser = *parser; +} + +int ds_parse(demux_stream_t *ds, uint8_t **buffer, int *len, double pts, off_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); +} +#endif + +void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) +{ +#if PARSE_ON_ADD && defined(CONFIG_LIBAVCODEC) + int len = dp->len; + int pos = 0; + while (len > 0) { + uint8_t *parsed_start = dp->buffer + pos; + int parsed_len = len; + int consumed = ds_parse(ds->sh, &parsed_start, &parsed_len, dp->pts, dp->pos); + pos += consumed; + len -= consumed; + if (parsed_start == dp->buffer && parsed_len == dp->len) { + ds_add_packet_internal(ds, dp); + } else if (parsed_len) { + demux_packet_t *dp2 = new_demux_packet(parsed_len); + dp2->pos = dp->pos; + dp2->pts = dp->pts; // should be parser->pts but that works badly + memcpy(dp2->buffer, parsed_start, parsed_len); + ds_add_packet_internal(ds, dp2); + } + } +#else + ds_add_packet_internal(ds, dp); +#endif +} + void ds_read_packet(demux_stream_t *ds, stream_t *stream, int len, double pts, off_t pos, int flags) { @@ -526,6 +648,18 @@ int ds_fill_buffer(demux_stream_t *ds) break; } if (!demux_fill_buffer(demux, ds)) { +#if PARSE_ON_ADD && defined(CONFIG_LIBAVCODEC) + uint8_t *parsed_start = NULL; + int parsed_len = 0; + ds_parse(ds->sh, &parsed_start, &parsed_len, MP_NOPTS_VALUE, 0); + if (parsed_len) { + demux_packet_t *dp2 = new_demux_packet(parsed_len); + dp2->pts = MP_NOPTS_VALUE; + memcpy(dp2->buffer, parsed_start, parsed_len); + ds_add_packet_internal(ds, dp2); + continue; + } +#endif mp_dbg(MSGT_DEMUXER, MSGL_DBG2, "ds_fill_buffer()->demux_fill_buffer() failed\n"); break; // EOF diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 44cd642ed3..5da35efa03 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -400,6 +400,7 @@ int ds_get_packet(demux_stream_t *ds,unsigned char **start); int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts); int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start); double ds_get_next_pts(demux_stream_t *ds); +int ds_parse(demux_stream_t *sh, uint8_t **buffer, int *len, double pts, off_t pos); // This is defined here because demux_stream_t ins't defined in stream.h stream_t* new_ds_stream(demux_stream_t *ds); diff --git a/libmpdemux/extension.c b/libmpdemux/extension.c index 59d242e4dd..1d2ffb832e 100644 --- a/libmpdemux/extension.c +++ b/libmpdemux/extension.c @@ -27,6 +27,12 @@ /* * 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 libmpdemux/demuxer_lavf.c will usually achieve + * the same effect in a much more reliable way. */ static struct { const char *extension; @@ -38,9 +44,6 @@ static struct { { "vob", DEMUXER_TYPE_MPEG_PS }, { "m2v", DEMUXER_TYPE_MPEG_PS }, { "avi", DEMUXER_TYPE_AVI }, - { "mp4", DEMUXER_TYPE_LAVF }, - { "mov", DEMUXER_TYPE_LAVF }, - { "qt", DEMUXER_TYPE_LAVF }, { "asx", DEMUXER_TYPE_ASF }, { "asf", DEMUXER_TYPE_ASF }, { "wmv", DEMUXER_TYPE_ASF }, @@ -65,7 +68,6 @@ static struct { { "it", DEMUXER_TYPE_XMMS }, { "mid", DEMUXER_TYPE_XMMS }, { "midi", DEMUXER_TYPE_XMMS }, - { "vqf", DEMUXER_TYPE_LAVF }, { "nsv", DEMUXER_TYPE_NSV }, { "nsa", DEMUXER_TYPE_NSV }, { "mpc", DEMUXER_TYPE_MPC }, @@ -81,6 +83,7 @@ static struct { { "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 diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h index 9b43f21dfd..b11b886ce1 100644 --- a/libmpdemux/stheader.h +++ b/libmpdemux/stheader.h @@ -26,14 +26,32 @@ struct demuxer; // Stream headers: +#define SH_COMMON \ + struct MPOpts *opts; \ + struct demux_stream *ds; \ + struct codecs *codec; \ + unsigned int format; \ + int initialized; \ + float stream_delay; /* number of seconds stream should be delayed (according to dwStart or similar) */ \ + /* things needed for parsing */ \ + int needs_parsing; \ + struct AVCodecContext *avctx; \ + struct AVCodecParserContext *parser; \ + /* audio: last known pts value in output from decoder \ + * video: predicted/interpolated PTS of the current frame */ \ + double pts; \ + /* codec-specific: */ \ + void* context; /* codec-specific stuff (usually HANDLE or struct pointer) */ \ + char* lang; /* track language */ \ + int default_track; \ + +typedef struct sh_common { + SH_COMMON +} sh_common_t; + typedef struct sh_audio { - struct MPOpts *opts; + SH_COMMON int aid; - struct demux_stream *ds; - struct codecs *codec; - unsigned int format; - int initialized; - float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // output format: int sample_format; int samplerate; @@ -65,29 +83,19 @@ typedef struct sh_audio { AVIStreamHeader audio; WAVEFORMATEX* wf; // codec-specific: - void* context; // codec-specific stuff (usually HANDLE or struct pointer) unsigned char* codecdata; // extra header data passed from demuxer to codec int codecdata_len; - double pts; // last known pts value in output from decoder int pts_bytes; // bytes output by decoder after last known pts - char* lang; // track language - int default_track; } sh_audio_t; typedef struct sh_video { - struct MPOpts *opts; + SH_COMMON int vid; - struct demux_stream *ds; - struct codecs *codec; - unsigned int format; - int initialized; float timer; // absolute time in video stream, since last start/seek - float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // frame counters: float num_frames; // number of frames played int num_frames_decoded; // number of frames decoded // timing (mostly for mpeg): - double pts; // predicted/interpolated PTS of the current frame double i_pts; // PTS for the _next_ I/P frame float next_frame_time; double last_pts; @@ -120,19 +128,15 @@ typedef struct sh_video { AVIStreamHeader video; BITMAPINFOHEADER* bih; void* ImageDesc; // for quicktime codecs - // codec-specific: - void* context; // codec-specific stuff (usually HANDLE or struct pointer) } sh_video_t; typedef struct sh_sub { - struct MPOpts *opts; + SH_COMMON int sid; char type; // t = text, v = VobSub, a = SSA/ASS unsigned char* extradata; // extra header data passed from demuxer int extradata_len; struct ass_track *ass_track; // for SSA/ASS streams (type == 'a') - char* lang; // track language - int default_track; } sh_sub_t; // demuxer.c: |