aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/changes.rst1
-rw-r--r--DOCS/man/en/options.rst21
-rw-r--r--DOCS/tech-overview.txt65
-rw-r--r--Makefile15
-rw-r--r--audio/decode/ad.h4
-rw-r--r--audio/decode/ad_lavc.c62
-rw-r--r--audio/decode/ad_mpg123.c16
-rw-r--r--audio/decode/ad_spdif.c79
-rw-r--r--audio/decode/dec_audio.c34
-rw-r--r--core/asxparser.c4
-rw-r--r--core/command.c10
-rw-r--r--core/encode_lavc.c2
-rw-r--r--core/input/input.c2
-rw-r--r--core/mp_core.h3
-rw-r--r--core/mplayer.c409
-rw-r--r--core/options.c18
-rw-r--r--core/options.h3
-rw-r--r--core/playlist_parser.c5
-rw-r--r--core/timeline/tl_cue.c15
-rw-r--r--core/timeline/tl_edl.c10
-rw-r--r--core/timeline/tl_matroska.c20
-rw-r--r--demux/asf.h251
-rw-r--r--demux/asfguid.h89
-rw-r--r--demux/asfheader.c721
-rw-r--r--demux/asfheader.h28
-rw-r--r--demux/aviheader.c674
-rw-r--r--demux/aviheader.h382
-rw-r--r--demux/aviprint.c197
-rw-r--r--demux/aviprint.h35
-rw-r--r--demux/demux.c1006
-rw-r--r--demux/demux.h231
-rw-r--r--demux/demux_asf.c691
-rw-r--r--demux/demux_avi.c899
-rw-r--r--demux/demux_cue.c34
-rw-r--r--demux/demux_edl.c34
-rw-r--r--demux/demux_lavf.c113
-rw-r--r--demux/demux_libass.c76
-rw-r--r--demux/demux_mf.c119
-rw-r--r--demux/demux_mkv.c75
-rw-r--r--demux/demux_mng.c101
-rw-r--r--demux/demux_mpg.c1306
-rw-r--r--demux/demux_raw.c274
-rw-r--r--demux/demux_rawaudio.c127
-rw-r--r--demux/demux_rawvideo.c178
-rw-r--r--demux/demux_subreader.c26
-rw-r--r--demux/demux_ts.c3532
-rw-r--r--demux/demux_ts.h24
-rw-r--r--demux/extension.c104
-rw-r--r--demux/mp3_hdr.c144
-rw-r--r--demux/mp3_hdr.h36
-rw-r--r--demux/mpeg_hdr.c539
-rw-r--r--demux/mpeg_hdr.h55
-rw-r--r--demux/ms_hdr.h54
-rw-r--r--demux/parse_es.c158
-rw-r--r--demux/parse_es.h45
-rw-r--r--demux/stheader.h47
-rw-r--r--demux/video.c620
-rw-r--r--stream/dvbin.h1
-rw-r--r--stream/stream.c78
-rw-r--r--stream/stream.h81
-rw-r--r--stream/stream_avdevice.c9
-rw-r--r--stream/stream_bluray.c14
-rw-r--r--stream/stream_cdda.c11
-rw-r--r--stream/stream_dvb.c15
-rw-r--r--stream/stream_dvd.c17
-rw-r--r--stream/stream_file.c43
-rw-r--r--stream/stream_lavf.c15
-rw-r--r--stream/stream_memory.c7
-rw-r--r--stream/stream_mf.c9
-rw-r--r--stream/stream_null.c10
-rw-r--r--stream/stream_pvr.c10
-rw-r--r--stream/stream_radio.c10
-rw-r--r--stream/stream_smb.c35
-rw-r--r--stream/stream_tv.c9
-rw-r--r--stream/stream_vcd.c54
-rw-r--r--stream/tv.c79
-rw-r--r--stream/tv.h4
-rw-r--r--stream/vcd_read.h2
-rw-r--r--sub/dec_sub.c6
-rw-r--r--sub/osd_libass.c2
-rw-r--r--video/decode/dec_video.c4
-rw-r--r--video/decode/vd.c1
-rw-r--r--video/decode/vd_lavc.c5
-rw-r--r--video/out/gl_lcms.c2
84 files changed, 1299 insertions, 13057 deletions
diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst
index 70f6fd71ec..eeac7fada9 100644
--- a/DOCS/man/en/changes.rst
+++ b/DOCS/man/en/changes.rst
@@ -104,7 +104,6 @@ Command Line Switches
``-subdelay`` ``--sub-delay``
``-subpos`` ``--sub-pos``
``-forcedsubsonly`` ``--sub-forced-only``
- ``-ni`` ``--avi-ni``
``-benchmark`` ``--untimed`` (no stats)
``-xineramascreen`` ``--screen`` (different values)
``-ss`` ``--start``
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index 150c12d043..58fc365db1 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -695,12 +695,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=<auto|top|bottom>``
Set first field for interlaced content. Useful for deinterlacers that
double the framerate: ``--vf=yadif=1`` and ``--vo=vdpau:deint``.
@@ -1049,11 +1043,6 @@
This option only works if the underlying media supports seeking
(i.e. not with stdin, pipe, etc).
-``--ignore-start``
- Matters with the builtin AVI demuxer only, which is not enabled by default.
- Ignore the specified starting time for streams in AVI files. This
- nullifies stream delays.
-
``--include=<configuration-file>``
Specify configuration file to be parsed after the default ones.
@@ -1258,20 +1247,10 @@
depends on the VO backend and how it handles keyboard input. Does not
apply to terminal input.)
-``--avi-ni``
- (Internal AVI demuxer which is not used by default only)
- Force usage of non-interleaved AVI parser (fixes playback of some bad AVI
- files).
-
``--no-aspect``
Ignore aspect ratio information from video file and assume the video has
square pixels. See also ``--aspect``.
-``--no-bps``
- (Internal AVI demuxer which is not used by default only)
- Do not use average byte/second value for A-V sync. Helps with some AVI
- files with broken header.
-
``--no-cache``
Turn off input stream caching. See ``--cache``.
diff --git a/DOCS/tech-overview.txt b/DOCS/tech-overview.txt
index e242df1325..d4dbd95938 100644
--- a/DOCS/tech-overview.txt
+++ b/DOCS/tech-overview.txt
@@ -1,9 +1,9 @@
NOTE: DOCS/OUTDATED-tech/* may contain more detailed information, but most of it
is possibly or definitely outdated. This file intends to give a big
- picture of how mplayer/mpv is structured.
+ picture of how mpv is structured.
core/mplayer.c:
- This contains the main play loop, anything related to mplayer and playback
+ This contains the main play loop, anything related to mpv and playback
related initializations. It also contains the main function. Generally, it
accesses all other subsystems, initializes them, and pushes data between
them during playback.
@@ -59,7 +59,7 @@ talloc.h & talloc.c:
allocation. (Needless to say, talloc_free() and free() are completely
different things.)
- The copy in mplayer has been modified to abort on OOM conditions. An
+ The copy in mpv has been modified to abort on OOM conditions. An
allocation call will never return NULL.
One very useful feature of talloc is fast tracking of memory leaks. ("Fast"
@@ -72,9 +72,13 @@ talloc.h & talloc.c:
Documentation can be found here:
http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD
+ Note: unlike tcmalloc, jemalloc, etc., talloc() is not actually a malloc
+ replacement. It works on top of system malloc and provides additional
+ features that are supposed to make memory management easier.
+
core/mp_core.h:
Data structures for mplayer.c and command.c. They are usually not accessed
- by other parts of mplayer for the sake of modularization.
+ by other parts of mpv for the sake of modularization.
Note that there are lots of global variables floating around everywhere
else. This is an ongoing transition, and eventually there should be no
@@ -92,7 +96,7 @@ core/input/input.c:
Note that keyboard input and slave mode input are essentially the same
things. Just looking at input.conf should make this clear. (The other
- direction of slave mode communication, mplayer to application, consists of
+ direction of slave mode communication, mpv to application, consists of
random mp_msg() calls all over the code in all parts of the player.)
core/command.c:
@@ -100,18 +104,18 @@ core/command.c:
Properties are essentially dynamic variables changed by certain commands.
This is basically responsible for all user commands, like initiating
seeking, switching tracks, etc. It calls into mplayer.c, where most of the
- work is done, but also into other parts of mplayer.
+ work is done, but also into other parts of mpv.
core/mp_msg.h:
- All terminal output should go though mp_msg().
+ All terminal output should go through mp_msg().
stream/*:
File input is implemented here. stream.h/.c provides a simple stream based
- interface (like reading a number of bytes at a given offset). mplayer can
+ interface (like reading a number of bytes at a given offset). mpv can
also play from http streams and such, which is implemented here.
- E.g. if mplayer sees "http://something" on the command line, it will pick
- stream_http.c based on the prefix, and pass the rest of the filename to it.
+ E.g. if mpv sees "http://something" on the command line, it will pick
+ stream_lavf.c based on the prefix, and pass the rest of the filename to it.
Some stream inputs are quite special: stream_dvd.c turns DVDs into mpeg
streams (DVDs are actually a bunch of vob files etc. on a filesystem),
@@ -120,39 +124,40 @@ stream/*:
Some stream inputs are just there to invoke special demuxers, like
stream_mf.c. (Basically to make the prefix "mf://" do something special.)
- cache2.c is a horrible little thing which provides a caching wrapper around
- stream implementations, needed for smooth network playback.
+ cache.c is a caching wrapper around streams implementations, needed for
+ smooth network playback.
demux/:
Demuxers split data streams into audio/video/sub streams, which in turn
- yield packets. Packets (see demux_packet.h) are mostly byte chunks tagged
- with a playback time (PTS). These packets are passed to the decoders.
+ are split in packets. Packets (see demux_packet.h) are mostly byte chunks
+ tagged with a playback time (PTS). These packets are passed to the decoders.
Most demuxers have been removed from this fork, and the only important and
"actual" demuxers left are demux_mkv.c and demux_lavf.c (uses libavformat).
There are some pseudo demuxers like demux_cue.c, which exist only to invoke
other frontend code (tl_cue.c in this case).
- The main interface is in demux.h. A demuxer provides a list of available
- streams. Also, for each type of stream (video/audio/sub) there is a
- demux_stream. This contains the current packet stream coming from the
- demuxer as a linked list of demux_packets.
+ The main interface is in demux.h. The stream headers are in stheader.h.
+ There is a stream header for each audio/video/sub stream, and each of them
+ holds codec information about the stream and other information.
video/:
- This contains several things related to audio/video encoding, as well as
+ This contains several things related to audio/video decoding, as well as
video filters.
- mp_image.h and img_format.h define how mplayer stores video frames
+ mp_image.h and img_format.h define how mpv stores decoded video frames
internally.
video/decode/:
- vd_*.c are video decoders. (There's only vd_ffmpeg.c left.) dec_video.c/vd.c
+ vd_*.c are video decoders. (There's only vd_lavc.c left.) dec_video.c/vd.c
handle most of connecting the frontend with the actual decoder.
video/filter/:
vf_*.c and vf.c form the video filter chain. They are fed by the video
decoder, and output the filtered images to the VOs though vf_vo.c. By
- default, no video filters (except vf_vo) are used.
+ default, no video filters (except vf_vo) are used. vf_scale is automatically
+ inserted if the video output can't handle the video format used by the
+ decoder.
video/out/:
Video output. They also create GUI windows and handle user input. In most
@@ -167,13 +172,18 @@ video/out/:
vo_vdpau and vo_opengl should be taken as reference.
audio/:
- format.h/format.c define the audio formats.
+ format.h/format.c define the uncompressed audio formats. (As well as some
+ compressed formats used for spdif.)
audio/decode/:
- ad_*.c and dec_audio.c/ad.c handle audio decoding.
+ ad_*.c and dec_audio.c/ad.c handle audio decoding. ad_lavc.c is the
+ decoder using ffmpeg. ad_spdif.c is not really a decoder, but is used for
+ compressed audio passthrough.
audio/filter/:
- Audio filter chain.
+ Audio filter chain. af_lavrresample is inserted if any form of conversion
+ between audio formats is needed. (af_format.c is also used for some corner
+ cases.)
audio/out/:
Audio outputs.
@@ -182,7 +192,7 @@ audio/out/:
--gapless-audio, even playing a new file will close and re-open the audio
device.
- Note that mplayer synchronizes the video to the audio. That's the reason
+ Note that mpv synchronizes the video to the audio. That's the reason
why buggy audio drivers can have a bad influence on playback quality.
sub/:
@@ -210,7 +220,8 @@ sub/:
Text subtitles can be preloaded, in which case they are read fully as soon
as the subtitle is selected, and then effectively stored in an ASS_Track.
It's used for external text subtitles, and required to make codepage
- detection as well as timing postprocessing work.
+ detection as well as timing postprocessing work. (Timing postprocessing
+ removes tiny gaps or overlaps between subtitle events.)
core/timeline/:
A timeline is the abstraction used by mplayer.c to combine several files
diff --git a/Makefile b/Makefile
index c3638c865f..5c0c1c6490 100644
--- a/Makefile
+++ b/Makefile
@@ -187,30 +187,17 @@ SOURCES = talloc.c \
core/timeline/tl_edl.c \
core/timeline/tl_matroska.c \
core/timeline/tl_cue.c \
- demux/asfheader.c \
- demux/aviheader.c \
- demux/aviprint.c \
demux/codec_tags.c \
demux/demux.c \
- demux/demux_asf.c \
- demux/demux_avi.c \
demux/demux_edl.c \
demux/demux_cue.c \
demux/demux_lavf.c \
demux/demux_mf.c \
demux/demux_mkv.c \
- demux/demux_mpg.c \
demux/demux_subreader.c \
- demux/demux_ts.c \
- demux/mp3_hdr.c \
- demux/parse_es.c \
- demux/mpeg_hdr.c \
- demux/demux_rawaudio.c \
- demux/demux_rawvideo.c \
+ demux/demux_raw.c \
demux/ebml.c \
- demux/extension.c \
demux/mf.c \
- demux/video.c \
osdep/io.c \
osdep/numcores.c \
osdep/timer.c \
diff --git a/audio/decode/ad.h b/audio/decode/ad.h
index ff51ecbe35..1c8a211f5b 100644
--- a/audio/decode/ad.h
+++ b/audio/decode/ad.h
@@ -42,10 +42,6 @@ typedef struct ad_functions
// NULL terminated array of all drivers
extern const ad_functions_t * const mpcodecs_ad_drivers[];
-// fallback if ADCTRL_RESYNC not implemented: sh_audio->a_in_buffer_len=0;
#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 b5a4ee1ef8..e78e26f208 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -24,6 +24,7 @@
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
+#include <libavutil/common.h>
#include "talloc.h"
@@ -50,8 +51,8 @@ struct priv {
uint8_t *output_packed; // used by deplanarize to store packed audio samples
int output_left;
int unitsize;
- int previous_data_left; // input demuxer packet data
bool force_channel_map;
+ struct demux_packet *packet;
};
#define OPT_BASE_STRUCT struct MPOpts
@@ -344,9 +345,9 @@ 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;
+ talloc_free(ctx->packet);
+ ctx->packet = NULL;
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
@@ -375,43 +376,35 @@ static int decode_new_packet(struct sh_audio *sh)
{
struct priv *priv = sh->context;
AVCodecContext *avctx = priv->avctx;
- double pts = MP_NOPTS_VALUE;
- int insize;
- bool packet_already_used = priv->previous_data_left;
- struct demux_packet *mpkt = ds_get_packet2(sh->ds,
- priv->previous_data_left);
- unsigned char *start;
- 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
- } else {
- assert(mpkt->len >= priv->previous_data_left);
- if (!priv->previous_data_left) {
- priv->previous_data_left = mpkt->len;
- pts = mpkt->pts;
- }
- 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 = FFMAX(priv->previous_data_left, 0);
- }
+ struct demux_packet *mpkt = priv->packet;
+ if (!mpkt)
+ mpkt = demux_read_packet(sh->gsh);
+ if (!mpkt)
+ return -1; // error or EOF
+
+ priv->packet = talloc_steal(priv, mpkt);
+
+ int in_len = mpkt->len;
AVPacket pkt;
mp_set_av_packet(&pkt, mpkt);
- pkt.data = start;
- pkt.size = insize;
- if (pts != MP_NOPTS_VALUE && !packet_already_used) {
- sh->pts = pts;
+ if (mpkt->pts != MP_NOPTS_VALUE) {
+ sh->pts = mpkt->pts;
sh->pts_bytes = 0;
}
int got_frame = 0;
int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt);
+ if (ret > 0) {
+ ret = FFMIN(ret, mpkt->len); // sanity check against decoder overreads
+ mpkt->buffer += ret;
+ mpkt->len -= ret;
+ mpkt->pts = MP_NOPTS_VALUE; // don't reset PTS next time
+ }
+ if (mpkt->len == 0 || ret <= 0) {
+ talloc_free(mpkt);
+ priv->packet = NULL;
+ }
// LATM may need many packets to find mux info
if (ret == AVERROR(EAGAIN))
return 0;
@@ -419,9 +412,6 @@ static int decode_new_packet(struct sh_audio *sh)
mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n");
return -1;
}
- // The "insize >= ret" test is sanity check against decoder overreads
- if (!sh->parser && insize >= ret)
- priv->previous_data_left = insize - ret;
if (!got_frame)
return 0;
uint64_t unitsize = (uint64_t)av_get_bytes_per_sample(avctx->sample_fmt) *
@@ -438,7 +428,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", insize,
+ 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 1314110062..d0fa43aa25 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,28 +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;
- }
- 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;
switch (lavf_ctx->streams[0]->codec->codec_id) {
@@ -226,64 +204,35 @@ 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) {
- x = 0;
- ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0);
- if (x == 0)
- continue; // END_NOT_FOUND
- in_size = x;
- } else {
- in_size = x;
- consumed = ds_parse(sh->ds, &start, &x, pts, 0);
- 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 out_len = spdif_ctx->out_buffer_len;
+ int ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt);
+ avio_flush(lavf_ctx->pb);
+ sh->pts_bytes += spdif_ctx->out_buffer_len - out_len;
+ talloc_free(mpkt);
if (ret < 0)
break;
}
- sh->pts_bytes += spdif_ctx->out_buffer_len;
return spdif_ctx->out_buffer_len;
}
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 4f2f462b92..d6b57dd2b5 100644
--- a/audio/decode/dec_audio.c
+++ b/audio/decode/dec_audio.c
@@ -21,6 +21,8 @@
#include <unistd.h>
#include <assert.h>
+#include <libavutil/mem.h>
+
#include "demux/codec_tags.h"
#include "config.h"
@@ -53,15 +55,6 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder)
return 0;
}
- /* allocate audio in buffer: */
- if (sh_audio->audio_in_minsize > 0) {
- sh_audio->a_in_buffer_size = sh_audio->audio_in_minsize;
- mp_tmsg(MSGT_DECAUDIO, MSGL_V,
- "dec_audio: Allocating %d bytes for input buffer.\n",
- sh_audio->a_in_buffer_size);
- sh_audio->a_in_buffer = av_mallocz(sh_audio->a_in_buffer_size);
- }
-
const int base_size = 65536;
// At least 64 KiB plus rounding up to next decodable unit size
sh_audio->a_buffer_size = base_size + sh_audio->audio_out_minsize;
@@ -91,9 +84,6 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder)
return 0;
}
- if (!sh_audio->o_bps)
- sh_audio->o_bps = sh_audio->channels.num * sh_audio->samplerate
- * sh_audio->samplesize;
return 1;
}
@@ -157,12 +147,9 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders)
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n",
sh_audio->gsh->decoder_desc);
mp_msg(MSGT_DECAUDIO, MSGL_V,
- "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n",
+ "AUDIO: %d Hz, %d ch, %s\n",
sh_audio->samplerate, sh_audio->channels.num,
- af_fmt2str_short(sh_audio->sample_format),
- sh_audio->i_bps * 8 * 0.001,
- ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0,
- sh_audio->i_bps, sh_audio->o_bps);
+ af_fmt2str_short(sh_audio->sample_format));
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n",
sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num);
@@ -192,7 +179,6 @@ void uninit_audio(sh_audio_t *sh_audio)
talloc_free(sh_audio->gsh->decoder_desc);
sh_audio->gsh->decoder_desc = NULL;
av_freep(&sh_audio->a_buffer);
- av_freep(&sh_audio->a_in_buffer);
}
@@ -368,20 +354,8 @@ void decode_audio_prepend_bytes(struct bstr *outbuf, int count, int byte)
void resync_audio_stream(sh_audio_t *sh_audio)
{
- sh_audio->a_in_buffer_len = 0; // clear audio input buffer
sh_audio->pts = MP_NOPTS_VALUE;
if (!sh_audio->initialized)
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/asxparser.c b/core/asxparser.c
index 17ce6b3e8c..ec15313547 100644
--- a/core/asxparser.c
+++ b/core/asxparser.c
@@ -27,7 +27,6 @@
#include "playlist.h"
#include "playlist_parser.h"
#include "stream/stream.h"
-#include "demux/demux.h"
#include "asxparser.h"
#include "core/mp_msg.h"
@@ -451,7 +450,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 +459,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/command.c b/core/command.c
index 6056596d04..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_video *sh_video = demuxer->video->sh;
- if (sh_video)
- resync_video_stream(sh_video);
+ if (mpctx->sh_video)
+ resync_video_stream(mpctx->sh_video);
- struct sh_audio *sh_audio = demuxer->audio->sh;
- if (sh_audio)
- resync_audio_stream(sh_audio);
+ if (mpctx->sh_audio)
+ resync_audio_stream(mpctx->sh_audio);
}
return M_PROPERTY_OK;
case M_PROPERTY_GET_TYPE: {
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 47005fdf83..7ae76b9e04 100644
--- a/core/input/input.c
+++ b/core/input/input.c
@@ -1958,7 +1958,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/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 1341a51a1a..95a31aa15b 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);
@@ -373,13 +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->sh && main_new_pos == MP_NOPTS_VALUE) {
- demux_fill_buffer(mpctx->demuxer, ds);
- if (ds->first)
- main_new_pos = ds->first->pts;
- }
+ 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;
@@ -445,11 +428,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;
}
}
}
@@ -484,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) {
@@ -930,12 +914,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,
@@ -954,7 +932,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;
}
@@ -967,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,
@@ -990,6 +970,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;
}
@@ -1021,6 +1003,7 @@ static void add_dvd_tracks(struct MPContext *mpctx)
track->lang = talloc_strdup(track, req.name);
}
}
+ demuxer_enable_autoselect(demuxer);
#endif
}
@@ -1152,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
@@ -1684,41 +1667,25 @@ static double written_audio_pts(struct MPContext *mpctx)
sh_audio_t *sh_audio = mpctx->sh_audio;
if (!sh_audio)
return MP_NOPTS_VALUE;
- demux_stream_t *d_audio = mpctx->sh_audio->ds;
+
+ double bps = sh_audio->channels.num * sh_audio->samplerate *
+ sh_audio->samplesize;
+
// first calculate the end pts of audio that has been output by decoder
double a_pts = sh_audio->pts;
- if (a_pts != MP_NOPTS_VALUE)
- // Good, decoder supports new way of calculating audio pts.
- // sh_audio->pts is the timestamp of the latest input packet with
- // known pts that the decoder has decoded. sh_audio->pts_bytes is
- // the amount of bytes the decoder has written after that timestamp.
- a_pts += sh_audio->pts_bytes / (double) sh_audio->o_bps;
- else {
- // Decoder doesn't support new way of calculating pts (or we're
- // being called before it has decoded anything with known timestamp).
- // Use the old method of audio pts calculation: take the timestamp
- // of last packet with known pts the decoder has read data from,
- // and add amount of bytes read after the beginning of that packet
- // divided by input bps. This will be inaccurate if the input/output
- // 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;
- if (a_pts == MP_NOPTS_VALUE)
- return a_pts;
-
- // ds_tell_pts returns bytes read after last timestamp from
- // demuxing layer, decoder might use sh_audio->a_in_buffer for bytes
- // it has read but not decoded
- if (sh_audio->i_bps)
- a_pts += (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len) /
- (double)sh_audio->i_bps;
- }
+ if (a_pts == MP_NOPTS_VALUE)
+ return MP_NOPTS_VALUE;
+
+ // sh_audio->pts is the timestamp of the latest input packet with
+ // known pts that the decoder has decoded. sh_audio->pts_bytes is
+ // the amount of bytes the decoder has written after that timestamp.
+ a_pts += sh_audio->pts_bytes / bps;
+
// Now a_pts hopefully holds the pts for end of audio from decoder.
- // Substract data in buffers between decoder and audio out.
+ // Subtract data in buffers between decoder and audio out.
// Decoded but not filtered
- a_pts -= sh_audio->a_buffer_len / (double)sh_audio->o_bps;
+ a_pts -= sh_audio->a_buffer_len / bps;
// Data buffered in audio filters, measured in bytes of "missing" output
double buffered_output = af_calc_delay(sh_audio->afilter);
@@ -1743,21 +1710,21 @@ double playing_audio_pts(struct MPContext *mpctx)
return pts - mpctx->opts.playback_speed *ao_get_delay(mpctx->ao);
}
-// When reading subtitles from a demuxer, and we don't read video or audio
-// from the demuxer, we must explicitly read subtitle packets. (Normally,
-// subs are interleaved with video and audio, so we get them automatically.)
-static bool is_non_interleaved(struct MPContext *mpctx, struct track *track)
+// When reading subtitles from a demuxer, and we read video or audio from the
+// demuxer, we should not explicitly read subtitle packets. (With external
+// subs, we have to.)
+static bool is_interleaved(struct MPContext *mpctx, struct track *track)
{
if (track->is_external || !track->demuxer)
- return true;
+ return false;
struct demuxer *demuxer = track->demuxer;
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
struct track *other = mpctx->current_track[type];
if (other && other != track && other->demuxer && other->demuxer == demuxer)
- return false;
+ return true;
}
- return true;
+ return false;
}
static void reset_subtitles(struct MPContext *mpctx)
@@ -1785,29 +1752,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);
+ bool interleaved = is_interleaved(mpctx, track);
while (1) {
- if (non_interleaved)
- ds_get_next_pts(d_sub);
- if (!d_sub->first)
+ if (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 == MP_NOPTS_VALUE) {
- // Try old method of getting PTS. This is only needed in the
- // DVD playback case with demux_mpg.
- // XXX This is wrong, sh_video->pts can be arbitrarily
- // much behind demuxing position. Unfortunately using
- // d_video->pts which would have been the simplest
- // improvement doesn't work because mpeg specific hacks
- // in video.c set d_video->pts to 0.
- float x = d_sub->pts - refpts_s;
- if (x > -20 && x < 20) // prevent missing subs on pts reset
- subpts_s = d_sub->pts;
- else
- subpts_s = curpts_s;
- }
if (subpts_s > curpts_s) {
mp_dbg(MSGT_CPLAYER, MSGL_DBG2,
"Sub early: c_pts=%5.3f s_pts=%5.3f\n",
@@ -1816,19 +1768,15 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
if (!sub_accept_packets_in_advance(dec_sub))
break;
// Try to avoid demuxing whole file at once
- if (non_interleaved && subpts_s > curpts_s + 1)
+ if (subpts_s > curpts_s + 1 && !interleaved)
break;
}
- struct demux_packet pkt;
- struct demux_packet *orig = ds_get_packet_sub(d_sub);
- if (!orig)
- break;
- pkt = *orig;
- pkt.pts = subpts_s;
+ 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);
+ "duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration,
+ pkt->len);
+ sub_decode(dec_sub, pkt);
+ talloc_free(pkt);
}
}
@@ -1840,9 +1788,13 @@ 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;
+ if (frame_time < 0)
+ frame_time = mpctx->sh_video->fps > 0 ? 1.0 / mpctx->sh_video->fps : 0;
// we should avoid dropping too many frames in sequence unless we
// are too late. and we allow 100ms A-V delay here:
if (d < -mpctx->dropped_frames * frame_time - 0.100 && !mpctx->paused
@@ -1933,21 +1885,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_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);
- 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;
@@ -2234,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;
@@ -2259,7 +2199,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;
}
@@ -2357,25 +2297,18 @@ int reinit_video_chain(struct MPContext *mpctx)
goto no_video;
}
- if (!video_read_properties(mpctx->sh_video)) {
- mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Video: Cannot read properties.\n");
- goto err_out;
- } else {
- mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X "
- "size:%dx%d fps:%5.3f ftime:=%6.4f\n",
- mpctx->master_demuxer->file_format, mpctx->sh_video->format,
- mpctx->sh_video->disp_w, mpctx->sh_video->disp_h,
- mpctx->sh_video->fps, mpctx->sh_video->frametime);
- if (opts->force_fps) {
- mpctx->sh_video->fps = opts->force_fps;
- mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps;
- }
- update_fps(mpctx);
+ mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] fourcc:0x%X "
+ "size:%dx%d fps:%5.3f\n",
+ mpctx->sh_video->format,
+ mpctx->sh_video->disp_w, mpctx->sh_video->disp_h,
+ mpctx->sh_video->fps);
+ if (opts->force_fps)
+ mpctx->sh_video->fps = opts->force_fps;
+ update_fps(mpctx);
- if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) {
- mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "FPS not specified in the "
- "header or invalid, use the -fps option.\n");
- }
+ if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) {
+ mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "FPS not specified in the "
+ "header or invalid, use the -fps option.\n");
}
double ar = -1.0;
@@ -2397,7 +2330,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;
@@ -2421,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++;
@@ -2433,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;
}
@@ -2484,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;
@@ -2493,26 +2437,57 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame)
filter_output_queued_frame(mpctx);
}
+
+static struct demux_packet *video_read_frame(struct MPContext *mpctx)
+{
+ sh_video_t *sh_video = mpctx->sh_video;
+ 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->fps > 0 ? 1.0f / sh_video->fps : 0;
+
+ // 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 ? sh_video->last_pts - pts1
+ : next_pts - sh_video->last_pts;
+ if (d >= 0) {
+ if (demuxer->type == DEMUXER_TYPE_TV) {
+ if (d > 0)
+ sh_video->fps = 1.0f / d;
+ frame_time = d;
+ } else {
+ if ((int)sh_video->fps <= 1)
+ frame_time = d;
+ }
+ }
+ }
+
+ sh_video->pts = sh_video->last_pts;
+ sh_video->next_frame_time = frame_time;
+ return pkt;
+}
+
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;
- 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, &sh_video->next_frame_time,
- &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;
@@ -2520,13 +2495,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);
}
@@ -2535,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;
@@ -2543,7 +2531,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
@@ -2575,22 +2563,24 @@ 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 = 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;
@@ -2599,14 +2589,15 @@ static double update_video(struct MPContext *mpctx, double endpts)
if (pts >= mpctx->hrseek_pts - .005)
mpctx->hrseek_framedrop = false;
int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ?
- 1 : check_framedrop(mpctx, sh_video->frametime);
+ 1 : check_framedrop(mpctx, -1);
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);
} else if (!pkt) {
- if (vo_get_buffered_frame(video_out, true) < 0)
+ if (!load_next_vo_frame(mpctx, true))
return -1;
}
break;
@@ -2616,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
@@ -2754,13 +2747,10 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac)
vf_chain_seek_reset(mpctx->sh_video->vfilter);
mpctx->sh_video->num_buffered_pts = 0;
mpctx->sh_video->last_pts = MP_NOPTS_VALUE;
+ mpctx->sh_video->pts = MP_NOPTS_VALUE;
+ mpctx->video_pts = MP_NOPTS_VALUE;
mpctx->delay = 0;
mpctx->time_frame = 0;
- // 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->video_pts = mpctx->sh_video->pts;
}
if (mpctx->sh_audio && reset_ac) {
@@ -3039,17 +3029,7 @@ double get_time_length(struct MPContext *mpctx)
if (len >= 0)
return len;
- struct sh_video *sh_video = mpctx->sh_video;
- struct sh_audio *sh_audio = mpctx->sh_audio;
- if (sh_video && sh_video->i_bps && sh_audio && sh_audio->i_bps)
- return (double) (demuxer->movi_end - demuxer->movi_start) /
- (sh_video->i_bps + sh_audio->i_bps);
- if (sh_video && sh_video->i_bps)
- return (double) (demuxer->movi_end - demuxer->movi_start) /
- sh_video->i_bps;
- if (sh_audio && sh_audio->i_bps)
- return (double) (demuxer->movi_end - demuxer->movi_start) /
- sh_audio->i_bps;
+ // Unknown
return 0;
}
@@ -3497,10 +3477,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);
}
@@ -3512,6 +3494,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))) {
@@ -3888,31 +3872,21 @@ 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,
opts->stream_cache_def_size,
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, &params);
+ demux_open(stream, demuxer_name, &params, &mpctx->opts);
if (!demuxer) {
free_stream(stream);
goto err_out;
@@ -3930,6 +3904,7 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename,
}
if (!first) {
free_demuxer(demuxer);
+ free_stream(stream);
mp_msg(MSGT_CPLAYER, MSGL_WARN, "No streams added from file %s.\n",
disp_filename);
goto err_out;
@@ -4171,36 +4146,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]) {
@@ -4228,9 +4180,7 @@ 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->demuxer = demux_open(mpctx->stream, NULL, NULL, opts);
mpctx->master_demuxer = mpctx->demuxer;
if (!mpctx->demuxer) {
@@ -4275,9 +4225,9 @@ goto_reopen_demuxer: ;
// Decide correct-pts mode based on first segment of video track
opts->correct_pts = opts->user_correct_pts;
if (opts->correct_pts < 0) {
- opts->correct_pts =
- demux_control(mpctx->demuxer, DEMUXER_CTRL_CORRECT_PTS,
- NULL) == DEMUXER_CTRL_OK;
+ int val = 1;
+ demux_control(mpctx->demuxer, DEMUXER_CTRL_CORRECT_PTS, &val);
+ opts->correct_pts = val;
}
mpctx->initialized_flags |= INITIALIZED_DEMUXER;
@@ -4317,21 +4267,10 @@ goto_reopen_demuxer: ;
//================ SETUP STREAMS ==========================
- if (mpctx->sh_video) {
- if (!opts->ignore_start)
- mpctx->audio_delay += mpctx->sh_video->stream_delay;
- }
- if (mpctx->sh_audio) {
- if (!opts->ignore_start)
- mpctx->audio_delay -= mpctx->sh_audio->stream_delay;
- }
-
if (opts->force_fps && mpctx->sh_video) {
mpctx->sh_video->fps = opts->force_fps;
- mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps;
mp_tmsg(MSGT_CPLAYER, MSGL_INFO,
- "FPS forced to be %5.3f (ftime: %5.3f).\n",
- mpctx->sh_video->fps, mpctx->sh_video->frametime);
+ "FPS forced to be %5.3f.\n", mpctx->sh_video->fps);
}
//==================== START PLAYING =======================
diff --git a/core/options.c b/core/options.c
index 68d4c2ce52..c28817db68 100644
--- a/core/options.c
+++ b/core/options.c
@@ -25,6 +25,7 @@
#include <stddef.h>
#include <sys/types.h>
+#include <limits.h>
#include "core/options.h"
#include "config.h"
@@ -372,12 +373,9 @@ const m_option_t mp_opts[] = {
OPT_FLAG("pause", pause, 0),
OPT_FLAG("keep-open", keep_open, 0),
- // AVI specific: force non-interleaved mode
- {"avi-ni", &force_ni, CONF_TYPE_FLAG, 0, 0, 1, NULL},
-
// AVI and Ogg only: (re)build index at startup
- {"idx", &index_mode, CONF_TYPE_FLAG, 0, -1, 1, NULL},
- {"forceidx", &index_mode, CONF_TYPE_FLAG, 0, -1, 2, NULL},
+ OPT_FLAG_CONSTANTS("idx", index_mode, 0, -1, 1),
+ OPT_FLAG_STORE("forceidx", index_mode, 0, 2),
// select audio/video/subtitle stream
OPT_TRACKCHOICE("aid", audio_id),
@@ -404,7 +402,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
@@ -422,9 +419,6 @@ const m_option_t mp_opts[] = {
// ------------------------- a-v sync options --------------------
- // AVI specific: A-V sync mode (bps vs. interleaving)
- {"bps", &pts_from_bps, CONF_TYPE_FLAG, 0, 0, 1, NULL},
-
// set A-V sync correction speed (0=disables it):
OPT_FLOATRANGE("mc", default_max_pts_correction, 0, 0, 100),
@@ -438,9 +432,6 @@ const m_option_t mp_opts[] = {
// set a-v distance
OPT_FLOATRANGE("audio-delay", audio_delay, 0, -100.0, 100.0),
- // ignore header-specified delay (dwStart)
- OPT_FLAG("ignore-start", ignore_start, 0),
-
// ------------------------- codec/vfilter options --------------------
{"af*", &af_cfg.list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
@@ -788,7 +779,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.,
@@ -807,6 +797,8 @@ const struct MPOpts mp_default_opts = {
.hwdec_codecs = "all",
+ .index_mode = -1,
+
.ad_lavc_param = {
.ac3drc = 1.,
.downmix = 1,
diff --git a/core/options.h b/core/options.h
index 28932693ed..d7c3bd715e 100644
--- a/core/options.h
+++ b/core/options.h
@@ -106,7 +106,6 @@ typedef struct MPOpts {
float hr_seek_demuxer_offset;
float audio_delay;
float default_max_pts_correction;
- int ignore_start;
int autosync;
int softsleep;
int frame_dropping;
@@ -154,13 +153,13 @@ 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;
char *screenshot_template;
double force_fps;
+ int index_mode; // -1=untouched 0=don't use index 1=use (generate) index
struct mp_chmap audio_output_channels;
int audio_output_format;
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 d9160e0b8e..1953f46116 100644
--- a/core/timeline/tl_cue.c
+++ b/core/timeline/tl_cue.c
@@ -188,15 +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,
- mpctx->opts.audio_id,
- mpctx->opts.video_id,
- mpctx->opts.sub_id,
- 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
@@ -205,11 +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,
- mpctx->opts.audio_id,
- mpctx->opts.video_id,
- mpctx->opts.sub_id,
- 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 5ec04ac716..6096d03b6a 100644
--- a/core/timeline/tl_edl.c
+++ b/core/timeline/tl_edl.c
@@ -354,16 +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,
- mpctx->opts.audio_id,
- mpctx->opts.video_id,
- mpctx->opts.sub_id,
- 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 098c02fd9f..7c100618a3 100644
--- a/core/timeline/tl_matroska.c
+++ b/core/timeline/tl_matroska.c
@@ -113,14 +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, mpctx->opts.audio_id,
- mpctx->opts.video_id, mpctx->opts.sub_id, filename, params);
-}
-
static int enable_cache(struct MPContext *mpctx, struct stream **stream,
struct demuxer **demuxer, struct demuxer_params *params)
{
@@ -133,8 +125,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;
@@ -146,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);
@@ -168,17 +159,16 @@ 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, &params);
+ struct demuxer *d = demux_open(s, "mkv", &params, &mpctx->opts);
if (!d) {
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/asf.h b/demux/asf.h
deleted file mode 100644
index db48f72edb..0000000000
--- a/demux/asf.h
+++ /dev/null
@@ -1,251 +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.
- */
-
-#ifndef MPLAYER_ASF_H
-#define MPLAYER_ASF_H
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-///////////////////////
-// ASF Object Header
-///////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t guid[16];
- uint64_t size;
-} ASF_obj_header_t;
-
-////////////////
-// ASF Header
-////////////////
-typedef struct __attribute__((packed)) {
- ASF_obj_header_t objh;
- uint32_t cno; // number of subchunks
- uint8_t v1; // unknown (0x01)
- uint8_t v2; // unknown (0x02)
-} ASF_header_t;
-
-/////////////////////
-// ASF File Header
-/////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t stream_id[16]; // stream GUID
- uint64_t file_size;
- uint64_t creation_time; //File creation time FILETIME 8
- uint64_t num_packets; //Number of packets UINT64 8
- uint64_t play_duration; //Timestamp of the end position UINT64 8
- uint64_t send_duration; //Duration of the playback UINT64 8
- uint64_t preroll; //Time to bufferize before playing UINT64 8
- uint32_t flags; //Unknown, maybe flags ( usually contains 2 ) UINT32 4
- uint32_t min_packet_size; //Min size of the packet, in bytes UINT32 4
- uint32_t max_packet_size; //Max size of the packet UINT32 4
- uint32_t max_bitrate; //Maximum bitrate of the media (sum of all the stream)
-} ASF_file_header_t;
-
-///////////////////////
-// ASF Stream Header
-///////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t type[16]; // Stream type (audio/video) GUID 16
- uint8_t concealment[16]; // Audio error concealment type GUID 16
- uint64_t unk1; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8
- uint32_t type_size; //Total size of type-specific data UINT32 4
- uint32_t stream_size; //Size of stream-specific data UINT32 4
- uint16_t stream_no; //Stream number UINT16 2
- uint32_t unk2; //Unknown UINT32 4
-} ASF_stream_header_t;
-
-///////////////////////////
-// ASF Content Description
-///////////////////////////
-typedef struct __attribute__((packed)) {
- uint16_t title_size;
- uint16_t author_size;
- uint16_t copyright_size;
- uint16_t comment_size;
- uint16_t rating_size;
-} ASF_content_description_t;
-
-////////////////////////
-// ASF Segment Header
-////////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t streamno;
- uint8_t seq;
- uint32_t x;
- uint8_t flag;
-} ASF_segmhdr_t;
-
-//////////////////////
-// ASF Stream Chunck
-//////////////////////
-typedef struct __attribute__((packed)) {
- uint16_t type;
- uint16_t size;
- uint32_t sequence_number;
- uint16_t unknown;
- uint16_t size_confirm;
-} ASF_stream_chunck_t;
-
-// Definition of the stream type
-#if BYTE_ORDER == BIG_ENDIAN
- #define ASF_STREAMING_CLEAR 0x2443 // $C
- #define ASF_STREAMING_DATA 0x2444 // $D
- #define ASF_STREAMING_END_TRANS 0x2445 // $E
- #define ASF_STREAMING_HEADER 0x2448 // $H
-#else
- #define ASF_STREAMING_CLEAR 0x4324 // $C
- #define ASF_STREAMING_DATA 0x4424 // $D
- #define ASF_STREAMING_END_TRANS 0x4524 // $E
- #define ASF_STREAMING_HEADER 0x4824 // $H
-#endif
-
-// Definition of the differents type of ASF streaming
-typedef enum {
- ASF_Unknown_e,
- ASF_Live_e,
- ASF_Prerecorded_e,
- ASF_Redirector_e,
- ASF_PlainText_e,
- ASF_Authenticate_e
-} ASF_StreamType_e;
-
-typedef struct {
- ASF_StreamType_e streaming_type;
- int request;
- int packet_size;
- int *audio_streams,n_audio,*video_streams,n_video;
- int audio_id, video_id;
-} asf_http_streaming_ctrl_t;
-
-
-/*
- * Some macros to swap little endian structures read from an ASF file
- * into machine endian format
- */
-#if BYTE_ORDER == BIG_ENDIAN
-#define le2me_ASF_obj_header_t(h) { \
- (h)->size = le2me_64((h)->size); \
-}
-#define le2me_ASF_header_t(h) { \
- le2me_ASF_obj_header_t(&(h)->objh); \
- (h)->cno = le2me_32((h)->cno); \
-}
-#define le2me_ASF_stream_header_t(h) { \
- (h)->unk1 = le2me_64((h)->unk1); \
- (h)->type_size = le2me_32((h)->type_size); \
- (h)->stream_size = le2me_32((h)->stream_size); \
- (h)->stream_no = le2me_16((h)->stream_no); \
- (h)->unk2 = le2me_32((h)->unk2); \
-}
-#define le2me_ASF_file_header_t(h) { \
- (h)->file_size = le2me_64((h)->file_size); \
- (h)->creation_time = le2me_64((h)->creation_time); \
- (h)->num_packets = le2me_64((h)->num_packets); \
- (h)->play_duration = le2me_64((h)->play_duration); \
- (h)->send_duration = le2me_64((h)->send_duration); \
- (h)->preroll = le2me_64((h)->preroll); \
- (h)->flags = le2me_32((h)->flags); \
- (h)->min_packet_size = le2me_32((h)->min_packet_size); \
- (h)->max_packet_size = le2me_32((h)->max_packet_size); \
- (h)->max_bitrate = le2me_32((h)->max_bitrate); \
-}
-#define le2me_ASF_content_description_t(h) { \
- (h)->title_size = le2me_16((h)->title_size); \
- (h)->author_size = le2me_16((h)->author_size); \
- (h)->copyright_size = le2me_16((h)->copyright_size); \
- (h)->comment_size = le2me_16((h)->comment_size); \
- (h)->rating_size = le2me_16((h)->rating_size); \
-}
-#define le2me_BITMAPINFOHEADER(h) { \
- (h)->biSize = le2me_32((h)->biSize); \
- (h)->biWidth = le2me_32((h)->biWidth); \
- (h)->biHeight = le2me_32((h)->biHeight); \
- (h)->biPlanes = le2me_16((h)->biPlanes); \
- (h)->biBitCount = le2me_16((h)->biBitCount); \
- (h)->biCompression = le2me_32((h)->biCompression); \
- (h)->biSizeImage = le2me_32((h)->biSizeImage); \
- (h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
- (h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
- (h)->biClrUsed = le2me_32((h)->biClrUsed); \
- (h)->biClrImportant = le2me_32((h)->biClrImportant); \
-}
-#define le2me_WAVEFORMATEX(h) { \
- (h)->wFormatTag = le2me_16((h)->wFormatTag); \
- (h)->nChannels = le2me_16((h)->nChannels); \
- (h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
- (h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
- (h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
- (h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
- (h)->cbSize = le2me_16((h)->cbSize); \
-}
-#define le2me_ASF_stream_chunck_t(h) { \
- (h)->size = le2me_16((h)->size); \
- (h)->sequence_number = le2me_32((h)->sequence_number); \
- (h)->unknown = le2me_16((h)->unknown); \
- (h)->size_confirm = le2me_16((h)->size_confirm); \
-}
-#else
-#define le2me_ASF_obj_header_t(h) /**/
-#define le2me_ASF_header_t(h) /**/
-#define le2me_ASF_stream_header_t(h) /**/
-#define le2me_ASF_file_header_t(h) /**/
-#define le2me_ASF_content_description_t(h) /**/
-#define le2me_BITMAPINFOHEADER(h) /**/
-#define le2me_WAVEFORMATEX(h) /**/
-#define le2me_ASF_stream_chunck_t(h) /**/
-#endif
-
-// priv struct for the demuxer
-struct asf_priv {
- ASF_header_t header;
- unsigned char* packet;
- int scrambling_h;
- int scrambling_w;
- int scrambling_b;
- unsigned packetsize;
- double packetrate;
- double movielength;
- int asf_is_dvr_ms;
- uint32_t asf_frame_state;
- int asf_frame_start_found;
- double dvr_last_vid_pts;
- uint64_t vid_frame_ct;
- uint64_t play_duration;
- uint64_t num_packets;
- int new_vid_frame_seg;
- int *vid_repdata_sizes;
- int *aud_repdata_sizes;
- int vid_repdata_count;
- int aud_repdata_count;
- uint64_t avg_vid_frame_time;
- uint64_t last_key_payload_time;
- uint64_t last_aud_pts;
- uint64_t last_aud_diff;
- int found_first_key_frame;
- uint32_t last_vid_seq;
- int vid_ext_timing_index;
- int aud_ext_timing_index;
- int vid_ext_frame_index;
- int know_frame_time;
- unsigned bps;
-};
-
-#endif /* MPLAYER_ASF_H */
diff --git a/demux/asfguid.h b/demux/asfguid.h
deleted file mode 100644
index e1dfed87d1..0000000000
--- a/demux/asfguid.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2001 Reimar Döffinger
- *
- * 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.
- */
-
-#ifndef MPLAYER_ASFGUID_H
-#define MPLAYER_ASFGUID_H
-
-#include <inttypes.h>
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-
-#define ASF_LOAD_GUID_PREFIX(guid) AV_RL32(guid)
-
-#define ASF_GUID_PREFIX_audio_stream 0xF8699E40
-#define ASF_GUID_PREFIX_video_stream 0xBC19EFC0
-#define ASF_GUID_PREFIX_audio_conceal_none 0x49f1a440
-#define ASF_GUID_PREFIX_audio_conceal_interleave 0xbfc3cd50
-#define ASF_GUID_PREFIX_header 0x75B22630
-#define ASF_GUID_PREFIX_data_chunk 0x75b22636
-#define ASF_GUID_PREFIX_index_chunk 0x33000890
-#define ASF_GUID_PREFIX_stream_header 0xB7DC0791
-#define ASF_GUID_PREFIX_header_2_0 0xD6E229D1
-#define ASF_GUID_PREFIX_file_header 0x8CABDCA1
-#define ASF_GUID_PREFIX_content_desc 0x75b22633
-#define ASF_GUID_PREFIX_stream_group 0x7bf875ce
-#define ASF_GUID_PREFIX_ext_audio_stream 0x31178C9D
-#define ASF_GUID_PREFIX_ext_stream_embed_stream_header 0x3AFB65E2
-#define ASF_GUID_PREFIX_dvr_ms_timing_rep_data 0xFD3CC02A
-#define ASF_GUID_PREFIX_dvr_ms_vid_frame_rep_data 0xDD6432CC
-
-/*
-const char asf_audio_stream_guid[16] = {0x40, 0x9e, 0x69, 0xf8,
- 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b};
-const char asf_video_stream_guid[16] = {0xc0, 0xef, 0x19, 0xbc,
- 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b};
-*/
-static const char asf_stream_header_guid[16] = {0x91, 0x07, 0xdc, 0xb7,
- 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65};
-static const char asf_file_header_guid[16] = {0xa1, 0xdc, 0xab, 0x8c,
- 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65};
-static const char asf_content_desc_guid[16] = {0x33, 0x26, 0xb2, 0x75,
- 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
-static const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b,
- 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2};
-static const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75,
- 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
-static const char asf_ext_stream_embed_stream_header[16] = {0xe2, 0x65, 0xfb, 0x3a,
- 0xef, 0x47, 0xf2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43};
-static const char asf_ext_stream_audio[16] = {0x9d, 0x8c, 0x17, 0x31,
- 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03};
-static const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14,
- 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A};
-static const char asf_metadata_header[16] = {0xea, 0xcb, 0xf8, 0xc5,
- 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca};
-static const char asf_content_encryption[16] = {0xfb, 0xb3, 0x11, 0x22,
- 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e};
-static const char asf_dvr_ms_timing_rep_data[16] = {0x2a, 0xc0, 0x3c,0xfd,
- 0xdb, 0x06, 0xfa, 0x4c, 0x80, 0x1c, 0x72, 0x12, 0xd3, 0x87, 0x45, 0xe4};
-static const char asf_dvr_ms_vid_frame_rep_data[16] = {0xcc, 0x32, 0x64, 0xdd,
- 0x29, 0xe2, 0xdb, 0x40, 0x80, 0xf6, 0xd2, 0x63, 0x28, 0xd2, 0x76, 0x1f};
-
-static int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len)
-{
- int i;
- for (i = cur_pos; i < buf_len - 19; i++) {
- if (memcmp(&buf[i], guid, 16) == 0)
- return i + 16 + 8; // point after guid + length
- }
- return -1;
-}
-
-#endif /* MPLAYER_ASFGUID_H */
diff --git a/demux/asfheader.c b/demux/asfheader.c
deleted file mode 100644
index e3f19840cd..0000000000
--- a/demux/asfheader.c
+++ /dev/null
@@ -1,721 +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.
- */
-
-// .asf fileformat docs from http://divx.euro.ru
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <libavutil/intreadwrite.h>
-#include <libavutil/common.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "aviprint.h"
-#include "demux.h"
-#include "stheader.h"
-
-#include "asf.h"
-#include "asfguid.h"
-#include "asfheader.h"
-
-typedef struct {
- // must be 0 for metadata record, might be non-zero for metadata lib record
- uint16_t lang_list_index;
- uint16_t stream_num;
- uint16_t name_length;
- uint16_t data_type;
- uint32_t data_length;
- uint16_t* name;
- void* data;
-} ASF_meta_record_t;
-
-static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen)
-{
- char* outbuf = calloc(inlen, 2);
- char* q;
- int i;
-
- if (!outbuf) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "Memory allocation failed.\n");
- return NULL;
- }
- q = outbuf;
- for (i = 0; i < inlen / 2; i++) {
- uint8_t tmp;
- PUT_UTF8(AV_RL16(&inbuf[i]), tmp, *q++ = tmp;)
- }
- return outbuf;
-}
-
-static const char* asf_chunk_type(unsigned char* guid) {
- static char tmp[60];
- char *p;
- int i;
-
- switch(ASF_LOAD_GUID_PREFIX(guid)){
- case ASF_GUID_PREFIX_audio_stream:
- return "guid_audio_stream";
- case ASF_GUID_PREFIX_ext_audio_stream:
- return "guid_ext_audio_stream";
- case ASF_GUID_PREFIX_ext_stream_embed_stream_header:
- return "guid_ext_stream_embed_stream_header";
- case ASF_GUID_PREFIX_video_stream:
- return "guid_video_stream";
- case ASF_GUID_PREFIX_audio_conceal_none:
- return "guid_audio_conceal_none";
- case ASF_GUID_PREFIX_audio_conceal_interleave:
- return "guid_audio_conceal_interleave";
- case ASF_GUID_PREFIX_header:
- return "guid_header";
- case ASF_GUID_PREFIX_data_chunk:
- return "guid_data_chunk";
- case ASF_GUID_PREFIX_index_chunk:
- return "guid_index_chunk";
- case ASF_GUID_PREFIX_stream_header:
- return "guid_stream_header";
- case ASF_GUID_PREFIX_header_2_0:
- return "guid_header_2_0";
- case ASF_GUID_PREFIX_file_header:
- return "guid_file_header";
- case ASF_GUID_PREFIX_content_desc:
- return "guid_content_desc";
- case ASF_GUID_PREFIX_dvr_ms_timing_rep_data:
- return "guid_dvr_ms_timing_rep_data";
- case ASF_GUID_PREFIX_dvr_ms_vid_frame_rep_data:
- return "guid_dvr_ms_vid_frame_rep_data";
- default:
- strcpy(tmp, "unknown guid ");
- p = tmp + strlen(tmp);
- for (i = 0; i < 16; i++) {
- if ((1 << i) & ((1<<4) | (1<<6) | (1<<8))) *p++ = '-';
- sprintf(p, "%02x", guid[i]);
- p += 2;
- }
- return tmp;
- }
-}
-
-int asf_check_header(demuxer_t *demuxer){
- unsigned char asfhdrguid[16]={0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
- struct asf_priv* asf = calloc(1,sizeof(*asf));
- asf->scrambling_h=asf->scrambling_w=asf->scrambling_b=1;
- stream_read(demuxer->stream,(char*) &asf->header,sizeof(asf->header)); // header obj
- le2me_ASF_header_t(&asf->header); // swap to machine endian
-// for(i=0;i<16;i++) printf(" %02X",temp[i]);printf("\n");
-// for(i=0;i<16;i++) printf(" %02X",asfhdrguid[i]);printf("\n");
- if(memcmp(asfhdrguid,asf->header.objh.guid,16)){
- mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: not ASF guid!\n");
- free(asf);
- return 0; // not ASF guid
- }
- if(asf->header.cno>256){
- mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: invalid subchunks_no %d\n",(int) asf->header.cno);
- free(asf);
- return 0; // invalid header???
- }
- demuxer->priv = asf;
- return DEMUXER_TYPE_ASF;
-}
-
-static int get_ext_stream_properties(char *buf, int buf_len, int stream_num, struct asf_priv* asf, int is_video)
-{
- int pos=0;
- uint8_t *buffer = &buf[0];
- uint64_t avg_ft av_unused;
- unsigned bitrate;
-
- while ((pos = find_asf_guid(buf, asf_ext_stream_header, pos, buf_len)) >= 0) {
- int this_stream_num, stnamect, payct, i;
- int buf_max_index=pos+50;
- if (buf_max_index > buf_len) return 0;
- buffer = &buf[pos];
-
- // the following info is available
- // some of it may be useful but we're skipping it for now
- // starttime(8 bytes), endtime(8),
- // leak-datarate(4), bucket-datasize(4), init-bucket-fullness(4),
- // alt-leak-datarate(4), alt-bucket-datasize(4), alt-init-bucket-fullness(4),
- // max-object-size(4),
- // flags(4) (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
-
- buffer += 8+8;
- bitrate = AV_RL32(buffer);
- buffer += 8*4;
- this_stream_num=AV_RL16(buffer);buffer+=2;
-
- if (this_stream_num == stream_num) {
- buf_max_index+=14;
- if (buf_max_index > buf_len) return 0;
- buffer+=2; //skip stream-language-id-index
- avg_ft = AV_RL64(buffer); // provided in 100ns units
- buffer+=8;
- asf->bps = bitrate / 8;
-
- // after this are values for stream-name-count and
- // payload-extension-system-count
- // followed by associated info for each
- stnamect = AV_RL16(buffer);buffer+=2;
- payct = AV_RL16(buffer);buffer+=2;
-
- // need to read stream names if present in order
- // to get lengths - values are ignored for now
- for (i=0; i<stnamect; i++) {
- int stream_name_len;
- buf_max_index+=4;
- if (buf_max_index > buf_len) return 0;
- buffer+=2; //language_id_index
- stream_name_len = AV_RL16(buffer);buffer+=2;
- buffer+=stream_name_len; //stream_name
- buf_max_index+=stream_name_len;
- if (buf_max_index > buf_len) return 0;
- }
-
- if (is_video) {
- asf->vid_repdata_count = payct;
- asf->vid_repdata_sizes = malloc(payct*sizeof(int));
- } else {
- asf->aud_repdata_count = payct;
- asf->aud_repdata_sizes = malloc(payct*sizeof(int));
- }
-
- for (i=0; i<payct; i++) {
- int payload_len;
- buf_max_index+=22;
- if (buf_max_index > buf_len) return 0;
- // Each payload extension definition starts with a GUID.
- // In dvr-ms files one of these indicates the presence an
- // extension that contains pts values and this is always present
- // in the video and audio streams.
- // Another GUID indicates the presence of an extension
- // that contains useful video frame demuxing information.
- // Note that the extension data in each packet does not contain
- // these GUIDs and that this header section defines the order the data
- // will appear in.
- if (memcmp(buffer, asf_dvr_ms_timing_rep_data, 16) == 0) {
- if (is_video)
- asf->vid_ext_timing_index = i;
- else
- asf->aud_ext_timing_index = i;
- } else if (is_video && memcmp(buffer, asf_dvr_ms_vid_frame_rep_data, 16) == 0)
- asf->vid_ext_frame_index = i;
- buffer+=16;
-
- payload_len = AV_RL16(buffer);buffer+=2;
-
- if (is_video)
- asf->vid_repdata_sizes[i] = payload_len;
- else
- asf->aud_repdata_sizes[i] = payload_len;
- buffer+=4;//sys_len
- }
-
- return 1;
- }
- }
- return 1;
-}
-
-#define CHECKDEC(l, n) if (((l) -= (n)) < 0) return 0
-static char* read_meta_record(ASF_meta_record_t* dest, char* buf,
- int* buf_len)
-{
- CHECKDEC(*buf_len, 2 + 2 + 2 + 2 + 4);
- dest->lang_list_index = AV_RL16(buf);
- dest->stream_num = AV_RL16(&buf[2]);
- dest->name_length = AV_RL16(&buf[4]);
- dest->data_type = AV_RL16(&buf[6]);
- dest->data_length = AV_RL32(&buf[8]);
- buf += 2 + 2 + 2 + 2 + 4;
- CHECKDEC(*buf_len, dest->name_length);
- dest->name = (uint16_t*)buf;
- buf += dest->name_length;
- CHECKDEC(*buf_len, dest->data_length);
- dest->data = buf;
- buf += dest->data_length;
- return buf;
-}
-
-static int get_meta(char *buf, int buf_len, int this_stream_num,
- float* asp_ratio)
-{
- int pos = 0;
- uint16_t records_count;
- uint16_t x = 0, y = 0;
-
- if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0)
- return 0;
-
- CHECKDEC(buf_len, pos);
- buf += pos;
- CHECKDEC(buf_len, 2);
- records_count = AV_RL16(buf);
- buf += 2;
-
- while (records_count--) {
- ASF_meta_record_t record_entry;
- char* name;
-
- if (!(buf = read_meta_record(&record_entry, buf, &buf_len)))
- return 0;
- /* reserved, must be zero */
- if (record_entry.lang_list_index)
- continue;
- /* match stream number: 0 to match all */
- if (record_entry.stream_num && record_entry.stream_num != this_stream_num)
- continue;
- if (!(name = get_ucs2str(record_entry.name, record_entry.name_length))) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "Memory allocation failed.\n");
- continue;
- }
- if (strcmp(name, "AspectRatioX") == 0)
- x = AV_RL16(record_entry.data);
- else if (strcmp(name, "AspectRatioY") == 0)
- y = AV_RL16(record_entry.data);
- free(name);
- }
- if (x && y) {
- *asp_ratio = (float)x / (float)y;
- return 1;
- }
- return 0;
-}
-
-static int is_drm(char* buf, int buf_len)
-{
- uint32_t data_len, type_len, key_len, url_len;
- int pos = find_asf_guid(buf, asf_content_encryption, 0, buf_len);
-
- if (pos < 0)
- return 0;
-
- CHECKDEC(buf_len, pos + 4);
- buf += pos;
- data_len = AV_RL32(buf);
- buf += 4;
- CHECKDEC(buf_len, data_len);
- buf += data_len;
- type_len = AV_RL32(buf);
- if (type_len < 4)
- return 0;
- CHECKDEC(buf_len, 4 + type_len + 4);
- buf += 4;
-
- if (buf[0] != 'D' || buf[1] != 'R' || buf[2] != 'M' || buf[3] != '\0')
- return 0;
-
- buf += type_len;
- key_len = AV_RL32(buf);
- CHECKDEC(buf_len, key_len + 4);
- buf += 4;
-
- buf[key_len - 1] = '\0';
- mp_msg(MSGT_HEADER, MSGL_V, "DRM Key ID: %s\n", buf);
-
- buf += key_len;
- url_len = AV_RL32(buf);
- CHECKDEC(buf_len, url_len);
- buf += 4;
-
- buf[url_len - 1] = '\0';
- mp_tmsg(MSGT_HEADER, MSGL_INFO, "DRM License URL: %s\n", buf);
- return 1;
-}
-
-static int asf_init_audio_stream(demuxer_t *demuxer,struct asf_priv* asf, sh_audio_t* sh_audio, ASF_stream_header_t *streamh, int *ppos, uint8_t** buf, char *hdr, unsigned int hdr_len)
-{
- uint8_t *buffer = *buf;
- int pos = *ppos;
-
- sh_audio->wf=calloc(FFMAX(streamh->type_size, sizeof(*sh_audio->wf)), 1);
- memcpy(sh_audio->wf,buffer,streamh->type_size);
- le2me_WAVEFORMATEX(sh_audio->wf);
- sh_audio->format=sh_audio->wf->wFormatTag;
- mp_set_audio_codec_from_tag(sh_audio);
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
- if(ASF_LOAD_GUID_PREFIX(streamh->concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){
- buffer = &hdr[pos];
- pos += streamh->stream_size;
- if (pos > hdr_len) return 0;
- asf->scrambling_h=buffer[0];
- asf->scrambling_w=(buffer[2]<<8)|buffer[1];
- asf->scrambling_b=(buffer[4]<<8)|buffer[3];
- if(asf->scrambling_b>0){
- asf->scrambling_w/=asf->scrambling_b;
- }
- } else {
- asf->scrambling_b=asf->scrambling_h=asf->scrambling_w=1;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf->scrambling_h,asf->scrambling_w,asf->scrambling_b);
- return 1;
-}
-
-static int find_backwards_asf_guid(char *buf, const char *guid, int cur_pos)
-{
- int i;
- for (i=cur_pos-16; i>0; i--) {
- if (memcmp(&buf[i], guid, 16) == 0)
- return i + 16 + 8; // point after guid + length
- }
- return -1;
-}
-
-int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
- int hdr_len = asf->header.objh.size - sizeof(asf->header);
- int hdr_skip = 0;
- char *hdr = NULL;
- char guid_buffer[16];
- int pos, start = stream_tell(demuxer->stream);
- uint32_t* streams = NULL;
- int audio_streams=0;
- int video_streams=0;
- uint16_t stream_count=0;
- int best_video = -1;
- int best_audio = -1;
- uint64_t data_len;
- ASF_stream_header_t *streamh;
- uint8_t *buffer;
- int audio_pos=0;
-
- if(hdr_len < 0) {
- mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n");
- return 0;
- }
-
- if (hdr_len > 1024 * 1024) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "FATAL: header size bigger than 1 MB (%d)!\nPlease contact MPlayer authors, and upload/send this file.\n",
- hdr_len);
- hdr_skip = hdr_len - 1024 * 1024;
- hdr_len = 1024 * 1024;
- }
- hdr = malloc(hdr_len);
- if (!hdr) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "Could not allocate %d bytes for header.\n",
- hdr_len);
- return 0;
- }
- stream_read(demuxer->stream, hdr, hdr_len);
- if (hdr_skip)
- stream_skip(demuxer->stream, hdr_skip);
- if (stream_eof(demuxer->stream)) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "EOF while reading ASF header, broken/incomplete file?\n");
- goto err_out;
- }
-
- if (is_drm(hdr, hdr_len))
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "This file has been encumbered with DRM encryption, it will not play in MPlayer!\n");
-
- if ((pos = find_asf_guid(hdr, asf_ext_stream_audio, 0, hdr_len)) >= 0)
- {
- // Special case: found GUID for dvr-ms audio.
- // Now skip back to associated stream header.
- int sh_pos=0;
-
- sh_pos = find_backwards_asf_guid(hdr, asf_stream_header_guid, pos);
-
- if (sh_pos > 0) {
- sh_audio_t *sh_audio;
-
- mp_msg(MSGT_HEADER, MSGL_V, "read_asf_header found dvr-ms audio stream header pos=%d\n", sh_pos);
- // found audio stream header - following code reads header and
- // initializes audio stream.
- audio_pos = pos - 16 - 8;
- streamh = (ASF_stream_header_t *)&hdr[sh_pos];
- le2me_ASF_stream_header_t(streamh);
- audio_pos += 64; //16+16+4+4+4+16+4;
- buffer = &hdr[audio_pos];
- sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
- sh_audio->needs_parsing = 1;
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "asfheader", streamh->stream_no & 0x7F);
- ++audio_streams;
- if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &audio_pos, &buffer, hdr, hdr_len))
- goto len_err_out;
- if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 0))
- goto len_err_out;
- }
- }
- // find stream headers
- // only reset pos if we didnt find dvr_ms audio stream
- // if we did find it then we want to avoid reading its header twice
- if (audio_pos == 0)
- pos = 0;
-
- while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0)
- {
- streamh = (ASF_stream_header_t *)&hdr[pos];
- pos += sizeof(ASF_stream_header_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_stream_header_t(streamh);
- mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n",
- asf_chunk_type(streamh->type));
- mp_msg(MSGT_HEADER, MSGL_V, "stream concealment: %s\n",
- asf_chunk_type(streamh->concealment));
- mp_msg(MSGT_HEADER, MSGL_V, "type: %d bytes, stream: %d bytes ID: %d\n",
- (int)streamh->type_size, (int)streamh->stream_size,
- (int)streamh->stream_no);
- mp_msg(MSGT_HEADER, MSGL_V, "unk1: %lX unk2: %X\n",
- (unsigned long)streamh->unk1, (unsigned int)streamh->unk2);
- mp_msg(MSGT_HEADER, MSGL_V, "FILEPOS=0x%X\n", pos + start);
- // type-specific data:
- buffer = &hdr[pos];
- pos += streamh->type_size;
- if (pos > hdr_len) goto len_err_out;
- switch(ASF_LOAD_GUID_PREFIX(streamh->type)){
- case ASF_GUID_PREFIX_audio_stream: {
- sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "asfheader", streamh->stream_no & 0x7F);
- ++audio_streams;
- if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &pos, &buffer, hdr, hdr_len))
- goto len_err_out;
- //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F;
- break;
- }
- case ASF_GUID_PREFIX_video_stream: {
- unsigned int len;
- float asp_ratio;
- sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "asfheader", streamh->stream_no & 0x7F);
- len=streamh->type_size-(4+4+1+2);
- ++video_streams;
-// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
- sh_video->bih=calloc((len<sizeof(*sh_video->bih))?sizeof(*sh_video->bih):len,1);
- memcpy(sh_video->bih,&buffer[4+4+1+2],len);
- le2me_BITMAPINFOHEADER(sh_video->bih);
- if (sh_video->bih->biSize > len && sh_video->bih->biSize > sizeof(*sh_video->bih))
- sh_video->bih->biSize = len;
- if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) {
- //mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "DVR will probably only work with libavformat, try -demuxer 35 if you have problems\n");
- //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- asf->asf_frame_state=-1;
- asf->asf_frame_start_found=0;
- asf->asf_is_dvr_ms=1;
- asf->dvr_last_vid_pts=0.0;
- } else asf->asf_is_dvr_ms=0;
- if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 1))
- goto len_err_out;
- if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) {
- sh_video->aspect = asp_ratio * sh_video->bih->biWidth /
- sh_video->bih->biHeight;
- }
- sh_video->i_bps = asf->bps;
- sh_video->format = sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- sh_video->format = mp_video_fourcc_alias(sh_video->format);
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
- //asf_video_id=streamh.stream_no & 0x7F;
- //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F;
- break;
- }
- }
- // stream-specific data:
- // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size);
- }
-
- // find file header
- pos = find_asf_guid(hdr, asf_file_header_guid, 0, hdr_len);
- if (pos >= 0) {
- ASF_file_header_t *fileh = (ASF_file_header_t *)&hdr[pos];
- pos += sizeof(ASF_file_header_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_file_header_t(fileh);
- mp_msg(MSGT_HEADER, MSGL_V, "ASF: packets: %d flags: %d "
- "max_packet_size: %d min_packet_size: %d max_bitrate: %d "
- "preroll: %d\n",
- (int)fileh->num_packets, (int)fileh->flags,
- (int)fileh->min_packet_size, (int)fileh->max_packet_size,
- (int)fileh->max_bitrate, (int)fileh->preroll);
- asf->packetsize=fileh->max_packet_size;
- asf->packet=malloc(asf->packetsize); // !!!
- asf->packetrate=fileh->max_bitrate/8.0/(double)asf->packetsize;
- asf->movielength=FFMAX(0.0, (fileh->play_duration / 10000.0 - fileh->preroll) / 1000.0);
- }
-
- // find content header
- pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len);
- if (pos >= 0) {
- ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos];
- char *string=NULL;
- uint16_t* wstring = NULL;
- uint16_t len;
- pos += sizeof(ASF_content_description_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_content_description_t(contenth);
- mp_msg(MSGT_HEADER,MSGL_V,"\n");
- // extract the title
- if((len = contenth->title_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Title: %s\n", string);
- demux_info_add(demuxer, "title", string);
- free(string);
- }
- }
- // extract the author
- if((len = contenth->author_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Author: %s\n", string);
- demux_info_add(demuxer, "author", string);
- free(string);
- }
- }
- // extract the copyright
- if((len = contenth->copyright_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Copyright: %s\n", string);
- demux_info_add(demuxer, "copyright", string);
- free(string);
- }
- }
- // extract the comment
- if((len = contenth->comment_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Comment: %s\n", string);
- demux_info_add(demuxer, "comments", string);
- free(string);
- }
- }
- // extract the rating
- if((len = contenth->rating_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Rating: %s\n", string);
- free(string);
- }
- }
- mp_msg(MSGT_HEADER,MSGL_V,"\n");
- }
-
- // find content header
- pos = find_asf_guid(hdr, asf_stream_group_guid, 0, hdr_len);
- if (pos >= 0) {
- int max_streams = (hdr_len - pos - 2) / 6;
- uint16_t stream_id, i;
- uint32_t max_bitrate;
- char *ptr = &hdr[pos];
- mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == START ===\n");
- if(max_streams <= 0) goto len_err_out;
- stream_count = AV_RL16(ptr);
- ptr += sizeof(uint16_t);
- if(stream_count > max_streams) stream_count = max_streams;
- if(stream_count > 0)
- streams = malloc(2*stream_count*sizeof(uint32_t));
- mp_msg(MSGT_HEADER,MSGL_V," stream count=[0x%x][%u]\n", stream_count, stream_count );
- for( i=0 ; i<stream_count ; i++ ) {
- stream_id = AV_RL16(ptr);
- ptr += sizeof(uint16_t);
- max_bitrate = AV_RL32(ptr);
- ptr += sizeof(uint32_t);
- mp_msg(MSGT_HEADER,MSGL_V," stream id=[0x%x][%u]\n", stream_id, stream_id );
- mp_msg(MSGT_HEADER,MSGL_V," max bitrate=[0x%x][%u]\n", max_bitrate, max_bitrate );
- streams[2*i] = stream_id;
- streams[2*i+1] = max_bitrate;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == END ===\n");
- }
- free(hdr);
- hdr = NULL;
- start = stream_tell(demuxer->stream); // start of first data chunk
- stream_read(demuxer->stream, guid_buffer, 16);
- if (memcmp(guid_buffer, asf_data_chunk_guid, 16) != 0) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "No data chunk following header!\n");
- free(streams);
- streams = NULL;
- return 0;
- }
- // read length of chunk
- data_len = stream_read_qword_le(demuxer->stream);
- demuxer->movi_start = stream_tell(demuxer->stream) + 26;
- demuxer->movi_end = start + data_len;
- mp_msg(MSGT_HEADER, MSGL_V, "Found movie at 0x%X - 0x%X\n",
- (int)demuxer->movi_start, (int)demuxer->movi_end);
-
-if(streams) {
- // stream selection is done in the network code, it shouldn't be done here
- // as the servers often do not care about what we requested.
-#if 0
- uint32_t vr = 0, ar = 0,i;
-#ifdef CONFIG_NETWORKING
- if( demuxer->stream->streaming_ctrl!=NULL ) {
- if( demuxer->stream->streaming_ctrl->bandwidth!=0 && demuxer->stream->streaming_ctrl->data!=NULL ) {
- best_audio = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->audio_id;
- best_video = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->video_id;
- }
- } else
-#endif
- for(i = 0; i < stream_count; i++) {
- uint32_t id = streams[2*i];
- uint32_t rate = streams[2*i+1];
- if(demuxer->v_streams[id] && rate > vr) {
- vr = rate;
- best_video = id;
- } else if(demuxer->a_streams[id] && rate > ar) {
- ar = rate;
- best_audio = id;
- }
- }
-#endif
- free(streams);
- streams = NULL;
-}
-
-mp_msg(MSGT_HEADER,MSGL_V,"ASF: %d audio and %d video streams found\n",audio_streams,video_streams);
-if(!audio_streams) demuxer->audio->id=-2; // nosound
-else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio;
-if(!video_streams){
- if(!audio_streams){
- mp_tmsg(MSGT_HEADER,MSGL_ERR,"ASF: no audio or video headers found - broken file?\n");
- return 0;
- }
- demuxer->video->id=-2; // audio-only
-} else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video;
-
-#if 0
-if( mp_msg_test(MSGT_HEADER,MSGL_V) ){
- printf("ASF duration: %d\n",(int)fileh.duration);
- printf("ASF start pts: %d\n",(int)fileh.start_timestamp);
- printf("ASF end pts: %d\n",(int)fileh.end_timestamp);
-}
-#endif
-
-return 1;
-
-len_err_out:
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "Invalid length in ASF header!\n");
-err_out:
- free(hdr);
- free(streams);
- return 0;
-}
diff --git a/demux/asfheader.h b/demux/asfheader.h
deleted file mode 100644
index 3741f22cd6..0000000000
--- a/demux/asfheader.h
+++ /dev/null
@@ -1,28 +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.
- */
-
-#ifndef MPLAYER_ASFHEADER_H
-#define MPLAYER_ASFHEADER_H
-
-#include "asf.h"
-#include "demux.h"
-
-int asf_check_header(demuxer_t *demuxer);
-int read_asf_header(demuxer_t *demuxer, struct asf_priv *asf);
-
-#endif /* MPLAYER_ASFHEADER_H */
diff --git a/demux/aviheader.c b/demux/aviheader.c
deleted file mode 100644
index c1b9c59692..0000000000
--- a/demux/aviheader.c
+++ /dev/null
@@ -1,674 +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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <libavutil/common.h>
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "aviprint.h"
-#include "aviheader.h"
-
-static MainAVIHeader avih;
-
-static int odml_get_vstream_id(int id, unsigned char res[])
-{
- if ((char)(id >> 16) == 'd') {
- if (res) {
- res[0] = id;
- res[1] = id >> 8;
- }
- return 1;
- }
- return 0;
-}
-
-static int avi_idx_cmp(const void *elem1, const void *elem2)
-{
- register int64_t a = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem1);
- register int64_t b = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem2);
- return (a > b) - (b > a);
-}
-
-void read_avi_header(demuxer_t *demuxer,int index_mode){
-sh_audio_t *sh_audio=NULL;
-sh_video_t *sh_video=NULL;
-int stream_id=-1;
-int idxfix_videostream=0;
-int idxfix_divx=0;
-avi_priv_t* priv=demuxer->priv;
-int64_t list_end=0;
-
-//---- AVI header:
-priv->idx_size=0;
-priv->audio_streams=0;
-while(1){
- int id=stream_read_dword_le(demuxer->stream);
- unsigned chunksize,size2;
- static int last_fccType=0;
- static int last_fccHandler=0;
- char* hdr=NULL;
- //
- if(stream_eof(demuxer->stream)) break;
- //
- if(id==mmioFOURCC('L','I','S','T')){
- unsigned len=stream_read_dword_le(demuxer->stream); // list size
- id=stream_read_dword_le(demuxer->stream); // list type
- mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%u\n",(char *) &id,len);
- if(len >= 4) {
- len -= 4;
- list_end=stream_tell(demuxer->stream)+((len+1)&(~1));
- } else {
- mp_tmsg(MSGT_HEADER,MSGL_WARN,"** empty list?!\n");
- list_end = 0;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"list_end=0x%X\n",(int)list_end);
- if(id==listtypeAVIMOVIE){
- // found MOVI header
- if(!demuxer->movi_start) demuxer->movi_start=stream_tell(demuxer->stream);
- demuxer->movi_end=stream_tell(demuxer->stream)+len;
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);
- if(demuxer->stream->end_pos>demuxer->movi_end) demuxer->movi_end=demuxer->stream->end_pos;
- if(index_mode==-2 || index_mode==2 || index_mode==0)
- break; // reading from non-seekable source (stdin) or forced index or no index forced
- if(list_end>0) stream_seek(demuxer->stream,list_end); // skip movi
- list_end=0;
- }
- continue;
- }
- size2=stream_read_dword_le(demuxer->stream);
- mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%u\n",(char *) &id,size2);
- chunksize=(size2+1)&(~1);
- switch(id){
-
- // Indicates where the subject of the file is archived
- case mmioFOURCC('I','A','R','L'): hdr="Archival Location";break;
- // Lists the artist of the original subject of the file;
- // for example, "Michaelangelo."
- case mmioFOURCC('I','A','R','T'): hdr="Artist";break;
- // Lists the name of the person or organization that commissioned
- // the subject of the file; for example "Pope Julian II."
- case mmioFOURCC('I','C','M','S'): hdr="Commissioned";break;
- // Provides general comments about the file or the subject
- // of the file. If the comment is several sentences long, end each
- // sentence with a period. Do not include new-line characters.
- case mmioFOURCC('I','C','M','T'): hdr="Comments";break;
- // Records the copyright information for the file; for example,
- // "Copyright Encyclopedia International 1991." If there are multiple
- // copyrights, separate them by semicolon followed by a space.
- case mmioFOURCC('I','C','O','P'): hdr="Copyright";break;
- // Describes whether an image has been cropped and, if so, how it
- // was cropped; for example, "lower-right corner."
- case mmioFOURCC('I','C','R','D'): hdr="Creation Date";break;
- // Describes whether an image has been cropped and, if so, how it
- // was cropped; for example, "lower-right corner."
- case mmioFOURCC('I','C','R','P'): hdr="Cropped";break;
- // Specifies the size of the original subject of the file; for
- // example, "8.5 in h, 11 in w."
- case mmioFOURCC('I','D','I','M'): hdr="Dimensions";break;
- // Stores dots per inch setting of the digitizer used to
- // produce the file, such as "300."
- case mmioFOURCC('I','D','P','I'): hdr="Dots Per Inch";break;
- // Stores the of the engineer who worked on the file. If there are
- // multiple engineers, separate the names by a semicolon and a blank;
- // for example, "Smith, John; Adams, Joe."
- case mmioFOURCC('I','E','N','G'): hdr="Engineer";break;
- // Describes the original work, such as "landscape,", "portrait,"
- // "still liefe," etc.
- case mmioFOURCC('I','G','N','R'): hdr="Genre";break;
- // Provides a list of keywords that refer to the file or subject of the
- // file. Separate multiple keywords with a semicolon and a blank;
- // for example, "Seattle, aerial view; scenery."
- case mmioFOURCC('I','K','E','Y'): hdr="Keywords";break;
- // ILGT - Describes the changes in the lightness settings on the digitizer
- // required to produce the file. Note that the format of this information
- // depends on the hardware used.
- case mmioFOURCC('I','L','G','T'): hdr="Lightness";break;
- // IMED - Decribes the original subject of the file, such as
- // "computer image," "drawing," "lithograph," and so on.
- case mmioFOURCC('I','M','E','D'): hdr="Medium";break;
- // INAM - Stores the title of the subject of the file, such as
- // "Seattle from Above."
- case mmioFOURCC('I','N','A','M'): hdr="Title";break;
- // IPLT - Specifies the number of colors requested when digitizing
- // an image, such as "256."
- case mmioFOURCC('I','P','L','T'): hdr="Palette Setting";break;
- // IPRD - Specifies the name of title the file was originally intended
- // for, such as "Encyclopedia of Pacific Northwest Geography."
- case mmioFOURCC('I','P','R','D'): hdr="Product";break;
- // ISBJ - Decsribes the contents of the file, such as
- // "Aerial view of Seattle."
- case mmioFOURCC('I','S','B','J'): hdr="Subject";break;
- // ISFT - Identifies the name of the software packages used to create the
- // file, such as "Microsoft WaveEdit"
- case mmioFOURCC('I','S','F','T'): hdr="Software";break;
- // ISHP - Identifies the change in sharpness for the digitizer
- // required to produce the file (the format depends on the hardware used).
- case mmioFOURCC('I','S','H','P'): hdr="Sharpness";break;
- // ISRC - Identifies the name of the person or organization who
- // supplied the original subject of the file; for example, "Try Research."
- case mmioFOURCC('I','S','R','C'): hdr="Source";break;
- // ISRF - Identifies the original form of the material that was digitized,
- // such as "slide," "paper," "map," and so on. This is not necessarily
- // the same as IMED
- case mmioFOURCC('I','S','R','F'): hdr="Source Form";break;
- // ITCH - Identifies the technician who digitized the subject file;
- // for example, "Smith, John."
- case mmioFOURCC('I','T','C','H'): hdr="Technician";break;
- case mmioFOURCC('I','S','M','P'): hdr="Time Code";break;
- case mmioFOURCC('I','D','I','T'): hdr="Digitization Time";break;
-
- case ckidAVIMAINHDR: // read 'avih'
- stream_read(demuxer->stream,(char*) &avih,FFMIN(size2,sizeof(avih)));
- le2me_MainAVIHeader(&avih); // swap to machine endian
- chunksize-=FFMIN(size2,sizeof(avih));
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_avih(&avih,MSGL_V); // else print_avih_flags(&avih,MSGL_V);
- break;
- case ckidSTREAMHEADER: { // read 'strh'
- AVIStreamHeader h;
- stream_read(demuxer->stream,(char*) &h,FFMIN(size2,sizeof(h)));
- le2me_AVIStreamHeader(&h); // swap to machine endian
- chunksize-=FFMIN(size2,sizeof(h));
- ++stream_id;
- if(h.fccType==streamtypeVIDEO){
- sh_video=new_sh_video(demuxer,stream_id);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "aviheader", stream_id);
- memcpy(&sh_video->video,&h,sizeof(h));
- sh_video->stream_delay = (float)sh_video->video.dwStart * sh_video->video.dwScale/sh_video->video.dwRate;
- } else
- if(h.fccType==streamtypeAUDIO){
- sh_audio=new_sh_audio(demuxer,stream_id);
- 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;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_strh(&h,MSGL_V);
- break; }
- case mmioFOURCC('i', 'n', 'd', 'x'): {
- uint32_t i;
- avisuperindex_chunk *s;
-
- if(!index_mode) break;
-
- if(chunksize<=24){
- break;
- }
- priv->suidx_size++;
- priv->suidx = realloc_struct(priv->suidx, priv->suidx_size, sizeof (avisuperindex_chunk));
- s = &priv->suidx[priv->suidx_size-1];
-
- chunksize-=24;
- memcpy(s->fcc, "indx", 4);
- s->dwSize = size2;
- s->wLongsPerEntry = stream_read_word_le(demuxer->stream);
- s->bIndexSubType = stream_read_char(demuxer->stream);
- s->bIndexType = stream_read_char(demuxer->stream);
- s->nEntriesInUse = stream_read_dword_le(demuxer->stream);
- AV_WN32(s->dwChunkId, stream_read_dword_le(demuxer->stream));
- stream_read(demuxer->stream, (char *)s->dwReserved, 3*4);
- memset(s->dwReserved, 0, 3*4);
-
- print_avisuperindex_chunk(s,MSGL_V);
-
- // Check and fix this useless crap
- if(s->wLongsPerEntry != sizeof (avisuperindex_entry)/4) {
- mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk size: %u\n",s->wLongsPerEntry);
- s->wLongsPerEntry = sizeof(avisuperindex_entry)/4;
- }
- if( ((chunksize/4)/s->wLongsPerEntry) < s->nEntriesInUse){
- mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk\n");
- s->nEntriesInUse = (chunksize/4)/s->wLongsPerEntry;
- }
-
- s->aIndex = calloc(s->nEntriesInUse, sizeof (avisuperindex_entry));
- s->stdidx = calloc(s->nEntriesInUse, sizeof (avistdindex_chunk));
-
- // now the real index of indices
- for (i=0; i<s->nEntriesInUse; i++) {
- chunksize-=16;
- s->aIndex[i].qwOffset = stream_read_qword_le(demuxer->stream);
- s->aIndex[i].dwSize = stream_read_dword_le(demuxer->stream);
- s->aIndex[i].dwDuration = stream_read_dword_le(demuxer->stream);
- mp_msg (MSGT_HEADER, MSGL_V, "ODML (%.4s): [%d] 0x%016"PRIx64" 0x%04x %u\n",
- s->dwChunkId, i,
- (uint64_t)s->aIndex[i].qwOffset, s->aIndex[i].dwSize, s->aIndex[i].dwDuration);
- }
-
- break; }
- case ckidSTREAMFORMAT: { // read 'strf'
- if(last_fccType==streamtypeVIDEO){
- sh_video->bih=calloc(FFMAX(chunksize, sizeof(*sh_video->bih)), 1);
-// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found 'bih', %u bytes of %zu\n",chunksize,sizeof(*sh_video->bih));
- stream_read(demuxer->stream,(char*) sh_video->bih,chunksize);
- le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian
- if (sh_video->bih->biSize > chunksize && sh_video->bih->biSize > sizeof(*sh_video->bih))
- sh_video->bih->biSize = chunksize;
- // fixup MS-RLE header (seems to be broken for <256 color files)
- if(sh_video->bih->biCompression<=1 && sh_video->bih->biSize==40)
- sh_video->bih->biSize=chunksize;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih,MSGL_V);
- chunksize=0;
- sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- sh_video->format = sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- sh_video->format = mp_video_fourcc_alias(sh_video->format);
-// if(demuxer->video->id==-1) demuxer->video->id=stream_id;
- // IdxFix:
- idxfix_videostream=stream_id;
- switch(sh_video->bih->biCompression){
- case mmioFOURCC('M', 'P', 'G', '4'):
- case mmioFOURCC('m', 'p', 'g', '4'):
- case mmioFOURCC('D', 'I', 'V', '1'):
- idxfix_divx=3; // set index recovery mpeg4 flavour: msmpeg4v1
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for M$ mpg4v1 video.\n");
- break;
- case mmioFOURCC('D', 'I', 'V', '3'):
- case mmioFOURCC('d', 'i', 'v', '3'):
- case mmioFOURCC('D', 'I', 'V', '4'):
- case mmioFOURCC('d', 'i', 'v', '4'):
- case mmioFOURCC('D', 'I', 'V', '5'):
- case mmioFOURCC('d', 'i', 'v', '5'):
- case mmioFOURCC('D', 'I', 'V', '6'):
- case mmioFOURCC('d', 'i', 'v', '6'):
- case mmioFOURCC('M', 'P', '4', '3'):
- case mmioFOURCC('m', 'p', '4', '3'):
- case mmioFOURCC('M', 'P', '4', '2'):
- case mmioFOURCC('m', 'p', '4', '2'):
- case mmioFOURCC('D', 'I', 'V', '2'):
- case mmioFOURCC('A', 'P', '4', '1'):
- idxfix_divx=1; // set index recovery mpeg4 flavour: msmpeg4v3
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for DIVX3 video.\n");
- break;
- case mmioFOURCC('D', 'I', 'V', 'X'):
- case mmioFOURCC('d', 'i', 'v', 'x'):
- case mmioFOURCC('D', 'X', '5', '0'):
- case mmioFOURCC('X', 'V', 'I', 'D'):
- case mmioFOURCC('x', 'v', 'i', 'd'):
- case mmioFOURCC('F', 'M', 'P', '4'):
- case mmioFOURCC('f', 'm', 'p', '4'):
- idxfix_divx=2; // set index recovery mpeg4 flavour: generic mpeg4
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for MPEG-4 video.\n");
- break;
- }
- } else
- if(last_fccType==streamtypeAUDIO){
- unsigned wf_size = chunksize<sizeof(*sh_audio->wf)?sizeof(*sh_audio->wf):chunksize;
- sh_audio->wf=calloc(wf_size,1);
-// sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize);
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found 'wf', %d bytes of %zu\n",chunksize,sizeof(*sh_audio->wf));
- stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize);
- le2me_WAVEFORMATEX(sh_audio->wf);
- if (sh_audio->wf->cbSize != 0 &&
- wf_size < sizeof(*sh_audio->wf)+sh_audio->wf->cbSize) {
- sh_audio->wf=realloc(sh_audio->wf, sizeof(*sh_audio->wf)+sh_audio->wf->cbSize);
- }
- sh_audio->format=sh_audio->wf->wFormatTag;
- if (sh_audio->wf->wFormatTag == 0xfffe && sh_audio->wf->cbSize >= 22)
- sh_audio->format = le2me_16(((WAVEFORMATEXTENSIBLE *)sh_audio->wf)->SubFormat);
- if (sh_audio->format == 1 &&
- last_fccHandler == mmioFOURCC('A', 'x', 'a', 'n'))
- sh_audio->format = last_fccHandler;
- mp_set_audio_codec_from_tag(sh_audio);
- sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;
- chunksize=0;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
- ++priv->audio_streams;
-// if(demuxer->audio->id==-1) demuxer->audio->id=stream_id;
- }
- break;
- }
- case mmioFOURCC('v', 'p', 'r', 'p'): {
- VideoPropHeader *vprp = malloc(chunksize);
- unsigned int i;
- stream_read(demuxer->stream, (void*)vprp, chunksize);
- le2me_VideoPropHeader(vprp);
- chunksize -= sizeof(*vprp)-sizeof(vprp->FieldInfo);
- chunksize /= sizeof(VIDEO_FIELD_DESC);
- if (vprp->nbFieldPerFrame > chunksize) {
- vprp->nbFieldPerFrame = chunksize;
- }
- chunksize = 0;
- for (i=0; i<vprp->nbFieldPerFrame; i++) {
- le2me_VIDEO_FIELD_DESC(&vprp->FieldInfo[i]);
- }
- if (sh_video) {
- sh_video->aspect = GET_AVI_ASPECT(vprp->dwFrameAspectRatio);
- }
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_vprp(vprp,MSGL_V);
- free(vprp);
- break;
- }
- case mmioFOURCC('d', 'm', 'l', 'h'): {
- // dmlh 00 00 00 04 frms
- unsigned int total_frames = stream_read_dword_le(demuxer->stream);
- mp_tmsg(MSGT_HEADER,MSGL_V,"AVI: dmlh found (size=%d) (total_frames=%d)\n", chunksize, total_frames);
- stream_skip(demuxer->stream, chunksize-4);
- chunksize = 0;
- }
- break;
- case ckidAVINEWINDEX:
- if(demuxer->movi_end>stream_tell(demuxer->stream))
- demuxer->movi_end=stream_tell(demuxer->stream); // fixup movi-end
- if(index_mode && !priv->isodml){
- int read;
- int i;
- priv->idx_size=size2>>4;
- mp_tmsg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %d frames (fpos=%"PRId64").\n",
- priv->idx_size,avih.dwTotalFrames, (int64_t)stream_tell(demuxer->stream));
- priv->idx=malloc(priv->idx_size<<4);
-// printf("\nindex to %p !!!!! (priv=%p)\n",priv->idx,priv);
- read = stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4);
- priv->idx_size = FFMAX(read, 0) >> 4;
- for (i = 0; i < priv->idx_size; i++) { // swap index to machine endian
- AVIINDEXENTRY *entry=(AVIINDEXENTRY*)priv->idx + i;
- le2me_AVIINDEXENTRY(entry);
- /*
- * We (ab)use the upper word for bits 32-47 of the offset, so
- * we'll clear them here.
- * FIXME: AFAIK no codec uses them, but if one does it will break
- */
- entry->dwFlags&=0xffff;
- }
- chunksize-=priv->idx_size<<4;
- if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2);
- }
- break;
- /* added May 2002 */
- case mmioFOURCC('R','I','F','F'): {
- char riff_type[4];
-
- mp_tmsg(MSGT_HEADER, MSGL_V, "Additional RIFF header...\n");
- stream_read(demuxer->stream, riff_type, sizeof riff_type);
- if (strncmp(riff_type, "AVIX", sizeof riff_type))
- mp_tmsg(MSGT_HEADER, MSGL_WARN, "** Warning: this is no extended AVI header..\n");
- else {
- /*
- * We got an extended AVI header, so we need to switch to
- * ODML to get seeking to work, provided we got indx chunks
- * in the header (suidx_size > 0).
- */
- if (priv->suidx_size > 0)
- priv->isodml = 1;
- }
- chunksize = 0;
- list_end = 0; /* a new list will follow */
- break; }
- case ckidAVIPADDING:
- stream_skip(demuxer->stream, chunksize);
- chunksize = 0;
- break;
- }
- if(hdr){
- mp_msg(MSGT_HEADER,MSGL_V,"hdr=%s size=%u\n",hdr,size2);
- if(size2==3)
- chunksize=1; // empty
- else {
- char buf[256];
- int len=(size2<250)?size2:250;
- stream_read(demuxer->stream,buf,len);
- chunksize-=len;
- buf[len]=0;
- mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf);
- demux_info_add(demuxer, hdr, buf);
- }
- }
- mp_msg(MSGT_HEADER,MSGL_DBG2,"list_end=0x%"PRIX64" pos=0x%"PRIX64" chunksize=0x%"PRIX64" next=0x%"PRIX64"\n",
- (int64_t)list_end, (int64_t)stream_tell(demuxer->stream),
- (int64_t)chunksize, (int64_t)chunksize+(int64_t)stream_tell(demuxer->stream));
- if(list_end>0 &&
- chunksize+stream_tell(demuxer->stream) == list_end) list_end=0;
- if(list_end>0 && chunksize+stream_tell(demuxer->stream)>list_end){
- mp_tmsg(MSGT_HEADER,MSGL_V,"Broken chunk? chunksize=%d (id=%.4s)\n",chunksize,(char *) &id);
- stream_seek(demuxer->stream,list_end);
- list_end=0;
- } else
- if(chunksize>0) stream_skip(demuxer->stream,chunksize); else
- if((int)chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%u (id=%.4s)\n",chunksize,(char *) &id);
-
-}
-
-if (priv->suidx_size > 0 && priv->idx_size == 0) {
- /*
- * No NEWAVIINDEX, but we got an OpenDML index.
- */
- priv->isodml = 1;
-}
-
-if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) {
- int i, j, k;
-
- avisuperindex_chunk *cx;
- AVIINDEXENTRY *idx;
-
-
- if (priv->idx_size) free(priv->idx);
- priv->idx_size = 0;
- priv->idx_offset = 0;
- priv->idx = NULL;
-
- mp_tmsg(MSGT_HEADER, MSGL_INFO, "AVI: ODML: Building ODML index (%d superindexchunks).\n", priv->suidx_size);
-
- // read the standard indices
- for (cx = &priv->suidx[0], i=0; i<priv->suidx_size; cx++, i++) {
- for (j=0; j<cx->nEntriesInUse; j++) {
- int ret1, ret2;
- memset(&cx->stdidx[j], 0, 32);
- ret1 = stream_seek(demuxer->stream, (int64_t)cx->aIndex[j].qwOffset);
- ret2 = stream_read(demuxer->stream, (char *)&cx->stdidx[j], 32);
- if (ret1 != 1 || ret2 != 32 || cx->stdidx[j].nEntriesInUse==0) {
- // this is a broken file (probably incomplete) let the standard
- // gen_index routine handle this
- priv->isodml = 0;
- priv->idx_size = 0;
- mp_tmsg(MSGT_HEADER, MSGL_WARN, "AVI: ODML: Broken (incomplete?) file detected. Will use traditional index.\n");
- goto freeout;
- }
-
- le2me_AVISTDIDXCHUNK(&cx->stdidx[j]);
- print_avistdindex_chunk(&cx->stdidx[j],MSGL_V);
- priv->idx_size += cx->stdidx[j].nEntriesInUse;
- cx->stdidx[j].aIndex = malloc(cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry));
- stream_read(demuxer->stream, (char *)cx->stdidx[j].aIndex,
- cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry));
- for (k=0;k<cx->stdidx[j].nEntriesInUse; k++)
- le2me_AVISTDIDXENTRY(&cx->stdidx[j].aIndex[k]);
-
- cx->stdidx[j].dwReserved3 = 0;
-
- }
- }
-
- /*
- * We convert the index by translating all entries into AVIINDEXENTRYs
- * and sorting them by offset. The result should be the same index
- * we would get with -forceidx.
- */
-
- idx = priv->idx = malloc(priv->idx_size * sizeof (AVIINDEXENTRY));
-
- for (cx = priv->suidx; cx != &priv->suidx[priv->suidx_size]; cx++) {
- avistdindex_chunk *sic;
- for (sic = cx->stdidx; sic != &cx->stdidx[cx->nEntriesInUse]; sic++) {
- avistdindex_entry *sie;
- for (sie = sic->aIndex; sie != &sic->aIndex[sic->nEntriesInUse]; sie++) {
- uint64_t off = sic->qwBaseOffset + sie->dwOffset - 8;
- memcpy(&idx->ckid, sic->dwChunkId, 4);
- idx->dwChunkOffset = off;
- idx->dwFlags = (off >> 32) << 16;
- idx->dwChunkLength = sie->dwSize & 0x7fffffff;
- idx->dwFlags |= (sie->dwSize&0x80000000)?0x0:AVIIF_KEYFRAME; // bit 31 denotes !keyframe
- idx++;
- }
- }
- }
- qsort(priv->idx, priv->idx_size, sizeof(AVIINDEXENTRY), avi_idx_cmp);
-
- /*
- Hack to work around a "wrong" index in some divx odml files
- (processor_burning.avi as an example)
- They have ##dc on non keyframes but the ix00 tells us they are ##db.
- Read the fcc of a non-keyframe vid frame and check it.
- */
-
- {
- uint32_t id;
- uint32_t db = 0;
-
- // find out the video stream id. I have seen files with 01db.
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- unsigned char res[2];
- if (odml_get_vstream_id(idx->ckid, res)) {
- db = mmioFOURCC(res[0], res[1], 'd', 'b');
- break;
- }
- }
-
- // find first non keyframe
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db) break;
- }
- if (i<priv->idx_size && db) {
- stream_seek(demuxer->stream, AVI_IDX_OFFSET(idx));
- id = stream_read_dword_le(demuxer->stream);
- if (id && id != db) // index fcc and real fcc differ? fix it.
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db)
- idx->ckid = id;
- }
- }
- }
-
- if ( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx, priv->idx_size,MSGL_DBG2);
-
- demuxer->movi_end=demuxer->stream->end_pos;
-
-freeout:
-
- // free unneeded stuff
- cx = &priv->suidx[0];
- do {
- for (j=0;j<cx->nEntriesInUse;j++)
- if (cx->stdidx[j].nEntriesInUse) free(cx->stdidx[j].aIndex);
- free(cx->stdidx);
-
- } while (cx++ != &priv->suidx[priv->suidx_size-1]);
- free(priv->suidx);
-
-}
-
-if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){
- int idx_pos = 0;
- // build index for file:
- stream_seek(demuxer->stream,demuxer->movi_start);
-
- priv->idx_size=0;
- priv->idx=NULL;
-
- while(1){
- int id;
- unsigned len;
- int64_t skip;
- AVIINDEXENTRY* idx;
- unsigned int c;
- demuxer->filepos=stream_tell(demuxer->stream);
- if(demuxer->filepos>=demuxer->movi_end && demuxer->movi_start<demuxer->movi_end) break;
- id=stream_read_dword_le(demuxer->stream);
- len=stream_read_dword_le(demuxer->stream);
- if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){
- id=stream_read_dword_le(demuxer->stream); // list or RIFF type
- continue;
- }
- if(stream_eof(demuxer->stream)) break;
- if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?)
-
- if(idx_pos>=priv->idx_size){
-// priv->idx_size+=32;
- priv->idx_size+=1024; // +16kB
- priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY));
- if(!priv->idx){idx_pos=0; break;} // error!
- }
- idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos++];
- idx->ckid=id;
- idx->dwFlags=AVIIF_KEYFRAME; // FIXME
- idx->dwFlags|=(demuxer->filepos>>16)&0xffff0000U;
- idx->dwChunkOffset=(unsigned long)demuxer->filepos;
- idx->dwChunkLength=len;
-
- c=stream_read_dword(demuxer->stream);
-
- if(!len) idx->dwFlags&=~AVIIF_KEYFRAME;
-
- // Fix keyframes for DivX files:
- if(idxfix_divx)
- if(avi_stream_id(id)==idxfix_videostream){
- switch(idxfix_divx){
- case 3: c=stream_read_dword(demuxer->stream)<<5; //skip 32+5 bits for m$mpeg4v1
- case 1: if(c&0x40000000) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 3
- case 2: if(c==0x1B6) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 4
- }
- }
-
- // update status line:
- { static int64_t lastpos;
- int64_t pos;
- int64_t len=demuxer->movi_end-demuxer->movi_start;
- if(len){
- pos=100*(demuxer->filepos-demuxer->movi_start)/len; // %
- } else {
- pos=(demuxer->filepos-demuxer->movi_start)>>20; // MB
- }
- if(pos!=lastpos){
- lastpos=pos;
- mp_tmsg(MSGT_HEADER,MSGL_STATUS, "Generating Index: %3lu %s \r",
- (unsigned long)pos, len?"%":"MB");
- }
- }
- mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %08X %X\n",(unsigned int)demuxer->filepos,id,(char *) &id,(int)c,(unsigned int) idx->dwFlags);
-#if 0
- { unsigned char tmp[64];
- int i;
- stream_read(demuxer->stream,tmp,64);
- printf("%.4s",&id);
- for(i=0;i<64;i++) printf(" %02X",tmp[i]);
- printf("\n");
- }
-#endif
-skip_chunk:
- skip=(len+1)&(~1UL); // total bytes in this chunk
- stream_seek(demuxer->stream,8+demuxer->filepos+skip);
- }
- priv->idx_size=idx_pos;
- mp_tmsg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size);
- if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2);
-
-}
-}
diff --git a/demux/aviheader.h b/demux/aviheader.h
deleted file mode 100644
index 0d721908d3..0000000000
--- a/demux/aviheader.h
+++ /dev/null
@@ -1,382 +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.
- */
-
-#ifndef MPLAYER_AVIHEADER_H
-#define MPLAYER_AVIHEADER_H
-
-#include <sys/types.h>
-#include <stdint.h>
-#include "config.h"
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-#ifndef mmioFOURCC
-#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
- ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
- ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
-#endif
-
-/* Macro to make a TWOCC out of two characters */
-#ifndef aviTWOCC
-#define aviTWOCC(ch0, ch1) ((uint16_t)(uint8_t)(ch0) | ((uint16_t)(uint8_t)(ch1) << 8))
-#endif
-
-//typedef uint16_t TWOCC;
-//typedef uint32_t FOURCC;
-
-/* form types, list types, and chunk types */
-#define formtypeAVI mmioFOURCC('A', 'V', 'I', ' ')
-#define listtypeAVIHEADER mmioFOURCC('h', 'd', 'r', 'l')
-#define ckidAVIMAINHDR mmioFOURCC('a', 'v', 'i', 'h')
-#define listtypeSTREAMHEADER mmioFOURCC('s', 't', 'r', 'l')
-#define ckidSTREAMHEADER mmioFOURCC('s', 't', 'r', 'h')
-#define ckidSTREAMFORMAT mmioFOURCC('s', 't', 'r', 'f')
-#define ckidSTREAMHANDLERDATA mmioFOURCC('s', 't', 'r', 'd')
-#define ckidSTREAMNAME mmioFOURCC('s', 't', 'r', 'n')
-
-#define listtypeAVIMOVIE mmioFOURCC('m', 'o', 'v', 'i')
-#define listtypeAVIRECORD mmioFOURCC('r', 'e', 'c', ' ')
-
-#define ckidAVINEWINDEX mmioFOURCC('i', 'd', 'x', '1')
-
-/*
-** Stream types for the <fccType> field of the stream header.
-*/
-#define streamtypeVIDEO mmioFOURCC('v', 'i', 'd', 's')
-#define streamtypeAUDIO mmioFOURCC('a', 'u', 'd', 's')
-#define streamtypeMIDI mmioFOURCC('m', 'i', 'd', 's')
-#define streamtypeTEXT mmioFOURCC('t', 'x', 't', 's')
-
-/* Basic chunk types */
-#define cktypeDIBbits aviTWOCC('d', 'b')
-#define cktypeDIBcompressed aviTWOCC('d', 'c')
-#define cktypePALchange aviTWOCC('p', 'c')
-#define cktypeWAVEbytes aviTWOCC('w', 'b')
-
-/* Chunk id to use for extra chunks for padding. */
-#define ckidAVIPADDING mmioFOURCC('J', 'U', 'N', 'K')
-
-/* flags for use in <dwFlags> in AVIFileHdr */
-#define AVIF_HASINDEX 0x00000010 // Index at end of file?
-#define AVIF_MUSTUSEINDEX 0x00000020
-#define AVIF_ISINTERLEAVED 0x00000100
-#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
-#define AVIF_WASCAPTUREFILE 0x00010000
-#define AVIF_COPYRIGHTED 0x00020000
-
-typedef struct
-{
- uint32_t dwMicroSecPerFrame; // frame display rate (or 0L)
- uint32_t dwMaxBytesPerSec; // max. transfer rate
- uint32_t dwPaddingGranularity; // pad to multiples of this
- // size; normally 2K.
- uint32_t dwFlags; // the ever-present flags
- uint32_t dwTotalFrames; // # frames in file
- uint32_t dwInitialFrames;
- uint32_t dwStreams;
- uint32_t dwSuggestedBufferSize;
-
- uint32_t dwWidth;
- uint32_t dwHeight;
-
- uint32_t dwReserved[4];
-} MainAVIHeader;
-
-typedef struct rectangle_t {
- short left;
- short top;
- short right;
- short bottom;
-} rectangle_t;
-
-typedef struct {
- uint32_t fccType;
- uint32_t fccHandler;
- uint32_t dwFlags; /* Contains AVITF_* flags */
- uint16_t wPriority;
- uint16_t wLanguage;
- uint32_t dwInitialFrames;
- uint32_t dwScale;
- uint32_t dwRate; /* dwRate / dwScale == samples/second */
- uint32_t dwStart;
- uint32_t dwLength; /* In units above... */
- uint32_t dwSuggestedBufferSize;
- uint32_t dwQuality;
- uint32_t dwSampleSize;
- rectangle_t rcFrame;
-} AVIStreamHeader;
-
-/* Flags for index */
-#define AVIIF_LIST 0x00000001L // chunk is a 'LIST'
-#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame.
-
-#define AVIIF_NOTIME 0x00000100L // this frame doesn't take any time
-#define AVIIF_COMPUSE 0x0FFF0000L // these bits are for compressor use
-
-#ifndef FOURCC_RIFF
-#define FOURCC_RIFF mmioFOURCC('R', 'I', 'F', 'F')
-#define FOURCC_LIST mmioFOURCC('L', 'I', 'S', 'T')
-#endif
-
-typedef struct
-{
- uint32_t ckid;
- uint32_t dwFlags;
- uint32_t dwChunkOffset; // Position of chunk
- uint32_t dwChunkLength; // Length of chunk
-} AVIINDEXENTRY;
-
-
-typedef struct avisuperindex_entry {
- uint64_t qwOffset; // absolute file offset
- uint32_t dwSize; // size of index chunk at this offset
- uint32_t dwDuration; // time span in stream ticks
-} avisuperindex_entry;
-
-typedef struct avistdindex_entry {
- uint32_t dwOffset; // qwBaseOffset + this is absolute file offset
- uint32_t dwSize; // bit 31 is set if this is NOT a keyframe
-} avistdindex_entry;
-
-// Standard index
-typedef struct __attribute__((packed)) avistdindex_chunk {
- char fcc[4]; // ix##
- uint32_t dwSize; // size of this chunk
- uint16_t wLongsPerEntry; // must be sizeof(aIndex[0])/sizeof(DWORD)
- uint8_t bIndexSubType; // must be 0
- uint8_t bIndexType; // must be AVI_INDEX_OF_CHUNKS
- uint32_t nEntriesInUse; // first unused entry
- char dwChunkId[4]; // '##dc' or '##db' or '##wb' etc..
- uint64_t qwBaseOffset; // all dwOffsets in aIndex array are relative to this
- uint32_t dwReserved3; // must be 0
- avistdindex_entry *aIndex; // the actual frames
-} avistdindex_chunk;
-
-
-// Base Index Form 'indx'
-typedef struct avisuperindex_chunk {
- char fcc[4];
- uint32_t dwSize; // size of this chunk
- uint16_t wLongsPerEntry; // size of each entry in aIndex array (must be 4*4 for us)
- uint8_t bIndexSubType; // future use. must be 0
- uint8_t bIndexType; // one of AVI_INDEX_* codes
- uint32_t nEntriesInUse; // index of first unused member in aIndex array
- char dwChunkId[4]; // fcc of what is indexed
- uint32_t dwReserved[3]; // meaning differs for each index type/subtype.
- // 0 if unused
- avisuperindex_entry *aIndex; // position of ix## chunks
- avistdindex_chunk *stdidx; // the actual std indices
-} avisuperindex_chunk;
-
-typedef struct {
- uint32_t CompressedBMHeight;
- uint32_t CompressedBMWidth;
- uint32_t ValidBMHeight;
- uint32_t ValidBMWidth;
- uint32_t ValidBMXOffset;
- uint32_t ValidBMYOffset;
- uint32_t VideoXOffsetInT;
- uint32_t VideoYValidStartLine;
-} VIDEO_FIELD_DESC;
-
-typedef struct {
- uint32_t VideoFormatToken;
- uint32_t VideoStandard;
- uint32_t dwVerticalRefreshRate;
- uint32_t dwHTotalInT;
- uint32_t dwVTotalInLines;
- uint32_t dwFrameAspectRatio;
- uint32_t dwFrameWidthInPixels;
- uint32_t dwFrameHeightInLines;
- uint32_t nbFieldPerFrame;
- VIDEO_FIELD_DESC FieldInfo[2];
-} VideoPropHeader;
-
-typedef enum {
- FORMAT_UNKNOWN,
- FORMAT_PAL_SQUARE,
- FORMAT_PAL_CCIR_601,
- FORMAT_NTSC_SQUARE,
- FORMAT_NTSC_CCIR_601,
-} VIDEO_FORMAT;
-
-typedef enum {
- STANDARD_UNKNOWN,
- STANDARD_PAL,
- STANDARD_NTSC,
- STANDARD_SECAM
-} VIDEO_STANDARD;
-
-#define MAKE_AVI_ASPECT(a, b) (((a)<<16)|(b))
-#define GET_AVI_ASPECT(a) ((float)((a)>>16)/(float)((a)&0xffff))
-
-/*
- * Some macros to swap little endian structures read from an AVI file
- * into machine endian format
- */
-#if BYTE_ORDER == BIG_ENDIAN
-#define le2me_MainAVIHeader(h) { \
- (h)->dwMicroSecPerFrame = le2me_32((h)->dwMicroSecPerFrame); \
- (h)->dwMaxBytesPerSec = le2me_32((h)->dwMaxBytesPerSec); \
- (h)->dwPaddingGranularity = le2me_32((h)->dwPaddingGranularity); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->dwTotalFrames = le2me_32((h)->dwTotalFrames); \
- (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \
- (h)->dwStreams = le2me_32((h)->dwStreams); \
- (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \
- (h)->dwWidth = le2me_32((h)->dwWidth); \
- (h)->dwHeight = le2me_32((h)->dwHeight); \
-}
-
-#define le2me_AVIStreamHeader(h) { \
- (h)->fccType = le2me_32((h)->fccType); \
- (h)->fccHandler = le2me_32((h)->fccHandler); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->wPriority = le2me_16((h)->wPriority); \
- (h)->wLanguage = le2me_16((h)->wLanguage); \
- (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \
- (h)->dwScale = le2me_32((h)->dwScale); \
- (h)->dwRate = le2me_32((h)->dwRate); \
- (h)->dwStart = le2me_32((h)->dwStart); \
- (h)->dwLength = le2me_32((h)->dwLength); \
- (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \
- (h)->dwQuality = le2me_32((h)->dwQuality); \
- (h)->dwSampleSize = le2me_32((h)->dwSampleSize); \
- le2me_RECT(&(h)->rcFrame); \
-}
-#define le2me_RECT(h) { \
- (h)->left = le2me_16((h)->left); \
- (h)->top = le2me_16((h)->top); \
- (h)->right = le2me_16((h)->right); \
- (h)->bottom = le2me_16((h)->bottom); \
-}
-#define le2me_BITMAPINFOHEADER(h) { \
- (h)->biSize = le2me_32((h)->biSize); \
- (h)->biWidth = le2me_32((h)->biWidth); \
- (h)->biHeight = le2me_32((h)->biHeight); \
- (h)->biPlanes = le2me_16((h)->biPlanes); \
- (h)->biBitCount = le2me_16((h)->biBitCount); \
- (h)->biCompression = le2me_32((h)->biCompression); \
- (h)->biSizeImage = le2me_32((h)->biSizeImage); \
- (h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
- (h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
- (h)->biClrUsed = le2me_32((h)->biClrUsed); \
- (h)->biClrImportant = le2me_32((h)->biClrImportant); \
-}
-#define le2me_WAVEFORMATEX(h) { \
- (h)->wFormatTag = le2me_16((h)->wFormatTag); \
- (h)->nChannels = le2me_16((h)->nChannels); \
- (h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
- (h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
- (h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
- (h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
- (h)->cbSize = le2me_16((h)->cbSize); \
-}
-#define le2me_AVIINDEXENTRY(h) { \
- (h)->ckid = le2me_32((h)->ckid); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->dwChunkOffset = le2me_32((h)->dwChunkOffset); \
- (h)->dwChunkLength = le2me_32((h)->dwChunkLength); \
-}
-#define le2me_AVISTDIDXCHUNK(h) {\
- char c; \
- c = (h)->fcc[0]; (h)->fcc[0] = (h)->fcc[3]; (h)->fcc[3] = c; \
- c = (h)->fcc[1]; (h)->fcc[1] = (h)->fcc[2]; (h)->fcc[2] = c; \
- (h)->dwSize = le2me_32((h)->dwSize); \
- (h)->wLongsPerEntry = le2me_16((h)->wLongsPerEntry); \
- (h)->nEntriesInUse = le2me_32((h)->nEntriesInUse); \
- c = (h)->dwChunkId[0]; (h)->dwChunkId[0] = (h)->dwChunkId[3]; (h)->dwChunkId[3] = c; \
- c = (h)->dwChunkId[1]; (h)->dwChunkId[1] = (h)->dwChunkId[2]; (h)->dwChunkId[2] = c; \
- (h)->qwBaseOffset = le2me_64((h)->qwBaseOffset); \
- (h)->dwReserved3 = le2me_32((h)->dwReserved3); \
-}
-#define le2me_AVISTDIDXENTRY(h) {\
- (h)->dwOffset = le2me_32((h)->dwOffset); \
- (h)->dwSize = le2me_32((h)->dwSize); \
-}
-#define le2me_VideoPropHeader(h) { \
- (h)->VideoFormatToken = le2me_32((h)->VideoFormatToken); \
- (h)->VideoStandard = le2me_32((h)->VideoStandard); \
- (h)->dwVerticalRefreshRate = le2me_32((h)->dwVerticalRefreshRate); \
- (h)->dwHTotalInT = le2me_32((h)->dwHTotalInT); \
- (h)->dwVTotalInLines = le2me_32((h)->dwVTotalInLines); \
- (h)->dwFrameAspectRatio = le2me_32((h)->dwFrameAspectRatio); \
- (h)->dwFrameWidthInPixels = le2me_32((h)->dwFrameWidthInPixels); \
- (h)->dwFrameHeightInLines = le2me_32((h)->dwFrameHeightInLines); \
- (h)->nbFieldPerFrame = le2me_32((h)->nbFieldPerFrame); \
-}
-#define le2me_VIDEO_FIELD_DESC(h) { \
- (h)->CompressedBMHeight = le2me_32((h)->CompressedBMHeight); \
- (h)->CompressedBMWidth = le2me_32((h)->CompressedBMWidth); \
- (h)->ValidBMHeight = le2me_32((h)->ValidBMHeight); \
- (h)->ValidBMWidth = le2me_32((h)->ValidBMWidth); \
- (h)->ValidBMXOffset = le2me_32((h)->ValidBMXOffset); \
- (h)->ValidBMYOffset = le2me_32((h)->ValidBMYOffset); \
- (h)->VideoXOffsetInT = le2me_32((h)->VideoXOffsetInT); \
- (h)->VideoYValidStartLine = le2me_32((h)->VideoYValidStartLine); \
-}
-
-#else
-#define le2me_MainAVIHeader(h) /**/
-#define le2me_AVIStreamHeader(h) /**/
-#define le2me_RECT(h) /**/
-#define le2me_BITMAPINFOHEADER(h) /**/
-#define le2me_WAVEFORMATEX(h) /**/
-#define le2me_AVIINDEXENTRY(h) /**/
-#define le2me_AVISTDIDXCHUNK(h) /**/
-#define le2me_AVISTDIDXENTRY(h) /**/
-#define le2me_VideoPropHeader(h) /**/
-#define le2me_VIDEO_FIELD_DESC(h) /**/
-#endif
-
-typedef struct {
- // index stuff:
- void* idx;
- int idx_size;
- int64_t idx_pos;
- int64_t idx_pos_a;
- int64_t idx_pos_v;
- int64_t idx_offset; // ennyit kell hozzaadni az index offset ertekekhez
- // bps-based PTS stuff:
- int video_pack_no;
- int audio_block_size;
- int64_t audio_block_no;
- // interleaved PTS stuff:
- int skip_video_frames;
- int audio_streams;
- float avi_audio_pts;
- float avi_video_pts;
- float pts_correction;
- unsigned int pts_corr_bytes;
- unsigned char pts_corrected;
- unsigned char pts_has_video;
- unsigned int numberofframes;
- avisuperindex_chunk *suidx;
- int suidx_size;
- int isodml;
- int warned_unaligned;
-} avi_priv_t;
-
-#define AVI_PRIV ((avi_priv_t*)(demuxer->priv))
-
-#define AVI_IDX_OFFSET(x) ((((uint64_t)(x)->dwFlags&0xffff0000)<<16)+(x)->dwChunkOffset)
-
-struct demuxer;
-void read_avi_header(struct demuxer *demuxer, int index_mode);
-
-#endif /* MPLAYER_AVIHEADER_H */
diff --git a/demux/aviprint.c b/demux/aviprint.c
deleted file mode 100644
index 5d285c2104..0000000000
--- a/demux/aviprint.c
+++ /dev/null
@@ -1,197 +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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <inttypes.h>
-
-#include "config.h"
-
-// for avi_stream_id():
-#include "stream/stream.h"
-#include "demux.h"
-
-#include "aviheader.h"
-#include "ms_hdr.h"
-#include "aviprint.h"
-
-//#include "codec-cfg.h"
-//#include "stheader.h"
-
-void print_avih_flags(MainAVIHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "MainAVIHeader.dwFlags: (%"PRId32")%s%s%s%s%s%s\n",h->dwFlags,
- (h->dwFlags&AVIF_HASINDEX)?" HAS_INDEX":"",
- (h->dwFlags&AVIF_MUSTUSEINDEX)?" MUST_USE_INDEX":"",
- (h->dwFlags&AVIF_ISINTERLEAVED)?" IS_INTERLEAVED":"",
- (h->dwFlags&AVIF_TRUSTCKTYPE)?" TRUST_CKTYPE":"",
- (h->dwFlags&AVIF_WASCAPTUREFILE)?" WAS_CAPTUREFILE":"",
- (h->dwFlags&AVIF_COPYRIGHTED)?" COPYRIGHTED":""
- );
-}
-
-void print_avih(MainAVIHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= AVI Header =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "us/frame: %"PRId32" (fps=%5.3f)\n",h->dwMicroSecPerFrame,1000000.0f/(float)h->dwMicroSecPerFrame);
- mp_msg(MSGT_HEADER, verbose_level, "max bytes/sec: %"PRId32"\n",h->dwMaxBytesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "padding: %"PRId32"\n",h->dwPaddingGranularity);
- print_avih_flags(h, verbose_level);
- mp_msg(MSGT_HEADER, verbose_level, "frames total: %"PRId32" initial: %"PRId32"\n",h->dwTotalFrames,h->dwInitialFrames);
- mp_msg(MSGT_HEADER, verbose_level, "streams: %"PRId32"\n",h->dwStreams);
- mp_msg(MSGT_HEADER, verbose_level, "Suggested BufferSize: %"PRId32"\n",h->dwSuggestedBufferSize);
- mp_msg(MSGT_HEADER, verbose_level, "Size: %"PRId32" x %"PRId32"\n",h->dwWidth,h->dwHeight);
- mp_msg(MSGT_HEADER, verbose_level, "==========================\n");
-}
-
-void print_strh(AVIStreamHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "====== STREAM Header =====\n");
- mp_msg(MSGT_HEADER, verbose_level, "Type: %.4s FCC: %.4s (%X)\n",(char *)&h->fccType,(char *)&h->fccHandler,(unsigned int)h->fccHandler);
- mp_msg(MSGT_HEADER, verbose_level, "Flags: %"PRId32"\n",h->dwFlags);
- mp_msg(MSGT_HEADER, verbose_level, "Priority: %d Language: %d\n",h->wPriority,h->wLanguage);
- mp_msg(MSGT_HEADER, verbose_level, "InitialFrames: %"PRId32"\n",h->dwInitialFrames);
- mp_msg(MSGT_HEADER, verbose_level, "Rate: %"PRId32"/%"PRId32" = %5.3f\n",h->dwRate,h->dwScale,(float)h->dwRate/(float)h->dwScale);
- mp_msg(MSGT_HEADER, verbose_level, "Start: %"PRId32" Len: %"PRId32"\n",h->dwStart,h->dwLength);
- mp_msg(MSGT_HEADER, verbose_level, "Suggested BufferSize: %"PRId32"\n",h->dwSuggestedBufferSize);
- mp_msg(MSGT_HEADER, verbose_level, "Quality %"PRId32"\n",h->dwQuality);
- mp_msg(MSGT_HEADER, verbose_level, "Sample size: %"PRId32"\n",h->dwSampleSize);
- mp_msg(MSGT_HEADER, verbose_level, "==========================\n");
-}
-
-void print_wave_header(WAVEFORMATEX *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= WAVE Format =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "Format Tag: %d (0x%X)\n",h->wFormatTag,h->wFormatTag);
- mp_msg(MSGT_HEADER, verbose_level, "Channels: %d\n",h->nChannels);
- mp_msg(MSGT_HEADER, verbose_level, "Samplerate: %"PRId32"\n",h->nSamplesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "avg byte/sec: %"PRId32"\n",h->nAvgBytesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "Block align: %d\n",h->nBlockAlign);
- mp_msg(MSGT_HEADER, verbose_level, "bits/sample: %d\n",h->wBitsPerSample);
- mp_msg(MSGT_HEADER, verbose_level, "cbSize: %d\n",h->cbSize);
- if(h->wFormatTag==0x55 && h->cbSize>=12){
- MPEGLAYER3WAVEFORMAT* h2=(MPEGLAYER3WAVEFORMAT *)h;
- mp_msg(MSGT_HEADER, verbose_level, "mp3.wID=%d\n",h2->wID);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.fdwFlags=0x%"PRIX32"\n",h2->fdwFlags);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nBlockSize=%d\n",h2->nBlockSize);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nFramesPerBlock=%d\n",h2->nFramesPerBlock);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nCodecDelay=%d\n",h2->nCodecDelay);
- }
- else if (h->wFormatTag == 0xfffe && h->cbSize >= 22) {
- WAVEFORMATEXTENSIBLE *h2 = (WAVEFORMATEXTENSIBLE *)h;
- mp_msg(MSGT_HEADER, verbose_level, "ex.wValidBitsPerSample=%d\n", h2->wValidBitsPerSample);
- mp_msg(MSGT_HEADER, verbose_level, "ex.dwChannelMask=0x%X\n", h2->dwChannelMask);
- mp_msg(MSGT_HEADER, verbose_level, "ex.SubFormat=%d (0x%X)\n", h2->SubFormat, h2->SubFormat);
- }
- else if (h->cbSize > 0)
- {
- int i;
- uint8_t* p = (uint8_t*)(h + 1);
- mp_msg(MSGT_HEADER, verbose_level, "Unknown extra header dump: ");
- for (i = 0; i < h->cbSize; i++)
- mp_msg(MSGT_HEADER, verbose_level, "[%x] ", p[i]);
- mp_msg(MSGT_HEADER, verbose_level, "\n");
- }
- mp_msg(MSGT_HEADER, verbose_level, "==========================================================================\n");
-}
-
-
-void print_video_header(BITMAPINFOHEADER *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= VIDEO Format ======\n");
- mp_msg(MSGT_HEADER, verbose_level, " biSize %d\n", h->biSize);
- mp_msg(MSGT_HEADER, verbose_level, " biWidth %d\n", h->biWidth);
- mp_msg(MSGT_HEADER, verbose_level, " biHeight %d\n", h->biHeight);
- mp_msg(MSGT_HEADER, verbose_level, " biPlanes %d\n", h->biPlanes);
- mp_msg(MSGT_HEADER, verbose_level, " biBitCount %d\n", h->biBitCount);
- mp_msg(MSGT_HEADER, verbose_level, " biCompression %d='%.4s'\n", h->biCompression, (char *)&h->biCompression);
- mp_msg(MSGT_HEADER, verbose_level, " biSizeImage %d\n", h->biSizeImage);
- if (h->biSize > sizeof(*h))
- {
- int i;
- uint8_t* p = (uint8_t*)(h + 1);
- mp_msg(MSGT_HEADER, verbose_level, "Unknown extra header dump: ");
- for (i = 0; i < h->biSize-sizeof(*h); i++)
- mp_msg(MSGT_HEADER, verbose_level, "[%x] ", *(p+i));
- mp_msg(MSGT_HEADER, verbose_level, "\n");
- }
- mp_msg(MSGT_HEADER, verbose_level, "===========================\n");
-}
-
-void print_vprp(VideoPropHeader *vprp, int verbose_level){
- int i;
- mp_msg(MSGT_HEADER, verbose_level, "======= Video Properties Header =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "Format: %d VideoStandard: %d\n",
- vprp->VideoFormatToken,vprp->VideoStandard);
- mp_msg(MSGT_HEADER, verbose_level, "VRefresh: %d HTotal: %d VTotal: %d\n",
- vprp->dwVerticalRefreshRate, vprp->dwHTotalInT, vprp->dwVTotalInLines);
- mp_msg(MSGT_HEADER, verbose_level, "FrameAspect: %d:%d Framewidth: %d Frameheight: %d\n",
- vprp->dwFrameAspectRatio >> 16, vprp->dwFrameAspectRatio & 0xffff,
- vprp->dwFrameWidthInPixels, vprp->dwFrameHeightInLines);
- mp_msg(MSGT_HEADER, verbose_level, "Fields: %d\n", vprp->nbFieldPerFrame);
- for (i=0; i<vprp->nbFieldPerFrame; i++) {
- VIDEO_FIELD_DESC *vfd = &vprp->FieldInfo[i];
- mp_msg(MSGT_HEADER, verbose_level, " == Field %d description ==\n", i);
- mp_msg(MSGT_HEADER, verbose_level, " CompressedBMHeight: %d CompressedBMWidth: %d\n",
- vfd->CompressedBMHeight, vfd->CompressedBMWidth);
- mp_msg(MSGT_HEADER, verbose_level, " ValidBMHeight: %d ValidBMWidth: %d\n",
- vfd->ValidBMHeight, vfd->ValidBMWidth);
- mp_msg(MSGT_HEADER, verbose_level, " ValidBMXOffset: %d ValidBMYOffset: %d\n",
- vfd->ValidBMXOffset, vfd->ValidBMYOffset);
- mp_msg(MSGT_HEADER, verbose_level, " VideoXOffsetInT: %d VideoYValidStartLine: %d\n",
- vfd->VideoXOffsetInT, vfd->VideoYValidStartLine);
- }
- mp_msg(MSGT_HEADER, verbose_level, "=======================================\n");
-}
-
-void print_index(AVIINDEXENTRY *idx, int idx_size, int verbose_level){
- int i;
- unsigned int pos[256];
- unsigned int num[256];
- memset(pos, 0, sizeof(pos));
- memset(num, 0, sizeof(num));
- for(i=0;i<idx_size;i++){
- int id=avi_stream_id(idx[i].ckid);
- if(id<0 || id>255) id=255;
- mp_msg(MSGT_HEADER, verbose_level, "%5d: %.4s %4X %016"PRIX64" len:%6"PRId32" pos:%7d->%7.3f %7d->%7.3f\n",i,
- (char *)&idx[i].ckid,
- (unsigned int)idx[i].dwFlags&0xffff,
- (uint64_t)AVI_IDX_OFFSET(&idx[i]),
-// idx[i].dwChunkOffset+demuxer->movi_start,
- idx[i].dwChunkLength,
- pos[id],(float)pos[id]/18747.0f,
- num[id],(float)num[id]/23.976f
- );
- pos[id]+=idx[i].dwChunkLength;
- ++num[id];
- }
-}
-
-void print_avistdindex_chunk(avistdindex_chunk *h, int verbose_level){
- mp_msg (MSGT_HEADER, verbose_level, "====== AVI Standard Index Header ========\n");
- mp_msg (MSGT_HEADER, verbose_level, " FCC (%.4s) dwSize (%d) wLongsPerEntry(%d)\n", h->fcc, h->dwSize, h->wLongsPerEntry);
- mp_msg (MSGT_HEADER, verbose_level, " bIndexSubType (%d) bIndexType (%d)\n", h->bIndexSubType, h->bIndexType);
- mp_msg (MSGT_HEADER, verbose_level, " nEntriesInUse (%d) dwChunkId (%.4s)\n", h->nEntriesInUse, h->dwChunkId);
- mp_msg (MSGT_HEADER, verbose_level, " qwBaseOffset (0x%"PRIX64") dwReserved3 (%d)\n", h->qwBaseOffset, h->dwReserved3);
- mp_msg (MSGT_HEADER, verbose_level, "===========================\n");
-}
-void print_avisuperindex_chunk(avisuperindex_chunk *h, int verbose_level){
- mp_msg (MSGT_HEADER, verbose_level, "====== AVI Super Index Header ========\n");
- mp_msg (MSGT_HEADER, verbose_level, " FCC (%.4s) dwSize (%d) wLongsPerEntry(%d)\n", h->fcc, h->dwSize, h->wLongsPerEntry);
- mp_msg (MSGT_HEADER, verbose_level, " bIndexSubType (%d) bIndexType (%d)\n", h->bIndexSubType, h->bIndexType);
- mp_msg (MSGT_HEADER, verbose_level, " nEntriesInUse (%d) dwChunkId (%.4s)\n", h->nEntriesInUse, h->dwChunkId);
- mp_msg (MSGT_HEADER, verbose_level, " dwReserved[0] (%d) dwReserved[1] (%d) dwReserved[2] (%d)\n",
- h->dwReserved[0], h->dwReserved[1], h->dwReserved[2]);
- mp_msg (MSGT_HEADER, verbose_level, "===========================\n");
-}
diff --git a/demux/aviprint.h b/demux/aviprint.h
deleted file mode 100644
index 86123b7725..0000000000
--- a/demux/aviprint.h
+++ /dev/null
@@ -1,35 +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.
- */
-
-#ifndef MPLAYER_AVIPRINT_H
-#define MPLAYER_AVIPRINT_H
-
-#include "ms_hdr.h"
-#include "aviheader.h"
-
-void print_avih_flags(MainAVIHeader *h, int verbose_level);
-void print_avih(MainAVIHeader *h, int verbose_level);
-void print_strh(AVIStreamHeader *h, int verbose_level);
-void print_wave_header(WAVEFORMATEX *h, int verbose_level);
-void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
-void print_vprp(VideoPropHeader *vprp, int verbose_level);
-void print_index(AVIINDEXENTRY *idx, int idx_size, int verbose_level);
-void print_avistdindex_chunk(avistdindex_chunk *h, int verbose_level);
-void print_avisuperindex_chunk(avisuperindex_chunk *h, int verbose_level);
-
-#endif /* MPLAYER_AVIPRINT_H */
diff --git a/demux/demux.c b/demux/demux.c
index 339333d36c..1783f92c96 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 <stdio.h>
#include <stdlib.h>
@@ -46,8 +47,6 @@
#error MP_INPUT_BUFFER_PADDING_SIZE is too small!
#endif
-static void clear_parser(sh_audio_t *sh);
-
// Demuxer list
extern const struct demuxer_desc demuxer_desc_edl;
extern const struct demuxer_desc demuxer_desc_cue;
@@ -55,18 +54,9 @@ extern const demuxer_desc_t demuxer_desc_rawaudio;
extern const demuxer_desc_t demuxer_desc_rawvideo;
extern const demuxer_desc_t demuxer_desc_tv;
extern const demuxer_desc_t demuxer_desc_mf;
-extern const demuxer_desc_t demuxer_desc_avi;
-extern const demuxer_desc_t demuxer_desc_asf;
extern const demuxer_desc_t demuxer_desc_matroska;
extern const demuxer_desc_t demuxer_desc_lavf;
extern const demuxer_desc_t demuxer_desc_mng;
-extern const demuxer_desc_t demuxer_desc_mpeg_ps;
-extern const demuxer_desc_t demuxer_desc_mpeg_pes;
-extern const demuxer_desc_t demuxer_desc_mpeg_gxf;
-extern const demuxer_desc_t demuxer_desc_mpeg_es;
-extern const demuxer_desc_t demuxer_desc_mpeg4_es;
-extern const demuxer_desc_t demuxer_desc_h264_es;
-extern const demuxer_desc_t demuxer_desc_mpeg_ts;
extern const demuxer_desc_t demuxer_desc_libass;
extern const demuxer_desc_t demuxer_desc_subreader;
@@ -88,18 +78,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
@@ -108,8 +89,31 @@ const demuxer_desc_t *const demuxer_list[] = {
NULL
};
+struct demux_stream {
+ int selected; // user wants packets from this stream
+ int eof; // end of demuxed stream? (true if all buffer empty)
+ int packs; // number of packets in buffer
+ int bytes; // total bytes of packets in buffer
+ struct demux_packet *head;
+ struct demux_packet *tail;
+};
+
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;
@@ -217,408 +221,178 @@ 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;
}
-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, int id)
-{
- demux_stream_t *ds = malloc(sizeof(demux_stream_t));
- *ds = (demux_stream_t) {
- .stream_type = type,
- .id = id,
- .demuxer = demuxer,
- .asf_seq = -1,
- };
- return ds;
-}
-
-/**
- * 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,
- int a_id, int v_id, int s_id, char *filename)
-{
- 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, a_id);
- d->video = new_demuxer_stream(d, STREAM_VIDEO, v_id);
- d->sub = new_demuxer_stream(d, STREAM_SUB, s_id);
- d->ds[STREAM_VIDEO] = d->video;
- d->ds[STREAM_AUDIO] = d->audio;
- d->ds[STREAM_SUB] = d->sub;
- 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 (filename) // Filename hack for avs_check_file
- d->filename = strdup(filename);
- stream_seek(stream, stream->start_pos);
- 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;
}
- struct sh_stream *sh = talloc_struct(demuxer, struct sh_stream, {
+ 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_ptrtype(demuxer, sh);
+ *sh = (struct sh_stream) {
.type = type,
.demuxer = demuxer,
.index = demuxer->num_streams,
.demuxer_id = demuxer_id, // may be overwritten by demuxer
- .stream_index = stream_index,
.opts = demuxer->opts,
- });
+ .ds = talloc_zero(sh, struct demux_stream),
+ };
MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh);
switch (sh->type) {
case STREAM_VIDEO: {
struct sh_video *sht = talloc_zero(demuxer, struct sh_video);
sht->gsh = sh;
sht->opts = sh->opts;
- sht->ds = demuxer->video;
sh->video = sht;
- demuxer->v_streams[sh->stream_index] = sht;
break;
}
case STREAM_AUDIO: {
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;
- demuxer->a_streams[sh->stream_index] = sht;
break;
}
case STREAM_SUB: {
struct sh_sub *sht = talloc_zero(demuxer, struct sh_sub);
sht->gsh = sh;
sht->opts = sh->opts;
- sht->ds = demuxer->sub;
sh->sub = sht;
- demuxer->s_streams[sh->stream_index] = sht;
break;
}
default: assert(false);
}
- 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);
-}
+ sh->ds->selected = demuxer->stream_autoselect;
-static void free_sh_stream(struct sh_stream *sh)
-{
+ return sh;
}
-sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid)
+static void free_sh_sub(sh_sub_t *sh)
{
- 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];
+ free(sh->extradata);
}
-struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid,
- const char *lang)
+static void free_sh_audio(sh_audio_t *sh)
{
- 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;
+ free(sh->wf);
+ free(sh->codecdata);
}
-static void free_sh_sub(sh_sub_t *sh)
+static void free_sh_video(sh_video_t *sh)
{
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_sub at %p\n", sh);
- free(sh->extradata);
- free_sh_stream(sh->gsh);
+ free(sh->bih);
}
-sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid)
+static void free_sh_stream(struct sh_stream *sh)
{
- 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);
+ 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;
+ case STREAM_SUB: free_sh_sub(sh->sub); break;
+ default: abort();
}
- return demuxer->a_streams[id];
}
-static void free_sh_audio(demuxer_t *demuxer, int id)
+void free_demuxer(demuxer_t *demuxer)
{
- sh_audio_t *sh = demuxer->a_streams[id];
- demuxer->a_streams[id] = NULL;
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_audio at %p\n", sh);
- free(sh->wf);
- free(sh->codecdata);
- clear_parser(sh);
- free_sh_stream(sh->gsh);
+ if (demuxer->desc->close)
+ demuxer->desc->close(demuxer);
+ // free streams:
+ for (int n = 0; n < demuxer->num_streams; n++)
+ free_sh_stream(demuxer->streams[n]);
+ talloc_free(demuxer);
}
-sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid)
+static const char *stream_type_name(enum stream_type type)
{
- 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);
+ switch (type) {
+ case STREAM_VIDEO: return "video";
+ case STREAM_AUDIO: return "audio";
+ case STREAM_SUB: return "sub";
+ default: return "unknown";
}
- return demuxer->v_streams[id];
}
-static void free_sh_video(sh_video_t *sh)
+static int count_packs(struct demuxer *demux, enum stream_type type)
{
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh);
- free(sh->bih);
- free_sh_stream(sh->gsh);
+ 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;
}
-void free_demuxer(demuxer_t *demuxer)
+static int count_bytes(struct demuxer *demux, enum stream_type type)
{
- 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]);
- // free demuxers:
- free_demuxer_stream(demuxer->audio);
- free_demuxer_stream(demuxer->video);
- free_demuxer_stream(demuxer->sub);
- free(demuxer->filename);
- talloc_free(demuxer);
+ 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 (!dp || !ds || !ds->selected) {
+ talloc_free(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)
-{
- // 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->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",
- (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 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)
-{
- 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);
+ "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?\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;
-
return true;
}
@@ -626,51 +400,19 @@ 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:
-// 0 = EOF
-// 1 = successful
-int ds_fill_buffer(demux_stream_t *ds)
-{
- 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",
- ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" :
- ds == demux->sub ? "d_sub" : "unknown");
+static void ds_get_packets(struct sh_stream *sh)
+{
+ struct demux_stream *ds = sh->ds;
+ demuxer_t *demux = sh->demuxer;
+ mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_get_packets (%s) called\n",
+ 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) {
- demux_packet_t *p = ds->first;
- // copy useful data:
- 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;
- }
- 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;
- ds->first = p->next;
- if (!ds->first)
- ds->last = NULL;
- --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
@@ -679,205 +421,76 @@ int ds_fill_buffer(demux_stream_t *ds)
* despite the eof flag then it's better to clear it to avoid
* 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
- // 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;
- if (!demux_fill_buffer(demux, ds)) {
- mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
- "ds_fill_buffer()->demux_fill_buffer() failed\n");
+ if (!demux_fill_buffer(demux))
break; // EOF
- }
-
- struct sh_video *sh_video = demux->video->sh;
-
- if (sh_video && sh_video->gsh->attached_picture) {
- if (demux->audio)
- ds->fill_count += demux->audio->packs - apacks;
- if (demux->video && demux->video->packs > vpacks)
- 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 == 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;
}
-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;
-}
+// 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 = sh ? sh->ds : NULL;
+ if (ds) {
+ ds_get_packets(sh);
+ 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--;
-/**
- * \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;
- while (dp) {
- demux_packet_t *dn = dp->next;
- 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;
- 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;
+ if (pkt->stream_pts != MP_NOPTS_VALUE)
+ sh->demuxer->stream_pts = pkt->stream_pts;
+
+ return pkt;
}
}
- len = ds->buffer_size - ds->buffer_pos;
- *start = &ds->buffer[ds->buffer_pos];
- ds->buffer_pos += len;
- return len;
+ return NULL;
}
-int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
+// 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)
{
- 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;
+ if (sh) {
+ ds_get_packets(sh);
+ if (sh->ds->head)
+ return sh->ds->head->pts;
+ }
+ return MP_NOPTS_VALUE;
}
-struct demux_packet *ds_get_packet_sub(demux_stream_t *ds)
+// Return whether a packet is queued. Never blocks, never forces any reads.
+bool demux_has_packet(struct sh_stream *sh)
{
- 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;
- }
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
+ return sh && sh->ds->head;
}
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last)
+// 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)
{
- 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;
+ return demux_has_packet(stream);
}
-double ds_get_next_pts(demux_stream_t *ds)
+// Return whether EOF was returned with an earlier packet read.
+bool demux_stream_eof(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;
+ return !sh || sh->ds->eof;
}
// ====================================================================
@@ -887,89 +500,60 @@ 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]->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,
- 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);
}
}
-
-/**
- * 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,
- 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->params = params;
- if (desc->check_file)
- fformat = desc->check_file(demuxer);
- else
- fformat = desc->type;
- if (force)
- fformat = desc->type;
- 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,
+ .accurate_seek = true,
+ .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);
+ demuxer->filetype, desc->desc);
else
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) {
- 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;
+ desc->desc);
if (stream_manages_timeline(demuxer->stream)) {
// Incorrect, but fixes some behavior with DVD/BD
demuxer->ts_resets_possible = false;
@@ -980,135 +564,73 @@ 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, audio_id,
- video_id, sub_id, filename, params);
}
- fail:
+
free_demuxer(demuxer);
return NULL;
}
-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,
- struct demuxer_params *params)
+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;
- 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;
- }
- 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 (!force_format)
+ force_format = opts->demuxer_name;
+ if (!force_format)
+ force_format = stream->demuxer;
- // 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, audio_id,
- video_id, sub_id, 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);
- 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 (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);
- 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, audio_id,
- video_id, sub_id, filename, 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;
+ }
}
}
return NULL;
}
-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);
-}
-
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,
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;
}
@@ -1117,10 +639,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
@@ -1267,48 +785,32 @@ void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
{
assert(!stream || stream->type == type);
- // don't flush buffers if stream is already selected
- if (stream && demuxer_stream_is_selected(demuxer, stream))
- return;
-
- int old_id = demuxer->ds[type]->id;
-
- // legacy
- 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();
- }
-
- 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;
- }
+ for (int n = 0; n < demuxer->num_streams; n++) {
+ struct sh_stream *cur = demuxer->streams[n];
+ if (cur->type == type)
+ demuxer_select_track(demuxer, cur, cur == stream);
}
- demuxer->ds[type]->sh = new;
+}
- if (old_id != new_id) {
- ds_free_packs(demuxer->ds[type]);
+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 && d->ds[stream->type]->id == stream->stream_index;
+ 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 20e6ba7a66..85ee738137 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -32,53 +32,15 @@
struct MPOpts;
-#if (__GNUC__ >= 3)
-#define likely(x) __builtin_expect((x) != 0, 1)
-#define unlikely(x) __builtin_expect((x) != 0, 0)
-#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#endif
-
#define MAX_PACKS 4096
#define MAX_PACK_BYTES 0x8000000 // 128 MiB
enum demuxer_type {
- DEMUXER_TYPE_UNKNOWN = 0,
- DEMUXER_TYPE_MPEG_PS,
- DEMUXER_TYPE_AVI,
- DEMUXER_TYPE_AVI_NI,
- DEMUXER_TYPE_AVI_NINI,
- DEMUXER_TYPE_ASF,
+ DEMUXER_TYPE_GENERIC = 0,
DEMUXER_TYPE_TV,
- DEMUXER_TYPE_Y4M,
- DEMUXER_TYPE_MF,
- DEMUXER_TYPE_RAWAUDIO,
- DEMUXER_TYPE_RAWVIDEO,
- DEMUXER_TYPE_MPEG_ES,
- DEMUXER_TYPE_MPEG4_ES,
- DEMUXER_TYPE_H264_ES,
- DEMUXER_TYPE_MPEG_PES,
- DEMUXER_TYPE_MPEG_GXF,
- DEMUXER_TYPE_GIF,
- DEMUXER_TYPE_MPEG_TS,
DEMUXER_TYPE_MATROSKA,
- DEMUXER_TYPE_LAVF,
- DEMUXER_TYPE_NSV,
- DEMUXER_TYPE_AVS,
- DEMUXER_TYPE_AAC,
- DEMUXER_TYPE_MPC,
- 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 {
@@ -101,8 +63,7 @@ enum timestamp_type {
#define DEMUXER_CTRL_RESYNC 13
#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 DEMUXER_CTRL_CORRECT_PTS 16 // int* (write 1 for ok, 0 for no)
#define SEEK_ABSOLUTE (1 << 0)
#define SEEK_FACTOR (1 << 1)
@@ -110,49 +71,26 @@ 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
-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
- 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
- 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
- int id; // stream ID (for multiple audio/video streams)
- struct demuxer *demuxer; // parent demuxer structure (stream handler)
-// ---- asf -----
- struct demux_packet *asf_packet; // read asf fragments here
- int asf_seq;
-// ---- stream header ----
- void *sh; // points to sh_audio or sh_video
-} demux_stream_t;
-
-typedef struct demuxer_info {
- char *name;
- char *author;
- char *encoder;
- char *comments;
- char *copyright;
-} demuxer_info_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;
@@ -160,29 +98,18 @@ 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;
- // 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
- 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);
- /// 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
+ enum demuxer_type type; // optional
+
+ // Return 0 on success, otherwise -1
+ 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);
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;
@@ -229,17 +156,8 @@ 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)
+ 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 */
@@ -249,20 +167,9 @@ 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
-
- // 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;
+ bool stream_autoselect;
int num_editions;
int edition;
@@ -300,87 +207,25 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp);
#define SIZE_MAX ((size_t)-1)
#endif
-static inline void *realloc_struct(void *ptr, size_t nmemb, size_t size)
-{
- if (nmemb > SIZE_MAX / size) {
- free(ptr);
- return NULL;
- }
- return realloc(ptr, nmemb * size);
-}
-
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);
+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);
-static inline int64_t ds_tell(struct demux_stream *ds)
-{
- return (ds->dpos - ds->buffer_size) + ds->buffer_pos;
-}
+struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type);
-static inline int ds_tell_pts(struct demux_stream *ds)
-{
- return (ds->pts_bytes - ds->buffer_size) + ds->buffer_pos;
-}
-
-int demux_read_data(struct demux_stream *ds, unsigned char *mem, int len);
-int demux_pattern_3(struct demux_stream *ds, unsigned char *mem, int maxlen,
- int *read, uint32_t pattern);
-
-#define demux_peekc(ds) ( \
- (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos] \
- : ((unlikely(!ds_fill_buffer(ds))) ? (-1) : ds->buffer[ds->buffer_pos]))
-#define demux_getc(ds) ( \
- (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos++] \
- : ((unlikely(!ds_fill_buffer(ds))) ? (-1) : ds->buffer[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);
-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);
-
-static inline int avi_stream_id(unsigned int id)
-{
- unsigned char a, b;
- a = id - '0';
- b = (id >> 8) - '0';
- if (a>9 || b>9)
- return 100; // invalid ID
- return a * 10 + b;
-}
-
-struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream,
- int file_format, int aid, int vid, int sid,
- 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,
- 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,
int flags);
-// AVI demuxer params:
-extern int index_mode; // -1=untouched 0=don't use index 1=use (generate) index
-extern int force_ni;
-extern int pts_from_bps;
-
int demux_info_add(struct demuxer *demuxer, const char *opt, const char *param);
int demux_info_add_bstr(struct demuxer *demuxer, struct bstr opt,
struct bstr param);
@@ -392,8 +237,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);
-
-int demuxer_type_by_filename(char *filename);
+void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
+ bool selected);
+void demuxer_enable_autoselect(struct demuxer *demuxer);
void demuxer_help(void);
@@ -427,6 +273,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/demux/demux_asf.c b/demux/demux_asf.c
deleted file mode 100644
index f800e09dc3..0000000000
--- a/demux/demux_asf.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * ASF file parser for DEMUXER v0.3
- * copyright (c) 2001 A'rpi/ESP-team
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "asf.h"
-#include "asfheader.h"
-#include "demux.h"
-#include "audio/decode/dec_audio.h"
-
-// based on asf file-format doc by Eugene [http://divx.euro.ru]
-
-/**
- * \brief reads int stored in number of bytes given by len
- * \param ptr pointer to read from, is incremented appropriately
- * \param len lowest 2 bits indicate number of bytes to read
- * \param def default value to return if len is invalid
- */
-static inline unsigned read_varlen(uint8_t **ptr, int len, int def) {
- const uint8_t *p = *ptr;
- len &= 3;
- switch (len) {
- case 1: *ptr += 1; return *p;
- case 2: *ptr += 2; return AV_RL16(p);
- case 3: *ptr += 4; return AV_RL32(p);
- }
- return def;
-}
-
-/**
- * \brief checks if there is enough data to read the bytes given by len
- * \param ptr pointer to read from
- * \param endptr pointer to the end of the buffer
- * \param len lowest 2 bits indicate number of bytes to read
- */
-static inline int check_varlen(uint8_t *ptr, uint8_t *endptr, int len) {
- return len&3 ? ptr + (1<<((len&3) - 1)) <= endptr : 1;
-}
-
-static void asf_descrambling(unsigned char **src,unsigned len, struct asf_priv* asf){
- unsigned char *dst;
- unsigned char *s2=*src;
- unsigned i=0,x,y;
- if (len > UINT_MAX - MP_INPUT_BUFFER_PADDING_SIZE)
- return;
- dst = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
- while(len>=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b+i){
-// mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b);
- //i+=asf_scrambling_h*asf_scrambling_w;
- for(x=0;x<asf->scrambling_w;x++)
- for(y=0;y<asf->scrambling_h;y++){
- memcpy(dst+i,s2+(y*asf->scrambling_w+x)*asf->scrambling_b,asf->scrambling_b);
- i+=asf->scrambling_b;
- }
- s2+=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b;
- }
- //if(i<len) memcpy(dst+i,src+i,len-i);
- free(*src);
- *src = dst;
-}
-
-/*****************************************************************
- * \brief initializes asf private data
- *
- */
-static void init_priv (struct asf_priv* asf){
- asf->last_vid_seq=-1;
- asf->vid_ext_timing_index=-1;
- asf->aud_ext_timing_index=-1;
- asf->vid_ext_frame_index=-1;
-}
-
-static void demux_asf_append_to_packet(demux_packet_t* dp,unsigned char *data,int len,int offs)
-{
- if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs);
- size_t old_len = dp->len;
- resize_demux_packet(dp, dp->len + len);
- memcpy(dp->buffer + old_len, data, len);
-}
-
-static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,uint64_t time,unsigned short dur,int offs,int keyframe){
- struct asf_priv* asf = demux->priv;
- demux_stream_t *ds=NULL;
- int close_seg=0;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len);
-
- if(demux->video->id==-1)
- if(demux->v_streams[id])
- demux->video->id=id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[id])
- demux->audio->id=id;
-
- if(id==demux->audio->id){
- // audio
- ds=demux->audio;
- if(!ds->sh){
- ds->sh=demux->a_streams[id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id);
- }
- } else
- if(id==demux->video->id){
- // video
- ds=demux->video;
- if(!ds->sh){
- ds->sh=demux->v_streams[id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id);
- }
- }
-
- if(ds){
- if(ds->asf_packet){
- demux_packet_t* dp=ds->asf_packet;
-
- if (ds==demux->video && asf->asf_is_dvr_ms) {
- if (asf->new_vid_frame_seg) {
- dp->pos=demux->filepos;
- close_seg = 1;
- } else seq = ds->asf_seq;
- } else close_seg = ds->asf_seq!=seq;
-
- if(close_seg){
- // closed segment, finalize packet:
- if(ds==demux->audio)
- if(asf->scrambling_h>1 && asf->scrambling_w>1 && asf->scrambling_b>0)
- asf_descrambling(&ds->asf_packet->buffer,ds->asf_packet->len,asf);
- ds_add_packet(ds,ds->asf_packet);
- ds->asf_packet=NULL;
- } else {
- // append data to it!
- demux_asf_append_to_packet(dp,data,len,offs);
- // we are ready now.
- return 1;
- }
- }
- // create new packet:
- { demux_packet_t* dp;
- if(offs>0){
- mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs);
- return 0;
- }
- dp=new_demux_packet(len);
- memcpy(dp->buffer,data,len);
- if (asf->asf_is_dvr_ms)
- dp->pts=time*0.0000001;
- else
- dp->pts=time*0.001;
- dp->keyframe = keyframe;
-// if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur);
- dp->pos=demux->filepos;
- ds->asf_packet=dp;
- ds->asf_seq=seq;
- // we are ready now.
- return 1;
- }
- }
-
- return 0;
-}
-
-/*****************************************************************
- * \brief read the replicated data associated with each segment
- * \parameter pp reference to replicated data
- * \parameter id stream number
- * \parameter seq media object number
- * \parameter keyframe key frame indicator - set to zero if keyframe, non-zero otherwise
- * \parameter seg_time set to payload time when valid, if audio or new video frame payload, zero otherwise
- *
- */
-static void get_payload_extension_data(demuxer_t *demux, unsigned char** pp, unsigned char id, unsigned int seq, int *keyframe, uint64_t *seg_time){
- struct asf_priv* asf = demux->priv;
- uint64_t payload_time = -1; //100ns units
- int i, ext_max, ext_timing_index;
- uint8_t *pi = *pp+4;
-
- if(demux->video->id==-1)
- if(demux->v_streams[id])
- demux->video->id=id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[id])
- demux->audio->id=id;
-
- if (id!=demux->video->id && id!=demux->audio->id) return;
-
- if (id==demux->video->id) {
- ext_max = asf->vid_repdata_count;
- ext_timing_index = asf->vid_ext_timing_index;
- } else {
- ext_max = asf->aud_repdata_count;
- ext_timing_index = asf->aud_ext_timing_index;
- }
-
- *seg_time=0.0;
- asf->new_vid_frame_seg = 0;
-
- for (i=0; i<ext_max; i++) {
- uint16_t payextsize;
- uint8_t segment_marker;
-
- if (id==demux->video->id)
- payextsize = asf->vid_repdata_sizes[i];
- else
- payextsize = asf->aud_repdata_sizes[i];
-
- if (payextsize == 65535) {
- payextsize = AV_RL16(pi);
- pi+=2;
- }
-
- // if this is the timing info extension then read the payload time
- if (i == ext_timing_index)
- payload_time = AV_RL64(pi+8);
-
- // if this is the video frame info extension then
- // set the keyframe indicator, the 'new frame segment' indicator
- // and (initially) the 'frame time'
- if (i == asf->vid_ext_frame_index && id==demux->video->id) {
- segment_marker = pi[0];
- // Known video stream segment_marker values that
- // contain useful information:
- //
- // NTSC/ATSC (29.97fps): 0X4A 01001010
- // 0X4B 01001011
- // 0X49 01001001
- //
- // PAL/ATSC (25fps): 0X3A 00111010
- // 0X3B 00111011
- // 0X39 00111001
- //
- // ATSC progressive (29.97fps): 0X7A 01111010
- // 0X7B 01111011
- // 0X79 01111001
- // 11111111
- // ^ this is new video frame marker
- //
- // ^^^^ these bits indicate the framerate
- // 0X4 is 29.97i, 0X3 is 25i, 0X7 is 29.97p, ???=25p
- //
- // ^^^ these bits indicate the frame type:
- // 001 means I-frame
- // 010 and 011 probably mean P and B
-
- asf->new_vid_frame_seg = (0X08 & segment_marker) && seq != asf->last_vid_seq;
-
- if (asf->new_vid_frame_seg) asf->last_vid_seq = seq;
-
- if (asf->avg_vid_frame_time == 0) {
- // set the average frame time initially (in 100ns units).
- // This is based on what works for known samples.
- // It can be extended if more samples of different types can be obtained.
- if (((segment_marker & 0XF0) >> 4) == 4) {
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 30.0) * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 3) {
- asf->avg_vid_frame_time = (uint64_t)(0.04 * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 6) {
- asf->avg_vid_frame_time = (uint64_t)(0.02 * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 7) {
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);
- asf->know_frame_time=1;
- } else {
- // we dont know the frame time initially so
- // make a guess and then recalculate as we go.
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);
- asf->know_frame_time=0;
- }
- }
- *keyframe = (asf->new_vid_frame_seg && (segment_marker & 0X07) == 1);
- }
- pi +=payextsize;
- }
-
- if (id==demux->video->id && asf->new_vid_frame_seg) {
- asf->vid_frame_ct++;
- // Some samples only have timings on key frames and
- // the rest contain non-cronological timestamps. Interpolating
- // the values between key frames works for all samples.
- if (*keyframe) {
- asf->found_first_key_frame=1;
- if (!asf->know_frame_time && asf->last_key_payload_time > 0) {
- // We dont know average frametime so recalculate.
- // Giving precedence to the 'weight' of the existing
- // average limits damage done to new value when there is
- // a sudden time jump which happens occasionally.
- asf->avg_vid_frame_time =
- (0.9 * asf->avg_vid_frame_time) +
- (0.1 * ((payload_time - asf->last_key_payload_time) / asf->vid_frame_ct));
- }
- asf->last_key_payload_time = payload_time;
- asf->vid_frame_ct = 1;
- *seg_time = payload_time;
- } else
- *seg_time = (asf->last_key_payload_time + (asf->avg_vid_frame_time * (asf->vid_frame_ct-1)));
- }
-
- if (id==demux->audio->id) {
- if (payload_time != -1)
- asf->last_aud_diff = payload_time - asf->last_aud_pts;
- asf->last_aud_pts += asf->last_aud_diff;
- *seg_time = asf->last_aud_pts;
- }
-}
-//static int num_elementary_packets100=0;
-//static int num_elementary_packets101=0;
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_asf_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
- struct asf_priv* asf = demux->priv;
-
- demux->filepos=stream_tell(demux->stream);
- // Brodcast stream have movi_start==movi_end
- // Better test ?
- if((demux->movi_start < demux->movi_end) && (demux->filepos>=demux->movi_end)){
- demux->stream->eof=1;
- return 0;
- }
-
- stream_read(demux->stream,asf->packet,asf->packetsize);
- if(demux->stream->eof) return 0; // EOF
- if(asf->packetsize < 2) return 0; // Packet too short
-
- {
- unsigned char* p=asf->packet;
- unsigned char* p_end=asf->packet+asf->packetsize;
- unsigned char flags=p[0];
- unsigned char segtype=p[1];
- unsigned padding;
- unsigned plen;
- unsigned sequence av_unused;
- unsigned long time av_unused = 0;
- unsigned short duration=0;
-
- int segs=1;
- unsigned char segsizetype=0x80;
- int seg=-1;
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){
- int i;
- for(i=0;i<FFMIN(16, asf->packetsize);i++) printf(" %02X",asf->packet[i]);
- printf("\n");
- }
-
- // skip ECC data if present by testing bit 7 of flags
- // 1xxxbbbb -> ecc data present, skip bbbb byte(s)
- // 0xxxxxxx -> payload parsing info starts
- if (flags & 0x80)
- {
- p += (flags & 0x0f)+1;
- if (p+1 >= p_end) return 0; // Packet too short
- flags = p[0];
- segtype = p[1];
- }
-
- //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n");
-
- p+=2; // skip flags & segtype
-
- // Read packet size (plen):
- if(!check_varlen(p, p_end, flags>> 5)) return 0; // Not enough data
- plen = read_varlen(&p, flags >> 5, 0);
-
- // Read sequence:
- if(!check_varlen(p, p_end, flags>> 1)) return 0; // Not enough data
- sequence = read_varlen(&p, flags >> 1, 0);
-
- // Read padding size (padding):
- if(!check_varlen(p, p_end, flags>> 3)) return 0; // Not enough data
- padding = read_varlen(&p, flags >> 3, 0);
-
- if(((flags>>5)&3)!=0){
- // Explicit (absoulte) packet size
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen);
- if(plen>asf->packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf->packetsize);
- } else {
- // Padding (relative) size
- plen=asf->packetsize-padding;
- }
-
- // Read time & duration:
- if (p+5 >= p_end) return 0; // Packet too short
- time = AV_RL32(p); p+=4;
- duration = AV_RL16(p); p+=2;
-
- // Read payload flags:
- if(flags&1){
- // multiple sub-packets
- if (p >= p_end) return 0; // Packet too short
- segsizetype=p[0]>>6;
- segs=p[0] & 0x3F;
- ++p;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08"PRIu64": flag=%02X segs=%d seq=%u plen=%u pad=%u time=%ld dur=%d\n",
- (uint64_t)demux->filepos,flags,segs,sequence,plen,padding,time,duration);
-
- for(seg=0;seg<segs;seg++){
- //ASF_segmhdr_t* sh;
- unsigned char streamno;
- unsigned int seq;
- unsigned int x; // offset or timestamp
- unsigned int rlen;
- //
- int len;
- uint64_t time2=0;
- int keyframe=0;
-
- if(p>=p_end) {
- mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, aborting parsing...\n");
- break;
- }
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){
- int i;
- printf("seg %d:",seg);
- for(i=0;i<FFMIN(16, p_end - p);i++) printf(" %02X",p[i]);
- printf("\n");
- }
-
- streamno=p[0]&0x7F;
- if(p[0]&0x80) keyframe=1;
- p++;
-
- // Read media object number (seq):
- if(!check_varlen(p, p_end, segtype >> 4)) break; // Not enough data
- seq = read_varlen(&p, segtype >> 4, 0);
-
- // Read offset or timestamp:
- if(!check_varlen(p, p_end, segtype >> 2)) break; // Not enough data
- x = read_varlen(&p, segtype >> 2, 0);
-
- // Read replic.data len:
- if(!check_varlen(p, p_end, segtype)) break; // Not enough data
- rlen = read_varlen(&p, segtype, 0);
-
-// printf("### rlen=%d \n",rlen);
- if (rlen > p_end - p) {
- mp_msg(MSGT_DEMUX, MSGL_V, "invalid rlen=%u\n", rlen);
- break;
- }
-
- switch(rlen){
- case 0x01: // 1 = special, means grouping
- //printf("grouping: %02X \n",p[0]);
- ++p; // skip PTS delta
- break;
- default:
- if(rlen>=8){
- p+=4; // skip object size
- if (p+3 >= p_end) break; // Packet too short
- time2=AV_RL32(p); // read PTS
- if (asf->asf_is_dvr_ms)
- get_payload_extension_data(demux, &p, streamno, seq, &keyframe, &time2);
- p+=rlen-4;
- } else {
- mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type (rlen): 0x%02X \n",rlen);
- time2=0; // unknown
- p+=rlen;
- }
- }
-
- if(flags&1){
- // multiple segments
- if(!check_varlen(p, p_end, segsizetype)) break; // Not enough data
- len = read_varlen(&p, segsizetype, plen-(p-asf->packet));
- } else {
- // single segment
- len=plen-(p-asf->packet);
- }
- if(len<0 || (p+len)>p_end){
- mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len);
- len = p_end - p;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,rlen,len);
-
- switch(rlen){
- case 0x01:
- // GROUPING:
- //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len);
- //printf(" total: %d \n",len);
- while(len>0){
- int len2=p[0];
- p++;
- //printf(" group part: %d bytes\n",len2);
- if(len2 > len - 1 || len2 < 0) break; // Not enough data
- len2 = FFMIN(len2, asf->packetsize);
- demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe);
- p+=len2;
- len-=len2+1;
- ++seq;
- }
- if(len!=0){
- mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n");
- }
- break;
- default:
- // NO GROUPING:
- //printf("fragment offset: %d \n",sh->x);
- if (len <= 0) break;
- if (!asf->asf_is_dvr_ms || asf->found_first_key_frame) {
- len = FFMIN(len, asf->packetsize);
- demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe);
- }
- p+=len;
- break;
- }
-
- } // for segs
- return 1; // success
- }
-
- mp_msg(MSGT_DEMUX,MSGL_V,"%08"PRIX64": UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",(int64_t)demux->filepos,asf->packet[0],asf->packet[1],asf->packet[2],asf->packet[3],asf->packet[4]);
- return 0;
-}
-
-#include "stheader.h"
-
-static void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
- struct asf_priv* asf = demuxer->priv;
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
-// sh_video_t *sh_video=d_video->sh;
-
- //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...)
- //FIXME: reports good or bad to steve@daviesfam.org please
-
- //================= seek in ASF ==========================
- float p_rate=asf->packetrate; // packets / sec
- int64_t rel_seek_packs=(flags&SEEK_FACTOR)? // FIXME: int may be enough?
- (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf->packetsize):
- (rel_seek_secs*p_rate);
- int64_t rel_seek_bytes=rel_seek_packs*asf->packetsize;
- int64_t newpos;
- //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration));
-// printf("ASF_seek: %d secs -> %d packs -> %d bytes \n",
-// rel_seek_secs,rel_seek_packs,rel_seek_bytes);
- newpos=((flags&SEEK_ABSOLUTE)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes;
- if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start;
-// printf("\r -- asf: newpos=%d -- \n",newpos);
- stream_seek(demuxer->stream,newpos);
-
- if (asf->asf_is_dvr_ms) asf->dvr_last_vid_pts = 0.0f;
-
- if (d_video->id >= 0)
- ds_fill_buffer(d_video);
- if(sh_audio){
- ds_fill_buffer(d_audio);
- }
-
- if (d_video->id >= 0)
- while(1){
- if(sh_audio && !d_audio->eof){
- float a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
- // sync audio:
- if (d_video->pts > a_pts){
- skip_audio_frame(sh_audio);
-// if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF?
- continue;
- }
- }
- if (d_video->keyframe)
- break;
- if(!ds_fill_buffer(d_video)) break; // skip frame. EOF?
- }
-
-
-}
-
-static int demux_asf_control(demuxer_t *demuxer,int cmd, void *arg){
- struct asf_priv* asf = demuxer->priv;
-/* demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
-*/
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- *((double *)arg)=asf->movielength;
- return DEMUXER_CTRL_OK;
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static demuxer_t* demux_open_asf(demuxer_t* demuxer)
-{
- struct asf_priv* asf = demuxer->priv;
- sh_video_t *sh_video=NULL;
-
- //---- ASF header:
- if(!asf) return NULL;
- init_priv(asf);
- if (!read_asf_header(demuxer,asf))
- return NULL;
- stream_seek(demuxer->stream,demuxer->movi_start);
-// demuxer->idx_pos=0;
-// demuxer->endpos=avi_header.movi_end;
- if(demuxer->video->id != -2) {
- if(!ds_fill_buffer(demuxer->video)){
- mp_msg(MSGT_DEMUXER, MSGL_WARN, "ASF: %s",
- mp_gtext("No video stream found.\n"));
- demuxer->video->sh=NULL;
- //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n");
- } else {
- sh_video=demuxer->video->sh;
- sh_video->fps=1000.0f; sh_video->frametime=0.001f;
-
- if (asf->asf_is_dvr_ms) {
- sh_video->bih->biWidth = 0;
- sh_video->bih->biHeight = 0;
- }
- }
- }
-
- if(demuxer->audio->id!=-2){
- mp_tmsg(MSGT_DEMUXER,MSGL_V,"ASF: Searching for audio stream (id:%d).\n",demuxer->audio->id);
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "ASF: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- }
- }
- if(!demuxer->stream->seek)
- demuxer->seekable=0;
-
- return demuxer;
-}
-
-
-static void demux_close_asf(demuxer_t *demuxer) {
- struct asf_priv* asf = demuxer->priv;
-
- if (!asf) return;
-
- free(asf->aud_repdata_sizes);
- free(asf->vid_repdata_sizes);
- free(asf->packet);
- free(asf);
-}
-
-const demuxer_desc_t demuxer_desc_asf = {
- "ASF demuxer",
- "asf",
- "ASF",
- "A'rpi",
- "ASF, WMV, WMA",
- DEMUXER_TYPE_ASF,
- 1, // safe autodetect
- asf_check_header,
- demux_asf_fill_buffer,
- demux_open_asf,
- demux_close_asf,
- demux_seek_asf,
- demux_asf_control
-};
diff --git a/demux/demux_avi.c b/demux/demux_avi.c
deleted file mode 100644
index a07f022cde..0000000000
--- a/demux/demux_avi.c
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- * AVI file parser for DEMUXER v2.9
- * Copyright (c) 2001 A'rpi/ESP-team
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "aviheader.h"
-
-extern const demuxer_desc_t demuxer_desc_avi_ni;
-extern const demuxer_desc_t demuxer_desc_avi_nini;
-
-// PTS: 0=interleaved 1=BPS-based
-int pts_from_bps=1;
-
-static void update_audio_block_size(demuxer_t *demux)
-{
- avi_priv_t *priv = demux->priv;
- sh_audio_t *sh = demux->audio->sh;
- if (!sh)
- return;
- priv->audio_block_size = sh->audio.dwSampleSize;
- if (sh->wf) {
- priv->audio_block_size = sh->wf->nBlockAlign;
- if (!priv->audio_block_size) {
- // for PCM audio we can calculate the blocksize:
- if (sh->format == 1)
- priv->audio_block_size = sh->wf->nChannels*(sh->wf->wBitsPerSample/8);
- else
- priv->audio_block_size = 1; // hope the best...
- } else {
- // workaround old mencoder bug:
- if (sh->audio.dwSampleSize == 1 && sh->audio.dwScale == 1 &&
- (sh->wf->nBlockAlign == 1152 || sh->wf->nBlockAlign == 576)) {
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: Working around CBR-MP3 nBlockAlign header bug!\n");
- priv->audio_block_size = 1;
- }
- }
- }
-}
-
-// Select ds from ID
-static demux_stream_t *demux_avi_select_stream(demuxer_t *demux,
- unsigned int id)
-{
- int stream_id=avi_stream_id(id);
-
-
- if(demux->video->id==-1)
- if(demux->v_streams[stream_id])
- demux->video->id=stream_id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[stream_id])
- demux->audio->id=stream_id;
-
- if(stream_id==demux->audio->id){
- if(!demux->audio->sh){
- demux->audio->sh=demux->a_streams[stream_id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id);
- update_audio_block_size(demux);
- }
- return demux->audio;
- }
- if(stream_id==demux->video->id){
- if(!demux->video->sh){
- demux->video->sh=demux->v_streams[stream_id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI video ID = %d\n",demux->video->id);
- }
- return demux->video;
- }
- if(id!=mmioFOURCC('J','U','N','K')){
- // unknown
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"Unknown chunk: %.4s (%X)\n",(char *) &id,id);
- //abort();
- }
- return NULL;
-}
-
-static int valid_fourcc(unsigned int id){
- static const char valid[] = "0123456789abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- unsigned char* fcc=(unsigned char*)(&id);
- return strchr(valid, fcc[0]) && strchr(valid, fcc[1]) &&
- strchr(valid, fcc[2]) && strchr(valid, fcc[3]);
-}
-
-static int valid_stream_id(unsigned int id) {
- unsigned char* fcc=(unsigned char*)(&id);
- return fcc[0] >= '0' && fcc[0] <= '9' && fcc[1] >= '0' && fcc[1] <= '9' &&
- ((fcc[2] == 'w' && fcc[3] == 'b') || (fcc[2] == 'd' && fcc[3] == 'c'));
-}
-
-static int choose_chunk_len(unsigned int len1,unsigned int len2){
- // len1 has a bit more priority than len2. len1!=len2
- // Note: this is a first-idea-logic, may be wrong. comments welcomed.
-
- // prefer small frames rather than 0
- if(!len1) return (len2>0x80000) ? len1 : len2;
- if(!len2) return (len1>0x100000) ? len2 : len1;
-
- // choose the smaller value:
- return (len1<len2)? len1 : len2;
-}
-
-static int demux_avi_read_packet(demuxer_t *demux,demux_stream_t *ds,unsigned int id,unsigned int len,int idxpos,int flags){
- avi_priv_t *priv=demux->priv;
- int skip;
- float pts=0;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id);
-
- if(ds==demux->audio){
- if(priv->pts_corrected==0){
- if(priv->pts_has_video){
- // we have video pts now
- float delay=0;
- if(((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec)
- delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;
- mp_msg(MSGT_DEMUX,MSGL_V,"XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay);
- //priv->pts_correction=-priv->avi_audio_pts+delay;
- priv->pts_correction=delay-priv->avi_audio_pts;
- priv->avi_audio_pts+=priv->pts_correction;
- priv->pts_corrected=1;
- } else
- priv->pts_corr_bytes+=len;
- }
- if(pts_from_bps){
- pts = priv->audio_block_no *
- (float)((sh_audio_t*)demux->audio->sh)->audio.dwScale /
- (float)((sh_audio_t*)demux->audio->sh)->audio.dwRate;
- } else
- pts=priv->avi_audio_pts; //+priv->pts_correction;
- priv->avi_audio_pts=0;
- // update blockcount:
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- } else
- if(ds==demux->video){
- // video
- if(priv->skip_video_frames>0){
- // drop frame (seeking)
- --priv->skip_video_frames;
- ds=NULL;
- }
-
- pts = priv->avi_video_pts = priv->video_pack_no *
- (float)((sh_video_t*)demux->video->sh)->video.dwScale /
- (float)((sh_video_t*)demux->video->sh)->video.dwRate;
-
- priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;
- priv->pts_has_video=1;
-
- if(ds) ++priv->video_pack_no;
-
- }
-
- skip=(len+1)&(~1); // total bytes in this chunk
-
- if(ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id);
- ds_read_packet(ds,demux->stream,len,pts,idxpos,flags);
- skip-=len;
- }
- skip = FFMAX(skip, 0);
- if (avi_stream_id(id) > 99 && id != mmioFOURCC('J','U','N','K'))
- skip = FFMIN(skip, 65536);
- if(skip){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id);
- stream_skip(demux->stream,skip);
- }
- return ds?1:0;
-}
-
-static uint32_t avi_find_id(stream_t *stream) {
- uint32_t id = stream_read_dword_le(stream);
- if (!id) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Incomplete stream? Trying resync.\n");
- do {
- id = stream_read_dword_le(stream);
- if (stream_eof(stream)) return 0;
- } while (avi_stream_id(id) > 99);
- }
- return id;
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-demux_stream_t *ds;
-
-do{
- int flags=1;
- AVIINDEXENTRY *idx=NULL;
- if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){
- int64_t pos;
-
- idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
-
- if(idx->dwFlags&AVIIF_LIST){
- if (!valid_stream_id(idx->ckid))
- // LIST
- continue;
- if (!priv->warned_unaligned)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Looks like unaligned chunk in index, broken AVI file!\n");
- priv->warned_unaligned = 1;
- }
- if(!demux_avi_select_stream(demux,idx->ckid)){
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
- continue; // skip this chunk
- }
-
- pos = (int64_t)priv->idx_offset+AVI_IDX_OFFSET(idx);
- if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start) && (demux->stream->flags & MP_STREAM_SEEK)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! idx=0x%"PRIX64" \n",(int64_t)pos);
- continue;
- }
- stream_seek(demux->stream,pos);
- demux->filepos=stream_tell(demux->stream);
- id=stream_read_dword_le(demux->stream);
- if(stream_eof(demux->stream)) return 0; // EOF!
-
- if(id!=idx->ckid){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid);
- if(valid_fourcc(idx->ckid))
- id=idx->ckid; // use index if valid
- else
- if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
- }
- len=stream_read_dword_le(demux->stream);
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
- }
- if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
- } else {
- demux->filepos=stream_tell(demux->stream);
- if(demux->filepos>=demux->movi_end && demux->movi_end>demux->movi_start && (demux->stream->flags & MP_STREAM_SEEK)){
- demux->stream->eof=1;
- return 0;
- }
- id=avi_find_id(demux->stream);
- len=stream_read_dword_le(demux->stream);
- if(stream_eof(demux->stream)) return 0; // EOF!
-
- if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){
- id=stream_read_dword_le(demux->stream); // list or RIFF type
- continue;
- }
- }
-
- ds=demux_avi_select_stream(demux,id);
- if(ds)
- if(ds->packs+1>=MAX_PACKS || ds->bytes+len>=MAX_PACK_BYTES){
- // this packet will cause a buffer overflow, switch to -ni mode!!!
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"\nBadly interleaved AVI file detected - switching to --avi-ni mode...\n");
- if(priv->idx_size>0){
- // has index
- demux->type=DEMUXER_TYPE_AVI_NI;
- demux->desc=&demuxer_desc_avi_ni;
- --priv->idx_pos; // hack
- } else {
- // no index
- demux->type=DEMUXER_TYPE_AVI_NINI;
- demux->desc=&demuxer_desc_avi_nini;
- priv->idx_pos=demux->filepos; // hack
- }
- priv->idx_pos_v=priv->idx_pos_a=priv->idx_pos;
- // quit now, we can't even (no enough buffer memory) read this packet :(
- return -1;
- }
-
- ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,flags);
-} while(ret!=1);
- return 1;
-}
-
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer_ni(demuxer_t *demux, demux_stream_t *ds)
-{
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-
-do{
- int flags=1;
- AVIINDEXENTRY *idx=NULL;
- int idx_pos=0;
- demux->filepos=stream_tell(demux->stream);
-
- if(ds==demux->video) idx_pos=priv->idx_pos_v++; else
- if(ds==demux->audio) idx_pos=priv->idx_pos_a++; else
- idx_pos=priv->idx_pos++;
-
- if(priv->idx_size>0 && idx_pos<priv->idx_size){
- int64_t pos;
- idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];
-
- if(idx->dwFlags&AVIIF_LIST){
- if (!valid_stream_id(idx->ckid))
- // LIST
- continue;
- if (!priv->warned_unaligned)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Looks like unaligned chunk in index, broken AVI file!\n");
- priv->warned_unaligned = 1;
- }
- if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
- continue; // skip this chunk
- }
-
- pos = priv->idx_offset+AVI_IDX_OFFSET(idx);
- if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! current=0x%"PRIX64" idx=0x%"PRIX64" \n",(int64_t)demux->filepos,(int64_t)pos);
- continue;
- }
- stream_seek(demux->stream,pos);
-
- id=stream_read_dword_le(demux->stream);
-
- if(stream_eof(demux->stream)) return 0;
-
- if(id!=idx->ckid){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid);
- if(valid_fourcc(idx->ckid))
- id=idx->ckid; // use index if valid
- else
- if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
- }
- len=stream_read_dword_le(demux->stream);
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
- }
- if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
- } else return 0;
- ret=demux_avi_read_packet(demux,demux_avi_select_stream(demux,id),id,len,idx_pos,flags);
-} while(ret!=1);
- return 1;
-}
-
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer_nini(demuxer_t *demux, demux_stream_t *ds)
-{
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-int64_t *fpos=NULL;
-
- if(ds==demux->video) fpos=&priv->idx_pos_v; else
- if(ds==demux->audio) fpos=&priv->idx_pos_a; else
- return 0;
-
- stream_seek(demux->stream,fpos[0]);
-
-do{
-
- demux->filepos=stream_tell(demux->stream);
- if(demux->filepos>=demux->movi_end && (demux->movi_end>demux->movi_start)){
- ds->eof=1;
- return 0;
- }
-
- id=avi_find_id(demux->stream);
- len=stream_read_dword_le(demux->stream);
-
- if(stream_eof(demux->stream)) return 0;
-
- if(id==mmioFOURCC('L','I','S','T')){
- id=stream_read_dword_le(demux->stream); // list type
- continue;
- }
-
- if(id==mmioFOURCC('R','I','F','F')){
- mp_msg(MSGT_DEMUX,MSGL_V,"additional RIFF header...\n");
- id=stream_read_dword_le(demux->stream); // "AVIX"
- continue;
- }
-
- if(ds==demux_avi_select_stream(demux,id)){
- // read it!
- ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,0);
- } else {
- // skip it!
- int skip=(len+1)&(~1); // total bytes in this chunk
- stream_skip(demux->stream,skip);
- }
-
-} while(ret!=1);
- fpos[0]=stream_tell(demux->stream);
- return 1;
-}
-
-// AVI demuxer parameters:
-int index_mode=-1; // -1=untouched 0=don't use index 1=use (generate) index
-int force_ni=0; // force non-interleaved AVI parsing
-
-static demuxer_t* demux_open_avi(demuxer_t* demuxer){
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
- avi_priv_t* priv=calloc(1, sizeof(avi_priv_t));
-
- demuxer->priv=(void*)priv;
-
- //---- AVI header:
- read_avi_header(demuxer,(demuxer->stream->flags & MP_STREAM_SEEK_BW)?index_mode:-2);
- update_audio_block_size(demuxer);
-
- if(demuxer->audio->id>=0 && !demuxer->a_streams[demuxer->audio->id]){
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid audio stream ID: %d - ignoring (nosound)\n",demuxer->audio->id);
- demuxer->audio->id=-2; // disabled
- }
- if(demuxer->video->id>=0 && !demuxer->v_streams[demuxer->video->id]){
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid video stream ID: %d - ignoring (using default)\n",demuxer->video->id);
- demuxer->video->id=-1; // autodetect
- }
-
- stream_seek(demuxer->stream,demuxer->movi_start);
- if(priv->idx_size>1){
- // decide index format:
-#if 1
- if((AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start ||
- AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[1])<demuxer->movi_start )&& !priv->isodml)
- priv->idx_offset=demuxer->movi_start-4;
-#else
- if(AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start)
- priv->idx_offset=demuxer->movi_start-4;
-#endif
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI index offset: 0x%X (movi=0x%X idx0=0x%X idx1=0x%X)\n",
- (int)priv->idx_offset,(int)demuxer->movi_start,
- (int)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset,
- (int)((AVIINDEXENTRY *)priv->idx)[1].dwChunkOffset);
- }
-
- if(priv->idx_size>0){
- // check that file is non-interleaved:
- int i;
- int64_t a_pos=-1;
- int64_t v_pos=-1;
- for(i=0;i<priv->idx_size;i++){
- AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];
- demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
- int64_t pos = priv->idx_offset + AVI_IDX_OFFSET(idx);
- if(a_pos==-1 && ds==demuxer->audio){
- a_pos=pos;
- if(v_pos!=-1) break;
- }
- if(v_pos==-1 && ds==demuxer->video){
- v_pos=pos;
- if(a_pos!=-1) break;
- }
- }
- if(v_pos==-1){
- mp_msg(MSGT_DEMUX, MSGL_ERR, "AVI_NI: %s",
- mp_gtext("No video stream found.\n"));
- return NULL;
- }
- if(a_pos==-1){
- d_audio->sh=sh_audio=NULL;
- } else {
- if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
- mp_tmsg(MSGT_DEMUX,MSGL_INFO,"%s NON-INTERLEAVED AVI file format.\n",force_ni?"Forced":"Detected");
- demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
- demuxer->desc=&demuxer_desc_avi_ni; // HACK!!!!
- pts_from_bps=1; // force BPS sync!
- }
- }
- } else {
- // no index
- if(force_ni){
- mp_tmsg(MSGT_DEMUX,MSGL_INFO,"Using NON-INTERLEAVED broken AVI file format.\n");
- demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
- demuxer->desc=&demuxer_desc_avi_nini; // HACK!!!!
- priv->idx_pos_a=
- priv->idx_pos_v=demuxer->movi_start;
- pts_from_bps=1; // force BPS sync!
- }
- demuxer->seekable=0;
- }
- if(!ds_fill_buffer(d_video)){
- mp_msg(MSGT_DEMUX, MSGL_ERR, "AVI: %s",
- mp_gtext("Missing video stream!? Contact the author, "
- "it may be a bug :(\n"));
- return NULL;
- }
- sh_video=d_video->sh;sh_video->ds=d_video;
- if(d_audio->id!=-2){
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI: Searching for audio stream (id:%d)\n",d_audio->id);
- if(!priv->audio_streams || !ds_fill_buffer(d_audio)){
- mp_msg(MSGT_DEMUX, MSGL_INFO, "AVI: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- d_audio->sh=sh_audio=NULL;
- } else {
- sh_audio=d_audio->sh;sh_audio->ds=d_audio;
- }
- }
-
- // calculating audio/video bitrate:
- if(priv->idx_size>0){
- // we have index, let's count 'em!
- AVIINDEXENTRY *idx = priv->idx;
- int64_t vsize=0;
- int64_t asize=0;
- size_t vsamples=0;
- size_t asamples=0;
- int i;
- for(i=0;i<priv->idx_size;i++){
- int id=avi_stream_id(idx[i].ckid);
- unsigned len=idx[i].dwChunkLength;
- if(sh_video->ds->id == id) {
- vsize+=len;
- ++vsamples;
- }
- else if(sh_audio && sh_audio->ds->id == id) {
- asize+=len;
- asamples+=(len+priv->audio_block_size-1)/priv->audio_block_size;
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_V,
- "AVI video size=%"PRId64" (%zu) audio size=%"PRId64" (%zu)\n",
- vsize, vsamples, asize, asamples);
- priv->numberofframes=vsamples;
- sh_video->i_bps=((float)vsize/(float)vsamples)*(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- if(sh_audio) sh_audio->i_bps=((float)asize/(float)asamples)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- } else {
- // guessing, results may be inaccurate:
- int64_t vsize;
- int64_t asize=0;
-
- if((priv->numberofframes=sh_video->video.dwLength)<=1)
- // bad video header, try to get number of frames from audio
- if(sh_audio && sh_audio->wf->nAvgBytesPerSec) priv->numberofframes=sh_video->fps*sh_audio->audio.dwLength/sh_audio->audio.dwRate*sh_audio->audio.dwScale;
- if(priv->numberofframes<=1){
- mp_tmsg(MSGT_SEEK,MSGL_WARN,"Could not determine number of frames (for absolute seek).\n");
- priv->numberofframes=0;
- }
-
- if(sh_audio){
- if(sh_audio->wf->nAvgBytesPerSec && sh_audio->audio.dwSampleSize!=1){
- asize=(float)sh_audio->wf->nAvgBytesPerSec*sh_audio->audio.dwLength*sh_audio->audio.dwScale/sh_audio->audio.dwRate;
- } else {
- asize=sh_audio->audio.dwLength;
- sh_audio->i_bps=(float)asize/(sh_video->frametime*priv->numberofframes);
- }
- }
- vsize=demuxer->movi_end-demuxer->movi_start-asize-8*priv->numberofframes;
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI video size=%"PRId64" (%u) audio size=%"PRId64"\n",vsize,priv->numberofframes,asize);
- sh_video->i_bps=(float)vsize/(sh_video->frametime*priv->numberofframes);
- }
-
- return demuxer;
-
-}
-
-
-static void demux_seek_avi(demuxer_t *demuxer, float rel_seek_secs,
- float audio_delay, int flags)
-{
- avi_priv_t *priv=demuxer->priv;
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
- float skip_audio_secs=0;
-
- //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?)
- //================= seek in AVI ==========================
- int rel_seek_frames=rel_seek_secs*sh_video->fps;
- int video_chunk_pos=d_video->pos;
- int i;
-
- if(flags&SEEK_ABSOLUTE){
- // seek absolute
- video_chunk_pos=0;
- }
-
- if(flags&SEEK_FACTOR){
- rel_seek_frames=rel_seek_secs*priv->numberofframes;
- }
-
- priv->skip_video_frames=0;
- priv->avi_audio_pts=0;
-
-// ------------ STEP 1: find nearest video keyframe chunk ------------
- // find nearest video keyframe chunk pos:
- if(rel_seek_frames>0){
- // seek forward
- while(video_chunk_pos<priv->idx_size-1){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
- if(avi_stream_id(id)==d_video->id){ // video frame
- if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
- }
- ++video_chunk_pos;
- }
- } else {
- // seek backward
- while(video_chunk_pos>0){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
- if(avi_stream_id(id)==d_video->id){ // video frame
- if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
- }
- --video_chunk_pos;
- }
- }
- priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=video_chunk_pos;
-
- // re-calc video pts:
- d_video->pack_no=0;
- for(i=0;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
- }
- priv->video_pack_no=d_video->pack_no;
- priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- d_video->pos=video_chunk_pos;
-
- mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos);
-
-// ------------ STEP 2: seek audio, find the right chunk & pos ------------
-
- d_audio->pack_no=0;
- priv->audio_block_no=0;
- d_audio->dpos=0;
-
- if(sh_audio){
- int i;
- int len=0;
- int skip_audio_bytes=0;
- int curr_audio_pos=-1;
- int audio_chunk_pos=-1;
- int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
-
- if(sh_audio->audio.dwSampleSize){
- // constant rate audio stream
- /* immediate seeking to audio position, including when streams are delayed */
- curr_audio_pos=(priv->avi_video_pts + audio_delay)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- curr_audio_pos*=sh_audio->audio.dwSampleSize;
-
- // find audio chunk pos:
- for(i=0;i<chunk_max;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
- if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
- break;
- }
- ++d_audio->pack_no;
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- d_audio->dpos+=len;
- }
- }
- audio_chunk_pos=i;
- skip_audio_bytes=curr_audio_pos-d_audio->dpos;
-
- mp_msg(MSGT_SEEK,MSGL_V,"SEEK: i=%d (max:%d) dpos=%d (wanted:%d) \n",
- i,chunk_max,(int)d_audio->dpos,curr_audio_pos);
-
- } else {
- // VBR audio
- /* immediate seeking to audio position, including when streams are delayed */
- int chunks=(priv->avi_video_pts + audio_delay)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- audio_chunk_pos=0;
-
- // find audio chunk pos:
- for(i=0;i<priv->idx_size && chunks>0;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
- if(i>chunk_max){
- skip_audio_bytes+=len;
- } else {
- ++d_audio->pack_no;
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- d_audio->dpos+=len;
- audio_chunk_pos=i;
- }
- chunks-=(len+priv->audio_block_size-1)/priv->audio_block_size;
- }
- }
- }
-
- // Now we have:
- // audio_chunk_pos = chunk no in index table (it's <=chunk_max)
- // skip_audio_bytes = bytes to be skipped after chunk seek
- // d-audio->pack_no = chunk_no in stream at audio_chunk_pos
- // d_audio->dpos = bytepos in stream at audio_chunk_pos
- // let's seek!
-
- // update stream position:
- d_audio->pos=audio_chunk_pos;
-
- if(demuxer->type==DEMUXER_TYPE_AVI){
- // interleaved stream:
- if(audio_chunk_pos<video_chunk_pos){
- // calc priv->skip_video_frames & adjust video pts counter:
- for(i=audio_chunk_pos;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
- }
- // requires for correct audio pts calculation (demuxer):
- priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- priv->avi_audio_pts=priv->avi_video_pts;
- // set index position:
- priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;
- }
- } else {
- // non-interleaved stream:
- priv->idx_pos_a=audio_chunk_pos;
- priv->idx_pos_v=video_chunk_pos;
- priv->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;
- }
-
- mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n",
- (int)priv->idx_pos,audio_chunk_pos,video_chunk_pos,
- (int)priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);
-
- if(skip_audio_bytes){
- demux_read_data(d_audio,NULL,skip_audio_bytes);
- }
-
- }
- d_video->pts=priv->avi_video_pts; // OSD
-
-}
-
-
-static void demux_close_avi(demuxer_t *demuxer)
-{
- avi_priv_t* priv=demuxer->priv;
-
- if(!priv)
- return;
-
- if(priv->idx_size > 0)
- free(priv->idx);
- free(priv);
-}
-
-
-static int demux_avi_control(demuxer_t *demuxer,int cmd, void *arg){
- avi_priv_t *priv=demuxer->priv;
- demux_stream_t *d_video=demuxer->video;
- sh_video_t *sh_video=d_video->sh;
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if (!priv->numberofframes || !sh_video) return DEMUXER_CTRL_DONTKNOW;
- *((double *)arg)=(double)priv->numberofframes/sh_video->fps;
- if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS;
- return DEMUXER_CTRL_OK;
-
- case DEMUXER_CTRL_SWITCH_AUDIO:
- case DEMUXER_CTRL_SWITCH_VIDEO: {
- int audio = (cmd == DEMUXER_CTRL_SWITCH_AUDIO);
- demux_stream_t *ds = audio ? demuxer->audio : demuxer->video;
- void **streams = audio ? (void **)demuxer->a_streams : (void **)demuxer->v_streams;
- int maxid = FFMIN(100, audio ? MAX_A_STREAMS : MAX_V_STREAMS);
- int chunkid;
- if (ds->id < -1)
- ds->id = -1;
-
- if (*(int *)arg >= 0)
- ds->id = *(int *)arg;
- else {
- int i;
- for (i = 0; i < maxid; i++) {
- if (++ds->id >= maxid) ds->id = 0;
- if (streams[ds->id]) break;
- }
- }
-
- chunkid = (ds->id / 10 + '0') | (ds->id % 10 + '0') << 8;
- ds->sh = NULL;
- if (!streams[ds->id]) // stream not available
- ds->id = -1;
- else
- demux_avi_select_stream(demuxer, chunkid);
- *(int *)arg = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static int avi_check_file(demuxer_t *demuxer)
-{
- int id=stream_read_dword_le(demuxer->stream); // "RIFF"
-
- if((id==mmioFOURCC('R','I','F','F')) || (id==mmioFOURCC('O','N','2',' '))) {
- stream_read_dword_le(demuxer->stream); //filesize
- id=stream_read_dword_le(demuxer->stream); // "AVI "
- if(id==formtypeAVI)
- return DEMUXER_TYPE_AVI;
- // "Samsung Digimax i6 PMP" crap according to bug 742
- if(id==mmioFOURCC('A','V','I',0x19))
- return DEMUXER_TYPE_AVI;
- if(id==mmioFOURCC('O','N','2','f')){
- mp_tmsg(MSGT_DEMUXER,MSGL_INFO,"ON2 AVI format");
- return DEMUXER_TYPE_AVI;
- }
- }
-
- return 0;
-}
-
-
-const demuxer_desc_t demuxer_desc_avi = {
- "AVI demuxer",
- "avi",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
-
-const demuxer_desc_t demuxer_desc_avi_ni = {
- "AVI demuxer, non-interleaved",
- "avini",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer_ni,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
-
-const demuxer_desc_t demuxer_desc_avi_nini = {
- "AVI demuxer, non-interleaved and no index",
- "avinini",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer_nini,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
diff --git a/demux/demux_cue.c b/demux/demux_cue.c
index 073fa9d336..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
@@ -29,31 +31,27 @@ 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 0;
- if (!mp_probe_cue((struct bstr) { buf, len }))
- return 0;
- 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 0;
- 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 = {
- .info = "CUE file demuxer",
.name = "cue",
- .shortdesc = "CUE",
- .author = "Uoti Urpala",
- .comment = "",
+ .desc = "CUE sheet",
.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 c35137ffb2..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
@@ -23,30 +25,28 @@
#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 0;
- if (strncmp(buf, header, len))
- return 0;
- 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 0;
- return DEMUXER_TYPE_EDL;
+ return -1;
+ return 0;
}
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,
- .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 39e1cb28c5..82ca2e24d0 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;
@@ -186,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;
@@ -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) {
@@ -213,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);
@@ -240,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);
@@ -260,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),
};
@@ -299,7 +298,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:
@@ -308,7 +307,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,
@@ -347,6 +346,18 @@ static void parse_cryptokey(AVFormatContext *avfc, const char *str)
*key++ = (char2int(str[0]) << 4) | char2int(str[1]);
}
+static void select_tracks(struct demuxer *demuxer, int start)
+{
+ lavf_priv_t *priv = demuxer->priv;
+ 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) &&
+ !stream->attached_picture;
+ st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
+ }
+}
+
static void handle_stream(demuxer_t *demuxer, int i)
{
lavf_priv_t *priv = demuxer->priv;
@@ -355,8 +366,6 @@ static void handle_stream(demuxer_t *demuxer, int i)
AVCodecContext *codec = st->codec;
struct sh_stream *sh = NULL;
- st->discard = AVDISCARD_ALL;
-
switch (codec->codec_type) {
case AVMEDIA_TYPE_AUDIO: {
sh = new_sh_stream(demuxer, STREAM_AUDIO);
@@ -381,8 +390,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;
@@ -402,7 +415,6 @@ static void handle_stream(demuxer_t *demuxer, int i)
av_q2d(st->codec->time_base) *
st->codec->ticks_per_frame);
sh_video->fps = fps;
- sh_video->frametime = 1 / fps;
if (st->sample_aspect_ratio.num)
sh_video->aspect = codec->width * st->sample_aspect_ratio.num
/ (float)(codec->height * st->sample_aspect_ratio.den);
@@ -428,7 +440,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: {
@@ -464,6 +475,8 @@ static void handle_stream(demuxer_t *demuxer, int i)
if (lang && lang->value)
sh->lang = talloc_strdup(sh, lang->value);
}
+
+ select_tracks(demuxer, i);
}
// Add any new streams that might have been added
@@ -481,19 +494,21 @@ 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, 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)
- return NULL;
+ if (lavf_check_file(demuxer, check) < 0)
+ return -1;
+
+ lavf_priv_t *priv = demuxer->priv;
+ if (!priv)
+ return -1;
stream_seek(demuxer->stream, 0);
@@ -510,7 +525,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer)
if (opts->user_correct_pts != 0)
avfc->flags |= AVFMT_FLAG_GENPTS;
}
- if (index_mode == 0)
+ if (opts->index_mode == 0)
avfc->flags |= AVFMT_FLAG_IGNIDX;
if (lavfdopts->probesize) {
@@ -536,7 +551,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;
}
}
@@ -555,14 +570,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() "
@@ -628,7 +643,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)
@@ -637,7 +652,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;
@@ -658,13 +673,6 @@ 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 &&
- stream->demuxer_id == priv->autoselect_sub)
- {
- priv->autoselect_sub = -1;
- demux->sub->id = stream->stream_index;
- }
-
if (!demuxer_stream_is_selected(demux, stream)) {
talloc_free(pkt);
return 1;
@@ -679,8 +687,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
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;
@@ -772,8 +778,6 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg)
lavf_priv_t *priv = demuxer->priv;
switch (cmd) {
- case DEMUXER_CTRL_CORRECT_PTS:
- return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_GET_TIME_LENGTH:
if (priv->seek_by_bytes) {
/* Our bitrate estimate may be better than would be used in
@@ -797,20 +801,7 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg)
case DEMUXER_CTRL_SWITCHED_TRACKS:
{
- 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) {
- bool selected = demuxer_stream_is_selected(demuxer, stream);
- st->discard = selected ? AVDISCARD_NONE : AVDISCARD_ALL;
- }
- }
- return DEMUXER_CTRL_OK;
- }
- case DEMUXER_CTRL_AUTOSELECT_SUBTITLE:
- {
- demuxer->sub->id = -1;
- priv->autoselect_sub = *((int *)arg);
+ select_tracks(demuxer, 0);
return DEMUXER_CTRL_OK;
}
case DEMUXER_CTRL_IDENTIFY_PROGRAM:
@@ -909,17 +900,11 @@ 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
+ .name = "lavf",
+ .desc = "libavformat",
+ .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..1dc8e92eb0 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;
@@ -41,49 +41,52 @@ 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;
-
- // 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 0;
- ass_free_track(track);
+ return -1;
+
+ 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 0;
+ 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);
if (!track)
- return 0;
+ return -1;
track->name = strdup(demuxer->filename);
@@ -96,7 +99,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)
@@ -109,13 +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 = "",
- .safe_check = 1,
- .type = DEMUXER_TYPE_LIBASS,
- .check_file = d_check_file,
+ .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 127ee8474e..7c4b83692d 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;
@@ -73,7 +74,7 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){
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) {
@@ -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);
}
@@ -148,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]) {
@@ -158,46 +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)
+static int demux_open_mf(demuxer_t* demuxer, enum demux_check check)
{
- if (demuxer->stream->type == STREAMTYPE_MF)
- return DEMUXER_TYPE_MF;
- mf_t *mf = open_mf(demuxer);
- bool ok = mf && probe_format(mf);
- free_mf(mf);
- return ok ? DEMUXER_TYPE_MF : 0;
-}
-
-static demuxer_t* demux_open_mf(demuxer_t* demuxer){
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;
+ }
- mf_t *mf = open_mf(demuxer);
- if (!mf)
+ if (!mf || mf->nr_of_files < 1)
+ goto error;
+
+ const char *codec = probe_format(mf, check);
+ if (!codec)
goto error;
mf->curr_frame = 0;
@@ -206,35 +203,22 @@ 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);
- // 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) {
- mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! (try -mf type=ext)\n" );
- 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;
+ struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO);
+ sh_video = sh->video;
+ sh_video->gsh->codec = codec;
sh_video->disp_w = 0;
sh_video->disp_h = 0;
sh_video->fps = mf_fps;
- sh_video->frametime = 1 / sh_video->fps;
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) {
@@ -251,26 +235,17 @@ static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) {
*((double *)arg) = (double)mf->nr_of_files / mf->sh->fps;
return DEMUXER_CTRL_OK;
- case DEMUXER_CTRL_CORRECT_PTS:
- return DEMUXER_CTRL_OK;
-
default:
return DEMUXER_CTRL_NOTIMPL;
}
}
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
+ .name = "mf",
+ .desc = "image files (mf)",
+ .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 1c93fa588c..ed6de6a69c 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -49,7 +49,7 @@
#include "stheader.h"
#include "ebml.h"
#include "matroska.h"
-//#include "demux_real.h"
+#include "codec_tags.h"
#include "core/mp_msg.h"
@@ -142,10 +142,6 @@ typedef struct mkv_track {
int sub_packet_cnt; ///< number of subpacket already received
int audio_filepos; ///< file position of first audio packet in block
- /* stuff for quicktime */
- int fix_i_bps;
- double qt_last_a_pts;
-
/* generic content encoding support */
mkv_content_encoding_t *encodings;
int num_encodings;
@@ -722,10 +718,11 @@ static void add_block_position(demuxer_t *demuxer, struct mkv_track *track,
static int demux_mkv_read_cues(demuxer_t *demuxer)
{
+ struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
stream_t *s = demuxer->stream;
- if (index_mode == 0 || index_mode == 2) {
+ if (opts->index_mode == 0 || opts->index_mode == 2) {
ebml_read_skip(s, NULL);
return 0;
}
@@ -1282,7 +1279,6 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
if (track->v_frate == 0.0)
track->v_frate = 25.0;
sh_v->fps = track->v_frate;
- sh_v->frametime = 1 / track->v_frate;
sh_v->aspect = 0;
if (!track->realmedia) {
sh_v->disp_w = track->v_width;
@@ -1430,8 +1426,6 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
|| !strcmp(track->codec_id, MKV_A_QDMC2)) {
sh_a->wf->nAvgBytesPerSec = 16000;
sh_a->wf->nBlockAlign = 1486;
- track->fix_i_bps = 1;
- track->qt_last_a_pts = 0.0;
copy_audio_private_data(sh_a, track);
} else if (track->a_formattag == mmioFOURCC('M', 'P', '4', 'A')) {
int profile, srate_idx;
@@ -1751,7 +1745,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;
@@ -1759,11 +1753,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 +1782,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;
}
@@ -1803,9 +1797,7 @@ static int demux_mkv_open(demuxer_t *demuxer)
demuxer->seekable = 1;
}
- demuxer->accurate_seek = true;
-
- return DEMUXER_TYPE_MATROSKA;
+ return 0;
}
static bool bstr_read_u8(bstr *buffer, uint8_t *out_u8)
@@ -1961,9 +1953,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);
+ track->stream->video->bih->biCompression,
+ &track->rv_kf_base, &track->rv_kf_pts, NULL);
dp->pos = demuxer->filepos;
dp->keyframe = keyframe;
@@ -2046,8 +2037,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 = track->stream->audio->wf->nBlockAlign;
track->sub_packet_cnt = 0;
// Release all the audio packets
for (x = 0; x < sph * w / apk_usize; x++) {
@@ -2277,20 +2267,6 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
use_this_block = keyframe;
if (mkv_d->v_skip_to_keyframe)
use_this_block = 0;
-
- if (track->fix_i_bps && use_this_block) {
- sh_audio_t *sh = stream->audio;
-
- if (block_duration != 0) {
- sh->i_bps = data.len * 1e9 / block_duration;
- track->fix_i_bps = 0;
- } else if (track->qt_last_a_pts == 0.0)
- track->qt_last_a_pts = current_pts;
- else if (track->qt_last_a_pts != current_pts) {
- sh->i_bps = data.len / (current_pts - track->qt_last_a_pts);
- track->fix_i_bps = 0;
- }
- }
} else if (track->type == MATROSKA_TRACK_SUBTITLE) {
use_this_block |= mkv_d->subtitle_preroll;
if (use_this_block) {
@@ -2466,7 +2442,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;
@@ -2658,7 +2634,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 {
@@ -2697,7 +2673,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);
}
}
@@ -2706,8 +2682,6 @@ static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg)
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
switch (cmd) {
- case DEMUXER_CTRL_CORRECT_PTS:
- return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_GET_TIME_LENGTH:
if (mkv_d->duration == 0)
return DEMUXER_CTRL_DONTKNOW;
@@ -2720,17 +2694,12 @@ 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
+ .name = "mkv",
+ .desc = "Matroska",
+ .type = DEMUXER_TYPE_MATROSKA,
+ .open = 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 bd86b3e3b8..f6cb66302c 100644
--- a/demux/demux_mng.c
+++ b/demux/demux_mng.c
@@ -38,14 +38,6 @@
#include <libmng.h>
/**
- * \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
*
* This structure is used as private data for MPlayer demuxer
@@ -263,28 +255,11 @@ static mng_bool demux_mng_settimer(mng_handle h_mng, mng_uint32 msecs)
}
/**
- * \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 0;
- if (memcmp(buf, "\x8AMNG", 4))
- return 0;
- return DEMUXER_TYPE_MNG;
-}
-
-/**
* \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;
@@ -346,26 +321,31 @@ 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->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;
}
-/**
- * \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, 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));
@@ -379,7 +359,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
@@ -399,7 +379,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
@@ -410,7 +390,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
@@ -419,22 +399,12 @@ 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
- sh_video = new_sh_video(demuxer, 0);
-
- // 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.
- // (Thanks to demux_gif.c for this.)
- sh_video->ds = demuxer->video;
+ struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO);
+ sh_video = sh->video;
// set format of pixels in video packets
sh_video->gsh->codec = "rawvideo";
@@ -442,7 +412,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer)
// set framerate to some value (MNG does not have a fixed framerate)
sh_video->fps = 5.0f;
- sh_video->frametime = 1.0f / sh_video->fps;
// set video frame parameters
sh_video->bih = calloc(1, sizeof(*sh_video->bih));
@@ -452,14 +421,12 @@ 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;
+ // weirdly broken
+ demuxer->accurate_seek = false;
// set private data in demuxer and return demuxer
demuxer->priv = mng_priv;
- return demuxer;
+ return 0;
}
/**
@@ -596,17 +563,11 @@ 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 <stefan@blinkenarea.org>",
- "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
+ .name = "mng",
+ .desc = "MNG",
+ .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_mpg.c b/demux/demux_mpg.c
deleted file mode 100644
index d47b3afd86..0000000000
--- a/demux/demux_mpg.c
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
- * MPG/VOB file parser for DEMUXER v2.5
- * copyright (c) 2001 by A'rpi/ESP-team
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <math.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-#include "core/options.h"
-
-#include "libavutil/attributes.h"
-#include "audio/decode/dec_audio.h"
-#include "stream/stream.h"
-#include "demux.h"
-#include "parse_es.h"
-#include "stheader.h"
-#include "mp3_hdr.h"
-
-//#define MAX_PS_PACKETSIZE 2048
-#define MAX_PS_PACKETSIZE (224*1024)
-
-#define UNKNOWN 0
-#define VIDEO_MPEG1 0x10000001
-#define VIDEO_MPEG2 0x10000002
-#define VIDEO_MPEG4 0x10000004
-#define VIDEO_H264 0x10000005
-#define AUDIO_MP2 0x50
-#define AUDIO_A52 0x2000
-#define AUDIO_LPCM_BE 0x10001
-#define AUDIO_AAC mmioFOURCC('M', 'P', '4', 'A')
-
-typedef struct mpg_demuxer {
- float last_pts;
- float first_pts; // first pts found in stream
- float first_to_final_pts_len; // difference between final pts and first pts
- int has_valid_timestamps; // !=0 iff time stamps look linear
- // (not necessarily starting with 0)
- unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef
- int num_a_streams;
- int a_stream_ids[MAX_A_STREAMS];
-} mpg_demuxer_t;
-
-static int mpeg_pts_error=0;
-int64_t ps_probe = 0;
-
-static int parse_psm(demuxer_t *demux, int len) {
- unsigned char c, id, type;
- unsigned int plen, prog_len, es_map_len;
- mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
-
- mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len);
- if(! len || len > 1018)
- return 0;
-
- c = stream_read_char(demux->stream);
- if(! (c & 0x80)) {
- stream_skip(demux->stream, len - 1); //not yet valid, discard
- return 0;
- }
- stream_skip(demux->stream, 1);
- prog_len = stream_read_word(demux->stream); //length of program descriptors
- stream_skip(demux->stream, prog_len); //.. that we ignore
- es_map_len = stream_read_word(demux->stream); //length of elementary streams map
- es_map_len = FFMIN(es_map_len, len - prog_len - 8); //sanity check
- while(es_map_len > 0) {
- type = stream_read_char(demux->stream);
- id = stream_read_char(demux->stream);
- if(id >= 0xB0 && id <= 0xEF && priv) {
- int idoffset = id - 0xB0;
- switch(type) {
- case 0x1:
- priv->es_map[idoffset] = VIDEO_MPEG1;
- break;
- case 0x2:
- priv->es_map[idoffset] = VIDEO_MPEG2;
- break;
- case 0x3:
- case 0x4:
- priv->es_map[idoffset] = AUDIO_MP2;
- break;
- case 0x0f:
- case 0x11:
- priv->es_map[idoffset] = AUDIO_AAC;
- break;
- case 0x10:
- priv->es_map[idoffset] = VIDEO_MPEG4;
- break;
- case 0x1b:
- priv->es_map[idoffset] = VIDEO_H264;
- break;
- case 0x81:
- priv->es_map[idoffset] = AUDIO_A52;
- break;
- }
- mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]);
- }
- plen = stream_read_word(demux->stream); //length of elementary stream descriptors
- plen = FFMIN(plen, es_map_len); //sanity check
- stream_skip(demux->stream, plen); //skip descriptors for now
- es_map_len -= 4 + plen;
- }
- stream_skip(demux->stream, 4); //skip crc32
- return 1;
-}
-
-// 500000 is a wild guess
-#define TIMESTAMP_PROBE_LEN 500000
-
-//MAX_PTS_DIFF_FOR_CONSECUTIVE denotes the maximum difference
-//between two pts to consider them consecutive
-//1.0 is a wild guess
-#define MAX_PTS_DIFF_FOR_CONSECUTIVE 1.0
-
-//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream.
-//if no pts is found or an error occurs, -1.0 is returned.
-//Packs are freed.
-static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, int64_t stream_pos)
-{
- stream_t *s = demuxer->stream;
- mpg_demuxer_t *mpg_d = demuxer->priv;
- float pts = -1.0; //the pts to return;
- float found_pts1; //the most recently found pts
- float found_pts2; //the pts found before found_pts1
- float found_pts3; //the pts found before found_pts2
- int found = 0;
-
- if(!mpg_d || stream_pos < 0)
- return pts;
-
- found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts;
- stream_seek(s, stream_pos);
-
- //We look for pts.
- //However, we do not stop at the first found one, as timestamps may reset
- //Therefore, we seek until we found three consecutive
- //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE.
-
- while(found<3 && !s->eof
- && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
- && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
- && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN)
- && ds_fill_buffer(demuxer->video))
- {
- if(mpg_d->last_pts != found_pts1)
- {
- if(!found)
- found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts
- else
- {
- found_pts3 = found_pts2;
- found_pts2 = found_pts1;
- found_pts1 = mpg_d->last_pts;
- }
- found++;
- }
- }
-
- if(found == 3) pts = found_pts3;
-
- //clean up from searching of first pts;
- demux_flush(demuxer);
-
- return pts;
-}
-
-/// Open an mpg physical stream
-static demuxer_t* demux_mpg_open(demuxer_t* demuxer) {
- stream_t *s = demuxer->stream;
- mpg_demuxer_t* mpg_d;
-
- if (!ds_fill_buffer(demuxer->video)) return 0;
- mpg_d = calloc(1,sizeof(mpg_demuxer_t));
- if(mpg_d)
- {
- demuxer->priv = mpg_d;
- mpg_d->last_pts = -1.0;
- mpg_d->first_pts = -1.0;
-
- //if seeking is allowed set has_valid_timestamps if appropriate
- if(demuxer->seekable
- && (demuxer->stream->type == STREAMTYPE_FILE
- || demuxer->stream->type == STREAMTYPE_VCD)
- && demuxer->movi_start != demuxer-> movi_end
- )
- {
- //We seek to the beginning of the stream, to somewhere in the
- //middle, and to the end of the stream, while remembering the pts
- //at each of the three positions. With these pts, we check whether
- //or not the pts are "linear enough" to justify seeking by the pts
- //of the stream
-
- //The position where the stream is now
- int64_t pos = stream_tell(s);
- float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);
- if(first_pts != -1.0)
- {
- float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);
- if(middle_pts != -1.0)
- {
- float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);
- if(final_pts != -1.0)
- {
- // found proper first, middle, and final pts.
- float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);
- // if they are linear enough set has_valid_timestamps
- if((0.5 < proportion) && (proportion < 2))
- {
- mpg_d->first_pts = first_pts;
- mpg_d->first_to_final_pts_len = final_pts - first_pts;
- mpg_d->has_valid_timestamps = 1;
- }
- }
- }
- }
-
- //Cleaning up from seeking in stream
- demuxer->stream->eof=0;
- demuxer->video->eof=0;
- demuxer->audio->eof=0;
-
- stream_seek(s,pos);
- ds_fill_buffer(demuxer->video);
- } // if ( demuxer->seekable )
- } // if ( mpg_d )
- return demuxer;
-}
-
-static void demux_close_mpg(demuxer_t* demuxer) {
- mpg_demuxer_t* mpg_d = demuxer->priv;
- free(mpg_d);
-}
-
-
-static unsigned long long read_mpeg_timestamp(stream_t *s,int c){
- unsigned int d,e;
- unsigned long long pts;
- d=stream_read_word(s);
- e=stream_read_word(s);
- if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){
- ++mpeg_pts_error;
- return 0; // invalid pts
- }
- pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%llu}",pts);
- return pts;
-}
-
-static void new_audio_stream(demuxer_t *demux, int aid){
- if(!demux->a_streams[aid]){
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;
- 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
- case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
- else sh_a->format=0x2000;break; // ac3
- }
- //evo files
- if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;
- else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;
- if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
- mp_set_audio_codec_from_tag(sh_a);
- }
- if(demux->audio->id==-1) demux->audio->id=aid;
-}
-
-static void dvdpcm_header(sh_audio_t *sh)
-{
- if (sh->format != 0x10001)
- return;
-
- WAVEFORMATEX *wf = calloc(sizeof(*wf), 1);
-
- if(sh->codecdata_len==3){
- // we have LPCM header:
- unsigned char h=sh->codecdata[1];
- wf->nChannels=1+(h&7);
- switch((h>>4)&3){
- case 0: wf->nSamplesPerSec=48000;break;
- case 1: wf->nSamplesPerSec=96000;break;
- case 2: wf->nSamplesPerSec=44100;break;
- case 3: wf->nSamplesPerSec=32000;break;
- }
- switch ((h >> 6) & 3) {
- case 0:
- wf->wBitsPerSample = 2 * 8;
- break;
- case 1:
- mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Samples of this format are needed to improve support. Please contact the developers.\n");
- wf->nAvgBytesPerSec = wf->nChannels * wf->nSamplesPerSec * 5 / 2;
- case 2:
- wf->wBitsPerSample = 3 * 8;
- break;
- default:
- wf->wBitsPerSample = 2 * 8;
- }
- } else {
- // use defaults:
- wf->nChannels=2;
- wf->nSamplesPerSec=48000;
- wf->wBitsPerSample = 2 * 8;
- }
- if (!wf->nAvgBytesPerSec)
- wf->nAvgBytesPerSec = wf->wBitsPerSample / 8 * wf->nChannels * wf->nSamplesPerSec;
- if (wf->wBitsPerSample == 16)
- sh->format = 0x20776172; // 'raw ', pcm_s16be
- sh->wf = wf;
-}
-
-static int demux_mpg_read_packet(demuxer_t *demux,int id){
- int d av_unused;
- int len;
- int set_pts=0; // !=0 iff pts has been set to a proper value
- unsigned char c=0;
- unsigned long long pts=0;
- unsigned long long dts av_unused = 0;
- int l;
- int pes_ext2_subid=-1;
- double stream_pts = MP_NOPTS_VALUE;
- demux_stream_t *ds=NULL;
- demux_packet_t* dp;
- mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id);
-
-// if(id==0x1F0){
-// demux->synced=0; // force resync after 0x1F0
-// return -1;
-//}
-
-// if(id==0x1BA) packet_start_pos=stream_tell(demux->stream);
- if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1;
- if(id==0x1BE) return -1; // padding stream
- if(id==0x1BF) return -1; // private2
-
- len=stream_read_word(demux->stream);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len);
-// if(len==62480){ demux->synced=0;return -1;} /* :) */
- if(len==0 || len>MAX_PS_PACKETSIZE){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len);
- return -2; // invalid packet !!!!!!
- }
-
- mpeg_pts_error=0;
-
- if(id==0x1BC) {
- parse_psm(demux, len);
- return 0;
- }
-
- while(len>0){ // Skip stuFFing bytes
- c=stream_read_char(demux->stream);
- --len;
- if(c!=0xFF)break;
- }
- if((c>>6)==1){ // Read (skip) STD scale & size value
-// printf(" STD_scale=%d",(c>>5)&1);
- d=((c&0x1F)<<8)|stream_read_char(demux->stream);
- len-=2;
-// printf(" STD_size=%d",d);
- c=stream_read_char(demux->stream);
- }
- // Read System-1 stream timestamps:
- if((c>>4)==2){
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- len-=4;
- } else
- if((c>>4)==3){
- pts=read_mpeg_timestamp(demux->stream,c);
- c=stream_read_char(demux->stream);
- if((c>>4)!=1) pts=0; //printf("{ERROR4}");
- else set_pts = 1;
- dts=read_mpeg_timestamp(demux->stream,c);
- len-=4+1+4;
- } else
- if((c>>6)==2){
- int pts_flags;
- int hdrlen;
- int parse_ext2;
- // System-2 (.VOB) stream:
- c=stream_read_char(demux->stream);
- pts_flags=c>>6;
- parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1);
- c=stream_read_char(demux->stream);
- hdrlen=c;
- len-=2;
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len);
- if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;}
- if(pts_flags==2 && hdrlen>=5){
- c=stream_read_char(demux->stream);
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- len-=5;hdrlen-=5;
- } else
- if(pts_flags==3 && hdrlen>=10){
- c=stream_read_char(demux->stream);
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- c=stream_read_char(demux->stream);
- dts=read_mpeg_timestamp(demux->stream,c);
- len-=10;hdrlen-=10;
- }
- len-=hdrlen;
- if(parse_ext2 && hdrlen>=3) {
- c=stream_read_char(demux->stream);
- hdrlen--;
-
- if((c & 0x0F) != 0x0F) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n");
- return -1;
- }
- if(c & 0x80) { //pes_private_data_flag
- if(hdrlen<16) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen);
- return -1;
- }
- stream_skip(demux->stream, 16);
- hdrlen-=16;
- }
- if(c & 0x40) { //pack_header_field_flag
- int l = stream_read_char(demux->stream);
- if(l < 0) //couldn't read from the stream?
- return -1;
- hdrlen--;
- if(l < 0 || hdrlen < l) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n",
- hdrlen, l);
- return -1;
- }
- stream_skip(demux->stream, l);
- hdrlen-=l;
- }
- if(c & 0x20) { //program_packet_sequence_counter_flag
- if(hdrlen < 2) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen);
- return -1;
- }
- stream_skip(demux->stream, 2);
- hdrlen-=2;
- }
- if(c & 0x10) {
- //STD
- stream_skip(demux->stream, 2);
- hdrlen-=2;
- }
- c=stream_read_char(demux->stream); //pes_extension2 flag
- hdrlen--;
- if(c!=0x81) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1 \n"); return -1;}
- c=stream_read_char(demux->stream); //pes_extension2 payload === substream id
- hdrlen--;
- if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;}
- pes_ext2_subid=c;
- }
- if(hdrlen>0)
- stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes
-
- if(id==0x1FD && pes_ext2_subid!=-1) {
- //==== EVO VC1 STREAMS ===//
- if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid);
- if(demux->video->id==-1) demux->video->id=pes_ext2_subid;
- if(demux->video->id==pes_ext2_subid){
- ds=demux->video;
- if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid];
- if(priv && ds->sh) {
- sh_video_t *sh = (sh_video_t *)ds->sh;
- sh->format = mmioFOURCC('W', 'V', 'C', '1');
- mp_set_video_codec_from_tag(sh);
- }
- }
- }
- //============== DVD Audio sub-stream ======================
- if(id==0x1BD){
- int aid, rawa52 = 0;
- int64_t tmppos;
- unsigned int tmp;
-
- tmppos = stream_tell(demux->stream);
- tmp = stream_read_word(demux->stream);
- stream_seek(demux->stream, tmppos);
- /// vdr stores A52 without the 4 header bytes, so we have to check this condition first
- if(tmp == 0x0B77) {
- aid = 128;
- rawa52 = 1;
- }
- else {
- aid=stream_read_char(demux->stream);--len;
- if(len<3) return -1; // invalid audio packet
- }
-
- // AID:
- // 0x20..0x3F subtitle
- // 0x80..0x87 and 0xC0..0xCF AC3 audio
- // 0x88..0x8F and 0x98..0x9F DTS audio
- // 0xA0..0xBF PCM audio
-
- if((aid & 0xE0) == 0x20){
- // subtitle:
- aid&=0x1F;
-
- if(!demux->s_streams[aid]){
- sh_sub_t *sh = new_sh_sub(demux, aid);
- if (sh) sh->gsh->codec = "dvd_subtitle_mpg";
- mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
- }
-
- if(demux->sub->id > -1)
- demux->sub->id &= 0x1F;
- if(!demux->opts->sub_lang && demux->sub->id == -1)
- demux->sub->id = aid;
- if(demux->sub->id==aid){
- ds=demux->sub;
- }
- } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) {
-
-// aid=128+(aid&0x7F);
- // aid=0x80..0xBF
- new_audio_stream(demux, aid);
- if(demux->audio->id==aid){
- int type;
- ds=demux->audio;
- if(!ds->sh) ds->sh=demux->a_streams[aid];
- // READ Packet: Skip additional audio header data:
- if(!rawa52) {
- c=stream_read_char(demux->stream);//num of frames
- type=stream_read_char(demux->stream);//startpos hi
- type=(type<<8)|stream_read_char(demux->stream);//startpos lo
-// printf("\r[%02X][%04X]",c,type);
- len-=3;
- }
- if((aid&0xE0)==0xA0 && len>=3){
- unsigned char* hdr;
- // save audio header as codecdata!
- if(!((sh_audio_t*)(ds->sh))->codecdata_len){
- ((sh_audio_t*)(ds->sh))->codecdata=malloc(3);
- ((sh_audio_t*)(ds->sh))->codecdata_len=3;
- }
- hdr=((sh_audio_t*)(ds->sh))->codecdata;
- // read LPCM header:
- // emphasis[1], mute[1], rvd[1], frame number[5]:
- hdr[0]=stream_read_char(demux->stream);
-// printf(" [%01X:%02d]",c>>5,c&31);
- // quantization[2],freq[2],rvd[1],channels[3]
- hdr[1]=stream_read_char(demux->stream);
-// printf("[%01X:%01X] ",c>>4,c&15);
- // dynamic range control (0x80=off):
- hdr[2]=stream_read_char(demux->stream);
-// printf("[%02X] ",c);
- len-=3;
- if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n");
- dvdpcm_header((sh_audio_t*)(ds->sh));
- mp_set_audio_codec_from_tag((sh_audio_t*)(ds->sh));
- }
-// printf(" \n");
- } // if(demux->audio->id==aid)
-
- } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid);
- } //if(id==0x1BD)
- } else {
- if(c!=0x0f){
- mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c);
- return -1; // invalid packet !!!!!!
- }
- }
- if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len);
-
-// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size
- if(len<=0 || len>MAX_PS_PACKETSIZE){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len);
- return -1; // invalid packet !!!!!!
- }
-
- if(id>=0x1C0 && id<=0x1DF){
- // mpeg audio
- int aid=id-0x1C0;
- new_audio_stream(demux, aid);
- if(demux->audio->id==aid){
- ds=demux->audio;
- if(!ds->sh) ds->sh=demux->a_streams[aid];
- if(priv && ds->sh) {
- sh_audio_t *sh = (sh_audio_t *)ds->sh;
- if(priv->es_map[id - 0x1B0])
- sh->format = priv->es_map[id - 0x1B0];
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
- dvdpcm_header(sh);
- mp_set_audio_codec_from_tag(sh);
- }
- }
- } else
- if(id>=0x1E0 && id<=0x1EF){
- // mpeg video
- int aid=id-0x1E0;
- if(!demux->v_streams[aid]) new_sh_video(demux,aid);
- if(demux->video->id==-1) demux->video->id=aid;
- if(demux->video->id==aid){
- ds=demux->video;
- if(!ds->sh) ds->sh=demux->v_streams[aid];
- if(priv && ds->sh) {
- sh_video_t *sh = (sh_video_t *)ds->sh;
- if(priv->es_map[id - 0x1B0]) {
- sh->format = priv->es_map[id - 0x1B0];
- mp_set_video_codec_from_tag(sh);
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
- }
- }
- }
- }
-
- if(ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);
-// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos);
-
- dp=new_demux_packet(len);
- if(!dp) {
- mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len);
- stream_skip(demux->stream,len);
- return 0;
- }
- l = stream_read(demux->stream,dp->buffer,len);
- if(l<len)
- resize_demux_packet(dp, l);
- len = l;
- if(set_pts)
- dp->pts=pts/90000.0f;
- dp->pos=demux->filepos;
- /*
- workaround:
- set dp->stream_pts only when feeding the video stream, or strangely interleaved files
- (such as SWIII) will show strange alternations in the stream time, wildly going
- back and forth
- */
- if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED)
- dp->stream_pts = stream_pts;
- ds_add_packet(ds,dp);
- if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;
-// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len);
- return 1;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id);
- if(len<=2356) stream_skip(demux->stream,len);
- return 0;
-}
-
-static int num_elementary_packets100=0;
-static int num_elementary_packets101=0;
-static int num_elementary_packets12x=0;
-static int num_elementary_packets1B6=0;
-static int num_elementary_packetsPES=0;
-static int num_mpeg12_startcode=0;
-static int num_h264_slice=0; //combined slice
-static int num_h264_dpa=0; //DPA Slice
-static int num_h264_dpb=0; //DPB Slice
-static int num_h264_dpc=0; //DPC Slice
-static int num_h264_idr=0; //IDR Slice
-static int num_h264_sps=0;
-static int num_h264_pps=0;
-
-static int num_mp3audio_packets=0;
-
-static void clear_stats(void)
-{
- num_elementary_packets100=0;
- num_elementary_packets101=0;
- num_elementary_packets1B6=0;
- num_elementary_packets12x=0;
- num_elementary_packetsPES=0;
- num_mpeg12_startcode=0;
- num_h264_slice=0; //combined slice
- num_h264_dpa=0; //DPA Slice
- num_h264_dpb=0; //DPB Slice
- num_h264_dpc=0; //DPC Slice
- num_h264_idr=0; //IDR Slice
- num_h264_sps=0;
- num_h264_pps=0;
- num_mp3audio_packets=0;
-}
-
-//assumes demuxer->synced < 2
-static inline void update_stats(int head)
-{
- if(head==0x1B6) ++num_elementary_packets1B6;
- else if(head==0x1B3 || head==0x1B8) ++num_mpeg12_startcode;
- else if(head==0x100) ++num_elementary_packets100;
- else if(head==0x101) ++num_elementary_packets101;
- else if(head==0x1BD || (0x1C0<=head && head<=0x1EF))
- num_elementary_packetsPES++;
- else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x;
- if(head>=0x100 && head<0x1B0)
- {
- if((head&~0x60) == 0x101) ++num_h264_slice;
- else if((head&~0x60) == 0x102) ++num_h264_dpa;
- else if((head&~0x60) == 0x103) ++num_h264_dpb;
- else if((head&~0x60) == 0x104) ++num_h264_dpc;
- else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr;
- else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps;
- else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps;
- }
-}
-
-static int demux_mpg_probe(demuxer_t *demuxer) {
- int pes av_unused = 1;
- int tmp;
- int64_t tmppos;
- int file_format = DEMUXER_TYPE_UNKNOWN;
-
- tmppos=stream_tell(demuxer->stream);
- tmp=stream_read_dword(demuxer->stream);
- if(tmp==0x1E0 || tmp==0x1C0) {
- tmp=stream_read_word(demuxer->stream);
- if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES...
- }
- stream_seek(demuxer->stream,tmppos);
-
- clear_stats();
-
- if(demux_mpg_open(demuxer))
- file_format=DEMUXER_TYPE_MPEG_PS;
- else {
- mp_msg(MSGT_DEMUX,MSGL_V,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d PES: %d MP3: %d, synced: %d\n",
- num_elementary_packets100,num_elementary_packets101,
- num_elementary_packets1B6,num_elementary_packets12x,
- num_h264_slice, num_h264_dpa,
- num_h264_dpb, num_h264_dpc=0,
- num_h264_idr, num_h264_sps=0,
- num_h264_pps,
- num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced);
-
- //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v)
- if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100
- && abs(num_elementary_packets100-num_elementary_packets101)>2)
- return file_format;
-
- // some hack to get meaningfull error messages to our unhappy users:
- if(num_mpeg12_startcode>=2 && num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
- abs(num_elementary_packets101+8-num_elementary_packets100)<16) {
- if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) {
- return file_format;
- }
- file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
- } else
- // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection!
- if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
- num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x &&
- demuxer->synced<2) {
- file_format=DEMUXER_TYPE_MPEG4_ES;
- } else
- // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection!
- if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
- /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 &&
- num_elementary_packets1B6==0 && num_elementary_packetsPES==0 &&
- demuxer->synced<2) {
- file_format=DEMUXER_TYPE_H264_ES;
- } else
- {
- if(demuxer->synced==2)
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "MPEG: %s",
- mp_gtext("Missing video stream!? Contact the author, it may be a bug :(\n"));
- else
- mp_tmsg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n");
- }
- }
- //FIXME this shouldn't be necessary
- stream_seek(demuxer->stream,tmppos);
- return file_format;
-}
-
-static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
- // Elementary video stream
- if(demux->stream->eof) return 0;
- demux->filepos=stream_tell(demux->stream);
- ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0);
- return 1;
-}
-
-/**
- * \brief discard until 0x100 header and return a filled buffer
- * \param b buffer-end pointer
- * \param pos current pos in stream, negative since b points to end of buffer
- * \param s stream to read from
- * \return new position, differs from original pos when eof hit and thus
- * b was modified to point to the new end of buffer
- */
-static int find_end(unsigned char **b, int pos, stream_t *s) {
- register int state = 0xffffffff;
- unsigned char *buf = *b;
- int start = pos;
- int read, unused;
- // search already read part
- while (state != 0x100 && pos) {
- state = state << 8 | buf[pos++];
- }
- // continue search in stream
- while (state != 0x100) {
- register int c = stream_read_char(s);
- if (c < 0) break;
- state = state << 8 | c;
- }
- // modify previous header (from 0x1bc or 0x1bf to 0x100)
- buf[start++] = 0;
- // copy remaining buffer part to current pos
- memmove(&buf[start], &buf[pos], -pos);
- unused = start + -pos; // -unused bytes in buffer
- read = stream_read(s, &buf[unused], -unused);
- unused += read;
- // fix buffer so it ends at pos == 0 (eof case)
- *b = &buf[unused];
- start -= unused;
- return start;
-}
-
-/**
- * This format usually uses an insane bitrate, which makes this function
- * performance-critical!
- * Be sure to benchmark any changes with different compiler versions.
- */
-static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
- demux_packet_t *pack;
- int len;
- demux->filepos = stream_tell(demux->stream);
- pack = new_demux_packet(STREAM_BUFFER_SIZE);
- len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE);
- if (len <= 0)
- {
- free_demux_packet(pack);
- return 0;
- }
- {
- register uint32_t state = (uint32_t)(uintptr_t)demux->priv;
- register int pos = -len;
- unsigned char *buf = &pack->buffer[len];
- do {
- state = state << 8 | buf[pos];
- if (unlikely((state | 3) == 0x1bf))
- pos = find_end(&buf, pos, demux->stream);
- } while (++pos < 0);
- demux->priv = (void *)(uintptr_t)state;
- len = buf - pack->buffer;
- }
- if (len < STREAM_BUFFER_SIZE)
- resize_demux_packet(pack, len);
- ds_add_packet(ds, pack);
- return 1;
-}
-
-static int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
-unsigned int head=0;
-int skipped=0;
-int max_packs=256; // 512kbyte
-int ret=0;
-
-// System stream
-do{
- demux->filepos=stream_tell(demux->stream);
- //lame workaround: this is needed to show the progress bar when playing dvdnav://
- //(ths poor guy doesn't know teh length of the stream at startup)
- demux->movi_end = demux->stream->end_pos;
- head=stream_read_dword(demux->stream);
- if((head&0xFFFFFF00)!=0x100){
- // sync...
- demux->filepos-=skipped;
- while(1){
- int c=stream_read_char(demux->stream);
- if(c<0) break; //EOF
- head<<=8;
- if(head!=0x100){
- head|=c;
- if(mp_check_mp3_header(head)) ++num_mp3audio_packets;
- ++skipped; //++demux->filepos;
- continue;
- }
- head|=c;
- break;
- }
- demux->filepos+=skipped;
- }
- if(stream_eof(demux->stream)) break;
- // sure: head=0x000001XX
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head);
- if(demux->synced==0){
- if(head==0x1BA) demux->synced=1; //else
-// if(head==0x1BD || (head>=0x1C0 && head<=0x1EF)) demux->synced=3; // PES?
- } else
- if(demux->synced==1){
- if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){
- demux->synced=2;
- mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%"PRIX64" (%"PRId64")!\n",(int64_t)demux->filepos,(int64_t)demux->filepos);
- num_elementary_packets100=0; // requires for re-sync!
- num_elementary_packets101=0; // requires for re-sync!
- } else demux->synced=0;
- } // else
- if(demux->synced>=2){
- ret=demux_mpg_read_packet(demux,head);
- if(!ret)
- if(--max_packs==0){
- demux->stream->eof=1;
- mp_tmsg(MSGT_DEMUX,MSGL_ERR,"demux: File doesn't contain the selected audio or video stream.\n");
- return 0;
- }
- if(demux->synced==3) demux->synced=(ret==1)?2:0; // PES detect
- } else {
- update_stats(head);
- if(head>=0x100 && head<0x1B0)
- mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head);
- else if((head>=0x1C0 && head<0x1F0) || head==0x1BD)
- mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head);
-
- if(((num_elementary_packets100>50 && num_elementary_packets101>50) ||
- (num_elementary_packetsPES>50)) && skipped>4000000){
- mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n");
- demux->stream->eof=1;
- break;
- }
- if(num_mp3audio_packets>100 && num_elementary_packets100<10){
- mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be MP3 stream...\n");
- demux->stream->eof=1;
- break;
- }
- }
-} while(ret!=1);
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped);
- if(demux->stream->eof){
- mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n");
- return 0;
- }
- return 1;
-}
-
-static void demux_seek_mpg(demuxer_t *demuxer, float rel_seek_secs,
- float audio_delay, int flags)
-{
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
- int precision = 1;
- float oldpts = 0;
- int64_t oldpos = demuxer->filepos;
- float newpts = 0;
- int64_t newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : oldpos;
-
- if(mpg_d)
- oldpts = mpg_d->last_pts;
- newpts = (flags & SEEK_ABSOLUTE) ? 0.0 : oldpts;
- //================= seek in MPEG ==========================
- //calculate the pts to seek to
- if(flags & SEEK_FACTOR) {
- if (mpg_d && mpg_d->first_to_final_pts_len > 0.0)
- newpts += mpg_d->first_to_final_pts_len * rel_seek_secs;
- else
- newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
- } else
- newpts += rel_seek_secs;
- if (newpts < 0) newpts = 0;
-
- if(flags&SEEK_FACTOR){
- // float seek 0..1
- newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
- } else {
- // time seek (secs)
- if (mpg_d && mpg_d->has_valid_timestamps) {
- if (mpg_d->first_to_final_pts_len > 0.0)
- newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->first_to_final_pts_len;
- else if (oldpts > 0.0)
- newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
- } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
- newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
- else
- newpos+=sh_video->i_bps*rel_seek_secs;
- }
-
- while (1) {
- if(newpos<demuxer->movi_start){
- if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
- if(newpos<demuxer->movi_start) newpos=demuxer->movi_start;
- }
-
- stream_seek(demuxer->stream,newpos);
-
- // re-sync video:
- videobuf_code_len=0; // reset ES stream buffer
-
- ds_fill_buffer(d_video);
- if(sh_audio){
- ds_fill_buffer(d_audio);
- }
-
- while(1){
- int i;
- if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){
- float a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
- if(d_video->pts>a_pts){
- skip_audio_frame(sh_audio); // sync audio
- continue;
- }
- }
- if(!sh_video) break;
- i=sync_video_packet(d_video);
- if(sh_video->format == mmioFOURCC('W', 'V', 'C', '1')) {
- if(i==0x10E || i==0x10F) //entry point or sequence header
- break;
- } else
- if(sh_video->format == 0x10000004) { //mpeg4
- if(i==0x1B6) { //vop (frame) startcode
- int pos = videobuf_len;
- if(!read_video_packet(d_video)) break; // EOF
- if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame
- }
- } else if(sh_video->format == 0x10000005){ //h264
- if((i & ~0x60) == 0x105) break;
- } else { //default mpeg1/2
- if(i==0x1B3 || i==0x1B8) break; // found it!
- }
- if(!i || !skip_video_packet(d_video)) break; // EOF?
- }
- if(!mpg_d)
- break;
- if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break;
- if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps
- mpg_d->has_valid_timestamps = 0;
- break;
- }
- precision--;
- //prepare another seek because we are off by more than 0.5s
- if(mpg_d) {
- newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts);
- demux_flush(demuxer);
- demuxer->stream->eof=0; // clear eof flag
- d_video->eof=0;
- d_audio->eof=0;
- }
- }
-}
-
-static int demux_mpg_control(demuxer_t *demuxer, int cmd, void *arg)
-{
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, arg) != STREAM_UNSUPPORTED) {
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\r\nDEMUX_MPG_CTRL, (%.3f)\r\n", *((double*)arg));
- return DEMUXER_CTRL_GUESS;
- }
- if (mpg_d && mpg_d->has_valid_timestamps) {
- *((double *)arg)=(double)mpg_d->first_to_final_pts_len;
- return DEMUXER_CTRL_OK;
- }
- return DEMUXER_CTRL_DONTKNOW;
-
- case DEMUXER_CTRL_GET_START_TIME:
- if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) {
- *((float *)arg)=mpg_d->first_pts;
- return DEMUXER_CTRL_OK;
- }
- return DEMUXER_CTRL_DONTKNOW;
-
- case DEMUXER_CTRL_SWITCH_AUDIO:
- if(! (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh))
- return DEMUXER_CTRL_NOTIMPL;
- else {
- demux_stream_t *d_audio = demuxer->audio;
- sh_audio_t *sh_audio = d_audio->sh;
- sh_audio_t *sh_a = sh_audio;
- int i;
- if(!sh_audio)
- return DEMUXER_CTRL_NOTIMPL;
- if (*((int*)arg) < 0)
- {
- for (i = 0; i < mpg_d->num_a_streams; i++) {
- if (d_audio->id == mpg_d->a_stream_ids[i]) break;
- }
- i = (i+1) % mpg_d->num_a_streams;
- sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]];
- }
- else {
- for (i = 0; i < mpg_d->num_a_streams; i++)
- if (*((int*)arg) == mpg_d->a_stream_ids[i]) break;
- if (i < mpg_d->num_a_streams)
- sh_a = (sh_audio_t*)demuxer->a_streams[*((int*)arg)];
- }
- if (i < mpg_d->num_a_streams && d_audio->id != mpg_d->a_stream_ids[i]) {
- d_audio->id = mpg_d->a_stream_ids[i];
- d_audio->sh = sh_a;
- ds_free_packs(d_audio);
- }
- }
- *((int*)arg) = demuxer->audio->id;
- return DEMUXER_CTRL_OK;
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static int demux_mpg_pes_probe(demuxer_t *demuxer) {
- demuxer->synced = 3;
- return (demux_mpg_probe(demuxer) == DEMUXER_TYPE_MPEG_PS) ? DEMUXER_TYPE_MPEG_PES : 0;
-}
-
-
-static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer)
-{
- sh_video_t *sh_video=NULL;
-
- demuxer->audio->sh = NULL; // ES streams has no audio channel
- demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
-
- demuxer->ts_resets_possible = true;
-
- return demuxer;
-}
-
-static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) {
- demuxer->audio->sh = NULL;
- demuxer->video->sh = new_sh_video(demuxer,0);
- ((sh_video_t *)demuxer->video->sh)->ds = demuxer->video;
- demuxer->priv = (void *) 0xffffffff;
-
- demuxer->ts_resets_possible = true;
-
- return demuxer;
-}
-
-static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
-{
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
-
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
-
- demuxer->ts_resets_possible = true;
-
- if(demuxer->audio->id!=-2) {
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "MPEG: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- } else {
- sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
- }
- }
-
- if(!sh_video->format && ps_probe > 0) {
- int head;
- int64_t pos = stream_tell(demuxer->stream);
-
- clear_stats();
- do {
- head=sync_video_packet(demuxer->video);
- if(!head) break;
- update_stats(head);
- skip_video_packet(demuxer->video);
- } while(stream_tell(demuxer->stream) < pos + ps_probe && !demuxer->stream->eof);
-
- ds_free_packs(demuxer->video);
- demuxer->stream->eof=0;
- stream_seek(demuxer->stream, pos);
- mp_msg(MSGT_DEMUX,MSGL_INFO,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d\n",
- num_elementary_packets100, num_elementary_packets101,
- num_elementary_packets1B6, num_elementary_packets12x,
- num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc,
- num_h264_idr, num_h264_sps, num_h264_pps);
-
- if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
- num_elementary_packets100<=num_elementary_packets12x)
- sh_video->format = 0x10000004;
- else if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
- num_h264_sps>=1 && num_h264_pps>=1 && num_h264_idr>=1 &&
- num_elementary_packets1B6==0)
- sh_video->format = 0x10000005;
- else sh_video->format = 0x10000002;
- mp_set_video_codec_from_tag(sh_video);
- }
-
- return demuxer;
-}
-
-
-const demuxer_desc_t demuxer_desc_mpeg_ps = {
- "MPEG PS demuxer",
- "mpegps",
- "MPEG-PS",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_PS,
- 0, // unsafe autodetect
- demux_mpg_probe,
- demux_mpg_fill_buffer,
- demux_mpg_ps_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg_pes = {
- "MPEG PES demuxer",
- "mpegpes",
- "MPEG-PES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_PES,
- 0, // unsafe autodetect
- demux_mpg_pes_probe,
- demux_mpg_fill_buffer,
- demux_mpg_ps_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg_gxf = {
- "MPEG ES in GXF demuxer",
- "mpeggxf",
- "MPEG-ES in GXF",
- "Reimar Doeffinger",
- "Mpeg",
- DEMUXER_TYPE_MPEG_GXF,
- 0, // hack autodetection
- NULL,
- demux_mpg_gxf_fill_buffer,
- demux_mpg_gxf_open,
- NULL,
- NULL,
- NULL
-};
-
-const demuxer_desc_t demuxer_desc_mpeg_es = {
- "MPEG ES demuxer",
- "mpeges",
- "MPEG-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg4_es = {
- "MPEG4 ES demuxer",
- "mpeg4es",
- "MPEG-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG4_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_h264_es = {
- "H.264 ES demuxer",
- "h264es",
- "H264-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_H264_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
diff --git a/demux/demux_raw.c b/demux/demux_raw.c
new file mode 100644
index 0000000000..4b3e8844a4
--- /dev/null
+++ b/demux/demux_raw.c
@@ -0,0 +1,274 @@
+/*
+ * 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 "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "core/m_option.h"
+
+#include "stream/stream.h"
+#include "demux.h"
+#include "stheader.h"
+#include "audio/format.h"
+
+#include "video/img_format.h"
+#include "video/img_fourcc.h"
+
+struct priv {
+ int frame_size;
+ double frame_rate;
+};
+
+static struct mp_chmap channels = MP_CHMAP_INIT_STEREO;
+static int samplerate = 44100;
+static int aformat = AF_FORMAT_S16_NE;
+
+const m_option_t demux_rawaudio_opts[] = {
+ { "channels", &channels, &m_option_type_chmap, CONF_MIN, 1 },
+ { "rate", &samplerate, CONF_TYPE_INT, CONF_RANGE, 1000, 8 * 48000, NULL },
+ { "format", &aformat, CONF_TYPE_AFMT, 0, 0, 0, NULL },
+ {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+static int vformat = MP_FOURCC_I420;
+static int mp_format;
+static char *codec;
+static int width = 0;
+static int height = 0;
+static float fps = 25;
+static int imgsize = 0;
+
+const m_option_t demux_rawvideo_opts[] = {
+ // size:
+ { "w", &width, CONF_TYPE_INT, CONF_RANGE, 1, 8192, NULL },
+ { "h", &height, CONF_TYPE_INT, CONF_RANGE, 1, 8192, NULL },
+ // format:
+ { "format", &vformat, CONF_TYPE_FOURCC, 0, 0, 0, NULL },
+ { "mp-format", &mp_format, CONF_TYPE_IMGFMT, 0, 0, 0, NULL },
+ { "codec", &codec, CONF_TYPE_STRING, 0, 0, 0, NULL },
+ // misc:
+ { "fps", &fps, CONF_TYPE_FLOAT, CONF_RANGE, 0.001, 1000, NULL },
+ { "size", &imgsize, CONF_TYPE_INT, CONF_RANGE, 1, 8192 * 8192 * 4, NULL },
+
+ {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+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 ((aformat & AF_FORMAT_SPECIAL_MASK) != 0)
+ return -1;
+
+ sh = new_sh_stream(demuxer, STREAM_AUDIO);
+ sh_audio = sh->audio;
+ sh_audio->gsh->codec = "mp-pcm";
+ sh_audio->format = aformat;
+ sh_audio->wf = w = malloc(sizeof(*w));
+ w->wFormatTag = 0;
+ sh_audio->channels = channels;
+ w->nChannels = sh_audio->channels.num;
+ w->nSamplesPerSec = sh_audio->samplerate = samplerate;
+ int samplesize = (af_fmt2bits(aformat) + 7) / 8;
+ w->nAvgBytesPerSec = samplerate * samplesize * w->nChannels;
+ w->nBlockAlign = w->nChannels * samplesize;
+ w->wBitsPerSample = 8 * samplesize;
+ w->cbSize = 0;
+
+ demuxer->movi_start = demuxer->stream->start_pos;
+ demuxer->movi_end = demuxer->stream->end_pos;
+
+ struct priv *p = talloc_ptrtype(demuxer, p);
+ demuxer->priv = p;
+ *p = (struct priv) {
+ .frame_size = samplesize * sh_audio->channels.num,
+ .frame_rate = samplerate,
+ };
+
+ return 0;
+}
+
+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;
+ }
+
+ const char *decoder = "rawvideo";
+ int imgfmt = vformat;
+ if (mp_format) {
+ decoder = "mp-rawvideo";
+ imgfmt = mp_format;
+ if (!imgsize) {
+ struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(mp_format);
+ for (int p = 0; p < desc.num_planes; p++) {
+ imgsize += ((width >> desc.xs[p]) * (height >> desc.ys[p]) *
+ desc.bpp[p] + 7) / 8;
+ }
+ }
+ } else if (codec && codec[0])
+ decoder = talloc_strdup(demuxer, codec);
+
+ if (!imgsize) {
+ int bpp = 0;
+ switch (vformat) {
+ case MP_FOURCC_I420: case MP_FOURCC_IYUV:
+ case MP_FOURCC_NV12: case MP_FOURCC_NV21:
+ case MP_FOURCC_HM12:
+ case MP_FOURCC_YV12:
+ bpp = 12;
+ break;
+ case MP_FOURCC_RGB12: case MP_FOURCC_BGR12:
+ case MP_FOURCC_RGB15: case MP_FOURCC_BGR15:
+ case MP_FOURCC_RGB16: case MP_FOURCC_BGR16:
+ case MP_FOURCC_YUY2: case MP_FOURCC_UYVY:
+ bpp = 16;
+ break;
+ case MP_FOURCC_RGB8: case MP_FOURCC_BGR8:
+ case MP_FOURCC_Y800: case MP_FOURCC_Y8:
+ bpp = 8;
+ break;
+ case MP_FOURCC_RGB24: case MP_FOURCC_BGR24:
+ bpp = 24;
+ break;
+ case MP_FOURCC_RGB32: case MP_FOURCC_BGR32:
+ bpp = 32;
+ break;
+ }
+ if (!bpp) {
+ mp_msg(MSGT_DEMUX, MSGL_ERR,
+ "rawvideo: img size not specified and unknown format!\n");
+ return -1;
+ }
+ imgsize = width * height * bpp / 8;
+ }
+
+ sh = new_sh_stream(demuxer, STREAM_VIDEO);
+ sh_video = sh->video;
+ sh_video->gsh->codec = decoder;
+ sh_video->format = imgfmt;
+ sh_video->fps = fps;
+ sh_video->disp_w = width;
+ sh_video->disp_h = height;
+ sh_video->i_bps = fps * imgsize;
+
+ demuxer->movi_start = demuxer->stream->start_pos;
+ demuxer->movi_end = demuxer->stream->end_pos;
+
+ struct priv *p = talloc_ptrtype(demuxer, p);
+ demuxer->priv = p;
+ *p = (struct priv) {
+ .frame_size = imgsize,
+ .frame_rate = fps,
+ };
+
+ return 0;
+}
+
+static int raw_fill_buffer(demuxer_t *demuxer)
+{
+ struct priv *p = demuxer->priv;
+
+ if (demuxer->stream->eof)
+ return 0;
+
+ struct demux_packet *dp = new_demux_packet(p->frame_size);
+ dp->pos = stream_tell(demuxer->stream) - demuxer->movi_start;
+ dp->pts = (dp->pos / p->frame_size) / p->frame_rate;
+
+ int len = stream_read(demuxer->stream, dp->buffer, dp->len);
+ resize_demux_packet(dp, len);
+ demuxer_add_packet(demuxer, demuxer->streams[0], dp);
+
+ return 1;
+}
+
+static void raw_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay,
+ int flags)
+{
+ struct priv *p = demuxer->priv;
+ stream_t *s = demuxer->stream;
+ stream_update_size(s);
+ int64_t start = s->start_pos;
+ int64_t end = s->end_pos;
+ int64_t pos = (flags & SEEK_ABSOLUTE) ? start : stream_tell(s);
+ if (flags & SEEK_FACTOR)
+ pos += (end - start) * rel_seek_secs;
+ else
+ pos += rel_seek_secs * p->frame_rate * p->frame_size;
+ if (pos < 0)
+ pos = 0;
+ if (end && pos > end)
+ pos = end;
+ stream_seek(s, (pos / p->frame_size) * p->frame_size);
+}
+
+static int raw_control(demuxer_t *demuxer, int cmd, void *arg)
+{
+ struct priv *p = demuxer->priv;
+
+ switch (cmd) {
+ case DEMUXER_CTRL_GET_TIME_LENGTH: {
+ stream_t *s = demuxer->stream;
+ stream_update_size(s);
+ int64_t start = s->start_pos;
+ int64_t end = s->end_pos;
+ if (!end)
+ return DEMUXER_CTRL_DONTKNOW;
+
+ *((double *) arg) = ((end - start) / p->frame_size) / p->frame_rate;
+ return DEMUXER_CTRL_OK;
+ }
+ default:
+ return DEMUXER_CTRL_NOTIMPL;
+ }
+}
+
+const demuxer_desc_t demuxer_desc_rawaudio = {
+ .name = "rawaudio",
+ .desc = "Uncompressed audio",
+ .open = demux_rawaudio_open,
+ .fill_buffer = raw_fill_buffer,
+ .seek = raw_seek,
+ .control = raw_control,
+};
+
+const demuxer_desc_t demuxer_desc_rawvideo = {
+ .name = "rawvideo",
+ .desc = "Uncompressed video",
+ .open = demux_rawvideo_open,
+ .fill_buffer = raw_fill_buffer,
+ .seek = raw_seek,
+ .control = raw_control,
+};
diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c
deleted file mode 100644
index 3cd2500e03..0000000000
--- a/demux/demux_rawaudio.c
+++ /dev/null
@@ -1,127 +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 "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "core/m_option.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "audio/format.h"
-
-
-static struct mp_chmap channels = MP_CHMAP_INIT_STEREO;
-static int samplerate = 44100;
-static int format = AF_FORMAT_S16_NE;
-
-const m_option_t demux_rawaudio_opts[] = {
- { "channels", &channels, &m_option_type_chmap, CONF_MIN, 1 },
- { "rate", &samplerate, CONF_TYPE_INT,CONF_RANGE,1000,8*48000, NULL },
- { "format", &format, CONF_TYPE_AFMT, 0, 0, 0, NULL },
- {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-
-static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) {
- sh_audio_t* sh_audio;
- WAVEFORMATEX* w;
-
- if ((format & AF_FORMAT_SPECIAL_MASK) != 0)
- return NULL;
-
- sh_audio = new_sh_audio(demuxer,0);
- sh_audio->gsh->codec = "mp-pcm";
- sh_audio->format = format;
- sh_audio->wf = w = malloc(sizeof(*w));
- w->wFormatTag = 0;
- sh_audio->channels = channels;
- w->nChannels = sh_audio->channels.num;
- w->nSamplesPerSec = sh_audio->samplerate = samplerate;
- int samplesize = (af_fmt2bits(format) + 7) / 8;
- w->nAvgBytesPerSec = samplerate * samplesize * w->nChannels;
- w->nBlockAlign = w->nChannels * samplesize;
- w->wBitsPerSample = 8 * samplesize;
- w->cbSize = 0;
-
- 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;
- sh_audio->needs_parsing = 1;
-
- return demuxer;
-}
-
-static int demux_rawaudio_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) {
- sh_audio_t* sh_audio = demuxer->audio->sh;
- int l = sh_audio->wf->nAvgBytesPerSec;
- int64_t spos = stream_tell(demuxer->stream);
- demux_packet_t* dp;
-
- if(demuxer->stream->eof)
- return 0;
-
- dp = new_demux_packet(l);
- dp->pts = (spos - demuxer->movi_start) / (float)(sh_audio->wf->nAvgBytesPerSec);
- dp->pos = (spos - demuxer->movi_start);
-
- l = stream_read(demuxer->stream,dp->buffer,l);
- resize_demux_packet(dp, l);
- ds_add_packet(ds,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->sh;
- int64_t base,pos;
-
- base = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s);
- if(flags & SEEK_FACTOR)
- pos = base + ((demuxer->movi_end - demuxer->movi_start)*rel_seek_secs);
- else
- pos = base + (rel_seek_secs*sh_audio->i_bps);
-
- pos -= (pos % (sh_audio->channels.num * sh_audio->samplesize) );
- stream_seek(s,pos);
-// printf("demux_rawaudio: streamtell=%d\n",(int)stream_tell(demuxer->stream));
-}
-
-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,
-};
diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c
deleted file mode 100644
index 1a09b8308a..0000000000
--- a/demux/demux_rawvideo.c
+++ /dev/null
@@ -1,178 +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 "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "core/m_option.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-
-#include "video/img_format.h"
-#include "video/img_fourcc.h"
-
-static int format = MP_FOURCC_I420;
-static int mp_format;
-static char *codec;
-static int width = 0;
-static int height = 0;
-static float fps = 25;
-static int imgsize=0;
-
-const m_option_t demux_rawvideo_opts[] = {
- // size:
- { "w", &width, CONF_TYPE_INT,CONF_RANGE,1,8192, NULL },
- { "h", &height, CONF_TYPE_INT,CONF_RANGE,1,8192, NULL },
- // format:
- { "format", &format, CONF_TYPE_FOURCC, 0, 0 , 0, NULL },
- { "mp-format", &mp_format, CONF_TYPE_IMGFMT, 0, 0 , 0, NULL },
- { "codec", &codec, CONF_TYPE_STRING, 0, 0 , 0, NULL },
- // misc:
- { "fps", &fps, CONF_TYPE_FLOAT,CONF_RANGE,0.001,1000, NULL },
- { "size", &imgsize, CONF_TYPE_INT, CONF_RANGE, 1 , 8192*8192*4, NULL },
-
- {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-
-static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) {
- sh_video_t* sh_video;
-
- if(!width || !height){
- mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: width or height not specified!\n");
- return 0;
- }
-
- const char *decoder = "rawvideo";
- int imgfmt = format;
- if (mp_format) {
- decoder = "mp-rawvideo";
- imgfmt = mp_format;
- if (!imgsize) {
- struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(mp_format);
- for (int p = 0; p < desc.num_planes; p++) {
- imgsize += ((width >> desc.xs[p]) * (height >> desc.ys[p]) *
- desc.bpp[p] + 7) / 8;
- }
- }
- } else if (codec && codec[0]) {
- decoder = talloc_strdup(demuxer, codec);
- }
-
- if (!imgsize) {
- int bpp = 0;
- switch(format){
- case MP_FOURCC_I420: case MP_FOURCC_IYUV:
- case MP_FOURCC_NV12: case MP_FOURCC_NV21:
- case MP_FOURCC_HM12:
- case MP_FOURCC_YV12:
- bpp = 12;
- break;
- case MP_FOURCC_RGB12: case MP_FOURCC_BGR12:
- case MP_FOURCC_RGB15: case MP_FOURCC_BGR15:
- case MP_FOURCC_RGB16: case MP_FOURCC_BGR16:
- case MP_FOURCC_YUY2: case MP_FOURCC_UYVY:
- bpp = 16;
- break;
- case MP_FOURCC_RGB8: case MP_FOURCC_BGR8:
- case MP_FOURCC_Y800: case MP_FOURCC_Y8:
- bpp = 8;
- break;
- case MP_FOURCC_RGB24: case MP_FOURCC_BGR24:
- bpp = 24;
- break;
- case MP_FOURCC_RGB32: case MP_FOURCC_BGR32:
- bpp = 32;
- break;
- }
- if (!bpp) {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: img size not specified and unknown format!\n");
- return 0;
- }
- imgsize = width * height * bpp / 8;
- }
-
- sh_video = new_sh_video(demuxer,0);
- sh_video->gsh->codec=decoder;
- sh_video->format=imgfmt;
- sh_video->fps=fps;
- sh_video->frametime=1.0/fps;
- sh_video->disp_w=width;
- sh_video->disp_h=height;
- sh_video->i_bps=fps*imgsize;
-
- 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;
- 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);
- 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->sh;
- 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);
- 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;
- demuxer->video->pts = pos * sh_video->frametime;
-// printf("demux_rawvideo: streamtell=%d\n",(int)stream_tell(demuxer->stream));
-}
-
-
-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
-};
diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c
index ca03e73c33..6cbea0d8ec 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;
@@ -1336,11 +1339,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;
@@ -1353,12 +1356,10 @@ static int d_check_file(struct demuxer *demuxer)
add_sub_data(demuxer, sd);
subdata_free(sd);
- demuxer->accurate_seek = true;
-
- return DEMUXER_TYPE_SUBREADER;
+ return 0;
}
-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,
@@ -1377,8 +1378,6 @@ static int d_control(struct demuxer *demuxer, int cmd, void *arg)
{
struct priv *p = demuxer->priv;
switch (cmd) {
- case DEMUXER_CTRL_CORRECT_PTS:
- return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_GET_TIME_LENGTH:
*((double *) arg) = demux_packet_list_duration(p->pkts, p->num_pkts);
return DEMUXER_CTRL_OK;
@@ -1388,14 +1387,9 @@ 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 = "",
- .type = DEMUXER_TYPE_SUBREADER,
- .safe_check = 1,
- .check_file = d_check_file,
+ .desc = "Deprecated MPlayer subreader",
+ .open = d_open_file,
.fill_buffer = d_fill_buffer,
.seek = d_seek,
.control = d_control,
diff --git a/demux/demux_ts.c b/demux/demux_ts.c
deleted file mode 100644
index a16891907d..0000000000
--- a/demux/demux_ts.c
+++ /dev/null
@@ -1,3532 +0,0 @@
-/*
- * Demultiplexer for MPEG2 Transport Streams.
- *
- * Written by Nico <nsabbi@libero.it>
- * Kind feedback is appreciated; 'sucks' and alike is not.
- * Originally based on demux_pva.c written by Matteo Giani and FFmpeg (libavformat) sources
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-#include "core/options.h"
-
-#include "audio/decode/dec_audio.h"
-#include "stream/stream.h"
-#include "demux.h"
-#include "parse_es.h"
-#include "stheader.h"
-#include "ms_hdr.h"
-#include "mpeg_hdr.h"
-#include "demux_ts.h"
-
-#define TS_PH_PACKET_SIZE 192
-#define TS_FEC_PACKET_SIZE 204
-#define TS_PACKET_SIZE 188
-#define NB_PID_MAX 8192
-
-#define MAX_HEADER_SIZE 6 /* enough for PES header + length */
-#define MAX_CHECK_SIZE 65535
-#define NUM_CONSECUTIVE_TS_PACKETS 32
-#define NUM_CONSECUTIVE_AUDIO_PACKETS 348
-#define MAX_A52_FRAME_SIZE 3840
-
-#ifndef SIZE_MAX
-#define SIZE_MAX ((size_t)-1)
-#endif
-
-#define TYPE_AUDIO 1
-#define TYPE_VIDEO 2
-#define TYPE_SUB 3
-
-int ts_prog;
-int ts_keep_broken=0;
-int64_t ts_probe = 0;
-int audio_substream_id = -1;
-
-typedef enum
-{
- UNKNOWN = -1,
- VIDEO_MPEG1 = 0x10000001,
- VIDEO_MPEG2 = 0x10000002,
- VIDEO_MPEG4 = 0x10000004,
- VIDEO_H264 = 0x10000005,
- VIDEO_AVC = mmioFOURCC('a', 'v', 'c', '1'),
- VIDEO_DIRAC = mmioFOURCC('d', 'r', 'a', 'c'),
- VIDEO_VC1 = mmioFOURCC('W', 'V', 'C', '1'),
- AUDIO_MP2 = 0x50,
- AUDIO_A52 = 0x2000,
- AUDIO_DTS = 0x2001,
- AUDIO_LPCM_BE = 0x10001,
- AUDIO_AAC = mmioFOURCC('M', 'P', '4', 'A'),
- AUDIO_AAC_LATM = mmioFOURCC('M', 'P', '4', 'L'),
- AUDIO_TRUEHD = mmioFOURCC('T', 'R', 'H', 'D'),
- AUDIO_S302M = mmioFOURCC('B', 'S', 'S', 'D'),
- AUDIO_PCM_BR = mmioFOURCC('B', 'P', 'C', 'M'),
- SPU_DVD = 0x3000000,
- SPU_DVB = 0x3000001,
- SPU_TELETEXT = 0x3000002,
- SPU_PGS = 0x3000003,
- PES_PRIVATE1 = 0xBD00000,
- SL_PES_STREAM = 0xD000000,
- SL_SECTION = 0xD100000,
- MP4_OD = 0xD200000,
-} es_stream_type_t;
-
-typedef struct {
- uint8_t *buffer;
- uint16_t buffer_len;
-} ts_section_t;
-
-typedef struct {
- int size;
- unsigned char *start;
- uint16_t payload_size;
- es_stream_type_t type, subtype;
- double pts, last_pts;
- int pid;
- char lang[4];
- int last_cc; // last cc code (-1 if first packet)
- int is_synced;
- ts_section_t section;
- uint8_t *extradata;
- int extradata_alloc, extradata_len;
- struct {
- uint8_t au_start, au_end, last_au_end;
- } sl;
-} ES_stream_t;
-
-typedef struct {
- void *sh;
- int id;
- int type;
-} sh_av_t;
-
-typedef struct MpegTSContext {
- int packet_size; // raw packet size, including FEC if present e.g. 188 bytes
- ES_stream_t *pids[NB_PID_MAX];
- sh_av_t streams[NB_PID_MAX];
-} MpegTSContext;
-
-
-typedef struct {
- demux_stream_t *ds;
- demux_packet_t *pack;
- int offset, buffer_size;
-} av_fifo_t;
-
-#define MAX_EXTRADATA_SIZE 64*1024
-typedef struct {
- int32_t object_type; //aka codec used
- int32_t stream_type; //video, audio etc.
- uint8_t buf[MAX_EXTRADATA_SIZE];
- uint16_t buf_size;
- uint8_t szm1;
-} mp4_decoder_config_t;
-
-typedef struct {
- //flags
- uint8_t flags;
- uint8_t au_start;
- uint8_t au_end;
- uint8_t random_accesspoint;
- uint8_t random_accesspoint_only;
- uint8_t padding;
- uint8_t use_ts;
- uint8_t idle;
- uint8_t duration;
-
- uint32_t ts_resolution, ocr_resolution;
- uint8_t ts_len, ocr_len, au_len, instant_bitrate_len, degr_len, au_seqnum_len, packet_seqnum_len;
- uint32_t timescale;
- uint16_t au_duration, cts_duration;
- uint64_t ocr, dts, cts;
-} mp4_sl_config_t;
-
-typedef struct {
- uint16_t id;
- uint8_t flags;
- mp4_decoder_config_t decoder;
- mp4_sl_config_t sl;
-} mp4_es_descr_t;
-
-typedef struct {
- uint16_t id;
- uint8_t flags;
- mp4_es_descr_t *es;
- uint16_t es_cnt;
-} mp4_od_t;
-
-typedef struct {
- uint8_t skip;
- uint8_t table_id;
- uint8_t ssi;
- uint16_t section_length;
- uint16_t ts_id;
- uint8_t version_number;
- uint8_t curr_next;
- uint8_t section_number;
- uint8_t last_section_number;
- struct pat_progs_t {
- uint16_t id;
- uint16_t pmt_pid;
- } *progs;
- uint16_t progs_cnt;
- ts_section_t section;
-} pat_t;
-
-typedef struct {
- uint16_t progid;
- uint8_t skip;
- uint8_t table_id;
- uint8_t ssi;
- uint16_t section_length;
- uint8_t version_number;
- uint8_t curr_next;
- uint8_t section_number;
- uint8_t last_section_number;
- uint16_t PCR_PID;
- uint16_t prog_descr_length;
- ts_section_t section;
- uint16_t es_cnt;
- struct pmt_es_t {
- uint16_t pid;
- uint32_t type; //it's 8 bit long, but cast to the right type as FOURCC
- uint16_t descr_length;
- uint8_t format_descriptor[5];
- uint8_t lang[4];
- uint16_t mp4_es_id;
- } *es;
- mp4_od_t iod, *od;
- mp4_es_descr_t *mp4es;
- int od_cnt, mp4es_cnt;
-} pmt_t;
-
-typedef struct {
- uint64_t size;
- float duration;
- double first_pts;
- double last_pts;
-} TS_stream_info;
-
-typedef struct {
- MpegTSContext ts;
- int last_pid;
- av_fifo_t fifo[3]; //0 for audio, 1 for video, 2 for subs
- pat_t pat;
- pmt_t *pmt;
- uint16_t pmt_cnt;
- uint32_t prog;
- uint32_t vbitrate;
- int keep_broken;
- int last_aid;
- int last_vid;
- int last_sid;
- char packet[TS_FEC_PACKET_SIZE];
- TS_stream_info vstr, astr;
-} ts_priv_t;
-
-
-typedef struct {
- es_stream_type_t type;
- ts_section_t section;
-} TS_pids_t;
-
-
-static int IS_AUDIO(es_stream_type_t type)
-{
- switch (type) {
- case AUDIO_MP2:
- case AUDIO_A52:
- case AUDIO_LPCM_BE:
- case AUDIO_PCM_BR:
- case AUDIO_AAC:
- case AUDIO_AAC_LATM:
- case AUDIO_DTS:
- case AUDIO_TRUEHD:
- case AUDIO_S302M:
- return 1;
- }
- return 0;
-}
-
-static int IS_VIDEO(es_stream_type_t type)
-{
- switch (type) {
- case VIDEO_MPEG1:
- case VIDEO_MPEG2:
- case VIDEO_MPEG4:
- case VIDEO_H264:
- case VIDEO_AVC:
- case VIDEO_DIRAC:
- case VIDEO_VC1:
- return 1;
- }
- return 0;
-}
-
-static int IS_SUB(es_stream_type_t type)
-{
- switch (type) {
- case SPU_DVD:
- case SPU_DVB:
- case SPU_PGS:
- case SPU_TELETEXT:
- return 1;
- }
- return 0;
-}
-
-static int ts_parse(demuxer_t *demuxer, ES_stream_t *es, unsigned char *packet, int probe);
-
-static uint8_t get_packet_size(const unsigned char *buf, int size)
-{
- int i;
-
- if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS))
- return 0;
-
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_PACKET_SIZE] != 0x47)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);
- goto try_fec;
- }
- }
- return TS_PACKET_SIZE;
-
-try_fec:
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_FEC_PACKET_SIZE] != 0x47){
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);
- goto try_philips;
- }
- }
- return TS_FEC_PACKET_SIZE;
-
- try_philips:
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_PH_PACKET_SIZE] != 0x47)
- return 0;
- }
- return TS_PH_PACKET_SIZE;
-}
-
-static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h);
-static uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid);
-
-static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es)
-{
- int i;
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
-
- if(priv->ts.streams[es->pid].sh)
- return;
-
- if((IS_AUDIO(es->type) || IS_AUDIO(es->subtype)) && priv->last_aid+1 < MAX_A_STREAMS)
- {
- sh_audio_t *sh = new_sh_audio_aid(demuxer, priv->last_aid, es->pid);
- 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;
- mp_set_audio_codec_from_tag(sh);
- sh->ds = demuxer->audio;
-
- priv->ts.streams[es->pid].id = priv->last_aid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_AUDIO;
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED AUDIO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_aid);
- if (lang && lang[0])
- mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_AID_%d_LANG=%s\n", es->pid, lang);
- priv->last_aid++;
-
- if(es->extradata && es->extradata_len)
- {
- sh->wf = malloc(sizeof(*sh->wf) + es->extradata_len);
- sh->wf->cbSize = es->extradata_len;
- memcpy(sh->wf + 1, es->extradata, es->extradata_len);
- }
- }
- }
-
- if((IS_VIDEO(es->type) || IS_VIDEO(es->subtype)) && priv->last_vid+1 < MAX_V_STREAMS)
- {
- sh_video_t *sh = new_sh_video_vid(demuxer, priv->last_vid, es->pid);
- if(sh)
- {
- sh->format = IS_VIDEO(es->type) ? es->type : es->subtype;
- mp_set_video_codec_from_tag(sh);
- sh->ds = demuxer->video;
-
- priv->ts.streams[es->pid].id = priv->last_vid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_VIDEO;
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED VIDEO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_vid);
- priv->last_vid++;
-
-
- if(sh->format == VIDEO_AVC && es->extradata && es->extradata_len)
- {
- int w = 0, h = 0;
- sh->bih = calloc(1, sizeof(*sh->bih) + es->extradata_len);
- sh->bih->biSize= sizeof(*sh->bih) + es->extradata_len;
- sh->bih->biCompression = sh->format;
- memcpy(sh->bih + 1, es->extradata, es->extradata_len);
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "EXTRADATA(%d BYTES): \n", es->extradata_len);
- for(i = 0;i < es->extradata_len; i++)
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "%02x ", (int) es->extradata[i]);
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\n");
- if(parse_avc_sps(es->extradata, es->extradata_len, &w, &h))
- {
- sh->bih->biWidth = w;
- sh->bih->biHeight = h;
- }
- }
- }
- }
-
- if(IS_SUB(es->type) && priv->last_sid+1 < MAX_S_STREAMS)
- {
- sh_sub_t *sh = new_sh_sub_sid_lang(demuxer, priv->last_sid, es->pid, pid_lang_from_pmt(priv, es->pid));
- if (sh) {
- switch (es->type) {
- case SPU_DVB:
- sh->gsh->codec = "dvb_subtitle"; break;
- case SPU_DVD:
- sh->gsh->codec = "dvd_subtitle"; break;
- case SPU_PGS:
- sh->gsh->codec = "hdmv_pgs_subtitle"; break;
- }
- priv->ts.streams[es->pid].id = priv->last_sid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_SUB;
- priv->last_sid++;
- }
- }
-}
-
-static int ts_check_file(demuxer_t * demuxer)
-{
- const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS);
- unsigned char buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS], done = 0, *ptr;
- uint32_t _read, i, count = 0, is_ts;
- int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c, good, bad;
- uint8_t size = 0;
- int64_t pos = 0;
- int64_t init_pos;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for MPEG-TS...\n");
-
- init_pos = stream_tell(demuxer->stream);
- is_ts = 0;
- while(! done)
- {
- i = 1;
- c = 0;
-
- while(((c=stream_read_char(demuxer->stream)) != 0x47)
- && (c >= 0)
- && (i < MAX_CHECK_SIZE)
- && ! demuxer->stream->eof
- ) i++;
-
-
- if(c != 0x47)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "THIS DOESN'T LOOK LIKE AN MPEG-TS FILE!\n");
- is_ts = 0;
- done = 1;
- continue;
- }
-
- pos = stream_tell(demuxer->stream) - 1;
- buf[0] = c;
- _read = stream_read(demuxer->stream, &buf[1], buf_size-1);
-
- if(_read < buf_size-1)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n");
- return 0;
- }
-
- size = get_packet_size(buf, buf_size);
- if(size)
- {
- done = 1;
- is_ts = 1;
- }
-
- if(pos - init_pos >= MAX_CHECK_SIZE)
- {
- done = 1;
- is_ts = 0;
- }
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %"PRIu64", FOUND %x, packet_size= %d, SEEMS A TS? %d\n", (uint64_t) pos, c, size, is_ts);
- stream_seek(demuxer->stream, pos);
-
- if(! is_ts)
- return 0;
-
- //LET'S CHECK continuity counters
- good = bad = 0;
- for(count = 0; count < NB_PID_MAX; count++)
- {
- cc[count] = last_cc[count] = -1;
- }
-
- for(count = 0; count < NUM_CONSECUTIVE_TS_PACKETS; count++)
- {
- ptr = &(buf[size * count]);
- pid = ((ptr[1] & 0x1f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "BUF: %02x %02x %02x %02x, PID %d, SIZE: %d \n",
- ptr[0], ptr[1], ptr[2], ptr[3], pid, size);
-
- if((pid == 8191) || (pid < 16))
- continue;
-
- cc[pid] = (ptr[3] & 0xf);
- cc_ok = (last_cc[pid] < 0) || ((((last_cc[pid] + 1) & 0x0f) == cc[pid]));
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PID %d, COMPARE CC %d AND LAST_CC %d\n", pid, cc[pid], last_cc[pid]);
- if(! cc_ok)
- //return 0;
- bad++;
- else
- good++;
-
- last_cc[pid] = cc[pid];
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "GOOD CC: %d, BAD CC: %d\n", good, bad);
-
- if(good >= bad)
- return size;
- else
- return 0;
-}
-
-
-static int32_t progid_idx_in_pmt(ts_priv_t *priv, uint16_t progid)
-{
- int x;
-
- if(priv->pmt == NULL)
- return -1;
-
- for(x = 0; x < priv->pmt_cnt; x++)
- {
- if(priv->pmt[x].progid == progid)
- return x;
- }
-
- return -1;
-}
-
-
-static int32_t progid_for_pid(ts_priv_t *priv, int pid, int32_t req) //finds the first program listing a pid
-{
- int i, j;
- pmt_t *pmt;
-
-
- if(priv->pmt == NULL)
- return -1;
-
-
- for(i=0; i < priv->pmt_cnt; i++)
- {
- pmt = &(priv->pmt[i]);
-
- if(pmt->es == NULL)
- return -1;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].pid == pid)
- {
- if((req == 0) || (req == pmt->progid))
- return pmt->progid;
- }
- }
-
- }
- return -1;
-}
-
-static int32_t prog_pcr_pid(ts_priv_t *priv, int progid)
-{
- int i;
-
- if(priv->pmt == NULL)
- return -1;
- for(i=0; i < priv->pmt_cnt; i++)
- {
- if(priv->pmt[i].progid == progid)
- return priv->pmt[i].PCR_PID;
- }
- return -1;
-}
-
-
-static int pid_match_lang(ts_priv_t *priv, uint16_t pid, char *lang)
-{
- uint16_t i, j;
- pmt_t *pmt;
-
- if(priv->pmt == NULL)
- return -1;
-
- for(i=0; i < priv->pmt_cnt; i++)
- {
- pmt = &(priv->pmt[i]);
-
- if(pmt->es == NULL)
- return -1;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].pid != pid)
- continue;
-
- mp_msg(MSGT_DEMUXER, MSGL_V, "CMP LANG %s AND %s, pids: %d %d\n",pmt->es[j].lang, lang, pmt->es[j].pid, pid);
- if(strncmp(pmt->es[j].lang, lang, 3) == 0)
- {
- return 1;
- }
- }
-
- }
-
- return -1;
-}
-
-typedef struct {
- int32_t atype, vtype, stype; //types
- int32_t apid, vpid, spid; //stream ids
- char alang[4]; //languages
- uint16_t prog;
- int64_t probe;
-} tsdemux_init_t;
-
-//second stage: returns the count of A52 syncwords found
-static int a52_check(char *buf, int len)
-{
- int cnt, frame_length = 0, ok, srate;
-
- cnt = ok = 0;
- if(len < 8)
- return 0;
-
- while(cnt < len - 7)
- {
- if(buf[cnt] == 0x0B && buf[cnt+1] == 0x77)
- {
- frame_length = mp_a52_framesize(&buf[cnt], &srate);
- if(frame_length>=7 && frame_length<=3840)
- {
- cnt += frame_length;
- ok++;
- }
- else
- cnt++;
- }
- else
- cnt++;
- }
-
- mp_msg(MSGT_DEMUXER, MSGL_V, "A52_CHECK(%d input bytes), found %d frame syncwords of %d bytes length\n", len, ok, frame_length);
- return ok;
-}
-
-
-static int64_t ts_detect_streams(demuxer_t *demuxer, tsdemux_init_t *param)
-{
- int video_found = 0, audio_found = 0, i, num_packets = 0, req_apid, req_vpid, req_spid;
- int is_audio, is_video, is_sub, has_tables;
- int32_t p, chosen_pid = 0;
- int64_t pos=0, ret = 0, init_pos, end_pos;
- ES_stream_t es;
- unsigned char tmp[TS_FEC_PACKET_SIZE];
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
- struct {
- char *buf;
- int pos;
- } pes_priv1[8192], *pptr;
- char *tmpbuf;
-
- priv->last_pid = 8192; //invalid pid
-
- req_apid = param->apid;
- req_vpid = param->vpid;
- req_spid = param->spid;
-
- has_tables = 0;
- memset(pes_priv1, 0, sizeof(pes_priv1));
- init_pos = stream_tell(demuxer->stream);
- mp_msg(MSGT_DEMUXER, MSGL_V, "PROBING UP TO %"PRIu64", PROG: %d\n", (uint64_t) param->probe, param->prog);
- end_pos = init_pos + (param->probe ? param->probe : TS_MAX_PROBE_SIZE);
- while(1)
- {
- pos = stream_tell(demuxer->stream);
- if(pos > end_pos || demuxer->stream->eof)
- break;
-
- if(ts_parse(demuxer, &es, tmp, 1))
- {
- //Non PES-aligned A52 audio may escape detection if PMT is not present;
- //in this case we try to find at least 3 A52 syncwords
- if((es.type == PES_PRIVATE1) && (! audio_found) && req_apid > -2)
- {
- pptr = &pes_priv1[es.pid];
- if(pptr->pos < 64*1024)
- {
- tmpbuf = realloc(pptr->buf, pptr->pos + es.size);
- if(tmpbuf != NULL)
- {
- pptr->buf = tmpbuf;
- memcpy(&(pptr->buf[ pptr->pos ]), es.start, es.size);
- pptr->pos += es.size;
- if(a52_check(pptr->buf, pptr->pos) > 2)
- {
- param->atype = AUDIO_A52;
- param->apid = es.pid;
- es.type = AUDIO_A52;
- }
- }
- }
- }
-
- is_audio = IS_AUDIO(es.type) || ((es.type==SL_PES_STREAM) && IS_AUDIO(es.subtype));
- is_video = IS_VIDEO(es.type) || ((es.type==SL_PES_STREAM) && IS_VIDEO(es.subtype));
- is_sub = IS_SUB(es.type);
-
-
- if((! is_audio) && (! is_video) && (! is_sub))
- continue;
- if(is_audio && req_apid==-2)
- continue;
-
- if(is_video)
- {
- chosen_pid = (req_vpid == es.pid);
- if((! chosen_pid) && (req_vpid > 0))
- continue;
- }
- else if(is_audio)
- {
- if(req_apid > 0)
- {
- chosen_pid = (req_apid == es.pid);
- if(! chosen_pid)
- continue;
- }
- else if(param->alang[0] > 0 && es.lang[0] > 0)
- {
- if(pid_match_lang(priv, es.pid, param->alang) == -1)
- continue;
-
- chosen_pid = 1;
- param->apid = req_apid = es.pid;
- }
- }
- else if(is_sub)
- {
- chosen_pid = (req_spid == es.pid);
- if((! chosen_pid) && (req_spid > 0))
- continue;
- }
-
- if(req_apid < 0 && (param->alang[0] == 0) && req_vpid < 0 && req_spid < 0)
- chosen_pid = 1;
-
- if((ret == 0) && chosen_pid)
- {
- ret = stream_tell(demuxer->stream);
- }
-
- p = progid_for_pid(priv, es.pid, param->prog);
- if(p != -1)
- {
- has_tables++;
- if(!param->prog && chosen_pid)
- param->prog = p;
- }
-
- if((param->prog > 0) && (param->prog != p))
- {
- if(audio_found)
- {
- if(is_video && (req_vpid == es.pid))
- {
- param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype;
- param->vpid = es.pid;
- video_found = 1;
- break;
- }
- }
-
- if(video_found)
- {
- if(is_audio && (req_apid == es.pid))
- {
- param->atype = IS_AUDIO(es.type) ? es.type : es.subtype;
- param->apid = es.pid;
- audio_found = 1;
- break;
- }
- }
-
-
- continue;
- }
-
-
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, param->prog);
-
-
- if(is_video)
- {
- if((req_vpid == -1) || (req_vpid == es.pid))
- {
- param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype;
- param->vpid = es.pid;
- video_found = 1;
- }
- }
-
-
- if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found && !param->probe)
- {
- //novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only)
- param->vtype = 0;
- break;
- }
-
- if(is_sub)
- {
- if((req_spid == -1) || (req_spid == es.pid))
- {
- param->stype = es.type;
- param->spid = es.pid;
- }
- }
-
- if(is_audio)
- {
- if((req_apid == -1) || (req_apid == es.pid))
- {
- param->atype = IS_AUDIO(es.type) ? es.type : es.subtype;
- param->apid = es.pid;
- audio_found = 1;
- }
- }
-
- if(audio_found && (param->apid == es.pid) && (! video_found))
- num_packets++;
-
- if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000))
- break;
- }
- }
-
- for(i=0; i<8192; i++)
- {
- if(pes_priv1[i].buf != NULL)
- {
- free(pes_priv1[i].buf);
- pes_priv1[i].buf = NULL;
- pes_priv1[i].pos = 0;
- }
- }
-
- if(video_found)
- {
- if(param->vtype == VIDEO_MPEG1)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG1(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_MPEG2)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_MPEG4)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG4(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_H264)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO H264(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_VC1)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO VC1(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_AVC)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO AVC(NAL-H264, pid=%d) ", param->vpid);
- }
- else
- {
- param->vtype = UNKNOWN;
- //WE DIDN'T MATCH ANY VIDEO STREAM
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! ");
- }
-
- if(param->atype == AUDIO_MP2)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MPA(pid=%d)", param->apid);
- else if(param->atype == AUDIO_A52)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", param->apid);
- else if(param->atype == AUDIO_DTS)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO DTS(pid=%d)", param->apid);
- else if(param->atype == AUDIO_LPCM_BE)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)", param->apid);
- else if(param->atype == AUDIO_PCM_BR)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO PCMBR(pid=%d)", param->apid);
- else if(param->atype == AUDIO_AAC)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC(pid=%d)", param->apid);
- else if(param->atype == AUDIO_AAC_LATM)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC LATM(pid=%d)", param->apid);
- else if(param->atype == AUDIO_TRUEHD)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO TRUEHD(pid=%d)", param->apid);
- else if(param->atype == AUDIO_S302M)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO S302M(pid=%d)", param->apid);
- else
- {
- audio_found = 0;
- param->atype = UNKNOWN;
- //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO! (try increasing -tsprobe)");
- }
-
- if(IS_SUB(param->stype))
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB %s(pid=%d) ", (param->stype==SPU_DVD ? "DVD" : param->stype==SPU_DVB ? "DVB" : "Teletext"), param->spid);
- else
- {
- param->stype = UNKNOWN;
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " NO SUBS (yet)! ");
- }
-
- if(video_found || audio_found)
- {
- if(!param->prog)
- {
- p = progid_for_pid(priv, video_found ? param->vpid : param->apid, 0);
- if(p != -1)
- param->prog = p;
- }
-
- if(demuxer->stream->eof && (ret == 0))
- ret = init_pos;
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", param->prog);
- }
- else
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "\n");
-
-
- for(i=0; i<NB_PID_MAX; i++)
- {
- if(priv->ts.pids[i] != NULL)
- {
- priv->ts.pids[i]->payload_size = 0;
- priv->ts.pids[i]->pts = priv->ts.pids[i]->last_pts = 0;
- priv->ts.pids[i]->last_cc = -1;
- priv->ts.pids[i]->is_synced = 0;
- }
- }
-
- return ret;
-}
-
-static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h)
-{
- int sps, sps_len;
- unsigned char *ptr;
- mp_mpeg_header_t picture;
- if(len < 6)
- return 0;
- sps = buf[5] & 0x1f;
- if(!sps)
- return 0;
- sps_len = (buf[6] << 8) | buf[7];
- if(!sps_len || (sps_len > len - 8))
- return 0;
- ptr = &(buf[8]);
- picture.display_picture_width = picture.display_picture_height = 0;
- h264_parse_sps(&picture, ptr, len - 8);
- if(!picture.display_picture_width || !picture.display_picture_height)
- return 0;
- *w = picture.display_picture_width;
- *h = picture.display_picture_height;
- return 1;
-}
-
-static demuxer_t *demux_open_ts(demuxer_t * demuxer)
-{
- int i;
- uint8_t packet_size;
- sh_video_t *sh_video;
- sh_audio_t *sh_audio;
- int64_t start_pos;
- tsdemux_init_t params;
- ts_priv_t * priv = demuxer->priv;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n",
- demuxer->audio->id, demuxer->video->id, demuxer->sub->id);
-
-
- demuxer->type= DEMUXER_TYPE_MPEG_TS;
- demuxer->ts_resets_possible = true;
-
- packet_size = ts_check_file(demuxer);
- if(!packet_size)
- return NULL;
-
- priv = calloc(1, sizeof(ts_priv_t));
- if(priv == NULL)
- {
- mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate enough memory for ts->priv, exit\n");
- return NULL;
- }
-
- for(i=0; i < NB_PID_MAX; i++)
- {
- priv->ts.pids[i] = NULL;
- priv->ts.streams[i].id = -3;
- }
- priv->pat.progs = NULL;
- priv->pat.progs_cnt = 0;
- priv->pat.section.buffer = NULL;
- priv->pat.section.buffer_len = 0;
-
- priv->pmt = NULL;
- priv->pmt_cnt = 0;
-
- priv->keep_broken = ts_keep_broken;
- priv->ts.packet_size = packet_size;
-
-
- demuxer->priv = priv;
-
- params.atype = params.vtype = params.stype = UNKNOWN;
- params.apid = demuxer->audio->id;
- params.vpid = demuxer->video->id;
- params.spid = demuxer->sub->id;
- params.prog = ts_prog;
- params.probe = ts_probe;
-
- if(demuxer->opts->audio_lang != NULL)
- {
- strncpy(params.alang, demuxer->opts->audio_lang[0], 3);
- params.alang[3] = 0;
- }
- else
- memset(params.alang, 0, 4);
-
- start_pos = ts_detect_streams(demuxer, &params);
-
- demuxer->sub->id = params.spid;
- priv->prog = params.prog;
-
- if(params.vtype != UNKNOWN)
- {
- ts_add_stream(demuxer, priv->ts.pids[params.vpid]);
- sh_video = priv->ts.streams[params.vpid].sh;
- demuxer->video->id = priv->ts.streams[params.vpid].id;
- sh_video->ds = demuxer->video;
- sh_video->format = params.vtype;
- mp_set_video_codec_from_tag(sh_video);
- demuxer->video->sh = sh_video;
- }
-
- if(params.atype != UNKNOWN)
- {
- ES_stream_t *es = priv->ts.pids[params.apid];
-
- if(!IS_AUDIO(es->type) && !IS_AUDIO(es->subtype) && IS_AUDIO(params.atype)) es->subtype = params.atype;
- ts_add_stream(demuxer, priv->ts.pids[params.apid]);
- sh_audio = priv->ts.streams[params.apid].sh;
- demuxer->audio->id = priv->ts.streams[params.apid].id;
- sh_audio->ds = demuxer->audio;
- sh_audio->format = params.atype;
- mp_set_audio_codec_from_tag(sh_audio);
- demuxer->audio->sh = sh_audio;
- }
-
-
- mp_msg(MSGT_DEMUXER,MSGL_V, "Opened TS demuxer, audio: %x(pid %d), video: %x(pid %d)...POS=%"PRIu64", PROBE=%"PRIu64"\n", params.atype, demuxer->audio->id, params.vtype, demuxer->video->id, (uint64_t) start_pos, ts_probe);
-
-
- start_pos = start_pos <= priv->ts.packet_size ?
- demuxer->stream->start_pos :
- start_pos - priv->ts.packet_size;
- demuxer->movi_start = start_pos;
- demuxer->reference_clock = MP_NOPTS_VALUE;
- stream_seek(demuxer->stream, start_pos); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
-
-
- priv->last_pid = 8192; //invalid pid
-
- for(i = 0; i < 3; i++)
- {
- priv->fifo[i].pack = NULL;
- priv->fifo[i].offset = 0;
- }
- priv->fifo[0].ds = demuxer->audio;
- priv->fifo[1].ds = demuxer->video;
- priv->fifo[2].ds = demuxer->sub;
-
- priv->fifo[0].buffer_size = 1536;
- priv->fifo[1].buffer_size = 32767;
- priv->fifo[2].buffer_size = 32767;
-
- priv->pat.section.buffer_len = 0;
- for(i = 0; i < priv->pmt_cnt; i++)
- priv->pmt[i].section.buffer_len = 0;
-
- demuxer->filepos = stream_tell(demuxer->stream);
- return demuxer;
-}
-
-static void demux_close_ts(demuxer_t * demuxer)
-{
- uint16_t i;
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
-
- if(priv)
- {
- free(priv->pat.section.buffer);
- free(priv->pat.progs);
-
- if(priv->pmt)
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- free(priv->pmt[i].section.buffer);
- free(priv->pmt[i].es);
- }
- free(priv->pmt);
- }
- for (i = 0; i < NB_PID_MAX; i++)
- {
- free(priv->ts.pids[i]);
- priv->ts.pids[i] = NULL;
- }
- for (i = 0; i < 3; i++)
- {
- if (priv->fifo[i].pack)
- free_demux_packet(priv->fifo[i].pack);
- priv->fifo[i].pack = NULL;
- }
- free(priv);
- }
- demuxer->priv=NULL;
-}
-
-
-#define getbits mp_getbits
-
-static int mp4_parse_sl_packet(pmt_t *pmt, uint8_t *buf, uint16_t packet_len, int pid, ES_stream_t *pes_es)
-{
- int i, n, m, mp4_es_id = -1;
- uint64_t v = 0;
- uint32_t pl_size = 0;
- int deg_flag = 0;
- mp4_es_descr_t *es = NULL;
- mp4_sl_config_t *sl = NULL;
- uint8_t au_start = 0, au_end = 0, rap_flag = 0, ocr_flag = 0, padding = 0, padding_bits = 0, idle = 0;
-
- pes_es->is_synced = 0;
- mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, pid: %d, pmt: %pm, packet_len: %d\n", pid, pmt, packet_len);
- if(! pmt || !packet_len)
- return 0;
-
- for(i = 0; i < pmt->es_cnt; i++)
- {
- if(pmt->es[i].pid == pid)
- mp4_es_id = pmt->es[i].mp4_es_id;
- }
- if(mp4_es_id < 0)
- return -1;
-
- for(i = 0; i < pmt->mp4es_cnt; i++)
- {
- if(pmt->mp4es[i].id == mp4_es_id)
- es = &(pmt->mp4es[i]);
- }
- if(! es)
- return -1;
-
- pes_es->subtype = es->decoder.object_type;
-
- sl = &(es->sl);
- if(!sl)
- return -1;
-
- //now es is the complete es_descriptor of out mp4 ES stream
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "ID: %d, FLAGS: 0x%x, subtype: %x\n", es->id, sl->flags, pes_es->subtype);
-
- n = 0;
- if(sl->au_start)
- pes_es->sl.au_start = au_start = getbits(buf, n++, 1);
- else
- pes_es->sl.au_start = (pes_es->sl.last_au_end ? 1 : 0);
- if(sl->au_end)
- pes_es->sl.au_end = au_end = getbits(buf, n++, 1);
-
- if(!sl->au_start && !sl->au_end)
- {
- pes_es->sl.au_start = pes_es->sl.au_end = au_start = au_end = 1;
- }
- pes_es->sl.last_au_end = pes_es->sl.au_end;
-
-
- if(sl->ocr_len > 0)
- ocr_flag = getbits(buf, n++, 1);
- if(sl->idle)
- idle = getbits(buf, n++, 1);
- if(sl->padding)
- padding = getbits(buf, n++, 1);
- if(padding)
- {
- padding_bits = getbits(buf, n, 3);
- n += 3;
- }
-
- if(idle || (padding && !padding_bits))
- {
- pes_es->payload_size = 0;
- return -1;
- }
-
- //(! idle && (!padding || padding_bits != 0)) is true
- n += sl->packet_seqnum_len;
- if(sl->degr_len)
- deg_flag = getbits(buf, n++, 1);
- if(deg_flag)
- n += sl->degr_len;
-
- if(ocr_flag)
- {
- n += sl->ocr_len;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "OCR: %d bits\n", sl->ocr_len);
- }
-
- if(packet_len * 8 <= n)
- return -1;
-
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "\nAU_START: %d, AU_END: %d\n", au_start, au_end);
- if(au_start)
- {
- int dts_flag = 0, cts_flag = 0, ib_flag = 0;
-
- if(sl->random_accesspoint)
- rap_flag = getbits(buf, n++, 1);
-
- //check commented because it seems it's rarely used, and we need this flag set in case of au_start
- //the decoder will eventually discard the payload if it can't decode it
- //if(rap_flag || sl->random_accesspoint_only)
- pes_es->is_synced = 1;
-
- n += sl->au_seqnum_len;
- if(packet_len * 8 <= n+8)
- return -1;
- if(sl->use_ts)
- {
- dts_flag = getbits(buf, n++, 1);
- cts_flag = getbits(buf, n++, 1);
- }
- if(sl->instant_bitrate_len)
- ib_flag = getbits(buf, n++, 1);
- if(packet_len * 8 <= n+8)
- return -1;
- if(dts_flag && (sl->ts_len > 0))
- {
- n += sl->ts_len;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "DTS: %d bits\n", sl->ts_len);
- }
- if(packet_len * 8 <= n+8)
- return -1;
- if(cts_flag && (sl->ts_len > 0))
- {
- int i = 0, m;
-
- while(i < sl->ts_len)
- {
- m = FFMIN(8, sl->ts_len - i);
- v |= getbits(buf, n, m);
- if(sl->ts_len - i > 8)
- v <<= 8;
- i += m;
- n += m;
- if(packet_len * 8 <= n+8)
- return -1;
- }
-
- pes_es->pts = (double) v / (double) sl->ts_resolution;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "CTS: %d bits, value: %"PRIu64"/%d = %.3f\n", sl->ts_len, v, sl->ts_resolution, pes_es->pts);
- }
-
-
- i = 0;
- pl_size = 0;
- while(i < sl->au_len)
- {
- m = FFMIN(8, sl->au_len - i);
- pl_size |= getbits(buf, n, m);
- if(sl->au_len - i > 8)
- pl_size <<= 8;
- i += m;
- n += m;
- if(packet_len * 8 <= n+8)
- return -1;
- }
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "AU_LEN: %u (%d bits)\n", pl_size, sl->au_len);
- if(ib_flag)
- n += sl->instant_bitrate_len;
- }
-
- m = (n+7)/8;
- if(0 < pl_size && pl_size < pes_es->payload_size)
- pes_es->payload_size = pl_size;
-
- mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, n=%d, m=%d, size from pes hdr: %u, sl hdr size: %u, RAP FLAGS: %d/%d\n",
- n, m, pes_es->payload_size, pl_size, (int) rap_flag, (int) sl->random_accesspoint_only);
-
- return m;
-}
-
-//this function parses the extension fields in the PES header and returns the substream_id, or -1 in case of errors
-static int parse_pes_extension_fields(unsigned char *p, int pkt_len)
-{
- int skip;
- unsigned char flags;
-
- if(!(p[7] & 0x1)) //no extension_field
- return -1;
- skip = 9;
- if(p[7] & 0x80)
- {
- skip += 5;
- if(p[7] & 0x40)
- skip += 5;
- }
- if(p[7] & 0x20) //escr_flag
- skip += 6;
- if(p[7] & 0x10) //es_rate_flag
- skip += 3;
- if(p[7] & 0x08)//dsm_trick_mode is unsupported, skip
- {
- skip = 0;//don't let's parse the extension fields
- }
- if(p[7] & 0x04) //additional_copy_info
- skip += 1;
- if(p[7] & 0x02) //pes_crc_flag
- skip += 2;
- if(skip >= pkt_len) //too few bytes
- return -1;
- flags = p[skip];
- skip++;
- if(flags & 0x80) //pes_private_data_flag
- skip += 16;
- if(skip >= pkt_len)
- return -1;
- if(flags & 0x40) //pack_header_field_flag
- {
- unsigned char l = p[skip];
- skip += l;
- }
- if(flags & 0x20) //program_packet_sequence_counter
- skip += 2;
- if(flags & 0x10) //p_std
- skip += 2;
- if(skip >= pkt_len)
- return -1;
- if(flags & 0x01) //finally the long desired pes_extension2
- {
- unsigned char l = p[skip]; //ext2 flag+len
- skip++;
- if((l == 0x81) && (skip < pkt_len))
- {
- int ssid = p[skip];
- mp_msg(MSGT_IDENTIFY, MSGL_V, "SUBSTREAM_ID=%d (0x%02X)\n", ssid, ssid);
- return ssid;
- }
- }
-
- return -1;
-}
-
-static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es, int32_t type_from_pmt, pmt_t *pmt, int pid)
-{
- unsigned char *p;
- uint32_t header_len;
- int64_t pts;
- uint32_t stream_id;
- uint32_t pkt_len, pes_is_aligned;
-
- //Here we are always at the start of a PES packet
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%p, %d): \n", buf, (uint32_t) packet_len);
-
- if(packet_len == 0 || packet_len > 184)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2, BUFFER LEN IS TOO SMALL OR TOO BIG: %d EXIT\n", packet_len);
- return 0;
- }
-
- p = buf;
- pkt_len = packet_len;
-
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: HEADER %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]);
- if (p[0] || p[1] || (p[2] != 1))
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: error HEADER %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
- return 0 ;
- }
-
- packet_len -= 6;
- if(packet_len==0)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: packet too short: %d, exit\n", packet_len);
- return 0;
- }
-
- es->payload_size = (p[4] << 8 | p[5]);
- pes_is_aligned = (p[6] & 4);
-
- stream_id = p[3];
-
-
- if (p[7] & 0x80)
- { /* pts available */
- pts = (int64_t)(p[9] & 0x0E) << 29 ;
- pts |= p[10] << 22 ;
- pts |= (p[11] & 0xFE) << 14 ;
- pts |= p[12] << 7 ;
- pts |= (p[13] & 0xFE) >> 1 ;
-
- es->pts = pts / 90000.0;
- }
- else
- es->pts = 0.0;
-
-
- header_len = p[8];
-
-
- if (header_len + 9 > pkt_len) //9 are the bytes read up to the header_length field
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len);
- return 0;
- }
-
- if(stream_id==0xfd)
- {
- int ssid = parse_pes_extension_fields(p, pkt_len);
- if((audio_substream_id!=-1) && (ssid != audio_substream_id))
- return 0;
- if(ssid == 0x72 && type_from_pmt != AUDIO_DTS && type_from_pmt != SPU_PGS)
- es->type = type_from_pmt = AUDIO_TRUEHD;
- }
-
- p += header_len + 9;
- packet_len -= header_len + 3;
-
- if(es->payload_size)
- es->payload_size -= header_len + 3;
-
-
- es->is_synced = 1; //only for SL streams we have to make sure it's really true, see below
- if (stream_id == 0xbd)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X, 80: %d\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0] & 0x80);
-
-
- /*
- * we check the descriptor tag first because some stations
- * do not include any of the A52 header info in their audio tracks
- * these "raw" streams may begin with a byte that looks like a stream type.
- */
-
-
- if(type_from_pmt == SPU_PGS)
- {
- es->start = p;
- es->size = packet_len;
- es->type = SPU_PGS;
- es->payload_size -= packet_len;
- return 1;
- }
- if(
- (type_from_pmt == AUDIO_A52) || /* A52 - raw */
- (packet_len >= 2 && p[0] == 0x0B && p[1] == 0x77) /* A52 - syncword */
- )
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 RAW OR SYNCWORD\n");
- es->start = p;
- es->size = packet_len;
- es->type = AUDIO_A52;
- es->payload_size -= packet_len;
-
- return 1;
- }
- /* SPU SUBS */
- else if(type_from_pmt == SPU_DVB ||
- (packet_len >= 2 && (p[0] == 0x20) && pes_is_aligned)) // && p[1] == 0x00))
- {
- // offset/length fiddling to make decoding with lavc possible
- es->start = p + 2;
- es->size = packet_len - 2;
- es->type = SPU_DVB;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 1 && ((p[0] & 0xE0) == 0x20)) //SPU_DVD
- {
- //DVD SUBS
- es->start = p+1;
- es->size = packet_len-1;
- es->type = SPU_DVD;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 4 && (p[0] & 0xF8) == 0x80)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 WITH HEADER\n");
- es->start = p+4;
- es->size = packet_len - 4;
- es->type = AUDIO_A52;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 1 && ((p[0]&0xf0) == 0xa0))
- {
- int pcm_offset;
-
- for (pcm_offset=0; ++pcm_offset < packet_len-1 ; )
- {
- if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80)
- { /* START */
- pcm_offset += 2;
- break;
- }
- }
-
- es->start = p + pcm_offset;
- es->size = packet_len - pcm_offset;
- es->type = AUDIO_LPCM_BE;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PES_PRIVATE1\n");
- es->start = p;
- es->size = packet_len;
- es->type = (type_from_pmt == UNKNOWN ? PES_PRIVATE1 : type_from_pmt);
- es->payload_size -= packet_len;
-
- return 1;
- }
- }
- else if((stream_id >= 0xe0 && stream_id <= 0xef) || (stream_id == 0xfd && type_from_pmt != UNKNOWN))
- {
- es->start = p;
- es->size = packet_len;
- if(type_from_pmt != UNKNOWN)
- es->type = type_from_pmt;
- else
- es->type = VIDEO_MPEG2;
- if(es->payload_size)
- es->payload_size -= packet_len;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: M2V size %d\n", es->size);
- return 1;
- }
- else if (stream_id == 0xfa)
- {
- int l;
-
- es->is_synced = 0;
- if(type_from_pmt != UNKNOWN) //MP4 A/V or SL
- {
- es->start = p;
- es->size = packet_len;
- es->type = type_from_pmt;
-
- if(type_from_pmt == SL_PES_STREAM)
- {
- //if(pes_is_aligned)
- //{
- l = mp4_parse_sl_packet(pmt, p, packet_len, pid, es);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "L=%d, TYPE=%x\n", l, type_from_pmt);
- if(l < 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: couldn't parse SL header, passing along full PES payload\n");
- l = 0;
- }
- //}
-
- es->start += l;
- es->size -= l;
- }
-
- if(es->payload_size)
- es->payload_size -= packet_len;
- return 1;
- }
- }
- else if ((stream_id & 0xe0) == 0xc0)
- {
- es->start = p;
- es->size = packet_len;
-
- if(type_from_pmt != UNKNOWN)
- es->type = type_from_pmt;
- else
- es->type = AUDIO_MP2;
-
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (type_from_pmt != -1) //as a last resort here we trust the PMT, if present
- {
- es->start = p;
- es->size = packet_len;
- es->type = type_from_pmt;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id);
- }
-
- es->is_synced = 0;
- return 0;
-}
-
-
-
-
-static int ts_sync(stream_t *stream)
-{
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "TS_SYNC \n");
-
- while (!stream->eof)
- if (stream_read_char(stream) == 0x47)
- return 1;
-
- return 0;
-}
-
-
-static void ts_dump_streams(ts_priv_t *priv)
-{
- int i;
-
- for(i = 0; i < 3; i++)
- {
- if((priv->fifo[i].pack != NULL) && (priv->fifo[i].offset != 0))
- {
- resize_demux_packet(priv->fifo[i].pack, priv->fifo[i].offset);
- ds_add_packet(priv->fifo[i].ds, priv->fifo[i].pack);
- priv->fifo[i].offset = 0;
- priv->fifo[i].pack = NULL;
- }
- }
-}
-
-
-static int32_t prog_idx_in_pat(ts_priv_t *priv, uint16_t progid)
-{
- int x;
-
- if(priv->pat.progs == NULL)
- return -1;
-
- for(x = 0; x < priv->pat.progs_cnt; x++)
- {
- if(priv->pat.progs[x].id == progid)
- return x;
- }
-
- return -1;
-}
-
-
-static int32_t prog_id_in_pat(ts_priv_t *priv, uint16_t pid)
-{
- int x;
-
- if(priv->pat.progs == NULL)
- return -1;
-
- for(x = 0; x < priv->pat.progs_cnt; x++)
- {
- if(priv->pat.progs[x].pmt_pid == pid)
- return priv->pat.progs[x].id;
- }
-
- return -1;
-}
-
-static int collect_section(ts_section_t *section, int is_start, unsigned char *buff, int size)
-{
- uint8_t *ptr;
- uint16_t tlen;
- int skip, tid;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, start: %d, size: %d, collected: %d\n", is_start, size, section->buffer_len);
- if(! is_start && !section->buffer_len)
- return 0;
-
- if(is_start)
- {
- if(! section->buffer)
- {
- section->buffer = malloc(4096 + 256);
- if(section->buffer == NULL)
- return 0;
- }
- section->buffer_len = 0;
- }
-
- if(size + section->buffer_len > 4096+256)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, excessive len: %d + %d\n", section->buffer_len, size);
- return 0;
- }
-
- memcpy(&(section->buffer[section->buffer_len]), buff, size);
- section->buffer_len += size;
-
- if(section->buffer_len < 3)
- return 0;
-
- skip = section->buffer[0];
- if(skip + 4 > section->buffer_len)
- return 0;
-
- ptr = &(section->buffer[skip + 1]);
- tid = ptr[0];
- tlen = ((ptr[1] & 0x0f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_V, "SKIP: %d+1, TID: %d, TLEN: %d, COLLECTED: %d\n", skip, tid, tlen, section->buffer_len);
- if(section->buffer_len < (skip+1+3+tlen))
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DATA IS NOT ENOUGH, NEXT TIME\n");
- return 0;
- }
-
- return skip+1;
-}
-
-static int parse_pat(ts_priv_t * priv, int is_start, unsigned char *buff, int size)
-{
- int skip;
- unsigned char *ptr;
- unsigned char *base;
- int entries, i;
- uint16_t progid;
- ts_section_t *section;
-
- section = &(priv->pat.section);
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- ptr = &(section->buffer[skip]);
- //PARSING
- priv->pat.table_id = ptr[0];
- if(priv->pat.table_id != 0)
- return 0;
- priv->pat.ssi = (ptr[1] >> 7) & 0x1;
- priv->pat.curr_next = ptr[5] & 0x01;
- priv->pat.ts_id = (ptr[3] << 8 ) | ptr[4];
- priv->pat.version_number = (ptr[5] >> 1) & 0x1F;
- priv->pat.section_length = ((ptr[1] & 0x03) << 8 ) | ptr[2];
- priv->pat.section_number = ptr[6];
- priv->pat.last_section_number = ptr[7];
-
- //check_crc32(0xFFFFFFFFL, ptr, priv->pat.buffer_len - 4, &ptr[priv->pat.buffer_len - 4]);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PAT: section_len: %d, section %d/%d\n", priv->pat.section_length, priv->pat.section_number, priv->pat.last_section_number);
-
- entries = (int) (priv->pat.section_length - 9) / 4; //entries per section
-
- for(i=0; i < entries; i++)
- {
- int32_t idx;
- base = &ptr[8 + i*4];
- progid = (base[0] << 8) | base[1];
-
- if((idx = prog_idx_in_pat(priv, progid)) == -1)
- {
- priv->pat.progs = realloc_struct(priv->pat.progs, priv->pat.progs_cnt+1, sizeof(struct pat_progs_t));
- if(!priv->pat.progs)
- {
- int sz = sizeof(struct pat_progs_t) * (priv->pat.progs_cnt+1);
- priv->pat.progs_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PAT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- break;
- }
- idx = priv->pat.progs_cnt;
- priv->pat.progs_cnt++;
- }
-
- priv->pat.progs[idx].id = progid;
- priv->pat.progs[idx].pmt_pid = ((base[2] & 0x1F) << 8) | base[3];
- mp_msg(MSGT_DEMUX, MSGL_V, "PROG: %d (%d-th of %d), PMT: %d\n", priv->pat.progs[idx].id, i+1, entries, priv->pat.progs[idx].pmt_pid);
- mp_msg(MSGT_IDENTIFY, MSGL_V, "PROGRAM_ID=%d (0x%02X), PMT_PID: %d(0x%02X)\n",
- progid, progid, priv->pat.progs[idx].pmt_pid, priv->pat.progs[idx].pmt_pid);
- }
-
- return 1;
-}
-
-
-static int32_t es_pid_in_pmt(pmt_t * pmt, uint16_t pid)
-{
- uint16_t i;
-
- if(pmt == NULL)
- return -1;
-
- if(pmt->es == NULL)
- return -1;
-
- for(i = 0; i < pmt->es_cnt; i++)
- {
- if(pmt->es[i].pid == pid)
- return (int32_t) i;
- }
-
- return -1;
-}
-
-
-static uint16_t get_mp4_desc_len(uint8_t *buf, int *len)
-{
- //uint16_t i = 0, size = 0;
- int i = 0, j, size = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PARSE_MP4_DESC_LEN(%d), bytes: ", *len);
- j = FFMIN(*len, 4);
- while(i < j)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, " %x ", buf[i]);
- size |= (buf[i] & 0x7f);
- if(!(buf[i] & 0x80))
- break;
- size <<= 7;
- i++;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, ", SIZE=%d\n", size);
-
- *len = i+1;
- return size;
-}
-
-
-static uint16_t parse_mp4_slconfig_descriptor(uint8_t *buf, int len, void *elem)
-{
- int i = 0;
- mp4_es_descr_t *es;
- mp4_sl_config_t *sl;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_SLCONFIG_DESCRIPTOR(%d)\n", len);
- es = (mp4_es_descr_t *) elem;
- if(!es)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
- sl = &(es->sl);
-
- sl->ts_len = sl->ocr_len = sl->au_len = sl->instant_bitrate_len = sl->degr_len = sl->au_seqnum_len = sl->packet_seqnum_len = 0;
- sl->ocr = sl->dts = sl->cts = 0;
-
- if(buf[0] == 0)
- {
- i++;
- sl->flags = buf[i];
- i++;
- sl->ts_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->ocr_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->ts_len = buf[i];
- i++;
- sl->ocr_len = buf[i];
- i++;
- sl->au_len = buf[i];
- i++;
- sl->instant_bitrate_len = buf[i];
- i++;
- sl->degr_len = (buf[i] >> 4) & 0x0f;
- sl->au_seqnum_len = ((buf[i] & 0x0f) << 1) | ((buf[i+1] >> 7) & 0x01);
- i++;
- sl->packet_seqnum_len = ((buf[i] >> 2) & 0x1f);
- i++;
-
- }
- else if(buf[0] == 1)
- {
- sl->flags = 0;
- sl->ts_resolution = 1000;
- sl->ts_len = 32;
- i++;
- }
- else if(buf[0] == 2)
- {
- sl->flags = 4;
- i++;
- }
- else
- {
- sl->flags = 0;
- i++;
- }
-
- sl->au_start = (sl->flags >> 7) & 0x1;
- sl->au_end = (sl->flags >> 6) & 0x1;
- sl->random_accesspoint = (sl->flags >> 5) & 0x1;
- sl->random_accesspoint_only = (sl->flags >> 4) & 0x1;
- sl->padding = (sl->flags >> 3) & 0x1;
- sl->use_ts = (sl->flags >> 2) & 0x1;
- sl->idle = (sl->flags >> 1) & 0x1;
- sl->duration = sl->flags & 0x1;
-
- if(sl->duration)
- {
- sl->timescale = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->au_duration = (buf[i] << 8) | buf[i+1];
- i += 2;
- sl->cts_duration = (buf[i] << 8) | buf[i+1];
- i += 2;
- }
- else //no support for fixed durations atm
- sl->timescale = sl->au_duration = sl->cts_duration = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4SLCONFIG(len=0x%x), predef: %d, flags: %x, use_ts: %d, tslen: %d, timescale: %d, dts: %"PRIu64", cts: %"PRIu64"\n",
- len, buf[0], sl->flags, sl->use_ts, sl->ts_len, sl->timescale, (uint64_t) sl->dts, (uint64_t) sl->cts);
-
- return len;
-}
-
-static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem);
-
-static uint16_t parse_mp4_decoder_config_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i = 0, j;
- mp4_es_descr_t *es;
- mp4_decoder_config_t *dec;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_CONFIG_DESCRIPTOR(%d)\n", len);
- es = (mp4_es_descr_t *) elem;
- if(!es)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
- dec = (mp4_decoder_config_t*) &(es->decoder);
-
- dec->object_type = buf[i];
- dec->stream_type = (buf[i+1]>>2) & 0x3f;
-
- if(dec->object_type == 1 && dec->stream_type == 1)
- {
- dec->object_type = MP4_OD;
- dec->stream_type = MP4_OD;
- }
- else if(dec->stream_type == 4)
- {
- if(dec->object_type == 0x6a)
- dec->object_type = VIDEO_MPEG1;
- if(dec->object_type >= 0x60 && dec->object_type <= 0x65)
- dec->object_type = VIDEO_MPEG2;
- else if(dec->object_type == 0x20)
- dec->object_type = VIDEO_MPEG4;
- else if(dec->object_type == 0x21)
- dec->object_type = VIDEO_AVC;
- /*else if(dec->object_type == 0x22)
- fprintf(stderr, "TYPE 0x22\n");*/
- else dec->object_type = UNKNOWN;
- }
- else if(dec->stream_type == 5)
- {
- if(dec->object_type == 0x40)
- dec->object_type = AUDIO_AAC;
- else if(dec->object_type == 0x6b)
- dec->object_type = AUDIO_MP2;
- else if(dec->object_type >= 0x66 && dec->object_type <= 0x69)
- dec->object_type = AUDIO_MP2;
- else
- dec->object_type = UNKNOWN;
- }
- else
- dec->object_type = dec->stream_type = UNKNOWN;
-
- if(dec->object_type != UNKNOWN)
- {
- //update the type of the current stream
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].mp4_es_id == es->id)
- {
- pmt->es[j].type = SL_PES_STREAM;
- }
- }
- }
-
- if(len > 13)
- parse_mp4_descriptors(pmt, &buf[13], len-13, dec);
-
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4DECODER(0x%x), object_type: 0x%x, stream_type: 0x%x\n", len, dec->object_type, dec->stream_type);
-
- return len;
-}
-
-static uint16_t parse_mp4_decoder_specific_descriptor(uint8_t *buf, int len, void *elem)
-{
- int i;
- mp4_decoder_config_t *dec;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_SPECIFIC_DESCRIPTOR(%d)\n", len);
- dec = (mp4_decoder_config_t *) elem;
- if(!dec)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4 SPECIFIC INFO BYTES: \n");
- for(i=0; i<len; i++)
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "%02x ", buf[i]);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "\n");
-
- if(len > MAX_EXTRADATA_SIZE)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "DEMUX_TS, EXTRADATA SUSPICIOUSLY BIG: %d, REFUSED\r\n", len);
- return len;
- }
- memcpy(dec->buf, buf, len);
- dec->buf_size = len;
-
- return len;
-}
-
-static uint16_t parse_mp4_es_descriptor(pmt_t *pmt, uint8_t *buf, int len)
-{
- int i = 0, j = 0, k, found;
- uint8_t flag;
- mp4_es_descr_t es, *target_es = NULL;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES: len=%d\n", len);
- memset(&es, 0, sizeof(mp4_es_descr_t));
- while(i < len)
- {
- es.id = (buf[i] << 8) | buf[i+1];
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_ID: %d\n", es.id);
- i += 2;
- flag = buf[i];
- i++;
- if(flag & 0x80)
- i += 2;
- if(flag & 0x40)
- i += buf[i]+1;
- if(flag & 0x20) //OCR, maybe we need it
- i += 2;
-
- j = parse_mp4_descriptors(pmt, &buf[i], len-i, &es);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES, types after parse_mp4_descriptors: 0x%x, 0x%x\n", es.decoder.object_type, es.decoder.stream_type);
- if(es.decoder.object_type != UNKNOWN && es.decoder.stream_type != UNKNOWN)
- {
- found = 0;
- //search this ES_ID if we already have it
- for(k=0; k < pmt->mp4es_cnt; k++)
- {
- if(pmt->mp4es[k].id == es.id)
- {
- target_es = &(pmt->mp4es[k]);
- found = 1;
- }
- }
-
- if(! found)
- {
- pmt->mp4es = realloc_struct(pmt->mp4es, pmt->mp4es_cnt+1, sizeof(mp4_es_descr_t));
- if(!pmt->mp4es)
- {
- pmt->mp4es_cnt = 0;
- fprintf(stderr, "CAN'T REALLOC MP4_ES_DESCR\n");
- continue;
- }
- target_es = &(pmt->mp4es[pmt->mp4es_cnt]);
- pmt->mp4es_cnt++;
- }
- memcpy(target_es, &es, sizeof(mp4_es_descr_t));
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_CNT: %d, ID=%d\n", pmt->mp4es_cnt, target_es->id);
- }
-
- i += j;
- }
-
- return len;
-}
-
-static void parse_mp4_object_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i, j = 0, id;
-
- i=0;
- id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_OBJECT_DESCRIPTOR: len=%d, OD_ID=%d\n", len, id);
- if(buf[1] & 0x20)
- {
- i += buf[2] + 1; //url
- mp_msg(MSGT_DEMUX, MSGL_V, "URL\n");
- }
- else
- {
- i = 2;
-
- while(i < len)
- {
- j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem);
- mp_msg(MSGT_DEMUX, MSGL_V, "OBJD, NOW i = %d, j=%d, LEN=%d\n", i, j, len);
- i += j;
- }
- }
-}
-
-
-static void parse_mp4_iod(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i, j = 0;
- mp4_od_t *iod = &(pmt->iod);
-
- iod->id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_IOD: len=%d, IOD_ID=%d\n", len, iod->id);
- i = 2;
- if(buf[1] & 0x20)
- {
- i += buf[2] + 1; //url
- mp_msg(MSGT_DEMUX, MSGL_V, "URL\n");
- }
- else
- {
- i = 7;
- while(i < len)
- {
- j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem);
- mp_msg(MSGT_DEMUX, MSGL_V, "IOD, NOW i = %d, j=%d, LEN=%d\n", i, j, len);
- i += j;
- }
- }
-}
-
-static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int tag, descr_len, i = 0, j = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DESCRIPTORS, len=%d\n", len);
- if(! len)
- return len;
-
- while(i < len)
- {
- tag = buf[i];
- j = len - i -1;
- descr_len = get_mp4_desc_len(&(buf[i+1]), &j);
- mp_msg(MSGT_DEMUX, MSGL_V, "TAG=%d (0x%x), DESCR_len=%d, len=%d, j=%d\n", tag, tag, descr_len, len, j);
- if(descr_len > len - j+1)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "descriptor is too long, exit\n");
- return len;
- }
- i += j+1;
-
- switch(tag)
- {
- case 0x1:
- parse_mp4_object_descriptor(pmt, &(buf[i]), descr_len, elem);
- break;
- case 0x2:
- parse_mp4_iod(pmt, &(buf[i]), descr_len, elem);
- break;
- case 0x3:
- parse_mp4_es_descriptor(pmt, &(buf[i]), descr_len);
- break;
- case 0x4:
- parse_mp4_decoder_config_descriptor(pmt, &buf[i], descr_len, elem);
- break;
- case 0x05:
- parse_mp4_decoder_specific_descriptor(&buf[i], descr_len, elem);
- break;
- case 0x6:
- parse_mp4_slconfig_descriptor(&buf[i], descr_len, elem);
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "Unsupported mp4 descriptor 0x%x\n", tag);
- }
- i += descr_len;
- }
-
- return len;
-}
-
-static ES_stream_t *new_pid(ts_priv_t *priv, int pid)
-{
- ES_stream_t *tss;
-
- tss = calloc(sizeof(*tss), 1);
- if(! tss)
- return NULL;
- tss->pid = pid;
- tss->last_cc = -1;
- tss->type = UNKNOWN;
- tss->subtype = UNKNOWN;
- tss->is_synced = 0;
- tss->extradata = NULL;
- tss->extradata_alloc = tss->extradata_len = 0;
- priv->ts.pids[pid] = tss;
-
- return tss;
-}
-
-
-static int parse_program_descriptors(pmt_t *pmt, uint8_t *buf, uint16_t len)
-{
- uint16_t i = 0, k, olen = len;
-
- while(len > 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PROG DESCR, TAG=%x, LEN=%d(%x)\n", buf[i], buf[i+1], buf[i+1]);
- if(buf[i+1] > len-2)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "ERROR, descriptor len is too long, skipping\n");
- return olen;
- }
-
- if(buf[i] == 0x1d)
- {
- if(buf[i+3] == 2) //buggy versions of vlc muxer make this non-standard mess (missing iod_scope)
- k = 3;
- else
- k = 4; //this is standard compliant
- parse_mp4_descriptors(pmt, &buf[i+k], (int) buf[i+1]-(k-2), NULL);
- }
-
- len -= 2 + buf[i+1];
- }
-
- return olen;
-}
-
-static int parse_descriptors(struct pmt_es_t *es, uint8_t *ptr)
-{
- int j, descr_len, len;
-
- j = 0;
- len = es->descr_length;
- while(len > 2)
- {
- descr_len = ptr[j+1];
- mp_msg(MSGT_DEMUX, MSGL_V, "...descr id: 0x%x, len=%d\n", ptr[j], descr_len);
- if(descr_len > len)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "INVALID DESCR LEN for tag %02x: %d vs %d max, EXIT LOOP\n", ptr[j], descr_len, len);
- return -1;
- }
-
-
- if(ptr[j] == 0x6a || ptr[j] == 0x7a) //A52 Descriptor
- {
- if(es->type == 0x6)
- {
- es->type = AUDIO_A52;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB A52 Descriptor\n");
- }
- }
- else if(ptr[j] == 0x7b) //DVB DTS Descriptor
- {
- if(es->type == 0x6)
- {
- es->type = AUDIO_DTS;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB DTS Descriptor\n");
- }
- }
- else if(ptr[j] == 0x56) // Teletext
- {
- if(descr_len >= 5) {
- memcpy(es->lang, ptr+j+2, 3);
- es->lang[3] = 0;
- }
- es->type = SPU_TELETEXT;
- }
- else if(ptr[j] == 0x59) //Subtitling Descriptor
- {
- uint8_t subtype;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Subtitling Descriptor\n");
- if(descr_len < 8)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Descriptor length too short for DVB Subtitle Descriptor: %d, SKIPPING\n", descr_len);
- }
- else
- {
- memcpy(es->lang, &ptr[j+2], 3);
- es->lang[3] = 0;
- subtype = ptr[j+5];
- if(
- (subtype >= 0x10 && subtype <= 0x13) ||
- (subtype >= 0x20 && subtype <= 0x23)
- )
- {
- es->type = SPU_DVB;
- //page parameters: compo page 2 bytes, ancillary page 2 bytes
- }
- else
- es->type = UNKNOWN;
- }
- }
- else if(ptr[j] == 0x50) //Component Descriptor
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Component Descriptor\n");
- memcpy(es->lang, &ptr[j+5], 3);
- es->lang[3] = 0;
- }
- else if(ptr[j] == 0xa) //Language Descriptor
- {
- memcpy(es->lang, &ptr[j+2], 3);
- es->lang[3] = 0;
- mp_msg(MSGT_DEMUX, MSGL_V, "Language Descriptor: %s\n", es->lang);
- }
- else if(ptr[j] == 0x5) //Registration Descriptor (looks like e fourCC :) )
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor\n");
- if(descr_len < 4)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor length too short: %d, SKIPPING\n", descr_len);
- }
- else
- {
- char *d;
- memcpy(es->format_descriptor, &ptr[j+2], 4);
- es->format_descriptor[4] = 0;
-
- d = &ptr[j+2];
- if(d[0] == 'A' && d[1] == 'C' && d[2] == '-' && d[3] == '3')
- {
- es->type = AUDIO_A52;
- }
- else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '1')
- {
- es->type = AUDIO_DTS;
- }
- else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '2')
- {
- es->type = AUDIO_DTS;
- }
- else if(d[0] == 'V' && d[1] == 'C' && d[2] == '-' && d[3] == '1')
- {
- es->type = VIDEO_VC1;
- }
- else if(d[0] == 'd' && d[1] == 'r' && d[2] == 'a' && d[3] == 'c')
- {
- es->type = VIDEO_DIRAC;
- }
- else if(d[0] == 'B' && d[1] == 'S' && d[2] == 'S' && d[3] == 'D')
- {
- es->type = AUDIO_S302M;
- }
- else
- es->type = UNKNOWN;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "FORMAT %s\n", es->format_descriptor);
- }
- }
- else if(ptr[j] == 0x1e || ptr[j] == 0x1f)
- {
- // 0x1f is FMC, but currently it is easiest to handle them the same way
- es->mp4_es_id = (ptr[j+2] << 8) | ptr[j+3];
- mp_msg(MSGT_DEMUX, MSGL_V, "SL Descriptor: ES_ID: %d(%x), pid: %d\n", es->mp4_es_id, es->mp4_es_id, es->pid);
- }
- else
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Unknown descriptor 0x%x, SKIPPING\n", ptr[j]);
-
- len -= 2 + descr_len;
- j += 2 + descr_len;
- }
-
- return 1;
-}
-
-static int parse_sl_section(pmt_t *pmt, ts_section_t *section, int is_start, unsigned char *buff, int size)
-{
- int tid, len, skip;
- uint8_t *ptr;
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- ptr = &(section->buffer[skip]);
- tid = ptr[0];
- len = ((ptr[1] & 0x0f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_V, "TABLEID: %d (av. %d), skip=%d, LEN: %d\n", tid, section->buffer_len, skip, len);
- if(len > 4093 || section->buffer_len < len || tid != 5)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "SECTION TOO LARGE or wrong section type, EXIT\n");
- return 0;
- }
-
- if(! (ptr[5] & 1))
- return 0;
-
- //8 is the current position, len - 9 is the amount of data available
- parse_mp4_descriptors(pmt, &ptr[8], len - 9, NULL);
-
- return 1;
-}
-
-static int parse_pmt(ts_priv_t * priv, uint16_t progid, uint16_t pid, int is_start, unsigned char *buff, int size)
-{
- unsigned char *base, *es_base;
- pmt_t *pmt;
- int32_t idx, es_count, section_bytes;
- uint8_t m=0;
- int skip;
- ts_section_t *section;
- ES_stream_t *tss;
- int i;
-
- idx = progid_idx_in_pmt(priv, progid);
-
- if(idx == -1)
- {
- priv->pmt = realloc_struct(priv->pmt, priv->pmt_cnt + 1, sizeof(pmt_t));
- if(!priv->pmt)
- {
- int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t);
- priv->pmt_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- return 0;
- }
- idx = priv->pmt_cnt;
- memset(&(priv->pmt[idx]), 0, sizeof(pmt_t));
- priv->pmt_cnt++;
- priv->pmt[idx].progid = progid;
- }
-
- pmt = &(priv->pmt[idx]);
-
- section = &(pmt->section);
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- base = &(section->buffer[skip]);
-
- mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TS_PID: %d, SIZE=%d, M=%d, ES_CNT=%d, IDX=%d, PMT_PTR=%p\n",
- progid, pmt->section.buffer_len, is_start, pid, size, m, pmt->es_cnt, idx, pmt);
-
- pmt->table_id = base[0];
- if(pmt->table_id != 2)
- return -1;
- pmt->ssi = base[1] & 0x80;
- pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]);
- pmt->version_number = (base[5] >> 1) & 0x1f;
- pmt->curr_next = (base[5] & 1);
- pmt->section_number = base[6];
- pmt->last_section_number = base[7];
- pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9];
- pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11];
- if(pmt->prog_descr_length > pmt->section_length - 9)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9);
- return -1;
- }
-
- if(pmt->prog_descr_length)
- parse_program_descriptors(pmt, &base[12], pmt->prog_descr_length);
-
- es_base = &base[12 + pmt->prog_descr_length]; //the beginning of th ES loop
-
- section_bytes= pmt->section_length - 13 - pmt->prog_descr_length;
- es_count = 0;
-
- while(section_bytes >= 5)
- {
- int es_pid, es_type;
-
- es_type = es_base[0];
- es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2];
-
- idx = es_pid_in_pmt(pmt, es_pid);
- if(idx == -1)
- {
- pmt->es = realloc_struct(pmt->es, pmt->es_cnt + 1, sizeof(struct pmt_es_t));
- if(!pmt->es)
- {
- int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1);
- pmt->es_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz);
- continue;
- }
- idx = pmt->es_cnt;
- memset(&(pmt->es[idx]), 0, sizeof(struct pmt_es_t));
- pmt->es_cnt++;
- }
-
- pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4];
-
-
- if(pmt->es[idx].descr_length > section_bytes - 5)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT\n",
- pmt->es[idx].descr_length, section_bytes - 5);
- return -1;
- }
-
-
- pmt->es[idx].pid = es_pid;
- if(es_type != 0x6)
- pmt->es[idx].type = UNKNOWN;
- else
- pmt->es[idx].type = es_type;
-
- parse_descriptors(&pmt->es[idx], &es_base[5]);
-
- switch(es_type)
- {
- case 1:
- pmt->es[idx].type = VIDEO_MPEG1;
- break;
- case 2:
- pmt->es[idx].type = VIDEO_MPEG2;
- break;
- case 3:
- case 4:
- pmt->es[idx].type = AUDIO_MP2;
- break;
- case 6:
- if(pmt->es[idx].type == 0x6) //this could have been ovrwritten by parse_descriptors
- pmt->es[idx].type = UNKNOWN;
- break;
- case 0x10:
- pmt->es[idx].type = VIDEO_MPEG4;
- break;
- case 0x0f:
- pmt->es[idx].type = AUDIO_AAC;
- break;
- case 0x11:
- pmt->es[idx].type = AUDIO_AAC_LATM;
- for (i = 0; i < pmt->mp4es_cnt; i++)
- if (pmt->mp4es[i].id == pmt->es[idx].mp4_es_id &&
- pmt->mp4es[i].decoder.object_type == AUDIO_AAC)
- pmt->es[idx].type = AUDIO_AAC;
- break;
- case 0x1b:
- pmt->es[idx].type = VIDEO_H264;
- break;
- case 0x12:
- pmt->es[idx].type = SL_PES_STREAM;
- break;
- case 0x13:
- pmt->es[idx].type = SL_SECTION;
- break;
- case 0x80:
- pmt->es[idx].type = AUDIO_PCM_BR;
- break;
- case 0x81:
- pmt->es[idx].type = AUDIO_A52;
- break;
- case 0x8A:
- case 0x82:
- case 0x85:
- case 0x86:
- pmt->es[idx].type = AUDIO_DTS;
- break;
- case 0x90:
- pmt->es[idx].type = SPU_PGS;
- break;
- case 0xD1:
- pmt->es[idx].type = VIDEO_DIRAC;
- break;
- case 0xEA:
- pmt->es[idx].type = VIDEO_VC1;
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "UNKNOWN ES TYPE=0x%x\n", es_type);
- pmt->es[idx].type = UNKNOWN;
- }
-
- tss = priv->ts.pids[es_pid]; //an ES stream
- if(tss == NULL)
- {
- tss = new_pid(priv, es_pid);
- if(tss)
- tss->type = pmt->es[idx].type;
- }
-
- section_bytes -= 5 + pmt->es[idx].descr_length;
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n",
- progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes);
-
-
- es_base += 5 + pmt->es[idx].descr_length;
-
- es_count++;
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "----------------------------\n");
- return 1;
-}
-
-static pmt_t* pmt_of_pid(ts_priv_t *priv, int pid, mp4_decoder_config_t **mp4_dec)
-{
- int32_t i, j, k;
-
- if(priv->pmt)
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- if(priv->pmt[i].es && priv->pmt[i].es_cnt)
- {
- for(j = 0; j < priv->pmt[i].es_cnt; j++)
- {
- if(priv->pmt[i].es[j].pid == pid)
- {
- //search mp4_es_id
- if(priv->pmt[i].es[j].mp4_es_id)
- {
- for(k = 0; k < priv->pmt[i].mp4es_cnt; k++)
- {
- if(priv->pmt[i].mp4es[k].id == priv->pmt[i].es[j].mp4_es_id)
- {
- *mp4_dec = &(priv->pmt[i].mp4es[k].decoder);
- break;
- }
- }
- }
-
- return &(priv->pmt[i]);
- }
- }
- }
- }
- }
-
- return NULL;
-}
-
-
-static int32_t pid_type_from_pmt(ts_priv_t *priv, int pid)
-{
- int32_t pmt_idx, pid_idx, i, j;
-
- pmt_idx = progid_idx_in_pmt(priv, priv->prog);
-
- if(pmt_idx != -1)
- {
- pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);
- if(pid_idx != -1)
- return priv->pmt[pmt_idx].es[pid_idx].type;
- }
- //else
- //{
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- pmt_t *pmt = &(priv->pmt[i]);
- for(j = 0; j < pmt->es_cnt; j++)
- if(pmt->es[j].pid == pid)
- return pmt->es[j].type;
- }
- //}
-
- return UNKNOWN;
-}
-
-
-static uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid)
-{
- int32_t pmt_idx, pid_idx, i, j;
-
- pmt_idx = progid_idx_in_pmt(priv, priv->prog);
-
- if(pmt_idx != -1)
- {
- pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);
- if(pid_idx != -1)
- return priv->pmt[pmt_idx].es[pid_idx].lang;
- }
- else
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- pmt_t *pmt = &(priv->pmt[i]);
- for(j = 0; j < pmt->es_cnt; j++)
- if(pmt->es[j].pid == pid)
- return pmt->es[j].lang;
- }
- }
-
- return NULL;
-}
-
-
-static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset, TS_stream_info *si)
-{
- int ret = 0;
-
- if(*dp && *dp_offset <= 0)
- {
- free_demux_packet(*dp);
- *dp = NULL;
- }
- if(*dp)
- {
- ret = *dp_offset;
- resize_demux_packet(*dp, ret); //shrinked to the right size
- ds_add_packet(ds, *dp);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts);
- if(si)
- {
- float diff = (*dp)->pts - si->last_pts;
- float dur;
-
- if(abs(diff) > 1) //1 second, there's a discontinuity
- {
- si->duration += si->last_pts - si->first_pts;
- si->first_pts = si->last_pts = (*dp)->pts;
- }
- else
- {
- si->last_pts = (*dp)->pts;
- }
- si->size += ret;
- dur = si->duration + (si->last_pts - si->first_pts);
-
- if(dur > 0 && ds == demuxer->video)
- {
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- if(dur > 1) //otherwise it may be unreliable
- priv->vbitrate = (uint32_t) ((float) si->size / dur);
- }
- }
- }
-
- *dp = NULL;
- *dp_offset = 0;
-
- return ret;
-}
-
-static int fill_extradata(mp4_decoder_config_t * mp4_dec, ES_stream_t *tss)
-{
- uint8_t *tmp;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4_dec: %p, pid: %d\n", mp4_dec, tss->pid);
-
- if(mp4_dec->buf_size > tss->extradata_alloc)
- {
- tmp = realloc(tss->extradata, mp4_dec->buf_size);
- if(!tmp)
- return 0;
- tss->extradata = tmp;
- tss->extradata_alloc = mp4_dec->buf_size;
- }
- memcpy(tss->extradata, mp4_dec->buf, mp4_dec->buf_size);
- tss->extradata_len = mp4_dec->buf_size;
- mp_msg(MSGT_DEMUX, MSGL_V, "EXTRADATA: %p, alloc=%d, len=%d\n", tss->extradata, tss->extradata_alloc, tss->extradata_len);
-
- return tss->extradata_len;
-}
-
-// 0 = EOF or no stream found
-// else = [-] number of bytes written to the packet
-static int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe)
-{
- ES_stream_t *tss;
- int buf_size, is_start, pid, base;
- int len, cc, cc_ok av_unused, afc, retv = 0, is_video, is_audio, is_sub;
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- stream_t *stream = demuxer->stream;
- char *p;
- demux_stream_t *ds = NULL;
- demux_packet_t **dp = NULL;
- int *dp_offset = 0, *buffer_size = 0;
- int32_t progid, pid_type, bad, ts_error;
- int junk = 0, rap_flag = 0;
- pmt_t *pmt;
- mp4_decoder_config_t *mp4_dec;
- TS_stream_info *si;
-
-
- memset(es, 0, sizeof(*es));
- while(1)
- {
- bad = ts_error = 0;
- ds = NULL;
- dp = NULL;
- dp_offset = buffer_size = NULL;
- rap_flag = 0;
- mp4_dec = NULL;
- es->is_synced = 0;
- es->lang[0] = 0;
- si = NULL;
-
- junk = priv->ts.packet_size - TS_PACKET_SIZE;
- buf_size = priv->ts.packet_size - junk;
-
- if(stream_eof(stream))
- {
- if(! probe)
- {
- ts_dump_streams(priv);
- demuxer->filepos = stream_tell(demuxer->stream);
- }
-
- return 0;
- }
-
-
- if(! ts_sync(stream))
- {
- mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n");
- return 0;
- }
-
- len = stream_read(stream, &packet[1], 3);
- if (len != 3)
- return 0;
- buf_size -= 4;
-
- if((packet[1] >> 7) & 0x01) //transport error
- ts_error = 1;
-
-
- is_start = packet[1] & 0x40;
- pid = ((packet[1] & 0x1f) << 8) | packet[2];
-
- tss = priv->ts.pids[pid]; //an ES stream
- if(tss == NULL)
- {
- tss = new_pid(priv, pid);
- if(tss == NULL)
- continue;
- }
-
- cc = (packet[3] & 0xf);
- cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
- tss->last_cc = cc;
-
- bad = ts_error; // || (! cc_ok);
- if(bad)
- {
- if(priv->keep_broken == 0)
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- is_start = 0; //queued to the packet data
- }
-
- if(is_start)
- tss->is_synced = 1;
-
- if((!is_start && !tss->is_synced) || ((pid > 1) && (pid < 16)) || (pid == 8191)) //invalid pid
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
-
- afc = (packet[3] >> 4) & 3;
- if(! (afc % 2)) //no payload in this TS packet
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- if(afc > 1)
- {
- int c;
- c = stream_read_char(stream);
- buf_size--;
- if(c < 0 || c > 183) //broken from the stream layer or invalid
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- //c==0 is allowed!
- if(c > 0)
- {
- uint8_t pcrbuf[188];
- int flags = stream_read_char(stream);
- int has_pcr;
- rap_flag = (flags & 0x40) >> 6;
- has_pcr = flags & 0x10;
-
- buf_size--;
- c--;
- stream_read(stream, pcrbuf, c);
-
- if(has_pcr)
- {
- int pcr_pid = prog_pcr_pid(priv, priv->prog);
- if(pcr_pid == pid)
- {
- uint64_t pcr, pcr_ext;
-
- pcr = (int64_t)(pcrbuf[0]) << 25;
- pcr |= pcrbuf[1] << 17 ;
- pcr |= (pcrbuf[2]) << 9;
- pcr |= pcrbuf[3] << 1 ;
- pcr |= (pcrbuf[4] & 0x80) >> 7;
-
- pcr_ext = (pcrbuf[4] & 0x01) << 8;
- pcr_ext |= pcrbuf[5];
-
- pcr = pcr * 300 + pcr_ext;
-
- demuxer->reference_clock = (double)pcr/(double)27000000.0;
- }
- }
-
- buf_size -= c;
- if(buf_size == 0)
- continue;
- }
- }
-
- //find the program that the pid belongs to; if (it's the right one or -1) && pid_type==SL_SECTION
- //call parse_sl_section()
- pmt = pmt_of_pid(priv, pid, &mp4_dec);
- if(mp4_dec)
- {
- fill_extradata(mp4_dec, tss);
- if(IS_VIDEO(mp4_dec->object_type) || IS_AUDIO(mp4_dec->object_type))
- {
- tss->type = SL_PES_STREAM;
- tss->subtype = mp4_dec->object_type;
- }
- }
-
-
- //TABLE PARSING
-
- base = priv->ts.packet_size - buf_size;
-
- priv->last_pid = pid;
-
- is_video = IS_VIDEO(tss->type) || (tss->type==SL_PES_STREAM && IS_VIDEO(tss->subtype));
- is_audio = IS_AUDIO(tss->type) || (tss->type==SL_PES_STREAM && IS_AUDIO(tss->subtype)) || (tss->type == PES_PRIVATE1);
- is_sub = IS_SUB(tss->type);
- pid_type = pid_type_from_pmt(priv, pid);
-
- // PES CONTENT STARTS HERE
- if(! probe)
- {
- if((is_video || is_audio || is_sub) && is_start)
- ts_add_stream(demuxer, tss);
-
- if(is_video && (demuxer->video->id == priv->ts.streams[pid].id))
- {
- ds = demuxer->video;
-
- dp = &priv->fifo[1].pack;
- dp_offset = &priv->fifo[1].offset;
- buffer_size = &priv->fifo[1].buffer_size;
- si = &priv->vstr;
- }
- else if(is_audio && (demuxer->audio->id == priv->ts.streams[pid].id))
- {
- ds = demuxer->audio;
-
- dp = &priv->fifo[0].pack;
- dp_offset = &priv->fifo[0].offset;
- buffer_size = &priv->fifo[0].buffer_size;
- si = &priv->astr;
- }
- else if(is_sub)
- {
- sh_sub_t *sh_sub = demuxer->sub->sh;
-
- if(sh_sub && sh_sub->gsh->demuxer_id == tss->pid)
- {
- ds = demuxer->sub;
-
- dp = &priv->fifo[2].pack;
- dp_offset = &priv->fifo[2].offset;
- buffer_size = &priv->fifo[2].buffer_size;
- }
- else
- {
- stream_skip(stream, buf_size+junk);
- continue;
- }
- }
-
- //IS IT TIME TO QUEUE DATA to the dp_packet?
- if(is_start && (dp != NULL))
- {
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
- }
-
-
- if(dp && *dp == NULL)
- {
- if(*buffer_size > MAX_PACK_BYTES)
- *buffer_size = MAX_PACK_BYTES;
- *dp = new_demux_packet(*buffer_size); //es->size
- *dp_offset = 0;
- if(! *dp)
- {
- fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", *buffer_size);
- continue;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "CREATED DP(%d)\n", *buffer_size);
- }
- }
-
-
- if(probe || !dp) //dp is NULL for tables and sections
- {
- p = &packet[base];
- }
- else //feeding
- {
- if(*dp_offset + buf_size > *buffer_size)
- {
- *buffer_size = *dp_offset + buf_size + TS_FEC_PACKET_SIZE;
- resize_demux_packet(*dp, *buffer_size);
- }
- p = &((*dp)->buffer[*dp_offset]);
- }
-
- len = stream_read(stream, p, buf_size);
- if(len < buf_size)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "\r\nts_parse() couldn't read enough data: %d < %d\r\n", len, buf_size);
- continue;
- }
- stream_skip(stream, junk);
-
- if(pid == 0)
- {
- parse_pat(priv, is_start, p, buf_size);
- continue;
- }
- else if((tss->type == SL_SECTION) && pmt)
- {
- int k, mp4_es_id = -1;
- ts_section_t *section;
- for(k = 0; k < pmt->mp4es_cnt; k++)
- {
- if(pmt->mp4es[k].decoder.object_type == MP4_OD && pmt->mp4es[k].decoder.stream_type == MP4_OD)
- mp4_es_id = pmt->mp4es[k].id;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4ESID: %d\n", mp4_es_id);
- for(k = 0; k < pmt->es_cnt; k++)
- {
- if(pmt->es[k].mp4_es_id == mp4_es_id)
- {
- section = &(tss->section);
- parse_sl_section(pmt, section, is_start, &packet[base], buf_size);
- }
- }
- continue;
- }
- else
- {
- progid = prog_id_in_pat(priv, pid);
- if(progid != -1)
- {
- if(pid != demuxer->video->id && pid != demuxer->audio->id && pid != demuxer->sub->id)
- {
- parse_pmt(priv, progid, pid, is_start, &packet[base], buf_size);
- continue;
- }
- else
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Argh! Data pid %d used in the PMT, Skipping PMT parsing!\n", pid);
- }
- }
-
- if(!probe && !dp)
- continue;
-
- if(is_start)
- {
- uint8_t *lang = NULL;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "IS_START\n");
-
- len = pes_parse2(p, buf_size, es, pid_type, pmt, pid);
- if(! len)
- {
- tss->is_synced = 0;
- continue;
- }
- es->pid = tss->pid;
- tss->is_synced |= es->is_synced || rap_flag;
- tss->payload_size = es->payload_size;
-
- if((is_sub || is_audio) && (lang = pid_lang_from_pmt(priv, es->pid)))
- {
- memcpy(es->lang, lang, 3);
- es->lang[3] = 0;
- }
- else
- es->lang[0] = 0;
-
- if(probe)
- {
- if(es->type == UNKNOWN)
- return 0;
-
- tss->type = es->type;
- tss->subtype = es->subtype;
-
- return 1;
- }
- else
- {
- if(es->pts == 0.0)
- es->pts = tss->pts = tss->last_pts;
- else
- tss->pts = tss->last_pts = es->pts;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, NEW pid=%d, PSIZE: %u, type=%X, start=%p, len=%d\n",
- es->pid, es->payload_size, es->type, es->start, es->size);
-
- demuxer->filepos = stream_tell(demuxer->stream) - es->size;
-
- if(es->size < 0 || es->size > buf_size) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Broken ES packet size\n");
- es->size = 0;
- }
- memmove(p, es->start, es->size);
- *dp_offset += es->size;
- (*dp)->keyframe = 0;
- (*dp)->pos = stream_tell(demuxer->stream);
- (*dp)->pts = es->pts;
- // subtitle packets must be returned immediately if possible
- if (is_sub && !tss->payload_size)
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
-
- if(retv > 0)
- return retv;
- else
- continue;
- }
- }
- else
- {
- uint16_t sz;
-
- es->pid = tss->pid;
- es->type = tss->type;
- es->subtype = tss->subtype;
- es->pts = tss->pts = tss->last_pts;
- es->start = &packet[base];
-
-
- if(tss->payload_size > 0)
- {
- sz = FFMIN(tss->payload_size, buf_size);
- tss->payload_size -= sz;
- es->size = sz;
- }
- else
- {
- if(is_video)
- {
- sz = es->size = buf_size;
- }
- else
- {
- continue;
- }
- }
-
-
- if(! probe)
- {
- *dp_offset += sz;
-
- // subtitle packets must be returned immediately if possible
- if(*dp_offset >= MAX_PACK_BYTES || (is_sub && !tss->payload_size))
- {
- (*dp)->pts = tss->last_pts;
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
- return 1;
- }
-
- continue;
- }
- else
- {
- memmove(es->start, p, sz);
-
- if(es->size)
- return es->size;
- else
- continue;
- }
- }
- }
-
- return 0;
-}
-
-
-static void reset_fifos(demuxer_t *demuxer, int a, int v, int s)
-{
- ts_priv_t* priv = demuxer->priv;
- if(a)
- {
- if(priv->fifo[0].pack != NULL)
- {
- free_demux_packet(priv->fifo[0].pack);
- priv->fifo[0].pack = NULL;
- }
- priv->fifo[0].offset = 0;
- }
-
- if(v)
- {
- if(priv->fifo[1].pack != NULL)
- {
- free_demux_packet(priv->fifo[1].pack);
- priv->fifo[1].pack = NULL;
- }
- priv->fifo[1].offset = 0;
- }
-
- if(s)
- {
- if(priv->fifo[2].pack != NULL)
- {
- free_demux_packet(priv->fifo[2].pack);
- priv->fifo[2].pack = NULL;
- }
- priv->fifo[2].offset = 0;
- }
- demuxer->reference_clock = MP_NOPTS_VALUE;
-}
-
-
-static void demux_seek_ts(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
-{
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- int i, video_stats;
- int64_t newpos;
-
- //================= seek in MPEG-TS ==========================
-
- ts_dump_streams(demuxer->priv);
- reset_fifos(demuxer, sh_audio != NULL, sh_video != NULL, demuxer->sub->id > 0);
-
- demux_flush(demuxer);
-
-
-
- video_stats = (sh_video != NULL);
- if(video_stats)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "IBPS: %d, vb: %d\r\n", sh_video->i_bps, priv->vbitrate);
- if(priv->vbitrate)
- video_stats = priv->vbitrate;
- else
- video_stats = sh_video->i_bps;
- }
-
- newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : demuxer->filepos;
- if(flags & SEEK_FACTOR) // float seek 0..1
- newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
- else
- {
- // time seek (secs)
- if(! video_stats) // unspecified or VBR
- newpos += 2324*75*rel_seek_secs; // 174.3 kbyte/sec
- else
- newpos += video_stats*rel_seek_secs;
- }
-
-
- if(newpos < demuxer->movi_start)
- newpos = demuxer->movi_start; //begininng of stream
-
- stream_seek(demuxer->stream, newpos);
- for(i = 0; i < NB_PID_MAX; i++)
- if(priv->ts.pids[i] != NULL)
- priv->ts.pids[i]->is_synced = 0;
-
- videobuf_code_len = 0;
-
- if(sh_video != NULL)
- ds_fill_buffer(d_video);
-
- if(sh_audio != NULL)
- {
- ds_fill_buffer(d_audio);
- }
-
- while(sh_video != NULL)
- {
- if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts)
- {
- double a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(double)sh_audio->i_bps;
- if(d_video->pts > a_pts)
- {
- skip_audio_frame(sh_audio); // sync audio
- continue;
- }
- }
-
-
- i = sync_video_packet(d_video);
- if((sh_video->format == VIDEO_MPEG1) || (sh_video->format == VIDEO_MPEG2))
- {
- if(i==0x1B3 || i==0x1B8) break; // found it!
- }
- else if((sh_video->format == VIDEO_MPEG4) && (i==0x1B6))
- break;
- else if(sh_video->format == VIDEO_VC1 && (i==0x10E || i==0x10F))
- break;
- else //H264
- {
- if((i & ~0x60) == 0x105 || (i & ~0x60) == 0x107) break;
- }
-
- if(!i || !skip_video_packet(d_video)) break; // EOF?
- }
-}
-
-
-static int demux_ts_fill_buffer(demuxer_t * demuxer, demux_stream_t *ds)
-{
- ES_stream_t es;
- ts_priv_t *priv = (ts_priv_t *)demuxer->priv;
-
- return -ts_parse(demuxer, &es, priv->packet, 0);
-}
-
-
-static int ts_check_file_dmx(demuxer_t *demuxer)
-{
- return ts_check_file(demuxer) ? DEMUXER_TYPE_MPEG_TS : 0;
-}
-
-static int is_usable_program(ts_priv_t *priv, pmt_t *pmt)
-{
- int j;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL)
- continue;
- if(
- priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO ||
- priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO
- )
- return 1;
- }
-
- return 0;
-}
-
-static int demux_ts_control(demuxer_t *demuxer, int cmd, void *arg)
-{
- ts_priv_t* priv = (ts_priv_t *)demuxer->priv;
-
- switch(cmd)
- {
- case DEMUXER_CTRL_SWITCH_AUDIO:
- case DEMUXER_CTRL_SWITCH_VIDEO:
- {
- void *sh = NULL;
- int i, n;
- int reftype, areset = 0, vreset = 0;
- demux_stream_t *ds;
-
- if(cmd == DEMUXER_CTRL_SWITCH_VIDEO)
- {
- reftype = TYPE_VIDEO;
- ds = demuxer->video;
- vreset = 1;
- }
- else
- {
- reftype = TYPE_AUDIO;
- ds = demuxer->audio;
- areset = 1;
- }
- n = *((int*)arg);
- if(n == -2)
- {
- reset_fifos(demuxer, areset, vreset, 0);
- ds->id = -2;
- ds->sh = NULL;
- ds_free_packs(ds);
- *((int*)arg) = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- if(n < 0)
- {
- for(i = 0; i < 8192; i++)
- {
- if(priv->ts.streams[i].id == ds->id && priv->ts.streams[i].type == reftype)
- break;
- }
-
- while(!sh)
- {
- i = (i+1) % 8192;
- if(priv->ts.streams[i].type == reftype)
- {
- if(priv->ts.streams[i].id == ds->id) //we made a complete loop
- break;
- sh = priv->ts.streams[i].sh;
- }
- }
- }
- else //audio track <n>
- {
- if (n >= 8192 || priv->ts.streams[n].type != reftype) return DEMUXER_CTRL_NOTIMPL;
- i = n;
- sh = priv->ts.streams[i].sh;
- }
-
- if(sh)
- {
- if(ds->id != priv->ts.streams[i].id)
- reset_fifos(demuxer, areset, vreset, 0);
- ds->id = priv->ts.streams[i].id;
- ds->sh = sh;
- ds_free_packs(ds);
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndemux_ts, switched to audio pid %d, id: %d, sh: %p\r\n", i, ds->id, sh);
- }
-
- *((int*)arg) = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- case DEMUXER_CTRL_IDENTIFY_PROGRAM: //returns in prog->{aid,vid} the new ids that comprise a program
- {
- int i, j, cnt=0;
- int vid_done=0, aid_done=0;
- pmt_t *pmt = NULL;
- demux_program_t *prog = arg;
-
- if(priv->pmt_cnt < 2)
- return DEMUXER_CTRL_NOTIMPL;
-
- if(prog->progid == -1)
- {
- int cur_pmt_idx = 0;
-
- for(i = 0; i < priv->pmt_cnt; i++)
- if(priv->pmt[i].progid == priv->prog)
- {
- cur_pmt_idx = i;
- break;
- }
-
- i = (cur_pmt_idx + 1) % priv->pmt_cnt;
- while(i != cur_pmt_idx)
- {
- pmt = &priv->pmt[i];
- cnt = is_usable_program(priv, pmt);
- if(cnt)
- break;
- i = (i + 1) % priv->pmt_cnt;
- }
- }
- else
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- if(priv->pmt[i].progid == prog->progid)
- {
- pmt = &priv->pmt[i]; //required program
- cnt = is_usable_program(priv, pmt);
- }
- }
-
- if(!cnt)
- return DEMUXER_CTRL_NOTIMPL;
-
- //finally some food
- prog->aid = prog->vid = -2; //no audio and no video by default
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL)
- continue;
-
- if(!vid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO)
- {
- vid_done = 1;
- prog->vid = pmt->es[j].pid;
- }
- else if(!aid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO)
- {
- aid_done = 1;
- prog->aid = pmt->es[j].pid;
- }
- }
-
- priv->prog = prog->progid = pmt->progid;
- return DEMUXER_CTRL_OK;
- }
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-const demuxer_desc_t demuxer_desc_mpeg_ts = {
- "MPEG-TS demuxer",
- "mpegts",
- "TS",
- "Nico Sabbi",
- "",
- DEMUXER_TYPE_MPEG_TS,
- 0, // unsafe autodetect
- ts_check_file_dmx,
- demux_ts_fill_buffer,
- demux_open_ts,
- demux_close_ts,
- demux_seek_ts,
- demux_ts_control
-};
diff --git a/demux/demux_ts.h b/demux/demux_ts.h
deleted file mode 100644
index 37bddb86da..0000000000
--- a/demux/demux_ts.h
+++ /dev/null
@@ -1,24 +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.
- */
-
-#ifndef MPLAYER_DEMUX_TS_H
-#define MPLAYER_DEMUX_TS_H
-
-#define TS_MAX_PROBE_SIZE 2000000
-
-#endif /* MPLAYER_DEMUX_TS_H */
diff --git a/demux/extension.c b/demux/extension.c
deleted file mode 100644
index 71b5bf8f4d..0000000000
--- a/demux/extension.c
+++ /dev/null
@@ -1,104 +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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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_MPEG_PS },
- { "m2v", DEMUXER_TYPE_MPEG_PS },
- { "avi", DEMUXER_TYPE_AVI },
- { "asx", DEMUXER_TYPE_ASF },
- { "asf", DEMUXER_TYPE_ASF },
- { "wmv", DEMUXER_TYPE_ASF },
- { "wma", DEMUXER_TYPE_ASF },
- { "rm", DEMUXER_TYPE_LAVF },
- { "rmvb", DEMUXER_TYPE_LAVF },
- { "ra", DEMUXER_TYPE_LAVF },
- { "y4m", DEMUXER_TYPE_Y4M },
- { "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_NSV },
- { "nsa", DEMUXER_TYPE_NSV },
- { "mpc", DEMUXER_TYPE_MPC },
-#ifdef CONFIG_WIN32DLL
- { "avs", DEMUXER_TYPE_AVS },
-#endif
- { "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/demux/mp3_hdr.c b/demux/mp3_hdr.c
deleted file mode 100644
index 27a02368da..0000000000
--- a/demux/mp3_hdr.c
+++ /dev/null
@@ -1,144 +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 <stdio.h>
-
-#include "config.h"
-#include "mp3_hdr.h"
-#include "core/mp_msg.h"
-
-//----------------------- mp3 audio frame header parser -----------------------
-
-static int tabsel_123[2][3][16] = {
- { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
- {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0},
- {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0} },
-
- { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }
-};
-
-static long freqs[9] = { 44100, 48000, 32000, // MPEG 1.0
- 22050, 24000, 16000, // MPEG 2.0
- 11025, 12000, 8000}; // MPEG 2.5
-
-/*
- * return frame size or -1 (bad frame)
- */
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* srate, int* spf, int* mpa_layer, int* br){
- int stereo,ssize,lsf,framesize,padding,bitrate_index,sampling_frequency, divisor;
- int bitrate;
- int layer, mult[3] = { 12000, 144000, 144000 };
- unsigned long newhead =
- hbuf[0] << 24 |
- hbuf[1] << 16 |
- hbuf[2] << 8 |
- hbuf[3];
-
-// printf("head=0x%08X\n",newhead);
-
- // head_check:
- if( (newhead & 0xffe00000) != 0xffe00000 ){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"head_check failed\n");
- return -1;
- }
-
- layer = 4-((newhead>>17)&3);
- if(layer==4){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"not layer-1/2/3\n");
- return -1;
- }
-
- sampling_frequency = ((newhead>>10)&0x3); // valid: 0..2
- if(sampling_frequency==3){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"invalid sampling_frequency\n");
- return -1;
- }
-
- if( newhead & ((long)1<<20) ) {
- // MPEG 1.0 (lsf==0) or MPEG 2.0 (lsf==1)
- lsf = (newhead & ((long)1<<19)) ? 0x0 : 0x1;
- sampling_frequency += (lsf*3);
- } else {
- // MPEG 2.5
- lsf = 1;
- sampling_frequency += 6;
- }
-
-// crc = ((newhead>>16)&0x1)^0x1;
- bitrate_index = ((newhead>>12)&0xf); // valid: 1..14
- padding = ((newhead>>9)&0x1);
-// fr->extension = ((newhead>>8)&0x1);
-// fr->mode = ((newhead>>6)&0x3);
-// fr->mode_ext = ((newhead>>4)&0x3);
-// fr->copyright = ((newhead>>3)&0x1);
-// fr->original = ((newhead>>2)&0x1);
-// fr->emphasis = newhead & 0x3;
-
- stereo = ( (((newhead>>6)&0x3)) == 3) ? 1 : 2;
-
-// !checked later through tabsel_123[]!
-// if(!bitrate_index || bitrate_index==15){
-// mp_msg(MSGT_DEMUXER,MSGL_DBG2,"Free format not supported.\n");
-// return -1;
-// }
-
- if(lsf)
- ssize = (stereo == 1) ? 9 : 17;
- else
- ssize = (stereo == 1) ? 17 : 32;
- if(!((newhead>>16)&0x1)) ssize += 2; // CRC
-
- bitrate = tabsel_123[lsf][layer-1][bitrate_index];
- framesize = bitrate * mult[layer-1];
-
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"FRAMESIZE: %d, layer: %d, bitrate: %d, mult: %d\n",
- framesize, layer, tabsel_123[lsf][layer-1][bitrate_index], mult[layer-1]);
- if(!framesize){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"invalid framesize/bitrate_index\n");
- return -1;
- }
-
- divisor = (layer == 3 ? (freqs[sampling_frequency] << lsf) : freqs[sampling_frequency]);
- framesize /= divisor;
- if(layer==1)
- framesize = (framesize+padding)*4;
- else
- framesize += padding;
-
-// if(framesize<=0 || framesize>MAXFRAMESIZE) return FALSE;
- if(srate) {
- *srate = freqs[sampling_frequency];
- if(spf) {
- if(layer == 1)
- *spf = 384;
- else if(layer == 2)
- *spf = 1152;
- else if(*srate < 32000)
- *spf = 576;
- else
- *spf = 1152;
- }
- }
- if(mpa_layer) *mpa_layer = layer;
- if(chans) *chans = stereo;
- if(br) *br = bitrate;
-
- return framesize;
-}
diff --git a/demux/mp3_hdr.h b/demux/mp3_hdr.h
deleted file mode 100644
index a9b34ac12c..0000000000
--- a/demux/mp3_hdr.h
+++ /dev/null
@@ -1,36 +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.
- */
-
-#ifndef MPLAYER_MP3_HDR_H
-#define MPLAYER_MP3_HDR_H
-
-#include <stddef.h>
-
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer, int* br);
-
-#define mp_decode_mp3_header(hbuf) mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL,NULL)
-
-static inline int mp_check_mp3_header(unsigned int head){
- unsigned char tmp[4] = {head >> 24, head >> 16, head >> 8, head};
- if( (head & 0xffe00000) != 0xffe00000 ||
- (head & 0x00000c00) == 0x00000c00) return 0;
- if(mp_decode_mp3_header(tmp)<=0) return 0;
- return 1;
-}
-
-#endif /* MPLAYER_MP3_HDR_H */
diff --git a/demux/mpeg_hdr.c b/demux/mpeg_hdr.c
deleted file mode 100644
index fcc4a33ecc..0000000000
--- a/demux/mpeg_hdr.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * based on libmpeg2/header.c by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "mpeg_hdr.h"
-#include "libavutil/attributes.h"
-#include "core/mp_msg.h"
-
-static float frameratecode2framerate[16] = {
- 0,
- // Official mpeg1/2 framerates: (1-8)
- 24000.0/1001, 24,25,
- 30000.0/1001, 30,50,
- 60000.0/1001, 60,
- // Xing's 15fps: (9)
- 15,
- // libmpeg3's "Unofficial economy rates": (10-13)
- 5,10,12,15,
- // some invalid ones: (14-15)
- 0,0
-};
-
-
-int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer)
-{
- int height;
-
- if ((buffer[6] & 0x20) != 0x20){
- fprintf(stderr, "missing marker bit!\n");
- return 1; /* missing marker_bit */
- }
-
- height = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
-
- picture->display_picture_width = height >> 12;
- picture->display_picture_height = height & 0xfff;
-
- picture->aspect_ratio_information = buffer[3] >> 4;
- picture->frame_rate_code = buffer[3] & 15;
- picture->fps=frameratecode2framerate[picture->frame_rate_code];
- picture->bitrate = (buffer[4]<<10)|(buffer[5]<<2)|(buffer[6]>>6);
- picture->mpeg1 = 1;
- picture->picture_structure = 3; //FRAME_PICTURE;
- picture->display_time=100;
- picture->frame_rate_extension_n = 1;
- picture->frame_rate_extension_d = 1;
- return 0;
-}
-
-static int header_process_sequence_extension (mp_mpeg_header_t * picture,
- unsigned char * buffer)
-{
- /* check chroma format, size extensions, marker bit */
-
- if ( ((buffer[1] & 0x06) == 0x00) ||
- ((buffer[1] & 0x01) != 0x00) || (buffer[2] & 0xe0) ||
- ((buffer[3] & 0x01) != 0x01) )
- return 1;
-
- picture->progressive_sequence = (buffer[1] >> 3) & 1;
- picture->frame_rate_extension_n = ((buffer[5] >> 5) & 3) + 1;
- picture->frame_rate_extension_d = (buffer[5] & 0x1f) + 1;
-
- picture->mpeg1 = 0;
- return 0;
-}
-
-static int header_process_picture_coding_extension (mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- picture->picture_structure = buffer[2] & 3;
- picture->top_field_first = buffer[3] >> 7;
- picture->repeat_first_field = (buffer[3] >> 1) & 1;
- picture->progressive_frame = buffer[4] >> 7;
-
- // repeat_first implementation by A'rpi/ESP-team, based on libmpeg3:
- picture->display_time=100;
- if(picture->repeat_first_field){
- if(picture->progressive_sequence){
- if(picture->top_field_first)
- picture->display_time+=200;
- else
- picture->display_time+=100;
- } else
- if(picture->progressive_frame){
- picture->display_time+=50;
- }
- }
- //temopral hack. We calc time on every field, so if we have 2 fields
- // interlaced we'll end with double time for 1 frame
- if( picture->picture_structure!=3 ) picture->display_time/=2;
- return 0;
-}
-
-int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- switch (buffer[0] & 0xf0) {
- case 0x10: /* sequence extension */
- return header_process_sequence_extension (picture, buffer);
- case 0x80: /* picture coding extension */
- return header_process_picture_coding_extension (picture, buffer);
- }
- return 0;
-}
-
-float mpeg12_aspect_info(mp_mpeg_header_t *picture)
-{
- float aspect = 0.0;
-
- switch(picture->aspect_ratio_information) {
- case 2: // PAL/NTSC SVCD/DVD 4:3
- case 8: // PAL VCD 4:3
- case 12: // NTSC VCD 4:3
- aspect=4.0/3.0;
- break;
- case 3: // PAL/NTSC Widescreen SVCD/DVD 16:9
- case 6: // (PAL?)/NTSC Widescreen SVCD 16:9
- aspect=16.0/9.0;
- break;
- case 4: // according to ISO-138182-2 Table 6.3
- aspect=2.21;
- break;
- case 1: // VGA 1:1 - do not prescale
- case 9: // Movie Type ??? / 640x480
- aspect=0.0;
- break;
- default:
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Detected unknown aspect_ratio_information in mpeg sequence header.\n"
- "Please report the aspect value (%i) along with the movie type (VGA,PAL,NTSC,"
- "SECAM) and the movie resolution (720x576,352x240,480x480,...) to the MPlayer"
- " developers, so that we can add support for it!\nAssuming 1:1 aspect for now.\n",
- picture->aspect_ratio_information);
- }
-
- return aspect;
-}
-
-//MPEG4 HEADERS
-unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len)
-{
- unsigned int n;
- unsigned char m, u, l, y;
-
- n = from / 8;
- m = from % 8;
- u = 8 - m;
- l = (len > u ? len - u : 0);
-
- y = (buffer[n] << m);
- if(8 > len)
- y >>= (8-len);
- if(l)
- y |= (buffer[n+1] >> (8-l));
-
- //fprintf(stderr, "GETBITS(%d -> %d): bytes=0x%x 0x%x, n=%d, m=%d, l=%d, u=%d, Y=%d\n",
- // from, (int) len, (int) buffer[n],(int) buffer[n+1], n, (int) m, (int) l, (int) u, (int) y);
- return y;
-}
-
-static inline unsigned int mp_getbits16(unsigned char *buffer, unsigned int from, unsigned char len)
-{
- if(len > 8)
- return (mp_getbits(buffer, from, len - 8) << 8) | mp_getbits(buffer, from + len - 8, 8);
- else
- return mp_getbits(buffer, from, len);
-}
-
-#define getbits mp_getbits
-#define getbits16 mp_getbits16
-
-static int read_timeinc(mp_mpeg_header_t * picture, unsigned char * buffer, int n)
-{
- if(picture->timeinc_bits > 8) {
- picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits - 8) << 8;
- n += picture->timeinc_bits - 8;
- picture->timeinc_unit |= getbits(buffer, n, 8);
- n += 8;
- } else {
- picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits);
- n += picture->timeinc_bits;
- }
- //fprintf(stderr, "TIMEINC2: %d, bits: %d\n", picture->timeinc_unit, picture->timeinc_bits);
- return n;
-}
-
-int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- unsigned int n, aspect=0, aspectw av_unused=0, aspecth av_unused=0, x=1, v;
-
- //begins with 0x0000012x
- picture->fps = 0;
- picture->timeinc_bits = picture->timeinc_resolution = picture->timeinc_unit = 0;
- n = 9;
- if(getbits(buffer, n, 1))
- n += 7;
- n++;
- aspect=getbits(buffer, n, 4);
- n += 4;
- if(aspect == 0x0f) {
- aspectw = getbits(buffer, n, 8);
- n += 8;
- aspecth = getbits(buffer, n, 8);
- n += 8;
- }
-
- if(getbits(buffer, n, 1)) {
- n += 4;
- if(getbits(buffer, n, 1))
- n += 79;
- n++;
- } else n++;
-
- n+=3;
-
- picture->timeinc_resolution = getbits(buffer, n, 8) << 8;
- n += 8;
- picture->timeinc_resolution |= getbits(buffer, n, 8);
- n += 8;
-
- picture->timeinc_bits = 0;
- v = picture->timeinc_resolution - 1;
- while(v && (x<16)) {
- v>>=1;
- picture->timeinc_bits++;
- }
- picture->timeinc_bits = (picture->timeinc_bits > 1 ? picture->timeinc_bits : 1);
-
- n++; //marker bit
-
- if(getbits(buffer, n++, 1)) { //fixed_vop_timeinc
- n += read_timeinc(picture, buffer, n);
-
- if(picture->timeinc_unit)
- picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit;
- }
-
- n++; //marker bit
- picture->display_picture_width = getbits16(buffer, n, 13);
- n += 13;
- n++; //marker bit
- picture->display_picture_height = getbits16(buffer, n, 13);
- n += 13;
-
- //fprintf(stderr, "ASPECT: %d, PARW=%d, PARH=%d, TIMEINCRESOLUTION: %d, FIXED_TIMEINC: %d (number of bits: %d), FPS: %u\n",
- // aspect, aspectw, aspecth, picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_bits, picture->fps);
-
- return 0;
-}
-
-void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- int n;
- n = 0;
- picture->picture_type = getbits(buffer, n, 2);
- n += 2;
- while(getbits(buffer, n, 1))
- n++;
- n++;
- getbits(buffer, n, 1);
- n++;
- n += read_timeinc(picture, buffer, n);
-}
-
-#define min(a, b) ((a) <= (b) ? (a) : (b))
-
-static unsigned int read_golomb(unsigned char *buffer, unsigned int *init)
-{
- unsigned int x, v = 0, v2 = 0, m, len = 0, n = *init;
-
- while(getbits(buffer, n++, 1) == 0)
- len++;
-
- x = len + n;
- while(n < x)
- {
- m = min(x - n, 8);
- v |= getbits(buffer, n, m);
- n += m;
- if(x - n > 8)
- v <<= 8;
- }
-
- v2 = 1;
- for(n = 0; n < len; n++)
- v2 <<= 1;
- v2 = (v2 - 1) + v;
-
- //fprintf(stderr, "READ_GOLOMB(%u), V=2^%u + %u-1 = %u\n", *init, len, v, v2);
- *init = x;
- return v2;
-}
-
-inline static int read_golomb_s(unsigned char *buffer, unsigned int *init)
-{
- unsigned int v = read_golomb(buffer, init);
- return (v & 1) ? ((v + 1) >> 1) : -(v >> 1);
-}
-
-static int h264_parse_vui(mp_mpeg_header_t * picture, unsigned char * buf, unsigned int n)
-{
- unsigned int overscan, vsp_color, chroma, timing, fixed_fps;
-
- if(getbits(buf, n++, 1))
- {
- picture->aspect_ratio_information = getbits(buf, n, 8);
- n += 8;
- if(picture->aspect_ratio_information == 255)
- {
- picture->display_picture_width = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
- n += 16;
-
- picture->display_picture_height = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
- n += 16;
- }
- }
-
- if((overscan=getbits(buf, n++, 1)))
- n++;
- if((vsp_color=getbits(buf, n++, 1)))
- {
- n += 4;
- if(getbits(buf, n++, 1))
- n += 24;
- }
- if((chroma=getbits(buf, n++, 1)))
- {
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- }
- if((timing=getbits(buf, n++, 1)))
- {
- picture->timeinc_unit = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
- n += 32;
-
- picture->timeinc_resolution = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
- n += 32;
-
- fixed_fps = getbits(buf, n, 1);
-
- if(picture->timeinc_unit > 0 && picture->timeinc_resolution > 0)
- picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit;
- if(fixed_fps)
- picture->fps /= 2;
- }
-
- //fprintf(stderr, "H264_PARSE_VUI, OVESCAN=%u, VSP_COLOR=%u, CHROMA=%u, TIMING=%u, DISPW=%u, DISPH=%u, TIMERES=%u, TIMEINC=%u, FIXED_FPS=%u\n", overscan, vsp_color, chroma, timing, picture->display_picture_width, picture->display_picture_height,
- // picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_unit, fixed_fps);
-
- return n;
-}
-
-static int mp_unescape03(unsigned char *buf, int len)
-{
- unsigned char *dest;
- int i, j, skip;
-
- dest = malloc(len);
- if(! dest)
- return 0;
-
- j = i = skip = 0;
- while(i <= len-3)
- {
- if(buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3)
- {
- dest[j] = dest[j+1] = 0;
- j += 2;
- i += 3;
- skip++;
- }
- else
- {
- dest[j] = buf[i];
- j++;
- i++;
- }
- }
- dest[j] = buf[len-2];
- dest[j+1] = buf[len-1];
- len -= skip;
- memcpy(buf, dest, len);
- free(dest);
-
- return len;
-}
-
-int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len)
-{
- unsigned int n = 0, v, i, k, mbh;
- int frame_mbs_only;
-
- len = mp_unescape03(buf, len);
-
- picture->fps = picture->timeinc_unit = picture->timeinc_resolution = 0;
- n = 24;
- read_golomb(buf, &n);
- if(buf[0] >= 100){
- if(read_golomb(buf, &n) == 3)
- n++;
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- n++;
- if(getbits(buf, n++, 1)){
- for(i = 0; i < 8; i++)
- { // scaling list is skipped for now
- if(getbits(buf, n++, 1))
- {
- v = 8;
- for(k = (i < 6 ? 16 : 64); k && v; k--)
- v = (v + read_golomb_s(buf, &n)) & 255;
- }
- }
- }
- }
- read_golomb(buf, &n);
- v = read_golomb(buf, &n);
- if(v == 0)
- read_golomb(buf, &n);
- else if(v == 1)
- {
- getbits(buf, n++, 1);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- v = read_golomb(buf, &n);
- for(i = 0; i < v; i++)
- read_golomb(buf, &n);
- }
- read_golomb(buf, &n);
- getbits(buf, n++, 1);
- picture->display_picture_width = 16 *(read_golomb(buf, &n)+1);
- mbh = read_golomb(buf, &n)+1;
- frame_mbs_only = getbits(buf, n++, 1);
- picture->display_picture_height = 16 * (2 - frame_mbs_only) * mbh;
- if(!frame_mbs_only)
- getbits(buf, n++, 1);
- getbits(buf, n++, 1);
- if(getbits(buf, n++, 1))
- {
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- }
- if(getbits(buf, n++, 1))
- n = h264_parse_vui(picture, buf, n);
-
- return n;
-}
-
-int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len)
-{
- int n, x;
-
- len = mp_unescape03(buf, len);
-
- picture->display_picture_width = picture->display_picture_height = 0;
- picture->fps = 0;
- n = 0;
- x = getbits(buf, n, 2);
- n += 2;
- if(x != 3) //not advanced profile
- return 0;
-
- getbits16(buf, n, 14);
- n += 14;
- picture->display_picture_width = getbits16(buf, n, 12) * 2 + 2;
- n += 12;
- picture->display_picture_height = getbits16(buf, n, 12) * 2 + 2;
- n += 12;
- getbits(buf, n, 6);
- n += 6;
- x = getbits(buf, n, 1);
- n += 1;
- if(x) //display info
- {
- getbits16(buf, n, 14);
- n += 14;
- getbits16(buf, n, 14);
- n += 14;
- if(getbits(buf, n++, 1)) //aspect ratio
- {
- x = getbits(buf, n, 4);
- n += 4;
- if(x == 15)
- {
- getbits16(buf, n, 16);
- n += 16;
- }
- }
-
- if(getbits(buf, n++, 1)) //framerates
- {
- int frexp=0, frnum=0, frden=0;
-
- if(getbits(buf, n++, 1))
- {
- frexp = getbits16(buf, n, 16);
- n += 16;
- picture->fps = (double) (frexp+1) / 32.0;
- }
- else
- {
- float frates[] = {0, 24000, 25000, 30000, 50000, 60000, 48000, 72000, 0};
- float frdivs[] = {0, 1000, 1001, 0};
-
- frnum = getbits(buf, n, 8);
- n += 8;
- frden = getbits(buf, n, 4);
- n += 4;
- if((frden == 1 || frden == 2) && (frnum < 8))
- picture->fps = frates[frnum] / frdivs[frden];
- }
- }
- }
-
- //free(dest);
- return 1;
-}
diff --git a/demux/mpeg_hdr.h b/demux/mpeg_hdr.h
deleted file mode 100644
index ccd84bcdb0..0000000000
--- a/demux/mpeg_hdr.h
+++ /dev/null
@@ -1,55 +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.
- */
-
-#ifndef MPLAYER_MPEG_HDR_H
-#define MPLAYER_MPEG_HDR_H
-
-typedef struct {
- // video info:
- int mpeg1; // 0=mpeg2 1=mpeg1
- int display_picture_width;
- int display_picture_height;
- int aspect_ratio_information;
- int frame_rate_code;
- float fps;
- int frame_rate_extension_n;
- int frame_rate_extension_d;
- int bitrate; // 0x3FFFF==VBR
- // timing:
- int picture_structure;
- int progressive_sequence;
- int repeat_first_field;
- int progressive_frame;
- int top_field_first;
- int display_time; // secs*100
- //the following are for mpeg4
- unsigned int timeinc_resolution, timeinc_bits, timeinc_unit;
- int picture_type;
-} mp_mpeg_header_t;
-
-int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer);
-int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer);
-float mpeg12_aspect_info(mp_mpeg_header_t *picture);
-int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer);
-void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer);
-int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len);
-int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len);
-
-unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len);
-
-#endif /* MPLAYER_MPEG_HDR_H */
diff --git a/demux/ms_hdr.h b/demux/ms_hdr.h
index 8e545635dd..5911d30730 100644
--- a/demux/ms_hdr.h
+++ b/demux/ms_hdr.h
@@ -22,6 +22,14 @@
#include <sys/types.h>
#include "config.h"
+#include "compat/mpbswap.h"
+
+#ifndef mmioFOURCC
+#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
+ ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
+ ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
+#endif
+
#ifndef _WAVEFORMATEX_
#define _WAVEFORMATEX_
typedef struct __attribute__((__packed__)) _WAVEFORMATEX {
@@ -46,18 +54,6 @@ typedef struct __attribute__((__packed__)) _WAVEFORMATEXTENSIBLE {
} WAVEFORMATEXTENSIBLE;
#endif /* _WAVEFORMATEXTENSIBLE_ */
-#ifndef _MPEGLAYER3WAVEFORMAT_
-#define _MPEGLAYER3WAVEFORMAT_
-typedef struct __attribute__((__packed__)) mpeglayer3waveformat_tag {
- WAVEFORMATEX wf;
- unsigned short wID;
- unsigned int fdwFlags;
- unsigned short nBlockSize;
- unsigned short nFramesPerBlock;
- unsigned short nCodecDelay;
-} MPEGLAYER3WAVEFORMAT;
-#endif /* _MPEGLAYER3WAVEFORMAT_ */
-
/* windows.h #includes wingdi.h on MinGW. */
#if !defined(_BITMAPINFOHEADER_) && !defined(_WINGDI_)
#define _BITMAPINFOHEADER_
@@ -75,40 +71,6 @@ typedef struct __attribute__((__packed__))
int biClrUsed;
int biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER, *LPBITMAPINFOHEADER;
-typedef struct {
- BITMAPINFOHEADER bmiHeader;
- int bmiColors[1];
-} BITMAPINFO, *LPBITMAPINFO;
-#endif
-
-#ifndef le2me_BITMAPINFOHEADER
-#if BYTE_ORDER == BIG_ENDIAN
-#define le2me_BITMAPINFOHEADER(h) { \
- (h)->biSize = le2me_32((h)->biSize); \
- (h)->biWidth = le2me_32((h)->biWidth); \
- (h)->biHeight = le2me_32((h)->biHeight); \
- (h)->biPlanes = le2me_16((h)->biPlanes); \
- (h)->biBitCount = le2me_16((h)->biBitCount); \
- (h)->biCompression = le2me_32((h)->biCompression); \
- (h)->biSizeImage = le2me_32((h)->biSizeImage); \
- (h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
- (h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
- (h)->biClrUsed = le2me_32((h)->biClrUsed); \
- (h)->biClrImportant = le2me_32((h)->biClrImportant); \
-}
-#define le2me_WAVEFORMATEX(h) { \
- (h)->wFormatTag = le2me_16((h)->wFormatTag); \
- (h)->nChannels = le2me_16((h)->nChannels); \
- (h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
- (h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
- (h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
- (h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
- (h)->cbSize = le2me_16((h)->cbSize); \
-}
-#else
-#define le2me_BITMAPINFOHEADER(h) /**/
-#define le2me_WAVEFORMATEX(h) /**/
-#endif
#endif
#endif /* MPLAYER_MS_HDR_H */
diff --git a/demux/parse_es.c b/demux/parse_es.c
deleted file mode 100644
index 8e43446c1f..0000000000
--- a/demux/parse_es.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * MPEG-ES video parser
- *
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "parse_es.h"
-
-//static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE];
-unsigned char* videobuffer=NULL;
-int videobuf_len=0;
-int next_nal = -1;
-///! legacy variable, 4 if stream is synced, 0 if not
-int videobuf_code_len=0;
-
-#define MAX_SYNCLEN (10 * 1024 * 1024)
-// sync video stream, and returns next packet code
-int sync_video_packet(demux_stream_t *ds){
- if (!videobuf_code_len) {
- int skipped=0;
- if (!demux_pattern_3(ds, NULL, MAX_SYNCLEN, &skipped, 0x100)) {
- if (skipped == MAX_SYNCLEN)
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "parse_es: could not sync video stream!\n");
- goto eof_out;
- }
- next_nal = demux_getc(ds);
- if (next_nal < 0)
- goto eof_out;
- videobuf_code_len = 4;
- if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped (next: 0x1%02X)\n",skipped,next_nal);
- }
- return 0x100|next_nal;
-
-eof_out:
- next_nal = -1;
- videobuf_code_len = 0;
- return 0;
-}
-
-// return: packet length
-int read_video_packet(demux_stream_t *ds){
-int packet_start;
- int res, read;
-
- if (VIDEOBUFFER_SIZE - videobuf_len < 5)
- return 0;
- // SYNC STREAM
-// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
-
- // COPY STARTCODE:
- packet_start=videobuf_len;
- videobuffer[videobuf_len+0]=0;
- videobuffer[videobuf_len+1]=0;
- videobuffer[videobuf_len+2]=1;
- videobuffer[videobuf_len+3]=next_nal;
- videobuf_len+=4;
-
- // READ PACKET:
- res = demux_pattern_3(ds, &videobuffer[videobuf_len],
- VIDEOBUFFER_SIZE - videobuf_len, &read, 0x100);
- videobuf_len += read;
- if (!res)
- goto eof_out;
-
- videobuf_len-=3;
-
- mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X len=%d (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len);
-
- // Save next packet code:
- next_nal = demux_getc(ds);
- if (next_nal < 0)
- goto eof_out;
- videobuf_code_len=4;
-
- return videobuf_len-packet_start;
-
-eof_out:
- next_nal = -1;
- videobuf_code_len = 0;
- return videobuf_len - packet_start;
-}
-
-// return: next packet code
-int skip_video_packet(demux_stream_t *ds){
-
- // SYNC STREAM
-// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
-
- videobuf_code_len=0; // force resync
-
- // SYNC AGAIN:
- return sync_video_packet(ds);
-}
-
-/* stripped down version of a52_syncinfo() from liba52
- * copyright belongs to Michel Lespinasse <walken@zoy.org>
- * and Aaron Holtzman <aholtzma@ess.engr.uvic.ca> */
-int mp_a52_framesize(uint8_t * buf, int *srate)
-{
- int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
- 128, 160, 192, 224, 256, 320, 384, 448,
- 512, 576, 640
- };
- uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
- int frmsizecod, bitrate, half;
-
- if ((buf[0] != 0x0b) || (buf[1] != 0x77)) /* syncword */
- return 0;
-
- if (buf[5] >= 0x60) /* bsid >= 12 */
- return 0;
-
- half = halfrate[buf[5] >> 3];
-
- frmsizecod = buf[4] & 63;
- if (frmsizecod >= 38)
- return 0;
-
- bitrate = rate[frmsizecod >> 1];
-
- switch (buf[4] & 0xc0) {
- case 0: /* 48 KHz */
- *srate = 48000 >> half;
- return 4 * bitrate;
- case 0x40: /* 44.1 KHz */
- *srate = 44100 >> half;
- return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
- case 0x80: /* 32 KHz */
- *srate = 32000 >> half;
- return 6 * bitrate;
- }
-
- return 0;
-}
diff --git a/demux/parse_es.h b/demux/parse_es.h
deleted file mode 100644
index af558e379d..0000000000
--- a/demux/parse_es.h
+++ /dev/null
@@ -1,45 +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.
- */
-
-#ifndef MPLAYER_PARSE_ES_H
-#define MPLAYER_PARSE_ES_H
-
-#include <stdint.h>
-
-#include "demux.h"
-
-#define MAX_VIDEO_PACKET_SIZE (224*1024+4)
-#define VIDEOBUFFER_SIZE 0x100000
-
-extern unsigned char* videobuffer;
-extern int videobuf_len;
-extern unsigned char videobuf_code[4];
-extern int videobuf_code_len;
-
-// sync video stream, and returns next packet code
-int sync_video_packet(demux_stream_t *ds);
-
-// return: packet length
-int read_video_packet(demux_stream_t *ds);
-
-// return: next packet code
-int skip_video_packet(demux_stream_t *ds);
-
-int mp_a52_framesize(uint8_t *buf, int *srate);
-
-#endif /* MPLAYER_PARSE_ES_H */
diff --git a/demux/stheader.h b/demux/stheader.h
index ff98430a65..c1f606090a 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -21,10 +21,7 @@
#include <stdbool.h>
-#include "codec_tags.h"
-
#include "audio/chmap.h"
-#include "aviheader.h"
#include "ms_hdr.h"
struct MPOpts;
struct demuxer;
@@ -43,8 +40,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;
@@ -64,26 +59,26 @@ 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;
// shouldn't exist type of stuff
struct MPOpts *opts;
-};
+ // Internal to demux.c
+ struct demux_stream *ds;
+};
#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; \
- /* number of seconds stream should be delayed \
- * (according to dwStart or similar) */ \
- float stream_delay; \
/* audio: last known pts value in output from decoder \
* video: predicted/interpolated PTS of the current frame */ \
double pts; \
@@ -98,13 +93,7 @@ typedef struct sh_audio {
int container_out_samplerate;
int samplesize;
struct mp_chmap channels;
- int o_bps; // == samplerate*samplesize*channels.num (uncompr. bytes/sec)
int i_bps; // == bitrate (compressed bytes/sec)
- // in buffers:
- int audio_in_minsize; // initial size to allocate for a_in_buffer if any
- char *a_in_buffer; // input buffer used by some decoders
- int a_in_buffer_len;
- int a_in_buffer_size;
// decoder buffers:
int audio_out_minsize; // minimal output from decoder may be this much
char *a_buffer; // buffer for decoder output
@@ -113,21 +102,15 @@ typedef struct sh_audio {
struct af_stream *afilter; // the audio filter stream
const struct ad_functions *ad_driver;
// win32-compatible codec parameters:
- AVIStreamHeader audio;
WAVEFORMATEX *wf;
// note codec extradata may be either under "wf" or "codecdata"
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 {
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];
@@ -141,7 +124,6 @@ typedef struct sh_video {
int pts_assoc_mode;
// output format: (set by demuxer)
float fps; // frames per second (set only if constant fps)
- float frametime; // 1/fps
float aspect; // aspect ratio stored in the file (for prescaling)
float stream_aspect; // aspect ratio in media headers (DVD IFO files)
int i_bps; // == bitrate (compressed bytes/sec)
@@ -153,7 +135,6 @@ typedef struct sh_video {
const struct vd_functions *vd_driver;
int vf_initialized; // -1 failed, 0 not done, 1 done
// win32-compatible codec parameters:
- AVIStreamHeader video;
BITMAPINFOHEADER *bih;
} sh_video_t;
@@ -167,20 +148,4 @@ typedef struct sh_sub {
struct dec_sub *dec_sub; // decoder context
} 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_sub *new_sh_sub_sid(struct demuxer *demuxer, int id, int sid);
-struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid,
- const char *lang);
-struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type);
-
-// video.c:
-int video_read_properties(struct sh_video *sh_video);
-int video_read_frame(struct sh_video *sh_video, float *frame_time_ptr,
- unsigned char **start, int force_fps);
-
#endif /* MPLAYER_STHEADER_H */
diff --git a/demux/video.c b/demux/video.c
deleted file mode 100644
index 69749e03d1..0000000000
--- a/demux/video.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * video frame reading
- *
- * 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 "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <libavutil/mem.h>
-
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "parse_es.h"
-#include "mpeg_hdr.h"
-
-/* sub_cc (closed captions)*/
-//#include "sub/sub_cc.h"
-
-/* biCompression constant */
-#define BI_RGB 0L
-
-static mp_mpeg_header_t picture;
-
-static int telecine=0;
-static float telecine_cnt=-2.5;
-
-typedef enum {
- VIDEO_MPEG12,
- VIDEO_MPEG4,
- VIDEO_H264,
- VIDEO_VC1,
- VIDEO_OTHER
-} video_codec_t;
-
-static video_codec_t find_video_codec(sh_video_t *sh_video)
-{
- demux_stream_t *d_video=sh_video->ds;
- int fmt = d_video->demuxer->file_format;
-
- if(
- (fmt == DEMUXER_TYPE_MPEG_ES) ||
- (fmt == DEMUXER_TYPE_MPEG_GXF) ||
- (fmt == DEMUXER_TYPE_MPEG_PES) ||
- (
- (fmt == DEMUXER_TYPE_MPEG_PS || fmt == DEMUXER_TYPE_MPEG_TS) &&
- ((! sh_video->format) || (sh_video->format==0x10000001) || (sh_video->format==0x10000002))
- )
- )
- return VIDEO_MPEG12;
- else if((fmt == DEMUXER_TYPE_MPEG4_ES) ||
- ((fmt == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) ||
- ((fmt == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000004))
- )
- return VIDEO_MPEG4;
- else if((fmt == DEMUXER_TYPE_H264_ES) ||
- ((fmt == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) ||
- ((fmt == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005))
- )
- return VIDEO_H264;
- else if((fmt == DEMUXER_TYPE_MPEG_PS || fmt == DEMUXER_TYPE_MPEG_TS) &&
- (sh_video->format==mmioFOURCC('W', 'V', 'C', '1')))
- return VIDEO_VC1;
- else if (fmt == DEMUXER_TYPE_ASF && sh_video->bih && sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' '))
- return VIDEO_MPEG12;
- else
- return VIDEO_OTHER;
-}
-
-int video_read_properties(sh_video_t *sh_video){
-demux_stream_t *d_video=sh_video->ds;
-video_codec_t video_codec = find_video_codec(sh_video);
-// Determine image properties:
-switch(video_codec){
- case VIDEO_OTHER: {
- if((d_video->demuxer->file_format == DEMUXER_TYPE_ASF) || (d_video->demuxer->file_format == DEMUXER_TYPE_AVI)) {
- // display info:
- // in case no strf chunk has been seen in avi, we have no bitmap header
- if(!sh_video->bih) return 0;
- sh_video->format=sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- sh_video->disp_w=sh_video->bih->biWidth;
- sh_video->disp_h=abs(sh_video->bih->biHeight);
- }
- break;
- }
- case VIDEO_MPEG4: {
- int pos = 0, vop_cnt=0, units[3];
- videobuf_len=0; videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Start code... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i<=0x11F) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- if(!videobuffer) {
- videobuffer = av_malloc(VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Layer Start code... ");
- while(1){
- int i=sync_video_packet(d_video);
- mp_msg(MSGT_DECVIDEO,MSGL_V,"M4V: 0x%X\n",i);
- if(i>=0x120 && i<=0x12F) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Layer Header\n");
- return 0;
- }
- mp4_header_process_vol(&picture, &(videobuffer[pos]));
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK! FPS SEEMS TO BE %.3f\nSearching for Video Object Plane Start code... ", sh_video->fps);
- mp4_init:
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x1B6) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Plane Header\n");
- return 0;
- }
- mp4_header_process_vop(&picture, &(videobuffer[pos]));
- sh_video->disp_w = picture.display_picture_width;
- sh_video->disp_h = picture.display_picture_height;
- units[vop_cnt] = picture.timeinc_unit;
- vop_cnt++;
- //mp_msg(MSGT_DECVIDEO,MSGL_V, "TYPE: %d, unit: %d\n", picture.picture_type, picture.timeinc_unit);
- if(!picture.fps) {
- int i, mn, md, mx, diff;
- if(vop_cnt < 3)
- goto mp4_init;
-
- i=0;
- mn = mx = units[0];
- for(i=0; i<3; i++) {
- if(units[i] < mn)
- mn = units[i];
- if(units[i] > mx)
- mx = units[i];
- }
- md = mn;
- for(i=0; i<3; i++) {
- if((units[i] > mn) && (units[i] < mx))
- md = units[i];
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V, "MIN: %d, mid: %d, max: %d\n", mn, md, mx);
- if(mx - md > md - mn)
- diff = md - mn;
- else
- diff = mx - md;
- if(diff > 0){
- picture.fps = ((float)picture.timeinc_resolution) / diff;
- mp_msg(MSGT_DECVIDEO,MSGL_V, "FPS seems to be: %f, resolution: %d, delta_units: %d\n", picture.fps, picture.timeinc_resolution, diff);
- }
- }
- if(picture.fps) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %f\n", picture.fps);
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- sh_video->format=0x10000004;
- break;
- }
- case VIDEO_H264: {
- int pos = 0;
- videobuf_len=0; videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence parameter set... ");
- while(1){
- int i=sync_video_packet(d_video);
- if((i&~0x60) == 0x107 && i != 0x107) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- if(!videobuffer) {
- videobuffer = av_malloc(VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read sequence parameter set\n");
- return 0;
- }
- h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
- sh_video->disp_w=picture.display_picture_width;
- sh_video->disp_h=picture.display_picture_height;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for picture parameter set... ");
- while(1){
- int i=sync_video_packet(d_video);
- mp_msg(MSGT_DECVIDEO,MSGL_V,"H264: 0x%X\n",i);
- if((i&~0x60) == 0x108 && i != 0x108) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\nSearching for Slice... ");
- while(1){
- int i=sync_video_packet(d_video);
- if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- sh_video->format=0x10000005;
- if(picture.fps) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %f\n", picture.fps);
- }
- break;
- }
- case VIDEO_MPEG12: {
- if (d_video->demuxer->file_format == DEMUXER_TYPE_ASF) { // DVR-MS
- if(!sh_video->bih) return 0;
- sh_video->format=sh_video->bih->biCompression;
- }
-mpeg_header_parser:
- // Find sequence_header first:
- videobuf_len=0; videobuf_code_len=0;
- telecine=0; telecine_cnt=-2.5;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence header... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x1B3) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- if( mp_msg_test(MSGT_DECVIDEO,MSGL_V) ) mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: FATAL: EOF while searching for sequence header.\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- // ========= Read & process sequence header & extension ============
- if(!videobuffer) {
- videobuffer = av_malloc(VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
-
- if(!read_video_packet(d_video)){
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"FATAL: Cannot read sequence header.\n");
- return 0;
- }
- if(mp_header_process_sequence_header (&picture, &videobuffer[4])) {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: bad sequence header\n");
- goto mpeg_header_parser;
- }
- if(sync_video_packet(d_video)==0x1B5){ // next packet is seq. ext.
- int pos=videobuf_len;
- if(!read_video_packet(d_video)){
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"FATAL: Cannot read sequence header extension.\n");
- return 0;
- }
- if(mp_header_process_extension (&picture, &videobuffer[pos+4])) {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: bad sequence header extension\n");
- return 0;
- }
- }
-
- // display info:
- sh_video->format=picture.mpeg1?0x10000001:0x10000002; // mpeg video
- sh_video->fps=picture.fps * picture.frame_rate_extension_n / picture.frame_rate_extension_d;
- if(!sh_video->fps){
- sh_video->frametime=0;
- } else {
- sh_video->frametime=1.0/sh_video->fps;
- }
- sh_video->disp_w=picture.display_picture_width;
- sh_video->disp_h=picture.display_picture_height;
- // bitrate:
- if(picture.bitrate!=0x3FFFF) // unspecified/VBR ?
- sh_video->i_bps=picture.bitrate * 400 / 8;
- // info:
- mp_dbg(MSGT_DECVIDEO,MSGL_DBG2,"mpeg bitrate: %d (%X)\n",picture.bitrate,picture.bitrate);
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"VIDEO: %s %dx%d (aspect %d) %5.3f fps %5.1f kbps (%4.1f kbyte/s)\n",
- picture.mpeg1?"MPEG1":"MPEG2",
- sh_video->disp_w,sh_video->disp_h,
- picture.aspect_ratio_information,
- sh_video->fps,
- sh_video->i_bps * 8 / 1000.0,
- sh_video->i_bps / 1000.0 );
- break;
- }
- case VIDEO_VC1: {
- // Find sequence_header:
- videobuf_len=0;
- videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"Searching for VC1 sequence header... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x10F) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- if( mp_msg_test(MSGT_DECVIDEO,MSGL_V) ) mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- mp_msg(MSGT_DECVIDEO,MSGL_ERR, "Couldn't find VC-1 sequence header\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"found\n");
- if(!videobuffer) {
- videobuffer = av_malloc(VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR, "Couldn't read VC-1 sequence header!\n");
- return 0;
- }
-
- while(1) {
- int i=sync_video_packet(d_video);
- if(i==0x10E) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Couldn't find VC-1 entry point sync-code:(\n");
- return 0;
- }
- }
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Couldn't read VC-1 entry point sync-code:(\n");
- return 0;
- }
-
- if(mp_vc1_decode_sequence_header(&picture, &videobuffer[4], videobuf_len-4)) {
- sh_video->bih = calloc(1, sizeof(*sh_video->bih) + videobuf_len);
- if(sh_video->bih == NULL) {
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Couldn't alloc %zu bytes for VC-1 extradata!\n", sizeof(*sh_video->bih) + videobuf_len);
- return 0;
- }
- sh_video->bih->biSize= sizeof(*sh_video->bih) + videobuf_len;
- memcpy(sh_video->bih + 1, videobuffer, videobuf_len);
- sh_video->bih->biCompression = sh_video->format;
- sh_video->bih->biWidth = sh_video->disp_w = picture.display_picture_width;
- sh_video->bih->biHeight = sh_video->disp_h = picture.display_picture_height;
- if(picture.fps > 0) {
- sh_video->frametime=1.0/picture.fps;
- sh_video->fps = picture.fps;
- }
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"VIDEO: VC-1 %dx%d, %5.3f fps, header len: %d\n",
- sh_video->disp_w, sh_video->disp_h, sh_video->fps, videobuf_len);
- }
- break;
- }
-} // switch(file_format)
-if (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS ||
- d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS)
- mp_set_video_codec_from_tag(sh_video);
-return 1;
-}
-
-static void process_userdata(const unsigned char* buf,int len){
- int i;
- /* if the user data starts with "CC", assume it is a CC info packet */
- if(len>2 && buf[0]=='C' && buf[1]=='C'){
-// mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"video.c: process_userdata() detected Closed Captions!\n");
- //subcc_process_data(buf+2,len-2);
- }
- if(verbose<2) return;
- fprintf(stderr, "user_data: len=%3d %02X %02X %02X %02X '",
- len, buf[0], buf[1], buf[2], buf[3]);
- for(i=0;i<len;i++)
-// if(buf[i]>=32 && buf[i]<127) fputc(buf[i], stderr);
- if(buf[i]&0x60) fputc(buf[i]&0x7F, stderr);
- fprintf(stderr, "'\n");
-}
-
-int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char** start,int force_fps){
- demux_stream_t *d_video=sh_video->ds;
- demuxer_t *demuxer=d_video->demuxer;
- float frame_time=1;
- float pts1=d_video->pts;
- float pts=0;
- float fps;
- int picture_coding_type=0;
- int in_size=0;
- video_codec_t video_codec = find_video_codec(sh_video);
-
- *start=NULL;
-
- if(video_codec == VIDEO_MPEG12){
- int in_frame=0;
- //float newfps;
- //videobuf_len=0;
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- //void* buffer=&videobuffer[videobuf_len+4];
- int start=videobuf_len+4;
- if(in_frame){
- if(i<0x101 || i>=0x1B0){ // not slice code -> end of frame
- if(!i) return -1; // EOF
- break;
- }
- } else {
- if(i==0x100){
- pts=d_video->pts;
- d_video->pts=0;
- }
- if(i>=0x101 && i<0x1B0) in_frame=1; // picture startcode
- else if(!i) return -1; // EOF
- }
- if(!read_video_packet(d_video)) return -1; // EOF
- // process headers:
- switch(i){
- case 0x1B3: mp_header_process_sequence_header (&picture, &videobuffer[start]);break;
- case 0x1B5: mp_header_process_extension (&picture, &videobuffer[start]);break;
- case 0x1B2: process_userdata (&videobuffer[start], videobuf_len-start);break;
- case 0x100: picture_coding_type=(videobuffer[start+1] >> 3) & 7;break;
- }
- }
- fps = picture.fps * picture.frame_rate_extension_n / picture.frame_rate_extension_d;
-
- *start=videobuffer; in_size=videobuf_len;
-
- // get mpeg fps:
- if(sh_video->fps!=fps) if(!force_fps && !telecine){
- mp_msg(MSGT_CPLAYER,MSGL_WARN,"Warning! FPS changed %5.3f -> %5.3f (%f) [%d] \n",sh_video->fps,fps,sh_video->fps-fps,picture.frame_rate_code);
- sh_video->fps=fps;
- sh_video->frametime=1.0/fps;
- }
-
- // fix mpeg2 frametime:
- frame_time=(picture.display_time)*0.01f;
- picture.display_time=100;
- videobuf_len=0;
-
- telecine_cnt*=0.9; // drift out error
- telecine_cnt+=frame_time-5.0/4.0;
- mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"\r telecine = %3.1f %5.3f \n",frame_time,telecine_cnt);
-
- if(telecine){
- frame_time=1;
- if(telecine_cnt<-1.5 || telecine_cnt>1.5){
- mp_tmsg(MSGT_DECVIDEO,MSGL_INFO,"\ndemux_mpg: 30000/1001fps NTSC content detected, switching framerate.\n");
- telecine=0;
- }
- } else
- if(telecine_cnt>-0.5 && telecine_cnt<0.5 && !force_fps){
- sh_video->fps=sh_video->fps*4/5;
- sh_video->frametime=sh_video->frametime*5/4;
- mp_tmsg(MSGT_DECVIDEO,MSGL_INFO,"\ndemux_mpg: 24000/1001fps progressive NTSC content detected, switching framerate.\n");
- telecine=1;
- }
- } else if(video_codec == VIDEO_MPEG4){
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if(i==0x1B6) break;
- }
- *start=videobuffer; in_size=videobuf_len;
- videobuf_len=0;
- } else if(video_codec == VIDEO_H264){
- int in_picture = 0;
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- int pos = videobuf_len+4;
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if((i&~0x60) == 0x107 && i != 0x107) {
- h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
- if(picture.fps > 0) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- }
- i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- }
-
- // here starts the access unit end detection code
- // see the mail on MPlayer-dev-eng for details:
- // Date: Sat, 17 Sep 2005 11:24:06 +0200
- // Subject: Re: [MPlayer-dev-eng] [RFC] h264 ES parser problems
- // Message-ID: <20050917092406.GA7699@rz.uni-karlsruhe.de>
- if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105)
- // found VCL NAL with slice header i.e. start of current primary coded
- // picture, so start scanning for the end now
- in_picture = 1;
- if (in_picture) {
- i = sync_video_packet(d_video) & ~0x60; // code of next packet
- if(i == 0x106 || i == 0x109) break; // SEI or access unit delim.
- if(i == 0x101 || i == 0x102 || i == 0x105) {
- // assuming arbitrary slice ordering is not allowed, the
- // first_mb_in_slice (golomb encoded) value should be 0 then
- // for the first VCL NAL in a picture
- if (demux_peekc(d_video) & 0x80)
- break;
- }
- }
- }
- *start=videobuffer; in_size=videobuf_len;
- videobuf_len=0;
- } else if(video_codec == VIDEO_VC1) {
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE) {
- int i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if(i==0x10D) break;
- }
- *start=videobuffer;
- in_size=videobuf_len;
- videobuf_len=0;
- } else {
- // frame-based file formats: (AVI,ASF,MOV)
- in_size=ds_get_packet(d_video,start);
- if(in_size<0) return -1; // EOF
- }
-
-
-//------------------------ frame decoded. --------------------
-
- frame_time*=sh_video->frametime;
-
- // override frame_time for variable/unknown FPS formats:
- if(!force_fps) switch(demuxer->file_format){
- case DEMUXER_TYPE_GIF:
- case DEMUXER_TYPE_MATROSKA:
- case DEMUXER_TYPE_MNG:
- if(d_video->pts>0 && pts1>0 && d_video->pts>pts1)
- frame_time=d_video->pts-pts1;
- break;
- case DEMUXER_TYPE_TV:
- case DEMUXER_TYPE_ASF: {
- double next_pts = ds_get_next_pts(d_video);
- double d= (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts-pts1;
- if(d>=0){
- if(d>0){
- if((int)sh_video->fps==1000)
- mp_msg(MSGT_CPLAYER,MSGL_V,"\navg. framerate: %d fps \n",(int)(1.0f/d));
- sh_video->frametime=d; // 1ms
- sh_video->fps=1.0f/d;
- }
- frame_time = d;
- } else {
- mp_msg(MSGT_CPLAYER,MSGL_WARN,"\nInvalid frame duration value (%5.3f/%5.3f => %5.3f). Defaulting to %5.3f sec.\n",d_video->pts,next_pts,d,frame_time);
- // frame_time = 1/25.0;
- }
- }
- break;
- case DEMUXER_TYPE_LAVF:
- if((int)sh_video->fps==1000 || (int)sh_video->fps<=1){
- double next_pts = ds_get_next_pts(d_video);
- double d= (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts-pts1;
- if(d>=0){
- frame_time = d;
- }
- }
- break;
- }
-
- if(video_codec == VIDEO_MPEG12){
- sh_video->pts+=frame_time;
- if(picture_coding_type==1)
- d_video->keyframe = true;
- if(picture_coding_type<=2 && sh_video->i_pts){
- sh_video->pts=sh_video->i_pts;
- sh_video->i_pts=pts;
- } else {
- if(pts){
- if(picture_coding_type<=2) sh_video->i_pts=pts;
- else sh_video->pts=pts;
- }
- }
- } else
- sh_video->pts=d_video->pts;
-
- if(frame_time_ptr) *frame_time_ptr=frame_time;
- return in_size;
-}
diff --git a/stream/dvbin.h b/stream/dvbin.h
index 8f7ff28d40..ccaf0db66c 100644
--- a/stream/dvbin.h
+++ b/stream/dvbin.h
@@ -76,6 +76,7 @@ typedef struct {
} dvb_config_t;
typedef struct {
+ int fd;
int card;
int fe_fd;
int sec_fd;
diff --git a/stream/stream.c b/stream/stream.c
index 92d2f84f41..523fcc2e8e 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -118,10 +118,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;
@@ -146,12 +144,11 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
}
s = new_stream(0);
s->opts = options;
- s->url = strdup(filename);
+ s->url = talloc_strdup(s, 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);
return NULL;
}
@@ -159,8 +156,6 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
if (!s->read_chunk)
s->read_chunk = 4 * (s->sector_size ? s->sector_size : STREAM_BUFFER_SIZE);
- if (s->type <= -2)
- mp_msg(MSGT_OPEN, MSGL_WARN, "Warning streams need a type !!!!\n");
if (!s->seek)
s->flags &= ~MP_STREAM_SEEK;
if (s->seek && !(s->flags & MP_STREAM_SEEK))
@@ -170,10 +165,7 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
s->uncached_type = s->type;
- mp_msg(MSGT_OPEN, MSGL_V, "STREAM: [%s] %s\n", sinfo->name, filename);
- mp_msg(MSGT_OPEN, MSGL_V, "STREAM: Description: %s\n", sinfo->info);
- mp_msg(MSGT_OPEN, MSGL_V, "STREAM: Author: %s\n", sinfo->author);
- mp_msg(MSGT_OPEN, MSGL_V, "STREAM: Comment: %s\n", sinfo->comment);
+ mp_msg(MSGT_OPEN, MSGL_V, "[stream] [%s] %s\n", sinfo->name, filename);
if (s->mime_type)
mp_msg(MSGT_OPEN, MSGL_V, "Mime-type: '%s'\n", s->mime_type);
@@ -183,21 +175,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) {
@@ -212,22 +197,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;
@@ -241,15 +214,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)
@@ -322,13 +294,7 @@ static int stream_read_unbuffered(stream_t *s, void *buf, int len)
int orig_len = len;
s->buf_pos = s->buf_len = 0;
// we will retry even if we already reached EOF previously.
- if (s->fill_buffer) {
- len = s->fill_buffer(s, buf, len);
- } else if (s->fd >= 0) {
- len = read(s->fd, buf, len);
- } else {
- len = 0;
- }
+ len = s->fill_buffer ? s->fill_buffer(s, buf, len) : -1;
if (len < 0)
len = 0;
if (len == 0) {
@@ -597,24 +563,19 @@ static stream_t *new_stream(size_t min_size)
min_size = FFMAX(min_size, TOTAL_BUFFER_SIZE);
stream_t *s = talloc_size(NULL, sizeof(stream_t) + min_size);
memset(s, 0, sizeof(stream_t));
-
- s->fd = -2;
- s->type = -2;
return s;
}
void free_stream(stream_t *s)
{
+ if (!s)
+ return;
+
stream_set_capture_file(s, NULL);
if (s->close)
s->close(s);
- if (s->fd > 0) {
- close(s->fd);
- }
- free(s->url);
- if (s->uncached_stream)
- free_stream(s->uncached_stream);
+ free_stream(s->uncached_stream);
talloc_free(s);
}
@@ -637,7 +598,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;
@@ -678,16 +639,15 @@ static int stream_enable_cache(stream_t **stream, int64_t size, int64_t min,
orig->buf_len = orig->buf_pos = 0;
stream_t *cache = new_stream(0);
- cache->type = STREAMTYPE_CACHE;
cache->uncached_type = orig->type;
cache->uncached_stream = orig;
cache->flags |= MP_STREAM_SEEK;
cache->mode = STREAM_READ;
cache->read_chunk = 4 * STREAM_BUFFER_SIZE;
- cache->url = strdup(orig->url);
+ cache->url = talloc_strdup(cache, orig->url);
cache->mime_type = talloc_strdup(cache, orig->mime_type);
- cache->lavf_type = orig->lavf_type;
+ cache->lavf_type = talloc_strdup(cache, orig->lavf_type);
cache->opts = orig->opts;
cache->start_pos = orig->start_pos;
cache->end_pos = orig->end_pos;
diff --git a/stream/stream.h b/stream/stream.h
index f1033ed38f..a0cd3d58fc 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -34,25 +34,17 @@
#define O_BINARY 0
#endif
-#define STREAMTYPE_DUMMY -1 // for placeholders, when the actual reading is handled in the demuxer
-#define STREAMTYPE_FILE 0 // read from seekable file
-#define STREAMTYPE_VCD 1 // raw mode-2 CDROM reading, 2324 bytes/sector
-#define STREAMTYPE_DVD 3 // libdvdread
-#define STREAMTYPE_MEMORY 4
-#define STREAMTYPE_PLAYLIST 6 // FIXME!!! same as STREAMTYPE_FILE now
-#define STREAMTYPE_CDDA 10 // raw audio CD reader
-#define STREAMTYPE_SMB 11 // smb:// url, using libsmbclient (samba)
-#define STREAMTYPE_VCDBINCUE 12 // vcd directly from bin/cue files
-#define STREAMTYPE_DVB 13
-#define STREAMTYPE_VSTREAM 14
-#define STREAMTYPE_SDP 15
-#define STREAMTYPE_PVR 16
-#define STREAMTYPE_TV 17
-#define STREAMTYPE_MF 18
-#define STREAMTYPE_RADIO 19
-#define STREAMTYPE_BLURAY 20
-#define STREAMTYPE_AVDEVICE 21
-#define STREAMTYPE_CACHE 22
+enum streamtype {
+ STREAMTYPE_GENERIC = 0,
+ STREAMTYPE_FILE,
+ STREAMTYPE_RADIO,
+ STREAMTYPE_DVB,
+ STREAMTYPE_DVD,
+ STREAMTYPE_PVR,
+ STREAMTYPE_TV,
+ STREAMTYPE_MF,
+ STREAMTYPE_AVDEVICE,
+};
#define STREAM_BUFFER_SIZE 2048
#define STREAM_MAX_SECTOR_SIZE (8 * 1024)
@@ -70,7 +62,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
@@ -116,12 +107,9 @@ struct stream_dvd_info_req {
struct stream;
typedef struct stream_info_st {
- const char *info;
const char *name;
- 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
@@ -143,9 +131,8 @@ typedef struct stream {
// Close
void (*close)(struct stream *s);
- int fd; // file descriptor, see man open(2)
- int type; // see STREAMTYPE_*
- int uncached_type; // like (uncached_stream ? uncached_stream->type : type)
+ enum streamtype type; // see STREAMTYPE_*
+ enum streamtype uncached_type; // if stream is cache, type of wrapped str.
int flags; // MP_STREAM_SEEK_* or'ed flags
int sector_size; // sector size (seek will be aligned on this size if non 0)
int read_chunk; // maximum amount of data to read at once to limit latency
@@ -157,6 +144,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;
@@ -190,14 +178,6 @@ inline static int stream_read_char(stream_t *s)
(stream_fill_buffer(s) ? s->buffer[s->buf_pos++] : -256);
}
-inline static unsigned int stream_read_word(stream_t *s)
-{
- int x, y;
- x = stream_read_char(s);
- y = stream_read_char(s);
- return (x << 8) | y;
-}
-
inline static unsigned int stream_read_dword(stream_t *s)
{
unsigned int y;
@@ -208,26 +188,6 @@ inline static unsigned int stream_read_dword(stream_t *s)
return y;
}
-#define stream_read_fourcc stream_read_dword_le
-
-inline static unsigned int stream_read_word_le(stream_t *s)
-{
- int x, y;
- x = stream_read_char(s);
- y = stream_read_char(s);
- return (y << 8) | x;
-}
-
-inline static uint32_t stream_read_dword_le(stream_t *s)
-{
- unsigned int y;
- y = stream_read_char(s);
- y |= stream_read_char(s) << 8;
- y |= stream_read_char(s) << 16;
- y |= stream_read_char(s) << 24;
- return y;
-}
-
inline static uint64_t stream_read_qword(stream_t *s)
{
uint64_t y;
@@ -242,14 +202,6 @@ inline static uint64_t stream_read_qword(stream_t *s)
return y;
}
-inline static uint64_t stream_read_qword_le(stream_t *s)
-{
- uint64_t y;
- y = stream_read_dword_le(s);
- y |= (uint64_t)stream_read_dword_le(s) << 32;
- return y;
-}
-
unsigned char *stream_read_line(stream_t *s, unsigned char *mem, int max,
int utf16);
@@ -276,8 +228,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..5d94b35d70 100644
--- a/stream/stream_avdevice.c
+++ b/stream/stream_avdevice.c
@@ -19,31 +19,26 @@
#include "config.h"
#include "stream.h"
-#include "demux/demux.h"
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;
}
const stream_info_t stream_info_avdevice = {
- .info = "FFmpeg libavdevice",
.name = "avdevice",
- .author = "",
- .comment =
- "Force a libavformat/libavdevice demuxer with avdevice://demuxer:args",
.open = open_f,
.protocols = { "avdevice", "av", NULL },
};
diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c
index 64d1856873..30145203df 100644
--- a/stream/stream_bluray.c
+++ b/stream/stream_bluray.c
@@ -29,18 +29,19 @@
*
*/
-#include <libbluray/bluray.h>
#include <string.h>
#include <assert.h>
+#include <libbluray/bluray.h>
+#include <libavutil/common.h>
+
#include "config.h"
-#include "libavutil/common.h"
-#include "demux/demux.h"
#include "talloc.h"
#include "core/mp_msg.h"
#include "core/m_struct.h"
#include "core/m_option.h"
#include "stream.h"
+#include "demux/stheader.h"
#define BLURAY_SECTOR_SIZE 6144
@@ -291,8 +292,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;
@@ -409,7 +409,6 @@ err_no_info:
s->sector_size = BLURAY_SECTOR_SIZE;
s->flags = MP_STREAM_SEEK;
s->priv = b;
- s->type = STREAMTYPE_BLURAY;
s->url = strdup("br://");
mp_tmsg(MSGT_OPEN, MSGL_V, "Blu-ray successfully opened.\n");
@@ -418,10 +417,7 @@ err_no_info:
}
const stream_info_t stream_info_bluray = {
- "Blu-ray Disc",
"bd",
- "Benjamin Zores",
- "Play Blu-ray discs through external libbluray",
bluray_stream_open,
{ "bd", "br", "bluray", NULL },
&bluray_stream_opts,
diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c
index 4e45e51a07..670f47e156 100644
--- a/stream/stream_cdda.c
+++ b/stream/stream_cdda.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original author: Albeu
+ *
* 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
@@ -44,7 +46,6 @@
#include "core/m_struct.h"
#include "libavutil/common.h"
#include "compat/mpbswap.h"
-#include "demux/demux.h"
#include "cdd.h"
@@ -333,7 +334,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;
@@ -471,7 +472,6 @@ static int open_cdda(stream_t *st, int m, void *opts, int *file_format)
st->priv = priv;
st->start_pos = priv->start_sector * CDIO_CD_FRAMESIZE_RAW;
st->end_pos = (priv->end_sector + 1) * CDIO_CD_FRAMESIZE_RAW;
- st->type = STREAMTYPE_CDDA;
st->sector_size = CDIO_CD_FRAMESIZE_RAW;
st->fill_buffer = fill_buffer;
@@ -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);
@@ -489,10 +489,7 @@ static int open_cdda(stream_t *st, int m, void *opts, int *file_format)
}
const stream_info_t stream_info_cdda = {
- "CDDA",
"cdda",
- "Albeu",
- "",
open_cdda,
{"cdda", NULL },
&stream_opts,
diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c
index 40c27f9aac..53761e8f60 100644
--- a/stream/stream_dvb.c
+++ b/stream/stream_dvb.c
@@ -3,6 +3,8 @@
dvbstream
(C) Dave Chapman <dave@dchapman.com> 2001, 2002.
+Original authors: Nico, probably Arpi
+
The latest version can be found at http://www.linuxstb.org/dvbstream
Modified for use with MPlayer, for details see the changelog at
@@ -40,7 +42,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <errno.h>
#include "stream.h"
-#include "demux/demux.h"
#include "core/m_option.h"
#include "core/m_struct.h"
#include "core/path.h"
@@ -444,7 +445,7 @@ static int dvb_streaming_read(stream_t *stream, char *buffer, int size)
tries = priv->retry + 1;
- fd = stream->fd;
+ fd = priv->fd;
while(pos < size)
{
pfds[0].fd = fd;
@@ -536,7 +537,7 @@ int dvb_set_channel(stream_t *stream, int card, int n)
priv->list = new_list;
priv->retry = 5;
new_list->current = n;
- stream->fd = priv->dvr_fd;
+ priv->fd = priv->dvr_fd;
mp_msg(MSGT_DEMUX, MSGL_V, "DVB_SET_CHANNEL: new channel name=%s, card: %d, channel %d\n", channel->name, card, n);
stream->buf_pos = stream->buf_len = 0;
@@ -659,7 +660,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 +740,8 @@ 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_MPEG_TS;
+ stream->demuxer = "lavf";
+ stream->lavf_type = "mpegts";
return STREAM_OK;
}
@@ -855,10 +857,7 @@ dvb_config_t *dvb_get_config(void)
const stream_info_t stream_info_dvb = {
- "Dvb Input",
"dvbin",
- "Nico",
- "based on the code from ??? (probably Arpi)",
dvb_open,
{ "dvb", NULL },
&stream_opts,
diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c
index bf9cb9d4c7..565054d81b 100644
--- a/stream/stream_dvd.c
+++ b/stream/stream_dvd.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original author: Benjamin Zores
+ *
* 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
@@ -745,7 +747,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 +1062,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,14 +1088,11 @@ 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 = {
- "DVD stream",
- "null",
- "",
- "",
+ "dvd",
open_s,
{ "dvd", NULL },
&stream_opts,
@@ -1100,10 +1100,7 @@ const stream_info_t stream_info_dvd = {
};
const stream_info_t stream_info_ifo = {
- "DVD IFO input",
"ifo",
- "Benjamin Zores",
- "Mostly used to play DVDs on disk through OSD Menu",
ifo_stream_open,
{ "file", "", NULL },
NULL,
diff --git a/stream/stream_file.c b/stream/stream_file.c
index 924eb31dad..b9e4f2f2e1 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original authors: Albeu, probably Arpi
+ *
* 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
@@ -32,6 +34,11 @@
#include "core/m_option.h"
#include "core/m_struct.h"
+struct priv {
+ int fd;
+ bool close;
+};
+
static struct stream_priv_s {
char* filename;
char *filename2;
@@ -54,15 +61,17 @@ static const struct m_struct_st stream_opts = {
};
static int fill_buffer(stream_t *s, char* buffer, int max_len){
- int r = read(s->fd,buffer,max_len);
+ struct priv *p = s->priv;
+ int r = read(p->fd,buffer,max_len);
return (r <= 0) ? -1 : r;
}
static int write_buffer(stream_t *s, char* buffer, int len) {
+ struct priv *p = s->priv;
int r;
int wr = 0;
while (wr < len) {
- r = write(s->fd,buffer,len);
+ r = write(p->fd,buffer,len);
if (r <= 0)
return -1;
wr += r;
@@ -72,8 +81,9 @@ static int write_buffer(stream_t *s, char* buffer, int len) {
}
static int seek(stream_t *s,int64_t newpos) {
+ struct priv *p = s->priv;
s->pos = newpos;
- if(lseek(s->fd,s->pos,SEEK_SET)<0) {
+ if(lseek(p->fd,s->pos,SEEK_SET)<0) {
return 0;
}
return 1;
@@ -95,12 +105,13 @@ static int seek_forward(stream_t *s,int64_t newpos) {
}
static int control(stream_t *s, int cmd, void *arg) {
+ struct priv *p = s->priv;
switch(cmd) {
case STREAM_CTRL_GET_SIZE: {
off_t size;
- size = lseek(s->fd, 0, SEEK_END);
- lseek(s->fd, s->pos, SEEK_SET);
+ size = lseek(p->fd, 0, SEEK_END);
+ lseek(p->fd, s->pos, SEEK_SET);
if(size != (off_t)-1) {
*(uint64_t*)arg = size;
return 1;
@@ -110,12 +121,23 @@ 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 void s_close(stream_t *s)
+{
+ struct priv *p = s->priv;
+ if (p->close && p->fd >= 0)
+ close(p->fd);
+}
+
+static int open_f(stream_t *stream,int mode, void* opts)
+{
int f;
mode_t m = 0;
int64_t len;
unsigned char *filename;
struct stream_priv_s* p = (struct stream_priv_s*)opts;
+ struct priv *priv = talloc_ptrtype(stream, priv);
+ *priv = (struct priv) { .fd = -1 };
+ stream->priv = priv;
if(mode == STREAM_READ)
m = O_RDONLY;
@@ -162,6 +184,8 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
setmode(fileno(stdout),O_BINARY);
#endif
}
+ priv->fd = f;
+ priv->close = false;
} else {
mode_t openmode = S_IRUSR|S_IWUSR;
#ifndef __MINGW32__
@@ -183,6 +207,8 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
return STREAM_ERROR;
}
#endif
+ priv->fd = f;
+ priv->close = true;
}
len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET);
@@ -202,21 +228,18 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %"PRId64" bytes\n", (int64_t)len);
- stream->fd = f;
stream->fill_buffer = fill_buffer;
stream->write_buffer = write_buffer;
stream->control = control;
stream->read_chunk = 64*1024;
+ stream->close = s_close;
m_struct_free(&stream_opts,opts);
return STREAM_OK;
}
const stream_info_t stream_info_file = {
- "File",
"file",
- "Albeu",
- "based on the code from ??? (probably Arpi)",
open_f,
{ "file", "", NULL },
&stream_opts,
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c
index 48d5e9d173..82241e83f3 100644
--- a/stream/stream_lavf.c
+++ b/stream/stream_lavf.c
@@ -26,14 +26,13 @@
#include "stream.h"
#include "core/m_option.h"
#include "core/m_struct.h"
-#include "demux/demux.h"
#include "cookies.h"
#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 +114,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 +131,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 +162,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,14 +215,13 @@ 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;
int64_t size = avio_size(avio);
if (size >= 0)
stream->end_pos = size;
- stream->type = STREAMTYPE_FILE;
stream->seek = seek;
if (!avio->seekable)
stream->seek = NULL;
@@ -307,10 +305,7 @@ done:
}
const stream_info_t stream_info_ffmpeg = {
- "FFmpeg",
"ffmpeg",
- "",
- "",
open_f,
{ "lavf", "ffmpeg", "rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh",
"mmshttp", "udp", "ftp", "rtp", "httpproxy", NULL },
diff --git a/stream/stream_memory.c b/stream/stream_memory.c
index 0994e0816f..79bfea459d 100644
--- a/stream/stream_memory.c
+++ b/stream/stream_memory.c
@@ -54,10 +54,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)
{
- stream->type = STREAMTYPE_MEMORY;
-
stream->fill_buffer = fill_buffer;
stream->seek = seek;
stream->control = control;
@@ -75,10 +73,7 @@ static int open_f(stream_t *stream, int mode, void* opts, int* file_format)
}
const stream_info_t stream_info_memory = {
- "Memory",
"memory",
- "",
- "",
open_f,
{ "memory", NULL },
};
diff --git a/stream/stream_mf.c b/stream/stream_mf.c
index 9b8b47188a..9f87dad6b1 100644
--- a/stream/stream_mf.c
+++ b/stream/stream_mf.c
@@ -2,6 +2,7 @@
* stream layer for multiple files input, based on previous work from Albeu
*
* Copyright (C) 2006 Benjamin Zores
+ * Original author: Albeu
*
* This file is part of MPlayer.
*
@@ -26,22 +27,18 @@
#include <string.h>
#include "stream.h"
-#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 = "mf";
return STREAM_OK;
}
const stream_info_t stream_info_mf = {
- "Multiple files input",
"mf",
- "Benjamin Zores, Albeu",
- "",
mf_stream_open,
{ "mf", NULL },
NULL,
diff --git a/stream/stream_null.c b/stream/stream_null.c
index 5465702be8..8bae12ff9d 100644
--- a/stream/stream_null.c
+++ b/stream/stream_null.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original author: Albeu
+ *
* 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
@@ -23,18 +25,14 @@
#include "stream.h"
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
- stream->type = STREAMTYPE_DUMMY;
-
+static int open_s(stream_t *stream,int mode, void* opts)
+{
return 1;
}
const stream_info_t stream_info_null = {
- "Null stream",
"null",
- "Albeu",
- "",
open_s,
{ "null", NULL },
NULL,
diff --git a/stream/stream_pvr.c b/stream/stream_pvr.c
index aeea46cf62..6038ee9221 100644
--- a/stream/stream_pvr.c
+++ b/stream/stream_pvr.c
@@ -40,14 +40,15 @@
#include <linux/types.h>
#include <linux/videodev2.h>
+#include <libavutil/common.h>
+#include <libavutil/avstring.h>
+
#include "core/mp_msg.h"
#include "stream.h"
#include "pvr.h"
#include "frequencies.h"
-#include "libavutil/common.h"
-#include "libavutil/avstring.h"
#define PVR_DEFAULT_DEVICE "/dev/video0"
#define PVR_MAX_CONTROLS 10
@@ -1555,7 +1556,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;
@@ -1756,10 +1757,7 @@ pvr_force_freq_step (stream_t *stream, int step)
}
const stream_info_t stream_info_pvr = {
- "V4L2 MPEG Input (a.k.a PVR)",
"pvr",
- "Benjamin Zores",
- "",
pvr_stream_open,
{ "pvr", NULL },
NULL,
diff --git a/stream/stream_radio.c b/stream/stream_radio.c
index fae9be43d1..dd173175f0 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;
@@ -967,10 +968,7 @@ static void close_s(struct stream *stream){
}
const stream_info_t stream_info_radio = {
- "Radio stream",
- "Radio",
- "Vladimir Voroshilov",
- "In development",
+ "radio",
open_s,
{ "radio", NULL },
&stream_opts,
diff --git a/stream/stream_smb.c b/stream/stream_smb.c
index 33b13f7a11..91c5c615d7 100644
--- a/stream/stream_smb.c
+++ b/stream/stream_smb.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original author: M. Tourne
+ *
* 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
@@ -26,6 +28,10 @@
#include "core/m_option.h"
#include "core/m_struct.h"
+struct priv {
+ int fd;
+};
+
static struct stream_priv_s {
} stream_priv_dflts = {
};
@@ -72,10 +78,11 @@ static void smb_auth_fn(const char *server, const char *share,
}
static int control(stream_t *s, int cmd, void *arg) {
+ struct priv *p = s->priv;
switch(cmd) {
case STREAM_CTRL_GET_SIZE: {
- off_t size = smbc_lseek(s->fd,0,SEEK_END);
- smbc_lseek(s->fd,s->pos,SEEK_SET);
+ off_t size = smbc_lseek(p->fd,0,SEEK_END);
+ smbc_lseek(p->fd,s->pos,SEEK_SET);
if(size != (off_t)-1) {
*(uint64_t *)arg = size;
return 1;
@@ -86,23 +93,26 @@ static int control(stream_t *s, int cmd, void *arg) {
}
static int seek(stream_t *s,int64_t newpos) {
+ struct priv *p = s->priv;
s->pos = newpos;
- if(smbc_lseek(s->fd,s->pos,SEEK_SET)<0) {
+ if(smbc_lseek(p->fd,s->pos,SEEK_SET)<0) {
return 0;
}
return 1;
}
static int fill_buffer(stream_t *s, char* buffer, int max_len){
- int r = smbc_read(s->fd,buffer,max_len);
+ struct priv *p = s->priv;
+ int r = smbc_read(p->fd,buffer,max_len);
return (r <= 0) ? -1 : r;
}
static int write_buffer(stream_t *s, char* buffer, int len) {
+ struct priv *p = s->priv;
int r;
int wr = 0;
while (wr < len) {
- r = smbc_write(s->fd,buffer,len);
+ r = smbc_write(p->fd,buffer,len);
if (r <= 0)
return -1;
wr += r;
@@ -112,15 +122,20 @@ static int write_buffer(stream_t *s, char* buffer, int len) {
}
static void close_f(stream_t *s){
- smbc_close(s->fd);
+ struct priv *p = s->priv;
+ smbc_close(p->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;
int fd, err;
+ struct priv *priv = talloc_zero(stream, struct priv);
+ stream->priv = priv;
+
filename = stream->url;
if(mode == STREAM_READ)
@@ -164,8 +179,7 @@ static int open_f (stream_t *stream, int mode, void *opts, int* file_format) {
stream->seek = seek;
if(mode == STREAM_READ) stream->end_pos = len;
}
- stream->type = STREAMTYPE_SMB;
- stream->fd = fd;
+ priv->fd = fd;
stream->fill_buffer = fill_buffer;
stream->write_buffer = write_buffer;
stream->close = close_f;
@@ -176,10 +190,7 @@ static int open_f (stream_t *stream, int mode, void *opts, int* file_format) {
}
const stream_info_t stream_info_smb = {
- "Server Message Block",
"smb",
- "M. Tourne",
- "based on the code from 'a bulgarian' (one says)",
open_f,
{"smb", NULL},
&stream_opts,
diff --git a/stream/stream_tv.c b/stream/stream_tv.c
index 595657dc43..d9a4636b00 100644
--- a/stream/stream_tv.c
+++ b/stream/stream_tv.c
@@ -2,6 +2,7 @@
* stream layer for TV Input, based on previous work from Albeu
*
* Copyright (C) 2006 Benjamin Zores
+ * Original author: Albeu
*
* This file is part of MPlayer.
*
@@ -26,7 +27,6 @@
#include <string.h>
#include "stream.h"
-#include "demux/demux.h"
#include "core/m_option.h"
#include "core/m_struct.h"
#include "tv.h"
@@ -97,22 +97,19 @@ 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;
}
const stream_info_t stream_info_tv = {
- "TV Input",
"tv",
- "Benjamin Zores, Albeu",
- "",
tv_stream_open,
{ "tv", NULL },
&stream_opts,
diff --git a/stream/stream_vcd.c b/stream/stream_vcd.c
index 422dea02cd..0fd2998c58 100644
--- a/stream/stream_vcd.c
+++ b/stream/stream_vcd.c
@@ -1,6 +1,8 @@
/*
* This file is part of MPlayer.
*
+ * Original author: Albeu
+ *
* 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
@@ -51,8 +53,6 @@
#include "vcd_read.h"
#endif
-#include "demux/demux.h"
-
extern char *cdrom_device;
static struct stream_priv_s {
@@ -94,46 +94,14 @@ static int seek(stream_t *s,int64_t newpos) {
return 1;
}
-static int control(stream_t *stream, int cmd, void *arg) {
- struct stream_priv_s *p = stream->priv;
- switch(cmd) {
- case STREAM_CTRL_GET_NUM_TITLES:
- case STREAM_CTRL_GET_NUM_CHAPTERS:
- {
- mp_vcd_priv_t *vcd = vcd_read_toc(stream->fd);
- if (!vcd)
- break;
- *(unsigned int *)arg = vcd_end_track(vcd);
- return STREAM_OK;
- }
- case STREAM_CTRL_SEEK_TO_CHAPTER:
- {
- int r;
- unsigned int track = *(unsigned int *)arg + 1;
- mp_vcd_priv_t *vcd = vcd_read_toc(stream->fd);
- if (!vcd)
- break;
- r = vcd_seek_to_track(vcd, track);
- if (r >= 0) {
- p->track = track;
- return STREAM_OK;
- }
- break;
- }
- case STREAM_CTRL_GET_CURRENT_CHAPTER:
- {
- *(unsigned int *)arg = p->track - 1;
- return STREAM_OK;
- }
- }
- return STREAM_UNSUPPORTED;
-}
-
static void close_s(stream_t *stream) {
- free(stream->priv);
+ mp_vcd_priv_t *p = stream->priv;
+ close(p->fd);
+ free(p);
}
-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;
@@ -221,8 +189,6 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
}
#endif
- stream->fd = f;
- stream->type = STREAMTYPE_VCD;
stream->sector_size = VCD_SECTOR_DATA;
stream->start_pos=ret;
stream->end_pos=ret2;
@@ -230,19 +196,15 @@ static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
stream->fill_buffer = fill_buffer;
stream->seek = seek;
- stream->control = control;
stream->close = close_s;
- *file_format = DEMUXER_TYPE_MPEG_PS;
+ stream->demuxer = "lavf"; // mpegps ( or "vcd"?)
m_struct_free(&stream_opts,opts);
return STREAM_OK;
}
const stream_info_t stream_info_vcd = {
- "Video CD",
"vcd",
- "Albeu",
- "based on the code from ???",
open_s,
{ "vcd", NULL },
&stream_opts,
diff --git a/stream/tv.c b/stream/tv.c
index 1fcb13037d..9b1f8024e4 100644
--- a/stream/tv.c
+++ b/stream/tv.c
@@ -210,15 +210,28 @@ 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;
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);
@@ -688,27 +701,31 @@ 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, 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 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;
- 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;
@@ -729,8 +746,6 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
if (tvh->tv_param->fps != -1.0f)
sh_video->fps = tvh->tv_param->fps;
- sh_video->frametime = 1.0f/sh_video->fps;
-
/* If playback only mode, go to immediate mode, fail silently */
if(tvh->tv_param->immediate == 1)
{
@@ -738,20 +753,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 */
@@ -786,7 +793,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);
@@ -800,7 +808,7 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
sh_audio->gsh->codec = "mp-pcm";
sh_audio->format = audio_format;
- sh_audio->i_bps = sh_audio->o_bps =
+ sh_audio->i_bps =
sh_audio->samplerate * sh_audio->samplesize *
sh_audio->channels.num;
@@ -816,17 +824,13 @@ 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:
if(!(funcs->start(tvh->priv))){
// start failed :(
tv_uninit(tvh);
- return NULL;
+ return -1;
}
/* set color eq */
@@ -839,7 +843,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)
@@ -1093,17 +1097,10 @@ 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
+ .name = "tv",
+ .desc = "TV card demuxer",
+ .type = DEMUXER_TYPE_TV,
+ .fill_buffer = demux_tv_fill_buffer,
+ .open = demux_open_tv,
+ .close = demux_close_tv,
};
diff --git a/stream/tv.h b/stream/tv.h
index 660a78be7b..ded9ace6c8 100644
--- a/stream/tv.h
+++ b/stream/tv.h
@@ -25,8 +25,6 @@
#ifndef MPLAYER_TV_H
#define MPLAYER_TV_H
-#include "demux/demux.h"
-
typedef struct tv_param_s {
char *freq;
char *channel;
@@ -105,7 +103,7 @@ typedef struct tvi_handle_s {
const tvi_functions_t *functions;
void *priv;
int seq;
- demuxer_t *demuxer;
+ struct demuxer *demuxer;
/* specific */
int norm;
diff --git a/stream/vcd_read.h b/stream/vcd_read.h
index 2d4a88604a..92a9c53b78 100644
--- a/stream/vcd_read.h
+++ b/stream/vcd_read.h
@@ -147,10 +147,12 @@ static mp_vcd_priv_t* vcd_read_toc(int fd){
return vcd;
}
+/*
static int vcd_end_track(mp_vcd_priv_t* vcd)
{
return vcd->tochdr.cdth_trk1;
}
+*/
static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
#ifndef sun
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 5fb8722296..4351cf60a0 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include <math.h>
#include <assert.h>
#include "config.h"
@@ -379,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)
@@ -393,6 +394,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
}
} else {
add_packet(subs, pkt);
+ talloc_free(pkt);
}
}
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index cbf9466780..fc4592ef99 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -34,7 +34,7 @@ static const char osd_font_pfb[] =
;
#include "sub/ass_mp.h"
-#include "core/mp_core.h"
+#include "core/options.h"
// NOTE: \fs-5 to reduce the size of the symbols in relation to normal text.
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index ed856e046c..d101237699 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -24,14 +24,12 @@
#include <stdbool.h>
#include <assert.h>
-#include "demux/codec_tags.h"
-
#include "core/mp_msg.h"
#include "osdep/timer.h"
#include "stream/stream.h"
-#include "demux/demux.h"
+#include "demux/demux_packet.h"
#include "core/codecs.h"
diff --git a/video/decode/vd.c b/video/decode/vd.c
index 6f05ab334c..9df1d39146 100644
--- a/video/decode/vd.c
+++ b/video/decode/vd.c
@@ -28,7 +28,6 @@
#include "video/img_format.h"
#include "stream/stream.h"
-#include "demux/demux.h"
#include "demux/stheader.h"
#include "dec_video.h"
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index ff1565f38f..3b266aeb94 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -345,10 +345,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
avctx->coded_width = sh->disp_w;
avctx->coded_height = sh->disp_h;
- // demux_avi only
- avctx->stream_codec_tag = sh->video.fccHandler;
-
- // demux_mkv, demux_avi, demux_asf
+ // demux_mkv
if (sh->bih)
set_from_bih(avctx, sh->format, sh->bih);
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);