1
mirror of https://github.com/mpv-player/mpv synced 2024-08-24 07:21:49 +02:00

Remove some demuxers and decoders

Most of these demuxers and decoders are provided in better form by
libav, while the mplayer builtin ones are essentially unmaintained. The
only legimitate use case for not using the libav ones was working around
libav bugs or bugs related to the way mplayer uses libav. Instead of
trying to keep dead code alive, development effort should go into
improving libav or the mplayer libav glue code.

Note that the libav demuxer have been preferred over the mplayer builtin
ones for a while in mplayer2. There were some exceptions: playing DVDs
with dvdnav or playing network sources. (That's because some stream
modules and network.c requested explicit file formats, such as
DEMUXER_TYPE_MPEG_PS, which mapped to builtin demuxers.) With this
commit, they are switched to use libav. One caveat is that the requested
format is not passed to libavformat, instead we rely on the auto probing
to select the correct libav demuxer (see code in demux_open_stream()).
This commit is contained in:
wm4 2012-07-30 18:40:46 +02:00
parent 17b69493b7
commit 1fde09db6f
54 changed files with 34 additions and 19301 deletions

View File

@ -88,11 +88,9 @@ SRCS_COMMON-$(LIBMAD) += libmpcodecs/ad_libmad.c
SRCS_COMMON-$(LIBNEMESI) += libmpdemux/demux_nemesi.c \
stream/stream_nemesi.c
SRCS_COMMON-$(LIBNUT) += libmpdemux/demux_nut.c
SRCS_COMMON-$(LIBPOSTPROC) += libmpcodecs/vf_pp.c
SRCS_COMMON-$(LIBSMBCLIENT) += stream/stream_smb.c
SRCS_COMMON-$(LIBTHEORA) += libmpcodecs/vd_theora.c
SRCS_COMMON-$(LIVE555) += libmpdemux/demux_rtp.cpp \
libmpdemux/demux_rtp_codec.cpp \
stream/stream_live555.c
@ -103,8 +101,6 @@ SRCS_COMMON-$(COCOA) += libvo/osx_common.c \
SRCS_COMMON-$(MNG) += libmpdemux/demux_mng.c
SRCS_COMMON-$(MPG123) += libmpcodecs/ad_mpg123.c
SRCS_COMMON-$(MUSEPACK) += libmpcodecs/ad_mpc.c \
libmpdemux/demux_mpc.c
SRCS_COMMON-$(NATIVE_RTSP) += stream/stream_rtsp.c \
stream/freesdp/common.c \
stream/freesdp/errorlist.c \
@ -148,7 +144,6 @@ SRCS_COMMON-$(RADIO) += stream/stream_radio.c
SRCS_COMMON-$(RADIO_CAPTURE) += stream/audio_in.c
SRCS_COMMON-$(REAL_CODECS) += libmpcodecs/ad_realaud.c \
libmpcodecs/vd_realvid.c
SRCS_COMMON-$(SPEEX) += libmpcodecs/ad_speex.c
SRCS_COMMON-$(STREAM_CACHE) += stream/cache2.c
SRCS_COMMON-$(TV) += stream/stream_tv.c stream/tv.c \
@ -161,8 +156,6 @@ SRCS_COMMON-$(TV_DSHOW) += stream/tvi_dshow.c \
SRCS_COMMON-$(TV_V4L1) += stream/tvi_v4l.c stream/audio_in.c
SRCS_COMMON-$(TV_V4L2) += stream/tvi_v4l2.c stream/audio_in.c
SRCS_COMMON-$(VCD) += stream/stream_vcd.c
SRCS_COMMON-$(VORBIS) += libmpcodecs/ad_libvorbis.c \
libmpdemux/demux_ogg.c
SRCS_COMMON-$(VSTREAM) += stream/stream_vstream.c
SRCS_QTX_EMULATION += loader/wrapper.S
SRCS_COMMON-$(QTX_EMULATION) += $(SRCS_QTX_EMULATION)
@ -181,7 +174,6 @@ SRCS_COMMON-$(WIN32_EMULATION) += $(SRCS_WIN32_EMULATION)
SRCS_COMMON-$(WIN32DLL) += libmpcodecs/ad_acm.c \
libmpcodecs/ad_dmo.c \
libmpcodecs/ad_dshow.c \
libmpcodecs/ad_twin.c \
libmpcodecs/vd_dmo.c \
libmpcodecs/vd_dshow.c \
libmpcodecs/vd_vfw.c \
@ -207,7 +199,6 @@ SRCS_COMMON-$(WIN32DLL) += libmpcodecs/ad_acm.c \
loader/dmo/dmo_guids.c \
SRCS_COMMON-$(XANIM_CODECS) += libmpcodecs/vd_xanim.c
SRCS_COMMON-$(XVID4) += libmpcodecs/vd_xvid4.c
SRCS_COMMON-$(DUMMY_OSD) += sub/osd_dummy.c
SRCS_COMMON-$(LIBASS_OSD) += sub/osd_libass.c
@ -262,7 +253,6 @@ SRCS_COMMON = asxparser.c \
libaf/window.c \
libmpcodecs/ad.c \
libmpcodecs/ad_alaw.c \
libmpcodecs/ad_dk3adpcm.c \
libmpcodecs/ad_dvdpcm.c \
libmpcodecs/ad_ffmpeg.c \
libmpcodecs/ad_hwac3.c \
@ -280,11 +270,9 @@ SRCS_COMMON = asxparser.c \
libmpcodecs/vd_ffmpeg.c \
libmpcodecs/vd_hmblck.c \
libmpcodecs/vd_lzo.c \
libmpcodecs/vd_mpegpes.c \
libmpcodecs/vd_mtga.c \
libmpcodecs/vd_null.c \
libmpcodecs/vd_raw.c \
libmpcodecs/vd_sgi.c \
libmpcodecs/vf.c \
libmpcodecs/vf_1bpp.c \
libmpcodecs/vf_2xsai.c \
@ -357,48 +345,30 @@ SRCS_COMMON = asxparser.c \
libmpcodecs/vf_yadif.c \
libmpcodecs/vf_yuvcsp.c \
libmpcodecs/vf_yvu9.c \
libmpdemux/aac_hdr.c \
libmpdemux/asfheader.c \
libmpdemux/aviheader.c \
libmpdemux/aviprint.c \
libmpdemux/demuxer.c \
libmpdemux/demux_aac.c \
libmpdemux/demux_asf.c \
libmpdemux/demux_audio.c \
libmpdemux/demux_avi.c \
libmpdemux/demux_demuxers.c \
libmpdemux/demux_edl.c \
libmpdemux/demux_cue.c \
libmpdemux/demux_film.c \
libmpdemux/demux_fli.c \
libmpdemux/demux_lavf.c \
libmpdemux/demux_lmlm4.c \
libmpdemux/demux_mf.c \
libmpdemux/demux_mkv.c \
libmpdemux/demux_mov.c \
libmpdemux/demux_mpg.c \
libmpdemux/demux_nsv.c \
libmpdemux/demux_pva.c \
libmpdemux/demux_rawaudio.c \
libmpdemux/demux_rawvideo.c \
libmpdemux/demux_realaud.c \
libmpdemux/demux_real.c \
libmpdemux/demux_roq.c \
libmpdemux/demux_smjpeg.c \
libmpdemux/demux_ts.c \
libmpdemux/demux_ty.c \
libmpdemux/demux_viv.c \
libmpdemux/demux_vqf.c \
libmpdemux/demux_y4m.c \
libmpdemux/ebml.c \
libmpdemux/extension.c \
libmpdemux/mf.c \
libmpdemux/mp3_hdr.c \
libmpdemux/mp_taglists.c \
libmpdemux/mpeg_hdr.c \
libmpdemux/mpeg_packetizer.c \
libmpdemux/parse_es.c \
libmpdemux/parse_mp4.c \
libmpdemux/video.c \
libmpdemux/yuv4mpeg.c \
libmpdemux/yuv4mpeg_ratio.c \

View File

@ -30,7 +30,6 @@
#include "config.h"
#include "m_config.h"
#include "m_option.h"
#include "libmpdemux/demux_ts.h"
#include "stream/tv.h"
#include "stream/stream_radio.h"
#include "libvo/csputils.h"
@ -77,12 +76,6 @@ extern const m_option_t demux_rawaudio_opts[];
extern const m_option_t demux_rawvideo_opts[];
extern const m_option_t cdda_opts[];
extern int ts_prog;
extern int ts_keep_broken;
extern off_t ts_probe;
extern int audio_substream_id;
extern off_t ps_probe;
extern int sws_flags;
extern const char pp_help[];
@ -465,7 +458,6 @@ const m_option_t common_opts[] = {
// select audio/video/subtitle stream
OPT_INTRANGE("aid", audio_id, 0, -2, 8190),
{"ausid", &audio_substream_id, CONF_TYPE_INT, 0, 0, 0, NULL},
OPT_INTRANGE("vid", video_id, 0, -2, 8190),
OPT_INTRANGE("sid", sub_id, 0, -2, 8190),
OPT_FLAG_CONSTANTS("no-sub", sub_id, 0, -1, -2),
@ -566,10 +558,6 @@ const m_option_t common_opts[] = {
OPT_FLAG_CONSTANTS("flip", flip, 0, -1, 1),
OPT_FLAG_CONSTANTS("no-flip", flip, 0, -1, 0),
{"tsprog", &ts_prog, CONF_TYPE_INT, CONF_RANGE, 0, 65534, NULL},
{"tsprobe", &ts_probe, CONF_TYPE_POSITION, 0, 0, TS_MAX_PROBE_SIZE, NULL},
{"psprobe", &ps_probe, CONF_TYPE_POSITION, 0, 0, TS_MAX_PROBE_SIZE, NULL},
{"tskeepbroken", &ts_keep_broken, CONF_TYPE_FLAG, 0, 0, 1, NULL},
// draw by slices or whole frame (useful with libmpeg2/libavcodec)
OPT_MAKE_FLAGS("slices", vd_use_slices, 0),

View File

@ -1610,8 +1610,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
if ((d_sub->demuxer->type == DEMUXER_TYPE_MATROSKA
|| d_sub->demuxer->type == DEMUXER_TYPE_LAVF
|| d_sub->demuxer->type == DEMUXER_TYPE_LAVF_PREFERRED
|| d_sub->demuxer->type == DEMUXER_TYPE_OGG)
|| d_sub->demuxer->type == DEMUXER_TYPE_LAVF_PREFERRED)
&& d_sub->sh && opts->sub_id >= 0) {
struct sh_sub *sh = d_sub->sh;
char *lang = sh->lang ? sh->lang : mp_gtext("unknown");

166
configure vendored
View File

@ -349,13 +349,7 @@ Codecs:
--disable-qtx disable QuickTime codecs support [enabled]
--disable-xanim disable XAnim codecs support [enabled]
--disable-real disable RealPlayer codecs support [enabled]
--disable-xvid disable Xvid [autodetect]
--disable-libnut disable libnut [autodetect]
--enable-libav skip Libav autodetection [autodetect]
--disable-libvorbis disable libvorbis support [autodetect]
--disable-tremor disable Tremor [autodetect if no libvorbis]
--disable-speex disable Speex support [autodetect]
--enable-theora enable OggTheora libraries [autodetect]
--enable-faad enable FAAD2 (AAC) [autodetect]
--disable-ladspa disable LADSPA plugin support [autodetect]
--disable-libbs2b disable libbs2b audio filter support [autodetect]
@ -364,8 +358,6 @@ Codecs:
--disable-mad disable libmad (MPEG audio) support [autodetect]
--enable-libdca enable libdca support [autodetect]
--disable-liba52 disable liba52 [autodetect]
--enable-musepack enable libmpcdec support (deprecated, libavcodec
Musepack decoder is preferred) [disabled]
Video output:
--enable-gl enable OpenGL video output [autodetect]
@ -492,10 +484,6 @@ _jack=auto
_openal=no
_libcdio=auto
_mad=auto
_tremor=auto
_libvorbis=auto
_speex=auto
_theora=auto
_mpg123=auto
_liba52=auto
_libdca=auto
@ -538,8 +526,6 @@ _winsock2_h=auto
_smb=auto
_libquvi=auto
_joystick=no
_xvid=auto
_libnut=auto
_lirc=auto
_lircc=auto
_apple_remote=auto
@ -568,7 +554,6 @@ _enca=auto
_inet6=auto
_gethostbyname2=auto
_ftp=auto
_musepack=no
_vstream=auto
_pthreads=auto
_w32threads=auto
@ -751,22 +736,12 @@ for ac_option do
--disable-mad) _mad=no ;;
--enable-libcdio) _libcdio=yes ;;
--disable-libcdio) _libcdio=no ;;
--enable-libvorbis) _libvorbis=yes ;;
--disable-libvorbis) _libvorbis=no ;;
--enable-speex) _speex=yes ;;
--disable-speex) _speex=no ;;
--enable-tremor) _tremor=yes ;;
--disable-tremor) _tremor=no ;;
--enable-theora) _theora=yes ;;
--disable-theora) _theora=no ;;
--enable-mpg123) _mpg123=yes ;;
--disable-mpg123) _mpg123=no ;;
--enable-liba52) _liba52=yes ;;
--disable-liba52) _liba52=no ;;
--enable-libdca) _libdca=yes ;;
--disable-libdca) _libdca=no ;;
--enable-musepack) _musepack=yes ;;
--disable-musepack) _musepack=no ;;
--enable-faad) _faad=yes ;;
--disable-faad) _faad=no ;;
--enable-ladspa) _ladspa=yes ;;
@ -835,10 +810,6 @@ for ac_option do
--disable-libquvi) _libquvi=no ;;
--enable-joystick) _joystick=yes ;;
--disable-joystick) _joystick=no ;;
--enable-xvid) _xvid=yes ;;
--disable-xvid) _xvid=no ;;
--enable-libnut) _libnut=yes ;;
--disable-libnut) _libnut=no ;;
--enable-libav) ffmpeg=yes ;;
--ffmpeg-source-dir=*)
_ffmpeg_source=$(echo $ac_option | cut -d '=' -f 2 ) ;;
@ -3396,71 +3367,6 @@ else
fi
echores "$_mad"
echocheck "OggVorbis support"
if test "$_libvorbis" = auto; then
_libvorbis=no
statement_check vorbis/codec.h 'vorbis_packet_blocksize(0, 0)' -lvorbis -logg $_ld_lm && _libvorbis=yes && _tremor=no
elif test "$_libvorbis" = yes ; then
_tremor=no
fi
if test "$_tremor" = auto; then
_tremor=no
statement_check tremor/ivorbiscodec.h 'vorbis_packet_blocksize(0, 0)' -logg -lvorbisidec $_ld_lm && _tremor=yes
fi
if test "$_tremor" = yes ; then
_vorbis=yes
def_vorbis='#define CONFIG_OGGVORBIS 1'
def_tremor='#define CONFIG_TREMOR 1'
codecmodules="tremor(external) $codecmodules"
res_comment="external Tremor"
extra_ldflags="$extra_ldflags -logg -lvorbisidec"
elif test "$_libvorbis" = yes ; then
_vorbis=yes
def_vorbis='#define CONFIG_OGGVORBIS 1'
codecmodules="libvorbis $codecmodules"
res_comment="libvorbis"
extra_ldflags="$extra_ldflags -lvorbis -logg"
else
_vorbis=no
nocodecmodules="libvorbis $nocodecmodules"
fi
echores "$_vorbis"
echocheck "libspeex (version >= 1.1 required)"
if test "$_speex" = auto ; then
_speex=no
cat > $TMPC << EOF
#include <stddef.h>
#include <speex/speex.h>
int main(void) { SpeexBits bits; void *dec = NULL; speex_decode_int(dec, &bits, dec); return 0; }
EOF
cc_check -lspeex $_ld_lm && _speex=yes
fi
if test "$_speex" = yes ; then
def_speex='#define CONFIG_SPEEX 1'
extra_ldflags="$extra_ldflags -lspeex"
codecmodules="speex $codecmodules"
else
def_speex='#undef CONFIG_SPEEX'
nocodecmodules="speex $nocodecmodules"
fi
echores "$_speex"
echocheck "OggTheora support"
if test "$_theora" = auto ; then
_theora=no
if pkg_config_add theora ; then
_theora=yes
fi
fi
if test "$_theora" = yes ; then
def_theora='#define CONFIG_OGGTHEORA 1'
codecmodules="libtheora $codecmodules"
else
def_theora='#undef CONFIG_OGGTHEORA'
nocodecmodules="libtheora $nocodecmodules"
fi
echores "$_theora"
# Any version of libmpg123 that knows MPG123_RESYNC_LIMIT shall be fine.
# That is, 1.2.0 onwards. Recommened is 1.14 onwards, though.
@ -3514,32 +3420,6 @@ else
fi
echores "$_libdca"
echocheck "libmpcdec (musepack, version >= 1.2.1 required)"
if test "$_musepack" = yes ; then
_musepack=no
cat > $TMPC << EOF
#include <stddef.h>
#include <mpcdec/mpcdec.h>
int main(void) {
mpc_streaminfo info;
mpc_decoder decoder;
mpc_decoder_set_streaminfo(&decoder, &info);
mpc_decoder_decode_frame(&decoder, NULL, 0, NULL);
return 0;
}
EOF
cc_check -lmpcdec $_ld_lm && _musepack=yes
fi
if test "$_musepack" = yes ; then
def_musepack='#define CONFIG_MUSEPACK 1'
extra_ldflags="$extra_ldflags -lmpcdec"
codecmodules="musepack $codecmodules"
else
def_musepack='#undef CONFIG_MUSEPACK'
nocodecmodules="musepack $nocodecmodules"
fi
echores "$_musepack"
echocheck "FAAD2 support"
if test "$_faad" = auto ; then
@ -3819,40 +3699,6 @@ fi
echores "$_libdv"
echocheck "Xvid"
if test "$_xvid" = auto ; then
_xvid=no
for _ld_tmp in "-lxvidcore $_ld_lm" "-lxvidcore $_ld_lm $_ld_pthread" ; do
statement_check xvid.h 'xvid_global(0, 0, 0, 0)' $_ld_tmp &&
extra_ldflags="$extra_ldflags $_ld_tmp" && _xvid=yes && break
done
fi
if test "$_xvid" = yes ; then
def_xvid='#define CONFIG_XVID4 1'
codecmodules="xvid $codecmodules"
else
def_xvid='#undef CONFIG_XVID4'
nocodecmodules="xvid $nocodecmodules"
fi
echores "$_xvid"
echocheck "libnut"
if test "$_libnut" = auto ; then
_libnut=no
statement_check libnut.h 'nut_context_tt * nut; nut_error(0)' -lnut && _libnut=yes
fi
if test "$_libnut" = yes ; then
def_libnut='#define CONFIG_LIBNUT 1'
extra_ldflags="$extra_ldflags -lnut"
else
def_libnut='#undef CONFIG_LIBNUT'
fi
echores "$_libnut"
echocheck "TV interface"
if test "$_tv" = yes ; then
def_tv='#define CONFIG_TV 1'
@ -4391,7 +4237,6 @@ LIBDVDCSS_INTERNAL = $_libdvdcss_internal
LIBMAD = $_mad
LIBNEMESI = $_nemesi
LCMS2 = $_lcms2
LIBNUT = $_libnut
LIBPOSTPROC = $libpostproc
LIBSMBCLIENT = $_smb
LIBQUVI = $_libquvi
@ -4402,7 +4247,6 @@ MACOSX_FINDER = $_macosx_finder
MD5SUM = $_md5sum
MNG = $_mng
MPG123 = $_mpg123
MUSEPACK = $_musepack
NATIVE_RTSP = $_native_rtsp
NETWORKING = $networking
OPENAL = $_openal
@ -4421,7 +4265,6 @@ RADIO=$_radio
RADIO_CAPTURE=$_radio_capture
REAL_CODECS = $_real
RSOUND = $_rsound
SPEEX = $_speex
STREAM_CACHE = $_stream_cache
TGA = $_tga
TV = $_tv
@ -4433,14 +4276,12 @@ TV_V4L2 = $_tv_v4l2
V4L2 = $_v4l2
VCD = $_vcd
VDPAU = $_vdpau
VORBIS = $_vorbis
VSTREAM = $_vstream
WIN32DLL = $_win32dll
WIN32_EMULATION = $_win32_emulation
X11 = $_x11
XANIM_CODECS = $_xanim
XV = $_xv
XVID4 = $_xvid
YUV4MPEG = $_yuv4mpeg
# FFmpeg
@ -4624,16 +4465,9 @@ $def_libdca
$def_libdv
$def_mad
$def_mpg123
$def_musepack
$def_speex
$def_theora
$def_tremor
$def_vorbis
$def_xvid
$def_zlib
$def_libpostproc
$def_libnut
/* binary codecs */

View File

@ -445,13 +445,6 @@ videocodec ffsgi
driver ffmpeg
dll sgi
videocodec sgi
info "SGI image"
status working
fourcc SGI1 ; SGI1 is an internal MPlayer FOURCC
driver sgi
out BGR24
videocodec ffsunras
info "FFmpeg SUN Rasterfile"
status working
@ -562,14 +555,6 @@ videocodec lzo
out YV12,I420
out BGR24 flip
videocodec theora
info "Theora (free, reworked VP3)"
status working
fourcc theo,Thra
driver theora
dll libtheora
out YV12,422P,444P
; prefer native codecs over win32?
; the win32 codecs probably are (better) optimized and support direct
; rendering, so this may be not the best idea...
@ -1099,41 +1084,6 @@ videocodec fflibdirac
driver ffmpeg
dll libdirac
videocodec xvid
info "Xvid (MPEG-4)"
status working
fourcc FMP4,fmp4
fourcc DIVX,divx
fourcc xvid,XVID,XviD,XVIX
fourcc DIV1,div1 divx
fourcc MP4S,mp4s ; ISO MPEG-4 Video V1
fourcc M4S2,m4s2
fourcc DX50,dx50,BLZ0 DX50
fourcc mp4v,MP4V
format 0x4
fourcc UMP4
fourcc RMP4
fourcc 3IV2,3iv2 ; 3ivx Delta 4
fourcc DXGM
fourcc SEDG ; diskless camcorder Samsung Miniket VP-M110
fourcc SMP4,smp4 ; Samsung SMP4 video codec
fourcc VIDM ; vidm 4.01 codec
fourcc FFDS
fourcc DCOD,MVXM,EM4A,PM4V
fourcc M4T3,DMK2,DIGI,INMC
fourcc EPHV,SN40,WAWV
fourcc uldx,ULDX,VSPX
format 0x10000004 ; mpeg 4 es
fourcc SIPP ; Samsung SHR-6040
driver xvid
out YV12
out I420
out YUY2
out UYVY
out YVYU
out BGR32,BGR24,BGR16,BGR15
dll "libxvidcore.a"
; is divx4vfw stable enough, working everywhere and faster than divxds?
videocodec divx4vfw
@ -3860,13 +3810,6 @@ audiocodec ffadpcmimadk3
driver ffmpeg
dll adpcm_ima_dk3
audiocodec dk3adpcm
info "Duck DK3 ADPCM (rogue format number)"
status working
format 0x62 ; This format number was used by Duck Corp. but not officially
; registered with Microsoft
driver dk3adpcm
audiocodec ffroqaudio
info "Id RoQ File Audio"
status working
@ -4501,13 +4444,6 @@ audiocodec ffmusepack8
driver ffmpeg
dll "mpc8"
audiocodec musepack
info "Musepack audio codec"
status working
fourcc "MPC "
format 0x2b4d
driver mpcdec
audiocodec ffamrnb
info "AMR Narrowband"
status working
@ -4630,46 +4566,6 @@ audiocodec ffvorbis
driver ffmpeg
dll "vorbis"
audiocodec vorbis
info "OggVorbis Audio"
status working
comment "OggVorbis driver using libvorbis"
fourcc vrbs
format 0x566F
driver libvorbis
dll "libvorbis"
audiocodec tremor
info "OggVorbis audio"
status working
comment "fixed-point decoder useful for systems without floating-point unit"
fourcc vrbs
format 0x566F
driver tremor
dll "tremor"
audiocodec vorbisacm
info "OggVorbis ACM"
status working
comment "OggVorbis driver using vorbis.acm"
format 0x674F ; mode1
format 0x6750 ; mode2
; format 0x6751 ; mode3
format 0x676F ; mode1+
format 0x6770 ; mode2+
format 0x6771 ; mode3+
driver acm
dll "vorbis.acm"
audiocodec speex
info "Speex audio"
status working
comment "Speex driver using libspeex"
fourcc 'spx '
format 0xA109
driver speex
dll "speex"
audiocodec vivoaudio
info "Vivo G.723/Siren Audio Codec"
status working
@ -4797,13 +4693,6 @@ audiocodec fftwinvq
driver ffmpeg
dll twinvq
audiocodec TwinVQ
info "VQF codec by NTTLabs"
status working
fourcc TWIN
driver vqf
dll "tvqdec.dll"
audiocodec hwmpa
info "MPEG audio pass-through for hardware MPEG decoders"
status working

View File

@ -41,20 +41,14 @@ extern const ad_functions_t mpcodecs_ad_dvdpcm;
extern const ad_functions_t mpcodecs_ad_alaw;
extern const ad_functions_t mpcodecs_ad_imaadpcm;
extern const ad_functions_t mpcodecs_ad_msadpcm;
extern const ad_functions_t mpcodecs_ad_dk3adpcm;
extern const ad_functions_t mpcodecs_ad_dk4adpcm;
extern const ad_functions_t mpcodecs_ad_dshow;
extern const ad_functions_t mpcodecs_ad_dmo;
extern const ad_functions_t mpcodecs_ad_acm;
extern const ad_functions_t mpcodecs_ad_faad;
extern const ad_functions_t mpcodecs_ad_libvorbis;
extern const ad_functions_t mpcodecs_ad_speex;
extern const ad_functions_t mpcodecs_ad_libmad;
extern const ad_functions_t mpcodecs_ad_realaud;
extern const ad_functions_t mpcodecs_ad_libdv;
extern const ad_functions_t mpcodecs_ad_qtaudio;
extern const ad_functions_t mpcodecs_ad_twin;
extern const ad_functions_t mpcodecs_ad_libmusepack;
extern const ad_functions_t mpcodecs_ad_libdca;
const ad_functions_t * const mpcodecs_ad_drivers[] =
@ -73,7 +67,6 @@ const ad_functions_t * const mpcodecs_ad_drivers[] =
&mpcodecs_ad_alaw,
&mpcodecs_ad_imaadpcm,
&mpcodecs_ad_msadpcm,
&mpcodecs_ad_dk3adpcm,
#ifdef CONFIG_WIN32DLL
&mpcodecs_ad_dshow,
&mpcodecs_ad_dmo,
@ -86,12 +79,6 @@ const ad_functions_t * const mpcodecs_ad_drivers[] =
#ifdef CONFIG_FAAD
&mpcodecs_ad_faad,
#endif
#ifdef CONFIG_OGGVORBIS
&mpcodecs_ad_libvorbis,
#endif
#ifdef CONFIG_SPEEX
&mpcodecs_ad_speex,
#endif
#ifdef CONFIG_LIBMAD
&mpcodecs_ad_libmad,
#endif
@ -101,9 +88,6 @@ const ad_functions_t * const mpcodecs_ad_drivers[] =
#ifdef CONFIG_LIBDV095
&mpcodecs_ad_libdv,
#endif
#ifdef CONFIG_MUSEPACK
&mpcodecs_ad_libmusepack,
#endif
#ifdef CONFIG_LIBDCA
&mpcodecs_ad_libdca,
#endif

View File

@ -1,262 +0,0 @@
/*
* DK3 ADPCM decoder
*
* "This format number was used by Duck Corp. but not officially
* registered with Microsoft"
*
* This file is responsible for decoding audio data encoded with
* Duck Corp's DK3 ADPCM algorithm. Details about the data format
* can be found here:
* http://www.pcisys.net/~melanson/codecs/
*
* Copyright (c) 2002 Mike Melanson
*
* 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 <libavutil/intreadwrite.h>
#include "config.h"
#include "ad_internal.h"
static const ad_info_t info =
{
"Duck Corp. DK3 ADPCM decoder",
"dk3adpcm",
"Nick Kurshev",
"Mike Melanson",
""
};
LIBAD_EXTERN(dk3adpcm)
#define DK3_ADPCM_PREAMBLE_SIZE 16
// useful macros
// clamp a number between 0 and 88
#define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88;
// clamp a number within a signed 16-bit range
#define CLAMP_S16(x) if (x < -32768) x = -32768; \
else if (x > 32767) x = 32767;
// clamp a number above 16
#define CLAMP_ABOVE_16(x) if (x < 16) x = 16;
// sign extend a 16-bit value
#define SE_16BIT(x) if (x & 0x8000) x -= 0x10000;
// sign extend a 4-bit value
#define SE_4BIT(x) if (x & 0x8) x -= 0x10;
// pertinent tables
static int adpcm_step[89] =
{
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
static int adpcm_index[16] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
static int preinit(sh_audio_t *sh_audio)
{
sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 6;
sh_audio->ds->ss_div =
(sh_audio->wf->nBlockAlign - DK3_ADPCM_PREAMBLE_SIZE) * 8 / 3;
sh_audio->audio_in_minsize=
sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign;
return 1;
}
static int init(sh_audio_t *sh_audio)
{
sh_audio->channels = sh_audio->wf->nChannels;
sh_audio->samplerate = sh_audio->wf->nSamplesPerSec;
sh_audio->i_bps =
(sh_audio->ds->ss_mul * sh_audio->samplerate) / sh_audio->ds->ss_div;
sh_audio->samplesize=2;
return 1;
}
static void uninit(sh_audio_t *sh_audio)
{
}
static int control(sh_audio_t *sh_audio,int cmd,void* arg, ...)
{
if(cmd==ADCTRL_SKIP_FRAME){
demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul);
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
#define DK3_GET_NEXT_NIBBLE() \
if (decode_top_nibble_next) \
{ \
nibble = (last_byte >> 4) & 0x0F; \
decode_top_nibble_next = 0; \
} \
else \
{ \
last_byte = input[in_ptr++]; \
nibble = last_byte & 0x0F; \
decode_top_nibble_next = 1; \
}
// note: This decoder assumes the format 0x62 data always comes in
// stereo flavor
static int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input,
int block_size)
{
int sum_pred;
int diff_pred;
int sum_index;
int diff_index;
int diff_channel;
int in_ptr = 0x10;
int out_ptr = 0;
unsigned char last_byte = 0;
unsigned char nibble;
int decode_top_nibble_next = 0;
// ADPCM work variables
int sign;
int delta;
int step;
int diff;
sum_pred = AV_RL16(&input[10]);
diff_pred = AV_RL16(&input[12]);
SE_16BIT(sum_pred);
SE_16BIT(diff_pred);
diff_channel = diff_pred;
sum_index = input[14];
diff_index = input[15];
while (in_ptr < block_size - !decode_top_nibble_next)
// while (in_ptr < 2048)
{
// process the first predictor of the sum channel
DK3_GET_NEXT_NIBBLE();
step = adpcm_step[sum_index];
sign = nibble & 8;
delta = nibble & 7;
diff = step >> 3;
if (delta & 4) diff += step;
if (delta & 2) diff += step >> 1;
if (delta & 1) diff += step >> 2;
if (sign)
sum_pred -= diff;
else
sum_pred += diff;
CLAMP_S16(sum_pred);
sum_index += adpcm_index[nibble];
CLAMP_0_TO_88(sum_index);
// process the diff channel predictor
DK3_GET_NEXT_NIBBLE();
step = adpcm_step[diff_index];
sign = nibble & 8;
delta = nibble & 7;
diff = step >> 3;
if (delta & 4) diff += step;
if (delta & 2) diff += step >> 1;
if (delta & 1) diff += step >> 2;
if (sign)
diff_pred -= diff;
else
diff_pred += diff;
CLAMP_S16(diff_pred);
diff_index += adpcm_index[nibble];
CLAMP_0_TO_88(diff_index);
// output the first pair of stereo PCM samples
diff_channel = (diff_channel + diff_pred) / 2;
output[out_ptr++] = sum_pred + diff_channel;
output[out_ptr++] = sum_pred - diff_channel;
// process the second predictor of the sum channel
DK3_GET_NEXT_NIBBLE();
step = adpcm_step[sum_index];
sign = nibble & 8;
delta = nibble & 7;
diff = step >> 3;
if (delta & 4) diff += step;
if (delta & 2) diff += step >> 1;
if (delta & 1) diff += step >> 2;
if (sign)
sum_pred -= diff;
else
sum_pred += diff;
CLAMP_S16(sum_pred);
sum_index += adpcm_index[nibble];
CLAMP_0_TO_88(sum_index);
// output the second pair of stereo PCM samples
output[out_ptr++] = sum_pred + diff_channel;
output[out_ptr++] = sum_pred - diff_channel;
}
return out_ptr;
}
static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
{
if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,
sh_audio->ds->ss_mul) !=
sh_audio->ds->ss_mul)
return -1; /* EOF */
if (maxlen < 2 * 4 * sh_audio->wf->nBlockAlign * 2 / 3) {
mp_msg(MSGT_DECAUDIO, MSGL_V, "dk3adpcm: maxlen too small in decode_audio\n");
return -1;
}
return 2 * dk3_adpcm_decode_block(
(unsigned short*)buf, sh_audio->a_in_buffer,
sh_audio->ds->ss_mul);
}

View File

@ -1,350 +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 <stdarg.h>
#include <math.h>
#include "config.h"
#include "ad_internal.h"
#include "libaf/reorder_ch.h"
static const ad_info_t info =
{
"Ogg/Vorbis audio decoder",
#ifdef CONFIG_TREMOR
"tremor",
#else
"libvorbis",
#endif
"Felix Buenemann, A'rpi",
"libvorbis",
""
};
LIBAD_EXTERN(libvorbis)
#ifdef CONFIG_TREMOR
#include <tremor/ivorbiscodec.h>
#else
#include <vorbis/codec.h>
#endif
// This struct is also defined in demux_ogg.c => common header ?
typedef struct ov_struct_st {
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
float rg_scale; /* replaygain scale */
#ifdef CONFIG_TREMOR
int rg_scale_int;
#endif
} ov_struct_t;
static int read_vorbis_comment( char* ptr, const char* comment, const char* format, ... ) {
va_list va;
int clen, ret;
va_start( va, format );
clen = strlen( comment );
ret = strncasecmp( ptr, comment, clen) == 0 ? vsscanf( ptr+clen, format, va ) : 0;
va_end( va );
return ret;
}
static int preinit(sh_audio_t *sh)
{
sh->audio_out_minsize=1024*4; // 1024 samples/frame
return 1;
}
static int init(sh_audio_t *sh)
{
unsigned int offset, i, length, hsizes[3];
void *headers[3];
unsigned char* extradata;
ogg_packet op;
vorbis_comment vc;
struct ov_struct_st *ov;
#define ERROR() { \
vorbis_comment_clear(&vc); \
vorbis_info_clear(&ov->vi); \
free(ov); \
return 0; \
}
/// Init the decoder with the 3 header packets
ov = malloc(sizeof(struct ov_struct_st));
vorbis_info_init(&ov->vi);
vorbis_comment_init(&vc);
if(! sh->wf) {
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent! exit\n");
ERROR();
}
if(! sh->wf->cbSize) {
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent!, exit\n");
ERROR();
}
mp_msg(MSGT_DECAUDIO,MSGL_V,"ad_vorbis, extradata seems is %d bytes long\n", sh->wf->cbSize);
extradata = (char*) (sh->wf+1);
if(!extradata) {
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be NULL!, exit\n");
ERROR();
}
if(*extradata != 2) {
mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
ERROR();
}
offset = 1;
for (i=0; i < 2; i++) {
length = 0;
while ((extradata[offset] == (unsigned char) 0xFF) && length < sh->wf->cbSize) {
length += 255;
offset++;
}
if(offset >= (sh->wf->cbSize - 1)) {
mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
ERROR();
}
length += extradata[offset];
offset++;
mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, offset: %u, length: %u\n", offset, length);
hsizes[i] = length;
}
headers[0] = &extradata[offset];
headers[1] = &extradata[offset + hsizes[0]];
headers[2] = &extradata[offset + hsizes[0] + hsizes[1]];
hsizes[2] = sh->wf->cbSize - offset - hsizes[0] - hsizes[1];
mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, header sizes: %d %d %d\n", hsizes[0], hsizes[1], hsizes[2]);
for(i=0; i<3; i++) {
op.bytes = hsizes[i];
op.packet = headers[i];
op.b_o_s = (i == 0);
if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: header n. %d broken! len=%ld\n", i, op.bytes);
ERROR();
}
if(i == 2) {
float rg_gain=0.f, rg_peak=0.f;
char **ptr=vc.user_comments;
while(*ptr){
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
/* replaygain */
read_vorbis_comment( *ptr, "replaygain_album_gain=", "%f", &rg_gain );
read_vorbis_comment( *ptr, "rg_audiophile=", "%f", &rg_gain );
if( !rg_gain ) {
read_vorbis_comment( *ptr, "replaygain_track_gain=", "%f", &rg_gain );
read_vorbis_comment( *ptr, "rg_radio=", "%f", &rg_gain );
}
read_vorbis_comment( *ptr, "replaygain_album_peak=", "%f", &rg_peak );
if( !rg_peak ) {
read_vorbis_comment( *ptr, "replaygain_track_peak=", "%f", &rg_peak );
read_vorbis_comment( *ptr, "rg_peak=", "%f", &rg_peak );
}
++ptr;
}
/* replaygain: scale */
if(!rg_gain)
ov->rg_scale = 1.f; /* just in case pow() isn't standard-conformant */
else
ov->rg_scale = pow(10.f, rg_gain/20);
/* replaygain: anticlip */
if(ov->rg_scale * rg_peak > 1.f)
ov->rg_scale = 1.f / rg_peak;
/* replaygain: security */
if(ov->rg_scale > 15.)
ov->rg_scale = 15.;
#ifdef CONFIG_TREMOR
ov->rg_scale_int = (int)(ov->rg_scale*64.f);
#endif
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel%s, %dHz, %dbit/s %cBR\n",(int)ov->vi.channels,ov->vi.channels>1?"s":"",(int)ov->vi.rate,(int)ov->vi.bitrate_nominal,
(ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C');
if(rg_gain || rg_peak)
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain, rg_peak, ov->rg_scale);
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
}
}
vorbis_comment_clear(&vc);
// printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
// Setup the decoder
sh->channels=ov->vi.channels;
sh->samplerate=ov->vi.rate;
sh->samplesize=2;
// assume 128kbit if bitrate not specified in the header
sh->i_bps=((ov->vi.bitrate_nominal>0) ? ov->vi.bitrate_nominal : 128000)/8;
sh->context = ov;
/// Finish the decoder init
vorbis_synthesis_init(&ov->vd,&ov->vi);
vorbis_block_init(&ov->vd,&ov->vb);
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n");
return 1;
}
static void uninit(sh_audio_t *sh)
{
struct ov_struct_st *ov = sh->context;
vorbis_dsp_clear(&ov->vd);
vorbis_block_clear(&ov->vb);
vorbis_info_clear(&ov->vi);
free(ov);
}
static int control(sh_audio_t *sh,int cmd,void* arg, ...)
{
switch(cmd)
{
#if 0
case ADCTRL_RESYNC_STREAM:
return CONTROL_TRUE;
case ADCTRL_SKIP_FRAME:
return CONTROL_TRUE;
#endif
}
return CONTROL_UNKNOWN;
}
static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen)
{
int len = 0;
int samples;
#ifdef CONFIG_TREMOR
ogg_int32_t **pcm;
#else
float scale;
float **pcm;
#endif
struct ov_struct_st *ov = sh->context;
while(len < minlen) {
while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))<=0){
ogg_packet op;
double pts;
memset(&op,0,sizeof(op)); //op.b_o_s = op.e_o_s = 0;
op.bytes = ds_get_packet_pts(sh->ds,&op.packet, &pts);
if(op.bytes<=0) break;
if (pts != MP_NOPTS_VALUE) {
sh->pts = pts;
sh->pts_bytes = 0;
}
if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */
vorbis_synthesis_blockin(&ov->vd,&ov->vb);
}
if(samples<=0) break; // error/EOF
while(samples>0){
int i,j;
int clipflag=0;
int convsize=(maxlen-len)/(2*ov->vi.channels); // max size!
int bout=((samples<convsize)?samples:convsize);
if(bout<=0) break; // no buffer space
/* convert floats to 16 bit signed ints (host order) and
interleave */
#ifdef CONFIG_TREMOR
if (ov->rg_scale_int == 64) {
for(i=0;i<ov->vi.channels;i++){
ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);
ogg_int16_t *ptr=convbuffer+i;
ogg_int32_t *mono=pcm[i];
for(j=0;j<bout;j++){
int val=mono[j]>>9;
/* might as well guard against clipping */
if(val>32767){
val=32767;
clipflag=1;
}
if(val<-32768){
val=-32768;
clipflag=1;
}
*ptr=val;
ptr+=ov->vi.channels;
}
}
} else
#endif /* CONFIG_TREMOR */
{
#ifndef CONFIG_TREMOR
scale = 32767.f * ov->rg_scale;
#endif
for(i=0;i<ov->vi.channels;i++){
ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);
ogg_int16_t *ptr=convbuffer+i;
#ifdef CONFIG_TREMOR
ogg_int32_t *mono=pcm[i];
for(j=0;j<bout;j++){
int val=(mono[j]*ov->rg_scale_int)>>(9+6);
#else
float *mono=pcm[i];
for(j=0;j<bout;j++){
int val=mono[j]*scale;
/* might as well guard against clipping */
if(val>32767){
val=32767;
clipflag=1;
}
if(val<-32768){
val=-32768;
clipflag=1;
}
#endif /* CONFIG_TREMOR */
*ptr=val;
ptr+=ov->vi.channels;
}
}
}
if(clipflag)
mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence));
len+=2*ov->vi.channels*bout;
sh->pts_bytes += 2*ov->vi.channels*bout;
mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);
samples-=bout;
vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how
many samples we
actually consumed */
} //while(samples>0)
// if (!samples) break; // why? how?
}
if (len > 0 && ov->vi.channels >= 5) {
reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_VORBIS_DEFAULT,
AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
ov->vi.channels, len / sh->samplesize,
sh->samplesize);
}
return len;
}

View File

@ -1,231 +0,0 @@
/*
* Musepack audio files decoder for MPlayer
* by Reza Jelveh <reza.jelveh@tuhh.de> and
* Reimar Döffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>
*
* This code may be be relicensed under the terms of the GNU LGPL when it
* becomes part of the FFmpeg project (ffmpeg.org)
*
* 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 "ad_internal.h"
#include "libaf/af_format.h"
#include "libvo/fastmemcpy.h"
static const ad_info_t info =
{
"Musepack audio decoder",
"mpcdec",
"Reza Jelveh and Reimar Döffinger",
"",
""
};
LIBAD_EXTERN(libmusepack)
#include <mpcdec/mpcdec.h>
// BUFFER_LENGTH is in MPC_SAMPLE_FORMAT units
#define MAX_FRAMESIZE (4 * MPC_DECODER_BUFFER_LENGTH)
//! this many frames should decode good after seeking
#define MIN_SEEK_GOOD 5
//! how many frames to discard at most after seeking
#define MAX_SEEK_DISCARD 50
typedef struct context_s {
char *header;
int header_len;
sh_audio_t *sh;
uint32_t pos;
mpc_decoder decoder;
} context_t;
/**
* \brief mpc_reader callback function for reading the header
*/
static mpc_int32_t cb_read(void *data, void *buf, mpc_int32_t size) {
context_t *d = (context_t *)data;
char *p = (char *)buf;
int s = size;
if (d->pos < d->header_len) {
if (s > d->header_len - d->pos)
s = d->header_len - d->pos;
fast_memcpy(p, &d->header[d->pos], s);
} else
s = 0;
memset(&p[s], 0, size - s);
d->pos += size;
return size;
}
/**
* \brief dummy mpc_reader callback function for seeking
*/
static mpc_bool_t cb_seek(void *data, mpc_int32_t offset ) {
context_t *d = (context_t *)data;
d->pos = offset;
return 1;
}
/**
* \brief dummy mpc_reader callback function for getting stream position
*/
static mpc_int32_t cb_tell(void *data) {
context_t *d = (context_t *)data;
return d->pos;
}
/**
* \brief dummy mpc_reader callback function for getting stream length
*/
static mpc_int32_t cb_get_size(void *data) {
return 1 << 30;
}
/**
* \brief mpc_reader callback function, we cannot seek.
*/
static mpc_bool_t cb_canseek(void *data) {
return 0;
}
mpc_reader header_reader = {
.read = cb_read, .seek = cb_seek, .tell = cb_tell,
.get_size = cb_get_size, .canseek = cb_canseek
};
static int preinit(sh_audio_t *sh) {
sh->audio_out_minsize = MAX_FRAMESIZE;
return 1;
}
static void uninit(sh_audio_t *sh) {
free(sh->context);
sh->context = NULL;
}
static int init(sh_audio_t *sh) {
mpc_streaminfo info;
context_t *cd = malloc(sizeof(context_t));
if (!sh->wf || (sh->wf->cbSize < 6 * 4)) {
mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Missing extradata!\n");
return 0;
}
cd->header = (char *)(sh->wf + 1);
cd->header_len = sh->wf->cbSize;
cd->sh = sh;
cd->pos = 0;
sh->context = (char *)cd;
/* read file's streaminfo data */
mpc_streaminfo_init(&info);
header_reader.data = cd;
if (mpc_streaminfo_read(&info, &header_reader) != ERROR_CODE_OK) {
mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Not a valid musepack file.\n");
return 0;
}
// this value is nonsense, since it relies on the get_size function.
// use the value from the demuxer instead.
// sh->i_bps = info.average_bitrate / 8;
sh->channels = info.channels;
sh->samplerate = info.sample_freq;
sh->samplesize = 4;
sh->sample_format =
#if MPC_SAMPLE_FORMAT == float
AF_FORMAT_FLOAT_NE;
#elif MPC_SAMPLE_FORMAT == mpc_int32_t
AF_FORMAT_S32_NE;
#else
#error musepack lib must use either float or mpc_int32_t sample format
#endif
mpc_decoder_setup(&cd->decoder, NULL);
mpc_decoder_set_streaminfo(&cd->decoder, &info);
return 1;
}
// FIXME: minlen is currently ignored
static int decode_audio(sh_audio_t *sh, unsigned char *buf,
int minlen, int maxlen) {
int status, len;
MPC_SAMPLE_FORMAT *sample_buffer = (MPC_SAMPLE_FORMAT *)buf;
mpc_uint32_t *packet = NULL;
context_t *cd = (context_t *) sh->context;
if (maxlen < MAX_FRAMESIZE) {
mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n");
return -1;
}
len = ds_get_packet(sh->ds, (unsigned char **)&packet);
if (len <= 0) return -1;
status = mpc_decoder_decode_frame(&cd->decoder, packet, len, sample_buffer);
if (status == -1) // decode error
mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Error decoding file.\n");
if (status <= 0) // error or EOF
return -1;
status = MPC_FRAME_LENGTH * sh->channels; // one sample per channel
#if MPC_SAMPLE_FORMAT == float || MPC_SAMPLE_FORMAT == mpc_int32_t
status *= 4;
#else
// should not happen
status *= 2;
#endif
return status;
}
/**
* \brief check if the decoded values are in a sane range
* \param buf decoded buffer
* \param len length of buffer in bytes
* \return 1 if all values are in (-1.01, 1.01) range, 0 otherwise
*/
static int check_clip(void *buf, int len) {
#if MPC_SAMPLE_FORMAT == float
float *p = buf;
if (len < 4) return 1;
len = -len / 4;
p = &p[-len];
do {
if (p[len] < -1 || p[len] > 1) return 0;
} while (++len);
#endif
return 1;
}
static int control(sh_audio_t *sh, int cmd, void* arg, ...) {
if (cmd == ADCTRL_RESYNC_STREAM) {
unsigned char *buf = malloc(MAX_FRAMESIZE);
int i;
int nr_ok = 0;
for (i = 0; i < MAX_SEEK_DISCARD; i++) {
int len = decode_audio(sh, buf, 0, MAX_FRAMESIZE);
if (check_clip(buf, len)) nr_ok++; else nr_ok = 0;
if (nr_ok > MIN_SEEK_GOOD) break;
}
free(buf);
}
return CONTROL_UNKNOWN;
}

View File

@ -1,179 +0,0 @@
/*
* Speex decoder by Reimar Döffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>
*
* This code may be be relicensed under the terms of the GNU LGPL when it
* becomes part of the FFmpeg project (ffmpeg.org)
*
* 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 <speex/speex.h>
#include <speex/speex_stereo.h>
#include <speex/speex_header.h>
#include "ad_internal.h"
static const ad_info_t info = {
"Speex audio decoder",
"speex",
"Reimar Döffinger",
"",
""
};
LIBAD_EXTERN(speex)
typedef struct {
SpeexBits bits;
void *dec_context;
SpeexStereoState stereo;
SpeexHeader *hdr;
} context_t;
#define MAX_FRAMES_PER_PACKET 100
static int preinit(sh_audio_t *sh) {
sh->audio_out_minsize = 2 * 320 * MAX_FRAMES_PER_PACKET * 2 * sizeof(short);
return 1;
}
static int read_le32(const uint8_t **src) {
const uint8_t *p = *src;
*src += 4;
return p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
}
static int init(sh_audio_t *sh) {
context_t *ctx = calloc(1, sizeof(context_t));
const uint8_t *hdr = (const uint8_t *)(sh->wf + 1);
const SpeexMode *spx_mode;
const SpeexStereoState st_st = SPEEX_STEREO_STATE_INIT; // hack
if (sh->wf && sh->wf->cbSize >= 80)
ctx->hdr = speex_packet_to_header((char *)&sh->wf[1], sh->wf->cbSize);
if (!ctx->hdr && sh->wf->cbSize == 0x72 && hdr[0] == 1 && hdr[1] == 0) {
// speex.acm format: raw SpeexHeader dump
ctx->hdr = calloc(1, sizeof(*ctx->hdr));
hdr += 2;
hdr += 8; // identifier string
hdr += 20; // version string
ctx->hdr->speex_version_id = read_le32(&hdr);
ctx->hdr->header_size = read_le32(&hdr);
ctx->hdr->rate = read_le32(&hdr);
ctx->hdr->mode = read_le32(&hdr);
ctx->hdr->mode_bitstream_version = read_le32(&hdr);
ctx->hdr->nb_channels = read_le32(&hdr);
ctx->hdr->bitrate = read_le32(&hdr);
ctx->hdr->frame_size = read_le32(&hdr);
ctx->hdr->vbr = read_le32(&hdr);
ctx->hdr->frames_per_packet = read_le32(&hdr);
}
if (!ctx->hdr) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Invalid or missing extradata! Assuming defaults.\n");
ctx->hdr = calloc(1, sizeof(*ctx->hdr));
ctx->hdr->frames_per_packet = 1;
ctx->hdr->mode = 0;
if (sh->wf) {
ctx->hdr->nb_channels = sh->wf->nChannels;
ctx->hdr->rate = sh->wf->nSamplesPerSec;
if (ctx->hdr->rate > 16000)
ctx->hdr->mode = 2;
else if (ctx->hdr->rate > 8000)
ctx->hdr->mode = 1;
}
}
if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) {
mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), "
"assuming mono\n", ctx->hdr->nb_channels);
ctx->hdr->nb_channels = 1;
}
if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) {
mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of frames per packet (%i), "
"assuming 1\n", ctx->hdr->frames_per_packet);
ctx->hdr->frames_per_packet = 1;
}
switch (ctx->hdr->mode) {
case 0:
spx_mode = &speex_nb_mode; break;
case 1:
spx_mode = &speex_wb_mode; break;
case 2:
spx_mode = &speex_uwb_mode; break;
default:
mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode);
spx_mode = &speex_nb_mode;
}
ctx->dec_context = speex_decoder_init(spx_mode);
speex_bits_init(&ctx->bits);
memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2
sh->channels = ctx->hdr->nb_channels;
sh->samplerate = ctx->hdr->rate;
sh->samplesize = 2;
sh->sample_format = AF_FORMAT_S16_NE;
sh->context = ctx;
return 1;
}
static void uninit(sh_audio_t *sh) {
context_t *ctx = sh->context;
if (ctx) {
speex_bits_destroy(&ctx->bits);
speex_decoder_destroy(ctx->dec_context);
free(ctx->hdr);
free(ctx);
}
ctx = NULL;
}
static int decode_audio(sh_audio_t *sh, unsigned char *buf,
int minlen, int maxlen) {
double pts;
context_t *ctx = sh->context;
int len, framelen, framesamples;
char *packet;
int i, err;
speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framesamples);
framelen = framesamples * ctx->hdr->nb_channels * sizeof(short);
if (maxlen < ctx->hdr->frames_per_packet * framelen) {
mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n");
return -1;
}
len = ds_get_packet_pts(sh->ds, (unsigned char **)&packet, &pts);
if (len <= 0) return -1;
if (sh->pts == MP_NOPTS_VALUE)
sh->pts = 0;
if (pts != MP_NOPTS_VALUE) {
sh->pts = pts;
sh->pts_bytes = 0;
}
speex_bits_read_from(&ctx->bits, packet, len);
i = ctx->hdr->frames_per_packet;
do {
err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf);
if (err == -2)
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n");
if (ctx->hdr->nb_channels == 2)
speex_decode_stereo_int((short *)buf, framesamples, &ctx->stereo);
buf = &buf[framelen];
} while (--i > 0);
sh->pts_bytes += ctx->hdr->frames_per_packet * framelen;
return ctx->hdr->frames_per_packet * framelen;
}
static int control(sh_audio_t *sh, int cmd, void *arg, ...) {
return CONTROL_UNKNOWN;
}

View File

@ -1,523 +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 "config.h"
#include "ad_internal.h"
#include "vqf.h"
#include "libmpdemux/aviprint.h"
#include "loader/ldt_keeper.h"
#include "loader/wine/windef.h"
#include "libaf/af_format.h"
static const ad_info_t info =
{
"TWinVQ decoder",
"vqf",
"Roberto Togni",
"Nick Kurshev",
"Ported from MPlayerXP"
};
LIBAD_EXTERN(twin)
void* WINAPI LoadLibraryA(char* name);
void* WINAPI GetProcAddress(void* handle, char* func);
int WINAPI FreeLibrary(void* handle);
static int (*TvqInitialize)( headerInfo *setupInfo, INDEX *index, int dispErrorMessageBox );
static void (*TvqTerminate)( INDEX *index );
static void (*TvqGetVectorInfo)(int *bits0[], int *bits1[]);
static void (*TvqDecodeFrame)(INDEX *indexp, float out[]);
static int (*TvqWtypeToBtype)( int w_type, int *btype );
static void (*TvqUpdateVectorInfo)(int varbits, int *ndiv, int bits0[], int bits1[]);
static int (*TvqCheckVersion)(char *versionID);
static void (*TvqGetConfInfo)(tvqConfInfo *cf);
static int (*TvqGetFrameSize)(void);
static int (*TvqGetNumFixedBitsPerFrame)(void);
#define BYTE_BIT 8
#define BBUFSIZ 1024 /* Bit buffer size (bytes) */
#define BBUFLEN (BBUFSIZ*BYTE_BIT) /* Bit buffer length (bits) */
typedef struct vqf_priv_s
{
float pts;
WAVEFORMATEX o_wf; // out format
INDEX index;
tvqConfInfo cf;
headerInfo hi;
int *bits_0[N_INTR_TYPE], *bits_1[N_INTR_TYPE];
unsigned framesize;
/* stream related */
int readable;
int ptr; /* current point in the bit buffer */
int nbuf; /* bit buffer size */
char buf[BBUFSIZ]; /* the bit buffer */
int skip_cnt;
}vqf_priv_t;
static void* vqf_dll;
static int load_dll( char *libname )
{
#ifdef WIN32_LOADER
Setup_LDT_Keeper();
#endif
vqf_dll = LoadLibraryA(libname);
if( vqf_dll == NULL )
{
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "failed loading dll\n" );
return 0;
}
TvqInitialize = GetProcAddress(vqf_dll,"TvqInitialize");
TvqTerminate = GetProcAddress(vqf_dll,"TvqTerminate");
TvqGetVectorInfo = GetProcAddress(vqf_dll,"TvqGetVectorInfo");
TvqDecodeFrame = GetProcAddress(vqf_dll,"TvqDecodeFrame");
TvqWtypeToBtype = GetProcAddress(vqf_dll,"TvqWtypeToBtype");
TvqUpdateVectorInfo = GetProcAddress(vqf_dll,"TvqUpdateVectorInfo");
TvqCheckVersion = GetProcAddress(vqf_dll,"TvqCheckVersion");
TvqGetConfInfo = GetProcAddress(vqf_dll,"TvqGetConfInfo");
TvqGetFrameSize = GetProcAddress(vqf_dll,"TvqGetFrameSize");
TvqGetNumFixedBitsPerFrame = GetProcAddress(vqf_dll,"TvqGetNumFixedBitsPerFrame");
return TvqInitialize && TvqTerminate && TvqGetVectorInfo &&
TvqDecodeFrame && TvqWtypeToBtype && TvqUpdateVectorInfo &&
TvqCheckVersion && TvqGetConfInfo && TvqGetFrameSize &&
TvqGetNumFixedBitsPerFrame;
}
static int init_vqf_audio_codec(sh_audio_t *sh_audio){
WAVEFORMATEX *in_fmt=sh_audio->wf;
vqf_priv_t*priv=sh_audio->context;
int ver;
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "======= Win32 (TWinVQ) AUDIO Codec init =======\n");
sh_audio->channels=in_fmt->nChannels;
sh_audio->samplerate=in_fmt->nSamplesPerSec;
sh_audio->sample_format=AF_FORMAT_S16_NE;
// sh_audio->sample_format=AF_FORMAT_FLOAT_NE;
sh_audio->samplesize=af_fmt2bits(sh_audio->sample_format)/8;
priv->o_wf.nChannels=in_fmt->nChannels;
priv->o_wf.nSamplesPerSec=in_fmt->nSamplesPerSec;
priv->o_wf.nBlockAlign=sh_audio->samplesize*in_fmt->nChannels;
priv->o_wf.nAvgBytesPerSec=in_fmt->nBlockAlign*in_fmt->nChannels;
priv->o_wf.wFormatTag=0x01;
priv->o_wf.wBitsPerSample=in_fmt->wBitsPerSample;
priv->o_wf.cbSize=0;
if( mp_msg_test(MSGT_DECAUDIO,MSGL_V) )
{
mp_msg(MSGT_DECAUDIO, MSGL_V, "Input format:\n");
print_wave_header(in_fmt, MSGL_V);
mp_msg(MSGT_DECAUDIO, MSGL_V, "Output fmt:\n");
print_wave_header(&priv->o_wf, MSGL_V);
}
memcpy(&priv->hi,&in_fmt[1],sizeof(headerInfo));
if((ver=TvqInitialize(&priv->hi,&priv->index,0))){
const char *tvqe[]={
"No errors",
"General error",
"Wrong version",
"Channel setting error",
"Wrong coding mode",
"Inner parameter setting error",
"Wrong number of VQ pre-selection candidates, used only in encoder" };
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Tvq initialization error: %s\n",ver>=0&&ver<7?tvqe[ver]:"Unknown");
return 0;
}
ver=TvqCheckVersion(priv->hi.ID);
if(ver==TVQ_UNKNOWN_VERSION){
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Tvq unknown version of stream\n" );
return 0;
}
TvqGetConfInfo(&priv->cf);
TvqGetVectorInfo(priv->bits_0,priv->bits_1);
priv->framesize=TvqGetFrameSize();
sh_audio->audio_in_minsize=priv->framesize*in_fmt->nChannels;
sh_audio->a_in_buffer_size=4*sh_audio->audio_in_minsize;
sh_audio->a_in_buffer=av_malloc(sh_audio->a_in_buffer_size);
sh_audio->a_in_buffer_len=0;
return 1;
}
static int close_vqf_audio_codec(sh_audio_t *sh_audio)
{
vqf_priv_t*priv=sh_audio->context;
TvqTerminate(&priv->index);
return 1;
}
int init(sh_audio_t *sh_audio)
{
return 1;
}
int preinit(sh_audio_t *sh_audio)
{
/* Win32 VQF audio codec: */
vqf_priv_t *priv;
if(!(sh_audio->context=malloc(sizeof(vqf_priv_t)))) return 0;
priv=sh_audio->context;
if(!load_dll(sh_audio->codec->dll))
{
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "win32.dll looks broken :(\n");
return 0;
}
if(!init_vqf_audio_codec(sh_audio)){
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "TWinVQ initialization fail\n");
return 0;
}
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "INFO: TWinVQ (%s) audio codec init OK!\n",sh_audio->codec->dll);
priv->skip_cnt = 2;
return 1;
}
void uninit(sh_audio_t *sh)
{
close_vqf_audio_codec(sh);
free(sh->context);
FreeLibrary(vqf_dll);
}
static int control(sh_audio_t *sh_audio,int cmd,void* arg, ...)
{
switch(cmd) {
case ADCTRL_QUERY_FORMAT:
return CONTROL_TRUE;
default:
return CONTROL_UNKNOWN;
}
}
static int bread(char *data, /* Output: Output data array */
int size, /* Input: Length of each data */
int nbits, /* Input: Number of bits to write */
sh_audio_t *sh) /* Input: File pointer */
{
/*--- Variables ---*/
int ibits, iptr, idata, ibufadr, ibufbit, icl;
unsigned char mask, tmpdat;
int retval;
vqf_priv_t *priv=sh->context;
/*--- Main operation ---*/
retval = 0;
mask = 0x1;
for ( ibits=0; ibits<nbits; ibits++ ){
if ( priv->readable == 0 ){ /* when the file data buffer is empty */
priv->nbuf = demux_read_data(sh->ds, priv->buf, BBUFSIZ);
priv->nbuf *= 8;
priv->readable = 1;
}
iptr = priv->ptr; /* current file data buffer pointer */
if ( iptr >= priv->nbuf ) /* If data file is empty then return */
return retval;
ibufadr = iptr/BYTE_BIT; /* current file data buffer address */
ibufbit = iptr%BYTE_BIT; /* current file data buffer bit */
/* tmpdat = stream->buf[ibufadr] >> (BYTE_BIT-ibufbit-1); */
tmpdat = (unsigned char)priv->buf[ibufadr];
tmpdat >>= (BYTE_BIT-ibufbit-1);
/* current data bit */
idata = ibits*size; /* output data address */
data[idata] = (char)(tmpdat & mask); /* set output data */
for (icl=1; icl<size; icl++)
data[idata+icl] = 0; /* clear the rest output data buffer */
priv->ptr += 1; /* update data buffer pointer */
if (priv->ptr == BBUFLEN){
priv->ptr = 0;
priv->readable = 0;
}
++retval;
}
return retval;
}
#define BITS_INT (sizeof(int)*8)
static int get_bstm(int *data, /* Input: input data */
unsigned nbits, /* Input: number of bits */
sh_audio_t *sh) /* Input: bit file pointer */
{
unsigned ibit;
unsigned mask;
unsigned work;
char tmpbit[BITS_INT];
int retval;
if ( nbits > BITS_INT ){
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "get_bstm(): %d: %d Error.\n",
nbits, BITS_INT);
exit(1);
}
retval = bread(tmpbit, sizeof(*tmpbit), nbits, sh);
for (ibit=retval; ibit<nbits; ibit++){
tmpbit[ibit] = 0;
}
mask = 0x1<<(nbits-1);
work=0;
for ( ibit=0; ibit<nbits; ibit++ ){
work += mask*tmpbit[ibit];
mask >>= 1;
}
*data = work;
return retval;
}
static int GetVqInfo( tvqConfInfoSubBlock *cfg,
int bits0[],
int bits1[],
int variableBits,
INDEX *index,
sh_audio_t *sh)
{
int idiv;
int bitcount = 0;
if ( index->btype == BLK_LONG ){
TvqUpdateVectorInfo( variableBits, &cfg->ndiv, bits0, bits1 ); // re-calculate VQ bits
}
for ( idiv=0; idiv<cfg->ndiv; idiv++ ){
bitcount += get_bstm(&index->wvq[idiv],bits0[idiv],sh); /* CB 0 */
bitcount += get_bstm(&index->wvq[idiv+cfg->ndiv],bits1[idiv],sh); /* CB 1 */
}
return bitcount;
}
static int GetBseInfo( tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh)
{
int i_sup, isf, itmp, idiv;
int bitcount = 0;
for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
for ( isf=0; isf<cfg->nsf; isf++ ){
for ( idiv=0; idiv<cfg->fw_ndiv; idiv++ ){
itmp = idiv + ( isf + i_sup * cfg->nsf ) * cfg->fw_ndiv;
bitcount += get_bstm(&index->fw[itmp],cfg->fw_nbit,sh);
}
}
}
for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
for ( isf=0; isf<cfg->nsf; isf++ ){
bitcount += get_bstm(&index->fw_alf[i_sup * cfg->nsf + isf],cf->FW_ARSW_BITS,sh);
}
}
return bitcount;
}
static int GetGainInfo(tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh )
{
int i_sup, iptop, isf;
int bitcount = 0;
for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
iptop = ( cfg->nsubg + 1 ) * i_sup;
bitcount += get_bstm(&index->pow[iptop], cf->GAIN_BITS,sh);
for ( isf=0; isf<cfg->nsubg; isf++ ){
bitcount += get_bstm(&index->pow[iptop+isf+1], cf->SUB_GAIN_BITS,sh);
}
}
return bitcount;
}
static int GetLspInfo( tvqConfInfo *cf, INDEX *index, sh_audio_t *sh )
{
int i_sup, itmp;
int bitcount = 0;
for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
bitcount += get_bstm(&index->lsp[i_sup][0], cf->LSP_BIT0,sh); /* pred. switch */
bitcount += get_bstm(&index->lsp[i_sup][1], cf->LSP_BIT1,sh); /* first stage */
for ( itmp=0; itmp<cf->LSP_SPLIT; itmp++ ){ /* second stage */
bitcount += get_bstm(&index->lsp[i_sup][itmp+2], cf->LSP_BIT2,sh);
}
}
return bitcount;
}
static int GetPpcInfo( tvqConfInfo *cf, INDEX *index, sh_audio_t *sh)
{
int idiv, i_sup;
int bitcount = 0;
vqf_priv_t*priv=sh->context;
for ( idiv=0; idiv<cf->N_DIV_P; idiv++ ){
bitcount += get_bstm(&(index->pls[idiv]), priv->bits_0[BLK_PPC][idiv],sh); /*CB0*/
bitcount += get_bstm(&(index->pls[idiv+cf->N_DIV_P]), priv->bits_1[BLK_PPC][idiv],sh);/*CB1*/
}
for (i_sup=0; i_sup<cf->N_CH; i_sup++){
bitcount += get_bstm(&(index->pit[i_sup]), cf->BASF_BIT,sh);
bitcount += get_bstm(&(index->pgain[i_sup]), cf->PGAIN_BIT,sh);
}
return bitcount;
}
static int GetEbcInfo( tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh)
{
int i_sup, isf, itmp;
int bitcount = 0;
for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
for ( isf=0; isf<cfg->nsf; isf++){
int indexSfOffset = isf * ( cfg->ncrb - cfg->ebc_crb_base ) - cfg->ebc_crb_base;
for ( itmp=cfg->ebc_crb_base; itmp<cfg->ncrb; itmp++ ){
bitcount += get_bstm(&index->bc[i_sup][itmp+indexSfOffset], cfg->ebc_bits,sh);
}
}
}
return bitcount;
}
static int vqf_read_frame(sh_audio_t *sh,INDEX *index)
{
/*--- Variables ---*/
tvqConfInfoSubBlock *cfg;
int variableBits;
int bitcount;
int numFixedBitsPerFrame = TvqGetNumFixedBitsPerFrame();
int btype;
vqf_priv_t *priv=sh->context;
/*--- Initialization ---*/
variableBits = 0;
bitcount = 0;
/*--- read block independent factors ---*/
/* Window type */
bitcount += get_bstm( &index->w_type, priv->cf.BITS_WTYPE, sh );
if ( TvqWtypeToBtype( index->w_type, &index->btype ) ) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error: unknown window type: %d\n", index->w_type);
return 0;
}
btype = index->btype;
/*--- read block dependent factors ---*/
cfg = &priv->cf.cfg[btype]; // set the block dependent paremeters table
bitcount += variableBits;
/* Interleaved vector quantization */
bitcount += GetVqInfo( cfg, priv->bits_0[btype], priv->bits_1[btype], variableBits, index, sh );
/* Bark-scale envelope */
bitcount += GetBseInfo( &priv->cf, cfg, index, sh );
/* Gain */
bitcount += GetGainInfo( &priv->cf, cfg, index, sh );
/* LSP */
bitcount += GetLspInfo( &priv->cf, index, sh );
/* PPC */
if ( cfg->ppc_enable ){
bitcount += GetPpcInfo( &priv->cf, index, sh );
}
/* Energy Balance Calibration */
if ( cfg->ebc_enable ){
bitcount += GetEbcInfo( &priv->cf, cfg, index, sh );
}
return bitcount == numFixedBitsPerFrame ? bitcount/8 : 0;
}
static void frtobuf_s16(float out[], /* Input --- input data frame */
short bufout[], /* Output --- output data buffer array */
unsigned frameSize, /* Input --- frame size */
unsigned numChannels) /* Input --- number of channels */
{
/*--- Variables ---*/
unsigned ismp, ich;
float *ptr;
float dtmp;
for ( ich=0; ich<numChannels; ich++ ){
ptr = out+ich*frameSize;
for ( ismp=0; ismp<frameSize; ismp++ ){
dtmp = ptr[ismp];
if ( dtmp >= 0. ) {
if ( dtmp > 32700. )
dtmp = 32700.;
bufout[ismp*numChannels+ich] = (short)(dtmp+0.5);
} else {
if ( dtmp < -32700. )
dtmp = -32700.;
bufout[ismp*numChannels+ich] = (short)(dtmp-0.5);
}
}
}
}
static void frtobuf_float(float out[], /* Input --- input data frame */
float bufout[], /* Output --- output data buffer array */
unsigned frameSize, /* Input --- frame size */
unsigned numChannels) /* Input --- number of channels */
{
/*--- Variables ---*/
unsigned ismp, ich;
float *ptr;
float dtmp;
for ( ich=0; ich<numChannels; ich++ ){
ptr = out+ich*frameSize;
for ( ismp=0; ismp<frameSize; ismp++ ){
dtmp = ptr[ismp];
if ( dtmp >= 0. ) {
if ( dtmp > 32700. )
dtmp = 32700.;
bufout[ismp*numChannels+ich] = dtmp/32767.;
} else {
if ( dtmp < -32700. )
dtmp = -32700.;
bufout[ismp*numChannels+ich] = dtmp/32767.;
}
}
}
}
int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
{
int l, len=0;
vqf_priv_t *priv=sh_audio->context;
while(len<minlen)
{
float out[priv->framesize*sh_audio->channels];
l=vqf_read_frame(sh_audio,&priv->index);
if(!l) break;
TvqDecodeFrame(&priv->index, out);
if (priv->skip_cnt) {
// Ingnore first two frames, replace them with silence
priv->skip_cnt--;
memset(buf, 0, priv->framesize*sh_audio->channels*sh_audio->samplesize);
} else {
if (sh_audio->sample_format == AF_FORMAT_S16_NE)
frtobuf_s16(out, (short *)buf, priv->framesize, sh_audio->channels);
else
frtobuf_float(out, (float *)buf, priv->framesize, sh_audio->channels);
}
len += priv->framesize*sh_audio->channels*sh_audio->samplesize;
buf += priv->framesize*sh_audio->channels*sh_audio->samplesize;
}
return len;
}

View File

@ -31,7 +31,6 @@
#include "stream/stream.h"
#include "libmpdemux/demuxer.h"
#include "libmpdemux/parse_es.h"
#include "codec-cfg.h"

View File

@ -39,7 +39,6 @@
extern const vd_functions_t mpcodecs_vd_null;
extern const vd_functions_t mpcodecs_vd_ffmpeg;
extern const vd_functions_t mpcodecs_vd_theora;
extern const vd_functions_t mpcodecs_vd_dshow;
extern const vd_functions_t mpcodecs_vd_dmo;
extern const vd_functions_t mpcodecs_vd_vfw;
@ -50,10 +49,7 @@ extern const vd_functions_t mpcodecs_vd_xanim;
extern const vd_functions_t mpcodecs_vd_mpng;
extern const vd_functions_t mpcodecs_vd_ijpg;
extern const vd_functions_t mpcodecs_vd_mtga;
extern const vd_functions_t mpcodecs_vd_sgi;
extern const vd_functions_t mpcodecs_vd_mpegpes;
extern const vd_functions_t mpcodecs_vd_realvid;
extern const vd_functions_t mpcodecs_vd_xvid;
extern const vd_functions_t mpcodecs_vd_libdv;
extern const vd_functions_t mpcodecs_vd_lzo;
extern const vd_functions_t mpcodecs_vd_qtvideo;
@ -65,9 +61,6 @@ extern const vd_functions_t mpcodecs_vd_qtvideo;
const vd_functions_t * const mpcodecs_vd_drivers[] = {
&mpcodecs_vd_null,
&mpcodecs_vd_ffmpeg,
#ifdef CONFIG_OGGTHEORA
&mpcodecs_vd_theora,
#endif
#ifdef CONFIG_WIN32DLL
&mpcodecs_vd_dshow,
&mpcodecs_vd_dmo,
@ -87,14 +80,9 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = {
&mpcodecs_vd_ijpg,
#endif
&mpcodecs_vd_mtga,
&mpcodecs_vd_sgi,
&mpcodecs_vd_mpegpes,
#ifdef CONFIG_REALCODECS
&mpcodecs_vd_realvid,
#endif
#ifdef CONFIG_XVID4
&mpcodecs_vd_xvid,
#endif
#ifdef CONFIG_LIBDV095
&mpcodecs_vd_libdv,
#endif

View File

@ -1,84 +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 "config.h"
#include "mp_msg.h"
#include "libmpdemux/mpeg_hdr.h"
#include "vd_internal.h"
static const vd_info_t info =
{
"MPEG 1/2 Video passthrough",
"mpegpes",
"A'rpi",
"A'rpi",
"for hw decoders"
};
LIBVD_EXTERN(mpegpes)
//#include "libmpdemux/parse_es.h"
#include "libvo/video_out.h"
// to set/get/query special features/parameters
static int control(sh_video_t *sh,int cmd,void* arg,...){
return CONTROL_UNKNOWN;
}
// init driver
static int init(sh_video_t *sh){
return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_MPEGPES);
}
// uninit driver
static void uninit(sh_video_t *sh){
}
// decode a frame
static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
mp_image_t* mpi;
static vo_mpegpes_t packet;
mp_mpeg_header_t picture;
const unsigned char *d = data;
if(len>10 && !d[0] && !d[1] && d[2]==1 && d[3]==0xB3) {
float old_aspect = sh->aspect;
int oldw = sh->disp_w, oldh = sh->disp_h;
mp_header_process_sequence_header(&picture, &d[4]);
sh->aspect = mpeg12_aspect_info(&picture);
sh->disp_w = picture.display_picture_width;
sh->disp_h = picture.display_picture_height;
if(sh->aspect != old_aspect || sh->disp_w != oldw || sh->disp_h != oldh) {
if(!mpcodecs_config_vo(sh, sh->disp_w,sh->disp_h,IMGFMT_MPEGPES))
return 0;
}
}
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, 0, sh->disp_w, sh->disp_h);
packet.data=data;
packet.size=len;
packet.timestamp=sh->timer*90000.0;
packet.id=0x1E0; //+sh_video->ds->id;
mpi->planes[0]=(uint8_t*)(&packet);
return mpi;
}

View File

@ -1,343 +0,0 @@
/*
* Copyright (c) 2003 Todd Kirby <slapcat@pacbell.net>
*
* 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 <libavutil/intreadwrite.h>
#include "config.h"
#include "mp_msg.h"
#include "mpbswap.h"
#include "vd_internal.h"
#define SGI_HEADER_LEN 512
#define SGI_MAGIC 474
#define SGI_GRAYSCALE_IMAGE 1
#define SGI_RGB_IMAGE 3
#define SGI_RGBA_IMAGE 4
#define OUT_PIXEL_STRIDE 3 /* RGB */
static const vd_info_t info =
{
"SGI Image decoder",
"sgi",
"Todd Kirby",
"Todd Kirby",
""
};
LIBVD_EXTERN(sgi)
typedef struct {
short magic;
char rle;
char bytes_per_channel;
unsigned short dimension;
unsigned short xsize;
unsigned short ysize;
unsigned short zsize;
} SGIInfo;
static unsigned int outfmt = IMGFMT_BGR24;
static unsigned short last_x = -1;
static unsigned short last_y = -1;
/* to set/get/query special features/parameters */
static int
control(sh_video_t* sh, int cmd, void *arg, ...)
{
switch (cmd)
{
case VDCTRL_QUERY_FORMAT:
if (*((unsigned int *) arg) == outfmt) {
return CONTROL_TRUE;
}
return CONTROL_FALSE;
}
return CONTROL_UNKNOWN;
}
/* init driver */
static int
init(sh_video_t *sh)
{
sh->context = calloc(1, sizeof(SGIInfo));
last_x = -1;
return 1;
}
/* uninit driver */
static void
uninit(sh_video_t *sh)
{
SGIInfo *info = sh->context;
free(info);
}
/* expand an rle row into a channel */
static void
expandrow(unsigned char *optr, unsigned char *iptr, int chan_offset)
{
unsigned char pixel, count;
optr += chan_offset;
while (1) {
pixel = *iptr++;
if (!(count = (pixel & 0x7f))) {
return;
}
if(pixel & 0x80) {
while (count--) {
*optr = *iptr;
optr += OUT_PIXEL_STRIDE;
iptr++;
}
} else {
pixel = *iptr++;
while (count--) {
*optr = pixel;
optr += OUT_PIXEL_STRIDE;
}
}
}
}
/* expand an rle row into all 3 channels.
a separate function for grayscale so we don't slow down the
more common case rgb function with a bunch of ifs. */
static void
expandrow_gs(unsigned char *optr, unsigned char *iptr)
{
unsigned char pixel, count;
while (1) {
pixel = *iptr++;
if (!(count = (pixel & 0x7f))) {
return;
}
if(pixel & 0x80) {
while (count--) {
optr[0] = *iptr;
optr[1] = *iptr;
optr[2] = *iptr;
optr += OUT_PIXEL_STRIDE;
iptr++;
}
} else {
pixel = *iptr++;
while (count--) {
optr[0] = pixel;
optr[1] = pixel;
optr[2] = pixel;
optr += OUT_PIXEL_STRIDE;
}
}
}
}
/* decode a run length encoded sgi image */
static void
decode_rle_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
{
unsigned char *rle_data, *dest_row;
uint32_t *starttab;
int y, z, ysize, zsize, chan_offset;
long start_offset;
ysize = info->ysize;
zsize = info->zsize;
/* rle offset table is right after the header */
starttab = (uint32_t*)(data + SGI_HEADER_LEN);
for (z = 0; z < zsize; z++) {
/* set chan_offset so RGB ends up BGR */
chan_offset = (zsize - 1) - z;
/* The origin for SGI images is the lower-left corner
so read scan lines from bottom to top */
for (y = ysize - 1; y >= 0; y--) {
dest_row = mpi->planes[0] + mpi->stride[0] * (ysize - 1 - y);
/* set start of next run (offsets are from start of header) */
start_offset = AV_RB32(&starttab[y + z * ysize]);
rle_data = &data[start_offset];
if(info->zsize == SGI_GRAYSCALE_IMAGE) {
expandrow_gs(dest_row, rle_data);
} else {
expandrow(dest_row, rle_data, chan_offset);
}
}
}
}
/* decode an sgi image */
static void
decode_uncompressed_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
{
unsigned char *src_row, *dest_row;
int x, y, z, xsize, ysize, zsize, chan_offset;
xsize = info->xsize;
ysize = info->ysize;
zsize = info->zsize;
/* skip header */
data += SGI_HEADER_LEN;
for (z = 0; z < zsize; z++) {
/* set row ptr to start of current plane */
src_row = data + (xsize * ysize * z);
/* set chan_offset for RGB -> BGR */
chan_offset = (zsize - 1) - z;
/* the origin for SGI images is the lower-left corner
so read scan lines from bottom to top. */
for (y = ysize - 1; y >= 0; y--) {
dest_row = mpi->planes[0] + mpi->stride[0] * y;
for (x = 0; x < xsize; x++) {
/* we only do 24 bit output so promote 8 bit pixels to 24 */
if (zsize == SGI_GRAYSCALE_IMAGE) {
/* write greyscale value into all channels */
dest_row[0] = src_row[x];
dest_row[1] = src_row[x];
dest_row[2] = src_row[x];
} else {
dest_row[chan_offset] = src_row[x];
}
dest_row += OUT_PIXEL_STRIDE;
}
/* move to next row of the current source plane */
src_row += xsize;
}
}
}
/* read sgi header fields */
static void
read_sgi_header(unsigned char *buf, SGIInfo *info)
{
/* sgi data is always stored in big endian byte order */
info->magic = AV_RB16(&buf[0]);
info->rle = buf[2];
info->bytes_per_channel = buf[3];
info->dimension = AV_RB16(&buf[4]);
info->xsize = AV_RB16(&buf[6]);
info->ysize = AV_RB16(&buf[8]);
info->zsize = AV_RB16(&buf[10]);
}
/* decode a frame */
static
mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
{
SGIInfo *info = sh->context;
unsigned char *data = raw;
mp_image_t *mpi;
if (len <= 0) {
return NULL; /* skip frame */
}
read_sgi_header(data, info);
/* make sure this is an SGI image file */
if (info->magic != SGI_MAGIC) {
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Bad magic number in image.\n");
return NULL;
}
/* check image depth */
if (info->bytes_per_channel != 1) {
mp_msg(MSGT_DECVIDEO, MSGL_INFO,
"Unsupported bytes per channel value %i.\n", info->bytes_per_channel);
return NULL;
}
/* check image dimension */
if (info->dimension != 2 && info->dimension != 3) {
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image dimension %i.\n",
info->dimension);
return NULL;
}
/* change rgba images to rgb so alpha channel will be ignored */
if (info->zsize == SGI_RGBA_IMAGE) {
info->zsize = SGI_RGB_IMAGE;
}
/* check image depth */
if (info->zsize != SGI_RGB_IMAGE && info->zsize != SGI_GRAYSCALE_IMAGE) {
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image depth.\n");
return NULL;
}
/* (re)init libvo if image size is changed */
if (last_x != info->xsize || last_y != info->ysize)
{
last_x = info->xsize;
last_y = info->ysize;
if (!mpcodecs_config_vo(sh, info->xsize, info->ysize, outfmt)) {
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Config vo failed:\n");
return NULL;
}
}
if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
info->xsize, info->ysize))) {
return NULL;
}
if (info->rle) {
decode_rle_sgi(info, data, mpi);
} else {
decode_uncompressed_sgi(info, data, mpi);
}
return mpi;
}

View File

@ -1,207 +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 <stdarg.h>
#include <assert.h>
#include <libavutil/intreadwrite.h>
#include "config.h"
#include "mp_msg.h"
#include "vd_internal.h"
static const vd_info_t info = {
"Theora/VP3",
"theora",
"David Kuehling",
"www.theora.org",
"Theora project's VP3 codec"
};
LIBVD_EXTERN(theora)
#include <theora/theora.h>
#define THEORA_NUM_HEADER_PACKETS 3
typedef struct theora_struct_st {
theora_state st;
theora_comment cc;
theora_info inf;
} theora_struct_t;
/** Convert Theora pixelformat to the corresponding IMGFMT_ */
static uint32_t theora_pixelformat2imgfmt(theora_pixelformat fmt){
switch(fmt) {
case OC_PF_420: return IMGFMT_YV12;
case OC_PF_422: return IMGFMT_422P;
case OC_PF_444: return IMGFMT_444P;
}
return 0;
}
// to set/get/query special features/parameters
static int control(sh_video_t *sh,int cmd,void* arg,...){
theora_struct_t *context = sh->context;
switch(cmd) {
case VDCTRL_QUERY_FORMAT:
if (*(int*)arg == theora_pixelformat2imgfmt(context->inf.pixelformat))
return CONTROL_TRUE;
return CONTROL_FALSE;
}
return CONTROL_UNKNOWN;
}
/*
* init driver
*/
static int init(sh_video_t *sh){
theora_struct_t *context = NULL;
uint8_t *extradata = (uint8_t *)(sh->bih + 1);
int extradata_size = sh->bih->biSize - sizeof(*sh->bih);
int errorCode = 0;
ogg_packet op;
int i;
context = calloc (sizeof (theora_struct_t), 1);
sh->context = context;
if (!context)
goto err_out;
theora_info_init(&context->inf);
theora_comment_init(&context->cc);
/* Read all header packets, pass them to theora_decode_header. */
for (i = 0; i < THEORA_NUM_HEADER_PACKETS; i++)
{
if (extradata_size > 2) {
op.bytes = AV_RB16(extradata);
op.packet = extradata + 2;
op.b_o_s = 1;
if (extradata_size < op.bytes + 2) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Theora header too small\n");
goto err_out;
}
extradata += op.bytes + 2;
extradata_size -= op.bytes + 2;
} else {
op.bytes = ds_get_packet (sh->ds, &op.packet);
op.b_o_s = 1;
}
if ( (errorCode = theora_decode_header (&context->inf, &context->cc, &op)) )
{
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Broken Theora header; errorCode=%i!\n", errorCode);
goto err_out;
}
}
/* now init codec */
errorCode = theora_decode_init (&context->st, &context->inf);
if (errorCode)
{
mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Theora decode init failed: %i \n", errorCode);
goto err_out;
}
if(sh->aspect==0.0 && context->inf.aspect_denominator!=0)
{
sh->aspect = ((double)context->inf.aspect_numerator * context->inf.width)/
((double)context->inf.aspect_denominator * context->inf.height);
}
mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Theora video init ok!\n");
mp_msg(MSGT_DECVIDEO,MSGL_INFO,"Frame: %dx%d, Picture %dx%d, Offset [%d,%d]\n", context->inf.width, context->inf.height, context->inf.frame_width, context->inf.frame_height, context->inf.offset_x, context->inf.offset_y);
return mpcodecs_config_vo (sh,context->inf.width,context->inf.height,theora_pixelformat2imgfmt(context->inf.pixelformat));
err_out:
free(context);
sh->context = NULL;
return 0;
}
/*
* uninit driver
*/
static void uninit(sh_video_t *sh)
{
theora_struct_t *context = sh->context;
if (context)
{
theora_info_clear(&context->inf);
theora_comment_clear(&context->cc);
theora_clear (&context->st);
free (context);
}
}
/*
* decode frame
*/
static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
{
theora_struct_t *context = sh->context;
int errorCode = 0;
ogg_packet op;
yuv_buffer yuv;
mp_image_t* mpi;
// no delayed frames
if (!data || !len)
return NULL;
memset (&op, 0, sizeof (op));
op.bytes = len;
op.packet = data;
op.granulepos = -1;
errorCode = theora_decode_packetin (&context->st, &op);
if (errorCode)
{
mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Theora decode packetin failed: %i \n",
errorCode);
return NULL;
}
errorCode = theora_decode_YUVout (&context->st, &yuv);
if (errorCode)
{
mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Theora decode YUVout failed: %i \n",
errorCode);
return NULL;
}
mpi = mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, 0, yuv.y_width, yuv.y_height);
if(!mpi) return NULL;
mpi->planes[0]=yuv.y;
mpi->stride[0]=yuv.y_stride;
mpi->planes[1]=yuv.u;
mpi->stride[1]=yuv.uv_stride;
mpi->planes[2]=yuv.v;
mpi->stride[2]=yuv.uv_stride;
return mpi;
}

View File

@ -1,393 +0,0 @@
/*
* - XviD 1.x decoder module for mplayer -
*
* Copyright(C) 2003 Marco Belli <elcabesa@inwind.it>
* 2003-2004 Edouard Gomez <ed.gomez@free.fr>
*
* 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.
*/
/*****************************************************************************
* Includes
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "mp_msg.h"
#include "vd_internal.h"
#include "m_option.h"
#include <xvid.h>
/*****************************************************************************
* Configuration options
****************************************************************************/
static int do_dr2 = 1;
static int filmeffect = 0;
static int lumadeblock = 0;
static int chromadeblock = 0;
static int lumadering = 0;
static int chromadering = 0;
const m_option_t xvid_dec_opts[] = {
{ "dr2", &do_dr2, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{ "nodr2", &do_dr2, CONF_TYPE_FLAG, 0, 1, 0, NULL},
{ "filmeffect", &filmeffect, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{ "deblock-luma", &lumadeblock, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{ "deblock-chroma", &chromadeblock, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{ "dering-luma", &lumadering, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{ "dering-chroma", &chromadering, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL}
};
/*****************************************************************************
* Module private data
****************************************************************************/
typedef struct {
int cs;
unsigned char img_type;
void* hdl;
mp_image_t* mpi;
int vo_initialized;
} priv_t;
/*****************************************************************************
* Module function helpers
****************************************************************************/
static float stats2aspect(xvid_dec_stats_t *stats);
/*****************************************************************************
* Video decoder API function definitions
****************************************************************************/
/*============================================================================
* control - to set/get/query special features/parameters
*==========================================================================*/
static int control(sh_video_t *sh,int cmd,void* arg,...)
{
return CONTROL_UNKNOWN;
}
/*============================================================================
* init - initialize the codec
*==========================================================================*/
static int init(sh_video_t *sh)
{
xvid_gbl_info_t xvid_gbl_info;
xvid_gbl_init_t xvid_ini;
xvid_dec_create_t dec_p;
priv_t* p;
int cs;
memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info_t));
xvid_gbl_info.version = XVID_VERSION;
memset(&xvid_ini, 0, sizeof(xvid_gbl_init_t));
xvid_ini.version = XVID_VERSION;
memset(&dec_p, 0, sizeof(xvid_dec_create_t));
dec_p.version = XVID_VERSION;
switch(sh->codec->outfmt[sh->outfmtidx]){
case IMGFMT_YV12:
/* We will use our own buffers, this speeds decoding avoiding
* frame memcpy's overhead */
cs = (do_dr2)?XVID_CSP_INTERNAL:XVID_CSP_USER;
break;
case IMGFMT_YUY2:
cs = XVID_CSP_YUY2;
break;
case IMGFMT_UYVY:
cs = XVID_CSP_UYVY;
break;
case IMGFMT_I420:
case IMGFMT_IYUV:
/* We will use our own buffers, this speeds decoding avoiding
* frame memcpy's overhead */
cs = (do_dr2)?XVID_CSP_INTERNAL:XVID_CSP_USER;
break;
case IMGFMT_BGR15:
cs = XVID_CSP_RGB555;
break;
case IMGFMT_BGR16:
cs = XVID_CSP_RGB565;
break;
case IMGFMT_BGR32:
cs = XVID_CSP_BGRA;
break;
case IMGFMT_YVYU:
cs = XVID_CSP_YVYU;
break;
default:
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Unsupported out_fmt: 0x%X\n",
sh->codec->outfmt[sh->outfmtidx]);
return 0;
}
/* Gather some information about the host library */
if(xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL) < 0) {
mp_msg(MSGT_DECVIDEO,MSGL_INFO, "xvid: could not get information about the library\n");
} else {
mp_msg(MSGT_DECVIDEO,MSGL_INFO, "xvid: using library version %d.%d.%d (build %s)\n",
XVID_VERSION_MAJOR(xvid_gbl_info.actual_version),
XVID_VERSION_MINOR(xvid_gbl_info.actual_version),
XVID_VERSION_PATCH(xvid_gbl_info.actual_version),
xvid_gbl_info.build);
}
/* Initialize the xvidcore library */
if(xvid_global(NULL, XVID_GBL_INIT, &xvid_ini, NULL))
return 0;
/* We use 0 width and height so xvidcore will resize its buffers
* if required. That allows this vd plugin to do resize on first
* VOL encountered (don't trust containers' width and height) */
dec_p.width = 0;
dec_p.height = 0;
/* Get a decoder instance */
if(xvid_decore(0, XVID_DEC_CREATE, &dec_p, NULL)<0) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "XviD init failed\n");
return 0;
}
p = malloc(sizeof(priv_t));
p->cs = cs;
p->hdl = dec_p.handle;
p->vo_initialized = 0;
sh->context = p;
switch(cs) {
case XVID_CSP_INTERNAL:
p->img_type = MP_IMGTYPE_EXPORT;
break;
case XVID_CSP_USER:
p->img_type = MP_IMGTYPE_STATIC;
break;
default:
p->img_type = MP_IMGTYPE_TEMP;
break;
}
return 1;
}
/*============================================================================
* uninit - close the codec
*==========================================================================*/
static void uninit(sh_video_t *sh){
priv_t* p = sh->context;
if(!p)
return;
xvid_decore(p->hdl,XVID_DEC_DESTROY, NULL, NULL);
free(p);
}
/*============================================================================
* decode - decode a frame from stream
*==========================================================================*/
static mp_image_t* decode(sh_video_t *sh, void* data, int len, int flags)
{
xvid_dec_frame_t dec;
xvid_dec_stats_t stats;
mp_image_t* mpi = NULL;
priv_t* p = sh->context;
if(!data || len <= 0)
return NULL;
memset(&dec,0,sizeof(xvid_dec_frame_t));
memset(&stats, 0, sizeof(xvid_dec_stats_t));
dec.version = XVID_VERSION;
stats.version = XVID_VERSION;
dec.bitstream = data;
dec.length = len;
dec.general |= XVID_LOWDELAY
/* XXX: if lowdelay is unset, and xvidcore internal buffers are
* used => crash. MUST FIX */
| (filmeffect ? XVID_FILMEFFECT : 0 )
| (lumadeblock ? XVID_DEBLOCKY : 0 )
| (chromadeblock ? XVID_DEBLOCKUV : 0 );
#if XVID_API >= XVID_MAKE_API(4,1)
dec.general |= (lumadering ? XVID_DEBLOCKY|XVID_DERINGY : 0 );
dec.general |= (chromadering ? XVID_DEBLOCKUV|XVID_DERINGUV : 0 );
#endif
dec.output.csp = p->cs;
/* Decoding loop because xvidcore may return VOL information for
* on the fly buffer resizing. In that case we must decode VOL,
* init VO, then decode the frame */
do {
int consumed;
/* If we don't know frame size yet, don't even try to request
* a buffer, we must loop until we find a VOL, so VO plugin
* is initialized and we can obviously output something */
if (p->vo_initialized) {
mpi = mpcodecs_get_image(sh, p->img_type,
MP_IMGFLAG_ACCEPT_STRIDE,
sh->disp_w, sh->disp_h);
if(p->cs != XVID_CSP_INTERNAL) {
dec.output.plane[0] = mpi->planes[0];
dec.output.plane[1] = mpi->planes[1];
dec.output.plane[2] = mpi->planes[2];
dec.output.stride[0] = mpi->stride[0];
dec.output.stride[1] = mpi->stride[1];
dec.output.stride[2] = mpi->stride[2];
}
}
/* Decode data */
consumed = xvid_decore(p->hdl, XVID_DEC_DECODE, &dec, &stats);
if (consumed < 0) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Decoding error\n");
return NULL;
}
/* Found a VOL information stats, if VO plugin is not initialized
* yet then do it now */
if (stats.type == XVID_TYPE_VOL && !p->vo_initialized) {
sh->aspect = stats2aspect(&stats);
if(!mpcodecs_config_vo(sh, stats.data.vol.width, stats.data.vol.height, IMGFMT_YV12))
return NULL;
/* Don't take this path twice */
p->vo_initialized = !p->vo_initialized;
}
/* Don't forget to update buffer position and buffer length */
dec.bitstream = (char *)dec.bitstream + consumed;
dec.length -= consumed;
} while ((stats.type == XVID_TYPE_VOL || stats.type == XVID_TYPE_NOTHING) && dec.length > 0);
/* There are two ways to get out of the decoding loop:
* - a frame has been returned
* - no more data in buffer and no frames returned */
/* If mpi is NULL, it proves nothing has been returned by the decoder
* so don't try to display internal buffers. */
if (mpi != NULL && p->cs == XVID_CSP_INTERNAL) {
mpi->planes[0] = dec.output.plane[0];
mpi->planes[1] = dec.output.plane[1];
mpi->planes[2] = dec.output.plane[2];
mpi->stride[0] = dec.output.stride[0];
mpi->stride[1] = dec.output.stride[1];
mpi->stride[2] = dec.output.stride[2];
}
/* If we got out the decoding loop because the buffer was empty and there was nothing
* to output yet, then just return NULL */
return (stats.type == XVID_TYPE_NOTHING) ? NULL : mpi;
}
/*****************************************************************************
* Helper functions
****************************************************************************/
/* Returns DAR value according to VOL's informations contained in stats
* param */
static float stats2aspect(xvid_dec_stats_t *stats)
{
if (stats->type == XVID_TYPE_VOL) {
float wpar;
float hpar;
float dar;
/* MPEG4 strem stores PAR (Pixel Aspect Ratio), mplayer uses
* DAR (Display Aspect Ratio)
*
* Both are related thanks to the equation:
* width
* DAR = ----- x PAR
* height
*
* As MPEG4 is so well designed (*cough*), VOL header carries
* both informations together -- lucky eh ? */
switch (stats->data.vol.par) {
case XVID_PAR_11_VGA: /* 1:1 vga (square), default if supplied PAR is not a valid value */
wpar = hpar = 1.0f;
break;
case XVID_PAR_43_PAL: /* 4:3 pal (12:11 625-line) */
wpar = 12;
hpar = 11;
break;
case XVID_PAR_43_NTSC: /* 4:3 ntsc (10:11 525-line) */
wpar = 10;
hpar = 11;
break;
case XVID_PAR_169_PAL: /* 16:9 pal (16:11 625-line) */
wpar = 16;
hpar = 11;
break;
case XVID_PAR_169_NTSC: /* 16:9 ntsc (40:33 525-line) */
wpar = 40;
hpar = 33;
break;
case XVID_PAR_EXT: /* extended par; use par_width, par_height */
wpar = stats->data.vol.par_width;
hpar = stats->data.vol.par_height;
break;
default:
wpar = hpar = 1.0f;
break;
}
dar = ((float)stats->data.vol.width*wpar);
dar /= ((float)stats->data.vol.height*hpar);
return dar;
}
return 0.0f;
}
/*****************************************************************************
* Module structure definition
****************************************************************************/
static const vd_info_t info =
{
"XviD 1.0 decoder",
"xvid",
"Marco Belli <elcabesa@inwind.it>, Edouard Gomez <ed.gomez@free.fr>",
"Marco Belli <elcabesa@inwind.it>, Edouard Gomez <ed.gomez@free.fr>",
"No Comment"
};
LIBVD_EXTERN(xvid)
/* Please do not change that tag comment.
* arch-tag: b7d654a5-76ea-4768-9713-2c791567fe7d mplayer xvid decoder module */

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) 2005 Nico Sabbi
*
* 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 "aac_hdr.h"
#include "libavutil/attributes.h"
/// \param srate (out) sample rate
/// \param num (out) number of audio frames in this ADTS frame
/// \return size of the ADTS frame in bytes
/// aac_parse_frames needs a buffer at least 8 bytes long
int aac_parse_frame(uint8_t *buf, int *srate, int *num)
{
int i = 0, sr, fl = 0, id av_unused;
static int srates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0};
if((buf[i] != 0xFF) || ((buf[i+1] & 0xF6) != 0xF0))
return 0;
id = (buf[i+1] >> 3) & 0x01; //id=1 mpeg2, 0: mpeg4
sr = (buf[i+2] >> 2) & 0x0F;
if(sr > 11)
return 0;
*srate = srates[sr];
fl = ((buf[i+3] & 0x03) << 11) | (buf[i+4] << 3) | ((buf[i+5] >> 5) & 0x07);
*num = (buf[i+6] & 0x02) + 1;
return fl;
}

View File

@ -1,26 +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_AAC_HDR_H
#define MPLAYER_AAC_HDR_H
#include <stdint.h>
int aac_parse_frame(uint8_t *buf, int *srate, int *num);
#endif /* MPLAYER_AAC_HDR_H */

View File

@ -1,260 +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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "parse_es.h"
#include "stheader.h"
#include "aac_hdr.h"
#include "ms_hdr.h"
typedef struct {
uint8_t *buf;
uint64_t size; /// amount of time of data packets pushed to demuxer->audio (in bytes)
float time; /// amount of time elapsed based upon samples_per_frame/sample_rate (in milliseconds)
float last_pts; /// last pts seen
int bitrate; /// bitrate computed as size/time
} aac_priv_t;
static int demux_aac_init(demuxer_t *demuxer)
{
aac_priv_t *priv;
priv = calloc(1, sizeof(aac_priv_t));
if(!priv)
return 0;
priv->buf = malloc(8);
if(!priv->buf)
{
free(priv);
return 0;
}
demuxer->priv = priv;
return 1;
}
static void demux_close_aac(demuxer_t *demuxer)
{
aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
if(!priv)
return;
free(priv->buf);
free(demuxer->priv);
return;
}
/// returns DEMUXER_TYPE_AAC if it finds 8 ADTS frames in 32768 bytes, 0 otherwise
static int demux_aac_probe(demuxer_t *demuxer)
{
int cnt = 0, c, len, srate, num;
off_t init, probed;
aac_priv_t *priv;
if(! demux_aac_init(demuxer))
{
mp_msg(MSGT_DEMUX, MSGL_ERR, "COULDN'T INIT aac_demux, exit\n");
return 0;
}
priv = (aac_priv_t *) demuxer->priv;
init = probed = stream_tell(demuxer->stream);
while(probed-init <= 32768 && cnt < 8)
{
c = 0;
while(c != 0xFF)
{
c = stream_read_char(demuxer->stream);
if(c < 0)
goto fail;
}
priv->buf[0] = 0xFF;
if(stream_read(demuxer->stream, &(priv->buf[1]), 7) < 7)
goto fail;
len = aac_parse_frame(priv->buf, &srate, &num);
if(len > 0)
{
cnt++;
stream_skip(demuxer->stream, len - 8);
}
probed = stream_tell(demuxer->stream);
}
stream_seek(demuxer->stream, init);
if(cnt < 8)
goto fail;
mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, INIT: %"PRIu64", PROBED: %"PRIu64", cnt: %d\n", init, probed, cnt);
return DEMUXER_TYPE_AAC;
fail:
mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, failed to detect an AAC stream\n");
return 0;
}
static demuxer_t* demux_aac_open(demuxer_t *demuxer)
{
sh_audio_t *sh;
sh = new_sh_audio(demuxer, 0);
sh->ds = demuxer->audio;
sh->format = mmioFOURCC('M', 'P', '4', 'A');
demuxer->audio->id = 0;
demuxer->audio->sh = sh;
demuxer->filepos = stream_tell(demuxer->stream);
return demuxer;
}
static int demux_aac_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
{
aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
demux_packet_t *dp;
int c1, c2, len, srate, num;
float tm = 0;
if(demuxer->stream->eof || (demuxer->movi_end && stream_tell(demuxer->stream) >= demuxer->movi_end))
return 0;
while(! demuxer->stream->eof)
{
c1 = c2 = 0;
while(c1 != 0xFF)
{
c1 = stream_read_char(demuxer->stream);
if(c1 < 0)
return 0;
}
c2 = stream_read_char(demuxer->stream);
if(c2 < 0)
return 0;
if((c2 & 0xF6) != 0xF0)
continue;
priv->buf[0] = (unsigned char) c1;
priv->buf[1] = (unsigned char) c2;
if(stream_read(demuxer->stream, &(priv->buf[2]), 6) < 6)
return 0;
len = aac_parse_frame(priv->buf, &srate, &num);
if(len > 0)
{
dp = new_demux_packet(len);
if(! dp)
{
mp_msg(MSGT_DEMUX, MSGL_ERR, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", len);
return 0;
}
memcpy(dp->buffer, priv->buf, 8);
stream_read(demuxer->stream, &(dp->buffer[8]), len-8);
if(srate)
tm = (float) (num * 1024.0/srate);
priv->last_pts += tm;
dp->pts = priv->last_pts;
//fprintf(stderr, "\nPTS: %.3f\n", dp->pts);
ds_add_packet(demuxer->audio, dp);
priv->size += len;
priv->time += tm;
priv->bitrate = (int) (priv->size / priv->time);
demuxer->filepos = stream_tell(demuxer->stream);
return len;
}
else
stream_skip(demuxer->stream, -6);
}
return 0;
}
//This is an almost verbatim copy of high_res_mp3_seek(), from demux_audio.c
static void demux_aac_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
{
aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
demux_stream_t *d_audio=demuxer->audio;
sh_audio_t *sh_audio=d_audio->sh;
float time;
ds_free_packs(d_audio);
time = (flags & SEEK_ABSOLUTE) ? rel_seek_secs - priv->last_pts : rel_seek_secs;
if(time < 0)
{
stream_seek(demuxer->stream, demuxer->movi_start);
time = priv->last_pts + time;
priv->last_pts = 0;
}
if(time > 0)
{
int len, nf, srate, num;
nf = time * sh_audio->samplerate/1024;
while(nf > 0)
{
if(stream_read(demuxer->stream,priv->buf, 8) < 8)
break;
len = aac_parse_frame(priv->buf, &srate, &num);
if(len <= 0)
{
stream_skip(demuxer->stream, -7);
continue;
}
stream_skip(demuxer->stream, len - 8);
priv->last_pts += (float) (num*1024.0/srate);
nf -= num;
}
}
}
const demuxer_desc_t demuxer_desc_aac = {
"AAC demuxer",
"aac",
"AAC",
"Nico Sabbi",
"Raw AAC files ",
DEMUXER_TYPE_AAC,
0, // unsafe autodetect
demux_aac_probe,
demux_aac_fill_buffer,
demux_aac_open,
demux_close_aac,
demux_aac_seek,
NULL
};

View File

@ -29,7 +29,6 @@
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "demux_ogg.h"
#include "aviheader.h"
extern const demuxer_desc_t demuxer_desc_avi_ni;
@ -862,38 +861,6 @@ static int avi_check_file(demuxer_t *demuxer)
}
static demuxer_t* demux_open_hack_avi(demuxer_t *demuxer)
{
struct MPOpts *opts = demuxer->opts;
sh_audio_t* sh_a;
demuxer = demux_open_avi(demuxer);
if(!demuxer) return NULL; // failed to open
sh_a = demuxer->audio->sh;
if(demuxer->audio->id != -2 && sh_a) {
#ifdef CONFIG_OGGVORBIS
// support for Ogg-in-AVI:
if(sh_a->format == 0xFFFE)
demuxer = init_avi_with_ogg(demuxer);
else if(sh_a->format == 0x674F) {
stream_t* s;
demuxer_t *od;
s = new_ds_stream(demuxer->audio);
od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL);
if(!demux_ogg_open(od)) {
mp_tmsg( MSGT_DEMUXER,MSGL_ERR,"Unable to open the Ogg demuxer.\n");
free_stream(s);
demuxer->audio->id = -2;
} else
demuxer = new_demuxers_demuxer(demuxer,od,demuxer);
}
#endif
}
return demuxer;
}
const demuxer_desc_t demuxer_desc_avi = {
"AVI demuxer",
"avi",
@ -904,7 +871,7 @@ const demuxer_desc_t demuxer_desc_avi = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer,
demux_open_hack_avi,
demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control
@ -920,7 +887,7 @@ const demuxer_desc_t demuxer_desc_avi_ni = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer_ni,
demux_open_hack_avi,
demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control
@ -936,7 +903,7 @@ const demuxer_desc_t demuxer_desc_avi_nini = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer_nini,
demux_open_hack_avi,
demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control

View File

@ -1,490 +0,0 @@
/*
* FILM file parser
* Copyright (C) 2002 Mike Melanson
*
* This demuxer handles FILM (a.k.a. CPK) files commonly found on Sega
* Saturn CD-ROM games. FILM files have also been found on 3DO games.
*
* details of the FILM file format can be found at:
* http://www.pcisys.net/~melanson/codecs/
*
* 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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
// chunk types found in a FILM file
#define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M')
#define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C')
#define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B')
typedef struct film_chunk_t
{
off_t chunk_offset;
int chunk_size;
unsigned int syncinfo1;
unsigned int syncinfo2;
float pts;
} film_chunk_t;
typedef struct film_data_t
{
unsigned int total_chunks;
unsigned int current_chunk;
film_chunk_t *chunks;
unsigned int chunks_per_second;
unsigned int film_version;
} film_data_t;
static void demux_seek_film(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
{
film_data_t *film_data = (film_data_t *)demuxer->priv;
int new_current_chunk=(flags&SEEK_ABSOLUTE)?0:film_data->current_chunk;
if(flags&SEEK_FACTOR)
new_current_chunk += rel_seek_secs * film_data->total_chunks; // 0..1
else
new_current_chunk += rel_seek_secs * film_data->chunks_per_second; // secs
mp_msg(MSGT_DECVIDEO, MSGL_INFO,"current, total chunks = %d, %d; seek %5.3f sec, new chunk guess = %d\n",
film_data->current_chunk, film_data->total_chunks,
rel_seek_secs, new_current_chunk);
// check if the new chunk number is valid
if (new_current_chunk < 0)
new_current_chunk = 0;
if ((unsigned int)new_current_chunk > film_data->total_chunks)
new_current_chunk = film_data->total_chunks - 1;
while (((film_data->chunks[new_current_chunk].syncinfo1 == 0xFFFFFFFF) ||
(film_data->chunks[new_current_chunk].syncinfo1 & 0x80000000)) &&
(new_current_chunk > 0))
new_current_chunk--;
film_data->current_chunk = new_current_chunk;
mp_msg(MSGT_DECVIDEO, MSGL_INFO," (flags = %X) actual new chunk = %d (syncinfo1 = %08X)\n",
flags, film_data->current_chunk, film_data->chunks[film_data->current_chunk].syncinfo1);
demuxer->video->pts=film_data->chunks[film_data->current_chunk].pts;
}
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_film_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
{
int i;
unsigned char byte_swap;
int cvid_size;
sh_video_t *sh_video = demuxer->video->sh;
sh_audio_t *sh_audio = demuxer->audio->sh;
film_data_t *film_data = (film_data_t *)demuxer->priv;
film_chunk_t film_chunk;
int length_fix_bytes;
demux_packet_t* dp;
// see if the end has been reached
if (film_data->current_chunk >= film_data->total_chunks)
return 0;
film_chunk = film_data->chunks[film_data->current_chunk];
// position stream and fetch chunk
stream_seek(demuxer->stream, film_chunk.chunk_offset);
// load the chunks manually (instead of using ds_read_packet()), since
// they require some adjustment
// (all ones in syncinfo1 indicates an audio chunk)
if (film_chunk.syncinfo1 == 0xFFFFFFFF)
{
if(demuxer->audio->id>=-1){ // audio not disabled
dp = new_demux_packet(film_chunk.chunk_size);
if (stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size) !=
film_chunk.chunk_size)
return 0;
dp->pts = film_chunk.pts;
dp->pos = film_chunk.chunk_offset;
// adjust the data before queuing it:
// 8-bit: signed -> unsigned
// 16-bit: big-endian -> little-endian
if (sh_audio->wf->wBitsPerSample == 8)
for (i = 0; i < film_chunk.chunk_size; i++)
dp->buffer[i] += 128;
else
for (i = 0; i < film_chunk.chunk_size; i += 2)
{
byte_swap = dp->buffer[i];
dp->buffer[i] = dp->buffer[i + 1];
dp->buffer[i + 1] = byte_swap;
}
/* for SegaSaturn .cpk file, translate audio data if stereo */
if (sh_audio->wf->nChannels == 2) {
if (sh_audio->wf->wBitsPerSample == 8) {
unsigned char* tmp = dp->buffer;
unsigned char buf[film_chunk.chunk_size];
for(i = 0; i < film_chunk.chunk_size/2; i++) {
buf[i*2] = tmp[i];
buf[i*2+1] = tmp[film_chunk.chunk_size/2+i];
}
memcpy( tmp, buf, film_chunk.chunk_size );
}
else {/* for 16bit */
unsigned short *tmp = (unsigned short *)dp->buffer;
unsigned short buf[film_chunk.chunk_size/2];
for(i = 0; i < film_chunk.chunk_size/4; i++) {
buf[i*2] = tmp[i];
buf[i*2+1] = tmp[film_chunk.chunk_size/4+i];
}
memcpy( tmp, buf, film_chunk.chunk_size );
}
}
// append packet to DS stream
ds_add_packet(demuxer->audio, dp);
}
}
else
{
// if the demuxer is dealing with CVID data, deal with it a special way
if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd'))
{
if (film_data->film_version)
length_fix_bytes = 2;
else
length_fix_bytes = 6;
// account for the fix bytes when allocating the buffer
dp = new_demux_packet(film_chunk.chunk_size - length_fix_bytes);
// these CVID data chunks have a few extra bytes; skip them
if (stream_read(demuxer->stream, dp->buffer, 10) != 10)
return 0;
stream_skip(demuxer->stream, length_fix_bytes);
if (stream_read(demuxer->stream, dp->buffer + 10,
film_chunk.chunk_size - (10 + length_fix_bytes)) !=
(film_chunk.chunk_size - (10 + length_fix_bytes)))
return 0;
dp->pts = film_chunk.pts;
dp->pos = film_chunk.chunk_offset;
dp->keyframe = film_chunk.syncinfo1 & 0x80000000;
// fix the CVID chunk size
cvid_size = film_chunk.chunk_size - length_fix_bytes;
dp->buffer[1] = (cvid_size >> 16) & 0xFF;
dp->buffer[2] = (cvid_size >> 8) & 0xFF;
dp->buffer[3] = (cvid_size >> 0) & 0xFF;
// append packet to DS stream
ds_add_packet(demuxer->video, dp);
}
else
{
ds_read_packet(demuxer->video, demuxer->stream, film_chunk.chunk_size,
film_chunk.pts,
film_chunk.chunk_offset, (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0);
}
}
film_data->current_chunk++;
return 1;
}
static demuxer_t* demux_open_film(demuxer_t* demuxer)
{
sh_video_t *sh_video = NULL;
sh_audio_t *sh_audio = NULL;
film_data_t *film_data;
film_chunk_t film_chunk;
int header_size;
unsigned int chunk_type;
unsigned int chunk_size;
unsigned int i;
unsigned int video_format;
int audio_channels;
int counting_chunks;
unsigned int total_audio_bytes = 0;
film_data = malloc(sizeof(film_data_t));
film_data->total_chunks = 0;
film_data->current_chunk = 0;
film_data->chunks = NULL;
film_data->chunks_per_second = 0;
// go back to the beginning
stream_reset(demuxer->stream);
stream_seek(demuxer->stream, 0);
// read the master chunk type
chunk_type = stream_read_fourcc(demuxer->stream);
// validate the chunk type
if (chunk_type != CHUNK_FILM)
{
mp_msg(MSGT_DEMUX, MSGL_ERR, "Not a FILM file\n");
free(film_data);
return NULL;
}
// get the header size, which implicitly points past the header and
// to the start of the data
header_size = stream_read_dword(demuxer->stream);
film_data->film_version = stream_read_fourcc(demuxer->stream);
demuxer->movi_start = header_size;
demuxer->movi_end = demuxer->stream->end_pos;
header_size -= 16;
mp_msg(MSGT_DEMUX, MSGL_HINT, "FILM version %.4s\n",
(char *)&film_data->film_version);
// skip to where the next chunk should be
stream_skip(demuxer->stream, 4);
// traverse through the header
while (header_size > 0)
{
// fetch the chunk type and size
chunk_type = stream_read_fourcc(demuxer->stream);
chunk_size = stream_read_dword(demuxer->stream);
header_size -= chunk_size;
switch (chunk_type)
{
case CHUNK_FDSC:
mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing FDSC chunk\n");
// fetch the video codec fourcc to see if there's any video
video_format = stream_read_fourcc(demuxer->stream);
if (video_format)
{
// create and initialize the video stream header
sh_video = new_sh_video(demuxer, 0);
demuxer->video->sh = sh_video;
sh_video->ds = demuxer->video;
sh_video->format = video_format;
sh_video->disp_h = stream_read_dword(demuxer->stream);
sh_video->disp_w = stream_read_dword(demuxer->stream);
mp_msg(MSGT_DECVIDEO, MSGL_V,
" FILM video: %d x %d\n", sh_video->disp_w,
sh_video->disp_h);
}
else
// skip height and width if no video
stream_skip(demuxer->stream, 8);
if(demuxer->audio->id<-1){
mp_msg(MSGT_DECVIDEO, MSGL_INFO,"chunk size = 0x%X \n",chunk_size);
stream_skip(demuxer->stream, chunk_size-12-8);
break; // audio disabled (or no soundcard)
}
// skip over unknown byte, but only if file had non-NULL version
if (film_data->film_version)
stream_skip(demuxer->stream, 1);
// fetch the audio channels to see if there's any audio
// don't do this if the file is a quirky file with NULL version
if (film_data->film_version)
{
audio_channels = stream_read_char(demuxer->stream);
if (audio_channels > 0)
{
// create and initialize the audio stream header
sh_audio = new_sh_audio(demuxer, 0);
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->wf = malloc(sizeof(*sh_audio->wf));
// uncompressed PCM format
sh_audio->wf->wFormatTag = 1;
sh_audio->format = 1;
sh_audio->wf->nChannels = audio_channels;
sh_audio->wf->wBitsPerSample = stream_read_char(demuxer->stream);
stream_skip(demuxer->stream, 1); // skip unknown byte
sh_audio->wf->nSamplesPerSec = stream_read_word(demuxer->stream);
sh_audio->wf->nAvgBytesPerSec =
sh_audio->wf->nSamplesPerSec * sh_audio->wf->wBitsPerSample
* sh_audio->wf->nChannels / 8;
stream_skip(demuxer->stream, 6); // skip the rest of the unknown
mp_msg(MSGT_DECVIDEO, MSGL_V,
" FILM audio: %d channels, %d bits, %d Hz\n",
sh_audio->wf->nChannels, 8 * sh_audio->wf->wBitsPerSample,
sh_audio->wf->nSamplesPerSec);
}
else
stream_skip(demuxer->stream, 10);
}
else
{
// otherwise, make some assumptions about the audio
// create and initialize the audio stream header
sh_audio = new_sh_audio(demuxer, 0);
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->wf = malloc(sizeof(*sh_audio->wf));
// uncompressed PCM format
sh_audio->wf->wFormatTag = 1;
sh_audio->format = 1;
sh_audio->wf->nChannels = 1;
sh_audio->wf->wBitsPerSample = 8;
sh_audio->wf->nSamplesPerSec = 22050;
sh_audio->wf->nAvgBytesPerSec =
sh_audio->wf->nSamplesPerSec * sh_audio->wf->wBitsPerSample
* sh_audio->wf->nChannels / 8;
mp_msg(MSGT_DECVIDEO, MSGL_V,
" FILM audio: %d channels, %d bits, %d Hz\n",
sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
sh_audio->wf->nSamplesPerSec);
}
break;
case CHUNK_STAB:
mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing STAB chunk\n");
if (sh_video)
{
sh_video->fps = stream_read_dword(demuxer->stream);
sh_video->frametime = 1.0 / sh_video->fps;
}
// fetch the number of chunks
film_data->total_chunks = stream_read_dword(demuxer->stream);
film_data->current_chunk = 0;
mp_msg(MSGT_DECVIDEO, MSGL_V,
" STAB chunk contains %d chunks\n", film_data->total_chunks);
// allocate enough entries for the chunk
film_data->chunks =
calloc(film_data->total_chunks, sizeof(film_chunk_t));
// build the chunk index
counting_chunks = 1;
for (i = 0; i < film_data->total_chunks; i++)
{
film_chunk = film_data->chunks[i];
film_chunk.chunk_offset =
demuxer->movi_start + stream_read_dword(demuxer->stream);
film_chunk.chunk_size = stream_read_dword(demuxer->stream);
film_chunk.syncinfo1 = stream_read_dword(demuxer->stream);
film_chunk.syncinfo2 = stream_read_dword(demuxer->stream);
// count chunks for the purposes of seeking
if (counting_chunks)
{
// if we're counting chunks, always count an audio chunk
if (film_chunk.syncinfo1 == 0xFFFFFFFF)
film_data->chunks_per_second++;
// if it's a video chunk, check if it's time to stop counting
else if ((film_chunk.syncinfo1 & 0x7FFFFFFF) >= sh_video->fps)
counting_chunks = 0;
else
film_data->chunks_per_second++;
}
// precalculate PTS
if (film_chunk.syncinfo1 == 0xFFFFFFFF)
{
if(demuxer->audio->id>=-1)
film_chunk.pts =
(float)total_audio_bytes / (float)sh_audio->wf->nAvgBytesPerSec;
total_audio_bytes += film_chunk.chunk_size;
}
else
film_chunk.pts =
(film_chunk.syncinfo1 & 0x7FFFFFFF) / sh_video->fps;
film_data->chunks[i] = film_chunk;
}
// in some FILM files (notably '1.09'), the length of the FDSC chunk
// follows different rules
if (chunk_size == (film_data->total_chunks * 16))
header_size -= 16;
break;
default:
mp_msg(MSGT_DEMUX, MSGL_ERR, "Unrecognized FILM header chunk: %08X\n",
chunk_type);
return NULL;
break;
}
}
demuxer->priv = film_data;
return demuxer;
}
static void demux_close_film(demuxer_t* demuxer) {
film_data_t *film_data = demuxer->priv;
if(!film_data)
return;
free(film_data->chunks);
free(film_data);
}
static int film_check_file(demuxer_t* demuxer)
{
int signature=stream_read_fourcc(demuxer->stream);
// check for the FILM file magic number
if(signature==mmioFOURCC('F', 'I', 'L', 'M'))
return DEMUXER_TYPE_FILM;
return 0;
}
const demuxer_desc_t demuxer_desc_film = {
"FILM/CPK demuxer for Sega Saturn CD-ROM games",
"film",
"FILM",
"Mike Melanson",
"",
DEMUXER_TYPE_FILM,
0, // unsafe autodetect (short signature)
film_check_file,
demux_film_fill_buffer,
demux_open_film,
demux_close_film,
demux_seek_film,
NULL
};

View File

@ -1,228 +0,0 @@
/*
* FLI file parser
* copyright (c) 2001 Mike Melanson
*
* 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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
typedef struct {
int num_frames;
int current_frame;
off_t *filepos;
unsigned int *frame_size;
} fli_frames_t;
static void demux_seek_fli(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
fli_frames_t *frames = (fli_frames_t *)demuxer->priv;
sh_video_t *sh_video = demuxer->video->sh;
int newpos=(flags&SEEK_ABSOLUTE)?0:frames->current_frame;
if(flags&SEEK_FACTOR){
// float 0..1
newpos+=rel_seek_secs*frames->num_frames;
} else {
// secs
newpos+=rel_seek_secs*sh_video->fps;
}
if(newpos<0) newpos=0; else
if(newpos>frames->num_frames) newpos=frames->num_frames;
frames->current_frame=newpos;
}
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_fli_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){
fli_frames_t *frames = (fli_frames_t *)demuxer->priv;
sh_video_t *sh_video = demuxer->video->sh;
// see if the end has been reached
if (frames->current_frame >= frames->num_frames)
return 0;
// fetch the frame from the file
// first, position the file properly since ds_read_packet() doesn't
// seem to do it, even though it takes a file offset as a parameter
stream_seek(demuxer->stream, frames->filepos[frames->current_frame]);
ds_read_packet(demuxer->video,
demuxer->stream,
frames->frame_size[frames->current_frame],
frames->current_frame/sh_video->fps,
frames->filepos[frames->current_frame],
0 /* what flags? -> demuxer.h (alex) */
);
// get the next frame ready
frames->current_frame++;
return 1;
}
static demuxer_t* demux_open_fli(demuxer_t* demuxer){
sh_video_t *sh_video = NULL;
fli_frames_t *frames = malloc(sizeof(fli_frames_t));
int frame_number;
int speed;
unsigned int frame_size;
int magic_number;
unsigned char * header;
// go back to the beginning
stream_reset(demuxer->stream);
stream_seek(demuxer->stream, 0);
header = calloc(1, sizeof(BITMAPINFOHEADER) + 128);
stream_read(demuxer->stream, header + sizeof(BITMAPINFOHEADER), 128);
stream_seek(demuxer->stream, 0);
demuxer->movi_start = 128;
demuxer->movi_end = stream_read_dword_le(demuxer->stream);
magic_number = stream_read_word_le(demuxer->stream);
if ((magic_number != 0xAF11) && (magic_number != 0xAF12))
{
mp_msg(MSGT_DEMUX, MSGL_ERR, "Bad/unknown magic number (%04x)\n",
magic_number);
free(header);
free(frames);
return NULL;
}
// fetch the number of frames
frames->num_frames = stream_read_word_le(demuxer->stream);
frames->current_frame = 0;
// allocate enough entries for the indices
// audit: num_frames is 16bit so it is safe against overflow
frames->filepos = malloc(frames->num_frames * sizeof(off_t));
frames->frame_size = malloc(frames->num_frames * sizeof(int));
// 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;
// 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;
// custom fourcc for internal MPlayer use
sh_video->format = mmioFOURCC('F', 'L', 'I', 'C');
sh_video->disp_w = stream_read_word_le(demuxer->stream);
sh_video->disp_h = stream_read_word_le(demuxer->stream);
// pass extradata to codec
sh_video->bih = (BITMAPINFOHEADER*)header;
sh_video->bih->biSize = sizeof(BITMAPINFOHEADER) + 128;
sh_video->bih->biWidth = sh_video->disp_w;
sh_video->bih->biHeight = sh_video->disp_h;
// skip the video depth and flags
stream_skip(demuxer->stream, 4);
// get the speed
speed = stream_read_word_le(demuxer->stream);
if (speed == 0)
speed = 1;
if (magic_number == 0xAF11)
speed *= 1000/70;
sh_video->fps = 1000 / speed;
sh_video->frametime = 1/sh_video->fps;
// build the frame index
stream_seek(demuxer->stream, demuxer->movi_start);
frame_number = 0;
while ((!stream_eof(demuxer->stream)) && (frame_number < frames->num_frames))
{
frames->filepos[frame_number] = stream_tell(demuxer->stream);
frame_size = stream_read_dword_le(demuxer->stream);
magic_number = stream_read_word_le(demuxer->stream);
stream_skip(demuxer->stream, frame_size - 6);
// if this chunk has the right magic number, index it
if ((magic_number == 0xF1FA) || (magic_number == 0xF5FA))
{
frames->frame_size[frame_number] = frame_size;
frame_number++;
}
}
// save the actual number of frames indexed
frames->num_frames = frame_number;
demuxer->priv = frames;
return demuxer;
}
static void demux_close_fli(demuxer_t* demuxer) {
fli_frames_t *frames = demuxer->priv;
if(!frames)
return;
free(frames->filepos);
free(frames->frame_size);
free(frames);
}
static int fli_check_file(demuxer_t* demuxer)
{
int id;
stream_seek(demuxer->stream, 4);
id=stream_read_word_le(demuxer->stream);
// check for the FLI file magic number
if((id==0xAF11) || (id==0xAF12))
return DEMUXER_TYPE_FLI;
return 0;
}
const demuxer_desc_t demuxer_desc_fli = {
"Autodesk FLIC demuxer",
"fli",
"FLI",
"Mike Melanson",
"Supports also some extensions",
DEMUXER_TYPE_FLI,
0, // unsafe autodetect (short signature)
fli_check_file,
demux_fli_fill_buffer,
demux_open_fli,
demux_close_fli,
demux_seek_fli,
NULL
};

View File

@ -1,385 +0,0 @@
/*
* LMLM4 MPEG4 Compression Card stream & file parser
* Copyright (C) 2003 Maxim Yevtyushkin <max@linuxmedialabs.com>
* based on SMJPEG file parser by Alex Beregszaszi
*
* 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 <string.h> /* strtok */
#include "config.h"
#include "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
typedef struct FrameInfo
{
ssize_t frameSize;
ssize_t paddingSize;
int frameType;
int channelNo;
} FrameInfo;
#define FRAMETYPE_I 0
#define FRAMETYPE_P 1
#define FRAMETYPE_B 2
#define FRAMETYPE_AUDIO_MPEG1L2 4
#define FRAMETYPE_AUDIO_ULAW 5
#define FRAMETYPE_AUDIO_ADPCM 6
#define PACKET_BLOCK_SIZE 0x00000200
#define PACKET_BLOCK_LAST 0x000001FF
#define PACKET_BLOCK_MASK 0xFFFFFE00
#define MAX_PACKET_SIZE 1048576 // 1 Mb
#define STREAM_START_CODE_SIZE 4
/*
// codes in MSB first
static unsigned int start_code [] =
{
0xB0010000, // VISUAL_OBJECT_SEQUENCE_START_CODE
0xB6010000, // VOP_START_CODE
0x04C4FDFF, // MPEG1LAYERII_START_CODE
0x00000000 // end of start codes list
};
*/
static int imeHeaderValid(FrameInfo *frame)
{
if ( frame->channelNo > 7 ||
frame->frameSize > MAX_PACKET_SIZE || frame->frameSize <= 0)
{
mp_msg(MSGT_DEMUX, MSGL_V,
"Invalid packet in LMLM4 stream: ch=%d size=%zd\n",
frame->channelNo, frame->frameSize);
return 0;
}
switch (frame->frameType) {
case FRAMETYPE_I:
case FRAMETYPE_P:
case FRAMETYPE_B:
case FRAMETYPE_AUDIO_MPEG1L2:
case FRAMETYPE_AUDIO_ULAW:
case FRAMETYPE_AUDIO_ADPCM:
break;
default:
mp_msg(MSGT_DEMUX, MSGL_V, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame->frameType);
return 0;
}
return 1;
}
/*
int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader)
{
void *data;
ssize_t imeHeaderSize = sizeof(IME6400Header);
ssize_t dataSize = sizeof(IME6400Header) * 3;
ssize_t ptr = imeHeaderSize * 2;
int errNo, startCodeNo;
off_t pos;
data = malloc(dataSize);
imeHeaderSwap(imeHeader);
memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize);
// printHex(data + imeHeaderSize, imeHeaderSize);
while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize)
{
// printHex(data + imeHeaderSize * 2, imeHeaderSize);
pos = stream_tell(demuxer->stream);
while (dataSize - ptr >= STREAM_START_CODE_SIZE) {
startCodeNo = 0;
while (start_code[startCodeNo])
{
if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match
{
memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize);
imeHeaderSwap(imeHeader);
if (imeHeaderValid(imeHeader))
{
stream_seek(demuxer->stream, pos - (dataSize - ptr));
free(data);
return 0;
}
}
startCodeNo++;
}
ptr++;
}
memcpy(data,data + imeHeaderSize, imeHeaderSize * 2);
ptr -= imeHeaderSize;
}
free(data);
return errNo;
}
*/
static int getFrame(demuxer_t *demuxer, FrameInfo *frameInfo)
{
unsigned int packetSize;
frameInfo->channelNo = stream_read_word(demuxer->stream);
frameInfo->frameType = stream_read_word(demuxer->stream);
packetSize=stream_read_dword(demuxer->stream);
if(stream_eof(demuxer->stream)){
frameInfo->frameSize = 0;
return 0;
}
frameInfo->frameSize = packetSize - 8; //sizeof(IME6400Header);
frameInfo->paddingSize = (packetSize & PACKET_BLOCK_LAST) ? PACKET_BLOCK_SIZE - (packetSize & PACKET_BLOCK_LAST) : 0;
mp_msg(MSGT_DEMUX, MSGL_DBG2, "typ: %d chan: %d size: %zd pad: %zd\n",
frameInfo->frameType,
frameInfo->channelNo,
frameInfo->frameSize,
frameInfo->paddingSize);
if(!imeHeaderValid(frameInfo)){
// skip this packet
stream_skip(demuxer->stream,PACKET_BLOCK_SIZE-8);
frameInfo->frameSize = 0;
return -1;
}
return 1;
}
static int lmlm4_check_file(demuxer_t* demuxer)
{
FrameInfo frameInfo;
unsigned int first;
mp_msg(MSGT_DEMUX, MSGL_V, "Checking for LMLM4 Stream Format\n");
if(getFrame(demuxer, &frameInfo)!=1){
mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format not found\n");
return 0;
}
first=stream_read_dword(demuxer->stream);
stream_skip(demuxer->stream,-12);
mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first=0x%08X\n",first);
switch(frameInfo.frameType){
case FRAMETYPE_AUDIO_MPEG1L2:
if( (first & 0xffe00000) != 0xffe00000 ){
mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not mpeg audio\n");
return 0;
}
if((4-((first>>17)&3))!=2){
mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not layer-2\n");
return 0;
}
if(((first>>10)&0x3)==3){
mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: invalid audio sampelrate\n");
return 0;
}
mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first packet is audio, header checks OK!\n");
break;
// TODO: add checks for video header too, for case of disabled audio
}
// stream_reset(demuxer->stream);
mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format found\n");
return DEMUXER_TYPE_LMLM4;
}
static int video = 0;
static int frames= 0;
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_lmlm4_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
{
FrameInfo frameInfo;
double pts;
int id=1;
int ret;
//hdr:
demux->filepos = stream_tell(demux->stream);
mp_msg(MSGT_DEMUX, MSGL_DBG2, "fpos = %"PRId64"\n", (int64_t)demux->filepos);
ret=getFrame(demux, &frameInfo);
if(ret<=0) return ret; // EOF/error
pts=demux->video->sh ? frames*((sh_video_t*)(demux->video->sh))->frametime : 0;
switch(frameInfo.frameType){
case FRAMETYPE_AUDIO_MPEG1L2:
mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Audio Packet\n");
if (!video)
{
stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize);
mp_msg(MSGT_DEMUX, MSGL_V, "Skip Audio Packet\n");
return -1; //goto hdr;
}
if(demux->audio->id==-1){
if(!demux->a_streams[id]) new_sh_audio(demux,id);
demux->audio->id=id;
demux->audio->sh=demux->a_streams[id];
((sh_audio_t*)(demux->audio->sh))->format=0x50; // mpeg audio layer 1/2
}
if(demux->audio->id==id)
ds_read_packet(demux->audio, demux->stream, frameInfo.frameSize,
pts, demux->filepos, 0);
else
stream_skip(demux->stream,frameInfo.frameSize);
break;
case FRAMETYPE_I:
if (!video) {
video = 1;
mp_dbg(MSGT_DEMUX, MSGL_DBG2, "First Video Packet\n");
}
case FRAMETYPE_P:
frames=(frames+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations
if (!video)
{
stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize);
mp_msg(MSGT_DEMUX, MSGL_V, "Skip Video P Packet\n");
return -1; //goto hdr;
}
mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Video Packet\n");
if(demux->video->id==-1){
if(!demux->v_streams[id]) new_sh_video(demux,id);
demux->video->id=id;
demux->video->sh=demux->v_streams[id];
((sh_video_t*)(demux->video->sh))->format=0x10000004; // mpeg4-ES
}
if(demux->video->id==id)
ds_read_packet(demux->video, demux->stream, frameInfo.frameSize,
pts, demux->filepos, 0);
break;
default:
stream_skip(demux->stream,frameInfo.frameSize);
}
stream_skip(demux->stream, frameInfo.paddingSize);
return 1;
}
static demuxer_t* demux_open_lmlm4(demuxer_t* demuxer){
sh_audio_t *sh_audio=NULL;
sh_video_t *sh_video=NULL;
#if 0
sh_video_t* sh_video;
sh_audio_t* sh_audio;
unsigned int htype = 0, hleng;
int i = 0;
sh_video = new_sh_video(demuxer, 0);
demuxer->video->sh = sh_video;
sh_video->ds = demuxer->video;
sh_video->disp_w = 640;
sh_video->disp_h = 480;
sh_video->format = mmioFOURCC('D','I','V','X');
sh_video->bih = calloc(1, sizeof(*sh_video->bih));
/* these are false values */
sh_video->bih->biSize = 40;
sh_video->bih->biWidth = sh_video->disp_w;
sh_video->bih->biHeight = sh_video->disp_h;
sh_video->bih->biPlanes = 3;
sh_video->bih->biBitCount = 16;
sh_video->bih->biCompression = sh_video->format;
sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h;
sh_audio = new_sh_audio(demuxer, 0);
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->wf = calloc(1, sizeof(*sh_audio->wf));
sh_audio->samplerate = 48000;
sh_audio->wf->wBitsPerSample = 16;
sh_audio->channels = 2;
sh_audio->format = 0x50;
sh_audio->wf->wFormatTag = sh_audio->format;
sh_audio->wf->nChannels = sh_audio->channels;
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels*
sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8;
sh_audio->wf->nBlockAlign = sh_audio->channels *2;
sh_audio->wf->cbSize = 0;
#endif
demuxer->seekable = 0;
if(!ds_fill_buffer(demuxer->video)){
mp_msg(MSGT_DEMUXER, MSGL_INFO, "LMLM4: %s",
mp_gtext("No video stream found.\n"));
demuxer->video->sh=NULL;
} else {
sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
}
if(demuxer->audio->id!=-2) {
if(!ds_fill_buffer(demuxer->audio)){
mp_msg(MSGT_DEMUXER, MSGL_INFO, "LMLM4: %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;
}
}
return demuxer;
}
static void demux_close_lmlm4(demuxer_t *demuxer)
{
// printf("Close LMLM4 Stream\n");
return;
}
const demuxer_desc_t demuxer_desc_lmlm4 = {
"LMLM4 MPEG4 Compression Card stream demuxer",
"lmlm4",
"RAW LMLM4",
"Maxim Yevtyushkin",
"",
DEMUXER_TYPE_LMLM4,
0, // unsafe autodetect
lmlm4_check_file,
demux_lmlm4_fill_buffer,
demux_open_lmlm4,
demux_close_lmlm4,
NULL,
NULL
};

File diff suppressed because it is too large Load Diff

View File

@ -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_MOV_H
#define MPLAYER_DEMUX_MOV_H
unsigned int store_ughvlc(unsigned char *s, unsigned int v);
#endif /* MPLAYER_DEMUX_MOV_H */

View File

@ -1,235 +0,0 @@
/*
* demuxer for Musepack v7 bitstream
* copyright (c) 2005 Reimar Doeffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>
*
* This code may be be relicensed under the terms of the GNU LGPL when it
* becomes part of the FFmpeg project (ffmpeg.org)
*
* 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 <string.h>
#include "mp_msg.h"
#include "libavutil/common.h"
#include "mpbswap.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#define HDR_SIZE (6 * 4)
typedef struct da_priv {
float last_pts;
float pts_per_packet;
uint32_t dword;
int pos;
float length;
} da_priv_t;
static uint32_t get_bits(da_priv_t* priv, stream_t* s, int bits) {
uint32_t out = priv->dword;
uint32_t mask = (1 << bits) - 1;
priv->pos += bits;
if (priv->pos < 32) {
out >>= (32 - priv->pos);
}
else {
stream_read(s, (void *)&priv->dword, 4);
priv->dword = le2me_32(priv->dword);
priv->pos -= 32;
if (priv->pos) {
out <<= priv->pos;
out |= priv->dword >> (32 - priv->pos);
}
}
return out & mask;
}
static int demux_mpc_check(demuxer_t* demuxer) {
stream_t *s = demuxer->stream;
uint8_t hdr[HDR_SIZE];
int i;
if (stream_read(s, hdr, HDR_SIZE) != HDR_SIZE)
return 0;
for (i = 0; i < 30000 && !s->eof; i++) {
if (hdr[0] == 'M' && hdr[1] == 'P' && hdr[2] == '+')
break;
memmove(hdr, &hdr[1], HDR_SIZE - 1);
stream_read(s, &hdr[HDR_SIZE - 1], 1);
}
if (hdr[0] != 'M' || hdr[1] != 'P' || hdr[2] != '+')
return 0;
demuxer->movi_start = stream_tell(s) - HDR_SIZE;
demuxer->movi_end = s->end_pos;
demuxer->priv = malloc(HDR_SIZE);
memcpy(demuxer->priv, hdr, HDR_SIZE);
return DEMUXER_TYPE_MPC;
}
static demuxer_t *demux_mpc_open(demuxer_t* demuxer) {
float seconds = 0;
stream_t *s = demuxer->stream;
sh_audio_t* sh_audio;
da_priv_t* priv = demuxer->priv;
sh_audio = new_sh_audio(demuxer,0);
{
char *wf = calloc(1, sizeof(WAVEFORMATEX) + HDR_SIZE);
char *header = &wf[sizeof(WAVEFORMATEX)];
const int freqs[4] = {44100, 48000, 37800, 32000};
int frames;
sh_audio->format = mmioFOURCC('M', 'P', 'C', ' ');
memcpy(header, priv, HDR_SIZE);
free(priv);
frames = header[4] | header[5] << 8 | header[6] << 16 | header[7] << 24;
sh_audio->wf = (WAVEFORMATEX *)wf;
sh_audio->wf->wFormatTag = sh_audio->format;
sh_audio->wf->nChannels = 2;
sh_audio->wf->nSamplesPerSec = freqs[header[10] & 3];
sh_audio->wf->nBlockAlign = 32 * 36;
sh_audio->wf->wBitsPerSample = 16;
seconds = 1152 * frames / (float)sh_audio->wf->nSamplesPerSec;
if (demuxer->movi_end > demuxer->movi_start && seconds > 1)
sh_audio->wf->nAvgBytesPerSec = (demuxer->movi_end - demuxer->movi_start) / seconds;
else
sh_audio->wf->nAvgBytesPerSec = 32 * 1024; // dummy to make mencoder not hang
sh_audio->wf->cbSize = HDR_SIZE;
demuxer->movi_start = stream_tell(s);
demuxer->movi_end = s->end_pos;
}
priv = malloc(sizeof(da_priv_t));
priv->last_pts = -1;
priv->pts_per_packet = (32 * 36) / (float)sh_audio->wf->nSamplesPerSec;
priv->length = seconds;
priv->dword = 0;
priv->pos = 32; // empty bit buffer
get_bits(priv, s, 8); // discard first 8 bits
demuxer->priv = priv;
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->samplerate = sh_audio->wf->nSamplesPerSec;
sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
sh_audio->audio.dwSampleSize = 0;
sh_audio->audio.dwScale = 32 * 36;
sh_audio->audio.dwRate = sh_audio->samplerate;
return demuxer;
}
static int demux_mpc_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
int l;
int bit_len;
demux_packet_t* dp;
sh_audio_t* sh_audio = ds->sh;
da_priv_t* priv = demux->priv;
stream_t* s = demux->stream;
sh_audio = ds->sh;
if (s->eof)
return 0;
bit_len = get_bits(priv, s, 20);
dp = new_demux_packet((bit_len + 7) / 8);
for (l = 0; l < (bit_len / 8); l++)
dp->buffer[l] = get_bits(priv, s, 8);
bit_len %= 8;
if (bit_len)
dp->buffer[l] = get_bits(priv, s, bit_len) << (8 - bit_len);
if (priv->last_pts < 0)
priv->last_pts = 0;
else
priv->last_pts += priv->pts_per_packet;
dp->pts = priv->last_pts;
ds_add_packet(ds, dp);
return 1;
}
static void demux_mpc_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
sh_audio_t* sh_audio = demuxer->audio->sh;
da_priv_t* priv = demuxer->priv;
stream_t* s = demuxer->stream;
float target = rel_seek_secs;
if (flags & SEEK_FACTOR)
target *= priv->length;
if (!(flags & SEEK_ABSOLUTE))
target += priv->last_pts;
if (target < priv->last_pts) {
stream_seek(s, demuxer->movi_start);
priv->pos = 32; // empty bit buffer
get_bits(priv, s, 8); // discard first 8 bits
priv->last_pts = 0;
}
while (target > priv->last_pts) {
int bit_len = get_bits(priv, s, 20);
if (bit_len > 32) {
stream_skip(s, bit_len / 32 * 4 - 4);
get_bits(priv, s, 32); // make sure dword is reloaded
}
get_bits(priv, s, bit_len % 32);
priv->last_pts += priv->pts_per_packet;
if (s->eof) break;
}
if (!sh_audio) return;
}
static void demux_close_mpc(demuxer_t* demuxer) {
da_priv_t* priv = demuxer->priv;
free(priv);
}
static int demux_mpc_control(demuxer_t *demuxer,int cmd, void *arg){
da_priv_t* priv = demuxer->priv;
switch (cmd) {
case DEMUXER_CTRL_GET_TIME_LENGTH:
if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
*((double *)arg) = priv->length;
return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_GET_PERCENT_POS:
if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
*((int *)arg) = priv->last_pts * 100 / priv->length;
return DEMUXER_CTRL_OK;
}
return DEMUXER_CTRL_NOTIMPL;
}
const demuxer_desc_t demuxer_desc_mpc = {
"Musepack demuxer",
"mpc",
"MPC",
"Reza Jelveh, Reimar Doeffinger",
"supports v7 bitstream only",
DEMUXER_TYPE_MPC,
0, // unsafe autodetect
demux_mpc_check,
demux_mpc_fill_buffer,
demux_mpc_open,
demux_close_mpc,
demux_mpc_seek,
demux_mpc_control
};

File diff suppressed because it is too large Load Diff

View File

@ -1,345 +0,0 @@
/*
* Nullsoft Streaming Video demuxer
* copyright (c) 2004 by Reza Jelveh <reza.jelveh@tuhh.de>
* Based on A'rpis G2 work
*
* seeking and PCM audio not yet supported
* PCM needs extra audio chunk "miniheader" parsing
*
* 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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
typedef struct {
float v_pts;
int video_pack_no;
unsigned int a_format;
unsigned int v_format;
unsigned char fps;
} nsv_priv_t;
#define HEADER_SEARCH_SIZE 256000
/**
* Seeking still to be implemented
*/
static void demux_seek_nsv ( demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags )
{
// seeking is not yet implemented
}
static int demux_nsv_fill_buffer ( demuxer_t *demuxer, demux_stream_t *ds )
{
unsigned char hdr[17];
// for the extra data
unsigned char aux[6];
int i_aux = 0;
// videolen = audio chunk length, audiolen = video chunk length
int videolen,audiolen;
sh_video_t *sh_video = demuxer->video->sh;
sh_audio_t *sh_audio = demuxer->audio->sh;
nsv_priv_t * priv = demuxer->priv;
// if the audio/video chunk has no new header the first 2 bytes will be discarded 0xBEEF
// or rather 0xEF 0xBE
stream_read(demuxer->stream,hdr,7);
if(stream_eof(demuxer->stream)) return 0;
// sometimes instead of 0xBEEF as described for the next audio/video chunk we get
// a whole new header
mp_dbg(MSGT_DEMUX, MSGL_DBG2, "demux_nsv: %08X %08X\n",
hdr[0]<<8|hdr[1], (unsigned int)stream_tell(demuxer->stream));
switch(hdr[0]<<8|hdr[1]) {
case 0x4E53:
if(hdr[2]==0x56 && hdr[3]==0x73){
// NSVs
// get the header since there is no more metaheader after the first one
// there is no more need to skip that
stream_read(demuxer->stream,hdr+7,17-7);
stream_read(demuxer->stream,hdr,7);
}
break;
case 0xEFBE:
break;
default:
mp_dbg(MSGT_DEMUX,MSGL_WARN,"demux_nsv: sync lost\n");
break;
}
if (sh_video)
priv->v_pts =demuxer->video->pts= priv->video_pack_no *
(float)sh_video->frametime;
else
priv->v_pts = priv->video_pack_no;
demuxer->filepos=stream_tell(demuxer->stream);
mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: %08X: %02X %02X | %02X %02X %02X | %02X %02X \n",
(int)demuxer->filepos, hdr[0],hdr[1],hdr[2],hdr[3],hdr[4],hdr[5],hdr[6]);
// read video:
videolen=(hdr[2]>>4)|(hdr[3]<<4)|(hdr[4]<<0xC);
//check if we got extra data like subtitles here
if( (hdr[2]&0x0f) != 0x0 ) {
stream_read( demuxer->stream, aux, 6);
i_aux = aux[0]|aux[1]<<8;
// We skip this extra data
stream_skip( demuxer->stream, i_aux );
i_aux+=6;
videolen -= i_aux;
}
// we need to return an empty packet when the
// video frame is empty otherwise the stream will fasten up
if(sh_video) {
if( (hdr[2]&0x0f) != 0x0 )
ds_read_packet(demuxer->video,demuxer->stream,videolen,priv->v_pts,demuxer->filepos-i_aux,0);
else
ds_read_packet(demuxer->video,demuxer->stream,videolen,priv->v_pts,demuxer->filepos,0);
}
else
stream_skip(demuxer->stream,videolen);
// read audio:
audiolen=(hdr[5])|(hdr[6]<<8);
// we need to return an empty packet when the
// audio frame is empty otherwise the stream will fasten up
if(sh_audio) {
ds_read_packet(demuxer->audio,demuxer->stream,audiolen,priv->v_pts,demuxer->filepos+videolen,0);
}
else
stream_skip(demuxer->stream,audiolen);
++priv->video_pack_no;
return 1;
}
static demuxer_t* demux_open_nsv ( demuxer_t* demuxer )
{
// last 2 bytes 17 and 18 are unknown but right after that comes the length
unsigned char hdr[17];
int videolen,audiolen;
unsigned char buf[10];
sh_video_t *sh_video = NULL;
sh_audio_t *sh_audio = NULL;
nsv_priv_t * priv = malloc(sizeof(nsv_priv_t));
demuxer->priv=priv;
priv->video_pack_no=0;
/* disable seeking yet to be fixed*/
demuxer->seekable = 0;
stream_read(demuxer->stream,hdr,4);
if(stream_eof(demuxer->stream)) return 0;
if(hdr[0]==0x4E && hdr[1]==0x53 && hdr[2]==0x56){
// NSV header!
if(hdr[3]==0x73){
// NSVs
stream_read(demuxer->stream,hdr+4,17-4);
}
if(hdr[3]==0x66){
// NSVf
int len=stream_read_dword_le(demuxer->stream);
// TODO: parse out metadata!!!!
stream_skip(demuxer->stream,len-8);
// NSVs
stream_read(demuxer->stream,hdr,17);
if (stream_eof(demuxer->stream) || strncmp(hdr, "NSVs", 4))
return 0;
}
// dummy debug message
mp_msg(MSGT_DEMUX,MSGL_V,"demux_nsv: Header: %.12s\n",hdr);
// bytes 8-11 audio codec fourcc
// PCM fourcc needs extra parsing for every audio chunk, yet to implement
if((demuxer->audio->id != -2) && strncmp(hdr+8,"NONE", 4)){//&&strncmp(hdr+8,"VLB ", 4)){
sh_audio = new_sh_audio ( demuxer, 0 );
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
sh_audio->format=mmioFOURCC(hdr[8],hdr[9],hdr[10],hdr[11]);
sh_audio->ds = demuxer->audio;
priv->a_format=mmioFOURCC(hdr[8],hdr[9],hdr[10],hdr[11]);
}
// store hdr fps
priv->fps=hdr[16];
if ((demuxer->video->id != -2) && strncmp(hdr+4,"NONE", 4)) {
/* 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;
/* 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;
// bytes 4-7 video codec fourcc
priv->v_format = sh_video->format=mmioFOURCC(hdr[4],hdr[5],hdr[6],hdr[7]);
// new video stream! parse header
sh_video->disp_w=hdr[12]|(hdr[13]<<8);
sh_video->disp_h=hdr[14]|(hdr[15]<<8);
sh_video->bih=calloc(1,sizeof(*sh_video->bih));
sh_video->bih->biSize=sizeof(*sh_video->bih);
sh_video->bih->biPlanes=1;
sh_video->bih->biBitCount=24;
sh_video->bih->biWidth=hdr[12]|(hdr[13]<<8);
sh_video->bih->biHeight=hdr[14]|(hdr[15]<<8);
memcpy(&sh_video->bih->biCompression,hdr+4,4);
sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3;
// here we search for the correct keyframe
// vp6 keyframe is when the 2nd byte of the vp6 header is
// 0x36 for VP61 and 0x46 for VP62
if((priv->v_format==mmioFOURCC('V','P','6','1')) ||
(priv->v_format==mmioFOURCC('V','P','6','2')) ||
(priv->v_format==mmioFOURCC('V','P','3','1'))) {
stream_read(demuxer->stream,buf,10);
if (((((priv->v_format>>16) & 0xff) == '6') && ((buf[8]&0x0e)!=0x06)) ||
((((priv->v_format>>16) & 0xff) == '3') && (buf[8]!=0x00 || buf[9]!=0x08))) {
mp_msg(MSGT_DEMUX,MSGL_V,"demux_nsv: searching %.4s keyframe...\n", (char*)&priv->v_format);
while(((((priv->v_format>>16) & 0xff) == '6') && ((buf[8]&0x0e)!=0x06)) ||
((((priv->v_format>>16) & 0xff) == '3') && (buf[8]!=0x00 || buf[9]!=0x08))){
mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: %.4s block skip.\n", (char*)&priv->v_format);
videolen=(buf[2]>>4)|(buf[3]<<4)|(buf[4]<<0xC);
audiolen=(buf[5])|(buf[6]<<8);
stream_skip(demuxer->stream, videolen+audiolen-3);
stream_read(demuxer->stream,buf,10);
if(stream_eof(demuxer->stream)) return 0;
if(buf[0]==0x4E){
mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: Got NSVs block.\n");
stream_skip(demuxer->stream,7);
stream_read(demuxer->stream,buf,10);
}
}
}
// data starts 10 bytes before current pos but later
// we seek 17 backwards
stream_skip(demuxer->stream,7);
}
switch(priv->fps){
case 0x80:
sh_video->fps=30;
break;
case 0x81:
sh_video->fps=(float)30000.0/1001.0;
break;
case 0x82:
sh_video->fps=25;
break;
case 0x83:
sh_video->fps=(float)24000.0/1001.0;
break;
case 0x85:
sh_video->fps=(float)15000.0/1001.0;
break;
case 0x89:
sh_video->fps=(float)10000.0/1001.0;
break;
default:
sh_video->fps = (float)priv->fps;
}
sh_video->frametime = (float)1.0 / (float)sh_video->fps;
}
}
// seek to start of NSV header
stream_seek(demuxer->stream,stream_tell(demuxer->stream)-17);
return demuxer;
}
static int nsv_check_file ( demuxer_t* demuxer )
{
uint32_t hdr = 0;
int i;
mp_msg ( MSGT_DEMUX, MSGL_V, "Checking for Nullsoft Streaming Video\n" );
for (i = 0; i < HEADER_SEARCH_SIZE; i++) {
uint8_t c = stream_read_char(demuxer->stream);
if (stream_eof(demuxer->stream))
return 0;
if (hdr == mmioFOURCC('s', 'V', 'S', 'N') ||
(hdr == mmioFOURCC('f', 'V', 'S', 'N') && !c)) {
stream_seek(demuxer->stream,stream_tell(demuxer->stream)-5);
return DEMUXER_TYPE_NSV;
}
hdr = (hdr << 8) | c;
}
return 0;
}
static void demux_close_nsv(demuxer_t* demuxer) {
nsv_priv_t* priv = demuxer->priv;
free(priv);
}
const demuxer_desc_t demuxer_desc_nsv = {
"NullsoftVideo demuxer",
"nsv",
"Nullsoft Streaming Video",
"Reza Jelveh",
"nsv and nsa streaming files",
DEMUXER_TYPE_NSV,
0, // safe but expensive autodetect
nsv_check_file,
demux_nsv_fill_buffer,
demux_open_nsv,
demux_close_nsv,
demux_seek_nsv,
NULL
};

View File

@ -1,321 +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 "config.h"
#include "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#include <libnut.h>
typedef struct {
int last_pts; // FIXME
nut_context_tt * nut;
nut_stream_header_tt * s;
} nut_priv_tt;
static size_t mp_read(void * h, size_t len, uint8_t * buf) {
stream_t * stream = (stream_t*)h;
if(stream_eof(stream)) return 0;
//len = MIN(len, 5);
return stream_read(stream, buf, len);
}
static int mp_eof(void * h) {
stream_t * stream = (stream_t*)h;
if(stream_eof(stream)) return 1;
return 0;
}
static off_t mp_seek(void * h, long long pos, int whence) {
stream_t * stream = (stream_t*)h;
if (stream->end_pos < stream_tell(stream))
stream->end_pos = stream_tell(stream);
if (whence == SEEK_CUR) pos += stream_tell(stream);
else if (whence == SEEK_END) pos += stream->end_pos;
else if (whence != SEEK_SET) return -1;
if (pos < stream->end_pos && stream->eof) stream_reset(stream);
if (stream_seek(stream, pos) == 0) return -1;
return pos;
}
#define ID_STRING "nut/multimedia container"
#define ID_LENGTH (strlen(ID_STRING) + 1)
static int nut_check_file(demuxer_t * demuxer) {
uint8_t buf[ID_LENGTH];
if (stream_read(demuxer->stream, buf, ID_LENGTH) != ID_LENGTH) return 0;
if (memcmp(buf, ID_STRING, ID_LENGTH)) return 0;
stream_seek(demuxer->stream, 0);
return DEMUXER_TYPE_NUT;
}
static demuxer_t * demux_open_nut(demuxer_t * demuxer) {
nut_demuxer_opts_tt dopts = {
.input = {
.priv = demuxer->stream,
.seek = mp_seek,
.read = mp_read,
.eof = mp_eof,
.file_pos = stream_tell(demuxer->stream),
},
.alloc = { .malloc = NULL },
.read_index = index_mode,
.cache_syncpoints = 1,
};
nut_priv_tt * priv = demuxer->priv = calloc(1, sizeof(nut_priv_tt));
nut_context_tt * nut = priv->nut = nut_demuxer_init(&dopts);
nut_stream_header_tt * s;
int ret;
int i;
while ((ret = nut_read_headers(nut, &s, NULL)) == NUT_ERR_EAGAIN);
if (ret) {
mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret));
return NULL;
}
priv->s = s;
for (i = 0; s[i].type != -1 && i < 2; i++) switch(s[i].type) {
case NUT_AUDIO_CLASS: {
WAVEFORMATEX *wf =
calloc(sizeof(*wf) +
s[i].codec_specific_len, 1);
sh_audio_t* sh_audio = new_sh_audio(demuxer, i);
int j;
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "nut", i);
sh_audio->wf= wf; sh_audio->ds = demuxer->audio;
sh_audio->audio.dwSampleSize = 0; // FIXME
sh_audio->audio.dwScale = s[i].time_base.num;
sh_audio->audio.dwRate = s[i].time_base.den;
sh_audio->format = 0;
for (j = 0; j < s[i].fourcc_len && j < 4; j++)
sh_audio->format |= s[i].fourcc[j]<<(j*8);
sh_audio->channels = s[i].channel_count;
sh_audio->samplerate =
s[i].samplerate_num / s[i].samplerate_denom;
sh_audio->i_bps = 0; // FIXME
wf->wFormatTag = sh_audio->format;
wf->nChannels = s[i].channel_count;
wf->nSamplesPerSec =
s[i].samplerate_num / s[i].samplerate_denom;
wf->nAvgBytesPerSec = 0; // FIXME
wf->nBlockAlign = 0; // FIXME
wf->wBitsPerSample = 0; // FIXME
wf->cbSize = s[i].codec_specific_len;
if (s[i].codec_specific_len)
memcpy(wf + 1, s[i].codec_specific,
s[i].codec_specific_len);
demuxer->audio->id = i;
demuxer->audio->sh= demuxer->a_streams[i];
break;
}
case NUT_VIDEO_CLASS: {
BITMAPINFOHEADER * bih =
calloc(sizeof(*bih) +
s[i].codec_specific_len, 1);
sh_video_t * sh_video = new_sh_video(demuxer, i);
int j;
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "nut", i);
sh_video->bih = bih;
sh_video->ds = demuxer->video;
sh_video->disp_w = s[i].width;
sh_video->disp_h = s[i].height;
sh_video->video.dwScale = s[i].time_base.num;
sh_video->video.dwRate = s[i].time_base.den;
sh_video->fps = sh_video->video.dwRate/
(float)sh_video->video.dwScale;
sh_video->frametime = 1./sh_video->fps;
sh_video->format = 0;
for (j = 0; j < s[i].fourcc_len && j < 4; j++)
sh_video->format |= s[i].fourcc[j]<<(j*8);
if (!s[i].sample_height) sh_video->aspect = 0;
else sh_video->aspect =
s[i].sample_width / (float)s[i].sample_height;
sh_video->i_bps = 0; // FIXME
bih->biSize = sizeof(*bih) +
s[i].codec_specific_len;
bih->biWidth = s[i].width;
bih->biHeight = s[i].height;
bih->biBitCount = 0; // FIXME
bih->biSizeImage = 0; // FIXME
bih->biCompression = sh_video->format;
if (s[i].codec_specific_len)
memcpy(bih + 1, s[i].codec_specific,
s[i].codec_specific_len);
demuxer->video->id = i;
demuxer->video->sh = demuxer->v_streams[i];
break;
}
}
return demuxer;
}
static int demux_nut_fill_buffer(demuxer_t * demuxer, demux_stream_t * dsds) {
nut_priv_tt * priv = demuxer->priv;
nut_context_tt * nut = priv->nut;
demux_packet_t *dp;
demux_stream_t *ds;
nut_packet_tt pd;
int ret;
double pts;
demuxer->filepos = stream_tell(demuxer->stream);
if (stream_eof(demuxer->stream)) return 0;
while ((ret = nut_read_next_packet(nut, &pd)) == NUT_ERR_EAGAIN);
if (ret) {
if (ret != NUT_ERR_EOF)
mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
nut_error(ret));
return 0; // fatal error
}
pts = (double)pd.pts * priv->s[pd.stream].time_base.num /
priv->s[pd.stream].time_base.den;
if (pd.stream == demuxer->audio->id) {
ds = demuxer->audio;
}
else if (pd.stream == demuxer->video->id) {
ds = demuxer->video;
}
else {
uint8_t buf[pd.len];
while ((ret = nut_read_frame(nut, &pd.len, buf)) == NUT_ERR_EAGAIN);
if (ret) {
mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
nut_error(ret));
return 0; // fatal error
}
return 1;
}
if (pd.stream == 0) priv->last_pts = pd.pts;
dp = new_demux_packet(pd.len);
dp->pts = pts;
dp->pos = demuxer->filepos;
dp->keyframe = pd.flags & NUT_FLAG_KEY;
{int len = pd.len;
while ((ret = nut_read_frame(nut, &len, dp->buffer + pd.len-len)) == NUT_ERR_EAGAIN);
}
if (ret) {
mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
nut_error(ret));
return 0; // fatal error
}
ds_add_packet(ds, dp); // append packet to DS stream
return 1;
}
static void demux_seek_nut(demuxer_t * demuxer, float time_pos, float audio_delay, int flags) {
nut_context_tt * nut = ((nut_priv_tt*)demuxer->priv)->nut;
nut_priv_tt * priv = demuxer->priv;
int nutflags = 0;
int ret;
const int tmp[] = { 0, -1 };
if (!(flags & SEEK_ABSOLUTE)) {
nutflags |= 1; // relative
if (time_pos > 0) nutflags |= 2; // forwards
}
if (flags & SEEK_FACTOR)
time_pos *= priv->s[0].max_pts *
(double)priv->s[0].time_base.num /
priv->s[0].time_base.den;
while ((ret = nut_seek(nut, time_pos, nutflags, tmp)) == NUT_ERR_EAGAIN);
priv->last_pts = -1;
if (ret) mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret));
demuxer->filepos = stream_tell(demuxer->stream);
}
static int demux_control_nut(demuxer_t * demuxer, int cmd, void * arg) {
nut_priv_tt * priv = demuxer->priv;
switch (cmd) {
case DEMUXER_CTRL_GET_TIME_LENGTH:
*((double *)arg) = priv->s[0].max_pts *
(double)priv->s[0].time_base.num /
priv->s[0].time_base.den;
return DEMUXER_CTRL_OK;
case DEMUXER_CTRL_GET_PERCENT_POS:
if (priv->s[0].max_pts == 0 || priv->last_pts == -1)
return DEMUXER_CTRL_DONTKNOW;
*((int *)arg) = priv->last_pts * 100 /
(double)priv->s[0].max_pts;
return DEMUXER_CTRL_OK;
default:
return DEMUXER_CTRL_NOTIMPL;
}
}
static void demux_close_nut(demuxer_t *demuxer) {
nut_priv_tt * priv = demuxer->priv;
if (!priv) return;
nut_demuxer_uninit(priv->nut);
free(demuxer->priv);
demuxer->priv = NULL;
}
const demuxer_desc_t demuxer_desc_nut = {
"NUT demuxer",
"nut",
"libnut",
"Oded Shimon (ods15)",
"NUT demuxer, requires libnut",
DEMUXER_TYPE_NUT,
1, // safe check demuxer
nut_check_file,
demux_nut_fill_buffer,
demux_open_nut,
demux_close_nut,
demux_seek_nut,
demux_control_nut
};

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +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_OGG_H
#define MPLAYER_DEMUX_OGG_H
#include "demuxer.h"
int demux_ogg_open(demuxer_t *demuxer);
demuxer_t *init_avi_with_ogg(demuxer_t *demuxer);
#endif /* MPLAYER_DEMUX_OGG_H */

View File

@ -1,536 +0,0 @@
/*
* demuxer for PVA files, such as the ones produced by software to manage
* DVB boards like the Hauppauge WinTV DVBs
* copyright (c) 2002 Matteo Giani
*
* Uses info from the PVA file specifications found at
* http://www.technotrend.de/download/av_format_v1.pdf
*
* 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.
*/
/* WARNING: Quite a hack was required in order to get files by MultiDec
* played back correctly. If it breaks anything else, just comment out
* the #define below and it will not be compiled in. */
#define DEMUX_PVA_MULTIDEC_HACK
#define PVA_NEW_PREBYTES_CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
/*
* #defines below taken from PVA spec (see URL above)
*/
#define PVA_MAX_VIDEO_PACK_LEN 6*1024
#define VIDEOSTREAM 0x01
#define MAINAUDIOSTREAM 0x02
typedef struct {
off_t offset;
long size;
uint8_t type;
uint8_t is_packet_start;
float pts;
} pva_payload_t;
typedef struct {
float last_audio_pts;
float last_video_pts;
#ifdef PVA_NEW_PREBYTES_CODE
float video_pts_after_prebytes;
long video_size_after_prebytes;
uint8_t prebytes_delivered;
#endif
uint8_t just_synced;
uint8_t synced_stream_id;
} pva_priv_t;
static int pva_sync(demuxer_t * demuxer)
{
uint8_t buffer[5]={0,0,0,0,0};
int count;
pva_priv_t * priv = (pva_priv_t *) demuxer->priv;
/* This function is used to find the next nearest PVA packet start after a seek, since a PVA file
* is not indexed.
* The just_synced field is in the priv structure so that pva_get_payload knows pva_sync
* has already read (part of) the PVA header. This way we can avoid to seek back and (hopefully)
* be able to read from pipes and such.
*/
for(count=0 ; count<PVA_MAX_VIDEO_PACK_LEN && !demuxer->stream->eof && !priv->just_synced ; count++)
{
buffer[0]=buffer[1];
buffer[1]=buffer[2];
buffer[2]=buffer[3];
buffer[3]=buffer[4];
buffer[4]=stream_read_char(demuxer->stream);
/*
* Check for a PVA packet beginning sequence: we check both the "AV" word at the
* very beginning and the "0x55" reserved byte (which is unused and set to 0x55 by spec)
*/
if(buffer[0]=='A' && buffer[1] == 'V' && buffer[4] == 0x55) priv->just_synced=1;
//printf("demux_pva: pva_sync(): current offset= %ld\n",stream_tell(demuxer->stream));
}
if(priv->just_synced)
{
priv->synced_stream_id=buffer[2];
return 1;
}
else
{
return 0;
}
}
static int pva_check_file(demuxer_t * demuxer)
{
uint8_t buffer[5]={0,0,0,0,0};
mp_msg(MSGT_DEMUX, MSGL_V, "Checking for PVA\n");
stream_read(demuxer->stream,buffer,5);
if(buffer[0]=='A' && buffer[1] == 'V' && buffer[4] == 0x55)
{
mp_msg(MSGT_DEMUX,MSGL_DBG2, "Success: PVA\n");
return DEMUXER_TYPE_PVA;
}
else
{
mp_msg(MSGT_DEMUX,MSGL_DBG2, "Failed: PVA\n");
return 0;
}
}
static demuxer_t * demux_open_pva (demuxer_t * demuxer)
{
sh_video_t *sh_video = new_sh_video(demuxer,0);
sh_audio_t *sh_audio = new_sh_audio(demuxer,0);
pva_priv_t * priv;
stream_reset(demuxer->stream);
stream_seek(demuxer->stream,0);
priv=malloc(sizeof(pva_priv_t));
if(demuxer->stream->type!=STREAMTYPE_FILE) demuxer->seekable=0;
else demuxer->seekable=1;
demuxer->priv=priv;
memset(demuxer->priv,0,sizeof(pva_priv_t));
if(!pva_sync(demuxer))
{
mp_msg(MSGT_DEMUX,MSGL_ERR,"Not a PVA file.\n");
return NULL;
}
//printf("priv->just_synced %s after initial sync!\n",priv->just_synced?"set":"UNSET");
demuxer->video->sh=sh_video;
//printf("demuxer->stream->end_pos= %d\n",demuxer->stream->end_pos);
mp_msg(MSGT_DEMUXER,MSGL_INFO,"Opened PVA demuxer...\n");
/*
* Audio and Video codecs:
* the PVA spec only allows MPEG2 video and MPEG layer II audio. No need to check the formats then.
* Moreover, there would be no way to do that since the PVA stream format has no fields to describe
* the used codecs.
*/
sh_video->format=0x10000002;
sh_video->ds=demuxer->video;
/*
printf("demuxer->video->id==%d\n",demuxer->video->id);
printf("demuxer->audio->id==%d\n",demuxer->audio->id);
*/
demuxer->audio->id = 0;
demuxer->audio->sh=sh_audio;
sh_audio->format=0x50;
sh_audio->ds=demuxer->audio;
demuxer->movi_start=0;
demuxer->movi_end=demuxer->stream->end_pos;
priv->last_video_pts=-1;
priv->last_audio_pts=-1;
return demuxer;
}
static int pva_get_payload(demuxer_t *d, pva_payload_t *payload)
{
uint8_t flags,pes_head_len;
uint16_t pack_size;
off_t pva_payload_start;
unsigned char buffer[256];
#ifndef PVA_NEW_PREBYTES_CODE
demux_packet_t * dp; //hack to deliver the preBytes (see PVA doc)
#endif
pva_priv_t * priv;
if(d==NULL)
{
mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: pva_get_payload got passed a NULL pointer!\n");
return 0;
}
priv = (pva_priv_t *)d->priv;
d->filepos=stream_tell(d->stream);
if(d->stream->eof)
{
mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() detected stream->eof!!!\n");
return 0;
}
//printf("priv->just_synced %s\n",priv->just_synced?"SET":"UNSET");
#ifdef PVA_NEW_PREBYTES_CODE
if(priv->prebytes_delivered)
/* The previous call to this fn has delivered the preBytes. Then we are already inside
* the payload. Let's just deliver the video along with its right PTS, the one we stored
* in the priv structure and was in the PVA header before the PreBytes.
*/
{
//printf("prebytes_delivered=1. Resetting.\n");
payload->size = priv->video_size_after_prebytes;
payload->pts = priv->video_pts_after_prebytes;
payload->is_packet_start = 1;
payload->offset = stream_tell(d->stream);
payload->type = VIDEOSTREAM;
priv->prebytes_delivered = 0;
return 1;
}
#endif
if(!priv->just_synced)
{
if(stream_read_word(d->stream) != (('A'<<8)|'V'))
{
mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() missed a SyncWord at %"PRId64"!! Trying to sync...\n",(int64_t)stream_tell(d->stream));
if(!pva_sync(d))
{
if (!d->stream->eof)
{
mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: couldn't sync! (broken file?)");
}
return 0;
}
}
}
if(priv->just_synced)
{
payload->type=priv->synced_stream_id;
priv->just_synced=0;
}
else
{
payload->type=stream_read_char(d->stream);
stream_skip(d->stream,2); //counter and reserved
}
flags=stream_read_char(d->stream);
payload->is_packet_start=flags & 0x10;
pack_size=stream_read_word(d->stream);
mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_pva::pva_get_payload(): pack_size=%u field read at offset %"PRIu64"\n",pack_size,(int64_t)stream_tell(d->stream)-2);
pva_payload_start=stream_tell(d->stream);
/*
* The code in the #ifdef directive below is a hack needed to get badly formatted PVA files
* such as the ones written by MultiDec played back correctly.
* Basically, it works like this: if the PVA packet does not signal a PES header, but the
* payload looks like one, let's assume it IS one. It has worked for me up to now.
* It can be disabled since it's quite an ugly hack and could potentially break things up
* if the PVA audio payload happens to start with 0x000001 even without being a non signalled
* PES header start.
* Though it's quite unlikely, it potentially could (AFAIK).
*/
#ifdef DEMUX_PVA_MULTIDEC_HACK
if(payload->type==MAINAUDIOSTREAM)
{
stream_read(d->stream,buffer,3);
if(buffer[0]==0x00 && buffer[1]==0x00 && buffer[2]==0x01 && !payload->is_packet_start)
{
mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: suspecting non signaled audio PES packet start. Maybe file by MultiDec?\n");
payload->is_packet_start=1;
}
stream_seek(d->stream,stream_tell(d->stream)-3);
}
#endif
if(!payload->is_packet_start)
{
payload->offset=stream_tell(d->stream);
payload->size=pack_size;
}
else
{ //here comes the good part...
switch(payload->type)
{
case VIDEOSTREAM:
payload->pts=(float)(stream_read_dword(d->stream))/90000;
//printf("Video PTS: %f\n",payload->pts);
if((flags&0x03)
#ifdef PVA_NEW_PREBYTES_CODE
&& !priv->prebytes_delivered
#endif
)
{
#ifndef PVA_NEW_PREBYTES_CODE
dp=new_demux_packet(flags&0x03);
stream_read(d->stream,dp->buffer,flags & 0x03); //read PreBytes
ds_add_packet(d->video,dp);
#else
//printf("Delivering prebytes. Setting prebytes_delivered.");
payload->offset=stream_tell(d->stream);
payload->size = flags & 0x03;
priv->video_pts_after_prebytes = payload->pts;
priv->video_size_after_prebytes = pack_size - 4 - (flags & 0x03);
payload->pts=priv->last_video_pts;
payload->is_packet_start=0;
priv->prebytes_delivered=1;
return 1;
#endif
}
//now we are at real beginning of payload.
payload->offset=stream_tell(d->stream);
//size is pack_size minus PTS size minus PreBytes size.
payload->size=pack_size - 4 - (flags & 0x03);
break;
case MAINAUDIOSTREAM:
stream_skip(d->stream,3); //FIXME properly parse PES header.
//printf("StreamID in audio PES header: 0x%2X\n",stream_read_char(d->stream));
stream_skip(d->stream,4);
buffer[255]=stream_read_char(d->stream);
pes_head_len=stream_read_char(d->stream);
stream_read(d->stream,buffer,pes_head_len);
if(!(buffer[255]&0x80)) //PES header does not contain PTS.
{
mp_msg(MSGT_DEMUX,MSGL_V,"Audio PES packet does not contain PTS. (pes_head_len=%d)\n",pes_head_len);
payload->pts=priv->last_audio_pts;
break;
}
else //PES header DOES contain PTS
{
if((buffer[0] & 0xf0)!=0x20) // PTS badly formatted
{
mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: expected audio PTS but badly formatted... (read 0x%02X). Falling back to previous PTS (hack).\n",buffer[0]);
payload->pts=priv->last_audio_pts;
// return 0;
}
else
{
uint64_t temp_pts;
temp_pts=0LL;
temp_pts|=((uint64_t)(buffer[0] & 0x0e) << 29);
temp_pts|=buffer[1]<<22;
temp_pts|=(buffer[2] & 0xfe) << 14;
temp_pts|=buffer[3]<<7;
temp_pts|=(buffer[4] & 0xfe) >> 1;
/*
* PTS parsing is hopefully finished.
*/
payload->pts=(float)temp_pts/90000;
}
}
payload->offset=stream_tell(d->stream);
payload->size=pack_size-stream_tell(d->stream)+pva_payload_start;
break;
}
}
return 1;
}
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_pva_fill_buffer (demuxer_t * demux, demux_stream_t *ds)
{
uint8_t done=0;
demux_packet_t * dp;
pva_priv_t * priv=demux->priv;
pva_payload_t current_payload;
while(!done)
{
if(!pva_get_payload(demux,&current_payload)) return 0;
switch(current_payload.type)
{
case VIDEOSTREAM:
if(demux->video->id==-1) demux->video->id=0;
if(!current_payload.is_packet_start && priv->last_video_pts==-1)
{
/* We should only be here at the beginning of a stream, when we have
* not yet encountered a valid Video PTS, or after a seek.
* So, skip these starting packets in order not to deliver the
* player a bogus PTS.
*/
done=0;
}
else
{
/*
* In every other condition, we are delivering the payload. Set this
* so that the following code knows whether to skip it or read it.
*/
done=1;
}
if(demux->video->id!=0) done=0;
if(current_payload.is_packet_start)
{
priv->last_video_pts=current_payload.pts;
//mp_msg(MSGT_DEMUXER,MSGL_DBG2,"demux_pva: Video PTS=%llu , delivered %f\n",current_payload.pts,priv->last_video_pts);
}
if(done)
{
dp=new_demux_packet(current_payload.size);
dp->pts=priv->last_video_pts;
stream_read(demux->stream,dp->buffer,current_payload.size);
ds_add_packet(demux->video,dp);
}
else
{
//printf("Skipping %u video bytes\n",current_payload.size);
stream_skip(demux->stream,current_payload.size);
}
break;
case MAINAUDIOSTREAM:
if(demux->audio->id==-1) demux->audio->id=0;
if(!current_payload.is_packet_start && priv->last_audio_pts==-1)
{
/* Same as above for invalid video PTS, just for audio. */
done=0;
}
else
{
done=1;
}
if(current_payload.is_packet_start)
{
priv->last_audio_pts=current_payload.pts;
}
if(demux->audio->id!=0) done=0;
if(done)
{
dp=new_demux_packet(current_payload.size);
dp->pts=priv->last_audio_pts;
if(current_payload.offset != stream_tell(demux->stream))
stream_seek(demux->stream,current_payload.offset);
stream_read(demux->stream,dp->buffer,current_payload.size);
ds_add_packet(demux->audio,dp);
}
else
{
stream_skip(demux->stream,current_payload.size);
}
break;
}
}
return 1;
}
static void demux_seek_pva(demuxer_t * demuxer,float rel_seek_secs,float audio_delay,int flags)
{
int total_bitrate=0;
off_t dest_offset;
pva_priv_t * priv=demuxer->priv;
total_bitrate=((sh_audio_t *)demuxer->audio->sh)->i_bps + ((sh_video_t *)demuxer->video->sh)->i_bps;
/*
* Compute absolute offset inside the stream. Approximate total bitrate with sum of bitrates
* reported by the audio and video codecs. The seek is not accurate because, just like
* with MPEG streams, the bitrate is not constant. Moreover, we do not take into account
* the overhead caused by PVA and PES headers.
* If the calculated absolute offset is negative, seek to the beginning of the file.
*/
dest_offset=stream_tell(demuxer->stream)+rel_seek_secs*total_bitrate;
if(dest_offset<0) dest_offset=0;
stream_seek(demuxer->stream,dest_offset);
if(!pva_sync(demuxer))
{
mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: Couldn't seek!\n");
return;
}
/*
* Reset the PTS info inside the pva_priv_t structure. This way we don't deliver
* data with the wrong PTSs (the ones we had before seeking).
*
*/
priv->last_video_pts=-1;
priv->last_audio_pts=-1;
}
static void demux_close_pva(demuxer_t * demuxer)
{
free(demuxer->priv);
demuxer->priv = NULL;
}
const demuxer_desc_t demuxer_desc_pva = {
"PVA demuxer",
"pva",
"PVA",
"Matteo Giani",
"streams from DVB cards",
DEMUXER_TYPE_PVA,
0, // unsafe autodetect
pva_check_file,
demux_pva_fill_buffer,
demux_open_pva,
demux_close_pva,
demux_seek_pva,
NULL
};

View File

@ -1,281 +0,0 @@
/*
* RoQ file demuxer
* copyright (c) 2002 Mike Melanson
* based on Dr. Tim Ferguson's RoQ document found at:
* http://www.csse.monash.edu.au/~timf/videocodec.html
*
* 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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "libavutil/attributes.h"
#define RoQ_INFO 0x1001
#define RoQ_QUAD_CODEBOOK 0x1002
#define RoQ_QUAD_VQ 0x1011
#define RoQ_SOUND_MONO 0x1020
#define RoQ_SOUND_STEREO 0x1021
#define CHUNK_TYPE_AUDIO 0
#define CHUNK_TYPE_VIDEO 1
typedef struct roq_chunk_t
{
int chunk_type;
off_t chunk_offset;
int chunk_size;
float video_chunk_number; // in the case of a video chunk
int running_audio_sample_count; // for an audio chunk
} roq_chunk_t;
typedef struct roq_data_t
{
int total_chunks;
int current_chunk;
int total_video_chunks;
int total_audio_sample_count;
roq_chunk_t *chunks;
} roq_data_t;
// Check if a stream qualifies as a RoQ file based on the magic numbers
// at the start of the file:
// 84 10 FF FF FF FF xx xx
static int roq_check_file(demuxer_t *demuxer)
{
if ((stream_read_dword(demuxer->stream) == 0x8410FFFF) &&
((stream_read_dword(demuxer->stream) & 0xFFFF0000) == 0xFFFF0000))
return DEMUXER_TYPE_ROQ;
else
return 0;
}
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_roq_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
{
sh_video_t *sh_video = demuxer->video->sh;
roq_data_t *roq_data = (roq_data_t *)demuxer->priv;
roq_chunk_t roq_chunk;
if (roq_data->current_chunk >= roq_data->total_chunks)
return 0;
roq_chunk = roq_data->chunks[roq_data->current_chunk];
// make sure we're at the right place in the stream and fetch the chunk
stream_seek(demuxer->stream, roq_chunk.chunk_offset);
if (roq_chunk.chunk_type == CHUNK_TYPE_AUDIO)
ds_read_packet(demuxer->audio, demuxer->stream, roq_chunk.chunk_size,
0,
roq_chunk.chunk_offset, 0);
else
ds_read_packet(demuxer->video, demuxer->stream, roq_chunk.chunk_size,
roq_chunk.video_chunk_number / sh_video->fps,
roq_chunk.chunk_offset, 0);
roq_data->current_chunk++;
return 1;
}
static demuxer_t* demux_open_roq(demuxer_t* demuxer)
{
sh_video_t *sh_video = NULL;
sh_audio_t *sh_audio = NULL;
roq_data_t *roq_data = malloc(sizeof(roq_data_t));
int chunk_id;
int chunk_size;
int chunk_arg av_unused;
int last_chunk_id = 0;
int largest_audio_chunk = 0;
int fps;
roq_data->total_chunks = 0;
roq_data->current_chunk = 0;
roq_data->total_video_chunks = 0;
roq_data->chunks = NULL;
// position the stream and start traversing
stream_seek(demuxer->stream, 6);
fps = stream_read_word_le(demuxer->stream);
while (!stream_eof(demuxer->stream))
{
chunk_id = stream_read_word_le(demuxer->stream);
chunk_size = stream_read_dword_le(demuxer->stream);
chunk_arg = stream_read_word_le(demuxer->stream);
// this is the only useful header info in the file
if (chunk_id == RoQ_INFO)
{
// there should only be one RoQ_INFO chunk per file
if (sh_video)
{
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n");
stream_skip(demuxer->stream, 8);
}
else
{
// this is a good opportunity to create a video stream header
sh_video = new_sh_video(demuxer, 0);
// make sure the demuxer knows about the new stream header
demuxer->video->sh = sh_video;
// make sure that the video demuxer stream header knows about its
// parent video demuxer stream
sh_video->ds = demuxer->video;
sh_video->disp_w = stream_read_word_le(demuxer->stream);
sh_video->disp_h = stream_read_word_le(demuxer->stream);
stream_skip(demuxer->stream, 4);
// custom fourcc for internal MPlayer use
sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V');
// constant frame rate
sh_video->fps = fps;
sh_video->frametime = 1 / sh_video->fps;
}
}
else if ((chunk_id == RoQ_SOUND_MONO) ||
(chunk_id == RoQ_SOUND_STEREO))
{
// create the audio stream header if it hasn't been created it
if (sh_audio == NULL)
{
// make the header first
sh_audio = new_sh_audio(demuxer, 0);
// make sure the demuxer knows about the new stream header
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
// make sure that the audio demuxer stream header knows about its
// parent audio demuxer stream
sh_audio->ds = demuxer->audio;
// go through the bother of making a WAVEFORMATEX structure
sh_audio->wf = malloc(sizeof(*sh_audio->wf));
// custom fourcc for internal MPlayer use
sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A');
if (chunk_id == RoQ_SOUND_STEREO)
sh_audio->wf->nChannels = 2;
else
sh_audio->wf->nChannels = 1;
// always 22KHz, 16-bit
sh_audio->wf->nSamplesPerSec = 22050;
sh_audio->wf->wBitsPerSample = 16;
}
// index the chunk
roq_data->chunks = realloc(roq_data->chunks,
(roq_data->total_chunks + 1) * sizeof (roq_chunk_t));
roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_AUDIO;
roq_data->chunks[roq_data->total_chunks].chunk_offset =
stream_tell(demuxer->stream) - 8;
roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8;
roq_data->chunks[roq_data->total_chunks].running_audio_sample_count =
roq_data->total_audio_sample_count;
// audio housekeeping
if (chunk_size > largest_audio_chunk)
largest_audio_chunk = chunk_size;
roq_data->total_audio_sample_count +=
(chunk_size / sh_audio->wf->nChannels);
stream_skip(demuxer->stream, chunk_size);
roq_data->total_chunks++;
}
else if ((chunk_id == RoQ_QUAD_CODEBOOK) ||
((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK)))
{
// index a new chunk if it's a codebook or quad VQ not following a
// codebook
roq_data->chunks = realloc(roq_data->chunks,
(roq_data->total_chunks + 1) * sizeof (roq_chunk_t));
roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_VIDEO;
roq_data->chunks[roq_data->total_chunks].chunk_offset =
stream_tell(demuxer->stream) - 8;
roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8;
roq_data->chunks[roq_data->total_chunks].video_chunk_number =
roq_data->total_video_chunks++;
stream_skip(demuxer->stream, chunk_size);
roq_data->total_chunks++;
}
else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK))
{
// if it's a quad VQ chunk following a codebook chunk, extend the last
// chunk
roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8);
stream_skip(demuxer->stream, chunk_size);
}
else if (!stream_eof(demuxer->stream))
{
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id);
}
last_chunk_id = chunk_id;
}
// minimum output buffer size = largest audio chunk * 2, since each byte
// in the DPCM encoding effectively represents 1 16-bit sample
// (store it in wf->nBlockAlign for the time being since init_audio() will
// step on it anyway)
if (sh_audio)
sh_audio->wf->nBlockAlign = largest_audio_chunk * 2;
roq_data->current_chunk = 0;
demuxer->priv = roq_data;
stream_reset(demuxer->stream);
return demuxer;
}
static void demux_close_roq(demuxer_t* demuxer) {
roq_data_t *roq_data = demuxer->priv;
free(roq_data);
}
const demuxer_desc_t demuxer_desc_roq = {
"RoQ demuxer",
"roq",
"ROQ",
"Mike Melanson",
"",
DEMUXER_TYPE_ROQ,
0, // unsafe autodetect
roq_check_file,
demux_roq_fill_buffer,
demux_open_roq,
demux_close_roq,
NULL,
NULL
};

View File

@ -1,200 +0,0 @@
/*
* SMJPEG file parser
* copyright (c) 2002 Alex Beregszaszi
* based on text by Arpi (SMJPEG-format.txt) and later on
* http://www.lokigames.com/development/download/smjpeg/SMJPEG.txt
*
* 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 <string.h> /* strtok */
#include "config.h"
#include "mp_msg.h"
#include "libavutil/attributes.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
static int smjpeg_check_file(demuxer_t* demuxer){
int orig_pos = stream_tell(demuxer->stream);
char buf[8];
int version;
mp_msg(MSGT_DEMUX, MSGL_V, "Checking for SMJPEG\n");
if (stream_read_word(demuxer->stream) == 0xA)
{
stream_read(demuxer->stream, buf, 6);
buf[7] = 0;
if (strncmp("SMJPEG", buf, 6)) {
mp_msg(MSGT_DEMUX, MSGL_DBG2, "Failed: SMJPEG\n");
return 0;
}
}
else
return 0;
version = stream_read_dword(demuxer->stream);
if (version != 0)
{
mp_msg(MSGT_DEMUX, MSGL_ERR, "Unknown version (%d) of SMJPEG. Please report!\n",
version);
return 0;
}
stream_seek(demuxer->stream, orig_pos);
return DEMUXER_TYPE_SMJPEG;
}
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_smjpeg_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
{
int dtype, dsize, dpts;
demux->filepos = stream_tell(demux->stream);
dtype = stream_read_dword_le(demux->stream);
dpts = stream_read_dword(demux->stream);
dsize = stream_read_dword(demux->stream);
switch(dtype)
{
case mmioFOURCC('s','n','d','D'):
/* fixme, but no decoder implemented yet */
ds_read_packet(demux->audio, demux->stream, dsize,
(float)dpts/1000.0, demux->filepos, 0);
break;
case mmioFOURCC('v','i','d','D'):
ds_read_packet(demux->video, demux->stream, dsize,
(float)dpts/1000.0, demux->filepos, 0);
break;
case mmioFOURCC('D','O','N','E'):
return 1;
default:
return 0;
}
return 1;
}
static demuxer_t* demux_open_smjpeg(demuxer_t* demuxer){
sh_video_t* sh_video;
sh_audio_t* sh_audio;
unsigned int htype = 0, hleng av_unused;
int i = 0;
/* file header */
stream_skip(demuxer->stream, 8); /* \x00\x0aSMJPEG */
stream_skip(demuxer->stream, 4);
mp_msg(MSGT_DEMUX, MSGL_INFO, "This clip is %d seconds\n",
stream_read_dword(demuxer->stream));
/* stream header */
while (i < 3)
{
i++;
htype = stream_read_dword_le(demuxer->stream);
if (htype == mmioFOURCC('H','E','N','D'))
break;
hleng = (stream_read_word(demuxer->stream)<<16)|stream_read_word(demuxer->stream);
switch(htype)
{
case mmioFOURCC('_','V','I','D'):
sh_video = new_sh_video(demuxer, 0);
demuxer->video->sh = sh_video;
sh_video->ds = demuxer->video;
sh_video->bih = calloc(1, sizeof(*sh_video->bih));
stream_skip(demuxer->stream, 4); /* number of frames */
// sh_video->fps = 24;
// sh_video->frametime = 1.0f/sh_video->fps;
sh_video->disp_w = stream_read_word(demuxer->stream);
sh_video->disp_h = stream_read_word(demuxer->stream);
sh_video->format = stream_read_dword_le(demuxer->stream);
/* these are false values */
sh_video->bih->biSize = 40;
sh_video->bih->biWidth = sh_video->disp_w;
sh_video->bih->biHeight = sh_video->disp_h;
sh_video->bih->biPlanes = 3;
sh_video->bih->biBitCount = 12;
sh_video->bih->biCompression = sh_video->format;
sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h;
break;
case mmioFOURCC('_','S','N','D'):
sh_audio = new_sh_audio(demuxer, 0);
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->wf = calloc(1, sizeof(*sh_audio->wf));
sh_audio->samplerate = stream_read_word(demuxer->stream);
sh_audio->wf->wBitsPerSample = stream_read_char(demuxer->stream);
sh_audio->channels = stream_read_char(demuxer->stream);
sh_audio->format = stream_read_dword_le(demuxer->stream);
sh_audio->wf->wFormatTag = sh_audio->format;
sh_audio->wf->nChannels = sh_audio->channels;
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels*
sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8;
sh_audio->wf->nBlockAlign = sh_audio->channels *2;
sh_audio->wf->cbSize = 0;
break;
case mmioFOURCC('_','T','X','T'):
stream_skip(demuxer->stream, stream_read_dword(demuxer->stream));
break;
}
}
demuxer->seekable = 0;
return demuxer;
}
static void demux_close_smjpeg(demuxer_t *demuxer)
{
return;
}
const demuxer_desc_t demuxer_desc_smjpeg = {
"smjpeg demuxer",
"smjpeg",
"SMJPEG",
"Alex Beregszasi",
"",
DEMUXER_TYPE_SMJPEG,
1, // safe autodetect
smjpeg_check_file,
demux_smjpeg_fill_buffer,
demux_open_smjpeg,
demux_close_smjpeg,
NULL,
NULL
};

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -1,899 +0,0 @@
/*
* tivo@wingert.org, February 2003
*
* Copyright (C) 2003 Christopher R. Wingert
*
* The license covers the portions of this file regarding TiVo additions.
*
* Olaf Beck and Tridge (indirectly) were essential at providing
* information regarding the format of the TiVo streams.
*
* However, no code in the following subsection is directly copied from
* either author.
*
* 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 <time.h>
#include <stdarg.h>
#include <libavutil/avstring.h>
#include <libavutil/intreadwrite.h>
#include "config.h"
#include "mp_msg.h"
#include "libmpcodecs/dec_audio.h"
#include "stream/stream.h"
#include "demuxer.h"
#ifdef DEMUX_TY_OSD
#include "demux_ty_osd.h"
#endif
#include "parse_es.h"
#include "stheader.h"
#include "sub/sub_cc.h"
#include "sub/sub.h"
// 2/c0: audio data
// 3/c0: audio packet header (PES header)
// 4/c0: audio data (S/A only?)
// 9/c0: audio packet header, AC-3 audio
// 2/e0: video data
// 6/e0: video packet header (PES header)
// 7/e0: video sequence header start
// 8/e0: video I-frame header start
// a/e0: video P-frame header start
// b/e0: video B-frame header start
// c/e0: video GOP header start
// e/01: closed-caption data
// e/02: Extended data services data
#define TIVO_PES_FILEID 0xf5467abd
#define TIVO_PART_LENGTH 0x20000000
#define CHUNKSIZE ( 128 * 1024 )
#define MAX_AUDIO_BUFFER ( 16 * 1024 )
#define TY_V 1
#define TY_A 2
typedef struct
{
off_t startOffset;
off_t fileSize;
int chunks;
} tmf_fileParts;
#define MAX_TMF_PARTS 16
typedef struct
{
int whichChunk;
unsigned char chunk[ CHUNKSIZE ];
unsigned char lastAudio[ MAX_AUDIO_BUFFER ];
int lastAudioEnd;
int tivoType; // 1 = SA, 2 = DTiVo
int64_t lastAudioPTS;
int64_t lastVideoPTS;
off_t size;
int readHeader;
int tmf;
tmf_fileParts tmfparts[ MAX_TMF_PARTS ];
int tmf_totalparts;
} TiVoInfo;
// ===========================================================================
#define TMF_SIG "showing.xml"
// ===========================================================================
static int ty_tmf_filetoparts( demuxer_t *demux, TiVoInfo *tivo )
{
int parts = 0;
stream_seek(demux->stream, 0);
mp_msg( MSGT_DEMUX, MSGL_DBG3, "Dumping tar contents\n" );
while (!demux->stream->eof)
{
char header[ 512 ];
char *name;
char *extension;
char *sizestr;
int size;
off_t skip;
if (stream_read(demux->stream, header, 512) < 512)
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "Read bad\n" );
break;
}
name = header;
name[99] = 0;
sizestr = &header[124];
sizestr[11] = 0;
size = strtol(sizestr, NULL, 8);
mp_msg( MSGT_DEMUX, MSGL_DBG3, "name %-20.20s size %-12.12s %d\n",
name, sizestr, size );
extension = strrchr(name, '.');
if (extension && strcmp(extension, ".ty") == 0)
{
if ( parts >= MAX_TMF_PARTS ) {
mp_msg( MSGT_DEMUX, MSGL_ERR, "ty:tmf too big\n" );
break;
}
tivo->tmfparts[ parts ].fileSize = size;
tivo->tmfparts[ parts ].startOffset = stream_tell(demux->stream);
tivo->tmfparts[ parts ].chunks = size / CHUNKSIZE;
mp_msg(MSGT_DEMUX, MSGL_DBG3,
"tmf_filetoparts(): index %d, chunks %d\n"
"tmf_filetoparts(): size %"PRId64"\n"
"tmf_filetoparts(): startOffset %"PRId64"\n",
parts, tivo->tmfparts[ parts ].chunks,
tivo->tmfparts[ parts ].fileSize, tivo->tmfparts[ parts ].startOffset
);
parts++;
}
// size rounded up to blocks
skip = (size + 511) & ~511;
stream_skip(demux->stream, skip);
}
stream_reset(demux->stream);
tivo->tmf_totalparts = parts;
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"tmf_filetoparts(): No More Part Files %d\n", parts );
return 1;
}
// ===========================================================================
static off_t tmf_filetooffset(TiVoInfo *tivo, int chunk)
{
int i;
for (i = 0; i < tivo->tmf_totalparts; i++) {
if (chunk < tivo->tmfparts[i].chunks)
return tivo->tmfparts[i].startOffset + chunk * CHUNKSIZE;
chunk -= tivo->tmfparts[i].chunks;
}
return -1;
}
// ===========================================================================
static int tmf_load_chunk( demuxer_t *demux, TiVoInfo *tivo,
unsigned char *buff, int readChunk )
{
off_t fileoffset;
int count;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "\ntmf_load_chunk() begin %d\n",
readChunk );
fileoffset = tmf_filetooffset(tivo, readChunk);
if (fileoffset == -1 || !stream_seek(demux->stream, fileoffset)) {
mp_msg( MSGT_DEMUX, MSGL_ERR, "Read past EOF()\n" );
return 0;
}
count = stream_read( demux->stream, buff, CHUNKSIZE );
demux->filepos = stream_tell( demux->stream );
mp_msg( MSGT_DEMUX, MSGL_DBG3, "tmf_load_chunk() count %x\n",
count );
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"tmf_load_chunk() bytes %x %x %x %x %x %x %x %x\n",
buff[ 0 ], buff[ 1 ], buff[ 2 ], buff[ 3 ],
buff[ 4 ], buff[ 5 ], buff[ 6 ], buff[ 7 ] );
mp_msg( MSGT_DEMUX, MSGL_DBG3, "tmf_load_chunk() end\n" );
return count;
}
// ===========================================================================
// DTiVo MPEG 336, 480, 576, 768
// SA TiVo 864
// DTiVo AC-3 1550
//
#define SERIES1_PTS_LENGTH 11
#define SERIES1_PTS_OFFSET 6
#define SERIES2_PTS_LENGTH 16
#define SERIES2_PTS_OFFSET 9
#define AC3_PTS_LENGTH 16
#define AC3_PTS_OFFSET 9
static int IsValidAudioPacket( int size, int *ptsOffset, int *ptsLen )
{
// AC-3
if ( size == 1550 || size == 1552 )
{
*ptsOffset = AC3_PTS_OFFSET;
*ptsLen = AC3_PTS_LENGTH;
return 1;
}
// MPEG
if ( (size & 15) == (SERIES1_PTS_LENGTH & 15) )
{
*ptsOffset = SERIES1_PTS_OFFSET;
*ptsLen = SERIES1_PTS_LENGTH;
return 1;
}
if ( (size & 15) == (SERIES2_PTS_LENGTH & 15) )
{
*ptsOffset = SERIES2_PTS_OFFSET;
*ptsLen = SERIES2_PTS_LENGTH;
return 1;
}
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Tossing Audio Packet Size %d\n",
size );
return 0;
}
static int64_t get_ty_pts( unsigned char *buf )
{
int a = buf[0] & 0xe;
int b = AV_RB16(buf + 1);
int c = AV_RB16(buf + 3);
if (!(1 & a & b & c)) // invalid MPEG timestamp
return MP_NOPTS_VALUE;
a >>= 1; b >>= 1; c >>= 1;
return (((uint64_t)a) << 30) | (b << 15) | c;
}
static void demux_ty_AddToAudioBuffer( TiVoInfo *tivo, unsigned char *buffer,
int size )
{
if ( tivo->lastAudioEnd + size < MAX_AUDIO_BUFFER )
{
memcpy( &tivo->lastAudio[ tivo->lastAudioEnd ],
buffer, size );
tivo->lastAudioEnd += size;
}
else
mp_msg( MSGT_DEMUX, MSGL_ERR,
"ty:WARNING - Would have blown my audio buffer\n" );
}
static void demux_ty_CopyToDemuxPacket( demux_stream_t *ds,
unsigned char *buffer, int size, off_t pos, int64_t pts )
{
demux_packet_t *dp = new_demux_packet( size );
memcpy( dp->buffer, buffer, size );
if (pts != MP_NOPTS_VALUE)
dp->pts = pts / 90000.0;
dp->pos = pos;
ds_add_packet( ds, dp );
}
static int demux_ty_FindESHeader( uint8_t nal,
unsigned char *buffer, int bufferSize )
{
uint32_t search = 0x00000100 | nal;
uint32_t found = -1;
uint8_t *p = buffer;
uint8_t *end = p + bufferSize;
while (p < end) {
found <<= 8;
found |= *p++;
if (found == search)
return p - buffer - 4;
}
return -1;
}
static void demux_ty_FindESPacket( uint8_t nal,
unsigned char *buffer, int bufferSize, int *esOffset1, int *esOffset2 )
{
*esOffset1 = demux_ty_FindESHeader(nal, buffer, bufferSize);
if (*esOffset1 == -1) {
*esOffset2 = -1;
return;
}
buffer += *esOffset1 + 1;
bufferSize -= *esOffset1 + 1;
*esOffset2 = demux_ty_FindESHeader(nal, buffer, bufferSize);
if (*esOffset2 != -1)
*esOffset2 += *esOffset1 + 1;
}
#define VIDEO_NAL 0xe0
#define AUDIO_NAL 0xc0
#define AC3_NAL 0xbd
static int demux_ty_fill_buffer( demuxer_t *demux, demux_stream_t *dsds )
{
int invalidType = 0;
int errorHeader = 0;
int recordsDecoded = 0;
int readSize;
int numberRecs;
unsigned char *recPtr;
int offset;
int counter;
int aid;
TiVoInfo *tivo = demux->priv;
unsigned char *chunk = tivo->chunk;
if ( demux->stream->type == STREAMTYPE_DVD )
return 0;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty processing\n" );
if( demux->stream->eof ) return 0;
// ======================================================================
// If we haven't figured out the size of the stream, let's do so
// ======================================================================
if ( demux->stream->type == STREAMTYPE_VSTREAM )
{
// The vstream code figures out the exact size of the stream
demux->movi_start = 0;
demux->movi_end = demux->stream->end_pos;
tivo->size = demux->stream->end_pos;
}
else
{
// If its a local file, try to find the Part Headers, so we can
// calculate the ACTUAL stream size
// If we can't find it, go off with the file size and hope the
// extract program did the "right thing"
if ( tivo->readHeader == 0 )
{
off_t filePos;
tivo->readHeader = 1;
filePos = demux->filepos;
stream_seek( demux->stream, 0 );
readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
if ( memcmp( chunk, TMF_SIG, sizeof( TMF_SIG ) ) == 0 )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Detected a tmf\n" );
tivo->tmf = 1;
ty_tmf_filetoparts( demux, tivo );
readSize = tmf_load_chunk( demux, tivo, chunk, 0 );
}
if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID )
{
off_t numberParts;
readSize = 0;
if ( tivo->tmf != 1 )
{
off_t offset;
numberParts = demux->stream->end_pos / TIVO_PART_LENGTH;
offset = numberParts * TIVO_PART_LENGTH;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty/ty+Number Parts %"PRId64"\n",
(int64_t)numberParts );
if ( offset + CHUNKSIZE < demux->stream->end_pos )
{
stream_seek( demux->stream, offset );
readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
}
}
else
{
numberParts = tivo->tmf_totalparts;
offset = numberParts * TIVO_PART_LENGTH;
readSize = tmf_load_chunk( demux, tivo, chunk,
numberParts * ( TIVO_PART_LENGTH - CHUNKSIZE ) /
CHUNKSIZE );
}
if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID )
{
int size = AV_RB24(chunk + 12);
size -= 4;
size *= CHUNKSIZE;
tivo->size = numberParts * TIVO_PART_LENGTH;
tivo->size += size;
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:Header Calc Stream Size %"PRId64"\n", tivo->size );
}
}
if ( demux->stream->start_pos > 0 )
filePos = demux->stream->start_pos;
stream_seek( demux->stream, filePos );
demux->filepos = stream_tell( demux->stream );
tivo->whichChunk = filePos / CHUNKSIZE;
}
demux->movi_start = 0;
demux->movi_end = tivo->size;
}
// ======================================================================
// Give a clue as to where we are in the stream
// ======================================================================
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:ty header size %"PRIx64"\n", (int64_t)tivo->size );
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:ty which Chunk %d\n", tivo->whichChunk );
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:file end_pos %"PRIx64"\n", (int64_t)demux->stream->end_pos );
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"\nty:wanted current offset %"PRIx64"\n", (int64_t)stream_tell( demux->stream ) );
if ( tivo->size > 0 && stream_tell( demux->stream ) > tivo->size )
{
demux->stream->eof = 1;
return 0;
}
do {
if ( tivo->tmf != 1 )
{
// Make sure we are on a 128k boundary
if ( demux->filepos % CHUNKSIZE != 0 )
{
int whichChunk = demux->filepos / CHUNKSIZE;
if ( demux->filepos % CHUNKSIZE > CHUNKSIZE / 2 )
whichChunk++;
stream_seek( demux->stream, whichChunk * CHUNKSIZE );
}
demux->filepos = stream_tell( demux->stream );
tivo->whichChunk = demux->filepos / CHUNKSIZE;
readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
if ( readSize != CHUNKSIZE )
return 0;
}
else
{
readSize = tmf_load_chunk( demux, tivo, chunk, tivo->whichChunk );
if ( readSize != CHUNKSIZE )
return 0;
tivo->whichChunk++;
}
if (AV_RB32(chunk) == TIVO_PES_FILEID)
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Skipping PART Header\n" );
} while (AV_RB32(chunk) == TIVO_PES_FILEID);
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"\nty:actual current offset %"PRIx64"\n", stream_tell( demux->stream ) -
CHUNKSIZE );
// Let's make a Video Demux Stream for MPlayer
aid = 0x0;
if( !demux->v_streams[ aid ] ) new_sh_video( demux, aid );
if( demux->video->id == -1 ) demux->video->id = aid;
if( demux->video->id == aid )
{
demux_stream_t *ds = demux->video;
if( !ds->sh ) ds->sh = demux->v_streams[ aid ];
}
// ======================================================================
// Finally, we get to actually parse the chunk
// ======================================================================
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty parsing a chunk\n" );
numberRecs = chunk[ 0 ];
recPtr = &chunk[ 4 ];
offset = numberRecs * 16 + 4;
for ( counter = 0 ; counter < numberRecs ; counter++ )
{
int size = AV_RB24(recPtr) >> 4;
int type = recPtr[ 3 ];
int nybbleType = recPtr[ 2 ] & 0x0f;
recordsDecoded++;
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:Record Type %x/%x %d\n", nybbleType, type, size );
// ================================================================
// Video Parsing
// ================================================================
if ( type == 0xe0 )
{
if ( size > 0 && size + offset <= CHUNKSIZE )
{
int esOffset1 = demux_ty_FindESHeader( VIDEO_NAL, &chunk[ offset ],
size);
if ( esOffset1 != -1 )
tivo->lastVideoPTS = get_ty_pts(
&chunk[ offset + esOffset1 + 9 ] );
// Do NOT Pass the PES Header onto the MPEG2 Decode
if( nybbleType != 0x06 )
demux_ty_CopyToDemuxPacket( demux->video,
&chunk[ offset ], size, demux->filepos + offset,
tivo->lastVideoPTS );
offset += size;
}
else
errorHeader++;
}
// ================================================================
// Audio Parsing
// ================================================================
else if ( type == 0xc0 )
{
if ( size > 0 && size + offset <= CHUNKSIZE )
{
if( demux->audio->id == -1 )
{
if ( nybbleType == 0x02 )
continue; // DTiVo inconclusive, wait for more
else if ( nybbleType == 0x09 )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting AC-3 Audio\n" );
aid = 0x80; // AC-3
}
else
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting MPEG Audio\n" );
aid = 0x0; // MPEG Audio
}
demux->audio->id = aid;
if( !demux->a_streams[ aid ] ) new_sh_audio( demux, aid );
if( demux->audio->id == aid )
{
demux_stream_t *ds = demux->audio;
if( !ds->sh ) {
sh_audio_t* sh_a;
ds->sh = demux->a_streams[ aid ];
sh_a = (sh_audio_t*)ds->sh;
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
}
}
}
}
aid = demux->audio->id;
// SA DTiVo Audio Data, no PES
// ================================================
if ( nybbleType == 0x02 || nybbleType == 0x04 )
{
if ( nybbleType == 0x02 && tivo->tivoType == 2 )
demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size );
else
{
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:Adding Audio Packet Size %d\n", size );
demux_ty_CopyToDemuxPacket( demux->audio,
&chunk[ offset ], size, ( demux->filepos + offset ),
tivo->lastAudioPTS );
}
}
// 3 - MPEG Audio with PES Header, either SA or DTiVo
// 9 - DTiVo AC3 Audio Data with PES Header
// ================================================
if ( nybbleType == 0x03 || nybbleType == 0x09 )
{
int esOffset1, esOffset2;
if ( nybbleType == 0x03 )
esOffset1 = demux_ty_FindESHeader( AUDIO_NAL, &chunk[ offset ],
size);
// SA PES Header, No Audio Data
// ================================================
if ( nybbleType == 0x03 && esOffset1 == 0 && size == 16 )
{
tivo->tivoType = 1;
tivo->lastAudioPTS = get_ty_pts( &chunk[ offset +
SERIES2_PTS_OFFSET ] );
}
else
// DTiVo Audio with PES Header
// ================================================
{
tivo->tivoType = 2;
demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size );
demux_ty_FindESPacket( nybbleType == 9 ? AC3_NAL : AUDIO_NAL,
tivo->lastAudio, tivo->lastAudioEnd, &esOffset1,
&esOffset2 );
if ( esOffset1 != -1 && esOffset2 != -1 )
{
int packetSize = esOffset2 - esOffset1;
int headerSize;
int ptsOffset;
if ( IsValidAudioPacket( packetSize, &ptsOffset,
&headerSize ) )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:Adding DTiVo Audio Packet Size %d\n",
packetSize );
tivo->lastAudioPTS = get_ty_pts(
&tivo->lastAudio[ esOffset1 + ptsOffset ] );
if (nybbleType == 9) headerSize = 0;
demux_ty_CopyToDemuxPacket
(
demux->audio,
&tivo->lastAudio[ esOffset1 + headerSize ],
packetSize - headerSize,
demux->filepos + offset,
tivo->lastAudioPTS
);
}
// Collapse the Audio Buffer
tivo->lastAudioEnd -= esOffset2;
memmove( &tivo->lastAudio[ 0 ],
&tivo->lastAudio[ esOffset2 ],
tivo->lastAudioEnd );
}
}
}
offset += size;
}
else
errorHeader++;
}
// ================================================================
// 1 = Closed Caption
// 2 = Extended Data Services
// ================================================================
else if ( type == 0x01 || type == 0x02 )
{
unsigned char lastXDS[ 16 ];
int b = AV_RB24(recPtr) >> 4;
b &= 0x7f7f;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:%s %04x\n", type == 1 ? "CC" : "XDS", b);
lastXDS[ 0x00 ] = 0x00;
lastXDS[ 0x01 ] = 0x00;
lastXDS[ 0x02 ] = 0x01;
lastXDS[ 0x03 ] = 0xb2;
lastXDS[ 0x04 ] = 'T';
lastXDS[ 0x05 ] = 'Y';
lastXDS[ 0x06 ] = type;
lastXDS[ 0x07 ] = b >> 8;
lastXDS[ 0x08 ] = b;
if ( subcc_enabled )
demux_ty_CopyToDemuxPacket( demux->video, lastXDS, 0x09,
demux->filepos + offset, tivo->lastVideoPTS );
}
// ================================================================
// Unknown
// ================================================================
else
{
if ( size > 0 && size + offset <= CHUNKSIZE )
offset += size;
if (type != 3 && type != 5 && (type != 0 || size > 0)) {
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Invalid Type %x\n", type );
invalidType++;
}
}
recPtr += 16;
}
if ( errorHeader > 0 || invalidType > 0 )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"ty:Error Check - Records %d, Parsed %d, Errors %d + %d\n",
numberRecs, recordsDecoded, errorHeader, invalidType );
// Invalid MPEG ES Size Check
if ( errorHeader > numberRecs / 2 )
return 0;
// Invalid MPEG Stream Type Check
if ( invalidType > numberRecs / 2 )
return 0;
}
demux->filepos = stream_tell( demux->stream );
return 1;
}
static void demux_seek_ty( 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;
off_t newpos;
off_t res;
TiVoInfo *tivo = demuxer->priv;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Seeking to %7.1f\n", rel_seek_secs );
tivo->lastAudioEnd = 0;
tivo->lastAudioPTS = MP_NOPTS_VALUE;
tivo->lastVideoPTS = MP_NOPTS_VALUE;
//
//================= seek in MPEG ==========================
demuxer->filepos = stream_tell( demuxer->stream );
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( ! 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;
}
if ( newpos < demuxer->movi_start )
{
if( demuxer->stream->type != STREAMTYPE_VCD ) demuxer->movi_start = 0;
if( newpos < demuxer->movi_start ) newpos = demuxer->movi_start;
}
res = newpos / CHUNKSIZE;
if ( rel_seek_secs >= 0 )
newpos = ( res + 1 ) * CHUNKSIZE;
else
newpos = res * CHUNKSIZE;
if ( newpos < 0 )
newpos = 0;
tivo->whichChunk = newpos / CHUNKSIZE;
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;
}
}
i = sync_video_packet( d_video );
if( i == 0x1B3 || i == 0x1B8 ) break; // found it!
if( !i || !skip_video_packet( d_video ) ) break; // EOF?
}
#ifdef DEMUX_TY_OSD
if ( subcc_enabled )
ty_ClearOSD( 0 );
#endif
}
static int demux_ty_control( demuxer_t *demuxer,int cmd, void *arg )
{
demux_stream_t *d_video = demuxer->video;
sh_video_t *sh_video = d_video->sh;
switch(cmd)
{
case DEMUXER_CTRL_GET_TIME_LENGTH:
if(!sh_video->i_bps) // unspecified or VBR
return DEMUXER_CTRL_DONTKNOW;
*(double *)arg=
(double)demuxer->movi_end-demuxer->movi_start/sh_video->i_bps;
return DEMUXER_CTRL_GUESS;
case DEMUXER_CTRL_GET_PERCENT_POS:
return DEMUXER_CTRL_DONTKNOW;
default:
return DEMUXER_CTRL_NOTIMPL;
}
}
static void demux_close_ty( demuxer_t *demux )
{
TiVoInfo *tivo = demux->priv;
free( tivo );
sub_justify = 0;
}
static int ty_check_file(demuxer_t* demuxer)
{
demuxer->filepos = 0;
TiVoInfo *tivo = calloc(1, sizeof(TiVoInfo));
demuxer->priv = tivo;
return ds_fill_buffer(demuxer->video) ? DEMUXER_TYPE_MPEG_TY : 0;
}
static demuxer_t* demux_open_ty(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;
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;
}
}
return demuxer;
}
const demuxer_desc_t demuxer_desc_mpeg_ty = {
"TiVo demuxer",
"tivo",
"TiVo",
"Christopher R. Wingert",
"Demux streams from TiVo",
DEMUXER_TYPE_MPEG_TY,
0, // unsafe autodetect
ty_check_file,
demux_ty_fill_buffer,
demux_open_ty,
demux_close_ty,
demux_seek_ty,
demux_ty_control
};

View File

@ -1,911 +0,0 @@
// Most of this was written by Mike Baker <mbm@linux.com>
// and released under the GPL v2+ license.
//
// Modifications and SEVERE cleanup of the code was done by
// Christopher Wingert
// Copyright 2003
//
// Released under GPL2 License.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "mp_msg.h"
//#include "stream/stream.h"
//#include "demuxer.h"
//#include "parse_es.h"
//#include "stheader.h"
//#include "mp3_hdr.h"
//#include "subreader.h"
#include "sub/sub_cc.h"
#include "sub/sub.h"
#include "demux_ty_osd.h"
//#include "dvdauth.h"
extern int sub_justify;
#define TY_TEXT_MODE ( 1 << 0 )
#define TY_OSD_MODE ( 1 << 1 )
static int TY_OSD_flags = TY_TEXT_MODE | TY_OSD_MODE;
static int TY_OSD_debug = 0;
// ===========================================================================
// Closed Caption Decoding and OSD Presentation
// ===========================================================================
#define TY_CCNONE ( -3 )
#define TY_CCTEXTMODE ( -2 )
#define TY_CCPOPUPNB ( -1 )
#define TY_CCPOPUP ( 0 )
#define TY_CCPAINTON ( 1 )
#define TY_CC_MAX_X ( 45 )
static int TY_CC_CUR_X;
static int TY_CC_CUR_Y;
static int TY_CC_stat = TY_CCNONE;
static char TY_CC_buf[ 255 ];
static char *TY_CC_ptr = TY_CC_buf;
static unsigned TY_CC_lastcap = 0;
static int TY_CC_TextItalic;
static int TY_CC_Y_Offset;
static subtitle ty_OSD1;
static subtitle ty_OSD2;
static subtitle *ty_pOSD1;
static subtitle *ty_pOSD2;
static int tyOSDInitialized = 0;
static int tyOSDUpdate = 0;
static void ty_DrawOSD(void)
{
// printf( "Calling ty_DrawOSD()\n" );
tyOSDUpdate = 1;
}
void ty_ClearOSD( int start )
{
int index;
// printf( "Calling ty_ClearOSD()\n" );
for ( index = start ; index < SUB_MAX_TEXT ; index++ )
{
memset( ty_OSD1.text[ index ], ' ', TY_CC_MAX_X - 1 );
ty_OSD1.text[ index ][ TY_CC_MAX_X - 1 ] = 0;
memset( ty_OSD2.text[ index ], ' ', TY_CC_MAX_X - 1 );
ty_OSD2.text[ index ][ TY_CC_MAX_X - 1 ] = 0;
}
}
static void ty_DrawChar( int *x, int *y, char disChar, int fgColor, int bgColor )
{
int cx;
int cy;
cx = *x;
cy = *y;
if ( *x >= ( TY_CC_MAX_X - 1 ) )
{
cx = 0;
}
if ( ( *y + TY_CC_Y_Offset ) > SUB_MAX_TEXT )
{
cy = SUB_MAX_TEXT - TY_CC_Y_Offset - 1;
}
// printf( "Calling ty_DrawChar() x:%d y:%d %c fg:%d bg:%d\n",
// cx, cy, disChar, fgColor, bgColor );
ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx ] = disChar;
memset( &( ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx + 1 ] ), ' ',
TY_CC_MAX_X - cx - 2 );
( *x )++;
}
static void ty_RollupBuf( int dest, int source, int numLines )
{
int index;
// printf( "Calling ty_RollupBuf() dest:%d source %d, numLines %d\n",
// dest, source, numLines );
//
if ( ( source + TY_CC_Y_Offset + numLines ) > SUB_MAX_TEXT )
{
ty_ClearOSD( 1 );
return;
}
if ( ( source + TY_CC_Y_Offset + numLines ) < 0 )
{
ty_ClearOSD( 1 );
return;
}
if ( numLines > SUB_MAX_TEXT )
{
ty_ClearOSD( 1 );
return;
}
for ( index = 0 ; index < numLines ; index++ )
{
strcpy( ty_OSD1.text[ TY_CC_Y_Offset + dest ],
ty_OSD1.text[ TY_CC_Y_Offset + source ] );
dest++;
source++;
}
memset( ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ], ' ', TY_CC_MAX_X - 1 );
ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ][ TY_CC_MAX_X - 1 ] = 0;
}
static void ty_drawchar( char c )
{
if ( c < 2 ) return;
if ( TY_OSD_flags & TY_OSD_MODE && TY_CC_stat != TY_CCNONE &&
TY_CC_CUR_Y != -1 )
ty_DrawChar( &TY_CC_CUR_X, &TY_CC_CUR_Y, c, 4, 13 );
if ( TY_CC_ptr - TY_CC_buf > sizeof( TY_CC_buf ) - 1 )
{ // buffer overflow
TY_CC_ptr = TY_CC_buf;
memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) );
}
*( TY_CC_ptr++ ) = ( c == 14 ) ? '/' : c; // swap a '/' for musical note
}
static void ty_draw(void)
{
if ( TY_CC_ptr != TY_CC_buf && TY_OSD_flags & TY_TEXT_MODE )
{
if ( *( TY_CC_ptr - 1 ) == '\n' ) *( TY_CC_ptr - 1 ) = 0;
mp_msg( MSGT_DEMUX, MSGL_V, "CC: %s\n", TY_CC_buf );
}
TY_CC_lastcap = time( NULL );
TY_CC_ptr = TY_CC_buf;
memset( TY_CC_buf, 0, sizeof( TY_CC_buf) );
if ( TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD();
if ( TY_CC_TextItalic ) TY_CC_TextItalic = 0;
}
static int CC_last = 0;
static char CC_mode = 0;
static int CC_row[] =
{
11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
};
// char specialchar[] = { '®', '°', '½', '¿', '*', '¢', '£', 14, 'à', ' ', 'è', 'â', 'ê', 'î', 'ô', 'û' };
static int ty_CCdecode( char b1, char b2 )
{
int x;
int data = ( b2 << 8 ) + b1;
if ( b1 & 0x60 ) // text
{
if ( !TY_OSD_debug && TY_CC_stat == TY_CCNONE ) return 0;
if ( TY_OSD_debug > 3 )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "%c %c", b1, b2 );
}
ty_drawchar( b1 );
ty_drawchar( b2 );
if ( TY_CC_stat > 0 && TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD();
}
else if ( ( b1 & 0x10 ) && ( b2 > 0x1F ) && ( data != CC_last ) )
{
#define CURRENT ( ( b1 & 0x08 ) >> 3 )
if ( CC_mode != CURRENT && TY_CC_stat != TY_CCNONE )
{
if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf ) ty_draw();
TY_CC_stat = TY_CCNONE;
return 0;
}
if ( TY_CC_stat == TY_CCNONE || TY_CC_CUR_Y == -1 )
{
if ( TY_CC_ptr != TY_CC_buf )
{
if ( TY_OSD_debug )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n",
TY_CC_buf );
TY_CC_ptr = TY_CC_buf;
memset(TY_CC_buf, 0, sizeof(TY_CC_buf));
}
if ( CC_mode != CURRENT ) return 0;
}
// preamble address code (row & indent)
if ( b2 & 0x40 )
{
TY_CC_CUR_Y = CC_row[ ( ( b1 << 1 ) & 14 ) | ( ( b2 >> 5 ) & 1 ) ];
// Offset into MPlayer's Buffer
if ( ( TY_CC_CUR_Y >= 1 ) && ( TY_CC_CUR_Y <= 4 ) )
{
TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 1;
}
if ( ( TY_CC_CUR_Y >= 5 ) && ( TY_CC_CUR_Y <= 10 ) )
{
TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 5;
}
if ( ( TY_CC_CUR_Y >= 12 ) && ( TY_CC_CUR_Y <= 15 ) )
{
TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 12;
}
if ( TY_OSD_debug > 3 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< preamble %d >>\n", TY_CC_CUR_Y );
// we still have something in the text buffer
if (TY_CC_ptr != TY_CC_buf)
{
*(TY_CC_ptr++) = '\n';
if ( TY_CC_TextItalic )
{
TY_CC_TextItalic = 0;
}
}
TY_CC_CUR_X = 1;
// row contains indent flag
if ( b2 & 0x10 )
{
for ( x = 0 ; x < ( ( b2 & 0x0F ) << 1 ) ; x++ )
{
TY_CC_CUR_X++;
*(TY_CC_ptr++) = ' ';
}
}
}
else
// !(b2 & 0x40)
{
if ( TY_OSD_debug > 3 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< %02x >>\n", b1 & 0x7 );
switch (b1 & 0x07)
{
case 0x00: // attribute
{
if ( TY_OSD_debug > 1 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<A: %d>>\n", b2 );
break;
}
case 0x01: // midrow or char
{
switch (b2 & 0x70)
{
case 0x20: // midrow attribute change
{
switch (b2 & 0x0e)
{
case 0x00: // italics off
{
TY_CC_TextItalic = 0;
*(TY_CC_ptr++) = ' ';
break;
}
case 0x0e: // italics on
{
ty_drawchar(' ');
TY_CC_TextItalic = 1;
break;
}
default:
{
if ( TY_OSD_debug > 1 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<D: %d>>\n",
b2 & 0x0e );
}
}
if ( b2 & 0x01 )
{
// TextUnderline = 1;
}
else
{
// TextUnderline = 0;
}
break;
}
case 0x30: // special character..
{
// transparent space
if ( ( b2 & 0x0f ) == 9 )
{
TY_CC_CUR_X++;
*(TY_CC_ptr++) = ' ';
}
else
{
// ty_drawchar(specialchar[ b2 & 0x0f ] );
ty_drawchar( ' ' );
}
break;
}
}
break;
}
case 0x04: // misc
case 0x05: // misc + F
{
if ( TY_OSD_debug > 3 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< misc %02x >>\n", b2 );
switch ( b2 )
{
case 0x20: // resume caption (new caption)
{
if ( TY_OSD_flags & TY_OSD_MODE &&
TY_CC_stat != TY_CCPOPUP )
ty_ClearOSD( 1 );
TY_CC_stat = TY_CCPOPUP;
break;
}
case 0x21: // backspace
{
TY_CC_CUR_X--;
break;
}
case 0x25: // 2-4 row captions
case 0x26:
case 0x27:
{
if ( TY_CC_stat == TY_CCPOPUP ) ty_ClearOSD( 1 );
TY_CC_stat = b2 - 0x23;
if ( TY_CC_CUR_Y < TY_CC_stat ) TY_CC_CUR_Y = TY_CC_stat;
break;
}
case 0x29: // resume direct caption
{
TY_CC_stat = TY_CCPAINTON;
break;
}
case 0x2A: // text restart
{
ty_draw();
/* FALL */
}
case 0x2B: // resume text display
{
TY_CC_stat = TY_CCTEXTMODE;
break;
}
case 0x2C: // erase displayed memory
{
TY_CC_lastcap = 0;
if ( TY_OSD_flags & TY_OSD_MODE )
{
if ( TY_CC_stat > TY_CCPOPUP || TY_CC_ptr == TY_CC_buf )
{
ty_ClearOSD( 1 );
ty_draw();
}
else
{
ty_ClearOSD( 1 );
// CRW -
// new buffer
// Used to be a buffer swap here, dunno why
}
}
break;
}
case 0x2D: // carriage return
{
ty_draw();
TY_CC_CUR_X = 1;
if ( TY_OSD_flags & TY_OSD_MODE )
{
if ( TY_CC_stat > TY_CCPAINTON )
ty_RollupBuf
(
TY_CC_CUR_Y - TY_CC_stat + 1 ,
TY_CC_CUR_Y - TY_CC_stat + 2,
TY_CC_stat - 1
);
else
TY_CC_CUR_Y++;
}
break;
}
case 0x2F: // end caption + swap memory
{
ty_draw();
/* FALL THROUGH TO 0x2E */
}
case 0x2E: // erase non-displayed memory
{
if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf )
mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n",
TY_CC_buf );
if ( TY_OSD_flags & TY_OSD_MODE ) ty_ClearOSD( 1 );
TY_CC_CUR_X = 1;
TY_CC_CUR_Y = -1;
TY_CC_ptr = TY_CC_buf;
memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) );
}
}
break;
}
case 0x07: // misc (TAB)
{
for ( x = 0 ; x < ( b2 - 0x20 ) ; x++ )
TY_CC_CUR_X++;
break;
}
}
}
}
CC_last = data;
return 0;
}
// ===========================================================================
// Extended Data Service Decoding and OSD Presentation
// ===========================================================================
#define XDS_BUFFER_LENGTH ( 16 )
#define XDS_DISPLAY_FRAMES ( 120 )
static char *ty_XDS_Display[ XDS_BUFFER_LENGTH ];
static int ty_XDSAddLine = -1;
static int ty_XDSDisplayCount = -1;
static void ty_AddXDSToDisplay( const char *format, ... )
{
char line[ 80 ];
int index;
va_list ap;
if ( ty_XDSAddLine == -1 )
{
for( index = 0 ; index < XDS_BUFFER_LENGTH ; index++ )
{
ty_XDS_Display[ index ] = 0;
}
ty_XDSAddLine = 0;
}
va_start( ap, format );
vsnprintf( line, 80, format, ap );
va_end( ap );
mp_msg( MSGT_DEMUX, MSGL_V, "XDS: %s\n", line );
if ( ty_XDSAddLine == XDS_BUFFER_LENGTH )
{
mp_msg( MSGT_DEMUX, MSGL_ERR, "XDS Buffer would have been blown\n" );
}
if ( ty_XDS_Display[ ty_XDSAddLine ] != 0 )
{
free( ty_XDS_Display[ ty_XDSAddLine ] );
ty_XDS_Display[ ty_XDSAddLine ] = 0;
}
ty_XDS_Display[ ty_XDSAddLine ] = malloc( strlen( line ) + 1 );
strcpy( ty_XDS_Display[ ty_XDSAddLine ], line );
ty_XDSAddLine++;
}
static void ty_DisplayXDSInfo(void)
{
int index;
int size;
if ( ty_XDSDisplayCount == -1 )
{
for( index = 0 ; index < XDS_BUFFER_LENGTH ; index++ )
{
if ( ty_XDS_Display[ index ] != 0 )
{
break;
}
}
if ( index != XDS_BUFFER_LENGTH )
{
size = strlen( ty_XDS_Display[ index ] );
// Right Justify the XDS Stuff
memcpy( &( ty_OSD1.text[ 0 ][ TY_CC_MAX_X - size - 1 ] ),
ty_XDS_Display[ index ], size );
free( ty_XDS_Display[ index ] );
ty_XDS_Display[ index ] = 0;
ty_XDSDisplayCount = 0;
tyOSDUpdate = 1;
}
else
{
// We cleaned out all the XDS stuff to be displayed
ty_XDSAddLine = 0;
}
}
else
{
// We displayed that piece of XDS information long enough
// Let's move on
ty_XDSDisplayCount++;
if ( ty_XDSDisplayCount >= XDS_DISPLAY_FRAMES )
{
memset( ty_OSD1.text[ 0 ], ' ', TY_CC_MAX_X - 1 );
ty_OSD1.text[ 0 ][ TY_CC_MAX_X - 1 ] = 0;
ty_XDSDisplayCount = -1;
tyOSDUpdate = 1;
}
}
}
static int TY_XDS_mode = 0;
static int TY_XDS_type = 0;
static int TY_XDS_length = 0;
static char TY_XDS_checksum = 0;
// Array of [ Mode ][ Type ][ Length ]
static char TY_XDS [ 8 ][ 25 ][ 34 ];
static char TY_XDS_new[ 8 ][ 25 ][ 34 ];
// Array of [ MPAARating|TVRating ][ NumberRatings ]
static const char * const TY_XDS_CHIP[ 2 ][ 8 ] =
{
{ "(NOT APPLICABLE)", "G", "PG", "PG-13", "R", "NC-17", "X", "(NOT RATED)" },
{ "(NOT RATED)", "TV-Y", "TV-Y7", "TV-G", "TV-PG", "TV-14", "TV-MA",
"(NOT RATED)" }
};
static const char * const TY_XDS_modes[] =
{
"CURRENT", // 01h-02h current program
"FUTURE ", // 03h-04h future program
"CHANNEL", // 05h-06h channel
"MISC. ", // 07h-08h miscellaneous
"PUBLIC ", // 09h-0Ah public service
"RESERV.", // 0Bh-0Ch reserved
"UNDEF. ",
"INVALID",
"INVALID",
"INVALID"
};
static int ty_XDSdecode( char b1, char b2 )
{
char line[ 80 ];
if ( b1 < 0x0F )
{ // start packet
TY_XDS_length = 0;
TY_XDS_mode = b1 >> 1; // every other mode is a resume
TY_XDS_type = b2;
TY_XDS_checksum = b1 + b2;
return 0;
}
TY_XDS_checksum += b1 + b2;
// eof (next byte is checksum)
if ( b1 == 0x0F )
{
// validity check
if ( !TY_XDS_length || TY_XDS_checksum & 0x7F )
{
if ( TY_OSD_debug > 3 && !TY_XDS_length )
{
mp_msg( MSGT_DEMUX, MSGL_DBG3,
"%% TY_XDS CHECKSUM ERROR (ignoring)\n" );
}
else
{
TY_XDS_mode = 0;
TY_XDS_type = 0;
return 1;
}
}
// check to see if the data has changed.
if ( strncmp( TY_XDS[ TY_XDS_mode ][ TY_XDS_type ],
TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ], TY_XDS_length - 1 ) )
{
char *TY_XDS_ptr = TY_XDS[ TY_XDS_mode ][ TY_XDS_type ];
TY_XDS_ptr[ TY_XDS_length ] = 0;
memcpy( TY_XDS[ TY_XDS_mode ][ TY_XDS_type ],
TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ], TY_XDS_length );
// nasty hack: only print time codes if seconds are 0
if ( TY_XDS_mode == 3 && TY_XDS_type == 1 &&
!( TY_XDS_new[ 3 ][ 1 ][ 3 ] & 0x20 ) )
{
return 0;
}
if ( TY_XDS_mode == 0 && TY_XDS_type == 2 &&
( TY_XDS_new[ 0 ][ 2 ][ 4 ] & 0x3f ) > 1 )
{
return 0;
}
mp_msg( MSGT_DEMUX, MSGL_DBG3, "%% %s ", TY_XDS_modes[ TY_XDS_mode ] );
line[ 0 ] = 0;
// printf( "XDS Code %x\n",
// ( TY_XDS_mode << 9 ) + TY_XDS_type + 0x100 );
switch ( ( TY_XDS_mode << 9 ) + TY_XDS_type + 0x100 )
{
// cases are specified in 2 bytes hex representing mode, type.
// TY_XDS_ptr will point to the current class buffer
case 0x0101: // current
case 0x0301: // future
{
char *mon[] =
{
"0", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec", "13", "14", "15"
};
ty_AddXDSToDisplay( "AIR DATE: %s %2d %d:%02d:00",
mon[ TY_XDS_ptr[ 3 ] & 0x0f ],
TY_XDS_ptr[ 2 ] & 0x1f,
TY_XDS_ptr[ 1 ] & 0x1f,
TY_XDS_ptr[ 0 ] & 0x3f
);
// Program is tape delayed
if ( TY_XDS_ptr[ 3 ] & 0x10 ) ty_AddXDSToDisplay( " TAPE" );
}
break;
case 0x0102: // current program length
case 0x0302: // future
{
ty_AddXDSToDisplay(
"DURATION: %d:%02d:%02d of %d:%02d:%02d",
TY_XDS_ptr[ 3 ] & 0x3f,
TY_XDS_ptr[ 2 ] & 0x3f,
TY_XDS_ptr[ 4 ] & 0x3f,
TY_XDS_ptr[ 1 ] & 0x3f,
TY_XDS_ptr[ 0 ] & 0x3f, 0);
break;
}
case 0x0103: // current program name
case 0x0303: // future
{
ty_AddXDSToDisplay( "TITLE: %s", TY_XDS_ptr );
break;
}
case 0x0104: // current program type
case 0x0304: // future
{
// for now just print out the raw data
// requires a 127 string array to parse
// properly and isn't worth it.
sprintf ( line, "%sGENRE:", line );
{
int x;
for ( x = 0 ; x < TY_XDS_length ; x++ )
sprintf( line, "%s %02x", line, TY_XDS_ptr[ x ] );
}
ty_AddXDSToDisplay( line );
break;
}
case 0x0105: // current program rating
case 0x0305: // future
{
sprintf( line, "%sRATING: %s", line,
TY_XDS_CHIP[ ( TY_XDS_ptr[ 0 ] & 0x08 ) >> 3 ]
[ TY_XDS_ptr[ 1 ] & 0x07 ] );
if ( TY_XDS_ptr[ 0 ] & 0x20 )
sprintf( line, "%s DIALOGUE", line );
if ( TY_XDS_ptr[ 1 ] & 0x08 )
sprintf( line, "%s LANGUAGE", line );
if ( TY_XDS_ptr[ 1 ] & 0x10 )
sprintf( line, "%s SEXUAL", line );
if ( TY_XDS_ptr[ 1 ] & 0x20 )
sprintf( line, "%s VIOLENCE", line );
ty_AddXDSToDisplay( line );
// raw output for verification.
if ( TY_OSD_debug > 1 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, " (%02x %02x)",
TY_XDS_ptr[ 0 ], TY_XDS_ptr[ 1 ] );
break;
}
case 0x0106: // current program audio services
case 0x0306: // future
{
// requires table, never actually seen it used either
ty_AddXDSToDisplay( "AUDIO: %02x %02x", TY_XDS_ptr[ 0 ],
TY_XDS_ptr[ 1 ] );
break;
}
case 0x0109: // current program aspect ratio
case 0x0309: // future
{
// requires table, rare
ty_AddXDSToDisplay( "ASPECT: %02x %02x",
TY_XDS_ptr[ 0 ], TY_XDS_ptr[ 1 ] );
break;
}
case 0x0110: // program description
case 0x0111:
case 0x0112:
case 0x0113:
case 0x0114:
case 0x0115:
case 0x0116:
case 0x0117:
{
ty_AddXDSToDisplay( "DESCRIP: %s", TY_XDS_ptr );
break;
}
case 0x0501: // channel network name
{
ty_AddXDSToDisplay( "NETWORK: %s", TY_XDS_ptr );
break;
}
case 0x0502: // channel network call letters
{
ty_AddXDSToDisplay( "CALLSIGN: %s", TY_XDS_ptr );
break;
}
case 0x0701: // misc. time of day
{
#define TIMEZONE ( TY_XDS[ 3 ][ 4 ][ 0 ] & 0x1f )
#define DST ( ( TY_XDS[ 3 ][ 4 ][ 0 ] & 0x20 ) >> 5 )
struct tm tm =
{
.tm_sec = 0, // sec
.tm_min = ( TY_XDS_ptr[ 0 ] & 0x3F ), // min
.tm_hour = ( TY_XDS_ptr[ 1 ] & 0x1F ), // hour
.tm_mday = ( TY_XDS_ptr[ 2 ] & 0x1F ), // day
.tm_mon = ( TY_XDS_ptr[ 3 ] & 0x1f ) - 1, // month
.tm_year = ( TY_XDS_ptr[ 5 ] & 0x3f ) + 90, // year
.tm_wday = 0, // day of week
.tm_yday = 0, // day of year
.tm_isdst = 0, // DST
};
time_t time_t = mktime( &tm );
char *timestr;
time_t -= ( ( TIMEZONE - DST ) * 60 * 60 );
timestr = ctime( &time_t );
timestr[ strlen( timestr ) - 1 ] = 0;
sprintf( line, "%sCUR.TIME: %s ", line, timestr );
if ( TY_XDS[ 3 ][ 4 ][ 0 ] )
{
sprintf( line, "%sUTC-%d", line, TIMEZONE );
if (DST) sprintf( line, "%s DST", line );
}
else
sprintf( line, "%sUTC", line );
ty_AddXDSToDisplay( line );
break;
}
case 0x0704: //misc. local time zone
{
sprintf( line, "%sTIMEZONE: UTC-%d",
line, TY_XDS_ptr[ 0 ] & 0x1f );
if ( TY_XDS_ptr[ 0 ] & 0x20 ) sprintf( line, "%s DST", line );
ty_AddXDSToDisplay( line );
break;
}
default:
{
mp_msg( MSGT_DEMUX, MSGL_DBG3, "UNKNOWN CLASS %d TYPE %d",
( TY_XDS_mode << 1 ) + 1, TY_XDS_type );
if ( TY_OSD_debug > 1 )
{
int x;
mp_msg( MSGT_DEMUX, MSGL_DBG3, "\nDUMP:\n" );
for ( x = 0 ; x < TY_XDS_length ; x++ )
mp_msg( MSGT_DEMUX, MSGL_DBG3, " %02x %c",
TY_XDS_ptr[ x ], TY_XDS_ptr[ x ] );
mp_msg( MSGT_DEMUX, MSGL_DBG3, "\n" );
}
}
}
if ( TY_OSD_debug > 1 )
mp_msg( MSGT_DEMUX, MSGL_DBG3, " (%d)", TY_XDS_length );
}
TY_XDS_mode = 0;
TY_XDS_type = 0;
}
else if ( TY_XDS_length < 34 )
{
TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ][ TY_XDS_length++ ] = b1;
TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ][ TY_XDS_length++ ] = b2;
}
return 0;
}
// ===========================================================================
// Callback from Video Display Processing to put up the OSD
// ===========================================================================
void ty_processuserdata( const unsigned char* buf, int len )
{
int index;
sub_justify = 1;
if ( subcc_enabled )
{
if ( tyOSDInitialized == 0 )
{
for ( index = 0; index < SUB_MAX_TEXT ; index++ )
{
ty_OSD1.text[ index ] = malloc( TY_CC_MAX_X );
ty_OSD2.text[ index ] = malloc( TY_CC_MAX_X );
}
ty_ClearOSD( 0 );
ty_OSD1.lines = SUB_MAX_TEXT;
ty_OSD2.lines = SUB_MAX_TEXT;
ty_pOSD1 = &ty_OSD1;
ty_pOSD2 = &ty_OSD2;
tyOSDUpdate = 0;
tyOSDInitialized = 1;
}
if ( buf[ 0 ] == 0x01 )
{
ty_CCdecode( buf[ 1 ], buf[ 2 ] );
}
if ( buf[ 0 ] == 0x02 )
{
ty_XDSdecode( buf[ 1 ], buf[ 2 ] );
}
ty_DisplayXDSInfo();
if ( tyOSDUpdate )
{
// for ( index = 0; index < SUB_MAX_TEXT ; index++ )
// {
// printf( "OSD:%d:%s\n", index, ty_OSD1.text[ index ] );
// }
vo_sub = &ty_OSD1;
vo_osd_changed( OSDTYPE_SUBTITLE );
tyOSDUpdate = 0;
}
}
}

View File

@ -1,25 +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_TY_OSD_H
#define MPLAYER_DEMUX_TY_OSD_H
void ty_ClearOSD(int start);
void ty_processuserdata(const unsigned char *buf, int len);
#endif /* MPLAYER_DEMUX_TY_OSD_H */

View File

@ -1,240 +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 <libavutil/common.h>
#include <libavutil/intreadwrite.h>
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
#include "libmpcodecs/vqf.h"
static int demux_probe_vqf(demuxer_t* demuxer)
{
char buf[KEYWORD_BYTES];
stream_t *s;
s = demuxer->stream;
if(stream_read(s,buf,KEYWORD_BYTES)!=KEYWORD_BYTES)
return 0;
if(memcmp(buf,"TWIN",KEYWORD_BYTES)==0) return DEMUXER_TYPE_VQF; /*version: 97012000*/
return 0;
}
static demuxer_t* demux_open_vqf(demuxer_t* demuxer) {
sh_audio_t* sh_audio;
WAVEFORMATEX* w;
stream_t *s;
headerInfo *hi;
s = demuxer->stream;
sh_audio = new_sh_audio(demuxer,0);
sh_audio->wf = w = calloc(1, sizeof(*sh_audio->wf)+sizeof(headerInfo));
hi = (headerInfo *)&w[1];
w->wFormatTag = 0x1;
sh_audio->format = mmioFOURCC('T','W','I','N'); /* TWinVQ */
w->nChannels = sh_audio->channels = 2;
w->nSamplesPerSec = sh_audio->samplerate = 44100;
w->nAvgBytesPerSec = w->nSamplesPerSec*sh_audio->channels*2;
w->nBlockAlign = 0;
sh_audio->samplesize = 2;
w->wBitsPerSample = 8*sh_audio->samplesize;
w->cbSize = 0;
strcpy(hi->ID,"TWIN");
stream_read(s,hi->ID+KEYWORD_BYTES,VERSION_BYTES); /* fourcc+version_id */
while(1)
{
char chunk_id[4];
unsigned chunk_size;
hi->size=chunk_size=stream_read_dword(s); /* include itself */
stream_read(s,chunk_id,4);
if (chunk_size < 8) return NULL;
chunk_size -= 8;
if(AV_RL32(chunk_id)==mmioFOURCC('C','O','M','M'))
{
char buf[BUFSIZ];
unsigned i,subchunk_size;
if (chunk_size > sizeof(buf) || chunk_size < 20) return NULL;
if(stream_read(s,buf,chunk_size)!=chunk_size) return NULL;
i=0;
subchunk_size = AV_RB32(buf);
hi->channelMode = AV_RB32(buf + 4);
w->nChannels=sh_audio->channels=hi->channelMode+1; /*0-mono;1-stereo*/
hi->bitRate = AV_RB32(buf + 8);
sh_audio->i_bps=hi->bitRate*1000/8; /* bitrate kbit/s */
w->nAvgBytesPerSec = sh_audio->i_bps;
hi->samplingRate = AV_RB32(buf + 12);
switch(hi->samplingRate){
case 44:
w->nSamplesPerSec=44100;
break;
case 22:
w->nSamplesPerSec=22050;
break;
case 11:
w->nSamplesPerSec=11025;
break;
default:
w->nSamplesPerSec=hi->samplingRate*1000;
break;
}
sh_audio->samplerate=w->nSamplesPerSec;
hi->securityLevel = AV_RB32(buf + 16);
w->nBlockAlign = 0;
sh_audio->samplesize = 4;
w->wBitsPerSample = 8*sh_audio->samplesize;
w->cbSize = 0;
if (subchunk_size > chunk_size - 4) continue;
i+=subchunk_size+4;
while(i + 8 < chunk_size)
{
unsigned slen,sid;
char sdata[BUFSIZ];
sid = AV_RL32(buf + i); i+=4;
slen = AV_RB32(buf + i); i+=4;
if (slen > sizeof(sdata) - 1 || slen > chunk_size - i) break;
if(sid==mmioFOURCC('D','S','I','Z'))
{
hi->Dsiz=AV_RB32(buf + i);
continue; /* describes the same info as size of DATA chunk */
}
memcpy(sdata,&buf[i],slen); sdata[slen]=0; i+=slen;
if(sid==mmioFOURCC('N','A','M','E'))
{
memcpy(hi->Name,sdata,FFMIN(BUFSIZ,slen));
demux_info_add(demuxer,"Title",sdata);
}
else
if(sid==mmioFOURCC('A','U','T','H'))
{
memcpy(hi->Auth,sdata,FFMIN(BUFSIZ,slen));
demux_info_add(demuxer,"Author",sdata);
}
else
if(sid==mmioFOURCC('C','O','M','T'))
{
memcpy(hi->Comt,sdata,FFMIN(BUFSIZ,slen));
demux_info_add(demuxer,"Comment",sdata);
}
else
if(sid==mmioFOURCC('(','c',')',' '))
{
memcpy(hi->Cpyr,sdata,FFMIN(BUFSIZ,slen));
demux_info_add(demuxer,"Copyright",sdata);
}
else
if(sid==mmioFOURCC('F','I','L','E'))
{
memcpy(hi->File,sdata,FFMIN(BUFSIZ,slen));
}
else
if(sid==mmioFOURCC('A','L','B','M')) demux_info_add(demuxer,"Album",sdata);
else
if(sid==mmioFOURCC('Y','E','A','R')) demux_info_add(demuxer,"Date",sdata);
else
if(sid==mmioFOURCC('T','R','A','C')) demux_info_add(demuxer,"Track",sdata);
else
if(sid==mmioFOURCC('E','N','C','D')) demux_info_add(demuxer,"Encoder",sdata);
else
mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled subchunk '%c%c%c%c'='%s'\n",((char *)&sid)[0],((char *)&sid)[1],((char *)&sid)[2],((char *)&sid)[3],sdata);
/* rest not recognized due to untranslatable Japanese expressions */
}
}
else
if(AV_RL32(chunk_id)==mmioFOURCC('D','A','T','A'))
{
demuxer->movi_start=stream_tell(s);
demuxer->movi_end=demuxer->movi_start+chunk_size;
mp_msg(MSGT_DEMUX, MSGL_V, "Found data at %"PRIX64" size %"PRIu64"\n",demuxer->movi_start,demuxer->movi_end);
/* Done! play it */
break;
}
else
{
mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled chunk '%c%c%c%c' %u bytes\n",chunk_id[0],chunk_id[1],chunk_id[2],chunk_id[3],chunk_size);
stream_skip(s,chunk_size); /*unknown chunk type */
}
}
demuxer->audio->id = 0;
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
stream_seek(s,demuxer->movi_start);
demuxer->seekable=0;
return demuxer;
}
static int demux_vqf_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) {
sh_audio_t* sh_audio = demuxer->audio->sh;
int l = sh_audio->wf->nAvgBytesPerSec;
off_t spos = stream_tell(demuxer->stream);
demux_packet_t* dp;
if(stream_eof(demuxer->stream))
return 0;
dp = new_demux_packet(l);
ds->pts = spos / (float)(sh_audio->wf->nAvgBytesPerSec);
ds->pos = spos;
l=stream_read(demuxer->stream,dp->buffer,l);
resize_demux_packet(dp,l);
ds_add_packet(ds,dp);
return 1;
}
static void demux_seek_vqf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
#if 0
stream_t* s = demuxer->stream;
sh_audio_t* sh_audio = demuxer->audio->sh;
off_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 * sh_audio->samplesize) );
stream_seek(s,pos);
#endif
}
static void demux_close_vqf(demuxer_t* demuxer) {}
const demuxer_desc_t demuxer_desc_vqf = {
"TwinVQ demuxer",
"vqf",
"VQF",
"Nick Kurshev",
"ported from MPlayerXP",
DEMUXER_TYPE_VQF,
1, // safe autodetect
demux_probe_vqf,
demux_vqf_fill_buffer,
demux_open_vqf,
demux_close_vqf,
demux_seek_vqf,
NULL
};

View File

@ -1,325 +0,0 @@
/*
* Y4M file parser
* copyright (c) 2001 Rik Snel
* (using yuv4mpeg*.[ch] from mjpeg.sourceforge.net)
* (derived from demux_viv.c)
* older YUV4MPEG (used by xawtv) support by Alex Beregszaszi
*
* 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 <string.h> /* strtok */
#include "config.h"
#include "mp_msg.h"
#include "yuv4mpeg.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
typedef struct {
int framenum;
y4m_stream_info_t* si;
int is_older;
} y4m_priv_t;
static int y4m_check_file(demuxer_t* demuxer){
int orig_pos = stream_tell(demuxer->stream);
char buf[10];
y4m_priv_t* priv;
mp_msg(MSGT_DEMUX, MSGL_V, "Checking for YUV4MPEG2\n");
if(stream_read(demuxer->stream, buf, 9)!=9)
return 0;
buf[9] = 0;
if (strncmp("YUV4MPEG2", buf, 9) && strncmp("YUV4MPEG ", buf, 9)) {
return 0;
}
demuxer->priv = malloc(sizeof(y4m_priv_t));
priv = demuxer->priv;
priv->is_older = 0;
if (!strncmp("YUV4MPEG ", buf, 9))
{
mp_msg(MSGT_DEMUX, MSGL_V, "Found older YUV4MPEG format (used by xawtv)\n");
priv->is_older = 1;
}
mp_msg(MSGT_DEMUX,MSGL_DBG2,"Success: YUV4MPEG2\n");
stream_seek(demuxer->stream, orig_pos);
return DEMUXER_TYPE_Y4M;
}
static void read_streaminfo(demuxer_t *demuxer);
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
static int demux_y4m_fill_buffer(demuxer_t *demux, demux_stream_t *dsds) {
demux_stream_t *ds=demux->video;
demux_packet_t *dp;
y4m_priv_t *priv=demux->priv;
y4m_frame_info_t fi;
unsigned char *buf[3];
int err, size;
int nextc;
// Concatenated stream check; only done if seekable so skip(-1) works
if (demux->stream->flags & MP_STREAM_SEEK_BW) {
nextc = stream_read_char(demux->stream);
stream_skip(demux->stream, -1);
if (nextc == 'Y') {
read_streaminfo(demux);
demux->seekable = 0;
}
}
y4m_init_frame_info(&fi);
demux->filepos=stream_tell(demux->stream);
size = ((sh_video_t*)ds->sh)->disp_w*((sh_video_t*)ds->sh)->disp_h;
dp = new_demux_packet(3*size/2);
/* swap U and V components */
buf[0] = dp->buffer;
buf[1] = dp->buffer + 5*size/4;
buf[2] = dp->buffer + size;
if (priv->is_older)
{
int c;
c = stream_read_char(demux->stream); /* F */
if (c == -256)
return 0; /* EOF */
if (c != 'F')
{
mp_msg(MSGT_DEMUX, MSGL_V, "Bad frame at %d\n", (int)stream_tell(demux->stream)-1);
return 0;
}
stream_skip(demux->stream, 5); /* RAME\n */
stream_read(demux->stream, buf[0], size);
stream_read(demux->stream, buf[1], size/4);
stream_read(demux->stream, buf[2], size/4);
}
else
{
if ((err=y4m_read_frame(demux->stream, priv->si, &fi, buf)) != Y4M_OK) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "error reading frame %s\n", y4m_strerr(err));
return 0;
}
}
/* This seems to be the right way to calculate the presentation time stamp */
dp->pts=(float)priv->framenum/((sh_video_t*)ds->sh)->fps;
priv->framenum++;
dp->pos=demux->filepos;
ds_add_packet(ds, dp);
return 1;
}
static void read_streaminfo(demuxer_t *demuxer)
{
y4m_priv_t *priv = demuxer->priv;
sh_video_t *sh = demuxer->video->sh;
y4m_ratio_t ratio;
int err;
if (priv->is_older)
{
char buf[4];
int frame_rate_code;
stream_skip(demuxer->stream, 8); /* YUV4MPEG */
stream_skip(demuxer->stream, 1); /* space */
stream_read(demuxer->stream, (char *)&buf[0], 3);
buf[3] = 0;
sh->disp_w = atoi(buf);
stream_skip(demuxer->stream, 1); /* space */
stream_read(demuxer->stream, (char *)&buf[0], 3);
buf[3] = 0;
sh->disp_h = atoi(buf);
stream_skip(demuxer->stream, 1); /* space */
stream_read(demuxer->stream, (char *)&buf[0], 1);
buf[1] = 0;
frame_rate_code = atoi(buf);
stream_skip(demuxer->stream, 1); /* new-line */
if (!sh->fps)
{
/* values from xawtv */
switch(frame_rate_code)
{
case 1:
sh->fps = 23.976f;
break;
case 2:
sh->fps = 24.0f;
break;
case 3:
sh->fps = 25.0f;
break;
case 4:
sh->fps = 29.97f;
break;
case 5:
sh->fps = 30.0f;
break;
case 6:
sh->fps = 50.0f;
break;
case 7:
sh->fps = 59.94f;
break;
case 8:
sh->fps = 60.0f;
break;
default:
sh->fps = 25.0f;
}
}
sh->frametime = 1.0f/sh->fps;
}
else
{
y4m_init_stream_info(priv->si);
if ((err=y4m_read_stream_header(demuxer->stream, priv->si)) != Y4M_OK)
mp_msg(MSGT_DEMUXER, MSGL_FATAL, "error parsing YUV4MPEG header: %s\n", y4m_strerr(err));
if(!sh->fps) {
ratio = y4m_si_get_framerate(priv->si);
if (ratio.d != 0)
sh->fps=(float)ratio.n/(float)ratio.d;
else
sh->fps=15.0f;
}
sh->frametime=1.0f/sh->fps;
ratio = y4m_si_get_sampleaspect(priv->si);
sh->disp_w = y4m_si_get_width(priv->si);
sh->disp_h = y4m_si_get_height(priv->si);
if (ratio.d != 0 && ratio.n != 0)
sh->aspect = (float)(sh->disp_w*ratio.n)/(float)(sh->disp_h*ratio.d);
demuxer->seekable = 0;
}
sh->format = mmioFOURCC('Y', 'V', '1', '2');
sh->bih->biSize=40;
sh->bih->biWidth = sh->disp_w;
sh->bih->biHeight = sh->disp_h;
sh->bih->biPlanes=3;
sh->bih->biBitCount=12;
sh->bih->biCompression=sh->format;
sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3/2; /* YV12 */
mp_msg(MSGT_DEMUX, MSGL_INFO, "YUV4MPEG2 Video stream %d size: display: %dx%d, codec: %ux%u\n",
demuxer->video->id, sh->disp_w, sh->disp_h, sh->bih->biWidth,
sh->bih->biHeight);
}
static demuxer_t* demux_open_y4m(demuxer_t* demuxer){
y4m_priv_t* priv = demuxer->priv;
sh_video_t* sh=new_sh_video(demuxer,0);
priv->framenum = 0;
priv->si = malloc(sizeof(y4m_stream_info_t));
sh->bih=calloc(1, sizeof(*sh->bih));
demuxer->video->sh=sh;
sh->ds=demuxer->video;
demuxer->video->id=0;
read_streaminfo(demuxer);
return demuxer;
}
static void demux_seek_y4m(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) {
sh_video_t* sh = demuxer->video->sh;
y4m_priv_t* priv = demuxer->priv;
int rel_seek_frames = sh->fps*rel_seek_secs;
int size = 3*sh->disp_w*sh->disp_h/2;
off_t curr_pos = stream_tell(demuxer->stream);
if (priv->framenum + rel_seek_frames < 0) rel_seek_frames = -priv->framenum;
//printf("seektoframe=%d rel_seek_secs=%f seektooffset=%ld\n", priv->framenum + rel_seek_frames, rel_seek_secs, curr_pos + rel_seek_frames*(size+6));
//printf("framenum=%d, curr_pos=%ld, currpos/(size+6)=%f\n", priv->framenum, curr_pos, (float)curr_pos/(float)(size+6));
priv->framenum += rel_seek_frames;
if (priv->is_older) {
/* Well this is easy: every frame takes up size+6 bytes
* in the stream and we may assume that the stream pointer
* is always at the beginning of a frame.
* framenum is the number of the frame that is about to be
* demuxed (counting from ONE (see demux_open_y4m)) */
stream_seek(demuxer->stream, curr_pos + rel_seek_frames*(size+6));
} else {
/* should never come here, because seeking for YUV4MPEG2
* is disabled. */
mp_msg(MSGT_DEMUX, MSGL_WARN, "Seeking for YUV4MPEG2 not yet implemented!\n");
}
}
static void demux_close_y4m(demuxer_t *demuxer)
{
y4m_priv_t* priv = demuxer->priv;
if(!priv)
return;
if (!priv->is_older)
y4m_fini_stream_info(((y4m_priv_t*)demuxer->priv)->si);
free(((y4m_priv_t*)demuxer->priv)->si);
free(demuxer->priv);
return;
}
const demuxer_desc_t demuxer_desc_y4m = {
"YUV4MPEG2 demuxer",
"y4m",
"YUV4MPEG2",
"Rik snel",
"",
DEMUXER_TYPE_Y4M,
1, // safe autodetect
y4m_check_file,
demux_y4m_fill_buffer,
demux_open_y4m,
demux_close_y4m,
demux_seek_y4m,
NULL
};

View File

@ -58,41 +58,19 @@ 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_y4m;
extern const demuxer_desc_t demuxer_desc_asf;
extern const demuxer_desc_t demuxer_desc_real;
extern const demuxer_desc_t demuxer_desc_smjpeg;
extern const demuxer_desc_t demuxer_desc_matroska;
extern const demuxer_desc_t demuxer_desc_realaudio;
extern const demuxer_desc_t demuxer_desc_vqf;
extern const demuxer_desc_t demuxer_desc_mov;
extern const demuxer_desc_t demuxer_desc_vivo;
extern const demuxer_desc_t demuxer_desc_fli;
extern const demuxer_desc_t demuxer_desc_film;
extern const demuxer_desc_t demuxer_desc_roq;
extern const demuxer_desc_t demuxer_desc_gif;
extern const demuxer_desc_t demuxer_desc_ogg;
extern const demuxer_desc_t demuxer_desc_avs;
extern const demuxer_desc_t demuxer_desc_pva;
extern const demuxer_desc_t demuxer_desc_nsv;
extern const demuxer_desc_t demuxer_desc_mpeg_ts;
extern const demuxer_desc_t demuxer_desc_lmlm4;
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_es;
extern const demuxer_desc_t demuxer_desc_mpeg_gxf;
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_rawdv;
extern const demuxer_desc_t demuxer_desc_mpc;
extern const demuxer_desc_t demuxer_desc_audio;
extern const demuxer_desc_t demuxer_desc_mpeg_ty;
extern const demuxer_desc_t demuxer_desc_rtp;
extern const demuxer_desc_t demuxer_desc_rtp_nemesi;
extern const demuxer_desc_t demuxer_desc_lavf;
extern const demuxer_desc_t demuxer_desc_lavf_preferred;
extern const demuxer_desc_t demuxer_desc_aac;
extern const demuxer_desc_t demuxer_desc_nut;
extern const demuxer_desc_t demuxer_desc_mng;
/* Please do not add any new demuxers here. If you want to implement a new
@ -110,39 +88,16 @@ const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_mf,
&demuxer_desc_lavf_preferred,
&demuxer_desc_avi,
&demuxer_desc_y4m,
&demuxer_desc_asf,
&demuxer_desc_nsv,
&demuxer_desc_real,
&demuxer_desc_smjpeg,
&demuxer_desc_matroska,
&demuxer_desc_realaudio,
&demuxer_desc_vqf,
&demuxer_desc_mov,
&demuxer_desc_vivo,
&demuxer_desc_fli,
&demuxer_desc_film,
&demuxer_desc_roq,
#ifdef CONFIG_GIF
&demuxer_desc_gif,
#endif
#ifdef CONFIG_OGGVORBIS
&demuxer_desc_ogg,
#endif
#ifdef CONFIG_WIN32DLL
&demuxer_desc_avs,
#endif
&demuxer_desc_pva,
&demuxer_desc_mpeg_ts,
&demuxer_desc_lmlm4,
&demuxer_desc_mpeg_ps,
&demuxer_desc_mpeg_pes,
&demuxer_desc_mpeg_es,
&demuxer_desc_mpeg_gxf,
&demuxer_desc_mpeg4_es,
&demuxer_desc_h264_es,
&demuxer_desc_audio,
&demuxer_desc_mpeg_ty,
#ifdef CONFIG_LIVE555
&demuxer_desc_rtp,
#endif
@ -150,15 +105,8 @@ const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_rtp_nemesi,
#endif
&demuxer_desc_lavf,
#ifdef CONFIG_MUSEPACK
&demuxer_desc_mpc,
#endif
#ifdef CONFIG_LIBDV095
&demuxer_desc_rawdv,
#endif
&demuxer_desc_aac,
#ifdef CONFIG_LIBNUT
&demuxer_desc_nut,
#endif
#ifdef CONFIG_MNG
&demuxer_desc_mng,
@ -1002,6 +950,22 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
struct demuxer *demuxer = NULL;
const struct demuxer_desc *desc;
// Some code (e.g. dvd stuff, network code, or extension.c) explicitly
// request certain file formats. The list of formats are always handled by
// libavformat.
// Maybe attempts should be made to convert the mplayer format to the libav
// format, instead of reyling on libav to auto-detect the stream's format
// correctly.
switch (file_format) {
case DEMUXER_TYPE_MPEG_PS:
case DEMUXER_TYPE_MPEG_TS:
case DEMUXER_TYPE_Y4M:
case DEMUXER_TYPE_NSV:
case DEMUXER_TYPE_AAC:
case DEMUXER_TYPE_MPC:
file_format = DEMUXER_TYPE_LAVF;
}
// If somebody requested a demuxer check it
if (file_format) {
desc = get_demuxer_desc_from_type(file_format);

View File

@ -44,47 +44,30 @@ struct MPOpts;
enum demuxer_type {
DEMUXER_TYPE_UNKNOWN = 0,
DEMUXER_TYPE_MPEG_ES,
DEMUXER_TYPE_MPEG_PS,
DEMUXER_TYPE_AVI,
DEMUXER_TYPE_AVI_NI,
DEMUXER_TYPE_AVI_NINI,
DEMUXER_TYPE_ASF,
DEMUXER_TYPE_MOV,
DEMUXER_TYPE_VIVO,
DEMUXER_TYPE_TV,
DEMUXER_TYPE_FLI,
DEMUXER_TYPE_REAL,
DEMUXER_TYPE_Y4M,
DEMUXER_TYPE_FILM,
DEMUXER_TYPE_ROQ,
DEMUXER_TYPE_MF,
DEMUXER_TYPE_AUDIO,
DEMUXER_TYPE_OGG,
DEMUXER_TYPE_RAWAUDIO,
DEMUXER_TYPE_RTP,
DEMUXER_TYPE_RAWDV,
DEMUXER_TYPE_PVA,
DEMUXER_TYPE_SMJPEG,
DEMUXER_TYPE_XMMS,
DEMUXER_TYPE_RAWVIDEO,
DEMUXER_TYPE_MPEG4_ES,
DEMUXER_TYPE_GIF,
DEMUXER_TYPE_MPEG_TS,
DEMUXER_TYPE_H264_ES,
DEMUXER_TYPE_MATROSKA,
DEMUXER_TYPE_REALAUDIO,
DEMUXER_TYPE_MPEG_TY,
DEMUXER_TYPE_LMLM4,
DEMUXER_TYPE_LAVF,
DEMUXER_TYPE_NSV,
DEMUXER_TYPE_VQF,
DEMUXER_TYPE_AVS,
DEMUXER_TYPE_AAC,
DEMUXER_TYPE_MPC,
DEMUXER_TYPE_MPEG_PES,
DEMUXER_TYPE_MPEG_GXF,
DEMUXER_TYPE_NUT,
DEMUXER_TYPE_LAVF_PREFERRED,
DEMUXER_TYPE_RTP_NEMESI,
DEMUXER_TYPE_MNG,

View File

@ -38,9 +38,6 @@ static struct {
const char *extension;
int demuxer_type;
} extensions_table[] = {
// { "mpeg", DEMUXER_TYPE_MPEG_PS },
// { "mpg", DEMUXER_TYPE_MPEG_PS },
// { "mpe", DEMUXER_TYPE_MPEG_PS },
{ "vob", DEMUXER_TYPE_MPEG_PS },
{ "m2v", DEMUXER_TYPE_MPEG_PS },
{ "avi", DEMUXER_TYPE_AVI },
@ -58,16 +55,16 @@ static struct {
{ "wav", DEMUXER_TYPE_AUDIO },
{ "flac", DEMUXER_TYPE_AUDIO },
{ "fla", DEMUXER_TYPE_AUDIO },
{ "ogg", DEMUXER_TYPE_OGG },
{ "ogm", DEMUXER_TYPE_OGG },
{ "ogg", DEMUXER_TYPE_LAVF },
{ "ogm", DEMUXER_TYPE_LAVF },
// { "pls", DEMUXER_TYPE_PLAYLIST },
// { "m3u", DEMUXER_TYPE_PLAYLIST },
{ "xm", DEMUXER_TYPE_XMMS },
{ "mod", DEMUXER_TYPE_XMMS },
{ "s3m", DEMUXER_TYPE_XMMS },
{ "it", DEMUXER_TYPE_XMMS },
{ "mid", DEMUXER_TYPE_XMMS },
{ "midi", DEMUXER_TYPE_XMMS },
{ "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 },
@ -75,8 +72,8 @@ static struct {
{ "avs", DEMUXER_TYPE_AVS },
#endif
{ "302", DEMUXER_TYPE_LAVF },
{ "264", DEMUXER_TYPE_H264_ES },
{ "26l", DEMUXER_TYPE_H264_ES },
{ "264", DEMUXER_TYPE_LAVF },
{ "26l", DEMUXER_TYPE_LAVF },
{ "ac3", DEMUXER_TYPE_LAVF },
{ "ape", DEMUXER_TYPE_LAVF },
{ "apl", DEMUXER_TYPE_LAVF },

View File

@ -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 "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;
}

View File

@ -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 */

View File

@ -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 "mp_msg.h"
#include "stream/stream.h"
#include "demuxer.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;
}

View File

@ -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 "demuxer.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 */

View File

@ -1,173 +0,0 @@
/*
* MP4 file format parser code
*
* Copyright (C) 2002 Felix Buenemann <atmosfear at users.sourceforge.net>
* Code inspired by libmp4 from http://mpeg4ip.sourceforge.net/.
*
* 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 <inttypes.h>
#include <stdlib.h>
#include "parse_mp4.h"
#include "mp_msg.h"
#include "stream/stream.h"
//#define MP4_DUMPATOM
#define MP4_DL MSGL_V
#define freereturn(a,b) free(a); return b
static int mp4_read_descr_len(stream_t *s)
{
uint8_t b;
uint8_t numBytes = 0;
uint32_t length = 0;
do {
b = stream_read_char(s);
numBytes++;
length = (length << 7) | (b & 0x7F);
} while ((b & 0x80) && numBytes < 4);
//printf("MP4 read desc len: %d\n", length);
return length;
}
/* parse the data part of MP4 esds atoms */
int mp4_parse_esds(unsigned char *data, int datalen, esds_t *esds) {
/* create memory stream from data */
stream_t *s = new_memory_stream(data, datalen);
uint16_t len;
#ifdef MP4_DUMPATOM
{int i;
printf("ESDS Dump (%dbyte):\n", datalen);
for(i = 0; i < datalen; i++)
printf("%02X ", data[i]);
printf("\nESDS Dumped\n");}
#endif
memset(esds, 0, sizeof(esds_t));
esds->version = stream_read_char(s);
esds->flags = stream_read_int24(s);
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 version: %d flags: 0x%06X\n",
esds->version, esds->flags);
/* get and verify ES_DescrTag */
if (stream_read_char(s) == MP4ESDescrTag) {
/* read length */
len = mp4_read_descr_len(s);
esds->ESId = stream_read_word(s);
esds->streamPriority = stream_read_char(s);
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 ES Descriptor (%dBytes):\n"
" -> ESId: %d\n"
" -> streamPriority: %d\n",
len, esds->ESId, esds->streamPriority);
if (len < (5 + 15)) {
freereturn(s,1);
}
} else {
esds->ESId = stream_read_word(s);
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 ES Descriptor (%dBytes):\n"
" -> ESId: %d\n", 2, esds->ESId);
}
/* get and verify DecoderConfigDescrTab */
if (stream_read_char(s) != MP4DecConfigDescrTag) {
freereturn(s,1);
}
/* read length */
len = mp4_read_descr_len(s);
esds->objectTypeId = stream_read_char(s);
esds->streamType = stream_read_char(s);
esds->bufferSizeDB = stream_read_int24(s);
esds->maxBitrate = stream_read_dword(s);
esds->avgBitrate = stream_read_dword(s);
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 Decoder Config Descriptor (%dBytes):\n"
" -> objectTypeId: %d\n"
" -> streamType: 0x%02X\n"
" -> bufferSizeDB: 0x%06X\n"
" -> maxBitrate: %.3fkbit/s\n"
" -> avgBitrate: %.3fkbit/s\n",
len, esds->objectTypeId, esds->streamType,
esds->bufferSizeDB, esds->maxBitrate/1000.0,
esds->avgBitrate/1000.0);
esds->decoderConfigLen=0;
if (len < 15) {
freereturn(s,0);
}
/* get and verify DecSpecificInfoTag */
if (stream_read_char(s) != MP4DecSpecificDescrTag) {
freereturn(s,0);
}
/* read length */
esds->decoderConfigLen = len = mp4_read_descr_len(s);
esds->decoderConfig = malloc(esds->decoderConfigLen);
if (esds->decoderConfig) {
stream_read(s, esds->decoderConfig, esds->decoderConfigLen);
} else {
esds->decoderConfigLen = 0;
}
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 Decoder Specific Descriptor (%dBytes)\n", len);
/* get and verify SLConfigDescrTag */
if(stream_read_char(s) != MP4SLConfigDescrTag) {
freereturn(s,0);
}
/* Note: SLConfig is usually constant value 2, size 1Byte */
esds->SLConfigLen = len = mp4_read_descr_len(s);
esds->SLConfig = malloc(esds->SLConfigLen);
if (esds->SLConfig) {
stream_read(s, esds->SLConfig, esds->SLConfigLen);
} else {
esds->SLConfigLen = 0;
}
mp_msg(MSGT_DEMUX, MP4_DL,
"ESDS MPEG4 Sync Layer Config Descriptor (%dBytes)\n"
" -> predefined: %d\n", len, esds->SLConfig[0]);
/* will skip the remainder of the atom */
freereturn(s,0);
}
/* cleanup all mem occupied by mp4_parse_esds */
void mp4_free_esds(esds_t *esds) {
if(esds->decoderConfigLen)
free(esds->decoderConfig);
if(esds->SLConfigLen)
free(esds->SLConfig);
}
#undef freereturn
#undef MP4_DL

View File

@ -1,127 +0,0 @@
/*
* MP4 file format parser code
*
* Copyright (C) 2002 Felix Buenemann <atmosfear at users.sourceforge.net>
* Code inspired by libmp4 from http://mpeg4ip.sourceforge.net/.
*
* 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_MP4_H
#define MPLAYER_PARSE_MP4_H
#include <inttypes.h>
/* one byte tag identifiers */
#define MP4ODescrTag 0x01
#define MP4IODescrTag 0x02
#define MP4ESDescrTag 0x03
#define MP4DecConfigDescrTag 0x04
#define MP4DecSpecificDescrTag 0x05
#define MP4SLConfigDescrTag 0x06
#define MP4ContentIdDescrTag 0x07
#define MP4SupplContentIdDescrTag 0x08
#define MP4IPIPtrDescrTag 0x09
#define MP4IPMPPtrDescrTag 0x0A
#define MP4IPMPDescrTag 0x0B
#define MP4RegistrationDescrTag 0x0D
#define MP4ESIDIncDescrTag 0x0E
#define MP4ESIDRefDescrTag 0x0F
#define MP4FileIODescrTag 0x10
#define MP4FileODescrTag 0x11
#define MP4ExtProfileLevelDescrTag 0x13
#define MP4ExtDescrTagsStart 0x80
#define MP4ExtDescrTagsEnd 0xFE
/* object type identifiers in the ESDS */
/* See http://gpac.sourceforge.net/tutorial/mediatypes.htm */
/* BIFS stream version 1 */
#define MP4OTI_MPEG4Systems1 0x01
/* BIFS stream version 2 */
#define MP4OTI_MPEG4Systems2 0x02
/* MPEG-4 visual stream */
#define MP4OTI_MPEG4Visual 0x20
/* MPEG-4 audio stream */
#define MP4OTI_MPEG4Audio 0x40
/* MPEG-2 visual streams with various profiles */
#define MP4OTI_MPEG2VisualSimple 0x60
#define MP4OTI_MPEG2VisualMain 0x61
#define MP4OTI_MPEG2VisualSNR 0x62
#define MP4OTI_MPEG2VisualSpatial 0x63
#define MP4OTI_MPEG2VisualHigh 0x64
#define MP4OTI_MPEG2Visual422 0x65
/* MPEG-2 audio stream part 7 ("AAC") with various profiles */
#define MP4OTI_MPEG2AudioMain 0x66
#define MP4OTI_MPEG2AudioLowComplexity 0x67
#define MP4OTI_MPEG2AudioScaleableSamplingRate 0x68
/* MPEG-2 audio part 3 ("MP3") */
#define MP4OTI_MPEG2AudioPart3 0x69
/* MPEG-1 visual visual stream */
#define MP4OTI_MPEG1Visual 0x6A
/* MPEG-1 audio stream part 3 ("MP3") */
#define MP4OTI_MPEG1Audio 0x6B
/* JPEG visual stream */
#define MP4OTI_JPEG 0x6C
/* 3GPP2 */
#define MP4OTI_13kVoice 0xE1
/* I define uint24 here for better understanding */
#ifndef uint24_t
#define uint24_t uint32_t
#endif
/* esds_t */
typedef struct {
uint8_t version;
uint24_t flags;
/* 0x03 ESDescrTag */
uint16_t ESId;
uint8_t streamPriority;
/* 0x04 DecConfigDescrTag */
uint8_t objectTypeId;
uint8_t streamType;
/* XXX: really streamType is
* only 6bit, followed by:
* 1bit upStream
* 1bit reserved
*/
uint24_t bufferSizeDB;
uint32_t maxBitrate;
uint32_t avgBitrate;
/* 0x05 DecSpecificDescrTag */
uint16_t decoderConfigLen;
uint8_t *decoderConfig;
/* 0x06 SLConfigDescrTag */
uint8_t SLConfigLen;
uint8_t *SLConfig;
/* TODO: add the missing tags,
* I currently have no specs
* for them and doubt they
* are currently needed ::atmos
*/
} esds_t;
int mp4_parse_esds(unsigned char *data, int datalen, esds_t *esds);
void mp4_free_esds(esds_t *esds);
#endif /* MPLAYER_PARSE_MP4_H */

View File

@ -36,8 +36,6 @@
#include "demux_ty_osd.h"
#endif
#include "stheader.h"
#include "parse_es.h"
#include "mpeg_hdr.h"
/* sub_cc (closed captions)*/
#include "sub/sub_cc.h"
@ -49,64 +47,9 @@
#include "demux_rtp.h"
#endif
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_PVA) ||
(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))
) ||
(fmt == DEMUXER_TYPE_MPEG_TY)
#ifdef CONFIG_LIVE555
|| ((fmt == DEMUXER_TYPE_RTP) && demux_is_mpeg_rtp_stream(d_video->demuxer))
#endif
)
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
@ -115,464 +58,22 @@ switch(video_codec){
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 = memalign(8, 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 = memalign(8, 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 = memalign(8, 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 = memalign(8, 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)
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);
}
#ifdef DEMUX_TY_OSD
if( len > 2 && buf[ 0 ] == 'T' && buf[ 1 ] == 'Y' )
{
ty_processuserdata( buf + 2, len - 2 );
return;
}
#endif
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. --------------------
@ -592,10 +93,7 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
frame_time=d_video->pts-pts1;
break;
case DEMUXER_TYPE_TV:
case DEMUXER_TYPE_MOV:
case DEMUXER_TYPE_FILM:
case DEMUXER_TYPE_VIVO:
case DEMUXER_TYPE_OGG:
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;
@ -633,21 +131,8 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
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;
sh_video->pts=d_video->pts;
if(frame_time_ptr) *frame_time_ptr=frame_time;
return in_size;

View File

@ -4237,10 +4237,6 @@ goto_enable_cache:
mpctx->d_video = mpctx->demuxer->video;
mpctx->d_sub = mpctx->demuxer->sub;
if (ts_prog) {
int tmp = ts_prog;
mp_property_do("switch_program", M_PROPERTY_SET, &tmp, mpctx);
}
// select audio stream
for (int i = 0; i < mpctx->num_sources; i++)
select_audio(mpctx->sources[i].demuxer->audio->demuxer, opts->audio_id,
@ -4288,7 +4284,7 @@ goto_enable_cache:
while (!ds->eof) {
unsigned char *start;
int in_size = ds_get_packet(ds, &start);
if ((mpctx->demuxer->file_format == DEMUXER_TYPE_AVI || mpctx->demuxer->file_format == DEMUXER_TYPE_ASF || mpctx->demuxer->file_format == DEMUXER_TYPE_MOV)
if ((mpctx->demuxer->file_format == DEMUXER_TYPE_AVI || mpctx->demuxer->file_format == DEMUXER_TYPE_ASF)
&& stream_dump_type == 2)
fwrite(&in_size, 1, 4, f);
if (in_size > 0) {

View File

@ -65,23 +65,8 @@ int network_ipv4_only_proxy = 0;
const mime_struct_t mime_type_table[] = {
// Flash Video
{ "video/x-flv", DEMUXER_TYPE_LAVF_PREFERRED},
// do not force any demuxer in this case!
// we want the lavf demuxer to be tried first (happens automatically anyway),
// but for mov reference files to work we must also try
// the native demuxer if lavf fails.
{ "video/quicktime", 0 },
// MP3 streaming, some MP3 streaming server answer with audio/mpeg
{ "audio/mpeg", DEMUXER_TYPE_AUDIO },
// MPEG streaming
{ "video/mpeg", DEMUXER_TYPE_UNKNOWN },
{ "video/x-mpeg", DEMUXER_TYPE_UNKNOWN },
{ "video/x-mpeg2", DEMUXER_TYPE_UNKNOWN },
// AVI ??? => video/x-msvideo
{ "video/x-msvideo", DEMUXER_TYPE_AVI },
// MOV => video/quicktime
{ "video/quicktime", DEMUXER_TYPE_MOV },
// ASF
{ "audio/x-ms-wax", DEMUXER_TYPE_ASF },
{ "audio/x-ms-wma", DEMUXER_TYPE_ASF },
@ -91,7 +76,6 @@ const mime_struct_t mime_type_table[] = {
{ "video/x-ms-wma", DEMUXER_TYPE_ASF },
{ "application/x-mms-framed", DEMUXER_TYPE_ASF },
{ "application/vnd.ms.wms-hdr.asfv1", DEMUXER_TYPE_ASF },
{ "application/octet-stream", DEMUXER_TYPE_UNKNOWN },
// Playlists
{ "video/x-ms-wmx", DEMUXER_TYPE_PLAYLIST },
{ "video/x-ms-wvx", DEMUXER_TYPE_PLAYLIST },
@ -100,11 +84,6 @@ const mime_struct_t mime_type_table[] = {
{ "audio/x-pls", DEMUXER_TYPE_PLAYLIST },
// Real Media
// { "audio/x-pn-realaudio", DEMUXER_TYPE_REAL },
// OGG Streaming
{ "application/x-ogg", DEMUXER_TYPE_OGG },
// NullSoft Streaming Video
{ "video/nsv", DEMUXER_TYPE_NSV},
{ "misc/ultravox", DEMUXER_TYPE_NSV},
{ NULL, DEMUXER_TYPE_UNKNOWN},
};