diff options
54 files changed, 34 insertions, 19301 deletions
@@ -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 \ diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 489419d941..8dc026a00d 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -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), @@ -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"); @@ -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 */ diff --git a/etc/codecs.conf b/etc/codecs.conf index 5120406f12..e4618a92d0 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -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 diff --git a/libmpcodecs/ad.c b/libmpcodecs/ad.c index 0ab5d44971..dce8f9f710 100644 --- a/libmpcodecs/ad.c +++ b/libmpcodecs/ad.c @@ -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 diff --git a/libmpcodecs/ad_dk3adpcm.c b/libmpcodecs/ad_dk3adpcm.c deleted file mode 100644 index 15027f88b1..0000000000 --- a/libmpcodecs/ad_dk3adpcm.c +++ /dev/null @@ -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); -} diff --git a/libmpcodecs/ad_libvorbis.c b/libmpcodecs/ad_libvorbis.c deleted file mode 100644 index a768095187..0000000000 --- a/libmpcodecs/ad_libvorbis.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/ad_mpc.c b/libmpcodecs/ad_mpc.c deleted file mode 100644 index 979dce6178..0000000000 --- a/libmpcodecs/ad_mpc.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/ad_speex.c b/libmpcodecs/ad_speex.c deleted file mode 100644 index c9ac1a42c6..0000000000 --- a/libmpcodecs/ad_speex.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/ad_twin.c b/libmpcodecs/ad_twin.c deleted file mode 100644 index 9aa304e4fc..0000000000 --- a/libmpcodecs/ad_twin.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c index a221a089b4..804b4d60b4 100644 --- a/libmpcodecs/dec_video.c +++ b/libmpcodecs/dec_video.c @@ -31,7 +31,6 @@ #include "stream/stream.h" #include "libmpdemux/demuxer.h" -#include "libmpdemux/parse_es.h" #include "codec-cfg.h" diff --git a/libmpcodecs/vd.c b/libmpcodecs/vd.c index c01796ac78..e7a497009a 100644 --- a/libmpcodecs/vd.c +++ b/libmpcodecs/vd.c @@ -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 diff --git a/libmpcodecs/vd_mpegpes.c b/libmpcodecs/vd_mpegpes.c deleted file mode 100644 index 22060bfc60..0000000000 --- a/libmpcodecs/vd_mpegpes.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/vd_sgi.c b/libmpcodecs/vd_sgi.c deleted file mode 100644 index 1ec9b2e868..0000000000 --- a/libmpcodecs/vd_sgi.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/vd_theora.c b/libmpcodecs/vd_theora.c deleted file mode 100644 index ba3c0d5d86..0000000000 --- a/libmpcodecs/vd_theora.c +++ /dev/null @@ -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; -} diff --git a/libmpcodecs/vd_xvid4.c b/libmpcodecs/vd_xvid4.c deleted file mode 100644 index c5e25cd1d6..0000000000 --- a/libmpcodecs/vd_xvid4.c +++ /dev/null @@ -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 */ diff --git a/libmpdemux/aac_hdr.c b/libmpdemux/aac_hdr.c deleted file mode 100644 index 36991e27a2..0000000000 --- a/libmpdemux/aac_hdr.c +++ /dev/null @@ -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; -} diff --git a/libmpdemux/aac_hdr.h b/libmpdemux/aac_hdr.h deleted file mode 100644 index be56368925..0000000000 --- a/libmpdemux/aac_hdr.h +++ /dev/null @@ -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 */ diff --git a/libmpdemux/demux_aac.c b/libmpdemux/demux_aac.c deleted file mode 100644 index 9d37d75cf8..0000000000 --- a/libmpdemux/demux_aac.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_avi.c b/libmpdemux/demux_avi.c index f73648166c..3841cf2736 100644 --- a/libmpdemux/demux_avi.c +++ b/libmpdemux/demux_avi.c @@ -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 diff --git a/libmpdemux/demux_film.c b/libmpdemux/demux_film.c deleted file mode 100644 index 713c9ea26e..0000000000 --- a/libmpdemux/demux_film.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_fli.c b/libmpdemux/demux_fli.c deleted file mode 100644 index e89fa75d97..0000000000 --- a/libmpdemux/demux_fli.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_lmlm4.c b/libmpdemux/demux_lmlm4.c deleted file mode 100644 index 739343cdb4..0000000000 --- a/libmpdemux/demux_lmlm4.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_mov.c b/libmpdemux/demux_mov.c deleted file mode 100644 index 96fb1a2d86..0000000000 --- a/libmpdemux/demux_mov.c +++ /dev/null @@ -1,2350 +0,0 @@ -/* - * QuickTime MOV file parser - * copyright(c) 2001 A'rpi - * additional work by Atmos - * based on TOOLS/movinfo.c by A'rpi & Al3x - * compressed header support from moov.c of the openquicktime lib. - * - * references: http://openquicktime.sf.net/, http://www.heroinewarrior.com/ - * http://www.geocities.com/SiliconValley/Lakes/2160/fformats/files/mov.pdf - * (above URL no longer works, file mirrored somewhere? ::atmos) - * The QuickTime File Format PDF from Apple: - * http://developer.apple.com/techpubs/quicktime/qtdevdocs/PDF/QTFileFormat.pdf - * (Complete list of documentation at http://developer.apple.com/quicktime/) - * MP4-Lib sources from http://mpeg4ip.sf.net/ might be useful for .mp4 - * as well as .mov specific stuff. - * - * All sort of Stuff about MPEG4: - * http://www.cmlab.csie.ntu.edu.tw/~pkhsiao/thesis.html - * I really recommend N4270-1.doc and N4270-2.doc which are exact specs - * of the MP4-File Format and the MPEG4 Specific extensions. ::atmos - * TSGS#15(02)0088 - * http://www.3gpp.org/ftp/tsg_sa/TSG_SA/TSGS_15/Docs/pdf/SP-020088.pdf - * http://www.3gpp2.org/Public_html/specs/C.S0050-0_v1.0_121503.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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <inttypes.h> - -#include <libavutil/common.h> -#include <libavutil/intreadwrite.h> - -#include "config.h" - -#ifdef CONFIG_QUICKTIME -#include <QuickTime/QuickTime.h> -#include <QuickTime/ImageCompression.h> -#include <QuickTime/ImageCodec.h> -#else -#include "loader/qtx/qtxsdk/components.h" -#endif - -#if CONFIG_ZLIB -#include <zlib.h> -#endif - -#ifndef _FCNTL_H -#include <fcntl.h> -#endif - -#include "mp_msg.h" - -#include "stream/stream.h" -#include "demuxer.h" -#include "stheader.h" - -#include "libmpcodecs/img_format.h" - -#include "sub/sub.h" - -#include "demux_mov.h" -#include "qtpalette.h" -#include "parse_mp4.h" // .MP4 specific stuff - -#define char2short(x,y) AV_RB16(&(x)[(y)]) -#define char2int(x,y) AV_RB32(&(x)[(y)]) - -typedef struct { - unsigned int pts; // duration - unsigned int size; - off_t pos; -} mov_sample_t; - -typedef struct { - unsigned int sample; // number of the first sample in the chunk - unsigned int size; // number of samples in the chunk - int desc; // for multiple codecs mode - not used - off_t pos; -} mov_chunk_t; - -typedef struct { - unsigned int first; - unsigned int spc; - unsigned int sdid; -} mov_chunkmap_t; - -typedef struct { - unsigned int num; - unsigned int dur; -} mov_durmap_t; - -typedef struct { - unsigned int dur; - unsigned int pos; - int speed; - // - int frames; - int start_sample; - int start_frame; - int pts_offset; -} mov_editlist_t; - -#define MOV_TRAK_UNKNOWN 0 -#define MOV_TRAK_VIDEO 1 -#define MOV_TRAK_AUDIO 2 -#define MOV_TRAK_FLASH 3 -#define MOV_TRAK_GENERIC 4 -#define MOV_TRAK_CODE 5 - -typedef struct { - int id; - int type; - off_t pos; - // - unsigned int media_handler; - unsigned int data_handler; - // - int timescale; - unsigned int length; - int samplesize; // 0 = variable - int duration; // 0 = variable - int width,height; // for video - unsigned int fourcc; - unsigned int nchannels; - unsigned int samplebytes; - // - int tkdata_len; // track data - unsigned char* tkdata; - int stdata_len; // stream data - unsigned char* stdata; - // - unsigned char* stream_header; - int stream_header_len; // if >0, this header should be sent before the 1st frame - // - int samples_size; - mov_sample_t* samples; - int chunks_size; - mov_chunk_t* chunks; - int chunkmap_size; - mov_chunkmap_t* chunkmap; - int durmap_size; - mov_durmap_t* durmap; - int keyframes_size; - unsigned int* keyframes; - int editlist_size; - mov_editlist_t* editlist; - int editlist_pos; - // - void* desc; // image/sound/etc description (pointer to ImageDescription etc) -} mov_track_t; - -static void mov_build_index(mov_track_t* trak,int timescale){ - int i,j,s; - int last=trak->chunks_size; - unsigned int pts=0; - -#if 0 - if (trak->chunks_size <= 0) - { - mp_msg(MSGT_DEMUX, MSGL_WARN, "No chunk offset table, trying to build one!\n"); - - trak->chunks_size = trak->samples_size; /* XXX: FIXME ! */ - // audit: this code will be vulnerable if it is reenabled (currently #if 0) - trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t)*trak->chunks_size); - - for (i=0; i < trak->chunks_size; i++) - trak->chunks[i].pos = -1; - } -#endif - - mp_msg(MSGT_DEMUX, MSGL_V, "MOV track #%d: %d chunks, %d samples\n",trak->id,trak->chunks_size,trak->samples_size); - mp_msg(MSGT_DEMUX, MSGL_V, "pts=%d scale=%d time=%5.3f\n",trak->length,trak->timescale,(float)trak->length/(float)trak->timescale); - - // process chunkmap: - i=trak->chunkmap_size; - while(i>0){ - --i; - j=trak->chunkmap[i].first; - for(;j>=0 && j<last;j++){ - trak->chunks[j].desc=trak->chunkmap[i].sdid; - trak->chunks[j].size=trak->chunkmap[i].spc; - } - last=FFMIN(trak->chunkmap[i].first, trak->chunks_size); - } - -#if 0 - for (i=0; i < trak->chunks_size; i++) - { - /* fixup position */ - if (trak->chunks[i].pos == -1) - if (i > 0) - trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size; - else - trak->chunks[i].pos = 0; /* FIXME: set initial pos */ -#endif - - // calc pts of chunks: - s=0; - for(j=0;j<trak->chunks_size;j++){ - trak->chunks[j].sample=s; - s+=trak->chunks[j].size; - } - i = 0; - for (j = 0; j < trak->durmap_size; j++) - i += trak->durmap[j].num; - if (i != s) { - mp_msg(MSGT_DEMUX, MSGL_WARN, - "MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s); - if (i > s) s = i; - } - - // workaround for fixed-size video frames (dv and uncompressed) - if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){ - trak->samples=calloc(s, sizeof(mov_sample_t)); - trak->samples_size=trak->samples ? s : 0; - for(i=0;i<trak->samples_size;i++) - trak->samples[i].size=trak->samplesize; - trak->samplesize=0; - } - - if(!trak->samples_size){ - // constant sampesize - if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){ - trak->duration=trak->durmap[0].dur; - } else mp_msg(MSGT_DEMUX, MSGL_ERR, "*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n"); - return; - } - - if (trak->samples_size < s) { - mp_msg(MSGT_DEMUX, MSGL_WARN, - "MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n", - s, trak->samples_size); - free(trak->samples); - trak->samples = calloc(s, sizeof(mov_sample_t)); - trak->samples_size = trak->samples ? s : 0; - } - - // calc pts: - s=0; - for(j=0;j<trak->durmap_size;j++){ - for(i=0;i<trak->durmap[j].num;i++){ - if (s >= trak->samples_size) - break; - trak->samples[s].pts=pts; - ++s; - pts+=trak->durmap[j].dur; - } - } - - // calc sample offsets - s=0; - for(j=0;j<trak->chunks_size;j++){ - off_t pos=trak->chunks[j].pos; - for(i=0;i<trak->chunks[j].size;i++){ - if (s >= trak->samples_size) - break; - trak->samples[s].pos=pos; - mp_msg(MSGT_DEMUX, MSGL_DBG3, "Sample %5d: pts=%8d off=0x%08X size=%d\n",s, - trak->samples[s].pts, - (int)trak->samples[s].pos, - trak->samples[s].size); - pos+=trak->samples[s].size; - ++s; - } - } - - // precalc editlist entries - if(trak->editlist_size>0){ - int frame=0; - int e_pts=0; - for(i=0;i<trak->editlist_size;i++){ - mov_editlist_t* el=&trak->editlist[i]; - int sample=0; - int pts=el->pos; - el->start_frame=frame; - if(pts<0){ - // skip! - el->frames=0; continue; - } - // find start sample - for(;sample<trak->samples_size;sample++){ - if(pts<=trak->samples[sample].pts) break; - } - el->start_sample=sample; - el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts; - pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale; - e_pts+=el->dur; - // find end sample - for(;sample<trak->samples_size;sample++){ - if(pts<trak->samples[sample].pts) break; - } - el->frames=sample-el->start_sample; - frame+=el->frames; - mp_msg(MSGT_DEMUX,MSGL_V,"EL#%d: pts=%d 1st_sample=%d frames=%d (%5.3fs) pts_offs=%d\n",i, - el->pos,el->start_sample, el->frames, - (float)(el->dur)/(float)timescale, el->pts_offset); - } - } - -} - -#define MOV_MAX_TRACKS 256 -#define MOV_MAX_SUBLEN 1024 - -typedef struct { - off_t moov_start; - off_t moov_end; - off_t mdat_start; - off_t mdat_end; - int track_db; - mov_track_t* tracks[MOV_MAX_TRACKS]; - int timescale; // movie timescale - int duration; // movie duration (in movie timescale units) - subtitle subs; - char subtext[MOV_MAX_SUBLEN + 1]; - int current_sub; -} mov_priv_t; - -#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) - -static int mov_check_file(demuxer_t* demuxer){ - int flags=0; - int no=0; - mov_priv_t* priv=calloc(1, sizeof(mov_priv_t)); - - mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n"); - - priv->current_sub = -1; - - while(1){ - int i; - int skipped=8; - off_t len=stream_read_dword(demuxer->stream); - unsigned int id=stream_read_dword(demuxer->stream); - if(stream_eof(demuxer->stream)) break; // EOF - if (len == 1) /* real size is 64bits - cjb */ - { -#ifndef _LARGEFILE_SOURCE - if (stream_read_dword(demuxer->stream) != 0) - mp_msg(MSGT_DEMUX, MSGL_WARN, "64bit file, but you've compiled MPlayer without LARGEFILE support!\n"); - len = stream_read_dword(demuxer->stream); -#else - len = stream_read_qword(demuxer->stream); -#endif - skipped += 8; - } -#if 0 - else if (len == 0) /* deleted chunk */ - { - /* XXX: CJB! is this right? - alex */ - goto skip_chunk; - } -#endif - if(len<8) break; // invalid chunk - - switch(id){ - case MOV_FOURCC('f','t','y','p'): { - unsigned int tmp; - // File Type Box (ftyp): - // char[4] major_brand (eg. 'isom') - // int minor_version (eg. 0x00000000) - // char[4] compatible_brands[] (eg. 'mp41') - // compatible_brands list spans to the end of box -#if 1 - tmp = stream_read_dword(demuxer->stream); - switch(tmp) { - case MOV_FOURCC('i','s','o','m'): - mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Major Brand: ISO Base Media\n"); - break; - case MOV_FOURCC('m','p','4','1'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n"); - break; - case MOV_FOURCC('m','p','4','2'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n"); - break; - case MOV_FOURCC('M','4','A',' '): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n"); - break; - case MOV_FOURCC('M','4','P',' '): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n"); - break; - case MOV_FOURCC('q','t',' ',' '): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Original QuickTime\n"); - break; - case MOV_FOURCC('3','g','p','1'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 1\n"); - break; - case MOV_FOURCC('3','g','p','2'): - case MOV_FOURCC('3','g','2','a'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 2\n"); - break; - case MOV_FOURCC('3','g','p','3'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 3\n"); - break; - case MOV_FOURCC('3','g','p','4'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 4\n"); - break; - case MOV_FOURCC('3','g','p','5'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 5\n"); - break; - case MOV_FOURCC('m','m','p','4'): - mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n"); - break; - default: - tmp = be2me_32(tmp); - mp_msg(MSGT_DEMUX,MSGL_WARN,"ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp); - } - mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Minor Version: %d\n", - stream_read_dword(demuxer->stream)); - skipped += 8; - // List all compatible brands - for(i = 0; i < ((len-16)/4); i++) { - tmp = be2me_32(stream_read_dword(demuxer->stream)); - mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp); - skipped += 4; - } -#endif - } break; - case MOV_FOURCC('m','o','o','v'): -// case MOV_FOURCC('c','m','o','v'): - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n"); - priv->moov_start=(off_t)stream_tell(demuxer->stream); - priv->moov_end=(off_t)priv->moov_start+len-skipped; - mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n", - (int64_t)priv->moov_start, (int64_t)priv->moov_end); - skipped+=8; - i = stream_read_dword(demuxer->stream)-8; - if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){ - skipped+=i; - mp_msg(MSGT_DEMUX,MSGL_INFO,"MOV: Reference Media file!!!\n"); - //set demuxer type to playlist ... - demuxer->type=DEMUXER_TYPE_PLAYLIST; - while(i>0){ - int len=stream_read_dword(demuxer->stream)-8; - int fcc=stream_read_dword(demuxer->stream); - if(len<0) break; // EOF!? - i-=8; -// printf("i=%d len=%d\n",i,len); - switch(fcc){ - case MOV_FOURCC('r','m','d','a'): - continue; - case MOV_FOURCC('r','d','r','f'): { - av_unused int tmp=stream_read_dword(demuxer->stream); - av_unused int type=stream_read_dword_le(demuxer->stream); - int slen=stream_read_dword(demuxer->stream); - //char* s=malloc(slen+1); - //stream_read(demuxer->stream,s,slen); - - //FIXME: also store type & data_rate ? - ds_read_packet(demuxer->video, - demuxer->stream, - slen, - 0, - stream_tell(demuxer->stream), - 0 // no flags - ); - flags|=4; - mp_msg(MSGT_DEMUX,MSGL_V,"Added reference to playlist\n"); - //s[slen]=0; - //mp_msg(MSGT_DEMUX,MSGL_INFO,"REF: [%.4s] %s\n",&type,s); - len-=12+slen;i-=12+slen; break; - } - case MOV_FOURCC('r','m','d','r'): { - av_unused int flags=stream_read_dword(demuxer->stream); - int rate=stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX,MSGL_V," min. data rate: %d bits/sec\n",rate); - len-=8; i-=8; break; - } - case MOV_FOURCC('r','m','q','u'): { - int q=stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX,MSGL_V," quality index: %d\n",q); - len-=4; i-=4; break; - } - } - i-=len;stream_skip(demuxer->stream,len); - } - } - flags|=1; - break; - case MOV_FOURCC('w','i','d','e'): - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: 'WIDE' chunk found!\n"); - if(flags&2) break; - case MOV_FOURCC('m','d','a','t'): - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n"); - priv->mdat_start=stream_tell(demuxer->stream); - priv->mdat_end=priv->mdat_start+len-skipped; - mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n", - (int64_t)priv->mdat_start, (int64_t)priv->mdat_end); - flags|=2; - if(flags==3){ - // if we're over the headers, then we can stop parsing here! - demuxer->priv=priv; - return DEMUXER_TYPE_MOV; - } - break; - case MOV_FOURCC('f','r','e','e'): - case MOV_FOURCC('s','k','i','p'): - case MOV_FOURCC('j','u','n','k'): - mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: free space (len: %"PRId64")\n", (int64_t)len); - /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */ - break; - case MOV_FOURCC('p','n','o','t'): - case MOV_FOURCC('P','I','C','T'): - /* dunno what, but we shoudl ignore it */ - break; - default: - if(no==0){ free(priv); return 0;} // first chunk is bad! - id = be2me_32(id); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); - } -//skip_chunk: - if(!stream_skip(demuxer->stream,len-skipped)) break; - ++no; - } - - if(flags==3){ - demuxer->priv=priv; - return DEMUXER_TYPE_MOV; - } - free(priv); - - if ((flags==5) || (flags==7)) // reference & header sent - return DEMUXER_TYPE_PLAYLIST; - - if(flags==1) - mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing data (mdat) chunk! Maybe broken file...\n"); - else if(flags==2) - mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); - - return 0; -} - -static void demux_close_mov(demuxer_t *demuxer) { - mov_priv_t* priv = demuxer->priv; - int i; - if (!priv) - return; - for (i = 0; i < MOV_MAX_TRACKS; i++) { - mov_track_t *track = priv->tracks[i]; - if (track) { - free(track->tkdata); - free(track->stdata); - free(track->stream_header); - free(track->samples); - free(track->chunks); - free(track->chunkmap); - free(track->durmap); - free(track->keyframes); - free(track->editlist); - free(track->desc); - free(track); - } - } - free(priv); -} - -unsigned int store_ughvlc(unsigned char *s, unsigned int v){ - unsigned int n = 0; - - while(v >= 0xff) { - *s++ = 0xff; - v -= 0xff; - n++; - } - *s = v; - n++; - - return n; -} - -static void init_vobsub(sh_sub_t *sh, mov_track_t *trak) { - sh->type = 'v'; - if (trak->stdata_len < 106) - return; - sh->extradata_len = 16*4; - sh->extradata = malloc(sh->extradata_len); - memcpy(sh->extradata, trak->stdata + 42, sh->extradata_len); -} - -static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, - off_t pos, off_t len, mov_track_t* trak); - -static int gen_sh_audio(sh_audio_t* sh, mov_track_t* trak, int timescale) { -#if 0 - struct { - int16_t version; // 0 or 1 (version 1 is qt3.0+) - int16_t revision; // 0 - int32_t vendor_id; // 0 - int16_t channels; // 1 or 2 (Mono/Stereo) - int16_t samplesize; // 8 or 16 (8Bit/16Bit) - int16_t compression_id; // if version 0 then 0 - // if version 1 and vbr then -2 else 0 - int16_t packet_size; // 0 - uint16_t sample_rate; // samplerate (Hz) - // qt3.0+ (version == 1) - uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet - // if 0 below three values are also 0 - uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel - uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels - // (channels * bytes_per_packet) - uint32_t bytes_per_sample; // 0 or size of uncompressed sample - // if samples_per_packet and bytes_per_packet are constant (CBR) - // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) - // --- - // optional additional atom-based fields - // ([int32_t size,int32_t type,some data ],repeat) - } my_stdata; -#endif - int version = -1, adjust; - int is_vorbis = 0; - sh->format=trak->fourcc; - - // crude audio delay from editlist0 hack ::atm - if(trak->editlist_size>=1) { - if(trak->editlist[0].pos == -1) { - sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); - } - } - - - switch( sh->format ) { - case 0x726D6173: /* samr */ - /* amr narrowband */ - trak->samplebytes=sh->samplesize=1; - trak->nchannels=sh->channels=1; - sh->samplerate=8000; - break; - - case 0x62776173: /* sawb */ - /* amr wideband */ - trak->samplebytes=sh->samplesize=1; - trak->nchannels=sh->channels=1; - sh->samplerate=16000; - break; - - default: - -// assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit -// XXX: 32bit fixed point numbers (intfp) are only 2 Byte! -// short values are usually one byte leftpadded by zero -// int values are usually two byte leftpadded by zero -// stdata[]: -// 8 short version -// 10 short revision -// 12 int vendor_id -// 16 short channels -// 18 short samplesize -// 20 short compression_id -// 22 short packet_size (==0) -// 24 intfp sample_rate -// (26 short) unknown (==0) -// ---- qt3.0+ (version>=1) -// 28 int samples_per_packet -// 32 int bytes_per_packet -// 36 int bytes_per_frame -// 40 int bytes_per_sample -// there may be additional atoms following at 28 (version 0) -// or 44 (version 1), eg. esds atom of .MP4 files -// esds atom: -// 28 int atom size (bytes of int size, int type and data) -// 32 char[4] atom type (fourc charater code -> esds) -// 36 char[] atom data (len=size-8) - -// TODO: fix parsing for files using version 2. - if (trak->stdata_len < 26) { - mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: broken (too small) sound atom!\n"); - return 0; - } - version=char2short(trak->stdata,8); - if (version > 1) - mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: version %d sound atom may not parse correctly!\n", version); - trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; - - /* I can't find documentation, but so far this is the case. -Corey */ - switch (char2short(trak->stdata,16)) { - case 1: - trak->nchannels = 1; break; - case 2: - trak->nchannels = 2; break; - case 3: - trak->nchannels = 6; break; - default: - mp_msg(MSGT_DEMUX, MSGL_WARN, - "MOV: unable to determine audio channels, assuming 2 (got %d)\n", - char2short(trak->stdata,16)); - trak->nchannels = 2; - } - sh->channels = trak->nchannels; - - /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", - trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, - trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, - char2short(trak->stdata,24)/trak->durmap[0].dur);*/ - sh->samplerate=char2short(trak->stdata,24); - if((sh->samplerate < 7000) && trak->durmap && trak->durmap[0].dur > 1) { - switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { - // TODO: add more cases. - case 31: - sh->samplerate = 32000; break; - case 43: - sh->samplerate = 44100; break; - case 47: - sh->samplerate = 48000; break; - default: - mp_msg(MSGT_DEMUX, MSGL_WARN, - "MOV: unable to determine audio samplerate, " - "assuming 44.1kHz (got %d)\n", - char2short(trak->stdata,24)/trak->durmap[0].dur); - sh->samplerate = 44100; - } - } - } - mp_msg(MSGT_DEMUX, MSGL_V, "Audio bits: %d chans: %d rate: %d\n", - sh->samplesize*8,sh->channels,sh->samplerate); - - if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ - mp_msg(MSGT_DEMUX,MSGL_V,"Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", - char2int(trak->stdata,28), - char2int(trak->stdata,32), - char2int(trak->stdata,36), - char2int(trak->stdata,40)); - if(trak->stdata_len>=44+8){ - int len=char2int(trak->stdata,44); - int fcc=char2int(trak->stdata,48); - // we have extra audio headers!!! - mp_msg(MSGT_DEMUX,MSGL_V,"Audio extra header: len=%d fcc=0x%X\n",len,fcc); - if((len >= 4) && - (char2int(trak->stdata,52) >= 12) && - (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) { - switch(char2int(trak->stdata,52+8)) { - case MOV_FOURCC('a','l','a','c'): - if (len >= 36 + char2int(trak->stdata,52)) { - sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", sh->codecdata_len); - sh->codecdata = malloc(sh->codecdata_len); - memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); - } - break; - case MOV_FOURCC('i','n','2','4'): - case MOV_FOURCC('i','n','3','2'): - case MOV_FOURCC('f','l','3','2'): - case MOV_FOURCC('f','l','6','4'): - if ((len >= 22) && - (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && - (char2short(trak->stdata,52+20))) { - sh->format=char2int(trak->stdata,52+8); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); - } - break; - default: - if (len > 8 && len + 44 <= trak->stdata_len) { - sh->codecdata_len = len-8; - sh->codecdata = malloc(sh->codecdata_len); - memcpy(sh->codecdata, trak->stdata+44+8, sh->codecdata_len); - } - } - } else { - if (len > 8 && len + 44 <= trak->stdata_len) { - sh->codecdata_len = len-8; - sh->codecdata = malloc(sh->codecdata_len); - memcpy(sh->codecdata, trak->stdata+44+8, sh->codecdata_len); - } - } - } - } - - switch (version) { - case 0: - adjust = 0; break; - case 1: - adjust = 48; break; - case 2: - adjust = 68; break; - default: - mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: unknown sound atom version (%d); may not work!\n", version); - adjust = 68; - } - if (trak->stdata_len >= 36 + adjust) { - int atom_len = char2int(trak->stdata,28+adjust); - if (atom_len < 0 || atom_len > trak->stdata_len - 28 - adjust) atom_len = trak->stdata_len - 28 - adjust; - switch(char2int(trak->stdata,32+adjust)) { // atom type - case MOV_FOURCC('e','s','d','s'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); - if(atom_len > 8) { - esds_t esds; - if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { - /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html), - so perform some extra checks to be sure that this is really vorbis audio */ - if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8) - { - //vorbis audio - unsigned char *buf[3]; - unsigned short sizes[3]; - int offset, len, k; - unsigned char *ptr = esds.decoderConfig; - - if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout - - offset = len = 0; - for(k = 0; k < 3; k++) - { - sizes[k] = (ptr[offset]<<8) | ptr[offset+1]; - len += sizes[k]; - offset += 2; - if(offset + sizes[k] > esds.decoderConfigLen) - { - mp_msg(MSGT_DEMUX, MSGL_FATAL, "MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen); - goto quit_vorbis_block; - } - buf[k] = malloc(sizes[k]); - if(!buf[k]) goto quit_vorbis_block; - memcpy(buf[k], &ptr[offset], sizes[k]); - offset += sizes[k]; - } - - sh->codecdata_len = len + len/255 + 64; - sh->codecdata = malloc(sh->codecdata_len); - ptr = sh->codecdata; - - ptr[0] = 2; - offset = 1; - offset += store_ughvlc(&ptr[offset], sizes[0]); - offset += store_ughvlc(&ptr[offset], sizes[1]); - for(k = 0; k < 3; k++) - { - memcpy(&ptr[offset], buf[k], sizes[k]); - offset += sizes[k]; - } - - sh->codecdata_len = offset; - sh->codecdata = realloc(sh->codecdata, offset); - mp_msg(MSGT_DEMUX,MSGL_V, "demux_mov, vorbis extradata size: %d\n", offset); - is_vorbis = 1; -quit_vorbis_block: - sh->format = mmioFOURCC('v', 'r', 'b', 's'); - } - sh->i_bps = esds.avgBitrate/8; - -// printf("######## audio format = %d ########\n",esds.objectTypeId); - if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) - sh->format=0x55; // .mp3 - - if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2 - sh->format=mmioFOURCC('Q', 'c', 'l', 'p'); - trak->nchannels=sh->channels=1; - trak->samplebytes=sh->samplesize=1; - } - - // dump away the codec specific configuration for the AAC decoder - if(esds.decoderConfigLen){ - if( (esds.decoderConfig[0]>>3) == 29 ) - sh->format = 0x1d61346d; // request multi-channel mp3 decoder - if(!is_vorbis) - { - sh->codecdata_len = esds.decoderConfigLen; - sh->codecdata = malloc(sh->codecdata_len); - memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); - } - } - } - mp4_free_esds(&esds); // freeup esds mem -#if 0 - { FILE* f=fopen("esds.dat","wb"); - fwrite(&trak->stdata[36],atom_len-8,1,f); - fclose(f); } -#endif - } - } break; - case MOV_FOURCC('a','l','a','c'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", atom_len); - if(atom_len > 8) { - // copy all the atom (not only payload) for lavc alac decoder - sh->codecdata_len = atom_len; - sh->codecdata = malloc(sh->codecdata_len); - memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); - } - } break; - case MOV_FOURCC('d','a','m','r'): - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); - if (atom_len>14) { - mp_msg(MSGT_DEMUX, MSGL_V, "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); - } - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", - trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], - atom_len); - } - } - mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s\n",(char *)&trak->fourcc); -#if 0 - { FILE* f=fopen("stdata.dat","wb"); - fwrite(trak->stdata,trak->stdata_len,1,f); - fclose(f); } - { FILE* f=fopen("tkdata.dat","wb"); - fwrite(trak->tkdata,trak->tkdata_len,1,f); - fclose(f); } -#endif - // Emulate WAVEFORMATEX struct: - sh->wf=calloc(1, sizeof(*sh->wf) + (is_vorbis ? sh->codecdata_len : 0)); - sh->wf->nChannels=sh->channels; - sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; - // sh->wf->nSamplesPerSec=trak->timescale; - sh->wf->nSamplesPerSec=sh->samplerate; - if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ - //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 - sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* - char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) - /char2int(trak->stdata,28); - sh->wf->nBlockAlign=char2int(trak->stdata,36); - } else { - sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; - // workaround for ms11 ima4 - if (sh->format == 0x1100736d && trak->stdata_len >= 36) - sh->wf->nBlockAlign=char2int(trak->stdata,36); - } - - if(is_vorbis && sh->codecdata_len) - { - memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len); - sh->wf->cbSize = sh->codecdata_len; - } - // Selection: -// if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ -// // (auto)selected audio track: -// demuxer->audio->id=priv->track_db; -// demuxer->audio->sh=sh; sh->ds=demuxer->audio; -// } - return 1; -} - -static int gen_sh_video(sh_video_t* sh, mov_track_t* trak, int timescale) { - int depth, i, entry; - int flag, start, count_flag, end, palette_count, gray; - int hdr_ptr = 76; // the byte just after depth - unsigned char *palette_map; - - sh->format=trak->fourcc; - - // crude video delay from editlist0 hack ::atm - if(trak->editlist_size>=1) { - if(trak->editlist[0].pos == -1) { - sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); - } - } - - - if (trak->stdata_len < 78) { - mp_msg(MSGT_DEMUXER, MSGL_WARN, - "MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", - trak->stdata_len); - return 0; - } - - depth = trak->stdata[75] | (trak->stdata[74] << 8); - if (trak->fourcc == mmioFOURCC('r', 'a', 'w', ' ')) - sh->format = IMGFMT_RGB | depth; - -// stdata[]: -// 8 short version -// 10 short revision -// 12 int vendor_id -// 16 int temporal_quality -// 20 int spatial_quality -// 24 short width -// 26 short height -// 28 int h_dpi -// 32 int v_dpi -// 36 int 0 -// 40 short frames_per_sample -// 42 char[4] compressor_name -// 74 short depth -// 76 short color_table_id -// additional atoms may follow, -// eg esds atom from .MP4 files -// 78 int atom size -// 82 char[4] atom type -// 86 ... atom data - - { ImageDescription* id=malloc(8+trak->stdata_len); // safe - trak->desc=id; - id->idSize=8+trak->stdata_len; -// id->cType=bswap_32(trak->fourcc); - id->cType=le2me_32(trak->fourcc); - id->version=char2short(trak->stdata,8); - id->revisionLevel=char2short(trak->stdata,10); - id->vendor=char2int(trak->stdata,12); - id->temporalQuality=char2int(trak->stdata,16); - id->spatialQuality=char2int(trak->stdata,20); - id->width=char2short(trak->stdata,24); - id->height=char2short(trak->stdata,26); - id->hRes=char2int(trak->stdata,28); - id->vRes=char2int(trak->stdata,32); - id->dataSize=char2int(trak->stdata,36); - id->frameCount=char2short(trak->stdata,40); - memcpy(&id->name,trak->stdata+42,32); - id->depth=char2short(trak->stdata,74); - id->clutID=char2short(trak->stdata,76); - if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); - sh->ImageDesc=id; -#if 0 - { FILE *f=fopen("ImageDescription","wb"); - fwrite(id,id->idSize,1,f); - fclose(f); - } -#endif - } - - if(trak->stdata_len >= 86) { // extra atoms found - int pos=78; - int atom_len; - while(pos+8<=trak->stdata_len && - (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ - switch(char2int(trak->stdata,pos+4)) { // switch atom type - case MOV_FOURCC('g','a','m','a'): - // intfp with gamma value at which movie was captured - // can be used to gamma correct movie display - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", - atom_len); - break; - case MOV_FOURCC('f','i','e','l'): - // 2 char-values (8bit int) that specify field handling - // see the Apple's QuickTime Fileformat PDF for more info - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Field-Handling movie atom (%d)!\n", - atom_len); - break; - case MOV_FOURCC('m','j','q','t'): - // Motion-JPEG default quantization table - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", - atom_len); - break; - case MOV_FOURCC('m','j','h','t'): - // Motion-JPEG default huffman table - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", - atom_len); - break; - case MOV_FOURCC('e','s','d','s'): - // MPEG4 Elementary Stream Descriptor header - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); - // add code here to save esds header of length atom_len-8 - // beginning at stdata[86] to some variable to pass it - // on to the decoder ::atmos - if(atom_len > 8) { - esds_t esds; - if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { - - if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || - esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || - esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) - sh->format=mmioFOURCC('m', 'p', 'g', '2'); - else if(esds.objectTypeId==MP4OTI_MPEG1Visual) - sh->format=mmioFOURCC('m', 'p', 'g', '1'); - - // dump away the codec specific configuration for the AAC decoder - trak->stream_header_len = esds.decoderConfigLen; - trak->stream_header = malloc(trak->stream_header_len); - memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); - } - mp4_free_esds(&esds); // freeup esds mem - } - break; - case MOV_FOURCC('a','v','c','C'): - // AVC decoder configuration record - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); - if(atom_len > 8) { - int i, poffs, cnt; - // Parse some parts of avcC, just for fun :) - // real parsing is done by avc1 decoder - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); - if (*(trak->stdata+pos+8) != 1) - mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); - poffs = pos + 14; - for (i = 0; i < cnt; i++) { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC sps %d have length %d\n", i, AV_RB16(trak->stdata+poffs)); - poffs += AV_RB16(trak->stdata+poffs) + 2; - } - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); - poffs++; - for (i = 0; i < cnt; i++) { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC pps %d have length %d\n", i, AV_RB16(trak->stdata+poffs)); - poffs += AV_RB16(trak->stdata+poffs) + 2; - } - // Copy avcC for the AVC decoder - // This data will be put in extradata below, where BITMAPINFOHEADER is created - trak->stream_header_len = atom_len-8; - trak->stream_header = malloc(trak->stream_header_len); - memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); - } - break; - case MOV_FOURCC('d','2','6','3'): - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len); - if (atom_len>10) - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); - break; - case 0: - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", - trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], - atom_len); - } - if(atom_len<8) break; - pos+=atom_len; -// printf("pos=%d max=%d\n",pos,trak->stdata_len); - } - } - sh->fps=trak->timescale/ - ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); - sh->frametime=1.0f/sh->fps; - - sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); - sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); - if(trak->tkdata_len>81) { - // if image size is zero, fallback to display size - if(!sh->disp_w && !sh->disp_h) { - sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); - sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); - } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ - // codec and display width differ... use display one for aspect - sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); - sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); - } - } - - if(depth>32+8) mp_msg(MSGT_DEMUX, MSGL_INFO,"*** depth = 0x%X\n",depth); - - // palettized? - gray = 0; - if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale - if ((depth == 2) || (depth == 4) || (depth == 8)) - palette_count = (1 << depth); - else - palette_count = 0; - - // emulate BITMAPINFOHEADER: - if (palette_count) - { - sh->bih=calloc(1, sizeof(*sh->bih) + palette_count * 4); - sh->bih->biSize=40 + palette_count * 4; - // fetch the relevant fields - flag = AV_RB16(&trak->stdata[hdr_ptr]); - hdr_ptr += 2; - start = AV_RB32(&trak->stdata[hdr_ptr]); - hdr_ptr += 4; - count_flag = AV_RB16(&trak->stdata[hdr_ptr]); - hdr_ptr += 2; - end = AV_RB16(&trak->stdata[hdr_ptr]); - hdr_ptr += 2; - palette_map = (unsigned char *)sh->bih + 40; - mp_msg(MSGT_DEMUX, MSGL_V, "Allocated %d entries for palette\n", - palette_count); - mp_msg(MSGT_DEMUX, MSGL_DBG2, "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", - start, end, count_flag, flag); - - /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ - - // load default palette - if (flag & 0x08) - { - if (gray) - { - mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT grayscale palette\n"); - if (palette_count == 16) - memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); - else if (palette_count == 256) { - memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); - if (trak->fourcc == mmioFOURCC('c','v','i','d')) { - int i; - // Hack for grayscale CVID, negative palette - // If you have samples where this is not required contact me (rxt) - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: greyscale cvid with default palette," - " enabling negative palette hack.\n"); - for (i = 0; i < 256 * 4; i++) - palette_map[i] = palette_map[i] ^ 0xff; - } - } - } - else - { - mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT colour palette\n"); - if (palette_count == 4) - memcpy(palette_map, qt_default_palette_4, 4 * 4); - else if (palette_count == 16) - memcpy(palette_map, qt_default_palette_16, 16 * 4); - else if (palette_count == 256) - memcpy(palette_map, qt_default_palette_256, 256 * 4); - } - } - // load palette from file - else - { - mp_msg(MSGT_DEMUX, MSGL_V, "Loading palette from file\n"); - for (i = start; i <= end; i++) - { - entry = AV_RB16(&trak->stdata[hdr_ptr]); - hdr_ptr += 2; - // apparently, if count_flag is set, entry is same as i - if (count_flag & 0x8000) - entry = i; - // only care about top 8 bits of 16-bit R, G, or B value - if (entry <= palette_count && entry >= 0) - { - palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; - palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; - palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; - mp_dbg(MSGT_DEMUX, MSGL_DBG2, "QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", - entry, palette_count, - palette_map[entry * 4 + 2], - palette_map[entry * 4 + 1], - palette_map[entry * 4 + 0]); - } - else - mp_msg(MSGT_DEMUX, MSGL_V, "QT palette: skipped entry (out of count): %d of %d\n", - entry, palette_count); - hdr_ptr += 6; - } - } - } - else - { - if (trak->fourcc == mmioFOURCC('a','v','c','1')) { - if (trak->stream_header_len > 0xffffffff - sizeof(*sh->bih)) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid extradata size %d, skipping\n",trak->stream_header_len); - trak->stream_header_len = 0; - } - sh->bih=calloc(1, sizeof(*sh->bih) + trak->stream_header_len); - sh->bih->biSize=40 + trak->stream_header_len; - memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); - free (trak->stream_header); - trak->stream_header_len = 0; - trak->stream_header = NULL; - } else { - sh->bih=calloc(1, sizeof(*sh->bih)); - sh->bih->biSize=40; - } - } - sh->bih->biWidth=sh->disp_w; - sh->bih->biHeight=sh->disp_h; - sh->bih->biPlanes=0; - sh->bih->biBitCount=depth; - sh->bih->biCompression=trak->fourcc; - sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; - - mp_msg(MSGT_DEMUX, MSGL_V, "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); - if(trak->tkdata_len>81) - mp_msg(MSGT_DEMUX, MSGL_V, "Display size: %d x %d\n", - trak->tkdata[77]|(trak->tkdata[76]<<8), - trak->tkdata[81]|(trak->tkdata[80]<<8)); - mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); - -// if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ -// // (auto)selected video track: -// demuxer->video->id=priv->track_db; -// demuxer->video->sh=sh; sh->ds=demuxer->video; -// } - return 1; -} - -static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ - mov_priv_t* priv=demuxer->priv; -// printf("lschunks (level=%d,endpos=%x)\n", level, endpos); - while(1){ - off_t pos; - off_t len; - unsigned int id; - // - pos=stream_tell(demuxer->stream); -// printf("stream_tell==%d\n",pos); - if(pos>=endpos) return; // END - len=stream_read_dword(demuxer->stream); -// printf("len==%d\n",len); - if(len<8) return; // error - len-=8; - id=stream_read_dword(demuxer->stream); - // - mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",(char *)&id,(int)len); - // - if(trak){ - if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0) - return; - } else { /* not in track */ - switch(id) { - case MOV_FOURCC('m','v','h','d'): { - int version = stream_read_char(demuxer->stream); - stream_skip(demuxer->stream, (version == 1) ? 19 : 11); - priv->timescale=stream_read_dword(demuxer->stream); - if (version == 1) - priv->duration=stream_read_qword(demuxer->stream); - else - priv->duration=stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, - (int)priv->timescale,(int)priv->duration); - break; - } - case MOV_FOURCC('t','r','a','k'): { -// if(trak) printf("MOV: Warning! trak in trak?\n"); - if(priv->track_db>=MOV_MAX_TRACKS){ - mp_tmsg(MSGT_DEMUX,MSGL_WARN,"MOV: WARNING: too many tracks"); - return; - } - if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n"); - trak=calloc(1, sizeof(mov_track_t)); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db); - trak->id=priv->track_db; - priv->tracks[priv->track_db]=trak; - lschunks(demuxer,level+1,pos+len,trak); - mov_build_index(trak,priv->timescale); - switch(trak->type){ - case MOV_TRAK_AUDIO: { - sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); - mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "mov", priv->track_db); - gen_sh_audio(sh, trak, priv->timescale); - break; - } - case MOV_TRAK_VIDEO: { - sh_video_t* sh=new_sh_video(demuxer,priv->track_db); - mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "mov", priv->track_db); - gen_sh_video(sh, trak, priv->timescale); - break; - } - case MOV_TRAK_GENERIC: - if (trak->fourcc == mmioFOURCC('m','p','4','s') || - trak->fourcc == mmioFOURCC('t','x','3','g') || - trak->fourcc == mmioFOURCC('t','e','x','t')) { - sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db); - mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Subtitle stream found, -sid %d\n", "mov", priv->track_db); - if (trak->fourcc == mmioFOURCC('m','p','4','s')) - init_vobsub(sh, trak); - else { - sh->type = 'm'; - sub_utf8 = 1; - } - } else - mp_msg(MSGT_DEMUX, MSGL_V, "Generic track - not completely understood! (id: %d)\n", - trak->id); - /* XXX: Also this contains the FLASH data */ - -#if 0 - { - int pos = stream_tell(demuxer->stream); - int i; - int fd; - char name[20]; - - for (i=0; i<trak->samples_size; i++) - { - char buf[trak->samples[i].size]; - stream_seek(demuxer->stream, trak->samples[i].pos); - snprintf((char *)&name[0], 20, "samp%d", i); - fd = open((char *)&name[0], O_CREAT|O_WRONLY); - stream_read(demuxer->stream, &buf[0], trak->samples[i].size); - write(fd, &buf[0], trak->samples[i].size); - close(fd); - } - for (i=0; i<trak->chunks_size; i++) - { - char buf[trak->length]; - stream_seek(demuxer->stream, trak->chunks[i].pos); - snprintf((char *)&name[0], 20, "chunk%d", i); - fd = open((char *)&name[0], O_CREAT|O_WRONLY); - stream_read(demuxer->stream, &buf[0], trak->length); - write(fd, &buf[0], trak->length); - close(fd); - } - if (trak->samplesize > 0) - { - char *buf; - - buf = malloc(trak->samplesize); - stream_seek(demuxer->stream, trak->chunks[0].pos); - snprintf((char *)&name[0], 20, "trak%d", trak->id); - fd = open((char *)&name[0], O_CREAT|O_WRONLY); - stream_read(demuxer->stream, buf, trak->samplesize); - write(fd, buf, trak->samplesize); - close(fd); - } - stream_seek(demuxer->stream, pos); - } -#endif - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, "Unknown track type found (type: %d)\n", trak->type); - break; - } - mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n"); - priv->track_db++; - trak=NULL; - break; - } -#if !CONFIG_ZLIB - case MOV_FOURCC('c','m','o','v'): { - mp_tmsg(MSGT_DEMUX,MSGL_ERR,"MOV: Compressed headers support requires ZLIB!\n"); - return; - } -#else - case MOV_FOURCC('m','o','o','v'): - case MOV_FOURCC('c','m','o','v'): { -// mp_tmsg(MSGT_DEMUX,MSGL_ERR,"MOV: Compressed headers support requires ZLIB!\n"); - lschunks(demuxer,level+1,pos+len,NULL); - break; - } - case MOV_FOURCC('d','c','o','m'): { -// int temp=stream_read_dword(demuxer->stream); - unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); - mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header uses %.4s algo!\n",(char *)&algo); - break; - } - case MOV_FOURCC('c','m','v','d'): { -// int temp=stream_read_dword(demuxer->stream); - unsigned int moov_sz=stream_read_dword(demuxer->stream); - unsigned int cmov_sz=len-4; - unsigned char* cmov_buf; - unsigned char* moov_buf; - int zret; - z_stream zstrm; - stream_t* backup; - - if (moov_sz > UINT_MAX - 16) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid cmvd atom size %d\n", moov_sz); - break; - } - cmov_buf=malloc(cmov_sz); - moov_buf=malloc(moov_sz+16); - mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header size: %d / %d\n",cmov_sz,moov_sz); - - stream_read(demuxer->stream,cmov_buf,cmov_sz); - - zstrm.zalloc = (alloc_func)0; - zstrm.zfree = (free_func)0; - zstrm.opaque = (voidpf)0; - zstrm.next_in = cmov_buf; - zstrm.avail_in = cmov_sz; - zstrm.next_out = moov_buf; - zstrm.avail_out = moov_sz; - - zret = inflateInit(&zstrm); - if (zret != Z_OK) - { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov: inflateInit err %d\n",zret); - return; - } - zret = inflate(&zstrm, Z_NO_FLUSH); - if ((zret != Z_OK) && (zret != Z_STREAM_END)) - { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov inflate: ERR %d\n",zret); - return; - } -#if 0 - else { - FILE *DecOut; - DecOut = fopen("Out.bin", "w"); - fwrite(moov_buf, 1, moov_sz, DecOut); - fclose(DecOut); - } -#endif - if(moov_sz != zstrm.total_out) - mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out); - zret = inflateEnd(&zstrm); - - backup=demuxer->stream; - demuxer->stream=new_memory_stream(moov_buf,moov_sz); - stream_skip(demuxer->stream,8); - lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' - //free_stream(demuxer->stream); - demuxer->stream=backup; - free(cmov_buf); - free(moov_buf); - break; - } -#endif - case MOV_FOURCC('u','d','t','a'): - { - unsigned int udta_id; - off_t udta_len; - off_t udta_size = len; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "mov: user data record found\n"); - mp_msg(MSGT_DEMUX, MSGL_V, "Quicktime Clip Info:\n"); - - while((len > 8) && (udta_size > 8)) - { - udta_len = stream_read_dword(demuxer->stream); - udta_id = stream_read_dword(demuxer->stream); - udta_size -= 8; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len); - switch (udta_id) - { - case MOV_FOURCC(0xa9,'c','p','y'): - case MOV_FOURCC(0xa9,'d','a','y'): - case MOV_FOURCC(0xa9,'d','i','r'): - /* 0xa9,'e','d','1' - '9' : edit timestamps */ - case MOV_FOURCC(0xa9,'f','m','t'): - case MOV_FOURCC(0xa9,'i','n','f'): - case MOV_FOURCC(0xa9,'p','r','d'): - case MOV_FOURCC(0xa9,'p','r','f'): - case MOV_FOURCC(0xa9,'r','e','q'): - case MOV_FOURCC(0xa9,'s','r','c'): - case MOV_FOURCC('n','a','m','e'): - case MOV_FOURCC(0xa9,'n','a','m'): - case MOV_FOURCC(0xa9,'A','R','T'): - case MOV_FOURCC(0xa9,'c','m','t'): - case MOV_FOURCC(0xa9,'a','u','t'): - case MOV_FOURCC(0xa9,'s','w','r'): - { - off_t text_len = stream_read_word(demuxer->stream); - char text[text_len+2+1]; - stream_read(demuxer->stream, (char *)&text, text_len+2); - text[text_len+2] = 0x0; - switch(udta_id) - { - case MOV_FOURCC(0xa9,'a','u','t'): - demux_info_add(demuxer, "author", &text[2]); - mp_msg(MSGT_DEMUX, MSGL_V, " Author: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'c','p','y'): - demux_info_add(demuxer, "copyright", &text[2]); - mp_msg(MSGT_DEMUX, MSGL_V, " Copyright: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'i','n','f'): - mp_msg(MSGT_DEMUX, MSGL_V, " Info: %s\n", &text[2]); - break; - case MOV_FOURCC('n','a','m','e'): - case MOV_FOURCC(0xa9,'n','a','m'): - demux_info_add(demuxer, "title", &text[2]); - mp_msg(MSGT_DEMUX, MSGL_V, " Name: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'A','R','T'): - mp_msg(MSGT_DEMUX, MSGL_V, " Artist: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'d','i','r'): - mp_msg(MSGT_DEMUX, MSGL_V, " Director: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'c','m','t'): - demux_info_add(demuxer, "comments", &text[2]); - mp_msg(MSGT_DEMUX, MSGL_V, " Comment: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'r','e','q'): - mp_msg(MSGT_DEMUX, MSGL_V, " Requirements: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'s','w','r'): - demux_info_add(demuxer, "encoder", &text[2]); - mp_msg(MSGT_DEMUX, MSGL_V, " Software: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'d','a','y'): - mp_msg(MSGT_DEMUX, MSGL_V, " Creation timestamp: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'f','m','t'): - mp_msg(MSGT_DEMUX, MSGL_V, " Format: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'p','r','d'): - mp_msg(MSGT_DEMUX, MSGL_V, " Producer: %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'p','r','f'): - mp_msg(MSGT_DEMUX, MSGL_V, " Performer(s): %s\n", &text[2]); - break; - case MOV_FOURCC(0xa9,'s','r','c'): - mp_msg(MSGT_DEMUX, MSGL_V, " Source providers: %s\n", &text[2]); - break; - } - udta_size -= 4+text_len; - break; - } - /* some other shits: WLOC - window location, - LOOP - looping style, - SelO - play only selected frames - AllF - play all frames - */ - case MOV_FOURCC('W','L','O','C'): - case MOV_FOURCC('L','O','O','P'): - case MOV_FOURCC('S','e','l','O'): - case MOV_FOURCC('A','l','l','F'): - default: - { - if( udta_len>udta_size) - udta_len=udta_size; - { - stream_skip(demuxer->stream, udta_len-4-4); - udta_size -= udta_len; - } - } - } - } - break; - } /* eof udta */ - default: - id = be2me_32(id); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); - } /* endof switch */ - } /* endof else */ - - pos+=len+8; - if(pos>=endpos) break; - if(!stream_seek(demuxer->stream,pos)) break; - } -} - -static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, - off_t pos, off_t len, mov_track_t* trak) -{ - switch(id) { - case MOV_FOURCC('m','d','a','t'): { - mp_msg(MSGT_DEMUX,MSGL_WARN,"Hmm, strange MOV, parsing mdat in lschunks?\n"); - return -1; - } - case MOV_FOURCC('f','r','e','e'): - case MOV_FOURCC('u','d','t','a'): - /* here not supported :p */ - break; - case MOV_FOURCC('t','k','h','d'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sTrack header!\n", level, ""); - // read codec data - trak->tkdata_len = len; - trak->tkdata = malloc(trak->tkdata_len); - stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len); -/* -0 1 Version -1 3 Flags -4 4 Creation time -8 4 Modification time -12 4 Track ID -16 4 Reserved -20 4 Duration -24 8 Reserved -32 2 Layer -34 2 Alternate group -36 2 Volume -38 2 Reserved -40 36 Matrix structure -76 4 Track width -80 4 Track height -*/ - mp_msg(MSGT_DEMUX, MSGL_V, - "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n", - trak->tkdata_len, trak->tkdata[0], trak->tkdata[1], - char2int(trak->tkdata, 12), // id - char2int(trak->tkdata, 20), // duration - char2short(trak->tkdata, 32), // layer - char2short(trak->tkdata, 36)); // volume - break; - } - case MOV_FOURCC('m','d','h','d'): { - int version = stream_read_char(demuxer->stream); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia header!\n", level, ""); - stream_skip(demuxer->stream, (version == 1) ? 19 : 11); - // read timescale - trak->timescale = stream_read_dword(demuxer->stream); - // read length - if (version == 1) - trak->length = stream_read_qword(demuxer->stream); - else - trak->length = stream_read_dword(demuxer->stream); - break; - } - case MOV_FOURCC('h','d','l','r'): { - av_unused unsigned int tmp = stream_read_dword(demuxer->stream); - unsigned int type = stream_read_dword_le(demuxer->stream); - unsigned int subtype = stream_read_dword_le(demuxer->stream); - unsigned int manufact = stream_read_dword_le(demuxer->stream); - av_unused unsigned int comp_flags = stream_read_dword(demuxer->stream); - av_unused unsigned int comp_mask = stream_read_dword(demuxer->stream); - int len = stream_read_char(demuxer->stream); - char* str = malloc(len + 1); - stream_read(demuxer->stream, str, len); - str[len] = 0; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "", - (char *)&type, (char *)&subtype, (char *)&manufact, str); - free(str); - switch(bswap_32(type)) { - case MOV_FOURCC('m','h','l','r'): - trak->media_handler = bswap_32(subtype); - break; - case MOV_FOURCC('d','h','l','r'): - trak->data_handler = bswap_32(subtype); - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: unknown handler class: 0x%X (%.4s)\n", - bswap_32(type), (char *)&type); - } - break; - } - case MOV_FOURCC('v','m','h','d'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sVideo header!\n", level, ""); - trak->type = MOV_TRAK_VIDEO; - // read video data - break; - } - case MOV_FOURCC('s','m','h','d'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sSound header!\n", level, ""); - trak->type = MOV_TRAK_AUDIO; - // read audio data - break; - } - case MOV_FOURCC('g','m','h','d'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sGeneric header!\n", level, ""); - trak->type = MOV_TRAK_GENERIC; - break; - } - case MOV_FOURCC('n','m','h','d'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sGeneric header!\n", level, ""); - trak->type = MOV_TRAK_GENERIC; - break; - } - case MOV_FOURCC('s','t','s','d'): { - int i = stream_read_dword(demuxer->stream); // temp! - int count = stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sDescription list! (cnt:%d)\n", - level, "", count); - for (i = 0; i < count; i++) { - off_t pos = stream_tell(demuxer->stream); - off_t len = stream_read_dword(demuxer->stream); - unsigned int fourcc = stream_read_dword_le(demuxer->stream); - /* some files created with Broadcast 2000 (e.g. ilacetest.mov) - contain raw I420 video but have a yv12 fourcc */ - if (fourcc == mmioFOURCC('y','v','1','2')) - fourcc = mmioFOURCC('I','4','2','0'); - if (len < 8) - break; // error - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*s desc #%d: %.4s (%"PRId64" bytes)\n", level, "", - i, (char *)&fourcc, (int64_t)len - 16); - if (fourcc != trak->fourcc && i) - mp_tmsg(MSGT_DEMUX, MSGL_WARN, "MOV: WARNING: Variable FourCC detected!?\n"); -// if(!i) - { - trak->fourcc = fourcc; - // read type specific (audio/video/time/text etc) header - // NOTE: trak type is not yet known at this point :((( - trak->stdata_len = len - 8; - trak->stdata = malloc(trak->stdata_len); - stream_read(demuxer->stream, trak->stdata, trak->stdata_len); - } - if (!stream_seek(demuxer->stream, pos + len)) - break; - } - break; - } - case MOV_FOURCC('s','t','t','s'): { - av_unused int temp = stream_read_dword(demuxer->stream); - int len = stream_read_dword(demuxer->stream); - int i; - unsigned int pts = 0; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sSample duration table! (%d blocks)\n", level, "", - len); - free(trak->durmap); - trak->durmap = calloc(len, sizeof(mov_durmap_t)); - trak->durmap_size = trak->durmap ? len : 0; - for (i = 0; i < trak->durmap_size; i++) { - trak->durmap[i].num = stream_read_dword(demuxer->stream); - trak->durmap[i].dur = stream_read_dword(demuxer->stream); - pts += trak->durmap[i].num * trak->durmap[i].dur; - } - if (trak->length != pts) - mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! pts=%d length=%d\n", - pts, trak->length); - break; - } - case MOV_FOURCC('s','t','s','c'): { - int temp = stream_read_dword(demuxer->stream); - int len = stream_read_dword(demuxer->stream); - int ver = (temp << 24); - int flags = (temp << 16) | (temp << 8) | temp; - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sSample->Chunk mapping table! (%d blocks) (ver:%d,flags:%d)\n", level, "", - len, ver, flags); - // read data: - free(trak->chunkmap); - trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t)); - trak->chunkmap_size = trak->chunkmap ? len : 0; - for (i = 0; i < trak->chunkmap_size; i++) { - trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1; - trak->chunkmap[i].spc = stream_read_dword(demuxer->stream); - trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream); - } - break; - } - case MOV_FOURCC('s','t','s','z'): { - int temp = stream_read_dword(demuxer->stream); - int ss=stream_read_dword(demuxer->stream); - int ver = (temp << 24); - int flags = (temp << 16) | (temp << 8) | temp; - int entries = stream_read_dword(demuxer->stream); - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "", - entries, ss, ver, flags); - trak->samplesize = ss; - if (!ss) { - // variable samplesize - free(trak->samples); - trak->samples = calloc(entries, sizeof(mov_sample_t)); - trak->samples_size = trak->samples ? entries : 0; - for (i = 0; i < trak->samples_size; i++) - trak->samples[i].size = stream_read_dword(demuxer->stream); - } - break; - } - case MOV_FOURCC('s','t','c','o'): { - av_unused int temp = stream_read_dword(demuxer->stream); - int len = stream_read_dword(demuxer->stream); - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sChunk offset table! (%d chunks)\n", level, "", - len); - // extend array if needed: - if (len > trak->chunks_size) { - free(trak->chunks); - trak->chunks = calloc(len, sizeof(mov_chunk_t)); - trak->chunks_size = trak->chunks ? len : 0; - } - // read elements: - for(i = 0; i < trak->chunks_size; i++) - trak->chunks[i].pos = stream_read_dword(demuxer->stream); - break; - } - case MOV_FOURCC('c','o','6','4'): { - av_unused int temp = stream_read_dword(demuxer->stream); - int len = stream_read_dword(demuxer->stream); - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "", - len); - // extend array if needed: - if (len > trak->chunks_size) { - free(trak->chunks); - trak->chunks = calloc(len, sizeof(mov_chunk_t)); - trak->chunks_size = trak->chunks ? len : 0; - } - // read elements: - for (i = 0; i < trak->chunks_size; i++) { -#ifndef _LARGEFILE_SOURCE - if (stream_read_dword(demuxer->stream) != 0) - mp_msg(MSGT_DEMUX, MSGL_WARN, "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i); - trak->chunks[i].pos = stream_read_dword(demuxer->stream); -#else - trak->chunks[i].pos = stream_read_qword(demuxer->stream); -#endif - } - break; - } - case MOV_FOURCC('s','t','s','s'): { - int temp = stream_read_dword(demuxer->stream); - int entries = stream_read_dword(demuxer->stream); - int ver = (temp << 24); - int flags = (temp << 16) | (temp<<8) | temp; - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "", - entries, ver, flags); - free(trak->keyframes); - trak->keyframes = calloc(entries, sizeof(unsigned int)); - trak->keyframes_size = trak->keyframes ? entries : 0; - for (i = 0; i < trak->keyframes_size; i++) - trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1; - break; - } - case MOV_FOURCC('m','d','i','a'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia stream!\n", level, ""); - lschunks(demuxer, level + 1, pos + len, trak); - break; - } - case MOV_FOURCC('m','i','n','f'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia info!\n", level, ""); - lschunks(demuxer, level + 1 ,pos + len, trak); - break; - } - case MOV_FOURCC('s','t','b','l'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sSample info!\n", level, ""); - lschunks(demuxer, level + 1, pos + len, trak); - break; - } - case MOV_FOURCC('e','d','t','s'): { - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sEdit atom!\n", level, ""); - lschunks(demuxer, level + 1, pos + len, trak); - break; - } - case MOV_FOURCC('e','l','s','t'): { - int temp = stream_read_dword(demuxer->stream); - int entries = stream_read_dword(demuxer->stream); - int ver = (temp << 24); - int flags = (temp << 16) | (temp << 8) | temp; - int i; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "", - entries, ver, flags); -#if 1 - free(trak->editlist); - trak->editlist = calloc(entries, sizeof(mov_editlist_t)); - trak->editlist_size = trak->editlist ? entries : 0; - for (i = 0; i < trak->editlist_size; i++) { - int dur = stream_read_dword(demuxer->stream); - int mt = stream_read_dword(demuxer->stream); - int mr = stream_read_dword(demuxer->stream); // 16.16fp - trak->editlist[i].dur = dur; - trak->editlist[i].pos = mt; - trak->editlist[i].speed = mr; - mp_msg(MSGT_DEMUX, MSGL_V, - "MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n", level, "", - i, dur, mt, (float)mr/65536.0f); - } -#endif - break; - } - case MOV_FOURCC('c','o','d','e'): { - /* XXX: Implement atom 'code' for FLASH support */ - break; - } - default: - id = be2me_32(id); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); - break; - }//switch(id) - return 0; -} - -static demuxer_t* mov_read_header(demuxer_t* demuxer){ - struct MPOpts *opts = demuxer->opts; - mov_priv_t* priv=demuxer->priv; - int t_no; - int best_a_id=-1, best_a_len=0; - int best_v_id=-1, best_v_len=0; - - mp_msg(MSGT_DEMUX, MSGL_DBG3, "mov_read_header!\n"); - - // Parse header: - stream_reset(demuxer->stream); - if(!stream_seek(demuxer->stream,priv->moov_start)) - { - mp_msg(MSGT_DEMUX,MSGL_ERR,"MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n", - (int64_t)priv->moov_start); - return 0; - } - lschunks(demuxer, 0, priv->moov_end, NULL); - // just in case we have hit eof while parsing... - demuxer->stream->eof = 0; -// mp_msg(MSGT_DEMUX, MSGL_INFO, "--------------\n"); - - // find the best (longest) streams: - for(t_no=0;t_no<priv->track_db;t_no++){ - mov_track_t* trak=priv->tracks[t_no]; - int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size; - if(demuxer->a_streams[t_no]){ // need audio - if(len>best_a_len){ best_a_len=len; best_a_id=t_no; } - } - if(demuxer->v_streams[t_no]){ // need video - if(len>best_v_len){ best_v_len=len; best_v_id=t_no; } - } - } - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: longest streams: A: #%d (%d samples) V: #%d (%d samples)\n", - best_a_id,best_a_len,best_v_id,best_v_len); - if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id; - if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id; - - // setup sh pointers: - if(demuxer->audio->id>=0){ - sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id]; - if(sh){ - demuxer->audio->sh=sh; sh->ds=demuxer->audio; - } else { - mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected audio stream (%d) does not exist\n",demuxer->audio->id); - demuxer->audio->id=-2; - } - } - if(demuxer->video->id>=0){ - sh_video_t* sh=demuxer->v_streams[demuxer->video->id]; - if(sh){ - demuxer->video->sh=sh; sh->ds=demuxer->video; - } else { - mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected video stream (%d) does not exist\n",demuxer->video->id); - demuxer->video->id=-2; - } - } - if(demuxer->sub->id>=0){ - sh_sub_t* sh=demuxer->s_streams[demuxer->sub->id]; - if(sh){ - demuxer->sub->sh=sh; - } else { - mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected subtitle stream (%d) does not exist\n",demuxer->sub->id); - demuxer->sub->id=-2; - } - } - - if(demuxer->video->id<0 && demuxer->audio->id<0) { - /* No AV streams found. Try to find an MPEG stream. */ - for(t_no=0;t_no<priv->track_db;t_no++){ - mov_track_t* trak=priv->tracks[t_no]; - if(trak->media_handler == MOV_FOURCC('M','P','E','G')) { - stream_t *s; - demuxer_t *od; - - demuxer->video->id = t_no; - s = new_ds_stream(demuxer->video); - od = demux_open(opts, s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); - if(od) return new_demuxers_demuxer(od, od, od); - demuxer->video->id = -2; //new linked demuxer couldn't be allocated - break; - } - } - } - -#if 0 - if( mp_msg_test(MSGT_DEMUX,MSGL_DBG3) ){ - for(t_no=0;t_no<priv->track_db;t_no++){ - mov_track_t* trak=priv->tracks[t_no]; - if(trak->type==MOV_TRAK_GENERIC){ - int i; - int fd; - char name[20]; - mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size); - for (i=0; i<trak->samples_size; i++) - { - int len=trak->samples[i].size; - char buf[len]; - stream_seek(demuxer->stream, trak->samples[i].pos); - snprintf(name, 20, "t%02d-s%03d.%s", t_no,i, - (trak->media_handler==MOV_FOURCC('f','l','s','h')) ? - "swf":"dump"); - fd = open(name, O_CREAT|O_WRONLY); -// { int j; -// for(j=0;j<trak->stdata_len-3; j++) -// printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b')); -// } - if( //trak->media_handler==MOV_FOURCC('s','p','r','t') && - trak->stdata_len>=16 && - char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b') - ){ - int newlen=stream_read_dword(demuxer->stream); -#if CONFIG_ZLIB - // unzip: - z_stream zstrm; - int zret; - char buf2[newlen]; - - len-=4; - stream_read(demuxer->stream, buf, len); - - zstrm.zalloc = (alloc_func)0; - zstrm.zfree = (free_func)0; - zstrm.opaque = (voidpf)0; - zstrm.next_in = buf; - zstrm.avail_in = len; - zstrm.next_out = buf2; - zstrm.avail_out = newlen; - - zret = inflateInit(&zstrm); - zret = inflate(&zstrm, Z_NO_FLUSH); - if(newlen != zstrm.total_out) - mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! unzipped frame size differs hdr: %d zlib: %ld\n",newlen,zstrm.total_out); - - write(fd, buf2, newlen); - } else { -#else - len-=4; - mp_msg(MSGT_DEMUX, MSGL_INFO, "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen); - } - { -#endif - stream_read(demuxer->stream, buf, len); - write(fd, buf, len); - } - close(fd); - } - } - } - } - demuxer->stream->eof = 0; -#endif - - return demuxer; -} - -/** - * \brief return the mov track that belongs to a demuxer stream - * \param ds the demuxer stream, may be NULL - * \return the mov track info structure belonging to the stream, - * NULL if not found - */ -static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) { - if (ds && (ds->id >= 0) && (ds->id < priv->track_db)) - return priv->tracks[ds->id]; - return NULL; -} - -// return value: -// 0 = EOF or no stream found -// 1 = successfully read a packet -static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ - mov_priv_t* priv=demuxer->priv; - mov_track_t* trak=NULL; - float pts; - int x; - off_t pos; - - if (ds->eof) return 0; - trak = stream_track(priv, ds); - if (!trak) return 0; - -if(trak->samplesize){ - // read chunk: - if(trak->pos>=trak->chunks_size) return 0; // EOF - stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); - pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; - if(trak->samplesize!=1) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "WARNING! Samplesize(%d) != 1\n", - trak->samplesize); - if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t'))) - x=trak->chunks[trak->pos].size*trak->samplesize; - else - x=trak->chunks[trak->pos].size; - } - else - x=trak->chunks[trak->pos].size; -// printf("X = %d\n", x); - /* the following stuff is audio related */ - if (trak->type == MOV_TRAK_AUDIO){ - if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ - // stsd version 1 - we have audio compression ratio info: - x/=char2int(trak->stdata,28); // samples/packet -// x*=char2int(trak->stdata,32); // bytes/packet - x*=char2int(trak->stdata,36); // bytes/frame - } else { - if(ds->ss_div && ds->ss_mul){ - // workaround for buggy files like 7up-high-traffic-areas.mov, - // with missing stsd v1 header containing compression rate - x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix ! HACK ! - } else { - x*=trak->nchannels; - x*=trak->samplebytes; - } - } - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts); - } /* MOV_TRAK_AUDIO */ - pos=trak->chunks[trak->pos].pos; -} else { - int frame=trak->pos; - // editlist support: - if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){ - // find the right editlist entry: - if(frame<trak->editlist[trak->editlist_pos].start_frame) - trak->editlist_pos=0; - while(trak->editlist_pos<trak->editlist_size-1 && - frame>=trak->editlist[trak->editlist_pos+1].start_frame) - ++trak->editlist_pos; - if(frame>=trak->editlist[trak->editlist_pos].start_frame+ - trak->editlist[trak->editlist_pos].frames) return 0; // EOF - // calc real frame index: - frame-=trak->editlist[trak->editlist_pos].start_frame; - frame+=trak->editlist[trak->editlist_pos].start_sample; - // calc pts: - pts=(float)(trak->samples[frame].pts+ - trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale; - } else { - if(frame>=trak->samples_size) return 0; // EOF - pts=(float)trak->samples[frame].pts/(float)trak->timescale; - } - // read sample: - stream_seek(demuxer->stream,trak->samples[frame].pos); - x=trak->samples[frame].size; - pos=trak->samples[frame].pos; -} -if(trak->pos==0 && trak->stream_header_len>0){ - // we have to append the stream header... - demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len); - memcpy(dp->buffer,trak->stream_header,trak->stream_header_len); - stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x); - free(trak->stream_header); - trak->stream_header = NULL; - trak->stream_header_len = 0; - dp->pts=pts; - dp->pos=pos; // FIXME? - ds_add_packet(ds,dp); -} else - ds_read_packet(ds,demuxer->stream,x,pts,pos,0); - - ++trak->pos; - - trak = NULL; - if (demuxer->sub->id >= 0 && demuxer->sub->id < priv->track_db) - trak = priv->tracks[demuxer->sub->id]; - if (trak) { - int samplenr = 0; - while (samplenr < trak->samples_size) { - double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale; - if (subpts >= pts) break; - samplenr++; - } - samplenr--; - if (samplenr < 0) - vo_sub = NULL; - else if (samplenr != priv->current_sub) { - off_t pos = trak->samples[samplenr].pos; - int len = trak->samples[samplenr].size; - double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale; - stream_seek(demuxer->stream, pos); - ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0); - priv->current_sub = samplenr; - } - } - - return 1; - -} - -static float mov_seek_track(mov_track_t* trak,float pts,int flags){ - -// printf("MOV track seek called %5.3f \n",pts); - if(flags&SEEK_FACTOR) pts*=trak->length; else pts*=(float)trak->timescale; - -if(trak->samplesize){ - int sample=pts/trak->duration; -// printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); - if(!(flags&SEEK_ABSOLUTE)) sample+=trak->chunks[trak->pos].sample; // relative - trak->pos=0; - while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; - if (trak->pos == trak->chunks_size) return -1; - pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; -} else { - unsigned int ipts; - if(!(flags&SEEK_ABSOLUTE)) pts+=trak->samples[trak->pos].pts; - if(pts<0) pts=0; - ipts=pts; - //printf("MOV track seek - sample: %d \n",ipts); - for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){ - if(trak->samples[trak->pos].pts>=ipts) break; // found it! - } - if (trak->pos == trak->samples_size) return -1; - if(trak->keyframes_size){ - // find nearest keyframe - int i; - for(i=0;i<trak->keyframes_size;i++){ - if(trak->keyframes[i]>=trak->pos) break; - } - if (i == trak->keyframes_size) return -1; - if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1])) - --i; - trak->pos=trak->keyframes[i]; -// printf("nearest keyframe: %d \n",trak->pos); - } - pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; -} - -// printf("MOV track seek done: %5.3f \n",pts); - -return pts; -} - -static void demux_seek_mov(demuxer_t *demuxer,float pts,float audio_delay,int flags){ - mov_priv_t* priv=demuxer->priv; - demux_stream_t* ds; - mov_track_t* trak; - -// printf("MOV seek called %5.3f flag=%d \n",pts,flags); - - ds=demuxer->video; - trak = stream_track(priv, ds); - if (trak) { - //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; - //if(!(flags&1)) pts+=ds->pts; - ds->pts=mov_seek_track(trak,pts,flags); - if (ds->pts < 0) ds->eof = 1; - else pts = ds->pts; - flags=1; // absolute seconds - } - - ds=demuxer->audio; - trak = stream_track(priv, ds); - if (trak) { - //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; - //if(!(flags&1)) pts+=ds->pts; - ds->pts=mov_seek_track(trak,pts,flags); - if (ds->pts < 0) ds->eof = 1; - } - -} - -static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){ - mov_track_t* track; - - // try the video track - track = stream_track(demuxer->priv, demuxer->video); - if (!track || !track->length) - // otherwise try to get the info from the audio track - track = stream_track(demuxer->priv, demuxer->audio); - - if (!track || !track->length) - return DEMUXER_CTRL_DONTKNOW; - - switch(cmd) { - case DEMUXER_CTRL_GET_TIME_LENGTH: - if (!track->timescale) - return DEMUXER_CTRL_DONTKNOW; - *((double *)arg) = (double)track->length / track->timescale; - return DEMUXER_CTRL_OK; - - case DEMUXER_CTRL_GET_PERCENT_POS: - { - off_t pos = track->pos; - if (track->durmap_size >= 1) - pos *= track->durmap[0].dur; - *((int *)arg) = (int)(100 * pos / track->length); - return DEMUXER_CTRL_OK; - } - } - return DEMUXER_CTRL_NOTIMPL; -} - - -const demuxer_desc_t demuxer_desc_mov = { - "Quicktime/MP4 demuxer", - "mov", - "Quicktime/MOV", - "Arpi, Al3x, Atmos, others", - "Handles Quicktime, MP4, 3GP", - DEMUXER_TYPE_MOV, - 0, // slow autodetect - mov_check_file, - demux_mov_fill_buffer, - mov_read_header, - demux_close_mov, - demux_seek_mov, - demux_mov_control -}; diff --git a/libmpdemux/demux_mov.h b/libmpdemux/demux_mov.h deleted file mode 100644 index 8aa515c349..0000000000 --- a/libmpdemux/demux_mov.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_DEMUX_MOV_H -#define MPLAYER_DEMUX_MOV_H - -unsigned int store_ughvlc(unsigned char *s, unsigned int v); - -#endif /* MPLAYER_DEMUX_MOV_H */ diff --git a/libmpdemux/demux_mpc.c b/libmpdemux/demux_mpc.c deleted file mode 100644 index 234eed45da..0000000000 --- a/libmpdemux/demux_mpc.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c deleted file mode 100644 index 44ec85d2db..0000000000 --- a/libmpdemux/demux_mpg.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* - * MPG/VOB file parser for DEMUXER v2.5 - * copyright (c) 2001 by A'rpi/ESP-team - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <math.h> - -#include "config.h" -#include "mp_msg.h" -#include "options.h" - -#include "libavutil/attributes.h" -#include "libmpcodecs/dec_audio.h" -#include "stream/stream.h" -#include "demuxer.h" -#include "parse_es.h" -#include "stheader.h" -#include "mp3_hdr.h" - -//#define MAX_PS_PACKETSIZE 2048 -#define MAX_PS_PACKETSIZE (224*1024) - -#define UNKNOWN 0 -#define VIDEO_MPEG1 0x10000001 -#define VIDEO_MPEG2 0x10000002 -#define VIDEO_MPEG4 0x10000004 -#define VIDEO_H264 0x10000005 -#define AUDIO_MP2 0x50 -#define AUDIO_A52 0x2000 -#define AUDIO_LPCM_BE 0x10001 -#define AUDIO_AAC mmioFOURCC('M', 'P', '4', 'A') - -typedef struct mpg_demuxer { - float last_pts; - float first_pts; // first pts found in stream - float first_to_final_pts_len; // difference between final pts and first pts - int has_valid_timestamps; // !=0 iff time stamps look linear - // (not necessarily starting with 0) - unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef - int num_a_streams; - int a_stream_ids[MAX_A_STREAMS]; -} mpg_demuxer_t; - -static int mpeg_pts_error=0; -off_t ps_probe = 0; - -static int parse_psm(demuxer_t *demux, int len) { - unsigned char c, id, type; - unsigned int plen, prog_len, es_map_len; - mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv; - - mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len); - if(! len || len > 1018) - return 0; - - c = stream_read_char(demux->stream); - if(! (c & 0x80)) { - stream_skip(demux->stream, len - 1); //not yet valid, discard - return 0; - } - stream_skip(demux->stream, 1); - prog_len = stream_read_word(demux->stream); //length of program descriptors - stream_skip(demux->stream, prog_len); //.. that we ignore - es_map_len = stream_read_word(demux->stream); //length of elementary streams map - es_map_len = FFMIN(es_map_len, len - prog_len - 8); //sanity check - while(es_map_len > 0) { - type = stream_read_char(demux->stream); - id = stream_read_char(demux->stream); - if(id >= 0xB0 && id <= 0xEF && priv) { - int idoffset = id - 0xB0; - switch(type) { - case 0x1: - priv->es_map[idoffset] = VIDEO_MPEG1; - break; - case 0x2: - priv->es_map[idoffset] = VIDEO_MPEG2; - break; - case 0x3: - case 0x4: - priv->es_map[idoffset] = AUDIO_MP2; - break; - case 0x0f: - case 0x11: - priv->es_map[idoffset] = AUDIO_AAC; - break; - case 0x10: - priv->es_map[idoffset] = VIDEO_MPEG4; - break; - case 0x1b: - priv->es_map[idoffset] = VIDEO_H264; - break; - case 0x81: - priv->es_map[idoffset] = AUDIO_A52; - break; - } - mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]); - } - plen = stream_read_word(demux->stream); //length of elementary stream descriptors - plen = FFMIN(plen, es_map_len); //sanity check - stream_skip(demux->stream, plen); //skip descriptors for now - es_map_len -= 4 + plen; - } - stream_skip(demux->stream, 4); //skip crc32 - return 1; -} - -// 500000 is a wild guess -#define TIMESTAMP_PROBE_LEN 500000 - -//MAX_PTS_DIFF_FOR_CONSECUTIVE denotes the maximum difference -//between two pts to consider them consecutive -//1.0 is a wild guess -#define MAX_PTS_DIFF_FOR_CONSECUTIVE 1.0 - -//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream. -//if no pts is found or an error occurs, -1.0 is returned. -//Packs are freed. -static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos) -{ - stream_t *s = demuxer->stream; - mpg_demuxer_t *mpg_d = demuxer->priv; - float pts = -1.0; //the pts to return; - float found_pts1; //the most recently found pts - float found_pts2; //the pts found before found_pts1 - float found_pts3; //the pts found before found_pts2 - int found = 0; - - if(!mpg_d || stream_pos < 0) - return pts; - - found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; - stream_seek(s, stream_pos); - - //We look for pts. - //However, we do not stop at the first found one, as timestamps may reset - //Therefore, we seek until we found three consecutive - //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE. - - while(found<3 && !s->eof - && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE) - && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE) - && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN) - && ds_fill_buffer(demuxer->video)) - { - if(mpg_d->last_pts != found_pts1) - { - if(!found) - found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts - else - { - found_pts3 = found_pts2; - found_pts2 = found_pts1; - found_pts1 = mpg_d->last_pts; - } - found++; - } - } - - if(found == 3) pts = found_pts3; - - //clean up from searching of first pts; - demux_flush(demuxer); - - return pts; -} - -/// Open an mpg physical stream -static demuxer_t* demux_mpg_open(demuxer_t* demuxer) { - stream_t *s = demuxer->stream; - mpg_demuxer_t* mpg_d; - - if (!ds_fill_buffer(demuxer->video)) return 0; - mpg_d = calloc(1,sizeof(mpg_demuxer_t)); - if(mpg_d) - { - demuxer->priv = mpg_d; - mpg_d->last_pts = -1.0; - mpg_d->first_pts = -1.0; - - //if seeking is allowed set has_valid_timestamps if appropriate - if(demuxer->seekable - && (demuxer->stream->type == STREAMTYPE_FILE - || demuxer->stream->type == STREAMTYPE_VCD) - && demuxer->movi_start != demuxer-> movi_end - ) - { - //We seek to the beginning of the stream, to somewhere in the - //middle, and to the end of the stream, while remembering the pts - //at each of the three positions. With these pts, we check whether - //or not the pts are "linear enough" to justify seeking by the pts - //of the stream - - //The position where the stream is now - off_t pos = stream_tell(s); - float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start); - if(first_pts != -1.0) - { - float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2); - if(middle_pts != -1.0) - { - float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN); - if(final_pts != -1.0) - { - // found proper first, middle, and final pts. - float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts); - // if they are linear enough set has_valid_timestamps - if((0.5 < proportion) && (proportion < 2)) - { - mpg_d->first_pts = first_pts; - mpg_d->first_to_final_pts_len = final_pts - first_pts; - mpg_d->has_valid_timestamps = 1; - } - } - } - } - - //Cleaning up from seeking in stream - demuxer->stream->eof=0; - demuxer->video->eof=0; - demuxer->audio->eof=0; - - stream_seek(s,pos); - ds_fill_buffer(demuxer->video); - } // if ( demuxer->seekable ) - } // if ( mpg_d ) - return demuxer; -} - -static void demux_close_mpg(demuxer_t* demuxer) { - mpg_demuxer_t* mpg_d = demuxer->priv; - free(mpg_d); -} - - -static unsigned long long read_mpeg_timestamp(stream_t *s,int c){ - unsigned int d,e; - unsigned long long pts; - d=stream_read_word(s); - e=stream_read_word(s); - if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){ - ++mpeg_pts_error; - return 0; // invalid pts - } - pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1); - mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%llu}",pts); - return pts; -} - -static void new_audio_stream(demuxer_t *demux, int aid){ - if(!demux->a_streams[aid]){ - mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv; - sh_audio_t* sh_a; - new_sh_audio(demux,aid); - sh_a = (sh_audio_t*)demux->a_streams[aid]; - sh_a->needs_parsing = 1; - switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) - case 0x00: sh_a->format=0x50;break; // mpeg - case 0xA0: sh_a->format=0x10001;break; // dvd pcm - case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts - else sh_a->format=0x2000;break; // ac3 - } - //evo files - if((aid & 0xC0) == 0xC0) sh_a->format=0x2000; - else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001; - if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid; - } - if(demux->audio->id==-1) demux->audio->id=aid; -} - -static int demux_mpg_read_packet(demuxer_t *demux,int id){ - int d av_unused; - int len; - int set_pts=0; // !=0 iff pts has been set to a proper value - unsigned char c=0; - unsigned long long pts=0; - unsigned long long dts av_unused = 0; - int l; - int pes_ext2_subid=-1; - double stream_pts = MP_NOPTS_VALUE; - demux_stream_t *ds=NULL; - demux_packet_t* dp; - mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv; - - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id); - -// if(id==0x1F0){ -// demux->synced=0; // force resync after 0x1F0 -// return -1; -//} - -// if(id==0x1BA) packet_start_pos=stream_tell(demux->stream); - if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1; - if(id==0x1BE) return -1; // padding stream - if(id==0x1BF) return -1; // private2 - - len=stream_read_word(demux->stream); - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len); -// if(len==62480){ demux->synced=0;return -1;} /* :) */ - if(len==0 || len>MAX_PS_PACKETSIZE){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len); - return -2; // invalid packet !!!!!! - } - - mpeg_pts_error=0; - - if(id==0x1BC) { - parse_psm(demux, len); - return 0; - } - - while(len>0){ // Skip stuFFing bytes - c=stream_read_char(demux->stream); - --len; - if(c!=0xFF)break; - } - if((c>>6)==1){ // Read (skip) STD scale & size value -// printf(" STD_scale=%d",(c>>5)&1); - d=((c&0x1F)<<8)|stream_read_char(demux->stream); - len-=2; -// printf(" STD_size=%d",d); - c=stream_read_char(demux->stream); - } - // Read System-1 stream timestamps: - if((c>>4)==2){ - pts=read_mpeg_timestamp(demux->stream,c); - set_pts=1; - len-=4; - } else - if((c>>4)==3){ - pts=read_mpeg_timestamp(demux->stream,c); - c=stream_read_char(demux->stream); - if((c>>4)!=1) pts=0; //printf("{ERROR4}"); - else set_pts = 1; - dts=read_mpeg_timestamp(demux->stream,c); - len-=4+1+4; - } else - if((c>>6)==2){ - int pts_flags; - int hdrlen; - int parse_ext2; - // System-2 (.VOB) stream: - c=stream_read_char(demux->stream); - pts_flags=c>>6; - parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1); - c=stream_read_char(demux->stream); - hdrlen=c; - len-=2; - mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len); - if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;} - if(pts_flags==2 && hdrlen>=5){ - c=stream_read_char(demux->stream); - pts=read_mpeg_timestamp(demux->stream,c); - set_pts=1; - len-=5;hdrlen-=5; - } else - if(pts_flags==3 && hdrlen>=10){ - c=stream_read_char(demux->stream); - pts=read_mpeg_timestamp(demux->stream,c); - set_pts=1; - c=stream_read_char(demux->stream); - dts=read_mpeg_timestamp(demux->stream,c); - len-=10;hdrlen-=10; - } - len-=hdrlen; - if(parse_ext2 && hdrlen>=3) { - c=stream_read_char(demux->stream); - hdrlen--; - - if((c & 0x0F) != 0x0F) { - mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n"); - return -1; - } - if(c & 0x80) { //pes_private_data_flag - if(hdrlen<16) { - mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen); - return -1; - } - stream_skip(demux->stream, 16); - hdrlen-=16; - } - if(c & 0x40) { //pack_header_field_flag - int l = stream_read_char(demux->stream); - if(l < 0) //couldn't read from the stream? - return -1; - hdrlen--; - if(l < 0 || hdrlen < l) { - mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n", - hdrlen, l); - return -1; - } - stream_skip(demux->stream, l); - hdrlen-=l; - } - if(c & 0x20) { //program_packet_sequence_counter_flag - if(hdrlen < 2) { - mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen); - return -1; - } - stream_skip(demux->stream, 2); - hdrlen-=2; - } - if(c & 0x10) { - //STD - stream_skip(demux->stream, 2); - hdrlen-=2; - } - c=stream_read_char(demux->stream); //pes_extension2 flag - hdrlen--; - if(c!=0x81) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1 \n"); return -1;} - c=stream_read_char(demux->stream); //pes_extension2 payload === substream id - hdrlen--; - if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;} - pes_ext2_subid=c; - } - if(hdrlen>0) - stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes - - if(id==0x1FD && pes_ext2_subid!=-1) { - //==== EVO VC1 STREAMS ===// - if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid); - if(demux->video->id==-1) demux->video->id=pes_ext2_subid; - if(demux->video->id==pes_ext2_subid){ - ds=demux->video; - if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid]; - if(priv && ds->sh) { - sh_video_t *sh = (sh_video_t *)ds->sh; - sh->format = mmioFOURCC('W', 'V', 'C', '1'); - } - } - } - //============== DVD Audio sub-stream ====================== - if(id==0x1BD){ - int aid, rawa52 = 0; - off_t tmppos; - unsigned int tmp; - - tmppos = stream_tell(demux->stream); - tmp = stream_read_word(demux->stream); - stream_seek(demux->stream, tmppos); - /// vdr stores A52 without the 4 header bytes, so we have to check this condition first - if(tmp == 0x0B77) { - aid = 128; - rawa52 = 1; - } - else { - aid=stream_read_char(demux->stream);--len; - if(len<3) return -1; // invalid audio packet - } - - // AID: - // 0x20..0x3F subtitle - // 0x80..0x87 and 0xC0..0xCF AC3 audio - // 0x88..0x8F and 0x98..0x9F DTS audio - // 0xA0..0xBF PCM audio - - if((aid & 0xE0) == 0x20){ - // subtitle: - aid&=0x1F; - - if(!demux->s_streams[aid]){ - sh_sub_t *sh = new_sh_sub(demux, aid); - if (sh) sh->type = 'v'; - mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid); - } - - if(demux->sub->id > -1) - demux->sub->id &= 0x1F; - if(!demux->opts->sub_lang && demux->sub->id == -1) - demux->sub->id = aid; - if(demux->sub->id==aid){ - ds=demux->sub; - } - } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) { - -// aid=128+(aid&0x7F); - // aid=0x80..0xBF - new_audio_stream(demux, aid); - if(demux->audio->id==aid){ - int type; - ds=demux->audio; - if(!ds->sh) ds->sh=demux->a_streams[aid]; - // READ Packet: Skip additional audio header data: - if(!rawa52) { - c=stream_read_char(demux->stream);//num of frames - type=stream_read_char(demux->stream);//startpos hi - type=(type<<8)|stream_read_char(demux->stream);//startpos lo -// printf("\r[%02X][%04X]",c,type); - len-=3; - } - if((aid&0xE0)==0xA0 && len>=3){ - unsigned char* hdr; - // save audio header as codecdata! - if(!((sh_audio_t*)(ds->sh))->codecdata_len){ - ((sh_audio_t*)(ds->sh))->codecdata=malloc(3); - ((sh_audio_t*)(ds->sh))->codecdata_len=3; - } - hdr=((sh_audio_t*)(ds->sh))->codecdata; - // read LPCM header: - // emphasis[1], mute[1], rvd[1], frame number[5]: - hdr[0]=stream_read_char(demux->stream); -// printf(" [%01X:%02d]",c>>5,c&31); - // quantization[2],freq[2],rvd[1],channels[3] - hdr[1]=stream_read_char(demux->stream); -// printf("[%01X:%01X] ",c>>4,c&15); - // dynamic range control (0x80=off): - hdr[2]=stream_read_char(demux->stream); -// printf("[%02X] ",c); - len-=3; - if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n"); - } -// printf(" \n"); - } // if(demux->audio->id==aid) - - } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid); - } //if(id==0x1BD) - } else { - if(c!=0x0f){ - mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c); - return -1; // invalid packet !!!!!! - } - } - if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error); - mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len); - -// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size - if(len<=0 || len>MAX_PS_PACKETSIZE){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len); - return -1; // invalid packet !!!!!! - } - - if(id>=0x1C0 && id<=0x1DF){ - // mpeg audio - int aid=id-0x1C0; - new_audio_stream(demux, aid); - if(demux->audio->id==aid){ - ds=demux->audio; - if(!ds->sh) ds->sh=demux->a_streams[aid]; - if(priv && ds->sh) { - sh_audio_t *sh = (sh_audio_t *)ds->sh; - if(priv->es_map[id - 0x1B0]) - sh->format = priv->es_map[id - 0x1B0]; - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); - } - } - } else - if(id>=0x1E0 && id<=0x1EF){ - // mpeg video - int aid=id-0x1E0; - if(!demux->v_streams[aid]) new_sh_video(demux,aid); - if(demux->video->id==-1) demux->video->id=aid; - if(demux->video->id==aid){ - ds=demux->video; - if(!ds->sh) ds->sh=demux->v_streams[aid]; - if(priv && ds->sh) { - sh_video_t *sh = (sh_video_t *)ds->sh; - if(priv->es_map[id - 0x1B0]) { - sh->format = priv->es_map[id - 0x1B0]; - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); - } - } - } - } - - if(ds){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id); -// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos); - - dp=new_demux_packet(len); - if(!dp) { - mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len); - stream_skip(demux->stream,len); - return 0; - } - l = stream_read(demux->stream,dp->buffer,len); - if(l<len) - resize_demux_packet(dp, l); - len = l; - if(set_pts) - dp->pts=pts/90000.0f; - dp->pos=demux->filepos; - /* - workaround: - set dp->stream_pts only when feeding the video stream, or strangely interleaved files - (such as SWIII) will show strange alternations in the stream time, wildly going - back and forth - */ - if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED) - dp->stream_pts = stream_pts; - ds_add_packet(ds,dp); - if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f; -// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len); - return 1; - } - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id); - if(len<=2356) stream_skip(demux->stream,len); - return 0; -} - -static int num_elementary_packets100=0; -static int num_elementary_packets101=0; -static int num_elementary_packets12x=0; -static int num_elementary_packets1B6=0; -static int num_elementary_packetsPES=0; -static int num_mpeg12_startcode=0; -static int num_h264_slice=0; //combined slice -static int num_h264_dpa=0; //DPA Slice -static int num_h264_dpb=0; //DPB Slice -static int num_h264_dpc=0; //DPC Slice -static int num_h264_idr=0; //IDR Slice -static int num_h264_sps=0; -static int num_h264_pps=0; - -static int num_mp3audio_packets=0; - -static void clear_stats(void) -{ - num_elementary_packets100=0; - num_elementary_packets101=0; - num_elementary_packets1B6=0; - num_elementary_packets12x=0; - num_elementary_packetsPES=0; - num_mpeg12_startcode=0; - num_h264_slice=0; //combined slice - num_h264_dpa=0; //DPA Slice - num_h264_dpb=0; //DPB Slice - num_h264_dpc=0; //DPC Slice - num_h264_idr=0; //IDR Slice - num_h264_sps=0; - num_h264_pps=0; - num_mp3audio_packets=0; -} - -//assumes demuxer->synced < 2 -static inline void update_stats(int head) -{ - if(head==0x1B6) ++num_elementary_packets1B6; - else if(head==0x1B3 || head==0x1B8) ++num_mpeg12_startcode; - else if(head==0x100) ++num_elementary_packets100; - else if(head==0x101) ++num_elementary_packets101; - else if(head==0x1BD || (0x1C0<=head && head<=0x1EF)) - num_elementary_packetsPES++; - else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x; - if(head>=0x100 && head<0x1B0) - { - if((head&~0x60) == 0x101) ++num_h264_slice; - else if((head&~0x60) == 0x102) ++num_h264_dpa; - else if((head&~0x60) == 0x103) ++num_h264_dpb; - else if((head&~0x60) == 0x104) ++num_h264_dpc; - else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr; - else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps; - else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps; - } -} - -static int demux_mpg_probe(demuxer_t *demuxer) { - int pes av_unused = 1; - int tmp; - off_t tmppos; - int file_format = DEMUXER_TYPE_UNKNOWN; - - tmppos=stream_tell(demuxer->stream); - tmp=stream_read_dword(demuxer->stream); - if(tmp==0x1E0 || tmp==0x1C0) { - tmp=stream_read_word(demuxer->stream); - if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES... - } - stream_seek(demuxer->stream,tmppos); - - clear_stats(); - - if(demux_mpg_open(demuxer)) - file_format=DEMUXER_TYPE_MPEG_PS; - else { - mp_msg(MSGT_DEMUX,MSGL_V,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d PES: %d MP3: %d, synced: %d\n", - num_elementary_packets100,num_elementary_packets101, - num_elementary_packets1B6,num_elementary_packets12x, - num_h264_slice, num_h264_dpa, - num_h264_dpb, num_h264_dpc=0, - num_h264_idr, num_h264_sps=0, - num_h264_pps, - num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced); - - //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v) - if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100 - && abs(num_elementary_packets100-num_elementary_packets101)>2) - return file_format; - - // some hack to get meaningfull error messages to our unhappy users: - if(num_mpeg12_startcode>=2 && num_elementary_packets100>=2 && num_elementary_packets101>=2 && - abs(num_elementary_packets101+8-num_elementary_packets100)<16) { - if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) { - return file_format; - } - file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :) - } else - // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection! - if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 && - num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x && - demuxer->synced<2) { - file_format=DEMUXER_TYPE_MPEG4_ES; - } else - // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection! - if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) && - /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 && - num_elementary_packets1B6==0 && num_elementary_packetsPES==0 && - demuxer->synced<2) { - file_format=DEMUXER_TYPE_H264_ES; - } else - { - if(demuxer->synced==2) - mp_msg(MSGT_DEMUXER, MSGL_ERR, "MPEG: %s", - mp_gtext("Missing video stream!? Contact the author, it may be a bug :(\n")); - else - mp_tmsg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n"); - } - } - //FIXME this shouldn't be necessary - stream_seek(demuxer->stream,tmppos); - return file_format; -} - -static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){ - // Elementary video stream - if(demux->stream->eof) return 0; - demux->filepos=stream_tell(demux->stream); - ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0); - return 1; -} - -/** - * \brief discard until 0x100 header and return a filled buffer - * \param b buffer-end pointer - * \param pos current pos in stream, negative since b points to end of buffer - * \param s stream to read from - * \return new position, differs from original pos when eof hit and thus - * b was modified to point to the new end of buffer - */ -static int find_end(unsigned char **b, int pos, stream_t *s) { - register int state = 0xffffffff; - unsigned char *buf = *b; - int start = pos; - int read, unused; - // search already read part - while (state != 0x100 && pos) { - state = state << 8 | buf[pos++]; - } - // continue search in stream - while (state != 0x100) { - register int c = stream_read_char(s); - if (c < 0) break; - state = state << 8 | c; - } - // modify previous header (from 0x1bc or 0x1bf to 0x100) - buf[start++] = 0; - // copy remaining buffer part to current pos - memmove(&buf[start], &buf[pos], -pos); - unused = start + -pos; // -unused bytes in buffer - read = stream_read(s, &buf[unused], -unused); - unused += read; - // fix buffer so it ends at pos == 0 (eof case) - *b = &buf[unused]; - start -= unused; - return start; -} - -/** - * This format usually uses an insane bitrate, which makes this function - * performance-critical! - * Be sure to benchmark any changes with different compiler versions. - */ -static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) { - demux_packet_t *pack; - int len; - demux->filepos = stream_tell(demux->stream); - pack = new_demux_packet(STREAM_BUFFER_SIZE); - len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE); - if (len <= 0) - { - free_demux_packet(pack); - return 0; - } - { - register uint32_t state = (uint32_t)demux->priv; - register int pos = -len; - unsigned char *buf = &pack->buffer[len]; - do { - state = state << 8 | buf[pos]; - if (unlikely((state | 3) == 0x1bf)) - pos = find_end(&buf, pos, demux->stream); - } while (++pos < 0); - demux->priv = (void *)state; - len = buf - pack->buffer; - } - if (len < STREAM_BUFFER_SIZE) - resize_demux_packet(pack, len); - ds_add_packet(ds, pack); - return 1; -} - -static int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds) -{ -unsigned int head=0; -int skipped=0; -int max_packs=256; // 512kbyte -int ret=0; - -// System stream -do{ - demux->filepos=stream_tell(demux->stream); - //lame workaround: this is needed to show the progress bar when playing dvdnav:// - //(ths poor guy doesn't know teh length of the stream at startup) - demux->movi_end = demux->stream->end_pos; - head=stream_read_dword(demux->stream); - if((head&0xFFFFFF00)!=0x100){ - // sync... - demux->filepos-=skipped; - while(1){ - int c=stream_read_char(demux->stream); - if(c<0) break; //EOF - head<<=8; - if(head!=0x100){ - head|=c; - if(mp_check_mp3_header(head)) ++num_mp3audio_packets; - ++skipped; //++demux->filepos; - continue; - } - head|=c; - break; - } - demux->filepos+=skipped; - } - if(stream_eof(demux->stream)) break; - // sure: head=0x000001XX - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head); - if(demux->synced==0){ - if(head==0x1BA) demux->synced=1; //else -// if(head==0x1BD || (head>=0x1C0 && head<=0x1EF)) demux->synced=3; // PES? - } else - if(demux->synced==1){ - if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){ - demux->synced=2; - mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%"PRIX64" (%"PRId64")!\n",(int64_t)demux->filepos,(int64_t)demux->filepos); - num_elementary_packets100=0; // requires for re-sync! - num_elementary_packets101=0; // requires for re-sync! - } else demux->synced=0; - } // else - if(demux->synced>=2){ - ret=demux_mpg_read_packet(demux,head); - if(!ret) - if(--max_packs==0){ - demux->stream->eof=1; - mp_tmsg(MSGT_DEMUX,MSGL_ERR,"demux: File doesn't contain the selected audio or video stream.\n"); - return 0; - } - if(demux->synced==3) demux->synced=(ret==1)?2:0; // PES detect - } else { - update_stats(head); - if(head>=0x100 && head<0x1B0) - mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head); - else if((head>=0x1C0 && head<0x1F0) || head==0x1BD) - mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head); - - if(((num_elementary_packets100>50 && num_elementary_packets101>50) || - (num_elementary_packetsPES>50)) && skipped>4000000){ - mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n"); - demux->stream->eof=1; - break; - } - if(num_mp3audio_packets>100 && num_elementary_packets100<10){ - mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be MP3 stream...\n"); - demux->stream->eof=1; - break; - } - } -} while(ret!=1); - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped); - if(demux->stream->eof){ - mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n"); - return 0; - } - return 1; -} - -static void demux_seek_mpg(demuxer_t *demuxer, float rel_seek_secs, - float audio_delay, int flags) -{ - demux_stream_t *d_audio=demuxer->audio; - demux_stream_t *d_video=demuxer->video; - sh_audio_t *sh_audio=d_audio->sh; - sh_video_t *sh_video=d_video->sh; - mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv; - int precision = 1; - float oldpts = 0; - off_t oldpos = demuxer->filepos; - float newpts = 0; - off_t newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : oldpos; - - if(mpg_d) - oldpts = mpg_d->last_pts; - newpts = (flags & SEEK_ABSOLUTE) ? 0.0 : oldpts; - //================= seek in MPEG ========================== - //calculate the pts to seek to - if(flags & SEEK_FACTOR) { - if (mpg_d && mpg_d->first_to_final_pts_len > 0.0) - newpts += mpg_d->first_to_final_pts_len * rel_seek_secs; - else - newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos; - } else - newpts += rel_seek_secs; - if (newpts < 0) newpts = 0; - - if(flags&SEEK_FACTOR){ - // float seek 0..1 - newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs; - } else { - // time seek (secs) - if (mpg_d && mpg_d->has_valid_timestamps) { - if (mpg_d->first_to_final_pts_len > 0.0) - newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->first_to_final_pts_len; - else if (oldpts > 0.0) - newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts; - } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR - newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec - else - newpos+=sh_video->i_bps*rel_seek_secs; - } - - while (1) { - if(newpos<demuxer->movi_start){ - if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD - if(newpos<demuxer->movi_start) newpos=demuxer->movi_start; - } - - stream_seek(demuxer->stream,newpos); - - // re-sync video: - videobuf_code_len=0; // reset ES stream buffer - - ds_fill_buffer(d_video); - if(sh_audio){ - ds_fill_buffer(d_audio); - } - - while(1){ - int i; - if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){ - float a_pts=d_audio->pts; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - if(d_video->pts>a_pts){ - skip_audio_frame(sh_audio); // sync audio - continue; - } - } - if(!sh_video) break; - i=sync_video_packet(d_video); - if(sh_video->format == mmioFOURCC('W', 'V', 'C', '1')) { - if(i==0x10E || i==0x10F) //entry point or sequence header - break; - } else - if(sh_video->format == 0x10000004) { //mpeg4 - if(i==0x1B6) { //vop (frame) startcode - int pos = videobuf_len; - if(!read_video_packet(d_video)) break; // EOF - if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame - } - } else if(sh_video->format == 0x10000005){ //h264 - if((i & ~0x60) == 0x105) break; - } else { //default mpeg1/2 - if(i==0x1B3 || i==0x1B8) break; // found it! - } - if(!i || !skip_video_packet(d_video)) break; // EOF? - } - if(!mpg_d) - break; - if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break; - if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps - mpg_d->has_valid_timestamps = 0; - break; - } - precision--; - //prepare another seek because we are off by more than 0.5s - if(mpg_d) { - newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts); - demux_flush(demuxer); - demuxer->stream->eof=0; // clear eof flag - d_video->eof=0; - d_audio->eof=0; - } - } -} - -static int demux_mpg_control(demuxer_t *demuxer, int cmd, void *arg) -{ - mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv; - - switch(cmd) { - case DEMUXER_CTRL_GET_TIME_LENGTH: - if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, arg) != STREAM_UNSUPPORTED) { - mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\r\nDEMUX_MPG_CTRL, (%.3f)\r\n", *((double*)arg)); - return DEMUXER_CTRL_GUESS; - } - if (mpg_d && mpg_d->has_valid_timestamps) { - *((double *)arg)=(double)mpg_d->first_to_final_pts_len; - return DEMUXER_CTRL_OK; - } - return DEMUXER_CTRL_DONTKNOW; - - case DEMUXER_CTRL_GET_PERCENT_POS: - if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) { - *((int *)arg)=(int)(100 * (mpg_d->last_pts-mpg_d->first_pts) / mpg_d->first_to_final_pts_len); - return DEMUXER_CTRL_OK; - } - return DEMUXER_CTRL_DONTKNOW; - - case DEMUXER_CTRL_SWITCH_AUDIO: - if(! (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh)) - return DEMUXER_CTRL_NOTIMPL; - else { - demux_stream_t *d_audio = demuxer->audio; - sh_audio_t *sh_audio = d_audio->sh; - sh_audio_t *sh_a = sh_audio; - int i; - if(!sh_audio) - return DEMUXER_CTRL_NOTIMPL; - if (*((int*)arg) < 0) - { - for (i = 0; i < mpg_d->num_a_streams; i++) { - if (d_audio->id == mpg_d->a_stream_ids[i]) break; - } - i = (i+1) % mpg_d->num_a_streams; - sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]]; - } - else { - for (i = 0; i < mpg_d->num_a_streams; i++) - if (*((int*)arg) == mpg_d->a_stream_ids[i]) break; - if (i < mpg_d->num_a_streams) - sh_a = (sh_audio_t*)demuxer->a_streams[*((int*)arg)]; - } - if (i < mpg_d->num_a_streams && d_audio->id != mpg_d->a_stream_ids[i]) { - d_audio->id = mpg_d->a_stream_ids[i]; - d_audio->sh = sh_a; - ds_free_packs(d_audio); - } - } - *((int*)arg) = demuxer->audio->id; - return DEMUXER_CTRL_OK; - - default: - return DEMUXER_CTRL_NOTIMPL; - } -} - - -static int demux_mpg_pes_probe(demuxer_t *demuxer) { - demuxer->synced = 3; - return (demux_mpg_probe(demuxer) == DEMUXER_TYPE_MPEG_PS) ? DEMUXER_TYPE_MPEG_PES : 0; -} - - -static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer) -{ - sh_video_t *sh_video=NULL; - - demuxer->audio->sh = NULL; // ES streams has no audio channel - demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0 - sh_video=demuxer->video->sh;sh_video->ds=demuxer->video; - - return demuxer; -} - -static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) { - demuxer->audio->sh = NULL; - demuxer->video->sh = new_sh_video(demuxer,0); - ((sh_video_t *)demuxer->video->sh)->ds = demuxer->video; - demuxer->priv = (void *) 0xffffffff; - return demuxer; -} - -static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer) -{ - sh_audio_t *sh_audio=NULL; - sh_video_t *sh_video=NULL; - - sh_video=demuxer->video->sh;sh_video->ds=demuxer->video; - - if(demuxer->audio->id!=-2) { - if(!ds_fill_buffer(demuxer->audio)){ - mp_msg(MSGT_DEMUXER, MSGL_INFO, "MPEG: %s", - mp_gtext("No audio stream found -> no sound.\n")); - demuxer->audio->sh=NULL; - } else { - sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio; - } - } - - if(!sh_video->format && ps_probe > 0) { - int head; - off_t pos = stream_tell(demuxer->stream); - - clear_stats(); - do { - head=sync_video_packet(demuxer->video); - if(!head) break; - update_stats(head); - skip_video_packet(demuxer->video); - } while(stream_tell(demuxer->stream) < pos + ps_probe && !demuxer->stream->eof); - - ds_free_packs(demuxer->video); - demuxer->stream->eof=0; - stream_seek(demuxer->stream, pos); - mp_msg(MSGT_DEMUX,MSGL_INFO,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d\n", - num_elementary_packets100, num_elementary_packets101, - num_elementary_packets1B6, num_elementary_packets12x, - num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc, - num_h264_idr, num_h264_sps, num_h264_pps); - - if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 && - num_elementary_packets100<=num_elementary_packets12x) - sh_video->format = 0x10000004; - else if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) && - num_h264_sps>=1 && num_h264_pps>=1 && num_h264_idr>=1 && - num_elementary_packets1B6==0) - sh_video->format = 0x10000005; - else sh_video->format = 0x10000002; - } - - return demuxer; -} - - -const demuxer_desc_t demuxer_desc_mpeg_ps = { - "MPEG PS demuxer", - "mpegps", - "MPEG-PS", - "Arpi?", - "Mpeg", - DEMUXER_TYPE_MPEG_PS, - 0, // unsafe autodetect - demux_mpg_probe, - demux_mpg_fill_buffer, - demux_mpg_ps_open, - demux_close_mpg, - demux_seek_mpg, - demux_mpg_control, -}; - - -const demuxer_desc_t demuxer_desc_mpeg_pes = { - "MPEG PES demuxer", - "mpegpes", - "MPEG-PES", - "Arpi?", - "Mpeg", - DEMUXER_TYPE_MPEG_PES, - 0, // unsafe autodetect - demux_mpg_pes_probe, - demux_mpg_fill_buffer, - demux_mpg_ps_open, - demux_close_mpg, - demux_seek_mpg, - demux_mpg_control, -}; - - -const demuxer_desc_t demuxer_desc_mpeg_gxf = { - "MPEG ES in GXF demuxer", - "mpeggxf", - "MPEG-ES in GXF", - "Reimar Doeffinger", - "Mpeg", - DEMUXER_TYPE_MPEG_GXF, - 0, // hack autodetection - NULL, - demux_mpg_gxf_fill_buffer, - demux_mpg_gxf_open, - NULL, - NULL, - NULL -}; - -const demuxer_desc_t demuxer_desc_mpeg_es = { - "MPEG ES demuxer", - "mpeges", - "MPEG-ES", - "Arpi?", - "Mpeg", - DEMUXER_TYPE_MPEG_ES, - 0, // hack autodetection - NULL, - demux_mpg_es_fill_buffer, - demux_mpg_es_open, - demux_close_mpg, - demux_seek_mpg, - demux_mpg_control, -}; - - -const demuxer_desc_t demuxer_desc_mpeg4_es = { - "MPEG4 ES demuxer", - "mpeg4es", - "MPEG-ES", - "Arpi?", - "Mpeg", - DEMUXER_TYPE_MPEG4_ES, - 0, // hack autodetection - NULL, - demux_mpg_es_fill_buffer, - demux_mpg_es_open, - demux_close_mpg, - demux_seek_mpg, - demux_mpg_control, -}; - - -const demuxer_desc_t demuxer_desc_h264_es = { - "H.264 ES demuxer", - "h264es", - "H264-ES", - "Arpi?", - "Mpeg", - DEMUXER_TYPE_H264_ES, - 0, // hack autodetection - NULL, - demux_mpg_es_fill_buffer, - demux_mpg_es_open, - demux_close_mpg, - demux_seek_mpg, - demux_mpg_control, -}; diff --git a/libmpdemux/demux_nsv.c b/libmpdemux/demux_nsv.c deleted file mode 100644 index 9ab68dd894..0000000000 --- a/libmpdemux/demux_nsv.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_nut.c b/libmpdemux/demux_nut.c deleted file mode 100644 index e6602ef506..0000000000 --- a/libmpdemux/demux_nut.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c deleted file mode 100644 index 9eea061106..0000000000 --- a/libmpdemux/demux_ogg.c +++ /dev/null @@ -1,1660 +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 <string.h> -#include <assert.h> -#include <math.h> -#include <inttypes.h> - -#include <libavutil/intreadwrite.h> - -#include "options.h" -#include "mp_msg.h" -#include "talloc.h" -#include "stream/stream.h" -#include "demuxer.h" -#include "stheader.h" -#include "aviprint.h" -#include "demux_mov.h" -#include "demux_ogg.h" - -#define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's') -#define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ') -#define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o') - -#ifdef CONFIG_TREMOR -#include <tremor/ogg.h> -#include <tremor/ivorbiscodec.h> -#else -#include <ogg/ogg.h> -#include <vorbis/codec.h> -#endif - -#ifdef CONFIG_OGGTHEORA -#include <theora/theora.h> -int _ilog (unsigned int); /* defined in many places in theora/lib/ */ -#endif - -#define BLOCK_SIZE 4096 - -/* Theora decoder context : we won't be able to interpret granule positions - * without using theora_granule_time with the theora_state of the stream. - * This is duplicated in `vd_theora.c'; put this in a common header? - */ -#ifdef CONFIG_OGGTHEORA -typedef struct theora_struct_st { - theora_state st; - theora_comment cc; - theora_info inf; -} theora_struct_t; -#endif - -//// OggDS headers -// Header for the new header format -typedef struct stream_header_video { - ogg_int32_t width; - ogg_int32_t height; -} stream_header_video; - -typedef struct stream_header_audio { - ogg_int16_t channels; - ogg_int16_t blockalign; - ogg_int32_t avgbytespersec; -} stream_header_audio; - -typedef struct __attribute__((__packed__)) stream_header { - char streamtype[8]; - char subtype[4]; - - ogg_int32_t size; // size of the structure - - ogg_int64_t time_unit; // in reference time - ogg_int64_t samples_per_unit; - ogg_int32_t default_len; // in media time - - ogg_int32_t buffersize; - ogg_int16_t bits_per_sample; - - ogg_int16_t padding; - - union { - // Video specific - stream_header_video video; - // Audio specific - stream_header_audio audio; - } sh; -} stream_header; - -/// Our private datas - -typedef struct ogg_syncpoint { - int64_t granulepos; - off_t page_pos; -} ogg_syncpoint_t; - -/// A logical stream -typedef struct ogg_stream { - /// Timestamping stuff - float samplerate; /// granulpos 2 time - int64_t lastpos; - int32_t lastsize; - int keyframe_frequency_force; - - // Logical stream state - ogg_stream_state stream; - int hdr_packets; - int vorbis; - int speex; - int theora; - int flac; - int text; - int id; - - vorbis_info vi; - int vi_initialized; - - void *ogg_d; -} ogg_stream_t; - -typedef struct ogg_demuxer { - /// Physical stream state - ogg_sync_state sync; - /// Current page - ogg_page page; - /// Logical streams - ogg_stream_t *subs; - int num_sub; - ogg_syncpoint_t *syncpoints; - int num_syncpoint; - off_t pos, last_size; - int64_t initial_granulepos; - int64_t final_granulepos; - int64_t duration; - - /* Used for subtitle switching. */ - int n_text; - int *text_ids; - char **text_langs; -} ogg_demuxer_t; - -#define NUM_VORBIS_HDR_PACKETS 3 - -/// Some defines from OggDS -#define PACKET_TYPE_HEADER 0x01 -#define PACKET_TYPE_BITS 0x07 -#define PACKET_LEN_BITS01 0xc0 -#define PACKET_LEN_BITS2 0x02 -#define PACKET_IS_SYNCPOINT 0x08 - -//-------- subtitle support - should be moved to decoder layer, and queue -// - subtitles up in demuxer buffer... - -#include "sub/subreader.h" -#include "sub/sub.h" -#define OGG_SUB_MAX_LINE 128 - -static subtitle ogg_sub; -//FILE* subout; - -static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack) -{ - int lcv; - char *packet = pack->packet; - - if (pack->bytes < 4) - return; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n", - (unsigned char)packet[0], - (unsigned char)packet[1], - (unsigned char)packet[2], - &packet[3]); - - if (((unsigned char)packet[0]) == 0x88) { // some subtitle text - // Find data start - double endpts = MP_NOPTS_VALUE; - int32_t duration = 0; - int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i; - - hdrlen |= (*packet & PACKET_LEN_BITS2) << 1; - lcv = 1 + hdrlen; - if (pack->bytes < lcv) - return; - for (i = hdrlen; i > 0; i--) { - duration <<= 8; - duration |= (unsigned char)packet[i]; - } - if (hdrlen > 0 && duration > 0) { - float pts; - - if (pack->granulepos == -1) - pack->granulepos = os->lastpos + os->lastsize; - pts = (float)pack->granulepos / (float)os->samplerate; - endpts = 1.0 + pts + (float)duration / 1000.0; - } - sub_clear_text(&ogg_sub, MP_NOPTS_VALUE); - sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts); - } - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n", - ogg_sub.lines, ogg_sub.text[0]); -#ifdef CONFIG_ICONV - subcp_recode(&ogg_sub); -#endif - vo_sub = &ogg_sub; - vo_osd_changed(OSDTYPE_SUBTITLE); -} - - -// get the logical stream of the current page -// fill os if non NULL and return the stream id -static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d, - ogg_stream_state **os) -{ - int id, s_no; - ogg_page *page = &ogg_d->page; - - s_no = ogg_page_serialno(page); - - for (id = 0; id < ogg_d->num_sub; id++) - if (s_no == ogg_d->subs[id].stream.serialno) - break; - - if (id == ogg_d->num_sub) { - // If we have only one vorbis stream allow the stream id to change - // it's normal on radio stream (each song have an different id). - // But we (or the codec?) should check that the samplerate, etc - // doesn't change (for radio stream it's ok) - if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) { - ogg_stream_reset(&ogg_d->subs[0].stream); - ogg_stream_init(&ogg_d->subs[0].stream, s_no); - id = 0; - } else - return -1; - } - - if (os) - *os = &ogg_d->subs[id].stream; - - return id; -} - -static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack, - float *pts, bool *keyframe, - int samplesize) -{ - unsigned char *data = pack->packet; - - *pts = MP_NOPTS_VALUE; - *keyframe = false; - - if (os->vorbis) { - if (*pack->packet & PACKET_TYPE_HEADER) { - os->hdr_packets++; - } else { - vorbis_info *vi; - int32_t blocksize = 0; - - // When we dump the audio, there is no vi, but we don't care of timestamp in this case - vi = os->vi_initialized ? &os->vi : NULL; - if (vi) - blocksize = vorbis_packet_blocksize(vi, pack) / samplesize; - // Calculate the timestamp if the packet don't have any - if (pack->granulepos == -1) { - pack->granulepos = os->lastpos; - if (os->lastsize > 0) - pack->granulepos += os->lastsize; - } else - *keyframe = true; - if (vi) - *pts = pack->granulepos / (float)vi->rate; - os->lastsize = blocksize; - os->lastpos = pack->granulepos; - } - } else if (os->speex) { - // whole packet (default) -# ifdef CONFIG_OGGTHEORA - } else if (os->theora) { - /* we pass complete packets to theora, mustn't strip the header! */ - os->lastsize = 1; - - /* header packets begin on 1-bit: thus check (*data&0x80). We don't - have theora_state st, until all header packets were passed to the - decoder. */ - if (!pack->bytes || !(*data&0x80)) { - int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1); - int64_t iframemask = (1 << keyframe_granule_shift) - 1; - - if (pack->granulepos >= 0) { - os->lastpos = pack->granulepos >> keyframe_granule_shift; - os->lastpos += pack->granulepos & iframemask; - *keyframe = (pack->granulepos & iframemask) == 0; - } else { - os->lastpos++; - } - pack->granulepos = os->lastpos; - *pts = (double)os->lastpos / (double)os->samplerate; - } -#endif /* CONFIG_OGGTHEORA */ - } else if (os->flac) { - /* we pass complete packets to flac, mustn't strip the header! */ - if (os->flac == 2 && pack->packet[0] != 0xff) - return NULL; - } else { - if (*pack->packet & PACKET_TYPE_HEADER) { - os->hdr_packets++; - } else { - // Find data start - int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6; - - hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1; - data = pack->packet + 1 + hdrlen; - // Calculate the timestamp - if (pack->granulepos == -1) - pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1); - // If we already have a timestamp it can be a syncpoint - if (*pack->packet & PACKET_IS_SYNCPOINT) - *keyframe = true; - *pts = pack->granulepos / os->samplerate; - // Save the packet length and timestamp - os->lastsize = 0; - while (hdrlen) { - os->lastsize <<= 8; - os->lastsize |= pack->packet[hdrlen]; - hdrlen--; - } - os->lastpos = pack->granulepos; - } - } - return data; -} - -// check if clang has substring from comma separated langlist -static int demux_ogg_check_lang(const char *clang, char **langlist) -{ - if (!langlist) - return 0; - for (int i = 0; langlist[i]; i++) - if (!strncasecmp(clang, langlist[i], strlen(langlist[i]))) - return 1; - return 0; -} - -/** \brief Change the current subtitle stream and return its ID. - - \param demuxer The demuxer whose subtitle stream will be changed. - \param new_num The number of the new subtitle track. The number must be - between 0 and ogg_d->n_text - 1. - - \returns The Ogg stream number ( = page serial number) of the newly selected - track. - */ -static int demux_ogg_sub_id(demuxer_t *demuxer, int index) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index]; -} - -/** \brief Translate the ogg track number into the subtitle number. - * \param demuxer The demuxer about whose subtitles we are inquiring. - * \param id The ogg track number of the subtitle track. - */ -static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - int i; - - for (i = 0; i < ogg_d->n_text; i++) - if (ogg_d->text_ids[i] == id) - return i; - return -1; -} - -/// Try to print out comments and also check for LANGUAGE= tag -static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, - int id, vorbis_comment *vc) -{ - const char *hdr, *val; - char **cmt = vc->user_comments; - int index, i; - ogg_demuxer_t *ogg_d = d->priv; - static const struct table { - const char *ogg; - const char *mp; - } table[] = { - { "ENCODED_USING", "Software" }, - { "ENCODER_URL", "Encoder URL" }, - { "TITLE", "Title" }, - { "ARTIST", "Artist" }, - { "COMMENT", "Comments" }, - { "DATE", "Creation Date" }, - { "GENRE", "Genre" }, - { "ALBUM", "Album" }, - { "TRACKNUMBER", "Track" }, - { NULL, NULL }, - }; - - while (*cmt) { - hdr = val = NULL; - if (!strncasecmp(*cmt, "LANGUAGE=", 9)) { - val = *cmt + 9; - if (ogg_d->subs[id].text) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", - ogg_d->subs[id].id, val); - else if (id != d->video->id) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", - ogg_d->subs[id].id, val); - if (ogg_d->subs[id].text) - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", - ogg_d->subs[id].id, val); - // copy this language name into the array - index = demux_ogg_sub_reverse_id(d, id); - if (index >= 0) { - sh_sub_t *sh; - - // in case of malicious files with more than one lang per track: - free(ogg_d->text_langs[index]); - ogg_d->text_langs[index] = strdup(val); - sh = d->s_streams[index]; - if (sh) { - talloc_free(sh->lang); - sh->lang = talloc_strdup(sh, val); - } - } - // check for -slang if subs are uninitialized yet - if (os->text && d->sub->id < 0 - && demux_ogg_check_lang(val, d->opts->sub_lang)) { - d->sub->id = index; - d->opts->sub_id = index; - mp_msg(MSGT_DEMUX, MSGL_V, - "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", - id, val); - } - else - hdr = "Language"; - } - else { - for (i = 0; table[i].ogg; i++) { - if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) && - (*cmt)[strlen(table[i].ogg)] == '=') { - hdr = table[i].mp; - val = *cmt + strlen(table[i].ogg) + 1; - } - } - } - if (hdr) - demux_info_add(d, hdr, val); - mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val); - cmt++; - } -} - -/// Calculate the timestamp and add the packet to the demux stream -// return 1 if the packet was added, 0 otherwise -static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os, - int id, ogg_packet *pack) -{ - demuxer_t *d = ds->demuxer; - int samplesize = 1; - - // If packet is an comment header then we try to get comments at first - if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) { - vorbis_info vi; - vorbis_comment vc; - - vorbis_info_init(&vi); - vorbis_comment_init(&vc); - vi.rate = 1L; // it's checked by vorbis_synthesis_headerin() - if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors - demux_ogg_check_comments(d, os, id, &vc); - vorbis_comment_clear(&vc); - vorbis_info_clear(&vi); - } - if (os->text) { - if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now - demux_ogg_add_sub(os, pack); - return 0; - } - if (os->speex) { - // discard first two packets, they contain the header and comment - if (os->hdr_packets < 2) { - os->hdr_packets++; - return 0; - } - } else { - // If packet is an header we jump it except for vorbis and theora - // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!) - // We jump nothing for FLAC. Ain't this great? Packet contents have to be - // handled differently for each and every stream type. The joy! The joy! - if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) && - (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) && - (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA))) - return 0; - } - - // For vorbis packet the packet is the data, for other codec we must jump - // the header - if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) { - samplesize = ((sh_audio_t *)ds->sh)->samplesize; - } - bool keyframe; - float pts; - unsigned char *data; - data = demux_ogg_read_packet(os, pack, &pts, &keyframe, samplesize); - if (!data) - return 0; - - /// Clear subtitles if necessary (for broken files) - if (sub_clear_text(&ogg_sub, pts)) { - vo_sub = &ogg_sub; - vo_osd_changed(OSDTYPE_SUBTITLE); - } - /// Send the packet - struct demux_packet *dp; - dp = new_demux_packet(pack->bytes - (data - pack->packet)); - memcpy(dp->buffer, data, pack->bytes - (data - pack->packet)); - dp->pts = pts; - dp->keyframe = keyframe; - ds_add_packet(ds, dp); - mp_msg(MSGT_DEMUX, MSGL_DBG2, - "New dp: %p ds=%p pts=%5.3f len=%d keyframe=%d \n", - dp, ds, pts, dp->len, keyframe); - return 1; -} - -/// if -forceidx build a table of all syncpoints to make seeking easier -/// otherwise try to get at least the final_granulepos -static void demux_ogg_scan_stream(demuxer_t *demuxer) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - stream_t *s = demuxer->stream; - ogg_sync_state *sync = &ogg_d->sync; - ogg_page *page = &ogg_d->page; - ogg_stream_state *oss; - ogg_stream_t *os; - ogg_packet op; - int np, sid, p, samplesize = 1; - off_t pos, last_pos; - - pos = last_pos = demuxer->movi_start; - - // Reset the stream - stream_seek(s, demuxer->movi_start); - ogg_sync_reset(sync); - - // Get the serial number of the stream we use - if (demuxer->video->id >= 0) { - sid = demuxer->video->id; - } else if (demuxer->audio->id >= 0) { - sid = demuxer->audio->id; - if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) - samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize; - } else - return; - os = &ogg_d->subs[sid]; - oss = &os->stream; - - while (1) { - np = ogg_sync_pageseek(sync, page); - if (np < 0) { // We had to skip some bytes - if (index_mode == 2) - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Bad page sync while building syncpoints table (%d)\n", - -np); - pos += -np; - continue; - } - if (np <= 0) { // We need more data - char *buf = ogg_sync_buffer(sync, BLOCK_SIZE); - int len = stream_read(s, buf, BLOCK_SIZE); - - if (len == 0 && s->eof) - break; - ogg_sync_wrote(sync, len); - continue; - } - // The page is ready - //ogg_sync_pageout(sync, page); - if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want - pos += np; - continue; - } - if (ogg_stream_pagein(oss, page) != 0) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n"); - pos += np; - continue; - } - p = 0; - while (ogg_stream_packetout(oss, &op) == 1) { - float pts; - bool keyframe; - - demux_ogg_read_packet(os, &op, &pts, &keyframe, samplesize); - if (op.granulepos >= 0) { - ogg_d->final_granulepos = op.granulepos; - if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && keyframe) { - ogg_d->initial_granulepos = op.granulepos; - if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) { - //the 270000 are just a wild guess - stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000)); - ogg_sync_reset(sync); - continue; - } - } - } - if (index_mode == 2 && (keyframe || (os->vorbis && op.granulepos >= 0))) { - if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) - break; - ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t)); - ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos; - ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos; - ogg_d->num_syncpoint++; - } - p++; - } - if (p > 1 || (p == 1 && !ogg_page_continued(page))) - last_pos = pos; - pos += np; - if (index_mode == 2) - mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r", - (int)(pos * 100 / s->end_pos)); - } - - if (index_mode == 2) { - mp_msg(MSGT_DEMUX, MSGL_INFO, "\n"); - mp_msg(MSGT_DEMUX, MSGL_V, - "Ogg syncpoints table builed: %d syncpoints\n", - ogg_d->num_syncpoint); - } - - mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n", - ogg_d->final_granulepos); - - stream_reset(s); - stream_seek(s, demuxer->movi_start); - ogg_sync_reset(sync); - for (np = 0; np < ogg_d->num_sub; np++) { - ogg_stream_reset(&ogg_d->subs[np].stream); - ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0; - } - - // Get the first page - while (1) { - np = ogg_sync_pageout(sync, page); - if (np <= 0) { // We need more data - char *buf = ogg_sync_buffer(sync, BLOCK_SIZE); - int len = stream_read(s, buf, BLOCK_SIZE); - - if (len == 0 && s->eof) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n"); - break; - } - ogg_sync_wrote(sync, len); - continue; - } - demux_ogg_get_page_stream(ogg_d, &oss); - ogg_stream_pagein(oss, page); - break; - } -} - -static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od) -{ - int i, offset; - int ris, init_error = 0; - ogg_packet op[3]; - unsigned char *buf[3]; - unsigned char *ptr; - unsigned int len; - ogg_stream_t *os = &od->subs[sh->ds->id]; - vorbis_comment vc; - - vorbis_info_init(&os->vi); - vorbis_comment_init(&vc); - for (i = 0; i < 3; i++) { - op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet)); - mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes); - if (op[i].bytes < 0) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i); - return; - } - buf[i] = malloc(op[i].bytes); - if (!buf[i]) - return; - memcpy(buf[i], op[i].packet, op[i].bytes); - - op[i].b_o_s = (i == 0); - ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]); - if (ris < 0) { - init_error = 1; - mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris); - } - } - vorbis_comment_clear(&vc); - if (!init_error) - os->vi_initialized = 1; - - len = op[0].bytes + op[1].bytes + op[2].bytes; - sh->wf = calloc(1, sizeof(*sh->wf) + len + len / 255 + 64); - ptr = (unsigned char*)(sh->wf + 1); - - ptr[0] = 2; - offset = 1; - offset += store_ughvlc(&ptr[offset], op[0].bytes); - mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset); - offset += store_ughvlc(&ptr[offset], op[1].bytes); - mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset); - for (i = 0; i < 3; i++) { - mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset); - memcpy(&ptr[offset], buf[i], op[i].bytes); - offset += op[i].bytes; - } - sh->wf->cbSize = offset; - mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize); - sh->wf = realloc(sh->wf, sizeof(*sh->wf) + sh->wf->cbSize); - - if (op[0].bytes >= 29) { - unsigned int br; - int nombr, minbr, maxbr; - - ptr = buf[0]; - sh->channels = ptr[11]; - sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]); - maxbr = AV_RL32(&ptr[16]); //max - nombr = AV_RL32(&ptr[20]); //nominal - minbr = AV_RL32(&ptr[24]); //minimum - - if (maxbr == -1) - maxbr = 0; - if (nombr == -1) - nombr = 0; - if (minbr == -1) - minbr = 0; - - br = maxbr / 8; - if (!br) - br = nombr / 8; - if (!br) - br = minbr / 8; - sh->wf->nAvgBytesPerSec = br; - sh->wf->wBitsPerSample = 16; - sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8; - - mp_msg(MSGT_DEMUX, MSGL_V, - "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n", - sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, - maxbr, nombr, minbr); - } - free(buf[2]); - free(buf[1]); - free(buf[0]); -} - -/// Open an ogg physical stream -// Not static because it's used also in demuxer_avi.c -int demux_ogg_open(demuxer_t *demuxer) -{ - ogg_demuxer_t *ogg_d; - stream_t *s; - char *buf; - int np, s_no, n_audio = 0, n_video = 0; - int audio_id = -1, video_id = -1, text_id = -1; - ogg_sync_state *sync; - ogg_page *page; - ogg_packet pack; - sh_audio_t *sh_a; - sh_video_t *sh_v; - -#ifdef CONFIG_ICONV - subcp_open(NULL); -#endif - - s = demuxer->stream; - - demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d)); - sync = &ogg_d->sync; - page = &ogg_d->page; - - ogg_sync_init(sync); - - while (1) { - /// Try to get a page - ogg_d->pos += ogg_d->last_size; - np = ogg_sync_pageseek(sync, page); - /// Error - if (np < 0) { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n"); - goto err_out; - } - /// Need some more data - if (np == 0) { - int len; - - buf = ogg_sync_buffer(sync, BLOCK_SIZE); - len = stream_read(s, buf, BLOCK_SIZE); - if (len == 0 && s->eof) { - goto err_out; - } - ogg_sync_wrote(sync, len); - continue; - } - ogg_d->last_size = np; - // We got one page now - - if (!ogg_page_bos(page)) { // It's not a beginning page - // Header parsing end here, we need to get the page otherwise it will be lost - int id = demux_ogg_get_page_stream(ogg_d, NULL); - if (id >= 0) - ogg_stream_pagein(&ogg_d->subs[id].stream, page); - else - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Ogg : Warning found none bos page from unknown stream %d\n", - ogg_page_serialno(page)); - break; - } - - /// Init the data structure needed for a logical stream - ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1, - sizeof(ogg_stream_t)); - memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t)); - /// Get the stream serial number - s_no = ogg_page_serialno(page); - ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no); - mp_msg(MSGT_DEMUX, MSGL_DBG2, - "Ogg : Found a stream with serial=%d\n", s_no); - // Take the first page - ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page); - // Get first packet of the page - ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack); - - // Reset our vars - sh_a = NULL; - sh_v = NULL; - - ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d; - - // Check for Vorbis - if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) { - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - sh_a->format = FOURCC_VORBIS; - ogg_d->subs[ogg_d->num_sub].vorbis = 1; - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (Vorbis), -aid %d\n", - ogg_d->num_sub, n_audio - 1); - } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) { - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - sh_a->wf = calloc(1, sizeof(*sh_a->wf) + pack.bytes); - sh_a->format = FOURCC_SPEEX; - sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]); - sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]); - sh_a->wf->wFormatTag = sh_a->format; - sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]); - sh_a->wf->nBlockAlign = 0; - sh_a->wf->wBitsPerSample = 16; - sh_a->samplesize = 2; - sh_a->wf->cbSize = pack.bytes; - memcpy(&sh_a->wf[1], pack.packet, pack.bytes); - - ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; - ogg_d->subs[ogg_d->num_sub].speex = 1; - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (Speex), -aid %d\n", - ogg_d->num_sub, n_audio - 1); - - // check for Theora -#ifdef CONFIG_OGGTHEORA - } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) { - int errorCode = 0; - theora_info inf; - theora_comment cc; - - theora_info_init (&inf); - theora_comment_init (&cc); - - errorCode = theora_decode_header (&inf, &cc, &pack); - if (errorCode) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Theora header parsing failed: %i \n", errorCode); - } else { - sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video); - - sh_v->bih = calloc(1, sizeof(*sh_v->bih)); - sh_v->bih->biSize = sizeof(*sh_v->bih); - sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA; - sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator; - sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator; - sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width; - sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height; - sh_v->bih->biBitCount = 24; - sh_v->bih->biPlanes = 3; - sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight); - ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps; - ogg_d->subs[ogg_d->num_sub].theora = 1; - ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force; - ogg_d->subs[ogg_d->num_sub].id = n_video; - n_video++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n", - ogg_d->num_sub, - (int)inf.version_major, - (int)inf.version_minor, - (int)inf.version_subminor, - n_video - 1); - if (mp_msg_test(MSGT_HEADER, MSGL_V)) - print_video_header(sh_v->bih, MSGL_V); - } - theora_comment_clear(&cc); - theora_info_clear(&inf); -#endif /* CONFIG_OGGTHEORA */ - } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) { - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - ogg_d->subs[ogg_d->num_sub].flac = 1; - sh_a->wf = NULL; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (FLAC), -aid %d\n", - ogg_d->num_sub, n_audio - 1); - } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) { - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - ogg_d->subs[ogg_d->num_sub].flac = 2; - sh_a->wf = calloc(1, sizeof(*sh_a->wf) + 34); - sh_a->wf->wFormatTag = sh_a->format; - sh_a->wf->cbSize = 34; - memcpy(&sh_a->wf[1], &pack.packet[17], 34); - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n", - ogg_d->num_sub, n_audio - 1); - - /// Check for old header - } else if (pack.bytes >= 142 && - !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) { - - // Old video header - if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) { - sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video); - sh_v->bih = calloc(1, sizeof(*sh_v->bih)); - sh_v->bih->biSize = sizeof(*sh_v->bih); - sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69], - pack.packet[70], pack.packet[71]); - sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001; - sh_v->fps = 1 / sh_v->frametime; - sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176); - sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180); - sh_v->bih->biBitCount = AV_RL16(pack.packet + 182); - if (!sh_v->bih->biBitCount) - sh_v->bih->biBitCount = 24; // hack, FIXME - sh_v->bih->biPlanes = 1; - sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight; - - ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps; - ogg_d->subs[ogg_d->num_sub].id = n_video; - n_video++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n", - ogg_d->num_sub, pack.packet[68], pack.packet[69], - pack.packet[70], pack.packet[71], n_video - 1); - if (mp_msg_test(MSGT_HEADER, MSGL_V)) - print_video_header(sh_v->bih, MSGL_V); - // Old audio header - } else if (AV_RL32(pack.packet + 96) == 0x05589F81) { - unsigned int extra_size; - - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - extra_size = AV_RL16(pack.packet + 140); - sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size); - sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124); - sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126); - sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128); - sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132); - sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136); - sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138); - sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8; - sh_a->wf->cbSize = extra_size; - if (extra_size > 0) - memcpy(sh_a->wf + 1, - pack.packet + 142, extra_size); - - ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels; - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n", - ogg_d->num_sub, sh_a->format, n_audio - 1); - if (mp_msg_test(MSGT_HEADER, MSGL_V)) - print_wave_header(sh_a->wf, MSGL_V); - } else - mp_msg(MSGT_DEMUX, MSGL_WARN, - "Ogg stream %d contains an old header but the header type is unknown\n", - ogg_d->num_sub); - - // Check new header - } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER && - pack.bytes >= (int)sizeof(stream_header) + 1) { - stream_header *st = (stream_header*)(pack.packet + 1); - /// New video header - if (strncmp(st->streamtype, "video", 5) == 0) { - sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video); - sh_v->bih = calloc(1, sizeof(*sh_v->bih)); - sh_v->bih->biSize = sizeof(*sh_v->bih); - sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1], - st->subtype[2], st->subtype[3]); - sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001; - sh_v->fps = 1.0 / sh_v->frametime; - sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample); - sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width); - sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height); - if (!sh_v->bih->biBitCount) - sh_v->bih->biBitCount = 24; // hack, FIXME - sh_v->bih->biPlanes = 1; - sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight; - - ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps; - ogg_d->subs[ogg_d->num_sub].id = n_video; - n_video++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n", - ogg_d->num_sub, st->subtype[0], st->subtype[1], - st->subtype[2], st->subtype[3], n_video - 1); - if (mp_msg_test(MSGT_HEADER, MSGL_V)) - print_video_header(sh_v->bih, MSGL_V); - /// New audio header - } else if (strncmp(st->streamtype, "audio", 5) == 0) { - char buffer[5]; - unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header); - unsigned int extra_offset = 0; - - memcpy(buffer, st->subtype, 4); - buffer[4] = '\0'; - - /* Nasty workaround. stream_header.size seems not to contain the real - size in all cases. There are four extra bytes that are unaccounted - for in front of the real codec initialization data _at least_ for - AAC. So far I've only seen those bytes being all 0, so we can - just skip them here. */ - if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) { - extra_size -= 4; - extra_offset = 4; - } - - sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio); - sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size); - sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16); - sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels); - sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit); - sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec); - sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign); - sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample); - sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8; - sh_a->wf->cbSize = extra_size; - if (extra_size) - memcpy(sh_a->wf+1, - ((char *)(st+1))+extra_offset, extra_size); - - ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels; - ogg_d->subs[ogg_d->num_sub].id = n_audio; - n_audio++; - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n", - ogg_d->num_sub, sh_a->format, n_audio - 1); - if (mp_msg_test(MSGT_HEADER, MSGL_V)) - print_wave_header(sh_a->wf, MSGL_V); - - /// Check for text (subtitles) header - } else if (strncmp(st->streamtype, "text", 4) == 0) { - mp_msg(MSGT_DEMUX, MSGL_INFO, - "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n", - ogg_d->num_sub, ogg_d->n_text); - ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10; - ogg_d->subs[ogg_d->num_sub].text = 1; - ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text; - if (demuxer->sub->id == ogg_d->n_text) - text_id = ogg_d->num_sub; - new_sh_sub(demuxer, ogg_d->n_text); - ogg_d->n_text++; - ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids)); - ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub; - ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs)); - ogg_d->text_langs[ogg_d->n_text - 1] = NULL; - //// Unknown header type - } else - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Ogg stream %d has a header marker but is of an unknown type\n", - ogg_d->num_sub); - /// Unknown (invalid ?) header - } else - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Ogg stream %d is of an unknown type\n", - ogg_d->num_sub); - - if (sh_a || sh_v) { - demux_stream_t *ds = NULL; - if (sh_a) { - // If the audio stream is not defined we took the first one - if (demuxer->audio->id == -1) { - demuxer->audio->id = n_audio - 1; - //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO); - } - /// Is it the stream we want - if (demuxer->audio->id == n_audio - 1) { - demuxer->audio->sh = sh_a; - sh_a->ds = demuxer->audio; - ds = demuxer->audio; - audio_id = ogg_d->num_sub; - } - } - if (sh_v) { - /// Also for video - if (demuxer->video->id == -1) { - demuxer->video->id = n_video - 1; - //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO); - } - if (demuxer->video->id == n_video - 1) { - demuxer->video->sh = sh_v; - sh_v->ds = demuxer->video; - ds = demuxer->video; - video_id = ogg_d->num_sub; - } - } - /// Add the header packets if the stream isn't seekable - if (ds && !s->end_pos) { - /// Finish the page, otherwise packets will be lost - do { - demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub], - ogg_d->num_sub, &pack); - } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1); - } - } - ogg_d->num_sub++; - } - - if (!n_video && !n_audio) { - goto err_out; - } - - if (!n_video || video_id < 0) - demuxer->video->id = -2; - else - demuxer->video->id = video_id; - if (!n_audio || audio_id < 0) - demuxer->audio->id = -2; - else - demuxer->audio->id = audio_id; - /* Disable the subs only if there are no text streams at all. - Otherwise the stream to display might be chosen later when the comment - packet is encountered and the user used -slang instead of -sid. */ - if (!ogg_d->n_text) - demuxer->sub->id = -2; - else if (text_id >= 0) { - demuxer->sub->id = text_id; - mp_msg(MSGT_DEMUX, MSGL_V, - "Ogg demuxer: Displaying subtitle stream id %d\n", text_id); - } - - ogg_d->final_granulepos = 0; - ogg_d->initial_granulepos = MP_NOPTS_VALUE; - if (!s->end_pos) { - demuxer->seekable = 0; - } else { - demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2) - demuxer->movi_end = s->end_pos; - demuxer->seekable = 1; - demux_ogg_scan_stream(demuxer); - } - if (ogg_d->initial_granulepos == MP_NOPTS_VALUE) - ogg_d->initial_granulepos = 0; - ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos; - - mp_msg(MSGT_DEMUX, MSGL_V, - "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n", - n_audio, n_audio > 1 ? "s" : "", - n_video, n_video > 1 ? "s" : "", - ogg_d->n_text, ogg_d->n_text > 1 ? "s" : ""); - - sh_a = demuxer->audio->sh; - if (sh_a && sh_a->format == FOURCC_VORBIS) - fixup_vorbis_wf(sh_a, ogg_d); - - return DEMUXER_TYPE_OGG; - -err_out: - return 0; -} - -static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) -{ - ogg_demuxer_t *ogg_d; - stream_t *s; - demux_stream_t *ds; - ogg_sync_state *sync; - ogg_stream_state *os; - ogg_page *page; - ogg_packet pack; - int np = 0, id=0; - - s = d->stream; - ogg_d = d->priv; - sync = &ogg_d->sync; - page = &ogg_d->page; - - /// Find the stream we are working on - if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n"); - return 0; - } - - while (1) { - np = 0; - ds = NULL; - /// Try to get some packet from the current page - while ((np = ogg_stream_packetout(os, &pack)) != 1) { - /// No packet we go the next page - if (np == 0) { - while (1) { - int pa, len; - char *buf; - - ogg_d->pos += ogg_d->last_size; - /// Get the next page from the physical stream - while ((pa = ogg_sync_pageseek(sync, page)) <= 0) { - /// Error : we skip some bytes - if (pa < 0) { - mp_msg(MSGT_DEMUX, MSGL_WARN, - "Ogg : Page out not synced, we skip some bytes\n"); - ogg_d->pos -= pa; - continue; - } - /// We need more data - buf = ogg_sync_buffer(sync, BLOCK_SIZE); - len = stream_read(s, buf, BLOCK_SIZE); - if (len == 0 && s->eof) { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n"); - return 0; - } - ogg_sync_wrote(sync, len); - } /// Page loop - ogg_d->last_size = pa; - /// Find the page's logical stream - if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "Ogg demuxer error : we met an unknown stream\n"); - return 0; - } - /// Take the page - if (ogg_stream_pagein(os, page) == 0) - break; - /// Page was invalid => retry - mp_msg(MSGT_DEMUX, MSGL_WARN, - "Ogg demuxer : got invalid page !!!!!\n"); - ogg_d->pos += ogg_d->last_size; - } - } else /// Packet was corrupted - mp_msg(MSGT_DEMUX, MSGL_WARN, - "Ogg : bad packet in stream %d\n", id); - } /// Packet loop - - /// Is the actual logical stream in use ? - if (id == d->audio->id) - ds = d->audio; - else if (id == d->video->id) - ds = d->video; - else if (ogg_d->subs[id].text) - ds = d->sub; - - if (ds) { - if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack)) - continue; /// Unuseful packet, get another - d->filepos = ogg_d->pos; - return 1; - } - } /// while (1) -} - -/// For avi with Ogg audio stream we have to create an ogg demuxer for this -// stream, then we join the avi and ogg demuxer with a demuxers demuxer -demuxer_t *init_avi_with_ogg(demuxer_t *demuxer) -{ - struct MPOpts *opts = demuxer->opts; - demuxer_t *od; - ogg_demuxer_t *ogg_d; - stream_t *s; - uint32_t hdrsizes[3]; - demux_packet_t *dp; - sh_audio_t *sh_audio = demuxer->audio->sh; - int np; - uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1); - int i; - unsigned char *p = NULL, *buf; - int plen; - - /// Check that the cbSize is big enough for the following reads - if (sh_audio->wf->cbSize < 22 + 3 * 4) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "AVI Ogg : Initial audio header is too small !!!!!\n"); - goto fallback; - } - /// Get the size of the 3 header packet - extradata += 22; - for (i = 0; i < 3; i++) { - hdrsizes[i] = AV_RL32(extradata); - extradata += 4; - } - // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]); - - /// Check the size - if (sh_audio->wf->cbSize < 22 + 3 * 4 + hdrsizes[0] + hdrsizes[1] + hdrsizes[2]) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "AVI Ogg : Audio header is too small !!!!!\n"); - goto fallback; - } - - // Build the ogg demuxer private datas - ogg_d = calloc(1, sizeof(*ogg_d)); - ogg_d->num_sub = 1; - ogg_d->subs = malloc(sizeof(*ogg_d->subs)); - ogg_d->subs[0].vorbis = 1; - - // Init the ogg physical stream - ogg_sync_init(&ogg_d->sync); - - // Get the first page of the stream : we assume there only 1 logical stream - while ((np = ogg_sync_pageout(&ogg_d->sync, &ogg_d->page)) <= 0 ) { - if (np < 0) { - mp_msg(MSGT_DEMUX, MSGL_ERR, - "AVI Ogg error : Can't init using first stream packets\n"); - free(ogg_d); - goto fallback; - } - // Add some data - plen = ds_get_packet(demuxer->audio, &p); - buf = ogg_sync_buffer(&ogg_d->sync, plen); - memcpy(buf, p, plen); - ogg_sync_wrote(&ogg_d->sync, plen); - } - // Init the logical stream - mp_msg(MSGT_DEMUX, MSGL_DBG2, - "AVI Ogg found page with serial %d\n", - ogg_page_serialno(&ogg_d->page)); - ogg_stream_init(&ogg_d->subs[0].stream, ogg_page_serialno(&ogg_d->page)); - // Write the page - ogg_stream_pagein(&ogg_d->subs[0].stream, &ogg_d->page); - - // Create the ds_stream and the ogg demuxer - s = new_ds_stream(demuxer->audio); - od = new_demuxer(opts, s, DEMUXER_TYPE_OGG, 0, -2, -2, NULL); - - /// Add the header packets in the ogg demuxer audio stream - for (i = 0; i < 3; i++) { - dp = new_demux_packet(hdrsizes[i]); - memcpy(dp->buffer, extradata, hdrsizes[i]); - ds_add_packet(od->audio, dp); - extradata += hdrsizes[i]; - } - - // Finish setting up the ogg demuxer - od->priv = ogg_d; - sh_audio = new_sh_audio(od, 0); - od->audio->id = 0; - od->video->id = -2; - od->audio->sh = sh_audio; - sh_audio->ds = od->audio; - sh_audio->format = FOURCC_VORBIS; - fixup_vorbis_wf(sh_audio, ogg_d); - - /// Return the joined demuxers - return new_demuxers_demuxer(demuxer, od, demuxer); - -fallback: - demuxer->audio->id = -2; - return demuxer; - -} - -static void demux_ogg_seek(demuxer_t *demuxer, float rel_seek_secs, - float audio_delay, int flags) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - ogg_sync_state *sync = &ogg_d->sync; - ogg_page* page= &ogg_d->page; - ogg_stream_state *oss; - ogg_stream_t *os; - demux_stream_t *ds; - ogg_packet op; - float rate; - int i, sp, first = 1, precision = 1, do_seek = 1; - vorbis_info *vi = NULL; - int64_t gp = 0, old_gp; - off_t pos, old_pos; - int np; - int is_gp_valid; - float pts; - bool is_keyframe; - int samplesize = 1; - ogg_int64_t granulepos_orig; - - if (demuxer->video->id >= 0) { - ds = demuxer->video; - rate = ogg_d->subs[ds->id].samplerate; - } else { - ds = demuxer->audio; - os = &ogg_d->subs[ds->id]; - vi = &(os->vi); - rate = (float)vi->rate; - samplesize = ((sh_audio_t*)ds->sh)->samplesize; - } - - os = &ogg_d->subs[ds->id]; - oss = &os->stream; - - old_gp = os->lastpos; - old_pos = ogg_d->pos; - - //calculate the granulepos to seek to - gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos; - if (flags & SEEK_FACTOR) { - if (ogg_d->duration > 0) - gp += ogg_d->duration * rel_seek_secs; - else - gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos; - } else - gp += rel_seek_secs * rate; - if (gp < 0) - gp = 0; - - //calculate the filepos to seek to - if (ogg_d->syncpoints) { - for (sp = 0; sp < ogg_d->num_syncpoint; sp++) - if (ogg_d->syncpoints[sp].granulepos >= gp) - break; - - if (sp >= ogg_d->num_syncpoint) - return; - if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp - 1].granulepos) - sp--; - if (ogg_d->syncpoints[sp].granulepos == os->lastpos) { - if (sp > 0 && gp < os->lastpos) - sp--; - if (sp < ogg_d->num_syncpoint - 1 && gp > os->lastpos) - sp++; - } - pos = ogg_d->syncpoints[sp].page_pos; - precision = 0; - } else { - pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos; - if (flags & SEEK_FACTOR) - pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs; - else { - if (ogg_d->duration > 0) { - pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate); - } else if (os->lastpos > 0) { - pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate); - } - } - if (pos < 0) - pos = 0; - if (pos > (demuxer->movi_end - demuxer->movi_start)) - pos = demuxer->movi_end - demuxer->movi_start; - } // if (ogg_d->syncpoints) - - while (1) { - if (do_seek) { - stream_seek(demuxer->stream, pos+demuxer->movi_start); - ogg_sync_reset(sync); - for (i = 0; i < ogg_d->num_sub; i++) { - ogg_stream_reset(&ogg_d->subs[i].stream); - ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0; - } - ogg_d->pos = pos; - ogg_d->last_size = 0; - /* we just guess that we reached correct granulepos, in case a - subsequent search occurs before we read a valid granulepos */ - os->lastpos = gp; - first = !(ogg_d->syncpoints); - do_seek=0; - } - ogg_d->pos += ogg_d->last_size; - ogg_d->last_size = 0; - np = ogg_sync_pageseek(sync, page); - - if (np < 0) - ogg_d->pos -= np; - if (np <= 0) { // We need more data - char *buf = ogg_sync_buffer(sync, BLOCK_SIZE); - int len = stream_read(demuxer->stream, buf, BLOCK_SIZE); - - if (len == 0 && demuxer->stream->eof) { - mp_msg(MSGT_DEMUX, MSGL_V, "EOF while trying to seek !!!!\n"); - return; - } - ogg_sync_wrote(sync, len); - continue; - } - ogg_d->last_size = np; - if (ogg_page_serialno(page) != oss->serialno) - continue; - - if (ogg_stream_pagein(oss, page) != 0) - continue; - - while (1) { - np = ogg_stream_packetout(oss, &op); - if (np < 0) - continue; - else if (np == 0) - break; - if (first) { /* Discard the first packet as it's probably broken, - and we don't have any other means to decide whether it is - complete or not. */ - first = 0; - break; - } - is_gp_valid = (op.granulepos >= 0); - granulepos_orig=op.granulepos; - demux_ogg_read_packet(os, &op, &pts, &is_keyframe, samplesize); - if (precision && is_gp_valid) { - precision--; - if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) { - //prepare another seek because we are off by more than 1s - pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp); - if (pos < 0) - pos = 0; - if (pos < demuxer->movi_end - demuxer->movi_start) { - do_seek=1; - break; - } - } - } - if (is_gp_valid && pos > 0 && old_gp > gp - && 2 * (old_gp - op.granulepos) < old_gp - gp) { - /* prepare another seek because looking for a syncpoint - destroyed the backward search */ - pos = old_pos - 1.5 * (old_pos - pos); - if (pos < 0) - pos = 0; - if (pos < demuxer->movi_end - demuxer->movi_start) { - do_seek=1; - break; - } - } - if (!precision && (is_keyframe || os->vorbis || os->speex)) { - if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) { - vo_sub = &ogg_sub; - vo_osd_changed(OSDTYPE_SUBTITLE); - } - op.granulepos=granulepos_orig; - demux_ogg_add_packet(ds, os, ds->id, &op); - return; - } - } - } - - mp_msg(MSGT_DEMUX, MSGL_ERR, "Can't find the good packet :(\n"); -} - -static void demux_close_ogg(demuxer_t *demuxer) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - ogg_stream_t *os = NULL; - int i; - - if (!ogg_d) - return; - -#ifdef CONFIG_ICONV - subcp_close(); -#endif - - ogg_sync_clear(&ogg_d->sync); - if (ogg_d->subs) { - for (i = 0; i < ogg_d->num_sub; i++) { - os = &ogg_d->subs[i]; - ogg_stream_clear(&os->stream); - if (os->vi_initialized) - vorbis_info_clear(&os->vi); - } - free(ogg_d->subs); - } - free(ogg_d->syncpoints); - free(ogg_d->text_ids); - if (ogg_d->text_langs) { - for (i = 0; i < ogg_d->n_text; i++) - free(ogg_d->text_langs[i]); - free(ogg_d->text_langs); - } - free(ogg_d); -} - -static int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg) -{ - ogg_demuxer_t *ogg_d = demuxer->priv; - ogg_stream_t *os; - float rate; - - if (demuxer->video->id >= 0) { - os = &ogg_d->subs[demuxer->video->id]; - rate = os->samplerate; - } else { - os = &ogg_d->subs[demuxer->audio->id]; - rate = os->vi.rate; - } - - switch(cmd) { - case DEMUXER_CTRL_GET_TIME_LENGTH: - if (ogg_d->duration <= 0) - return DEMUXER_CTRL_DONTKNOW; - *(double *)arg = (double)(ogg_d->duration) / rate; - return DEMUXER_CTRL_GUESS; - - case DEMUXER_CTRL_GET_PERCENT_POS: - if (ogg_d->duration <= 0) - return DEMUXER_CTRL_DONTKNOW; - *(int *)arg = ((os->lastpos - ogg_d->initial_granulepos) * 100) / ogg_d->duration; - return DEMUXER_CTRL_OK; - - default: - return DEMUXER_CTRL_NOTIMPL; - } -} - -const demuxer_desc_t demuxer_desc_ogg = { - "Ogg demuxer", - "ogg", - "Ogg", - "?", - "", - DEMUXER_TYPE_OGG, - 1, // safe autodetect - demux_ogg_open, - demux_ogg_fill_buffer, - NULL, - demux_close_ogg, - demux_ogg_seek, - demux_ogg_control -}; diff --git a/libmpdemux/demux_ogg.h b/libmpdemux/demux_ogg.h deleted file mode 100644 index 0bdc30b910..0000000000 --- a/libmpdemux/demux_ogg.h +++ /dev/null @@ -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 */ diff --git a/libmpdemux/demux_pva.c b/libmpdemux/demux_pva.c deleted file mode 100644 index 883641fbc8..0000000000 --- a/libmpdemux/demux_pva.c +++ /dev/null @@ -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,¤t_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 -}; diff --git a/libmpdemux/demux_roq.c b/libmpdemux/demux_roq.c deleted file mode 100644 index af9e4c5a8e..0000000000 --- a/libmpdemux/demux_roq.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_smjpeg.c b/libmpdemux/demux_smjpeg.c deleted file mode 100644 index 8dabc8a0e2..0000000000 --- a/libmpdemux/demux_smjpeg.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c deleted file mode 100644 index dbf12b7456..0000000000 --- a/libmpdemux/demux_ts.c +++ /dev/null @@ -1,3533 +0,0 @@ -/* - * Demultiplexer for MPEG2 Transport Streams. - * - * Written by Nico <nsabbi@libero.it> - * Kind feedback is appreciated; 'sucks' and alike is not. - * Originally based on demux_pva.c written by Matteo Giani and FFmpeg (libavformat) sources - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "config.h" -#include "mp_msg.h" -#include "options.h" - -#include "libmpcodecs/dec_audio.h" -#include "stream/stream.h" -#include "demuxer.h" -#include "parse_es.h" -#include "stheader.h" -#include "ms_hdr.h" -#include "mpeg_hdr.h" -#include "demux_ts.h" - -#define TS_PH_PACKET_SIZE 192 -#define TS_FEC_PACKET_SIZE 204 -#define TS_PACKET_SIZE 188 -#define NB_PID_MAX 8192 - -#define MAX_HEADER_SIZE 6 /* enough for PES header + length */ -#define MAX_CHECK_SIZE 65535 -#define NUM_CONSECUTIVE_TS_PACKETS 32 -#define NUM_CONSECUTIVE_AUDIO_PACKETS 348 -#define MAX_A52_FRAME_SIZE 3840 - -#ifndef SIZE_MAX -#define SIZE_MAX ((size_t)-1) -#endif - -#define TYPE_AUDIO 1 -#define TYPE_VIDEO 2 -#define TYPE_SUB 3 - -int ts_prog; -int ts_keep_broken=0; -off_t ts_probe = 0; -int audio_substream_id = -1; - -typedef enum -{ - UNKNOWN = -1, - VIDEO_MPEG1 = 0x10000001, - VIDEO_MPEG2 = 0x10000002, - VIDEO_MPEG4 = 0x10000004, - VIDEO_H264 = 0x10000005, - VIDEO_AVC = mmioFOURCC('a', 'v', 'c', '1'), - VIDEO_DIRAC = mmioFOURCC('d', 'r', 'a', 'c'), - VIDEO_VC1 = mmioFOURCC('W', 'V', 'C', '1'), - AUDIO_MP2 = 0x50, - AUDIO_A52 = 0x2000, - AUDIO_DTS = 0x2001, - AUDIO_LPCM_BE = 0x10001, - AUDIO_AAC = mmioFOURCC('M', 'P', '4', 'A'), - AUDIO_AAC_LATM = mmioFOURCC('M', 'P', '4', 'L'), - AUDIO_TRUEHD = mmioFOURCC('T', 'R', 'H', 'D'), - AUDIO_S302M = mmioFOURCC('B', 'S', 'S', 'D'), - SPU_DVD = 0x3000000, - SPU_DVB = 0x3000001, - SPU_TELETEXT = 0x3000002, - SPU_PGS = 0x3000003, - PES_PRIVATE1 = 0xBD00000, - SL_PES_STREAM = 0xD000000, - SL_SECTION = 0xD100000, - MP4_OD = 0xD200000, -} es_stream_type_t; - -typedef struct { - uint8_t *buffer; - uint16_t buffer_len; -} ts_section_t; - -typedef struct { - int size; - unsigned char *start; - uint16_t payload_size; - es_stream_type_t type, subtype; - double pts, last_pts; - int pid; - char lang[4]; - int last_cc; // last cc code (-1 if first packet) - int is_synced; - ts_section_t section; - uint8_t *extradata; - int extradata_alloc, extradata_len; - struct { - uint8_t au_start, au_end, last_au_end; - } sl; -} ES_stream_t; - -typedef struct { - void *sh; - int id; - int type; -} sh_av_t; - -typedef struct MpegTSContext { - int packet_size; // raw packet size, including FEC if present e.g. 188 bytes - ES_stream_t *pids[NB_PID_MAX]; - sh_av_t streams[NB_PID_MAX]; -} MpegTSContext; - - -typedef struct { - demux_stream_t *ds; - demux_packet_t *pack; - int offset, buffer_size; -} av_fifo_t; - -#define MAX_EXTRADATA_SIZE 64*1024 -typedef struct { - int32_t object_type; //aka codec used - int32_t stream_type; //video, audio etc. - uint8_t buf[MAX_EXTRADATA_SIZE]; - uint16_t buf_size; - uint8_t szm1; -} mp4_decoder_config_t; - -typedef struct { - //flags - uint8_t flags; - uint8_t au_start; - uint8_t au_end; - uint8_t random_accesspoint; - uint8_t random_accesspoint_only; - uint8_t padding; - uint8_t use_ts; - uint8_t idle; - uint8_t duration; - - uint32_t ts_resolution, ocr_resolution; - uint8_t ts_len, ocr_len, au_len, instant_bitrate_len, degr_len, au_seqnum_len, packet_seqnum_len; - uint32_t timescale; - uint16_t au_duration, cts_duration; - uint64_t ocr, dts, cts; -} mp4_sl_config_t; - -typedef struct { - uint16_t id; - uint8_t flags; - mp4_decoder_config_t decoder; - mp4_sl_config_t sl; -} mp4_es_descr_t; - -typedef struct { - uint16_t id; - uint8_t flags; - mp4_es_descr_t *es; - uint16_t es_cnt; -} mp4_od_t; - -typedef struct { - uint8_t skip; - uint8_t table_id; - uint8_t ssi; - uint16_t section_length; - uint16_t ts_id; - uint8_t version_number; - uint8_t curr_next; - uint8_t section_number; - uint8_t last_section_number; - struct pat_progs_t { - uint16_t id; - uint16_t pmt_pid; - } *progs; - uint16_t progs_cnt; - ts_section_t section; -} pat_t; - -typedef struct { - uint16_t progid; - uint8_t skip; - uint8_t table_id; - uint8_t ssi; - uint16_t section_length; - uint8_t version_number; - uint8_t curr_next; - uint8_t section_number; - uint8_t last_section_number; - uint16_t PCR_PID; - uint16_t prog_descr_length; - ts_section_t section; - uint16_t es_cnt; - struct pmt_es_t { - uint16_t pid; - uint32_t type; //it's 8 bit long, but cast to the right type as FOURCC - uint16_t descr_length; - uint8_t format_descriptor[5]; - uint8_t lang[4]; - uint16_t mp4_es_id; - } *es; - mp4_od_t iod, *od; - mp4_es_descr_t *mp4es; - int od_cnt, mp4es_cnt; -} pmt_t; - -typedef struct { - uint64_t size; - float duration; - double first_pts; - double last_pts; -} TS_stream_info; - -typedef struct { - MpegTSContext ts; - int last_pid; - av_fifo_t fifo[3]; //0 for audio, 1 for video, 2 for subs - pat_t pat; - pmt_t *pmt; - uint16_t pmt_cnt; - uint32_t prog; - uint32_t vbitrate; - int keep_broken; - int last_aid; - int last_vid; - int last_sid; - char packet[TS_FEC_PACKET_SIZE]; - TS_stream_info vstr, astr; -} ts_priv_t; - - -typedef struct { - es_stream_type_t type; - ts_section_t section; -} TS_pids_t; - - -static int IS_AUDIO(es_stream_type_t type) -{ - switch (type) { - case AUDIO_MP2: - case AUDIO_A52: - case AUDIO_LPCM_BE: - case AUDIO_AAC: - case AUDIO_AAC_LATM: - case AUDIO_DTS: - case AUDIO_TRUEHD: - case AUDIO_S302M: - return 1; - } - return 0; -} - -static int IS_VIDEO(es_stream_type_t type) -{ - switch (type) { - case VIDEO_MPEG1: - case VIDEO_MPEG2: - case VIDEO_MPEG4: - case VIDEO_H264: - case VIDEO_AVC: - case VIDEO_DIRAC: - case VIDEO_VC1: - return 1; - } - return 0; -} - -static int IS_SUB(es_stream_type_t type) -{ - switch (type) { - case SPU_DVD: - case SPU_DVB: - case SPU_PGS: - case SPU_TELETEXT: - return 1; - } - return 0; -} - -static int ts_parse(demuxer_t *demuxer, ES_stream_t *es, unsigned char *packet, int probe); - -static uint8_t get_packet_size(const unsigned char *buf, int size) -{ - int i; - - if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS)) - return 0; - - for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++) - { - if (buf[i * TS_PACKET_SIZE] != 0x47) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]); - goto try_fec; - } - } - return TS_PACKET_SIZE; - -try_fec: - for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++) - { - if (buf[i * TS_FEC_PACKET_SIZE] != 0x47){ - mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]); - goto try_philips; - } - } - return TS_FEC_PACKET_SIZE; - - try_philips: - for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++) - { - if (buf[i * TS_PH_PACKET_SIZE] != 0x47) - return 0; - } - return TS_PH_PACKET_SIZE; -} - -static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h); -static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid); - -static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es) -{ - int i; - ts_priv_t *priv = (ts_priv_t*) demuxer->priv; - - if(priv->ts.streams[es->pid].sh) - return; - - if((IS_AUDIO(es->type) || IS_AUDIO(es->subtype)) && priv->last_aid+1 < MAX_A_STREAMS) - { - sh_audio_t *sh = new_sh_audio_aid(demuxer, priv->last_aid, es->pid); - if(sh) - { - const char *lang = pid_lang_from_pmt(priv, es->pid); - sh->needs_parsing = 1; - sh->format = IS_AUDIO(es->type) ? es->type : es->subtype; - sh->ds = demuxer->audio; - - priv->ts.streams[es->pid].id = priv->last_aid; - priv->ts.streams[es->pid].sh = sh; - priv->ts.streams[es->pid].type = TYPE_AUDIO; - mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED AUDIO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_aid); - if (lang && lang[0]) - mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_AID_%d_LANG=%s\n", es->pid, lang); - priv->last_aid++; - } - - if(es->extradata && es->extradata_len) - { - sh->wf = malloc(sizeof(*sh->wf) + es->extradata_len); - sh->wf->cbSize = es->extradata_len; - memcpy(sh->wf + 1, es->extradata, es->extradata_len); - } - } - - if((IS_VIDEO(es->type) || IS_VIDEO(es->subtype)) && priv->last_vid+1 < MAX_V_STREAMS) - { - sh_video_t *sh = new_sh_video_vid(demuxer, priv->last_vid, es->pid); - if(sh) - { - sh->format = IS_VIDEO(es->type) ? es->type : es->subtype; - sh->ds = demuxer->video; - - priv->ts.streams[es->pid].id = priv->last_vid; - priv->ts.streams[es->pid].sh = sh; - priv->ts.streams[es->pid].type = TYPE_VIDEO; - mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED VIDEO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_vid); - priv->last_vid++; - - - if(sh->format == VIDEO_AVC && es->extradata && es->extradata_len) - { - int w = 0, h = 0; - sh->bih = calloc(1, sizeof(*sh->bih) + es->extradata_len); - sh->bih->biSize= sizeof(*sh->bih) + es->extradata_len; - sh->bih->biCompression = sh->format; - memcpy(sh->bih + 1, es->extradata, es->extradata_len); - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "EXTRADATA(%d BYTES): \n", es->extradata_len); - for(i = 0;i < es->extradata_len; i++) - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "%02x ", (int) es->extradata[i]); - mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\n"); - if(parse_avc_sps(es->extradata, es->extradata_len, &w, &h)) - { - sh->bih->biWidth = w; - sh->bih->biHeight = h; - } - } - } - } - - if(IS_SUB(es->type) && priv->last_sid+1 < MAX_S_STREAMS) - { - sh_sub_t *sh = new_sh_sub_sid_lang(demuxer, priv->last_sid, es->pid, pid_lang_from_pmt(priv, es->pid)); - if (sh) { - switch (es->type) { - case SPU_DVB: - sh->type = 'b'; break; - case SPU_DVD: - sh->type = 'v'; break; - case SPU_PGS: - sh->type = 'p'; break; - } - priv->ts.streams[es->pid].id = priv->last_sid; - priv->ts.streams[es->pid].sh = sh; - priv->ts.streams[es->pid].type = TYPE_SUB; - priv->last_sid++; - } - } -} - -static int ts_check_file(demuxer_t * demuxer) -{ - const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS); - unsigned char buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS], done = 0, *ptr; - uint32_t _read, i, count = 0, is_ts; - int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c, good, bad; - uint8_t size = 0; - off_t pos = 0; - off_t init_pos; - - mp_msg(MSGT_DEMUX, MSGL_V, "Checking for MPEG-TS...\n"); - - init_pos = stream_tell(demuxer->stream); - is_ts = 0; - while(! done) - { - i = 1; - c = 0; - - while(((c=stream_read_char(demuxer->stream)) != 0x47) - && (c >= 0) - && (i < MAX_CHECK_SIZE) - && ! demuxer->stream->eof - ) i++; - - - if(c != 0x47) - { - mp_msg(MSGT_DEMUX, MSGL_V, "THIS DOESN'T LOOK LIKE AN MPEG-TS FILE!\n"); - is_ts = 0; - done = 1; - continue; - } - - pos = stream_tell(demuxer->stream) - 1; - buf[0] = c; - _read = stream_read(demuxer->stream, &buf[1], buf_size-1); - - if(_read < buf_size-1) - { - mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n"); - stream_reset(demuxer->stream); - return 0; - } - - size = get_packet_size(buf, buf_size); - if(size) - { - done = 1; - is_ts = 1; - } - - if(pos - init_pos >= MAX_CHECK_SIZE) - { - done = 1; - is_ts = 0; - } - } - - mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %"PRIu64", FOUND %x, packet_size= %d, SEEMS A TS? %d\n", (uint64_t) pos, c, size, is_ts); - stream_seek(demuxer->stream, pos); - - if(! is_ts) - return 0; - - //LET'S CHECK continuity counters - good = bad = 0; - for(count = 0; count < NB_PID_MAX; count++) - { - cc[count] = last_cc[count] = -1; - } - - for(count = 0; count < NUM_CONSECUTIVE_TS_PACKETS; count++) - { - ptr = &(buf[size * count]); - pid = ((ptr[1] & 0x1f) << 8) | ptr[2]; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "BUF: %02x %02x %02x %02x, PID %d, SIZE: %d \n", - ptr[0], ptr[1], ptr[2], ptr[3], pid, size); - - if((pid == 8191) || (pid < 16)) - continue; - - cc[pid] = (ptr[3] & 0xf); - cc_ok = (last_cc[pid] < 0) || ((((last_cc[pid] + 1) & 0x0f) == cc[pid])); - mp_msg(MSGT_DEMUX, MSGL_DBG2, "PID %d, COMPARE CC %d AND LAST_CC %d\n", pid, cc[pid], last_cc[pid]); - if(! cc_ok) - //return 0; - bad++; - else - good++; - - last_cc[pid] = cc[pid]; - } - - mp_msg(MSGT_DEMUX, MSGL_V, "GOOD CC: %d, BAD CC: %d\n", good, bad); - - if(good >= bad) - return size; - else - return 0; -} - - -static inline int32_t progid_idx_in_pmt(ts_priv_t *priv, uint16_t progid) -{ - int x; - - if(priv->pmt == NULL) - return -1; - - for(x = 0; x < priv->pmt_cnt; x++) - { - if(priv->pmt[x].progid == progid) - return x; - } - - return -1; -} - - -static inline int32_t progid_for_pid(ts_priv_t *priv, int pid, int32_t req) //finds the first program listing a pid -{ - int i, j; - pmt_t *pmt; - - - if(priv->pmt == NULL) - return -1; - - - for(i=0; i < priv->pmt_cnt; i++) - { - pmt = &(priv->pmt[i]); - - if(pmt->es == NULL) - return -1; - - for(j = 0; j < pmt->es_cnt; j++) - { - if(pmt->es[j].pid == pid) - { - if((req == 0) || (req == pmt->progid)) - return pmt->progid; - } - } - - } - return -1; -} - -static inline int32_t prog_pcr_pid(ts_priv_t *priv, int progid) -{ - int i; - - if(priv->pmt == NULL) - return -1; - for(i=0; i < priv->pmt_cnt; i++) - { - if(priv->pmt[i].progid == progid) - return priv->pmt[i].PCR_PID; - } - return -1; -} - - -static inline int pid_match_lang(ts_priv_t *priv, uint16_t pid, char *lang) -{ - uint16_t i, j; - pmt_t *pmt; - - if(priv->pmt == NULL) - return -1; - - for(i=0; i < priv->pmt_cnt; i++) - { - pmt = &(priv->pmt[i]); - - if(pmt->es == NULL) - return -1; - - for(j = 0; j < pmt->es_cnt; j++) - { - if(pmt->es[j].pid != pid) - continue; - - mp_msg(MSGT_DEMUXER, MSGL_V, "CMP LANG %s AND %s, pids: %d %d\n",pmt->es[j].lang, lang, pmt->es[j].pid, pid); - if(strncmp(pmt->es[j].lang, lang, 3) == 0) - { - return 1; - } - } - - } - - return -1; -} - -typedef struct { - int32_t atype, vtype, stype; //types - int32_t apid, vpid, spid; //stream ids - char alang[4]; //languages - uint16_t prog; - off_t probe; -} tsdemux_init_t; - -//second stage: returns the count of A52 syncwords found -static int a52_check(char *buf, int len) -{ - int cnt, frame_length = 0, ok, srate; - - cnt = ok = 0; - if(len < 8) - return 0; - - while(cnt < len - 7) - { - if(buf[cnt] == 0x0B && buf[cnt+1] == 0x77) - { - frame_length = mp_a52_framesize(&buf[cnt], &srate); - if(frame_length>=7 && frame_length<=3840) - { - cnt += frame_length; - ok++; - } - else - cnt++; - } - else - cnt++; - } - - mp_msg(MSGT_DEMUXER, MSGL_V, "A52_CHECK(%d input bytes), found %d frame syncwords of %d bytes length\n", len, ok, frame_length); - return ok; -} - - -static off_t ts_detect_streams(demuxer_t *demuxer, tsdemux_init_t *param) -{ - int video_found = 0, audio_found = 0, i, num_packets = 0, req_apid, req_vpid, req_spid; - int is_audio, is_video, is_sub, has_tables; - int32_t p, chosen_pid = 0; - off_t pos=0, ret = 0, init_pos, end_pos; - ES_stream_t es; - unsigned char tmp[TS_FEC_PACKET_SIZE]; - ts_priv_t *priv = (ts_priv_t*) demuxer->priv; - struct { - char *buf; - int pos; - } pes_priv1[8192], *pptr; - char *tmpbuf; - - priv->last_pid = 8192; //invalid pid - - req_apid = param->apid; - req_vpid = param->vpid; - req_spid = param->spid; - - has_tables = 0; - memset(pes_priv1, 0, sizeof(pes_priv1)); - init_pos = stream_tell(demuxer->stream); - mp_msg(MSGT_DEMUXER, MSGL_V, "PROBING UP TO %"PRIu64", PROG: %d\n", (uint64_t) param->probe, param->prog); - end_pos = init_pos + (param->probe ? param->probe : TS_MAX_PROBE_SIZE); - while(1) - { - pos = stream_tell(demuxer->stream); - if(pos > end_pos || demuxer->stream->eof) - break; - - if(ts_parse(demuxer, &es, tmp, 1)) - { - //Non PES-aligned A52 audio may escape detection if PMT is not present; - //in this case we try to find at least 3 A52 syncwords - if((es.type == PES_PRIVATE1) && (! audio_found) && req_apid > -2) - { - pptr = &pes_priv1[es.pid]; - if(pptr->pos < 64*1024) - { - tmpbuf = realloc(pptr->buf, pptr->pos + es.size); - if(tmpbuf != NULL) - { - pptr->buf = tmpbuf; - memcpy(&(pptr->buf[ pptr->pos ]), es.start, es.size); - pptr->pos += es.size; - if(a52_check(pptr->buf, pptr->pos) > 2) - { - param->atype = AUDIO_A52; - param->apid = es.pid; - es.type = AUDIO_A52; - } - } - } - } - - is_audio = IS_AUDIO(es.type) || ((es.type==SL_PES_STREAM) && IS_AUDIO(es.subtype)); - is_video = IS_VIDEO(es.type) || ((es.type==SL_PES_STREAM) && IS_VIDEO(es.subtype)); - is_sub = IS_SUB(es.type); - - - if((! is_audio) && (! is_video) && (! is_sub)) - continue; - if(is_audio && req_apid==-2) - continue; - - if(is_video) - { - chosen_pid = (req_vpid == es.pid); - if((! chosen_pid) && (req_vpid > 0)) - continue; - } - else if(is_audio) - { - if(req_apid > 0) - { - chosen_pid = (req_apid == es.pid); - if(! chosen_pid) - continue; - } - else if(param->alang[0] > 0 && es.lang[0] > 0) - { - if(pid_match_lang(priv, es.pid, param->alang) == -1) - continue; - - chosen_pid = 1; - param->apid = req_apid = es.pid; - } - } - else if(is_sub) - { - chosen_pid = (req_spid == es.pid); - if((! chosen_pid) && (req_spid > 0)) - continue; - } - - if(req_apid < 0 && (param->alang[0] == 0) && req_vpid < 0 && req_spid < 0) - chosen_pid = 1; - - if((ret == 0) && chosen_pid) - { - ret = stream_tell(demuxer->stream); - } - - p = progid_for_pid(priv, es.pid, param->prog); - if(p != -1) - { - has_tables++; - if(!param->prog && chosen_pid) - param->prog = p; - } - - if((param->prog > 0) && (param->prog != p)) - { - if(audio_found) - { - if(is_video && (req_vpid == es.pid)) - { - param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype; - param->vpid = es.pid; - video_found = 1; - break; - } - } - - if(video_found) - { - if(is_audio && (req_apid == es.pid)) - { - param->atype = IS_AUDIO(es.type) ? es.type : es.subtype; - param->apid = es.pid; - audio_found = 1; - break; - } - } - - - continue; - } - - - mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, param->prog); - - - if(is_video) - { - if((req_vpid == -1) || (req_vpid == es.pid)) - { - param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype; - param->vpid = es.pid; - video_found = 1; - } - } - - - if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found && !param->probe) - { - //novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only) - param->vtype = 0; - break; - } - - if(is_sub) - { - if((req_spid == -1) || (req_spid == es.pid)) - { - param->stype = es.type; - param->spid = es.pid; - } - } - - if(is_audio) - { - if((req_apid == -1) || (req_apid == es.pid)) - { - param->atype = IS_AUDIO(es.type) ? es.type : es.subtype; - param->apid = es.pid; - audio_found = 1; - } - } - - if(audio_found && (param->apid == es.pid) && (! video_found)) - num_packets++; - - if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000)) - break; - } - } - - for(i=0; i<8192; i++) - { - if(pes_priv1[i].buf != NULL) - { - free(pes_priv1[i].buf); - pes_priv1[i].buf = NULL; - pes_priv1[i].pos = 0; - } - } - - if(video_found) - { - if(param->vtype == VIDEO_MPEG1) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG1(pid=%d) ", param->vpid); - else if(param->vtype == VIDEO_MPEG2) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2(pid=%d) ", param->vpid); - else if(param->vtype == VIDEO_MPEG4) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG4(pid=%d) ", param->vpid); - else if(param->vtype == VIDEO_H264) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO H264(pid=%d) ", param->vpid); - else if(param->vtype == VIDEO_VC1) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO VC1(pid=%d) ", param->vpid); - else if(param->vtype == VIDEO_AVC) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO AVC(NAL-H264, pid=%d) ", param->vpid); - } - else - { - param->vtype = UNKNOWN; - //WE DIDN'T MATCH ANY VIDEO STREAM - mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! "); - } - - if(param->atype == AUDIO_MP2) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MPA(pid=%d)", param->apid); - else if(param->atype == AUDIO_A52) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", param->apid); - else if(param->atype == AUDIO_DTS) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO DTS(pid=%d)", param->apid); - else if(param->atype == AUDIO_LPCM_BE) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)", param->apid); - else if(param->atype == AUDIO_AAC) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC(pid=%d)", param->apid); - else if(param->atype == AUDIO_AAC_LATM) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC LATM(pid=%d)", param->apid); - else if(param->atype == AUDIO_TRUEHD) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO TRUEHD(pid=%d)", param->apid); - else if(param->atype == AUDIO_S302M) - mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO S302M(pid=%d)", param->apid); - else - { - audio_found = 0; - param->atype = UNKNOWN; - //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO - mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO! (try increasing -tsprobe)"); - } - - if(IS_SUB(param->stype)) - mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB %s(pid=%d) ", (param->stype==SPU_DVD ? "DVD" : param->stype==SPU_DVB ? "DVB" : "Teletext"), param->spid); - else - { - param->stype = UNKNOWN; - mp_msg(MSGT_DEMUXER, MSGL_INFO, " NO SUBS (yet)! "); - } - - if(video_found || audio_found) - { - if(!param->prog) - { - p = progid_for_pid(priv, video_found ? param->vpid : param->apid, 0); - if(p != -1) - param->prog = p; - } - - if(demuxer->stream->eof && (ret == 0)) - ret = init_pos; - mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", param->prog); - } - else - mp_msg(MSGT_DEMUXER, MSGL_INFO, "\n"); - - - for(i=0; i<NB_PID_MAX; i++) - { - if(priv->ts.pids[i] != NULL) - { - priv->ts.pids[i]->payload_size = 0; - priv->ts.pids[i]->pts = priv->ts.pids[i]->last_pts = 0; - priv->ts.pids[i]->last_cc = -1; - priv->ts.pids[i]->is_synced = 0; - } - } - - return ret; -} - -static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h) -{ - int sps, sps_len; - unsigned char *ptr; - mp_mpeg_header_t picture; - if(len < 6) - return 0; - sps = buf[5] & 0x1f; - if(!sps) - return 0; - sps_len = (buf[6] << 8) | buf[7]; - if(!sps_len || (sps_len > len - 8)) - return 0; - ptr = &(buf[8]); - picture.display_picture_width = picture.display_picture_height = 0; - h264_parse_sps(&picture, ptr, len - 8); - if(!picture.display_picture_width || !picture.display_picture_height) - return 0; - *w = picture.display_picture_width; - *h = picture.display_picture_height; - return 1; -} - -static demuxer_t *demux_open_ts(demuxer_t * demuxer) -{ - int i; - uint8_t packet_size; - sh_video_t *sh_video; - sh_audio_t *sh_audio; - off_t start_pos; - tsdemux_init_t params; - ts_priv_t * priv = demuxer->priv; - - mp_msg(MSGT_DEMUX, MSGL_V, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n", - demuxer->audio->id, demuxer->video->id, demuxer->sub->id); - - - demuxer->type= DEMUXER_TYPE_MPEG_TS; - - - stream_reset(demuxer->stream); - - packet_size = ts_check_file(demuxer); - if(!packet_size) - return NULL; - - priv = calloc(1, sizeof(ts_priv_t)); - if(priv == NULL) - { - mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate enough memory for ts->priv, exit\n"); - return NULL; - } - - for(i=0; i < NB_PID_MAX; i++) - { - priv->ts.pids[i] = NULL; - priv->ts.streams[i].id = -3; - } - priv->pat.progs = NULL; - priv->pat.progs_cnt = 0; - priv->pat.section.buffer = NULL; - priv->pat.section.buffer_len = 0; - - priv->pmt = NULL; - priv->pmt_cnt = 0; - - priv->keep_broken = ts_keep_broken; - priv->ts.packet_size = packet_size; - - - demuxer->priv = priv; - if(demuxer->stream->type != STREAMTYPE_FILE) - demuxer->seekable = 1; - else - demuxer->seekable = 1; - - - params.atype = params.vtype = params.stype = UNKNOWN; - params.apid = demuxer->audio->id; - params.vpid = demuxer->video->id; - params.spid = demuxer->sub->id; - params.prog = ts_prog; - params.probe = ts_probe; - - if(demuxer->opts->audio_lang != NULL) - { - strncpy(params.alang, demuxer->opts->audio_lang[0], 3); - params.alang[3] = 0; - } - else - memset(params.alang, 0, 4); - - start_pos = ts_detect_streams(demuxer, ¶ms); - - demuxer->sub->id = params.spid; - priv->prog = params.prog; - - if(params.vtype != UNKNOWN) - { - ts_add_stream(demuxer, priv->ts.pids[params.vpid]); - sh_video = priv->ts.streams[params.vpid].sh; - demuxer->video->id = priv->ts.streams[params.vpid].id; - sh_video->ds = demuxer->video; - sh_video->format = params.vtype; - demuxer->video->sh = sh_video; - } - - if(params.atype != UNKNOWN) - { - ES_stream_t *es = priv->ts.pids[params.apid]; - - if(!IS_AUDIO(es->type) && !IS_AUDIO(es->subtype) && IS_AUDIO(params.atype)) es->subtype = params.atype; - ts_add_stream(demuxer, priv->ts.pids[params.apid]); - sh_audio = priv->ts.streams[params.apid].sh; - demuxer->audio->id = priv->ts.streams[params.apid].id; - sh_audio->ds = demuxer->audio; - sh_audio->format = params.atype; - demuxer->audio->sh = sh_audio; - } - - - mp_msg(MSGT_DEMUXER,MSGL_V, "Opened TS demuxer, audio: %x(pid %d), video: %x(pid %d)...POS=%"PRIu64", PROBE=%"PRIu64"\n", params.atype, demuxer->audio->id, params.vtype, demuxer->video->id, (uint64_t) start_pos, ts_probe); - - - start_pos = start_pos <= priv->ts.packet_size ? - demuxer->stream->start_pos : - start_pos - priv->ts.packet_size; - demuxer->movi_start = start_pos; - demuxer->reference_clock = MP_NOPTS_VALUE; - stream_reset(demuxer->stream); - stream_seek(demuxer->stream, start_pos); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES? - - - priv->last_pid = 8192; //invalid pid - - for(i = 0; i < 3; i++) - { - priv->fifo[i].pack = NULL; - priv->fifo[i].offset = 0; - } - priv->fifo[0].ds = demuxer->audio; - priv->fifo[1].ds = demuxer->video; - priv->fifo[2].ds = demuxer->sub; - - priv->fifo[0].buffer_size = 1536; - priv->fifo[1].buffer_size = 32767; - priv->fifo[2].buffer_size = 32767; - - priv->pat.section.buffer_len = 0; - for(i = 0; i < priv->pmt_cnt; i++) - priv->pmt[i].section.buffer_len = 0; - - demuxer->filepos = stream_tell(demuxer->stream); - return demuxer; -} - -static void demux_close_ts(demuxer_t * demuxer) -{ - uint16_t i; - ts_priv_t *priv = (ts_priv_t*) demuxer->priv; - - if(priv) - { - free(priv->pat.section.buffer); - free(priv->pat.progs); - - if(priv->pmt) - { - for(i = 0; i < priv->pmt_cnt; i++) - { - free(priv->pmt[i].section.buffer); - free(priv->pmt[i].es); - } - free(priv->pmt); - } - for (i = 0; i < NB_PID_MAX; i++) - { - free(priv->ts.pids[i]); - priv->ts.pids[i] = NULL; - } - for (i = 0; i < 3; i++) - { - if (priv->fifo[i].pack) - free_demux_packet(priv->fifo[i].pack); - priv->fifo[i].pack = NULL; - } - free(priv); - } - demuxer->priv=NULL; -} - - -#define getbits mp_getbits - -static int mp4_parse_sl_packet(pmt_t *pmt, uint8_t *buf, uint16_t packet_len, int pid, ES_stream_t *pes_es) -{ - int i, n, m, mp4_es_id = -1; - uint64_t v = 0; - uint32_t pl_size = 0; - int deg_flag = 0; - mp4_es_descr_t *es = NULL; - mp4_sl_config_t *sl = NULL; - uint8_t au_start = 0, au_end = 0, rap_flag = 0, ocr_flag = 0, padding = 0, padding_bits = 0, idle = 0; - - pes_es->is_synced = 0; - mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, pid: %d, pmt: %pm, packet_len: %d\n", pid, pmt, packet_len); - if(! pmt || !packet_len) - return 0; - - for(i = 0; i < pmt->es_cnt; i++) - { - if(pmt->es[i].pid == pid) - mp4_es_id = pmt->es[i].mp4_es_id; - } - if(mp4_es_id < 0) - return -1; - - for(i = 0; i < pmt->mp4es_cnt; i++) - { - if(pmt->mp4es[i].id == mp4_es_id) - es = &(pmt->mp4es[i]); - } - if(! es) - return -1; - - pes_es->subtype = es->decoder.object_type; - - sl = &(es->sl); - if(!sl) - return -1; - - //now es is the complete es_descriptor of out mp4 ES stream - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "ID: %d, FLAGS: 0x%x, subtype: %x\n", es->id, sl->flags, pes_es->subtype); - - n = 0; - if(sl->au_start) - pes_es->sl.au_start = au_start = getbits(buf, n++, 1); - else - pes_es->sl.au_start = (pes_es->sl.last_au_end ? 1 : 0); - if(sl->au_end) - pes_es->sl.au_end = au_end = getbits(buf, n++, 1); - - if(!sl->au_start && !sl->au_end) - { - pes_es->sl.au_start = pes_es->sl.au_end = au_start = au_end = 1; - } - pes_es->sl.last_au_end = pes_es->sl.au_end; - - - if(sl->ocr_len > 0) - ocr_flag = getbits(buf, n++, 1); - if(sl->idle) - idle = getbits(buf, n++, 1); - if(sl->padding) - padding = getbits(buf, n++, 1); - if(padding) - { - padding_bits = getbits(buf, n, 3); - n += 3; - } - - if(idle || (padding && !padding_bits)) - { - pes_es->payload_size = 0; - return -1; - } - - //(! idle && (!padding || padding_bits != 0)) is true - n += sl->packet_seqnum_len; - if(sl->degr_len) - deg_flag = getbits(buf, n++, 1); - if(deg_flag) - n += sl->degr_len; - - if(ocr_flag) - { - n += sl->ocr_len; - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "OCR: %d bits\n", sl->ocr_len); - } - - if(packet_len * 8 <= n) - return -1; - - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "\nAU_START: %d, AU_END: %d\n", au_start, au_end); - if(au_start) - { - int dts_flag = 0, cts_flag = 0, ib_flag = 0; - - if(sl->random_accesspoint) - rap_flag = getbits(buf, n++, 1); - - //check commented because it seems it's rarely used, and we need this flag set in case of au_start - //the decoder will eventually discard the payload if it can't decode it - //if(rap_flag || sl->random_accesspoint_only) - pes_es->is_synced = 1; - - n += sl->au_seqnum_len; - if(packet_len * 8 <= n+8) - return -1; - if(sl->use_ts) - { - dts_flag = getbits(buf, n++, 1); - cts_flag = getbits(buf, n++, 1); - } - if(sl->instant_bitrate_len) - ib_flag = getbits(buf, n++, 1); - if(packet_len * 8 <= n+8) - return -1; - if(dts_flag && (sl->ts_len > 0)) - { - n += sl->ts_len; - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "DTS: %d bits\n", sl->ts_len); - } - if(packet_len * 8 <= n+8) - return -1; - if(cts_flag && (sl->ts_len > 0)) - { - int i = 0, m; - - while(i < sl->ts_len) - { - m = FFMIN(8, sl->ts_len - i); - v |= getbits(buf, n, m); - if(sl->ts_len - i > 8) - v <<= 8; - i += m; - n += m; - if(packet_len * 8 <= n+8) - return -1; - } - - pes_es->pts = (double) v / (double) sl->ts_resolution; - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "CTS: %d bits, value: %"PRIu64"/%d = %.3f\n", sl->ts_len, v, sl->ts_resolution, pes_es->pts); - } - - - i = 0; - pl_size = 0; - while(i < sl->au_len) - { - m = FFMIN(8, sl->au_len - i); - pl_size |= getbits(buf, n, m); - if(sl->au_len - i > 8) - pl_size <<= 8; - i += m; - n += m; - if(packet_len * 8 <= n+8) - return -1; - } - mp_msg(MSGT_DEMUXER,MSGL_DBG2, "AU_LEN: %u (%d bits)\n", pl_size, sl->au_len); - if(ib_flag) - n += sl->instant_bitrate_len; - } - - m = (n+7)/8; - if(0 < pl_size && pl_size < pes_es->payload_size) - pes_es->payload_size = pl_size; - - mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, n=%d, m=%d, size from pes hdr: %u, sl hdr size: %u, RAP FLAGS: %d/%d\n", - n, m, pes_es->payload_size, pl_size, (int) rap_flag, (int) sl->random_accesspoint_only); - - return m; -} - -//this function parses the extension fields in the PES header and returns the substream_id, or -1 in case of errors -static int parse_pes_extension_fields(unsigned char *p, int pkt_len) -{ - int skip; - unsigned char flags; - - if(!(p[7] & 0x1)) //no extension_field - return -1; - skip = 9; - if(p[7] & 0x80) - { - skip += 5; - if(p[7] & 0x40) - skip += 5; - } - if(p[7] & 0x20) //escr_flag - skip += 6; - if(p[7] & 0x10) //es_rate_flag - skip += 3; - if(p[7] & 0x08)//dsm_trick_mode is unsupported, skip - { - skip = 0;//don't let's parse the extension fields - } - if(p[7] & 0x04) //additional_copy_info - skip += 1; - if(p[7] & 0x02) //pes_crc_flag - skip += 2; - if(skip >= pkt_len) //too few bytes - return -1; - flags = p[skip]; - skip++; - if(flags & 0x80) //pes_private_data_flag - skip += 16; - if(skip >= pkt_len) - return -1; - if(flags & 0x40) //pack_header_field_flag - { - unsigned char l = p[skip]; - skip += l; - } - if(flags & 0x20) //program_packet_sequence_counter - skip += 2; - if(flags & 0x10) //p_std - skip += 2; - if(skip >= pkt_len) - return -1; - if(flags & 0x01) //finally the long desired pes_extension2 - { - unsigned char l = p[skip]; //ext2 flag+len - skip++; - if((l == 0x81) && (skip < pkt_len)) - { - int ssid = p[skip]; - mp_msg(MSGT_IDENTIFY, MSGL_V, "SUBSTREAM_ID=%d (0x%02X)\n", ssid, ssid); - return ssid; - } - } - - return -1; -} - -static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es, int32_t type_from_pmt, pmt_t *pmt, int pid) -{ - unsigned char *p; - uint32_t header_len; - int64_t pts; - uint32_t stream_id; - uint32_t pkt_len, pes_is_aligned; - - //Here we are always at the start of a PES packet - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%p, %d): \n", buf, (uint32_t) packet_len); - - if(packet_len == 0 || packet_len > 184) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2, BUFFER LEN IS TOO SMALL OR TOO BIG: %d EXIT\n", packet_len); - return 0; - } - - p = buf; - pkt_len = packet_len; - - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: HEADER %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]); - if (p[0] || p[1] || (p[2] != 1)) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: error HEADER %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]); - return 0 ; - } - - packet_len -= 6; - if(packet_len==0) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: packet too short: %d, exit\n", packet_len); - return 0; - } - - es->payload_size = (p[4] << 8 | p[5]); - pes_is_aligned = (p[6] & 4); - - stream_id = p[3]; - - - if (p[7] & 0x80) - { /* pts available */ - pts = (int64_t)(p[9] & 0x0E) << 29 ; - pts |= p[10] << 22 ; - pts |= (p[11] & 0xFE) << 14 ; - pts |= p[12] << 7 ; - pts |= (p[13] & 0xFE) >> 1 ; - - es->pts = pts / 90000.0; - } - else - es->pts = 0.0; - - - header_len = p[8]; - - - if (header_len + 9 > pkt_len) //9 are the bytes read up to the header_length field - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len); - return 0; - } - - if(stream_id==0xfd) - { - int ssid = parse_pes_extension_fields(p, pkt_len); - if((audio_substream_id!=-1) && (ssid != audio_substream_id)) - return 0; - if(ssid == 0x72 && type_from_pmt != AUDIO_DTS && type_from_pmt != SPU_PGS) - es->type = type_from_pmt = AUDIO_TRUEHD; - } - - p += header_len + 9; - packet_len -= header_len + 3; - - if(es->payload_size) - es->payload_size -= header_len + 3; - - - es->is_synced = 1; //only for SL streams we have to make sure it's really true, see below - if (stream_id == 0xbd) - { - mp_msg(MSGT_DEMUX, MSGL_DBG3, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X, 80: %d\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0] & 0x80); - - - /* - * we check the descriptor tag first because some stations - * do not include any of the A52 header info in their audio tracks - * these "raw" streams may begin with a byte that looks like a stream type. - */ - - - if(type_from_pmt == SPU_PGS) - { - es->start = p; - es->size = packet_len; - es->type = SPU_PGS; - es->payload_size -= packet_len; - return 1; - } - if( - (type_from_pmt == AUDIO_A52) || /* A52 - raw */ - (packet_len >= 2 && p[0] == 0x0B && p[1] == 0x77) /* A52 - syncword */ - ) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 RAW OR SYNCWORD\n"); - es->start = p; - es->size = packet_len; - es->type = AUDIO_A52; - es->payload_size -= packet_len; - - return 1; - } - /* SPU SUBS */ - else if(type_from_pmt == SPU_DVB || - (packet_len >= 2 && (p[0] == 0x20) && pes_is_aligned)) // && p[1] == 0x00)) - { - // offset/length fiddling to make decoding with lavc possible - es->start = p + 2; - es->size = packet_len - 2; - es->type = SPU_DVB; - es->payload_size -= packet_len; - - return 1; - } - else if (pes_is_aligned && packet_len >= 1 && ((p[0] & 0xE0) == 0x20)) //SPU_DVD - { - //DVD SUBS - es->start = p+1; - es->size = packet_len-1; - es->type = SPU_DVD; - es->payload_size -= packet_len; - - return 1; - } - else if (pes_is_aligned && packet_len >= 4 && (p[0] & 0xF8) == 0x80) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 WITH HEADER\n"); - es->start = p+4; - es->size = packet_len - 4; - es->type = AUDIO_A52; - es->payload_size -= packet_len; - - return 1; - } - else if (pes_is_aligned && packet_len >= 1 && ((p[0]&0xf0) == 0xa0)) - { - int pcm_offset; - - for (pcm_offset=0; ++pcm_offset < packet_len-1 ; ) - { - if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80) - { /* START */ - pcm_offset += 2; - break; - } - } - - es->start = p + pcm_offset; - es->size = packet_len - pcm_offset; - es->type = AUDIO_LPCM_BE; - es->payload_size -= packet_len; - - return 1; - } - else - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "PES_PRIVATE1\n"); - es->start = p; - es->size = packet_len; - es->type = (type_from_pmt == UNKNOWN ? PES_PRIVATE1 : type_from_pmt); - es->payload_size -= packet_len; - - return 1; - } - } - else if((stream_id >= 0xe0 && stream_id <= 0xef) || (stream_id == 0xfd && type_from_pmt != UNKNOWN)) - { - es->start = p; - es->size = packet_len; - if(type_from_pmt != UNKNOWN) - es->type = type_from_pmt; - else - es->type = VIDEO_MPEG2; - if(es->payload_size) - es->payload_size -= packet_len; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: M2V size %d\n", es->size); - return 1; - } - else if (stream_id == 0xfa) - { - int l; - - es->is_synced = 0; - if(type_from_pmt != UNKNOWN) //MP4 A/V or SL - { - es->start = p; - es->size = packet_len; - es->type = type_from_pmt; - - if(type_from_pmt == SL_PES_STREAM) - { - //if(pes_is_aligned) - //{ - l = mp4_parse_sl_packet(pmt, p, packet_len, pid, es); - mp_msg(MSGT_DEMUX, MSGL_DBG2, "L=%d, TYPE=%x\n", l, type_from_pmt); - if(l < 0) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: couldn't parse SL header, passing along full PES payload\n"); - l = 0; - } - //} - - es->start += l; - es->size -= l; - } - - if(es->payload_size) - es->payload_size -= packet_len; - return 1; - } - } - else if ((stream_id & 0xe0) == 0xc0) - { - es->start = p; - es->size = packet_len; - - if(type_from_pmt != UNKNOWN) - es->type = type_from_pmt; - else - es->type = AUDIO_MP2; - - es->payload_size -= packet_len; - - return 1; - } - else if (type_from_pmt != -1) //as a last resort here we trust the PMT, if present - { - es->start = p; - es->size = packet_len; - es->type = type_from_pmt; - es->payload_size -= packet_len; - - return 1; - } - else - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id); - } - - es->is_synced = 0; - return 0; -} - - - - -static int ts_sync(stream_t *stream) -{ - mp_msg(MSGT_DEMUX, MSGL_DBG3, "TS_SYNC \n"); - - while (!stream->eof) - if (stream_read_char(stream) == 0x47) - return 1; - - return 0; -} - - -static void ts_dump_streams(ts_priv_t *priv) -{ - int i; - - for(i = 0; i < 3; i++) - { - if((priv->fifo[i].pack != NULL) && (priv->fifo[i].offset != 0)) - { - resize_demux_packet(priv->fifo[i].pack, priv->fifo[i].offset); - ds_add_packet(priv->fifo[i].ds, priv->fifo[i].pack); - priv->fifo[i].offset = 0; - priv->fifo[i].pack = NULL; - } - } -} - - -static inline int32_t prog_idx_in_pat(ts_priv_t *priv, uint16_t progid) -{ - int x; - - if(priv->pat.progs == NULL) - return -1; - - for(x = 0; x < priv->pat.progs_cnt; x++) - { - if(priv->pat.progs[x].id == progid) - return x; - } - - return -1; -} - - -static inline int32_t prog_id_in_pat(ts_priv_t *priv, uint16_t pid) -{ - int x; - - if(priv->pat.progs == NULL) - return -1; - - for(x = 0; x < priv->pat.progs_cnt; x++) - { - if(priv->pat.progs[x].pmt_pid == pid) - return priv->pat.progs[x].id; - } - - return -1; -} - -static int collect_section(ts_section_t *section, int is_start, unsigned char *buff, int size) -{ - uint8_t *ptr; - uint16_t tlen; - int skip, tid; - - mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, start: %d, size: %d, collected: %d\n", is_start, size, section->buffer_len); - if(! is_start && !section->buffer_len) - return 0; - - if(is_start) - { - if(! section->buffer) - { - section->buffer = malloc(4096 + 256); - if(section->buffer == NULL) - return 0; - } - section->buffer_len = 0; - } - - if(size + section->buffer_len > 4096+256) - { - mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, excessive len: %d + %d\n", section->buffer_len, size); - return 0; - } - - memcpy(&(section->buffer[section->buffer_len]), buff, size); - section->buffer_len += size; - - if(section->buffer_len < 3) - return 0; - - skip = section->buffer[0]; - if(skip + 4 > section->buffer_len) - return 0; - - ptr = &(section->buffer[skip + 1]); - tid = ptr[0]; - tlen = ((ptr[1] & 0x0f) << 8) | ptr[2]; - mp_msg(MSGT_DEMUX, MSGL_V, "SKIP: %d+1, TID: %d, TLEN: %d, COLLECTED: %d\n", skip, tid, tlen, section->buffer_len); - if(section->buffer_len < (skip+1+3+tlen)) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "DATA IS NOT ENOUGH, NEXT TIME\n"); - return 0; - } - - return skip+1; -} - -static int parse_pat(ts_priv_t * priv, int is_start, unsigned char *buff, int size) -{ - int skip; - unsigned char *ptr; - unsigned char *base; - int entries, i; - uint16_t progid; - struct pat_progs_t *tmp; - ts_section_t *section; - - section = &(priv->pat.section); - skip = collect_section(section, is_start, buff, size); - if(! skip) - return 0; - - ptr = &(section->buffer[skip]); - //PARSING - priv->pat.table_id = ptr[0]; - if(priv->pat.table_id != 0) - return 0; - priv->pat.ssi = (ptr[1] >> 7) & 0x1; - priv->pat.curr_next = ptr[5] & 0x01; - priv->pat.ts_id = (ptr[3] << 8 ) | ptr[4]; - priv->pat.version_number = (ptr[5] >> 1) & 0x1F; - priv->pat.section_length = ((ptr[1] & 0x03) << 8 ) | ptr[2]; - priv->pat.section_number = ptr[6]; - priv->pat.last_section_number = ptr[7]; - - //check_crc32(0xFFFFFFFFL, ptr, priv->pat.buffer_len - 4, &ptr[priv->pat.buffer_len - 4]); - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PAT: section_len: %d, section %d/%d\n", priv->pat.section_length, priv->pat.section_number, priv->pat.last_section_number); - - entries = (int) (priv->pat.section_length - 9) / 4; //entries per section - - for(i=0; i < entries; i++) - { - int32_t idx; - base = &ptr[8 + i*4]; - progid = (base[0] << 8) | base[1]; - - if((idx = prog_idx_in_pat(priv, progid)) == -1) - { - int sz = sizeof(struct pat_progs_t) * (priv->pat.progs_cnt+1); - tmp = realloc_struct(priv->pat.progs, priv->pat.progs_cnt+1, sizeof(struct pat_progs_t)); - if(tmp == NULL) - { - mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PAT: COULDN'T REALLOC %d bytes, NEXT\n", sz); - break; - } - priv->pat.progs = tmp; - idx = priv->pat.progs_cnt; - priv->pat.progs_cnt++; - } - - priv->pat.progs[idx].id = progid; - priv->pat.progs[idx].pmt_pid = ((base[2] & 0x1F) << 8) | base[3]; - mp_msg(MSGT_DEMUX, MSGL_V, "PROG: %d (%d-th of %d), PMT: %d\n", priv->pat.progs[idx].id, i+1, entries, priv->pat.progs[idx].pmt_pid); - mp_msg(MSGT_IDENTIFY, MSGL_V, "PROGRAM_ID=%d (0x%02X), PMT_PID: %d(0x%02X)\n", - progid, progid, priv->pat.progs[idx].pmt_pid, priv->pat.progs[idx].pmt_pid); - } - - return 1; -} - - -static inline int32_t es_pid_in_pmt(pmt_t * pmt, uint16_t pid) -{ - uint16_t i; - - if(pmt == NULL) - return -1; - - if(pmt->es == NULL) - return -1; - - for(i = 0; i < pmt->es_cnt; i++) - { - if(pmt->es[i].pid == pid) - return (int32_t) i; - } - - return -1; -} - - -static uint16_t get_mp4_desc_len(uint8_t *buf, int *len) -{ - //uint16_t i = 0, size = 0; - int i = 0, j, size = 0; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "PARSE_MP4_DESC_LEN(%d), bytes: ", *len); - j = FFMIN(*len, 4); - while(i < j) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, " %x ", buf[i]); - size |= (buf[i] & 0x7f); - if(!(buf[i] & 0x80)) - break; - size <<= 7; - i++; - } - mp_msg(MSGT_DEMUX, MSGL_DBG2, ", SIZE=%d\n", size); - - *len = i+1; - return size; -} - - -static uint16_t parse_mp4_slconfig_descriptor(uint8_t *buf, int len, void *elem) -{ - int i = 0; - mp4_es_descr_t *es; - mp4_sl_config_t *sl; - - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_SLCONFIG_DESCRIPTOR(%d)\n", len); - es = (mp4_es_descr_t *) elem; - if(!es) - { - mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); - return len; - } - sl = &(es->sl); - - sl->ts_len = sl->ocr_len = sl->au_len = sl->instant_bitrate_len = sl->degr_len = sl->au_seqnum_len = sl->packet_seqnum_len = 0; - sl->ocr = sl->dts = sl->cts = 0; - - if(buf[0] == 0) - { - i++; - sl->flags = buf[i]; - i++; - sl->ts_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; - i += 4; - sl->ocr_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; - i += 4; - sl->ts_len = buf[i]; - i++; - sl->ocr_len = buf[i]; - i++; - sl->au_len = buf[i]; - i++; - sl->instant_bitrate_len = buf[i]; - i++; - sl->degr_len = (buf[i] >> 4) & 0x0f; - sl->au_seqnum_len = ((buf[i] & 0x0f) << 1) | ((buf[i+1] >> 7) & 0x01); - i++; - sl->packet_seqnum_len = ((buf[i] >> 2) & 0x1f); - i++; - - } - else if(buf[0] == 1) - { - sl->flags = 0; - sl->ts_resolution = 1000; - sl->ts_len = 32; - i++; - } - else if(buf[0] == 2) - { - sl->flags = 4; - i++; - } - else - { - sl->flags = 0; - i++; - } - - sl->au_start = (sl->flags >> 7) & 0x1; - sl->au_end = (sl->flags >> 6) & 0x1; - sl->random_accesspoint = (sl->flags >> 5) & 0x1; - sl->random_accesspoint_only = (sl->flags >> 4) & 0x1; - sl->padding = (sl->flags >> 3) & 0x1; - sl->use_ts = (sl->flags >> 2) & 0x1; - sl->idle = (sl->flags >> 1) & 0x1; - sl->duration = sl->flags & 0x1; - - if(sl->duration) - { - sl->timescale = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3]; - i += 4; - sl->au_duration = (buf[i] << 8) | buf[i+1]; - i += 2; - sl->cts_duration = (buf[i] << 8) | buf[i+1]; - i += 2; - } - else //no support for fixed durations atm - sl->timescale = sl->au_duration = sl->cts_duration = 0; - - mp_msg(MSGT_DEMUX, MSGL_V, "MP4SLCONFIG(len=0x%x), predef: %d, flags: %x, use_ts: %d, tslen: %d, timescale: %d, dts: %"PRIu64", cts: %"PRIu64"\n", - len, buf[0], sl->flags, sl->use_ts, sl->ts_len, sl->timescale, (uint64_t) sl->dts, (uint64_t) sl->cts); - - return len; -} - -static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem); - -static uint16_t parse_mp4_decoder_config_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem) -{ - int i = 0, j; - mp4_es_descr_t *es; - mp4_decoder_config_t *dec; - - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_CONFIG_DESCRIPTOR(%d)\n", len); - es = (mp4_es_descr_t *) elem; - if(!es) - { - mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); - return len; - } - dec = (mp4_decoder_config_t*) &(es->decoder); - - dec->object_type = buf[i]; - dec->stream_type = (buf[i+1]>>2) & 0x3f; - - if(dec->object_type == 1 && dec->stream_type == 1) - { - dec->object_type = MP4_OD; - dec->stream_type = MP4_OD; - } - else if(dec->stream_type == 4) - { - if(dec->object_type == 0x6a) - dec->object_type = VIDEO_MPEG1; - if(dec->object_type >= 0x60 && dec->object_type <= 0x65) - dec->object_type = VIDEO_MPEG2; - else if(dec->object_type == 0x20) - dec->object_type = VIDEO_MPEG4; - else if(dec->object_type == 0x21) - dec->object_type = VIDEO_AVC; - /*else if(dec->object_type == 0x22) - fprintf(stderr, "TYPE 0x22\n");*/ - else dec->object_type = UNKNOWN; - } - else if(dec->stream_type == 5) - { - if(dec->object_type == 0x40) - dec->object_type = AUDIO_AAC; - else if(dec->object_type == 0x6b) - dec->object_type = AUDIO_MP2; - else if(dec->object_type >= 0x66 && dec->object_type <= 0x69) - dec->object_type = AUDIO_MP2; - else - dec->object_type = UNKNOWN; - } - else - dec->object_type = dec->stream_type = UNKNOWN; - - if(dec->object_type != UNKNOWN) - { - //update the type of the current stream - for(j = 0; j < pmt->es_cnt; j++) - { - if(pmt->es[j].mp4_es_id == es->id) - { - pmt->es[j].type = SL_PES_STREAM; - } - } - } - - if(len > 13) - parse_mp4_descriptors(pmt, &buf[13], len-13, dec); - - mp_msg(MSGT_DEMUX, MSGL_V, "MP4DECODER(0x%x), object_type: 0x%x, stream_type: 0x%x\n", len, dec->object_type, dec->stream_type); - - return len; -} - -static uint16_t parse_mp4_decoder_specific_descriptor(uint8_t *buf, int len, void *elem) -{ - int i; - mp4_decoder_config_t *dec; - - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_SPECIFIC_DESCRIPTOR(%d)\n", len); - dec = (mp4_decoder_config_t *) elem; - if(!dec) - { - mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n"); - return len; - } - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4 SPECIFIC INFO BYTES: \n"); - for(i=0; i<len; i++) - mp_msg(MSGT_DEMUX, MSGL_DBG2, "%02x ", buf[i]); - mp_msg(MSGT_DEMUX, MSGL_DBG2, "\n"); - - if(len > MAX_EXTRADATA_SIZE) - { - mp_msg(MSGT_DEMUX, MSGL_ERR, "DEMUX_TS, EXTRADATA SUSPICIOUSLY BIG: %d, REFUSED\r\n", len); - return len; - } - memcpy(dec->buf, buf, len); - dec->buf_size = len; - - return len; -} - -static uint16_t parse_mp4_es_descriptor(pmt_t *pmt, uint8_t *buf, int len) -{ - int i = 0, j = 0, k, found; - uint8_t flag; - mp4_es_descr_t es, *target_es = NULL, *tmp; - - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES: len=%d\n", len); - memset(&es, 0, sizeof(mp4_es_descr_t)); - while(i < len) - { - es.id = (buf[i] << 8) | buf[i+1]; - mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_ID: %d\n", es.id); - i += 2; - flag = buf[i]; - i++; - if(flag & 0x80) - i += 2; - if(flag & 0x40) - i += buf[i]+1; - if(flag & 0x20) //OCR, maybe we need it - i += 2; - - j = parse_mp4_descriptors(pmt, &buf[i], len-i, &es); - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES, types after parse_mp4_descriptors: 0x%x, 0x%x\n", es.decoder.object_type, es.decoder.stream_type); - if(es.decoder.object_type != UNKNOWN && es.decoder.stream_type != UNKNOWN) - { - found = 0; - //search this ES_ID if we already have it - for(k=0; k < pmt->mp4es_cnt; k++) - { - if(pmt->mp4es[k].id == es.id) - { - target_es = &(pmt->mp4es[k]); - found = 1; - } - } - - if(! found) - { - tmp = realloc_struct(pmt->mp4es, pmt->mp4es_cnt+1, sizeof(mp4_es_descr_t)); - if(tmp == NULL) - { - fprintf(stderr, "CAN'T REALLOC MP4_ES_DESCR\n"); - continue; - } - pmt->mp4es = tmp; - target_es = &(pmt->mp4es[pmt->mp4es_cnt]); - pmt->mp4es_cnt++; - } - memcpy(target_es, &es, sizeof(mp4_es_descr_t)); - mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_CNT: %d, ID=%d\n", pmt->mp4es_cnt, target_es->id); - } - - i += j; - } - - return len; -} - -static void parse_mp4_object_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem) -{ - int i, j = 0, id; - - i=0; - id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6); - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_OBJECT_DESCRIPTOR: len=%d, OD_ID=%d\n", len, id); - if(buf[1] & 0x20) - { - i += buf[2] + 1; //url - mp_msg(MSGT_DEMUX, MSGL_V, "URL\n"); - } - else - { - i = 2; - - while(i < len) - { - j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem); - mp_msg(MSGT_DEMUX, MSGL_V, "OBJD, NOW i = %d, j=%d, LEN=%d\n", i, j, len); - i += j; - } - } -} - - -static void parse_mp4_iod(pmt_t *pmt, uint8_t *buf, int len, void *elem) -{ - int i, j = 0; - mp4_od_t *iod = &(pmt->iod); - - iod->id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6); - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_IOD: len=%d, IOD_ID=%d\n", len, iod->id); - i = 2; - if(buf[1] & 0x20) - { - i += buf[2] + 1; //url - mp_msg(MSGT_DEMUX, MSGL_V, "URL\n"); - } - else - { - i = 7; - while(i < len) - { - j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem); - mp_msg(MSGT_DEMUX, MSGL_V, "IOD, NOW i = %d, j=%d, LEN=%d\n", i, j, len); - i += j; - } - } -} - -static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem) -{ - int tag, descr_len, i = 0, j = 0; - - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DESCRIPTORS, len=%d\n", len); - if(! len) - return len; - - while(i < len) - { - tag = buf[i]; - j = len - i -1; - descr_len = get_mp4_desc_len(&(buf[i+1]), &j); - mp_msg(MSGT_DEMUX, MSGL_V, "TAG=%d (0x%x), DESCR_len=%d, len=%d, j=%d\n", tag, tag, descr_len, len, j); - if(descr_len > len - j+1) - { - mp_msg(MSGT_DEMUX, MSGL_V, "descriptor is too long, exit\n"); - return len; - } - i += j+1; - - switch(tag) - { - case 0x1: - parse_mp4_object_descriptor(pmt, &(buf[i]), descr_len, elem); - break; - case 0x2: - parse_mp4_iod(pmt, &(buf[i]), descr_len, elem); - break; - case 0x3: - parse_mp4_es_descriptor(pmt, &(buf[i]), descr_len); - break; - case 0x4: - parse_mp4_decoder_config_descriptor(pmt, &buf[i], descr_len, elem); - break; - case 0x05: - parse_mp4_decoder_specific_descriptor(&buf[i], descr_len, elem); - break; - case 0x6: - parse_mp4_slconfig_descriptor(&buf[i], descr_len, elem); - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, "Unsupported mp4 descriptor 0x%x\n", tag); - } - i += descr_len; - } - - return len; -} - -static ES_stream_t *new_pid(ts_priv_t *priv, int pid) -{ - ES_stream_t *tss; - - tss = calloc(sizeof(*tss), 1); - if(! tss) - return NULL; - tss->pid = pid; - tss->last_cc = -1; - tss->type = UNKNOWN; - tss->subtype = UNKNOWN; - tss->is_synced = 0; - tss->extradata = NULL; - tss->extradata_alloc = tss->extradata_len = 0; - priv->ts.pids[pid] = tss; - - return tss; -} - - -static int parse_program_descriptors(pmt_t *pmt, uint8_t *buf, uint16_t len) -{ - uint16_t i = 0, k, olen = len; - - while(len > 0) - { - mp_msg(MSGT_DEMUX, MSGL_V, "PROG DESCR, TAG=%x, LEN=%d(%x)\n", buf[i], buf[i+1], buf[i+1]); - if(buf[i+1] > len-2) - { - mp_msg(MSGT_DEMUX, MSGL_V, "ERROR, descriptor len is too long, skipping\n"); - return olen; - } - - if(buf[i] == 0x1d) - { - if(buf[i+3] == 2) //buggy versions of vlc muxer make this non-standard mess (missing iod_scope) - k = 3; - else - k = 4; //this is standard compliant - parse_mp4_descriptors(pmt, &buf[i+k], (int) buf[i+1]-(k-2), NULL); - } - - len -= 2 + buf[i+1]; - } - - return olen; -} - -static int parse_descriptors(struct pmt_es_t *es, uint8_t *ptr) -{ - int j, descr_len, len; - - j = 0; - len = es->descr_length; - while(len > 2) - { - descr_len = ptr[j+1]; - mp_msg(MSGT_DEMUX, MSGL_V, "...descr id: 0x%x, len=%d\n", ptr[j], descr_len); - if(descr_len > len) - { - mp_msg(MSGT_DEMUX, MSGL_ERR, "INVALID DESCR LEN for tag %02x: %d vs %d max, EXIT LOOP\n", ptr[j], descr_len, len); - return -1; - } - - - if(ptr[j] == 0x6a || ptr[j] == 0x7a) //A52 Descriptor - { - if(es->type == 0x6) - { - es->type = AUDIO_A52; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB A52 Descriptor\n"); - } - } - else if(ptr[j] == 0x7b) //DVB DTS Descriptor - { - if(es->type == 0x6) - { - es->type = AUDIO_DTS; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB DTS Descriptor\n"); - } - } - else if(ptr[j] == 0x56) // Teletext - { - if(descr_len >= 5) { - memcpy(es->lang, ptr+2, 3); - es->lang[3] = 0; - } - es->type = SPU_TELETEXT; - } - else if(ptr[j] == 0x59) //Subtitling Descriptor - { - uint8_t subtype; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Subtitling Descriptor\n"); - if(descr_len < 8) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Descriptor length too short for DVB Subtitle Descriptor: %d, SKIPPING\n", descr_len); - } - else - { - memcpy(es->lang, &ptr[j+2], 3); - es->lang[3] = 0; - subtype = ptr[j+5]; - if( - (subtype >= 0x10 && subtype <= 0x13) || - (subtype >= 0x20 && subtype <= 0x23) - ) - { - es->type = SPU_DVB; - //page parameters: compo page 2 bytes, ancillary page 2 bytes - } - else - es->type = UNKNOWN; - } - } - else if(ptr[j] == 0x50) //Component Descriptor - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Component Descriptor\n"); - memcpy(es->lang, &ptr[j+5], 3); - es->lang[3] = 0; - } - else if(ptr[j] == 0xa) //Language Descriptor - { - memcpy(es->lang, &ptr[j+2], 3); - es->lang[3] = 0; - mp_msg(MSGT_DEMUX, MSGL_V, "Language Descriptor: %s\n", es->lang); - } - else if(ptr[j] == 0x5) //Registration Descriptor (looks like e fourCC :) ) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor\n"); - if(descr_len < 4) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor length too short: %d, SKIPPING\n", descr_len); - } - else - { - char *d; - memcpy(es->format_descriptor, &ptr[j+2], 4); - es->format_descriptor[4] = 0; - - d = &ptr[j+2]; - if(d[0] == 'A' && d[1] == 'C' && d[2] == '-' && d[3] == '3') - { - es->type = AUDIO_A52; - } - else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '1') - { - es->type = AUDIO_DTS; - } - else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '2') - { - es->type = AUDIO_DTS; - } - else if(d[0] == 'V' && d[1] == 'C' && d[2] == '-' && d[3] == '1') - { - es->type = VIDEO_VC1; - } - else if(d[0] == 'd' && d[1] == 'r' && d[2] == 'a' && d[3] == 'c') - { - es->type = VIDEO_DIRAC; - } - else if(d[0] == 'B' && d[1] == 'S' && d[2] == 'S' && d[3] == 'D') - { - es->type = AUDIO_S302M; - } - else - es->type = UNKNOWN; - mp_msg(MSGT_DEMUX, MSGL_DBG2, "FORMAT %s\n", es->format_descriptor); - } - } - else if(ptr[j] == 0x1e || ptr[j] == 0x1f) - { - // 0x1f is FMC, but currently it is easiest to handle them the same way - es->mp4_es_id = (ptr[j+2] << 8) | ptr[j+3]; - mp_msg(MSGT_DEMUX, MSGL_V, "SL Descriptor: ES_ID: %d(%x), pid: %d\n", es->mp4_es_id, es->mp4_es_id, es->pid); - } - else - mp_msg(MSGT_DEMUX, MSGL_DBG2, "Unknown descriptor 0x%x, SKIPPING\n", ptr[j]); - - len -= 2 + descr_len; - j += 2 + descr_len; - } - - return 1; -} - -static int parse_sl_section(pmt_t *pmt, ts_section_t *section, int is_start, unsigned char *buff, int size) -{ - int tid, len, skip; - uint8_t *ptr; - skip = collect_section(section, is_start, buff, size); - if(! skip) - return 0; - - ptr = &(section->buffer[skip]); - tid = ptr[0]; - len = ((ptr[1] & 0x0f) << 8) | ptr[2]; - mp_msg(MSGT_DEMUX, MSGL_V, "TABLEID: %d (av. %d), skip=%d, LEN: %d\n", tid, section->buffer_len, skip, len); - if(len > 4093 || section->buffer_len < len || tid != 5) - { - mp_msg(MSGT_DEMUX, MSGL_V, "SECTION TOO LARGE or wrong section type, EXIT\n"); - return 0; - } - - if(! (ptr[5] & 1)) - return 0; - - //8 is the current position, len - 9 is the amount of data available - parse_mp4_descriptors(pmt, &ptr[8], len - 9, NULL); - - return 1; -} - -static int parse_pmt(ts_priv_t * priv, uint16_t progid, uint16_t pid, int is_start, unsigned char *buff, int size) -{ - unsigned char *base, *es_base; - pmt_t *pmt; - int32_t idx, es_count, section_bytes; - uint8_t m=0; - int skip; - pmt_t *tmp; - struct pmt_es_t *tmp_es; - ts_section_t *section; - ES_stream_t *tss; - int i; - - idx = progid_idx_in_pmt(priv, progid); - - if(idx == -1) - { - int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t); - tmp = realloc_struct(priv->pmt, priv->pmt_cnt + 1, sizeof(pmt_t)); - if(tmp == NULL) - { - mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz); - return 0; - } - priv->pmt = tmp; - idx = priv->pmt_cnt; - memset(&(priv->pmt[idx]), 0, sizeof(pmt_t)); - priv->pmt_cnt++; - priv->pmt[idx].progid = progid; - } - - pmt = &(priv->pmt[idx]); - - section = &(pmt->section); - skip = collect_section(section, is_start, buff, size); - if(! skip) - return 0; - - base = &(section->buffer[skip]); - - mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TS_PID: %d, SIZE=%d, M=%d, ES_CNT=%d, IDX=%d, PMT_PTR=%p\n", - progid, pmt->section.buffer_len, is_start, pid, size, m, pmt->es_cnt, idx, pmt); - - pmt->table_id = base[0]; - if(pmt->table_id != 2) - return -1; - pmt->ssi = base[1] & 0x80; - pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]); - pmt->version_number = (base[5] >> 1) & 0x1f; - pmt->curr_next = (base[5] & 1); - pmt->section_number = base[6]; - pmt->last_section_number = base[7]; - pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9]; - pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11]; - if(pmt->prog_descr_length > pmt->section_length - 9) - { - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9); - return -1; - } - - if(pmt->prog_descr_length) - parse_program_descriptors(pmt, &base[12], pmt->prog_descr_length); - - es_base = &base[12 + pmt->prog_descr_length]; //the beginning of th ES loop - - section_bytes= pmt->section_length - 13 - pmt->prog_descr_length; - es_count = 0; - - while(section_bytes >= 5) - { - int es_pid, es_type; - - es_type = es_base[0]; - es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2]; - - idx = es_pid_in_pmt(pmt, es_pid); - if(idx == -1) - { - int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1); - tmp_es = realloc_struct(pmt->es, pmt->es_cnt + 1, sizeof(struct pmt_es_t)); - if(tmp_es == NULL) - { - mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz); - continue; - } - pmt->es = tmp_es; - idx = pmt->es_cnt; - memset(&(pmt->es[idx]), 0, sizeof(struct pmt_es_t)); - pmt->es_cnt++; - } - - pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4]; - - - if(pmt->es[idx].descr_length > section_bytes - 5) - { - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT\n", - pmt->es[idx].descr_length, section_bytes - 5); - return -1; - } - - - pmt->es[idx].pid = es_pid; - if(es_type != 0x6) - pmt->es[idx].type = UNKNOWN; - else - pmt->es[idx].type = es_type; - - parse_descriptors(&pmt->es[idx], &es_base[5]); - - switch(es_type) - { - case 1: - pmt->es[idx].type = VIDEO_MPEG1; - break; - case 2: - pmt->es[idx].type = VIDEO_MPEG2; - break; - case 3: - case 4: - pmt->es[idx].type = AUDIO_MP2; - break; - case 6: - if(pmt->es[idx].type == 0x6) //this could have been ovrwritten by parse_descriptors - pmt->es[idx].type = UNKNOWN; - break; - case 0x10: - pmt->es[idx].type = VIDEO_MPEG4; - break; - case 0x0f: - pmt->es[idx].type = AUDIO_AAC; - break; - case 0x11: - pmt->es[idx].type = AUDIO_AAC_LATM; - for (i = 0; i < pmt->mp4es_cnt; i++) - if (pmt->mp4es[i].id == pmt->es[idx].mp4_es_id && - pmt->mp4es[i].decoder.object_type == AUDIO_AAC) - pmt->es[idx].type = AUDIO_AAC; - break; - case 0x1b: - pmt->es[idx].type = VIDEO_H264; - break; - case 0x12: - pmt->es[idx].type = SL_PES_STREAM; - break; - case 0x13: - pmt->es[idx].type = SL_SECTION; - break; - case 0x81: - pmt->es[idx].type = AUDIO_A52; - break; - case 0x8A: - case 0x82: - case 0x85: - case 0x86: - pmt->es[idx].type = AUDIO_DTS; - break; - case 0x90: - pmt->es[idx].type = SPU_PGS; - break; - case 0xD1: - pmt->es[idx].type = VIDEO_DIRAC; - break; - case 0xEA: - pmt->es[idx].type = VIDEO_VC1; - break; - default: - mp_msg(MSGT_DEMUX, MSGL_DBG2, "UNKNOWN ES TYPE=0x%x\n", es_type); - pmt->es[idx].type = UNKNOWN; - } - - tss = priv->ts.pids[es_pid]; //an ES stream - if(tss == NULL) - { - tss = new_pid(priv, es_pid); - if(tss) - tss->type = pmt->es[idx].type; - } - - section_bytes -= 5 + pmt->es[idx].descr_length; - mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n", - progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes); - - - es_base += 5 + pmt->es[idx].descr_length; - - es_count++; - } - - mp_msg(MSGT_DEMUX, MSGL_V, "----------------------------\n"); - return 1; -} - -static pmt_t* pmt_of_pid(ts_priv_t *priv, int pid, mp4_decoder_config_t **mp4_dec) -{ - int32_t i, j, k; - - if(priv->pmt) - { - for(i = 0; i < priv->pmt_cnt; i++) - { - if(priv->pmt[i].es && priv->pmt[i].es_cnt) - { - for(j = 0; j < priv->pmt[i].es_cnt; j++) - { - if(priv->pmt[i].es[j].pid == pid) - { - //search mp4_es_id - if(priv->pmt[i].es[j].mp4_es_id) - { - for(k = 0; k < priv->pmt[i].mp4es_cnt; k++) - { - if(priv->pmt[i].mp4es[k].id == priv->pmt[i].es[j].mp4_es_id) - { - *mp4_dec = &(priv->pmt[i].mp4es[k].decoder); - break; - } - } - } - - return &(priv->pmt[i]); - } - } - } - } - } - - return NULL; -} - - -static inline int32_t pid_type_from_pmt(ts_priv_t *priv, int pid) -{ - int32_t pmt_idx, pid_idx, i, j; - - pmt_idx = progid_idx_in_pmt(priv, priv->prog); - - if(pmt_idx != -1) - { - pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid); - if(pid_idx != -1) - return priv->pmt[pmt_idx].es[pid_idx].type; - } - //else - //{ - for(i = 0; i < priv->pmt_cnt; i++) - { - pmt_t *pmt = &(priv->pmt[i]); - for(j = 0; j < pmt->es_cnt; j++) - if(pmt->es[j].pid == pid) - return pmt->es[j].type; - } - //} - - return UNKNOWN; -} - - -static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid) -{ - int32_t pmt_idx, pid_idx, i, j; - - pmt_idx = progid_idx_in_pmt(priv, priv->prog); - - if(pmt_idx != -1) - { - pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid); - if(pid_idx != -1) - return priv->pmt[pmt_idx].es[pid_idx].lang; - } - else - { - for(i = 0; i < priv->pmt_cnt; i++) - { - pmt_t *pmt = &(priv->pmt[i]); - for(j = 0; j < pmt->es_cnt; j++) - if(pmt->es[j].pid == pid) - return pmt->es[j].lang; - } - } - - return NULL; -} - - -static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset, TS_stream_info *si) -{ - int ret = 0; - - if(*dp && *dp_offset <= 0) - { - free_demux_packet(*dp); - *dp = NULL; - } - if(*dp) - { - ret = *dp_offset; - resize_demux_packet(*dp, ret); //shrinked to the right size - ds_add_packet(ds, *dp); - mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts); - if(si) - { - float diff = (*dp)->pts - si->last_pts; - float dur; - - if(abs(diff) > 1) //1 second, there's a discontinuity - { - si->duration += si->last_pts - si->first_pts; - si->first_pts = si->last_pts = (*dp)->pts; - } - else - { - si->last_pts = (*dp)->pts; - } - si->size += ret; - dur = si->duration + (si->last_pts - si->first_pts); - - if(dur > 0 && ds == demuxer->video) - { - ts_priv_t * priv = (ts_priv_t*) demuxer->priv; - if(dur > 1) //otherwise it may be unreliable - priv->vbitrate = (uint32_t) ((float) si->size / dur); - } - } - } - - *dp = NULL; - *dp_offset = 0; - - return ret; -} - -static int fill_extradata(mp4_decoder_config_t * mp4_dec, ES_stream_t *tss) -{ - uint8_t *tmp; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4_dec: %p, pid: %d\n", mp4_dec, tss->pid); - - if(mp4_dec->buf_size > tss->extradata_alloc) - { - tmp = realloc(tss->extradata, mp4_dec->buf_size); - if(!tmp) - return 0; - tss->extradata = tmp; - tss->extradata_alloc = mp4_dec->buf_size; - } - memcpy(tss->extradata, mp4_dec->buf, mp4_dec->buf_size); - tss->extradata_len = mp4_dec->buf_size; - mp_msg(MSGT_DEMUX, MSGL_V, "EXTRADATA: %p, alloc=%d, len=%d\n", tss->extradata, tss->extradata_alloc, tss->extradata_len); - - return tss->extradata_len; -} - -// 0 = EOF or no stream found -// else = [-] number of bytes written to the packet -static int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe) -{ - ES_stream_t *tss; - int buf_size, is_start, pid, base; - int len, cc, cc_ok av_unused, afc, retv = 0, is_video, is_audio, is_sub; - ts_priv_t * priv = (ts_priv_t*) demuxer->priv; - stream_t *stream = demuxer->stream; - char *p; - demux_stream_t *ds = NULL; - demux_packet_t **dp = NULL; - int *dp_offset = 0, *buffer_size = 0; - int32_t progid, pid_type, bad, ts_error; - int junk = 0, rap_flag = 0; - pmt_t *pmt; - mp4_decoder_config_t *mp4_dec; - TS_stream_info *si; - - - memset(es, 0, sizeof(*es)); - while(1) - { - bad = ts_error = 0; - ds = NULL; - dp = NULL; - dp_offset = buffer_size = NULL; - rap_flag = 0; - mp4_dec = NULL; - es->is_synced = 0; - es->lang[0] = 0; - si = NULL; - - junk = priv->ts.packet_size - TS_PACKET_SIZE; - buf_size = priv->ts.packet_size - junk; - - if(stream_eof(stream)) - { - if(! probe) - { - ts_dump_streams(priv); - demuxer->filepos = stream_tell(demuxer->stream); - } - - return 0; - } - - - if(! ts_sync(stream)) - { - mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n"); - return 0; - } - - len = stream_read(stream, &packet[1], 3); - if (len != 3) - return 0; - buf_size -= 4; - - if((packet[1] >> 7) & 0x01) //transport error - ts_error = 1; - - - is_start = packet[1] & 0x40; - pid = ((packet[1] & 0x1f) << 8) | packet[2]; - - tss = priv->ts.pids[pid]; //an ES stream - if(tss == NULL) - { - tss = new_pid(priv, pid); - if(tss == NULL) - continue; - } - - cc = (packet[3] & 0xf); - cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); - tss->last_cc = cc; - - bad = ts_error; // || (! cc_ok); - if(bad) - { - if(priv->keep_broken == 0) - { - stream_skip(stream, buf_size-1+junk); - continue; - } - - is_start = 0; //queued to the packet data - } - - if(is_start) - tss->is_synced = 1; - - if((!is_start && !tss->is_synced) || ((pid > 1) && (pid < 16)) || (pid == 8191)) //invalid pid - { - stream_skip(stream, buf_size-1+junk); - continue; - } - - - afc = (packet[3] >> 4) & 3; - if(! (afc % 2)) //no payload in this TS packet - { - stream_skip(stream, buf_size-1+junk); - continue; - } - - if(afc > 1) - { - int c; - c = stream_read_char(stream); - buf_size--; - if(c < 0 || c > 183) //broken from the stream layer or invalid - { - stream_skip(stream, buf_size-1+junk); - continue; - } - - //c==0 is allowed! - if(c > 0) - { - uint8_t pcrbuf[188]; - int flags = stream_read_char(stream); - int has_pcr; - rap_flag = (flags & 0x40) >> 6; - has_pcr = flags & 0x10; - - buf_size--; - c--; - stream_read(stream, pcrbuf, c); - - if(has_pcr) - { - int pcr_pid = prog_pcr_pid(priv, priv->prog); - if(pcr_pid == pid) - { - uint64_t pcr, pcr_ext; - - pcr = (int64_t)(pcrbuf[0]) << 25; - pcr |= pcrbuf[1] << 17 ; - pcr |= (pcrbuf[2]) << 9; - pcr |= pcrbuf[3] << 1 ; - pcr |= (pcrbuf[4] & 0x80) >> 7; - - pcr_ext = (pcrbuf[4] & 0x01) << 8; - pcr_ext |= pcrbuf[5]; - - pcr = pcr * 300 + pcr_ext; - - demuxer->reference_clock = (double)pcr/(double)27000000.0; - } - } - - buf_size -= c; - if(buf_size == 0) - continue; - } - } - - //find the program that the pid belongs to; if (it's the right one or -1) && pid_type==SL_SECTION - //call parse_sl_section() - pmt = pmt_of_pid(priv, pid, &mp4_dec); - if(mp4_dec) - { - fill_extradata(mp4_dec, tss); - if(IS_VIDEO(mp4_dec->object_type) || IS_AUDIO(mp4_dec->object_type)) - { - tss->type = SL_PES_STREAM; - tss->subtype = mp4_dec->object_type; - } - } - - - //TABLE PARSING - - base = priv->ts.packet_size - buf_size; - - priv->last_pid = pid; - - is_video = IS_VIDEO(tss->type) || (tss->type==SL_PES_STREAM && IS_VIDEO(tss->subtype)); - is_audio = IS_AUDIO(tss->type) || (tss->type==SL_PES_STREAM && IS_AUDIO(tss->subtype)) || (tss->type == PES_PRIVATE1); - is_sub = IS_SUB(tss->type); - pid_type = pid_type_from_pmt(priv, pid); - - // PES CONTENT STARTS HERE - if(! probe) - { - if((is_video || is_audio || is_sub) && is_start) - ts_add_stream(demuxer, tss); - - if(is_video && (demuxer->video->id == priv->ts.streams[pid].id)) - { - ds = demuxer->video; - - dp = &priv->fifo[1].pack; - dp_offset = &priv->fifo[1].offset; - buffer_size = &priv->fifo[1].buffer_size; - si = &priv->vstr; - } - else if(is_audio && (demuxer->audio->id == priv->ts.streams[pid].id)) - { - ds = demuxer->audio; - - dp = &priv->fifo[0].pack; - dp_offset = &priv->fifo[0].offset; - buffer_size = &priv->fifo[0].buffer_size; - si = &priv->astr; - } - else if(is_sub) - { - sh_sub_t *sh_sub = demuxer->sub->sh; - - if(sh_sub && sh_sub->sid == tss->pid) - { - ds = demuxer->sub; - - dp = &priv->fifo[2].pack; - dp_offset = &priv->fifo[2].offset; - buffer_size = &priv->fifo[2].buffer_size; - } - else - { - stream_skip(stream, buf_size+junk); - continue; - } - } - - //IS IT TIME TO QUEUE DATA to the dp_packet? - if(is_start && (dp != NULL)) - { - retv = fill_packet(demuxer, ds, dp, dp_offset, si); - } - - - if(dp && *dp == NULL) - { - if(*buffer_size > MAX_PACK_BYTES) - *buffer_size = MAX_PACK_BYTES; - *dp = new_demux_packet(*buffer_size); //es->size - *dp_offset = 0; - if(! *dp) - { - fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", *buffer_size); - continue; - } - mp_msg(MSGT_DEMUX, MSGL_DBG2, "CREATED DP(%d)\n", *buffer_size); - } - } - - - if(probe || !dp) //dp is NULL for tables and sections - { - p = &packet[base]; - } - else //feeding - { - if(*dp_offset + buf_size > *buffer_size) - { - *buffer_size = *dp_offset + buf_size + TS_FEC_PACKET_SIZE; - resize_demux_packet(*dp, *buffer_size); - } - p = &((*dp)->buffer[*dp_offset]); - } - - len = stream_read(stream, p, buf_size); - if(len < buf_size) - { - mp_msg(MSGT_DEMUX, MSGL_DBG2, "\r\nts_parse() couldn't read enough data: %d < %d\r\n", len, buf_size); - continue; - } - stream_skip(stream, junk); - - if(pid == 0) - { - parse_pat(priv, is_start, p, buf_size); - continue; - } - else if((tss->type == SL_SECTION) && pmt) - { - int k, mp4_es_id = -1; - ts_section_t *section; - for(k = 0; k < pmt->mp4es_cnt; k++) - { - if(pmt->mp4es[k].decoder.object_type == MP4_OD && pmt->mp4es[k].decoder.stream_type == MP4_OD) - mp4_es_id = pmt->mp4es[k].id; - } - mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4ESID: %d\n", mp4_es_id); - for(k = 0; k < pmt->es_cnt; k++) - { - if(pmt->es[k].mp4_es_id == mp4_es_id) - { - section = &(tss->section); - parse_sl_section(pmt, section, is_start, &packet[base], buf_size); - } - } - continue; - } - else - { - progid = prog_id_in_pat(priv, pid); - if(progid != -1) - { - if(pid != demuxer->video->id && pid != demuxer->audio->id && pid != demuxer->sub->id) - { - parse_pmt(priv, progid, pid, is_start, &packet[base], buf_size); - continue; - } - else - mp_msg(MSGT_DEMUX, MSGL_ERR, "Argh! Data pid %d used in the PMT, Skipping PMT parsing!\n", pid); - } - } - - if(!probe && !dp) - continue; - - if(is_start) - { - uint8_t *lang = NULL; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "IS_START\n"); - - len = pes_parse2(p, buf_size, es, pid_type, pmt, pid); - if(! len) - { - tss->is_synced = 0; - continue; - } - es->pid = tss->pid; - tss->is_synced |= es->is_synced || rap_flag; - tss->payload_size = es->payload_size; - - if((is_sub || is_audio) && (lang = pid_lang_from_pmt(priv, es->pid))) - { - memcpy(es->lang, lang, 3); - es->lang[3] = 0; - } - else - es->lang[0] = 0; - - if(probe) - { - if(es->type == UNKNOWN) - return 0; - - tss->type = es->type; - tss->subtype = es->subtype; - - return 1; - } - else - { - if(es->pts == 0.0) - es->pts = tss->pts = tss->last_pts; - else - tss->pts = tss->last_pts = es->pts; - - mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, NEW pid=%d, PSIZE: %u, type=%X, start=%p, len=%d\n", - es->pid, es->payload_size, es->type, es->start, es->size); - - demuxer->filepos = stream_tell(demuxer->stream) - es->size; - - if(es->size < 0 || es->size > buf_size) { - mp_msg(MSGT_DEMUX, MSGL_ERR, "Broken ES packet size\n"); - es->size = 0; - } - memmove(p, es->start, es->size); - *dp_offset += es->size; - (*dp)->keyframe = 0; - (*dp)->pos = stream_tell(demuxer->stream); - (*dp)->pts = es->pts; - // subtitle packets must be returned immediately if possible - if (is_sub && !tss->payload_size) - retv = fill_packet(demuxer, ds, dp, dp_offset, si); - - if(retv > 0) - return retv; - else - continue; - } - } - else - { - uint16_t sz; - - es->pid = tss->pid; - es->type = tss->type; - es->subtype = tss->subtype; - es->pts = tss->pts = tss->last_pts; - es->start = &packet[base]; - - - if(tss->payload_size > 0) - { - sz = FFMIN(tss->payload_size, buf_size); - tss->payload_size -= sz; - es->size = sz; - } - else - { - if(is_video) - { - sz = es->size = buf_size; - } - else - { - continue; - } - } - - - if(! probe) - { - *dp_offset += sz; - - // subtitle packets must be returned immediately if possible - if(*dp_offset >= MAX_PACK_BYTES || (is_sub && !tss->payload_size)) - { - (*dp)->pts = tss->last_pts; - retv = fill_packet(demuxer, ds, dp, dp_offset, si); - return 1; - } - - continue; - } - else - { - memmove(es->start, p, sz); - - if(es->size) - return es->size; - else - continue; - } - } - } - - return 0; -} - - -static void reset_fifos(demuxer_t *demuxer, int a, int v, int s) -{ - ts_priv_t* priv = demuxer->priv; - if(a) - { - if(priv->fifo[0].pack != NULL) - { - free_demux_packet(priv->fifo[0].pack); - priv->fifo[0].pack = NULL; - } - priv->fifo[0].offset = 0; - } - - if(v) - { - if(priv->fifo[1].pack != NULL) - { - free_demux_packet(priv->fifo[1].pack); - priv->fifo[1].pack = NULL; - } - priv->fifo[1].offset = 0; - } - - if(s) - { - if(priv->fifo[2].pack != NULL) - { - free_demux_packet(priv->fifo[2].pack); - priv->fifo[2].pack = NULL; - } - priv->fifo[2].offset = 0; - } - demuxer->reference_clock = MP_NOPTS_VALUE; -} - - -static void demux_seek_ts(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) -{ - demux_stream_t *d_audio=demuxer->audio; - demux_stream_t *d_video=demuxer->video; - sh_audio_t *sh_audio=d_audio->sh; - sh_video_t *sh_video=d_video->sh; - ts_priv_t * priv = (ts_priv_t*) demuxer->priv; - int i, video_stats; - off_t newpos; - - //================= seek in MPEG-TS ========================== - - ts_dump_streams(demuxer->priv); - reset_fifos(demuxer, sh_audio != NULL, sh_video != NULL, demuxer->sub->id > 0); - - demux_flush(demuxer); - - - - video_stats = (sh_video != NULL); - if(video_stats) - { - mp_msg(MSGT_DEMUX, MSGL_V, "IBPS: %d, vb: %d\r\n", sh_video->i_bps, priv->vbitrate); - if(priv->vbitrate) - video_stats = priv->vbitrate; - else - video_stats = sh_video->i_bps; - } - - newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : demuxer->filepos; - if(flags & SEEK_FACTOR) // float seek 0..1 - newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs; - else - { - // time seek (secs) - if(! video_stats) // unspecified or VBR - newpos += 2324*75*rel_seek_secs; // 174.3 kbyte/sec - else - newpos += video_stats*rel_seek_secs; - } - - - if(newpos < demuxer->movi_start) - newpos = demuxer->movi_start; //begininng of stream - - stream_seek(demuxer->stream, newpos); - for(i = 0; i < NB_PID_MAX; i++) - if(priv->ts.pids[i] != NULL) - priv->ts.pids[i]->is_synced = 0; - - videobuf_code_len = 0; - - if(sh_video != NULL) - ds_fill_buffer(d_video); - - if(sh_audio != NULL) - { - ds_fill_buffer(d_audio); - } - - while(sh_video != NULL) - { - if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts) - { - double a_pts=d_audio->pts; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(double)sh_audio->i_bps; - if(d_video->pts > a_pts) - { - skip_audio_frame(sh_audio); // sync audio - continue; - } - } - - - i = sync_video_packet(d_video); - if((sh_video->format == VIDEO_MPEG1) || (sh_video->format == VIDEO_MPEG2)) - { - if(i==0x1B3 || i==0x1B8) break; // found it! - } - else if((sh_video->format == VIDEO_MPEG4) && (i==0x1B6)) - break; - else if(sh_video->format == VIDEO_VC1 && (i==0x10E || i==0x10F)) - break; - else //H264 - { - if((i & ~0x60) == 0x105 || (i & ~0x60) == 0x107) break; - } - - if(!i || !skip_video_packet(d_video)) break; // EOF? - } -} - - -static int demux_ts_fill_buffer(demuxer_t * demuxer, demux_stream_t *ds) -{ - ES_stream_t es; - ts_priv_t *priv = (ts_priv_t *)demuxer->priv; - - return -ts_parse(demuxer, &es, priv->packet, 0); -} - - -static int ts_check_file_dmx(demuxer_t *demuxer) -{ - return ts_check_file(demuxer) ? DEMUXER_TYPE_MPEG_TS : 0; -} - -static int is_usable_program(ts_priv_t *priv, pmt_t *pmt) -{ - int j; - - for(j = 0; j < pmt->es_cnt; j++) - { - if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL) - continue; - if( - priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO || - priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO - ) - return 1; - } - - return 0; -} - -static int demux_ts_control(demuxer_t *demuxer, int cmd, void *arg) -{ - ts_priv_t* priv = (ts_priv_t *)demuxer->priv; - - switch(cmd) - { - case DEMUXER_CTRL_SWITCH_AUDIO: - case DEMUXER_CTRL_SWITCH_VIDEO: - { - void *sh = NULL; - int i, n; - int reftype, areset = 0, vreset = 0; - demux_stream_t *ds; - - if(cmd == DEMUXER_CTRL_SWITCH_VIDEO) - { - reftype = TYPE_VIDEO; - ds = demuxer->video; - vreset = 1; - } - else - { - reftype = TYPE_AUDIO; - ds = demuxer->audio; - areset = 1; - } - n = *((int*)arg); - if(n == -2) - { - reset_fifos(demuxer, areset, vreset, 0); - ds->id = -2; - ds->sh = NULL; - ds_free_packs(ds); - *((int*)arg) = ds->id; - return DEMUXER_CTRL_OK; - } - - if(n < 0) - { - for(i = 0; i < 8192; i++) - { - if(priv->ts.streams[i].id == ds->id && priv->ts.streams[i].type == reftype) - break; - } - - while(!sh) - { - i = (i+1) % 8192; - if(priv->ts.streams[i].type == reftype) - { - if(priv->ts.streams[i].id == ds->id) //we made a complete loop - break; - sh = priv->ts.streams[i].sh; - } - } - } - else //audio track <n> - { - if (n >= 8192 || priv->ts.streams[n].type != reftype) return DEMUXER_CTRL_NOTIMPL; - i = n; - sh = priv->ts.streams[i].sh; - } - - if(sh) - { - if(ds->id != priv->ts.streams[i].id) - reset_fifos(demuxer, areset, vreset, 0); - ds->id = priv->ts.streams[i].id; - ds->sh = sh; - ds_free_packs(ds); - mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndemux_ts, switched to audio pid %d, id: %d, sh: %p\r\n", i, ds->id, sh); - } - - *((int*)arg) = ds->id; - return DEMUXER_CTRL_OK; - } - - case DEMUXER_CTRL_IDENTIFY_PROGRAM: //returns in prog->{aid,vid} the new ids that comprise a program - { - int i, j, cnt=0; - int vid_done=0, aid_done=0; - pmt_t *pmt = NULL; - demux_program_t *prog = arg; - - if(priv->pmt_cnt < 2) - return DEMUXER_CTRL_NOTIMPL; - - if(prog->progid == -1) - { - int cur_pmt_idx = 0; - - for(i = 0; i < priv->pmt_cnt; i++) - if(priv->pmt[i].progid == priv->prog) - { - cur_pmt_idx = i; - break; - } - - i = (cur_pmt_idx + 1) % priv->pmt_cnt; - while(i != cur_pmt_idx) - { - pmt = &priv->pmt[i]; - cnt = is_usable_program(priv, pmt); - if(cnt) - break; - i = (i + 1) % priv->pmt_cnt; - } - } - else - { - for(i = 0; i < priv->pmt_cnt; i++) - if(priv->pmt[i].progid == prog->progid) - { - pmt = &priv->pmt[i]; //required program - cnt = is_usable_program(priv, pmt); - } - } - - if(!cnt) - return DEMUXER_CTRL_NOTIMPL; - - //finally some food - prog->aid = prog->vid = -2; //no audio and no video by default - for(j = 0; j < pmt->es_cnt; j++) - { - if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL) - continue; - - if(!vid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO) - { - vid_done = 1; - prog->vid = pmt->es[j].pid; - } - else if(!aid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO) - { - aid_done = 1; - prog->aid = pmt->es[j].pid; - } - } - - priv->prog = prog->progid = pmt->progid; - return DEMUXER_CTRL_OK; - } - - default: - return DEMUXER_CTRL_NOTIMPL; - } -} - - -const demuxer_desc_t demuxer_desc_mpeg_ts = { - "MPEG-TS demuxer", - "mpegts", - "TS", - "Nico Sabbi", - "", - DEMUXER_TYPE_MPEG_TS, - 0, // unsafe autodetect - ts_check_file_dmx, - demux_ts_fill_buffer, - demux_open_ts, - demux_close_ts, - demux_seek_ts, - demux_ts_control -}; diff --git a/libmpdemux/demux_ts.h b/libmpdemux/demux_ts.h deleted file mode 100644 index 37bddb86da..0000000000 --- a/libmpdemux/demux_ts.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_DEMUX_TS_H -#define MPLAYER_DEMUX_TS_H - -#define TS_MAX_PROBE_SIZE 2000000 - -#endif /* MPLAYER_DEMUX_TS_H */ diff --git a/libmpdemux/demux_ty.c b/libmpdemux/demux_ty.c deleted file mode 100644 index 527d350bc6..0000000000 --- a/libmpdemux/demux_ty.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_ty_osd.c b/libmpdemux/demux_ty_osd.c deleted file mode 100644 index 983c243f98..0000000000 --- a/libmpdemux/demux_ty_osd.c +++ /dev/null @@ -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; - } - } -} diff --git a/libmpdemux/demux_ty_osd.h b/libmpdemux/demux_ty_osd.h deleted file mode 100644 index ce0af05788..0000000000 --- a/libmpdemux/demux_ty_osd.h +++ /dev/null @@ -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 */ diff --git a/libmpdemux/demux_vqf.c b/libmpdemux/demux_vqf.c deleted file mode 100644 index 051e912339..0000000000 --- a/libmpdemux/demux_vqf.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demux_y4m.c b/libmpdemux/demux_y4m.c deleted file mode 100644 index cf0f7cf7e6..0000000000 --- a/libmpdemux/demux_y4m.c +++ /dev/null @@ -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 -}; diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 0cce5e8543..e77e32b942 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -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,16 +105,9 @@ 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, #endif @@ -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); diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 3f9aa80b96..0e208d666e 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -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, diff --git a/libmpdemux/extension.c b/libmpdemux/extension.c index 1d2ffb832e..8c4602bab4 100644 --- a/libmpdemux/extension.c +++ b/libmpdemux/extension.c @@ -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 }, diff --git a/libmpdemux/mpeg_hdr.c b/libmpdemux/mpeg_hdr.c deleted file mode 100644 index 0c368aa7a2..0000000000 --- a/libmpdemux/mpeg_hdr.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * based on libmpeg2/header.c by Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <inttypes.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "config.h" -#include "mpeg_hdr.h" -#include "libavutil/attributes.h" -#include "mp_msg.h" - -static float frameratecode2framerate[16] = { - 0, - // Official mpeg1/2 framerates: (1-8) - 24000.0/1001, 24,25, - 30000.0/1001, 30,50, - 60000.0/1001, 60, - // Xing's 15fps: (9) - 15, - // libmpeg3's "Unofficial economy rates": (10-13) - 5,10,12,15, - // some invalid ones: (14-15) - 0,0 -}; - - -int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer) -{ - int height; - - if ((buffer[6] & 0x20) != 0x20){ - fprintf(stderr, "missing marker bit!\n"); - return 1; /* missing marker_bit */ - } - - height = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; - - picture->display_picture_width = height >> 12; - picture->display_picture_height = height & 0xfff; - - picture->aspect_ratio_information = buffer[3] >> 4; - picture->frame_rate_code = buffer[3] & 15; - picture->fps=frameratecode2framerate[picture->frame_rate_code]; - picture->bitrate = (buffer[4]<<10)|(buffer[5]<<2)|(buffer[6]>>6); - picture->mpeg1 = 1; - picture->picture_structure = 3; //FRAME_PICTURE; - picture->display_time=100; - picture->frame_rate_extension_n = 1; - picture->frame_rate_extension_d = 1; - return 0; -} - -static int header_process_sequence_extension (mp_mpeg_header_t * picture, - unsigned char * buffer) -{ - /* check chroma format, size extensions, marker bit */ - - if ( ((buffer[1] & 0x06) == 0x00) || - ((buffer[1] & 0x01) != 0x00) || (buffer[2] & 0xe0) || - ((buffer[3] & 0x01) != 0x01) ) - return 1; - - picture->progressive_sequence = (buffer[1] >> 3) & 1; - picture->frame_rate_extension_n = ((buffer[5] >> 5) & 3) + 1; - picture->frame_rate_extension_d = (buffer[5] & 0x1f) + 1; - - picture->mpeg1 = 0; - return 0; -} - -static int header_process_picture_coding_extension (mp_mpeg_header_t * picture, unsigned char * buffer) -{ - picture->picture_structure = buffer[2] & 3; - picture->top_field_first = buffer[3] >> 7; - picture->repeat_first_field = (buffer[3] >> 1) & 1; - picture->progressive_frame = buffer[4] >> 7; - - // repeat_first implementation by A'rpi/ESP-team, based on libmpeg3: - picture->display_time=100; - if(picture->repeat_first_field){ - if(picture->progressive_sequence){ - if(picture->top_field_first) - picture->display_time+=200; - else - picture->display_time+=100; - } else - if(picture->progressive_frame){ - picture->display_time+=50; - } - } - //temopral hack. We calc time on every field, so if we have 2 fields - // interlaced we'll end with double time for 1 frame - if( picture->picture_structure!=3 ) picture->display_time/=2; - return 0; -} - -int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer) -{ - switch (buffer[0] & 0xf0) { - case 0x10: /* sequence extension */ - return header_process_sequence_extension (picture, buffer); - case 0x80: /* picture coding extension */ - return header_process_picture_coding_extension (picture, buffer); - } - return 0; -} - -float mpeg12_aspect_info(mp_mpeg_header_t *picture) -{ - float aspect = 0.0; - - switch(picture->aspect_ratio_information) { - case 2: // PAL/NTSC SVCD/DVD 4:3 - case 8: // PAL VCD 4:3 - case 12: // NTSC VCD 4:3 - aspect=4.0/3.0; - break; - case 3: // PAL/NTSC Widescreen SVCD/DVD 16:9 - case 6: // (PAL?)/NTSC Widescreen SVCD 16:9 - aspect=16.0/9.0; - break; - case 4: // according to ISO-138182-2 Table 6.3 - aspect=2.21; - break; - case 1: // VGA 1:1 - do not prescale - case 9: // Movie Type ??? / 640x480 - aspect=0.0; - break; - default: - mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Detected unknown aspect_ratio_information in mpeg sequence header.\n" - "Please report the aspect value (%i) along with the movie type (VGA,PAL,NTSC," - "SECAM) and the movie resolution (720x576,352x240,480x480,...) to the MPlayer" - " developers, so that we can add support for it!\nAssuming 1:1 aspect for now.\n", - picture->aspect_ratio_information); - } - - return aspect; -} - -//MPEG4 HEADERS -unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len) -{ - unsigned int n; - unsigned char m, u, l, y; - - n = from / 8; - m = from % 8; - u = 8 - m; - l = (len > u ? len - u : 0); - - y = (buffer[n] << m); - if(8 > len) - y >>= (8-len); - if(l) - y |= (buffer[n+1] >> (8-l)); - - //fprintf(stderr, "GETBITS(%d -> %d): bytes=0x%x 0x%x, n=%d, m=%d, l=%d, u=%d, Y=%d\n", - // from, (int) len, (int) buffer[n],(int) buffer[n+1], n, (int) m, (int) l, (int) u, (int) y); - return y; -} - -static inline unsigned int mp_getbits16(unsigned char *buffer, unsigned int from, unsigned char len) -{ - if(len > 8) - return (mp_getbits(buffer, from, len - 8) << 8) | mp_getbits(buffer, from + len - 8, 8); - else - return mp_getbits(buffer, from, len); -} - -#define getbits mp_getbits -#define getbits16 mp_getbits16 - -static int read_timeinc(mp_mpeg_header_t * picture, unsigned char * buffer, int n) -{ - if(picture->timeinc_bits > 8) { - picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits - 8) << 8; - n += picture->timeinc_bits - 8; - picture->timeinc_unit |= getbits(buffer, n, 8); - n += 8; - } else { - picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits); - n += picture->timeinc_bits; - } - //fprintf(stderr, "TIMEINC2: %d, bits: %d\n", picture->timeinc_unit, picture->timeinc_bits); - return n; -} - -int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer) -{ - unsigned int n, aspect=0, aspectw av_unused=0, aspecth av_unused=0, x=1, v; - - //begins with 0x0000012x - picture->fps = 0; - picture->timeinc_bits = picture->timeinc_resolution = picture->timeinc_unit = 0; - n = 9; - if(getbits(buffer, n, 1)) - n += 7; - n++; - aspect=getbits(buffer, n, 4); - n += 4; - if(aspect == 0x0f) { - aspectw = getbits(buffer, n, 8); - n += 8; - aspecth = getbits(buffer, n, 8); - n += 8; - } - - if(getbits(buffer, n, 1)) { - n += 4; - if(getbits(buffer, n, 1)) - n += 79; - n++; - } else n++; - - n+=3; - - picture->timeinc_resolution = getbits(buffer, n, 8) << 8; - n += 8; - picture->timeinc_resolution |= getbits(buffer, n, 8); - n += 8; - - picture->timeinc_bits = 0; - v = picture->timeinc_resolution - 1; - while(v && (x<16)) { - v>>=1; - picture->timeinc_bits++; - } - picture->timeinc_bits = (picture->timeinc_bits > 1 ? picture->timeinc_bits : 1); - - n++; //marker bit - - if(getbits(buffer, n++, 1)) { //fixed_vop_timeinc - n += read_timeinc(picture, buffer, n); - - if(picture->timeinc_unit) - picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit; - } - - n++; //marker bit - picture->display_picture_width = getbits16(buffer, n, 13); - n += 13; - n++; //marker bit - picture->display_picture_height = getbits16(buffer, n, 13); - n += 13; - - //fprintf(stderr, "ASPECT: %d, PARW=%d, PARH=%d, TIMEINCRESOLUTION: %d, FIXED_TIMEINC: %d (number of bits: %d), FPS: %u\n", - // aspect, aspectw, aspecth, picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_bits, picture->fps); - - return 0; -} - -void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer) -{ - int n; - n = 0; - picture->picture_type = getbits(buffer, n, 2); - n += 2; - while(getbits(buffer, n, 1)) - n++; - n++; - getbits(buffer, n, 1); - n++; - n += read_timeinc(picture, buffer, n); -} - -#define min(a, b) ((a) <= (b) ? (a) : (b)) - -static unsigned int read_golomb(unsigned char *buffer, unsigned int *init) -{ - unsigned int x, v = 0, v2 = 0, m, len = 0, n = *init; - - while(getbits(buffer, n++, 1) == 0) - len++; - - x = len + n; - while(n < x) - { - m = min(x - n, 8); - v |= getbits(buffer, n, m); - n += m; - if(x - n > 8) - v <<= 8; - } - - v2 = 1; - for(n = 0; n < len; n++) - v2 <<= 1; - v2 = (v2 - 1) + v; - - //fprintf(stderr, "READ_GOLOMB(%u), V=2^%u + %u-1 = %u\n", *init, len, v, v2); - *init = x; - return v2; -} - -inline static int read_golomb_s(unsigned char *buffer, unsigned int *init) -{ - unsigned int v = read_golomb(buffer, init); - return (v & 1) ? ((v + 1) >> 1) : -(v >> 1); -} - -static int h264_parse_vui(mp_mpeg_header_t * picture, unsigned char * buf, unsigned int n) -{ - unsigned int overscan, vsp_color, chroma, timing, fixed_fps; - - if(getbits(buf, n++, 1)) - { - picture->aspect_ratio_information = getbits(buf, n, 8); - n += 8; - if(picture->aspect_ratio_information == 255) - { - picture->display_picture_width = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8); - n += 16; - - picture->display_picture_height = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8); - n += 16; - } - } - - if((overscan=getbits(buf, n++, 1))) - n++; - if((vsp_color=getbits(buf, n++, 1))) - { - n += 4; - if(getbits(buf, n++, 1)) - n += 24; - } - if((chroma=getbits(buf, n++, 1))) - { - read_golomb(buf, &n); - read_golomb(buf, &n); - } - if((timing=getbits(buf, n++, 1))) - { - picture->timeinc_unit = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8); - n += 32; - - picture->timeinc_resolution = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8); - n += 32; - - fixed_fps = getbits(buf, n, 1); - - if(picture->timeinc_unit > 0 && picture->timeinc_resolution > 0) - picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit; - if(fixed_fps) - picture->fps /= 2; - } - - //fprintf(stderr, "H264_PARSE_VUI, OVESCAN=%u, VSP_COLOR=%u, CHROMA=%u, TIMING=%u, DISPW=%u, DISPH=%u, TIMERES=%u, TIMEINC=%u, FIXED_FPS=%u\n", overscan, vsp_color, chroma, timing, picture->display_picture_width, picture->display_picture_height, - // picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_unit, fixed_fps); - - return n; -} - -static int mp_unescape03(unsigned char *buf, int len) -{ - unsigned char *dest; - int i, j, skip; - - dest = malloc(len); - if(! dest) - return 0; - - j = i = skip = 0; - while(i <= len-3) - { - if(buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3) - { - dest[j] = dest[j+1] = 0; - j += 2; - i += 3; - skip++; - } - else - { - dest[j] = buf[i]; - j++; - i++; - } - } - dest[j] = buf[len-2]; - dest[j+1] = buf[len-1]; - len -= skip; - memcpy(buf, dest, len); - free(dest); - - return len; -} - -int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len) -{ - unsigned int n = 0, v, i, k, mbh; - int frame_mbs_only; - - len = mp_unescape03(buf, len); - - picture->fps = picture->timeinc_unit = picture->timeinc_resolution = 0; - n = 24; - read_golomb(buf, &n); - if(buf[0] >= 100){ - if(read_golomb(buf, &n) == 3) - n++; - read_golomb(buf, &n); - read_golomb(buf, &n); - n++; - if(getbits(buf, n++, 1)){ - for(i = 0; i < 8; i++) - { // scaling list is skipped for now - if(getbits(buf, n++, 1)) - { - v = 8; - for(k = (i < 6 ? 16 : 64); k && v; k--) - v = (v + read_golomb_s(buf, &n)) & 255; - } - } - } - } - read_golomb(buf, &n); - v = read_golomb(buf, &n); - if(v == 0) - read_golomb(buf, &n); - else if(v == 1) - { - getbits(buf, n++, 1); - read_golomb(buf, &n); - read_golomb(buf, &n); - v = read_golomb(buf, &n); - for(i = 0; i < v; i++) - read_golomb(buf, &n); - } - read_golomb(buf, &n); - getbits(buf, n++, 1); - picture->display_picture_width = 16 *(read_golomb(buf, &n)+1); - mbh = read_golomb(buf, &n)+1; - frame_mbs_only = getbits(buf, n++, 1); - picture->display_picture_height = 16 * (2 - frame_mbs_only) * mbh; - if(!frame_mbs_only) - getbits(buf, n++, 1); - getbits(buf, n++, 1); - if(getbits(buf, n++, 1)) - { - read_golomb(buf, &n); - read_golomb(buf, &n); - read_golomb(buf, &n); - read_golomb(buf, &n); - } - if(getbits(buf, n++, 1)) - n = h264_parse_vui(picture, buf, n); - - return n; -} - -int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len) -{ - int n, x; - - len = mp_unescape03(buf, len); - - picture->display_picture_width = picture->display_picture_height = 0; - picture->fps = 0; - n = 0; - x = getbits(buf, n, 2); - n += 2; - if(x != 3) //not advanced profile - return 0; - - getbits16(buf, n, 14); - n += 14; - picture->display_picture_width = getbits16(buf, n, 12) * 2 + 2; - n += 12; - picture->display_picture_height = getbits16(buf, n, 12) * 2 + 2; - n += 12; - getbits(buf, n, 6); - n += 6; - x = getbits(buf, n, 1); - n += 1; - if(x) //display info - { - getbits16(buf, n, 14); - n += 14; - getbits16(buf, n, 14); - n += 14; - if(getbits(buf, n++, 1)) //aspect ratio - { - x = getbits(buf, n, 4); - n += 4; - if(x == 15) - { - getbits16(buf, n, 16); - n += 16; - } - } - - if(getbits(buf, n++, 1)) //framerates - { - int frexp=0, frnum=0, frden=0; - - if(getbits(buf, n++, 1)) - { - frexp = getbits16(buf, n, 16); - n += 16; - picture->fps = (double) (frexp+1) / 32.0; - } - else - { - float frates[] = {0, 24000, 25000, 30000, 50000, 60000, 48000, 72000, 0}; - float frdivs[] = {0, 1000, 1001, 0}; - - frnum = getbits(buf, n, 8); - n += 8; - frden = getbits(buf, n, 4); - n += 4; - if((frden == 1 || frden == 2) && (frnum < 8)) - picture->fps = frates[frnum] / frdivs[frden]; - } - } - } - - //free(dest); - return 1; -} diff --git a/libmpdemux/mpeg_hdr.h b/libmpdemux/mpeg_hdr.h deleted file mode 100644 index ccd84bcdb0..0000000000 --- a/libmpdemux/mpeg_hdr.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_MPEG_HDR_H -#define MPLAYER_MPEG_HDR_H - -typedef struct { - // video info: - int mpeg1; // 0=mpeg2 1=mpeg1 - int display_picture_width; - int display_picture_height; - int aspect_ratio_information; - int frame_rate_code; - float fps; - int frame_rate_extension_n; - int frame_rate_extension_d; - int bitrate; // 0x3FFFF==VBR - // timing: - int picture_structure; - int progressive_sequence; - int repeat_first_field; - int progressive_frame; - int top_field_first; - int display_time; // secs*100 - //the following are for mpeg4 - unsigned int timeinc_resolution, timeinc_bits, timeinc_unit; - int picture_type; -} mp_mpeg_header_t; - -int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer); -int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer); -float mpeg12_aspect_info(mp_mpeg_header_t *picture); -int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer); -void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer); -int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len); -int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len); - -unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len); - -#endif /* MPLAYER_MPEG_HDR_H */ diff --git a/libmpdemux/parse_es.c b/libmpdemux/parse_es.c deleted file mode 100644 index 05507a495a..0000000000 --- a/libmpdemux/parse_es.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * MPEG-ES video parser - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" -#include "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; -} diff --git a/libmpdemux/parse_es.h b/libmpdemux/parse_es.h deleted file mode 100644 index ed76593e50..0000000000 --- a/libmpdemux/parse_es.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_PARSE_ES_H -#define MPLAYER_PARSE_ES_H - -#include <stdint.h> - -#include "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 */ diff --git a/libmpdemux/parse_mp4.c b/libmpdemux/parse_mp4.c deleted file mode 100644 index 137ec3e6e7..0000000000 --- a/libmpdemux/parse_mp4.c +++ /dev/null @@ -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 diff --git a/libmpdemux/parse_mp4.h b/libmpdemux/parse_mp4.h deleted file mode 100644 index 27d4d44d7d..0000000000 --- a/libmpdemux/parse_mp4.h +++ /dev/null @@ -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 */ diff --git a/libmpdemux/video.c b/libmpdemux/video.c index e788818825..7bb1ade6e0 100644 --- a/libmpdemux/video.c +++ b/libmpdemux/video.c @@ -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; @@ -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) { diff --git a/stream/network.c b/stream/network.c index 0961c8d12b..b1212ab5e2 100644 --- a/stream/network.c +++ b/stream/network.c @@ -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}, }; |