summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-12-30 00:53:08 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-12-30 00:56:10 +0200
commitd46b86bc7c39082b26ec71aa16431f3275d836ff (patch)
tree035da87ed658f7d75c0eba5a5d4de5462a4c8ddd /libmpdemux
parenta06b32b64e91082c11f747e2910f10a4afd3dfa9 (diff)
parent3e8f2815c19703f5cb6f75db2910234d499d9676 (diff)
downloadmpv-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.c1
-rw-r--r--libmpdemux/demux_mpg.c1
-rw-r--r--libmpdemux/demux_ts.c1
-rw-r--r--libmpdemux/demuxer.c136
-rw-r--r--libmpdemux/demuxer.h1
-rw-r--r--libmpdemux/extension.c11
-rw-r--r--libmpdemux/stheader.h48
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: