Imported Upstream version 0.4.5+svn3912~dfsg0
authorAlessio Treglia <alessio@debian.org>
Sat, 11 Feb 2012 17:45:02 +0000 (18:45 +0100)
committerAlessio Treglia <alessio@debian.org>
Sat, 11 Feb 2012 17:45:02 +0000 (18:45 +0100)
506 files changed:
Makefile
applications/GPAX/GPAX.cpp [deleted file]
applications/GPAX/GPAX.def [deleted file]
applications/GPAX/GPAX.dsp [deleted file]
applications/GPAX/GPAX.h [deleted file]
applications/GPAX/GPAX.idl [deleted file]
applications/GPAX/GPAX.rc [deleted file]
applications/GPAX/GPAX.rgs [deleted file]
applications/GPAX/GPAXPlugin.cpp [deleted file]
applications/GPAX/GPAXPlugin.h [deleted file]
applications/GPAX/GPAX_i.c [deleted file]
applications/GPAX/GPAX_p.c [deleted file]
applications/GPAX/GPAXps.def [deleted file]
applications/GPAX/GPAXps.mk [deleted file]
applications/GPAX/StdAfx.cpp [deleted file]
applications/GPAX/StdAfx.h [deleted file]
applications/GPAX/dlldata.c [deleted file]
applications/GPAX/gpax.bmp [deleted file]
applications/GPAX/resource.h [deleted file]
applications/Makefile
applications/generators/MPEG4/main.c
applications/hbbtvplayer/README.txt [new file with mode: 0644]
applications/hbbtvplayer/REQUIREMENT [new file with mode: 0644]
applications/hbbtvplayer/doc/avancement.txt [new file with mode: 0644]
applications/hbbtvplayer/doc/introduction.txt [new file with mode: 0644]
applications/hbbtvplayer/doc/projectmanagement.txt [new file with mode: 0644]
applications/hbbtvplayer/getsources.sh [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/README [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/autogen.sh [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/configure.ac [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/doc/hbbtvBrowserPlugin-NPAPI-20111108.pptx [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/doc/listeOIPFProfile.xlsx [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.pc.in [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.vcproj [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/makefile.am [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/makefile.old [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.cbp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.layout [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/releases/hbbtvbrowserplugin-0.01.tar.gz [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/makefile.am [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.c [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npapi.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npfunctions.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npruntime.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/nptypes.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/autogen.sh [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/configure.ac [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/hbbtv_terminal.vcproj [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/makefile.am [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/makefile.old [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.cbp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.layout [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtv_channel.cpp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtv_demux.cpp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtv_keycontrol.cpp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtv_tools.cpp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.cpp [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.h [new file with mode: 0644]
applications/hbbtvplayer/hbbtvterminal/src/makefile.am [new file with mode: 0644]
applications/hbbtvplayer/install.sh [new file with mode: 0644]
applications/hbbtvplayer/listdependencies [new file with mode: 0644]
applications/hbbtvplayer/projectmanager/codeblocks/hbbtvplayer.workspace [new file with mode: 0644]
applications/m3u82mpd/m3u82mpd.vcproj [new file with mode: 0644]
applications/m3u82mpd/main.c
applications/mp42avi/main.c
applications/mp42ts/main.c
applications/mp42ts/mp42ts.dsp [deleted file]
applications/mp42ts/mp42ts.vcproj [deleted file]
applications/mp4box/filedump.c
applications/mp4box/fileimport.c
applications/mp4box/live.c
applications/mp4box/main.c
applications/mp4client/extract.c
applications/mp4client/main.c
applications/osmo4_ios/Resources/icon.png [new file with mode: 0644]
applications/osmo4_ios/Resources/osmo.icns [new file with mode: 0644]
applications/osmo4_ios/extract.c [new file with mode: 0644]
applications/osmo4_ios/main.c [new file with mode: 0644]
applications/osmo4_ios/osmo4ios-Info.plist [new file with mode: 0644]
applications/osmo4_wx/Darwin.Info.plist [new file with mode: 0644]
applications/osmo4_wx/Darwin.InfoPlist.strings [new file with mode: 0644]
applications/osmo4_wx/Darwin.Osmo.icns [new file with mode: 0644]
applications/osmo4_wx/Makefile [new file with mode: 0644]
applications/osmo4_wx/Playlist.cpp [new file with mode: 0644]
applications/osmo4_wx/Playlist.h [new file with mode: 0644]
applications/osmo4_wx/fileprops.cpp [new file with mode: 0644]
applications/osmo4_wx/fileprops.h [new file with mode: 0644]
applications/osmo4_wx/menubtn.cpp [new file with mode: 0644]
applications/osmo4_wx/menubtn.h [new file with mode: 0644]
applications/osmo4_wx/osmo4.ico [new file with mode: 0644]
applications/osmo4_wx/osmo4.xpm [new file with mode: 0644]
applications/osmo4_wx/playlist.xpm [new file with mode: 0644]
applications/osmo4_wx/resource.h [new file with mode: 0644]
applications/osmo4_wx/toolbar.xpm [new file with mode: 0644]
applications/osmo4_wx/wxGPACControl.cpp [new file with mode: 0644]
applications/osmo4_wx/wxGPACControl.h [new file with mode: 0644]
applications/osmo4_wx/wxOsmo4.cpp [new file with mode: 0644]
applications/osmo4_wx/wxOsmo4.h [new file with mode: 0644]
applications/osmo4_wx/wxOsmo4.rc [new file with mode: 0644]
applications/osmozilla/Makefile [deleted file]
applications/osmozilla/nsIOsmozilla.h [deleted file]
applications/osmozilla/nsIOsmozilla.idl [deleted file]
applications/osmozilla/nsIOsmozilla.xpt_linux [deleted file]
applications/osmozilla/nsIOsmozilla.xpt_w32 [deleted file]
applications/osmozilla/osmo_npapi.cpp [deleted file]
applications/osmozilla/osmo_npapi.h [deleted file]
applications/osmozilla/osmozilla.cpp [deleted file]
applications/osmozilla/osmozilla.def [deleted file]
applications/osmozilla/osmozilla.h [deleted file]
applications/osmozilla/osmozilla.png [deleted file]
applications/osmozilla/osmozilla.rc [deleted file]
applications/osmozilla/readme.txt [deleted file]
applications/osmozilla/resource.h [deleted file]
applications/testapps/broadcaster/Makefile
applications/testapps/broadcaster/broadcaster.c
applications/testapps/broadcaster/sdp_generator.c
applications/testapps/dmbrs/main.c
applications/testapps/mpedemux/main.c
applications/testapps/mpeg2ts/main.c
applications/udptsseg/main.c
bin/w32_rel/Osmo4.ico [deleted file]
bin/w32_rel/nsis_install/gpac_installer.nsi [deleted file]
bin/win32/release/nsis_install/gpac_installer.nsi
configure
doc/configuration.html
doc/man/mp4box.1
doc/man/mp4client.1
extra_lib/include/OpenSVCDecoder/ControlLayer.h [new file with mode: 0644]
extra_lib/include/OpenSVCDecoder/ParseAU.h [new file with mode: 0644]
extra_lib/include/OpenSVCDecoder/SVCDecoder_ietr_api.h [new file with mode: 0644]
extra_lib/include/OpenSVCDecoder/SvcInterface.h [new file with mode: 0644]
extra_lib/include/avcap/CaptureDevice.h [new file with mode: 0644]
extra_lib/include/avcap/CaptureHandler.h [new file with mode: 0644]
extra_lib/include/avcap/CaptureManager.h [new file with mode: 0644]
extra_lib/include/avcap/Connector.h [new file with mode: 0644]
extra_lib/include/avcap/ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/Control_avcap.h [new file with mode: 0644]
extra_lib/include/avcap/DeviceCollector.h [new file with mode: 0644]
extra_lib/include/avcap/DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/IOBuffer.h [new file with mode: 0644]
extra_lib/include/avcap/Interval.h [new file with mode: 0644]
extra_lib/include/avcap/Manager.h [new file with mode: 0644]
extra_lib/include/avcap/ProbeValues.h [new file with mode: 0644]
extra_lib/include/avcap/Tuner_avcap.h [new file with mode: 0644]
extra_lib/include/avcap/avcap-export.h [new file with mode: 0644]
extra_lib/include/avcap/avcap.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_Device.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_Reader.h [new file with mode: 0644]
extra_lib/include/avcap/linux/AVC_VidCapManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_Connector.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_Control.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_Device.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L1_VidCapManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_BoolControl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_ButtonControl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_Connector.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_ControlBase.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_CtrlClassControl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_Device.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_IntControl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_MenuControl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_Tuner.h [new file with mode: 0644]
extra_lib/include/avcap/linux/V4L2_VidCapManager.h [new file with mode: 0644]
extra_lib/include/avcap/linux/error.h [new file with mode: 0644]
extra_lib/include/avcap/linux/frame.h [new file with mode: 0644]
extra_lib/include/avcap/linux/ieee1394io.h [new file with mode: 0644]
extra_lib/include/avcap/linux/ivtv.h [new file with mode: 0644]
extra_lib/include/avcap/linux/pwc-ioctl.h [new file with mode: 0644]
extra_lib/include/avcap/linux/raw1394util.h [new file with mode: 0644]
extra_lib/include/avcap/linux/uvc_compat.h [new file with mode: 0644]
extra_lib/include/avcap/log.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_Control.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_Device.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_DeviceEnumerator.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/osx/QT_VidCapManager.h [new file with mode: 0644]
extra_lib/include/avcap/osx/avcap-config.h [new file with mode: 0644]
extra_lib/include/avcap/singleton.h [new file with mode: 0644]
extra_lib/include/avcap/windows/Crossbar.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_Connector.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_ConnectorManager.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_Control.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_ControlManager.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_Device.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_DeviceDescriptor.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_FormatManager.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_Tuner.h [new file with mode: 0644]
extra_lib/include/avcap/windows/DS_VidCapManager.h [new file with mode: 0644]
extra_lib/include/avcap/windows/FormatNames.h [new file with mode: 0644]
extra_lib/include/avcap/windows/HelpFunc.h [new file with mode: 0644]
extra_lib/include/avcap/windows/SampleGrabberCallback.h [new file with mode: 0644]
gui/extensions/widget_manager/init.js
gui/gui.js
gui/gwlib.js
gui/iphone_wm_gui.js
include/gpac/ait.h [new file with mode: 0644]
include/gpac/avparse.h
include/gpac/carousel.h [deleted file]
include/gpac/config_file.h
include/gpac/constants.h
include/gpac/download.h
include/gpac/dsmcc.h [new file with mode: 0644]
include/gpac/dvb_mpe.h
include/gpac/events.h
include/gpac/events_constants.h [new file with mode: 0644]
include/gpac/internal/bifs_dev.h
include/gpac/internal/bifs_tables.h
include/gpac/internal/compositor_dev.h
include/gpac/internal/dvb_mpe_dev.h
include/gpac/internal/ietf_dev.h
include/gpac/internal/isomedia_dev.h
include/gpac/internal/m3u8.h
include/gpac/internal/mpd.h
include/gpac/internal/scenegraph_dev.h
include/gpac/internal/terminal_dev.h
include/gpac/isomedia.h
include/gpac/list.h
include/gpac/math.h
include/gpac/media_tools.h
include/gpac/mediaobject.h
include/gpac/modules/service.h
include/gpac/mpeg4_odf.h
include/gpac/mpegts.h
include/gpac/nodes_mpeg4.h
include/gpac/path2d.h
include/gpac/scenegraph.h
include/gpac/scenegraph_svg.h
include/gpac/setup.h
include/gpac/terminal.h
include/gpac/thread.h
include/gpac/tools.h
include/gpac/xml.h
modules/Makefile
modules/aac_in/aac_in.c
modules/aac_in/faad_dec.c
modules/ac3_in/ac3_in.c
modules/amr_dec/amr_in.c
modules/amr_float_dec/amr_float_dec.c
modules/avcap/Makefile [new file with mode: 0644]
modules/avcap/avcap.cpp [new file with mode: 0644]
modules/directfb_out/Makefile
modules/directfb_out/directfb_out.c
modules/directfb_out/directfb_out.h
modules/directfb_out/directfb_wrapper.c [new file with mode: 0644]
modules/droid_cam/droid_cam.c [new file with mode: 0644]
modules/droid_mpegv/droid_mpegv.c [new file with mode: 0644]
modules/dummy_in/dummy_in.c
modules/dx_hw/dx_2d.c
modules/dx_hw/dx_audio.c
modules/dx_hw/dx_hw.h
modules/dx_hw/dx_video.c
modules/dx_hw/dx_window.c
modules/ffmpeg_in/ffmpeg_decode.c
modules/ffmpeg_in/ffmpeg_demux.c
modules/ffmpeg_in/ffmpeg_in.h
modules/freenect/Makefile [new file with mode: 0644]
modules/freenect/freenect.c [new file with mode: 0644]
modules/ft_font/ft_font.c
modules/gapi/gapi.cpp
modules/gpac_js/gpac_js.c
modules/hyb_in/Makefile [new file with mode: 0644]
modules/hyb_in/fm_fake_pull.c
modules/hyb_in/fm_fake_push.c
modules/hyb_in/fm_mmbtools.c
modules/hyb_in/hyb_in.c
modules/img_in/img_in.c
modules/img_in/jp2_dec.c
modules/ismacryp/ismacryp.c
modules/isom_in/isom_in.h
modules/isom_in/load.c
modules/isom_in/read.c
modules/isom_in/read_ch.c
modules/libplayer/libplayer.c
modules/mp3_in/mp3_in.c
modules/mpd_in/mpd_in.c
modules/mpegts_in/mpegts_in.c
modules/opencv_is/Makefile
modules/opensvc_dec/Makefile
modules/opensvc_dec/opensvc_dec.c
modules/osd/osd.c
modules/platinum/GPACFileMediaServer.cpp
modules/platinum/GPACPlatinum.cpp
modules/platinum/GenericDevice.cpp
modules/redirect_av/redirect_av.c
modules/rtp_in/rtp_session.c
modules/rtp_in/sdp_fetch.c
modules/rtp_in/sdp_load.c
modules/rvc_dec/Makefile
modules/rvc_dec/rvc_dec.c
modules/saf_in/saf_in.c
modules/sdl_out/video.c
modules/soft_raster/ftgrays.c
modules/soft_raster/rast_soft.h
modules/soft_raster/raster_565.c
modules/soft_raster/raster_argb.c
modules/soft_raster/raster_rgb.c
modules/soft_raster/surface.c
modules/svg_in/svg_in.c
modules/timedtext/timedtext_in.c
modules/ui_rec/ui_rec.c
modules/validator/README.TXT [new file with mode: 0644]
modules/validator/validator.c [new file with mode: 0644]
modules/x11_out/Makefile
modules/x11_out/x11_out.c
modules/xvid_dec/Makefile
regression_tests/bifs/bifs-linking-anchor-mp4-next.bt
regression_tests/bifs/bifs-linking-inline-direct.bt
src/Makefile
src/bifs/bifs_node_tables.c
src/bifs/com_dec.c
src/bifs/com_enc.c
src/bifs/conditional.c
src/bifs/field_decode.c
src/bifs/field_encode.c
src/bifs/memory_decoder.c
src/bifs/script_dec.c
src/compositor/audio_input.c
src/compositor/audio_render.c
src/compositor/camera.c
src/compositor/compositor.c
src/compositor/compositor_2d.c
src/compositor/compositor_node_init.c
src/compositor/drawable.c
src/compositor/events.c
src/compositor/font_engine.c
src/compositor/gl_inc.h
src/compositor/hc_flash_shape.c
src/compositor/mesh.c
src/compositor/mpeg4_audio.c
src/compositor/mpeg4_bitmap.c
src/compositor/mpeg4_form.c
src/compositor/mpeg4_geometry_2d.c
src/compositor/mpeg4_geometry_ifs2d.c
src/compositor/mpeg4_grouping_2d.c
src/compositor/mpeg4_layer_2d.c
src/compositor/mpeg4_layout.c
src/compositor/mpeg4_text.c
src/compositor/mpeg4_textures.c
src/compositor/mpeg4_viewport.c
src/compositor/navigate.c
src/compositor/nodes_stacks.h
src/compositor/svg_geometry.c
src/compositor/svg_grouping.c
src/compositor/svg_media.c
src/compositor/svg_paint_servers.c
src/compositor/texturing.c
src/compositor/texturing_gl.c
src/compositor/visual_manager_2d.c
src/compositor/visual_manager_2d_draw.c
src/compositor/visual_manager_3d.c
src/compositor/visual_manager_3d_gl.c
src/export.cpp
src/ietf/rtcp.c
src/ietf/rtp.c
src/ietf/rtp_depacketizer.c
src/ietf/rtp_packetizer.c
src/ietf/rtp_pck_3gpp.c
src/ietf/rtp_pck_mpeg4.c
src/ietf/rtp_streamer.c
src/ietf/rtsp_common.c
src/isomedia/box_code_3gpp.c
src/isomedia/box_code_base.c
src/isomedia/box_code_isma.c
src/isomedia/box_dump.c
src/isomedia/box_funcs.c
src/isomedia/isom_intern.c
src/isomedia/isom_read.c
src/isomedia/isom_write.c
src/isomedia/media.c
src/isomedia/meta.c
src/isomedia/movie_fragments.c
src/isomedia/stbl_read.c
src/isomedia/stbl_write.c
src/isomedia/track.c
src/laser/lsr_dec.c
src/laser/lsr_enc.c
src/media_tools/ait.c [new file with mode: 0644]
src/media_tools/av_parsers.c
src/media_tools/avilib.c
src/media_tools/carousel.c [deleted file]
src/media_tools/dsmcc.c [new file with mode: 0644]
src/media_tools/dvb.c
src/media_tools/dvb_mpe.c
src/media_tools/filestreamer.c
src/media_tools/img.c
src/media_tools/ismacryp.c
src/media_tools/isom_hinter.c
src/media_tools/isom_tools.c
src/media_tools/m2ts_mux.c
src/media_tools/m3u8.c
src/media_tools/media_export.c
src/media_tools/media_import.c
src/media_tools/mpd.c
src/media_tools/mpegts.c
src/media_tools/text_import.c
src/media_tools/vobsub.c
src/odf/desc_private.c
src/odf/descriptors.c
src/odf/odf_code.c
src/odf/odf_command.c
src/odf/odf_parse.c
src/odf/slc.c
src/scene_manager/encode_isom.c
src/scene_manager/loader_bt.c
src/scene_manager/loader_isom.c
src/scene_manager/loader_qt.c
src/scene_manager/loader_svg.c
src/scene_manager/loader_xmt.c
src/scene_manager/scene_dump.c
src/scene_manager/scene_engine.c
src/scene_manager/scene_manager.c
src/scene_manager/swf_bifs.c
src/scene_manager/swf_parse.c
src/scene_manager/text_to_bifs.c
src/scenegraph/dom_events.c
src/scenegraph/dom_smjs.c
src/scenegraph/mpeg4_nodes.c
src/scenegraph/smil_anim.c
src/scenegraph/smil_timing.c
src/scenegraph/svg_attributes.c
src/scenegraph/svg_smjs.c
src/scenegraph/svg_types.c
src/scenegraph/vrml_proto.c
src/scenegraph/vrml_route.c
src/scenegraph/vrml_smjs.c
src/scenegraph/vrml_tools.c
src/scenegraph/xbl_process.c
src/scenegraph/xml_ns.c
src/terminal/channel.c
src/terminal/clock.c
src/terminal/decoder.c
src/terminal/input_sensor.c
src/terminal/media_control.c
src/terminal/media_manager.c
src/terminal/media_memory.c
src/terminal/media_object.c
src/terminal/media_sensor.c
src/terminal/mpeg4_inline.c
src/terminal/network_service.c
src/terminal/object_browser.c
src/terminal/object_manager.c
src/terminal/scene.c
src/terminal/terminal.c
src/utils/alloc.c
src/utils/bitstream.c
src/utils/cache.c
src/utils/color.c
src/utils/configfile.c
src/utils/downloader.c
src/utils/error.c
src/utils/list.c
src/utils/math.c
src/utils/module.c
src/utils/os_config_init.c
src/utils/os_divers.c
src/utils/os_module.c
src/utils/os_net.c
src/utils/os_thread.c
src/utils/path2d.c
src/utils/xml_parser.c

index a04681a9c93e50fc66d87104d7e334f8b2b61896..1d56214920ceb1cb761f521d45d2ce25d63b1cf3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -64,7 +64,7 @@ install:
        rm -f $(DESTDIR)$(moddir)/nposmozilla.$(DYN_LIB_SUFFIX)
        $(MAKE) installdylib
        $(INSTALL) -d "$(DESTDIR)$(mandir)"
-       $(INSTALL) -d "$(DESTDIR)$(mandir)/man1"
+       $(INSTALL) -d "$(DESTDIR)$(mandir)/man1";
        if [ -d  doc ] ; then \
        $(INSTALL) $(INSTFLAGS) -m 644 doc/man/mp4box.1 $(DESTDIR)$(mandir)/man1/ ; \
        $(INSTALL) $(INSTFLAGS) -m 644 doc/man/mp4client.1 $(DESTDIR)$(mandir)/man1/ ; \
@@ -94,6 +94,7 @@ uninstall:
        rm -rf $(DESTDIR)$(mandir)/man1/mp4client.1
        rm -rf $(DESTDIR)$(mandir)/man1/gpac.1
        rm -rf $(DESTDIR)$(prefix)/share/gpac
+       rm -rf $(DESTDIR)$(prefix)/include/gpac
 
 installdylib:
 ifeq ($(CONFIG_WIN32),yes)
diff --git a/applications/GPAX/GPAX.cpp b/applications/GPAX/GPAX.cpp
deleted file mode 100644 (file)
index 97c8f11..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// GPAX.cpp : Implementation of DLL Exports.
-
-
-// Note: Proxy/Stub Information
-//      To build a separate proxy/stub DLL, 
-//      run nmake -f GPAXps.mk in the project directory.
-
-#include "stdafx.h"
-#include "resource.h"
-#include <initguid.h>
-#include "GPAX.h"
-
-#include "GPAX_i.c"
-#include "GPAXPlugin.h"
-
-
-CComModule _Module;
-
-BEGIN_OBJECT_MAP(ObjectMap)
-OBJECT_ENTRY(CLSID_GPAX, CGPAXPlugin)
-END_OBJECT_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// DLL Entry Point
-
-extern "C"
-#ifdef _WIN32_WCE
-BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
-#else
-BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
-#endif
-{
-    if (dwReason == DLL_PROCESS_ATTACH)
-    {
-        _Module.Init(ObjectMap, (HINSTANCE) hInstance, &LIBID_GPAXLib);
-        DisableThreadLibraryCalls((HINSTANCE) hInstance);
-    }
-    else if (dwReason == DLL_PROCESS_DETACH)
-        _Module.Term();
-    return TRUE;    // ok
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Used to determine whether the DLL can be unloaded by OLE
-
-STDAPI DllCanUnloadNow(void)
-{
-    return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Returns a class factory to create an object of the requested type
-
-STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
-{
-    return _Module.GetClassObject(rclsid, riid, ppv);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// DllRegisterServer - Adds entries to the system registry
-
-STDAPI DllRegisterServer(void)
-{
-    // registers object, typelib and all interfaces in typelib
-    return _Module.RegisterServer(TRUE);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// DllUnregisterServer - Removes entries from the system registry
-
-STDAPI DllUnregisterServer(void)
-{
-    return _Module.UnregisterServer(TRUE);
-}
-
-
diff --git a/applications/GPAX/GPAX.def b/applications/GPAX/GPAX.def
deleted file mode 100644 (file)
index f61476d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-; GPAX.def : Declares the module parameters.
-
-LIBRARY      "GPAX.dll"
-
-EXPORTS
-       DllCanUnloadNow     PRIVATE
-       DllGetClassObject   PRIVATE
-       DllRegisterServer   PRIVATE
-       DllUnregisterServer     PRIVATE
diff --git a/applications/GPAX/GPAX.dsp b/applications/GPAX/GPAX.dsp
deleted file mode 100644 (file)
index ac3d1a3..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-# Microsoft Developer Studio Project File - Name="GPAX" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=GPAX - Win32 Release\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "GPAX.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "GPAX.mak" CFG="GPAX - Win32 Release"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "GPAX - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "GPAX - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "GPAX - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "obj/w32_deb"\r
-# PROP Intermediate_Dir "obj/w32_deb"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /Yu"stdafx.h" /FD /GZ /c\r
-# ADD BASE RSC /l 0x804 /d "_DEBUG"\r
-# ADD RSC /l 0x804 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 js32.lib zlib.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/w32_deb/GPAX.dll" /pdbtype:sept /libpath:"../../extra_lib/lib/w32_deb"\r
-# Begin Custom Build - Performing registration\r
-OutDir=.\obj/w32_deb\r
-TargetPath=\CVS\gpac\bin\w32_deb\GPAX.dll\r
-InputPath=\CVS\gpac\bin\w32_deb\GPAX.dll\r
-SOURCE="$(InputPath)"\r
-\r
-"$(OutDir)\regsvr32.trg" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
-       regsvr32 /s /c "$(TargetPath)" \r
-       echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg" \r
-       \r
-# End Custom Build\r
-\r
-!ELSEIF  "$(CFG)" == "GPAX - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "obj/w32_rel"\r
-# PROP BASE Intermediate_Dir "obj/w32_rel"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "obj/w32_rel"\r
-# PROP Intermediate_Dir "obj/w32_rel"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /Yu"stdafx.h" /FD /GZ /c\r
-# ADD CPP /nologo /MD /W3 /Gm /ZI /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /Yu"stdafx.h" /FD /GZ /c\r
-# SUBTRACT CPP /O<none>\r
-# ADD BASE RSC /l 0x804 /d "_DEBUG"\r
-# ADD RSC /l 0x804 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 js32.lib zlib.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"../gpac/extra_lib/lib/w32_deb"\r
-# ADD LINK32 js32.lib zlib.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/w32_rel/GPAX.dll" /pdbtype:sept /libpath:"../../extra_lib/lib/w32_rel"\r
-# Begin Special Build Tool\r
-SOURCE="$(InputPath)"\r
-PostBuild_Cmds=copy ..\..\bin\w32_rel\GPAX.dll "C:\Program Files\GPAC"\r
-# End Special Build Tool\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "GPAX - Win32 Debug"\r
-# Name "GPAX - Win32 Release"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAX.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAX.def\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAX.idl\r
-# ADD MTL /tlb ".\GPAX.tlb" /h "GPAX.h" /iid "GPAX_i.c" /Oicf\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAX.rc\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAXPlugin.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\StdAfx.cpp\r
-# ADD CPP /Yc"stdafx.h"\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAXPlugin.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\Resource.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\StdAfx.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# Begin Source File\r
-\r
-SOURCE=.\gpax.bmp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAX.rgs\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\GPAXProp.rgs\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
-# Section GPAX : {00000000-0000-0000-0000-800000800000}\r
-#      1:21:IDS_DOCSTRINGGPAXProp:105\r
-#      1:12:IDD_GPAXPROP:107\r
-#      1:12:IDR_GPAXPROP:106\r
-#      1:20:IDS_HELPFILEGPAXProp:104\r
-#      1:17:IDS_TITLEGPAXProp:103\r
-# End Section\r
diff --git a/applications/GPAX/GPAX.h b/applications/GPAX/GPAX.h
deleted file mode 100644 (file)
index c38c76d..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-
-#pragma warning( disable: 4049 )  /* more than 64k source lines */
-
-/* this ALWAYS GENERATED file contains the definitions for the interfaces */
-
-
- /* File created by MIDL compiler version 5.03.0286 */
-/* at Thu Jul 20 19:14:15 2006
- */
-/* Compiler settings for \CVS\gpac\applications\GPAX\GPAX.idl:
-    Oicf (OptLev=i2), W1, Zp8, env=Win32 (32b run), ms_ext, c_ext
-    error checks: allocation ref bounds_check enum stub_data 
-    VC __declspec() decoration level: 
-         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
-         DECLSPEC_UUID(), MIDL_INTERFACE()
-*/
-//@@MIDL_FILE_HEADING(  )
-
-
-/* verify that the <rpcndr.h> version is high enough to compile this file*/
-#ifndef __REQUIRED_RPCNDR_H_VERSION__
-#define __REQUIRED_RPCNDR_H_VERSION__ 440
-#endif
-
-#include "rpc.h"
-#include "rpcndr.h"
-
-#ifndef __GPAX_h__
-#define __GPAX_h__
-
-/* Forward Declarations */ 
-
-#ifndef __IGPAX_FWD_DEFINED__
-#define __IGPAX_FWD_DEFINED__
-typedef interface IGPAX IGPAX;
-#endif         /* __IGPAX_FWD_DEFINED__ */
-
-
-#ifndef __IGPAXEvents_FWD_DEFINED__
-#define __IGPAXEvents_FWD_DEFINED__
-typedef interface IGPAXEvents IGPAXEvents;
-#endif         /* __IGPAXEvents_FWD_DEFINED__ */
-
-
-#ifndef __GPAX_FWD_DEFINED__
-#define __GPAX_FWD_DEFINED__
-
-#ifdef __cplusplus
-typedef class GPAX GPAX;
-#else
-typedef struct GPAX GPAX;
-#endif /* __cplusplus */
-
-#endif         /* __GPAX_FWD_DEFINED__ */
-
-
-/* header files for imported files */
-#include "oaidl.h"
-#include "ocidl.h"
-
-#ifdef __cplusplus
-extern "C"{
-#endif 
-
-void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
-void __RPC_USER MIDL_user_free( void __RPC_FAR * ); 
-
-
-#ifndef __GPAXLib_LIBRARY_DEFINED__
-#define __GPAXLib_LIBRARY_DEFINED__
-
-/* library GPAXLib */
-/* [helpstring][version][uuid] */ 
-
-
-
-#define        DISPID_SRC      ( 100 )
-
-#define        DISPID_AutoStart        ( 101 )
-
-#define        DISPID_PlayEvent        ( 100 )
-
-#define        DISPID_PauseEvent       ( 101 )
-
-#define        DISPID_StopEvent        ( 102 )
-
-
-EXTERN_C const IID LIBID_GPAXLib;
-
-#ifndef __IGPAX_INTERFACE_DEFINED__
-#define __IGPAX_INTERFACE_DEFINED__
-
-/* interface IGPAX */
-/* [object][oleautomation][hidden][dual][helpstring][uuid] */ 
-
-
-EXTERN_C const IID IID_IGPAX;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-    
-    MIDL_INTERFACE("E2A9A937-BB35-47E0-8942-964806299AB4")
-    IGPAX : public IDispatch
-    {
-    public:
-        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0;
-        
-        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0;
-        
-        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0;
-        
-        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Update( 
-            /* [in] */ BSTR mtype,
-            /* [in] */ BSTR updates) = 0;
-        
-        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_src( 
-            /* [retval][out] */ BSTR __RPC_FAR *url) = 0;
-        
-        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_src( 
-            /* [in] */ BSTR url) = 0;
-        
-        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AutoStart( 
-            /* [retval][out] */ VARIANT_BOOL __RPC_FAR *autoplay) = 0;
-        
-        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AutoStart( 
-            /* [in] */ VARIANT_BOOL autoplay) = 0;
-        
-    };
-    
-#else  /* C style interface */
-
-    typedef struct IGPAXVtbl
-    {
-        BEGIN_INTERFACE
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ REFIID riid,
-            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
-        
-        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( 
-            IGPAX __RPC_FAR * This);
-        
-        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( 
-            IGPAX __RPC_FAR * This);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )( 
-            IGPAX __RPC_FAR * This,
-            /* [out] */ UINT __RPC_FAR *pctinfo);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ UINT iTInfo,
-            /* [in] */ LCID lcid,
-            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ REFIID riid,
-            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
-            /* [in] */ UINT cNames,
-            /* [in] */ LCID lcid,
-            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
-        
-        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ DISPID dispIdMember,
-            /* [in] */ REFIID riid,
-            /* [in] */ LCID lcid,
-            /* [in] */ WORD wFlags,
-            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
-            /* [out] */ VARIANT __RPC_FAR *pVarResult,
-            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
-            /* [out] */ UINT __RPC_FAR *puArgErr);
-        
-        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Play )( 
-            IGPAX __RPC_FAR * This);
-        
-        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Pause )( 
-            IGPAX __RPC_FAR * This);
-        
-        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Stop )( 
-            IGPAX __RPC_FAR * This);
-        
-        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Update )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ BSTR mtype,
-            /* [in] */ BSTR updates);
-        
-        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_src )( 
-            IGPAX __RPC_FAR * This,
-            /* [retval][out] */ BSTR __RPC_FAR *url);
-        
-        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_src )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ BSTR url);
-        
-        /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_AutoStart )( 
-            IGPAX __RPC_FAR * This,
-            /* [retval][out] */ VARIANT_BOOL __RPC_FAR *autoplay);
-        
-        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *put_AutoStart )( 
-            IGPAX __RPC_FAR * This,
-            /* [in] */ VARIANT_BOOL autoplay);
-        
-        END_INTERFACE
-    } IGPAXVtbl;
-
-    interface IGPAX
-    {
-        CONST_VTBL struct IGPAXVtbl __RPC_FAR *lpVtbl;
-    };
-
-    
-
-#ifdef COBJMACROS
-
-
-#define IGPAX_QueryInterface(This,riid,ppvObject)      \
-    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
-
-#define IGPAX_AddRef(This)     \
-    (This)->lpVtbl -> AddRef(This)
-
-#define IGPAX_Release(This)    \
-    (This)->lpVtbl -> Release(This)
-
-
-#define IGPAX_GetTypeInfoCount(This,pctinfo)   \
-    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
-
-#define IGPAX_GetTypeInfo(This,iTInfo,lcid,ppTInfo)    \
-    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
-
-#define IGPAX_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)  \
-    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
-
-#define IGPAX_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)    \
-    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
-
-
-#define IGPAX_Play(This)       \
-    (This)->lpVtbl -> Play(This)
-
-#define IGPAX_Pause(This)      \
-    (This)->lpVtbl -> Pause(This)
-
-#define IGPAX_Stop(This)       \
-    (This)->lpVtbl -> Stop(This)
-
-#define IGPAX_Update(This,mtype,updates)       \
-    (This)->lpVtbl -> Update(This,mtype,updates)
-
-#define IGPAX_get_src(This,url)        \
-    (This)->lpVtbl -> get_src(This,url)
-
-#define IGPAX_put_src(This,url)        \
-    (This)->lpVtbl -> put_src(This,url)
-
-#define IGPAX_get_AutoStart(This,autoplay)     \
-    (This)->lpVtbl -> get_AutoStart(This,autoplay)
-
-#define IGPAX_put_AutoStart(This,autoplay)     \
-    (This)->lpVtbl -> put_AutoStart(This,autoplay)
-
-#endif /* COBJMACROS */
-
-
-#endif         /* C style interface */
-
-
-
-/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGPAX_Play_Proxy( 
-    IGPAX __RPC_FAR * This);
-
-
-void __RPC_STUB IGPAX_Play_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGPAX_Pause_Proxy( 
-    IGPAX __RPC_FAR * This);
-
-
-void __RPC_STUB IGPAX_Pause_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGPAX_Stop_Proxy( 
-    IGPAX __RPC_FAR * This);
-
-
-void __RPC_STUB IGPAX_Stop_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGPAX_Update_Proxy( 
-    IGPAX __RPC_FAR * This,
-    /* [in] */ BSTR mtype,
-    /* [in] */ BSTR updates);
-
-
-void __RPC_STUB IGPAX_Update_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IGPAX_get_src_Proxy( 
-    IGPAX __RPC_FAR * This,
-    /* [retval][out] */ BSTR __RPC_FAR *url);
-
-
-void __RPC_STUB IGPAX_get_src_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IGPAX_put_src_Proxy( 
-    IGPAX __RPC_FAR * This,
-    /* [in] */ BSTR url);
-
-
-void __RPC_STUB IGPAX_put_src_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IGPAX_get_AutoStart_Proxy( 
-    IGPAX __RPC_FAR * This,
-    /* [retval][out] */ VARIANT_BOOL __RPC_FAR *autoplay);
-
-
-void __RPC_STUB IGPAX_get_AutoStart_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IGPAX_put_AutoStart_Proxy( 
-    IGPAX __RPC_FAR * This,
-    /* [in] */ VARIANT_BOOL autoplay);
-
-
-void __RPC_STUB IGPAX_put_AutoStart_Stub(
-    IRpcStubBuffer *This,
-    IRpcChannelBuffer *_pRpcChannelBuffer,
-    PRPC_MESSAGE _pRpcMessage,
-    DWORD *_pdwStubPhase);
-
-
-
-#endif         /* __IGPAX_INTERFACE_DEFINED__ */
-
-
-#ifndef __IGPAXEvents_DISPINTERFACE_DEFINED__
-#define __IGPAXEvents_DISPINTERFACE_DEFINED__
-
-/* dispinterface IGPAXEvents */
-/* [helpstring][uuid] */ 
-
-
-EXTERN_C const IID DIID_IGPAXEvents;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-
-    MIDL_INTERFACE("1FDA32FC-4C9A-461F-B33B-0715B0343006")
-    IGPAXEvents : public IDispatch
-    {
-    };
-    
-#else  /* C style interface */
-
-    typedef struct IGPAXEventsVtbl
-    {
-        BEGIN_INTERFACE
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( 
-            IGPAXEvents __RPC_FAR * This,
-            /* [in] */ REFIID riid,
-            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
-        
-        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( 
-            IGPAXEvents __RPC_FAR * This);
-        
-        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( 
-            IGPAXEvents __RPC_FAR * This);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )( 
-            IGPAXEvents __RPC_FAR * This,
-            /* [out] */ UINT __RPC_FAR *pctinfo);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )( 
-            IGPAXEvents __RPC_FAR * This,
-            /* [in] */ UINT iTInfo,
-            /* [in] */ LCID lcid,
-            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
-        
-        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )( 
-            IGPAXEvents __RPC_FAR * This,
-            /* [in] */ REFIID riid,
-            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
-            /* [in] */ UINT cNames,
-            /* [in] */ LCID lcid,
-            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
-        
-        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )( 
-            IGPAXEvents __RPC_FAR * This,
-            /* [in] */ DISPID dispIdMember,
-            /* [in] */ REFIID riid,
-            /* [in] */ LCID lcid,
-            /* [in] */ WORD wFlags,
-            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
-            /* [out] */ VARIANT __RPC_FAR *pVarResult,
-            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
-            /* [out] */ UINT __RPC_FAR *puArgErr);
-        
-        END_INTERFACE
-    } IGPAXEventsVtbl;
-
-    interface IGPAXEvents
-    {
-        CONST_VTBL struct IGPAXEventsVtbl __RPC_FAR *lpVtbl;
-    };
-
-    
-
-#ifdef COBJMACROS
-
-
-#define IGPAXEvents_QueryInterface(This,riid,ppvObject)        \
-    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
-
-#define IGPAXEvents_AddRef(This)       \
-    (This)->lpVtbl -> AddRef(This)
-
-#define IGPAXEvents_Release(This)      \
-    (This)->lpVtbl -> Release(This)
-
-
-#define IGPAXEvents_GetTypeInfoCount(This,pctinfo)     \
-    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
-
-#define IGPAXEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo)      \
-    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
-
-#define IGPAXEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)    \
-    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
-
-#define IGPAXEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)      \
-    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
-
-#endif /* COBJMACROS */
-
-
-#endif         /* C style interface */
-
-
-#endif         /* __IGPAXEvents_DISPINTERFACE_DEFINED__ */
-
-
-EXTERN_C const CLSID CLSID_GPAX;
-
-#ifdef __cplusplus
-
-class DECLSPEC_UUID("181D18E6-4DC1-4B55-B72E-BE2A10064995")
-GPAX;
-#endif
-#endif /* __GPAXLib_LIBRARY_DEFINED__ */
-
-/* Additional Prototypes for ALL interfaces */
-
-/* end of Additional Prototypes */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
diff --git a/applications/GPAX/GPAX.idl b/applications/GPAX/GPAX.idl
deleted file mode 100644 (file)
index 922910f..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// GPAX.idl : IDL source for GPAX.dll
-//
-
-// This file will be processed by the MIDL tool to
-// produce the type library (GPAX.tlb) and marshalling code.
-
-import "oaidl.idl";
-import "ocidl.idl";
-#include "olectl.h"
-       
-
-[
-       uuid(E64FAC7F-0134-4A75-A7DA-80D53EBC56A6),
-       version(1.0),
-       helpstring("GPAX ActiveX Control")
-]
-
-library GPAXLib
-{
-       importlib("stdole2.tlb");
-
-    // Forward declare all types defined in this typelib
-    interface IGPAX;
-    dispinterface IGPAXEvents;
-
-    const int DISPID_SRC        = 100;
-    const int DISPID_AutoStart  = 101;
-
-
-       //IDispatch interface
-       [
-               odl,
-               uuid(E2A9A937-BB35-47E0-8942-964806299AB4),
-               helpstring("GPAC ActiveX Control"),
-               dual,
-               hidden,
-               oleautomation
-       ]
-       interface IGPAX : IDispatch
-       {
-               /*functions*/
-               [helpstring("Play Movie")] HRESULT Play();
-               [helpstring("Pause/Resume Movie")] HRESULT Pause();
-               [helpstring("Stop Movie")] HRESULT Stop();
-               [helpstring("Update Scene")] HRESULT Update([in] BSTR mtype, [in] BSTR updates);
-
-
-               /*properties*/
-        [id(DISPID_SRC), propget, helpstring("Get/Set the media source")]
-        HRESULT src([out, retval] BSTR* url);
-        [id(DISPID_SRC), propput, helpstring("Get/Set the media source")]
-        HRESULT src([in] BSTR url);
-
-        [id(DISPID_AutoStart), propget, helpstring("Get/Set automatic playback upon load")]
-        HRESULT AutoStart([out, retval] VARIANT_BOOL* autoplay);
-        [id(DISPID_AutoStart), propput, helpstring("Get/Set automatic playback upon load")]
-        HRESULT AutoStart([in] VARIANT_BOOL autoplay);
-       };
-
-
-       //event interface
-       [
-               uuid(1FDA32FC-4C9A-461F-B33B-0715B0343006),
-               helpstring("GPAX Control Events")
-       ]
-       dispinterface IGPAXEvents
-       {
-               properties:
-               methods:
-       };
-
-
-       //AX control
-       [
-               uuid(181D18E6-4DC1-4B55-B72E-BE2A10064995),
-               helpstring("GPAC Control"),
-               control
-       ]
-       coclass GPAX
-       {
-               [default] interface IGPAX;
-               [default, source] dispinterface IGPAXEvents;
-       };
-};
diff --git a/applications/GPAX/GPAX.rc b/applications/GPAX/GPAX.rc
deleted file mode 100644 (file)
index 9ba86a4..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Chinese (P.R.C.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
-#ifdef _WIN32
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
-#pragma code_page(936)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""winres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "1 TYPELIB ""GPAX.tlb""\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // Chinese (P.R.C.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-            VALUE "Comments", "\0"
-            VALUE "CompanyName", "ENST\0"
-            VALUE "FileDescription", "GPAX\0"
-            VALUE "FileVersion", "0.4.5\0"
-            VALUE "InternalName", "GPAX\0"
-            VALUE "LegalCopyright", "Copyright Â© 2007\0"
-            VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "GPAX.dll\0"
-            VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "ENST GPAX\0"
-            VALUE "ProductVersion", "0.4.5\0"
-            VALUE "SpecialBuild", "\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // !_MAC
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Bitmap
-//
-
-IDB_GPAXPLUGIN          BITMAP  DISCARDABLE     "gpax.bmp"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// REGISTRY
-//
-
-IDR_GPAXPLUGIN          REGISTRY DISCARDABLE    "GPAX.rgs"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// String Table
-//
-
-STRINGTABLE DISCARDABLE 
-BEGIN
-    IDS_PROJNAME            "GPAX"
-    IDS_TITLEGPAXProp       "&GPAX"
-    IDS_HELPFILEGPAXProp    "Help File Name"
-    IDS_DOCSTRINGGPAXProp   "URLs setting"
-END
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-1 TYPELIB "GPAX.tlb"
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/applications/GPAX/GPAX.rgs b/applications/GPAX/GPAX.rgs
deleted file mode 100644 (file)
index 2949a85..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-HKCR
-{
-       ForceRemove '.aac'
-       {
-               val 'Content Type' = s 'audio/aac'
-       }
-       ForceRemove '.amr'
-       {
-               val 'Content Type' = s 'audio/amr'
-       }
-       ForceRemove '.mp4'
-       {
-               val 'Content Type' = s 'application/mp4'
-       }
-       ForceRemove '.3gp'
-       {
-               val 'Content Type' = s 'video/3gpp'
-       }
-       ForceRemove '.3g2'
-       {
-               val 'Content Type' = s 'video/3gpp2'
-       }
-       ForceRemove '.wrl'
-       {
-               val 'Content Type' = s 'model/vrml'
-       }
-       ForceRemove '.x3dv'
-       {
-               val 'Content Type' = s 'model/x3d+vrml'
-       }
-       ForceRemove '.x3d'
-       {
-               val 'Content Type' = s 'model/x3d+xml'
-       }
-       ForceRemove '.svg'
-       {
-               val 'Content Type' = s 'image/svg+xml'
-       }
-       ForceRemove '.sdp'
-       {
-               val 'Content Type' = s 'application/sdp'
-       }
-       
-       GPAX.GPAXPlugin.1 = s 'GPAC ActiveX'
-       {
-               CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-       }
-       GPAX.GPAXPlugin = s 'GPAC ActiveX'
-       {
-               CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-               CurVer = s 'GPAX.GPAXPlugin.1'
-       }
-       NoRemove CLSID
-       {
-               ForceRemove {181D18E6-4DC1-4B55-B72E-BE2A10064995} = s 'GPAC ActiveX'
-               {
-                       ProgID = s 'GPAX.GPAXPlugin.1'
-                       VersionIndependentProgID = s 'GPAX.GPAXPlugin'
-                       ForceRemove 'Programmable'
-                       InprocServer32 = s '%MODULE%'
-                       {
-                               val ThreadingModel = s 'Both'
-                       }
-                       ForceRemove 'Control'
-                       ForceRemove 'Insertable'
-                       ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 101'
-                       'MiscStatus' = s '0'
-                       {
-                           '1' = s '131473'
-                       }
-                       'TypeLib' = s '{E64FAC7F-0134-4A75-A7DA-80D53EBC56A6}'
-                       'Version' = s '1.0'
-                ForceRemove 'EnableFullPage'
-                    {
-                               ForceRemove .mp4
-                               ForceRemove .3gp
-                               ForceRemove .3g2
-                               ForceRemove .wrl
-                               ForceRemove .x3d
-                               ForceRemove .x3dv
-                               ForceRemove .svg
-                }
-               }
-       }
-
-       NoRemove MIME
-       {
-               NoRemove Database
-               {
-                       NoRemove 'Content Type'
-                       {
-                               'application/x-gpac'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.gpac'
-                               }
-                               'application/mp4'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.mp4'
-                               }
-                               'application/sdp'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.sdp'
-                               }
-                               'audio/aac'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.aac'
-                               }
-                               'audio/amr'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.amr'
-                               }
-                               'audio/mp4'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.mp4'
-                               }
-                               'audio/mpeg'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.mp3'
-                               }
-                               'image/svg+xml'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.svg'
-                               }
-                               'model/vrml'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.wrl'
-                               }
-                               'model/x3d+vrml'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.x3dv'
-                               }
-                               'model/x3d+xml'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.x3d'
-                               }
-                               'video/mp4'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.mp4'
-                               }
-                               'video/3gpp'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.3gp'
-                               }
-                               'video/3gpp2'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.3g2'
-                               }
-                               'video/avi'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.avi'
-                               }
-                               'video/mpeg'
-                               {
-                                       val CLSID = s '{181D18E6-4DC1-4B55-B72E-BE2A10064995}'
-                                       val Extension = s '.mpg'
-                               }
-                       }
-               }
-       }
-}
diff --git a/applications/GPAX/GPAXPlugin.cpp b/applications/GPAX/GPAXPlugin.cpp
deleted file mode 100644 (file)
index d37e823..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- *                     GPAC - Multimedia Framework C SDK
- *
- *                     Authors: Y.XI, X. ZHAO, J. Le Feuvre
- *                     Copyright (c) ENST 2006-200x
- *                                     All rights reserved
- *
- *  This file is part of GPAC / ActiveX control
- *
- *  GPAC is gf_free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  GPAC 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 Lesser General Public License for more details.
- *   
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *             
- */
-
-#include "stdafx.h"
-#include "GPAX.h"
-#include "GPAXPlugin.h"
-#include <gpac/network.h>
-#include <gpac/utf.h>
-#include <shlobj.h>
-
-#ifndef _WIN32_WCE
-#include <direct.h>
-#include <mshtml.h>
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CGPAXPlugin
-
-#if 0
-static print_err(char *msg, char *title)
-{
-       u16 w_msg[1024], w_title[1024];
-       CE_CharToWide(msg, w_msg);
-       CE_CharToWide(title, w_title);
-       ::MessageBox(NULL, w_msg, w_title, MB_OK);
-}
-#endif
-
-
-void CGPAXPlugin::SetStatusText(char *msg)
-{
-#ifndef _WIN32_WCE
-       if (m_pBrowser) {
-               if (msg) {
-                       u16 w_msg[1024];
-                       gf_utf8_mbstowcs(w_msg, 1024, (const char **)&msg);
-                       m_pBrowser->put_StatusText((BSTR) w_msg);
-               } else {
-                       m_pBrowser->put_StatusText(L"");
-               }
-       }
-#endif
-}
-//GPAC player Event Handler. not yet implemented, just dummies here
-Bool CGPAXPlugin::EventProc(GF_Event *evt)
-{
-       char msg[1024];
-       if (!m_term) return 0;
-
-    switch (evt->type) {
-       case GF_EVENT_MESSAGE:
-               if (evt->message.error) {
-                       sprintf(msg, "(GPAC) %s (%s)", evt->message.message, gf_error_to_string(evt->message.error));
-               } else {
-                       sprintf(msg, "(GPAC) %s", evt->message.message);
-               }
-               SetStatusText(msg);
-        break;
-       case GF_EVENT_PROGRESS:
-               if (evt->progress.done == evt->progress.total) {
-                       SetStatusText(NULL);
-               } else {
-                       char *szTitle = "";
-                       if (evt->progress.progress_type==0) szTitle = "Buffer ";
-                       else if (evt->progress.progress_type==1) szTitle = "Download ";
-                       else if (evt->progress.progress_type==2) szTitle = "Import ";
-                       sprintf(msg, "(GPAC) %s: %02.2f", szTitle, (100.0*evt->progress.done) / evt->progress.total);
-                       SetStatusText(msg);
-               }
-               break;
-    case GF_EVENT_CONNECT:
-        m_bIsConnected = evt->connect.is_connected;
-        break;
-       /*IGNORE any scene size, just work with the size allocated in the parent doc*/
-       case GF_EVENT_SCENE_SIZE:
-        gf_term_set_size(m_term, m_width, m_height);
-        break;
-       /*window has been resized (full-screen plugin), resize*/
-       case GF_EVENT_SIZE:
-               m_width = evt->size.width;
-               m_height = evt->size.height;
-        gf_term_set_size(m_term, m_width, m_height);
-        break;
-       case GF_EVENT_DBLCLICK:
-               gf_term_set_option(m_term, GF_OPT_FULLSCREEN, !gf_term_get_option(m_term, GF_OPT_FULLSCREEN));
-               break;
-       case GF_EVENT_KEYDOWN:
-               if ((evt->key.flags  & GF_KEY_MOD_ALT)) {
-           } else {
-                       switch (evt->key.key_code) {
-                       case GF_KEY_HOME:
-                               gf_term_set_option(m_term, GF_OPT_NAVIGATION_TYPE, 1);
-                               break;
-                       case GF_KEY_ESCAPE:
-                               gf_term_set_option(m_term, GF_OPT_FULLSCREEN, !gf_term_get_option(m_term, GF_OPT_FULLSCREEN));
-                               break;
-                       }
-               }
-           break;
-       case GF_EVENT_NAVIGATE_INFO:
-               strcpy(msg, evt->navigate.to_url);
-               SetStatusText(msg);
-               break;
-       case GF_EVENT_NAVIGATE:
-               if (gf_term_is_supported_url(m_term, evt->navigate.to_url, 1, 1)) {
-                       gf_term_navigate_to(m_term, evt->navigate.to_url);
-                       return 1;
-               } 
-#ifndef _WIN32_WCE
-               else if (m_pBrowser) {
-                       u32 i;
-                       const char **sz_ptr;
-                       u16 w_szTar[1024], w_szURL[1024];
-                       VARIANT target, flags;
-                       flags.intVal = 0;
-                       target.bstrVal = L"_SELF";
-
-                       for (i=0; i<evt->navigate.param_count; i++) {
-                               if (!strcmp(evt->navigate.parameters[i], "_parent")) target.bstrVal = L"_PARENT";
-                               else if (!strcmp(evt->navigate.parameters[i], "_blank")) target.bstrVal = L"_BLANK";
-                               else if (!strcmp(evt->navigate.parameters[i], "_top")) target.bstrVal = L"_TOP";
-                               else if (!strcmp(evt->navigate.parameters[i], "_new")) flags.intVal |= navOpenInNewWindow;
-                               else if (!strnicmp(evt->navigate.parameters[i], "_target=", 8)) {
-                                       sz_ptr = & evt->navigate.parameters[i]+8;
-                                       gf_utf8_mbstowcs(w_szTar, 1024, (const char **)sz_ptr);
-                                       target.bstrVal = (BSTR) w_szTar;
-                               }
-                       }
-                       sz_ptr = & evt->navigate.to_url;
-                       gf_utf8_mbstowcs(w_szURL, 1024, (const char **)sz_ptr);
-                       m_pBrowser->Navigate((BSTR) w_szURL, &flags, &target, NULL, NULL);;
-                       return 1;
-               }
-#endif
-               break;
-    }
-    return 0;
-}
-
-Bool GPAX_EventProc(void *ptr, GF_Event *evt)
-{
-    CGPAXPlugin *_this = (CGPAXPlugin *)ptr;
-    return _this->EventProc(evt);
-}
-
-//Read Parameters from pPropBag given by MSIE
-Bool CGPAXPlugin::ReadParamString(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
-                                 WCHAR *name, char *buf, int bufsize)
-{
-    VARIANT v;
-    HRESULT hr;
-    Bool retval=0;
-
-    v.vt = VT_EMPTY;
-    v.bstrVal = NULL;
-    hr = pPropBag->Read(name, &v, pErrorLog);
-    if(SUCCEEDED(hr))
-    {
-        if(v.vt==VT_BSTR && v.bstrVal)
-        {
-//            USES_CONVERSION;
-//            lstrcpyn(buf,OLE2T(v.bstrVal),bufsize);
-                       const u16 *srcp = (const u16 *) v.bstrVal;
-                       u32 len = gf_utf8_wcstombs(buf, bufsize, &srcp);
-                       if (len>=0) {
-                               buf[len] = 0;
-                               retval=1;
-                       }
-        }
-        VariantClear(&v);
-    }
-    return retval;
-}
-
-void CGPAXPlugin::LoadDATAUrl()
-{
-#ifndef _WIN32_WCE
-       HRESULT hr;
-
-       if (m_url[0]) return;
-    /*get parent doc*/
-       CComPtr<IOleContainer> spContainer;
-       if (m_spClientSite->GetContainer(&spContainer) != S_OK)
-               return;
-    CComPtr<IHTMLDocument2> spDoc = CComQIPtr<IHTMLDocument2>(spContainer);
-    CComPtr<IHTMLElementCollection> spColl;
-       if (spDoc->get_all(&spColl) != S_OK)
-               return;
-       /*get HTML <object> in the doc*/
-    CComPtr<IDispatch> spDisp;
-       CComPtr<IHTMLElementCollection> sphtmlObjects;
-
-    CComPtr<IDispatch> spDispObjects;
-       if (spColl->tags(CComVariant("OBJECT"), &spDispObjects) != S_OK)
-               return;
-    CComPtr<IHTMLElementCollection> spObjs = CComQIPtr<IHTMLElementCollection>(spDispObjects);
-       
-       /*browse all objects and find us*/
-       long lCount = 0;
-       spObjs->get_length(&lCount);
-       for (long lCnt = 0; lCnt < lCount; lCnt++) {   
-               IDispatch *an_obj= NULL;
-               CComVariant varEmpty;
-               CComVariant varName;
-               varName.vt = VT_I4;
-               varName.lVal = lCnt;
-               hr = spObjs->item(varName, varEmpty, &an_obj);
-               varName.Clear();
-               varEmpty.Clear();
-               if (hr != S_OK) continue;
-
-               /*get the IHTMLObject*/
-               IHTMLObjectElement* pObjectElem=NULL;
-               an_obj->QueryInterface(IID_IHTMLObjectElement, (void**)&pObjectElem);
-               if (!pObjectElem) continue;
-
-               /*get its parent owner - it MUST be us*/
-               IDispatch *disp= NULL;
-               pObjectElem->get_object(&disp);
-               if (disp != this) continue;
-
-               BSTR data = NULL;
-               if ((pObjectElem->get_data(&data) == S_OK) && data) {
-                       const u16 *srcp = (const u16 *) data;
-                       u32 len = gf_utf8_wcstombs(m_url, MAXLEN_URL, &srcp);
-                       if (len>=0) m_url[len] = 0;
-               }
-               SysFreeString(data);
-               break;
-       }
-
-       if (m_url) {
-               UpdateURL();
-       }
-#endif
-
-}
-
-// trap keys and forward on to the control
-BOOL CGPAXPlugin::PreTranslateMessage(MSG* pMsg)
-{
-  switch (pMsg->message)
-  {
-     case WM_KEYDOWN:
-     case WM_KEYUP:
-        switch (pMsg->wParam)
-        {
-           case VK_UP:
-           case VK_DOWN:
-           case VK_LEFT:
-           case VK_RIGHT:
-           case VK_HOME:
-           case VK_END:
-              SendMessage (pMsg->message, pMsg->wParam, pMsg->lParam);
-              // Windowless controls won't be able to call SendMessage.
-              // Instead, just respond to the message here.
-              return TRUE;
-        }
-        break;
-  }
-  return FALSE;
-//  return COleControl::PreTranslateMessage(pMsg);
-}
-
-
-
-
-#define GPAC_REG_KEY   HKEY_CURRENT_USER
-
-//Create window message fuction. when the window is created, also initialize a instance of
-//GPAC player instance.
-LRESULT CGPAXPlugin::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    if (m_term) return 0;
-    const char *str;
-
-    if (m_hWnd==NULL) return 0;
-
-
-       //Create a structure m_user for initialize the terminal. the parameters to set:
-       //1)config file path
-       //2)Modules file path
-       //3)window handler
-       //4)EventProc
-    memset(&m_user, 0, sizeof(m_user));
-
-    m_user.config = gf_cfg_init(NULL, NULL);
-    if(!m_user.config) {
-#ifdef _WIN32_WCE
-               ::MessageBox(NULL, _T("GPAC Configuration file not found"), _T("Fatal Error"), MB_OK);
-#else
-               ::MessageBox(NULL, "GPAC Configuration file not found", "Fatal Error", MB_OK);
-#endif
-               goto err_exit;
-       }
-
-    str = gf_cfg_get_key(m_user.config, "General", "ModulesDirectory");
-    m_user.modules = gf_modules_new(str, m_user.config);
-    if(!gf_modules_get_count(m_user.modules)) goto err_exit;
-
-    m_user.os_window_handler = m_hWnd;
-    m_user.opaque = this;
-    m_user.EventProc = GPAX_EventProc;
-
-       //create a terminal
-    m_term = gf_term_new(&m_user);
-
-       if (!m_term) goto err_exit;
-       
-       gf_term_set_option(m_term, GF_OPT_AUDIO_VOLUME, 100);
-    
-       LoadDATAUrl();
-
-       RECT rc;
-    ::GetWindowRect(m_hWnd, &rc);
-    m_width = rc.right-rc.left;
-    m_height = rc.bottom-rc.top;
-       if (m_bAutoStart && strlen(m_url)) Play();
-    return 0;
-
-       //Error Processing
-err_exit:
-    if(m_user.modules)
-        gf_modules_del(m_user.modules);
-    m_user.modules = NULL;
-    if(m_user.config)
-        gf_cfg_del(m_user.config);
-    m_user.config = NULL;
-       return 1;
-}
-
-void CGPAXPlugin::UnloadTerm()
-{
-       if (m_term) {
-               GF_Terminal *a_term = m_term;
-               m_term = NULL;
-               gf_term_del(a_term);
-       }
-       if (m_user.modules) gf_modules_del(m_user.modules);
-       if (m_user.config) gf_cfg_del(m_user.config);
-       memset(&m_user, 0, sizeof(m_user));
-}
-CGPAXPlugin::~CGPAXPlugin()
-{
-       UnloadTerm();
-#ifndef _WIN32_WCE
-       if (m_pBrowser) m_pBrowser->Release();
-       m_pBrowser = NULL;
-#endif
-}
-LRESULT CGPAXPlugin::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-       UnloadTerm();
-    return 0;
-}
-
-
-HRESULT CGPAXPlugin::OnDraw(ATL_DRAWINFO& di)
-{
-       if (m_term && m_bInitialDraw) {
-               m_bInitialDraw = FALSE;
-               if (m_bAutoStart) Play();
-       }
-    return S_OK;
-}
-
-// Load is called before OnCreate, but it may not be called at
-// all if there are no parameters.
-STDMETHODIMP CGPAXPlugin::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
-{
-       char szOpt[1024];
-    // examine the <embed>/<param> tag arguments
-
-       m_url[0] = 0;
-    ReadParamString(pPropBag,pErrorLog,L"src", m_url, MAXLEN_URL);
-       if (!m_url[0])
-           ReadParamString(pPropBag,pErrorLog,L"data", m_url, MAXLEN_URL);
-
-    if (ReadParamString(pPropBag,pErrorLog,L"autostart", szOpt, 1024))
-               m_bAutoStart = (!stricmp(szOpt, "false") || !stricmp(szOpt, "no")) ? 0 : 1;
-
-    if (ReadParamString(pPropBag,pErrorLog,L"use3d", szOpt, 1024))
-               m_bUse3D = (!stricmp(szOpt, "true") || !stricmp(szOpt, "yes")) ? 1 : 0;
-
-    if (ReadParamString(pPropBag,pErrorLog,L"aspectratio", szOpt, 1024)) {
-               if (!stricmp(szOpt, "keep")) m_AR = GF_ASPECT_RATIO_KEEP;
-               else if (!stricmp(szOpt, "16:9")) m_AR = GF_ASPECT_RATIO_16_9;
-               else if (!stricmp(szOpt, "4:3")) m_AR = GF_ASPECT_RATIO_4_3;
-               else if (!stricmp(szOpt, "fill")) m_AR = GF_ASPECT_RATIO_FILL_SCREEN;
-       }
-
-    if (ReadParamString(pPropBag,pErrorLog,L"loop", szOpt, 1024))
-               m_bLoop = !stricmp(szOpt, "true") ? 0 : 1;
-
-       UpdateURL();
-
-#ifndef _WIN32_WCE
-       /*get the top-level container*/
-       if (!m_pBrowser) {
-               IServiceProvider *isp, *isp2 = NULL;
-               if ( SUCCEEDED(m_spClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&isp)) ) ) {
-
-                       if (SUCCEEDED(isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2)) ) ) {
-                               isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&m_pBrowser));
-                               isp2->Release();
-                       }
-                       isp->Release();
-               }
-       }
-       if (m_pBrowser) m_pBrowser->put_StatusText(L"GPAC Ready");
-#endif
-
-       return IPersistPropertyBagImpl<CGPAXPlugin>::Load(pPropBag, pErrorLog);
-}
-
-void CGPAXPlugin::UpdateURL()
-{
-       /*get absolute URL*/
-       if (!strlen(m_url)) return;
-       IMoniker* pMoniker      = NULL;
-       LPOLESTR sDisplayName;
-
-       if (SUCCEEDED(m_spClientSite->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
-                                                                          OLEWHICHMK_CONTAINER,
-                                                                          &pMoniker) ) ) {
-               char parent_url[1024];
-               pMoniker->GetDisplayName(NULL, NULL, &sDisplayName);
-               wcstombs(parent_url, sDisplayName, 300);
-               pMoniker->Release();
-
-               char *abs_url = gf_url_concatenate(parent_url, m_url);
-               if (abs_url) {
-                       strcpy(m_url, abs_url);
-                       gf_free(abs_url);
-               }
-       }
-}
-
-STDMETHODIMP CGPAXPlugin::Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
-{
-       u16 wurl[MAXLEN_URL];
-       const char *sptr;
-       u16 len;
-
-    VARIANT value;
-    if( pPropBag == NULL) return E_INVALIDARG;
-
-    VariantInit(&value);
-
-    V_VT(&value) = VT_BOOL;
-    V_BOOL(&value) = m_bAutoStart ? VARIANT_TRUE : VARIANT_FALSE;
-    pPropBag->Write(OLESTR("AutoStart"), &value);
-    VariantClear(&value);
-
-    V_VT(&value) = VT_BSTR;
-
-       sptr = (const char *)m_url;
-       len = gf_utf8_mbstowcs(wurl, MAXLEN_URL, &sptr);
-    V_BSTR(&value) = SysAllocStringLen(NULL, len+1);
-       memcpy(V_BSTR(&value) , wurl, len*sizeof(u16));
-       V_BSTR(&value) [len] = 0;
-       
-    pPropBag->Write(OLESTR("src"), &value);
-    VariantClear(&value);
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::Play()
-{
-       if (m_term) {
-               if (!m_bIsConnected) {
-                       if (strlen(m_url)) {
-                               /*connect from 0 and pause if not autoplay*/
-                               const char *gui = gf_cfg_get_key(m_user.config, "General", "StartupFile");
-                               if (gui) {
-                                       gf_cfg_set_key(m_user.config, "Temp", "BrowserMode", "yes");
-                                       gf_cfg_set_key(m_user.config, "Temp", "GUIStartupFile", m_url);
-                                       gf_term_connect(m_term, gui);
-                               } else {
-                                       gf_term_connect(m_term, m_url);
-                               }
-                               gf_term_set_option(m_term, GF_OPT_ASPECT_RATIO, m_AR);
-                       }
-               } else
-                       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);   //if target is connected, set it playing
-       }
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::Pause()
-{
-    if(m_term) {
-               if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE) == GF_STATE_PAUSED) {
-               gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
-               } else {
-               gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);
-               }
-       }
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::Stop()
-{
-    if(m_term) gf_term_disconnect(m_term);     //set it stop
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::Update(BSTR _mtype, BSTR _updates)
-{
-    if (m_term) {
-               u16 *srcp;
-               u32 len;
-               char mtype[1024], *updates;
-
-               srcp = (u16 *) _mtype;
-               len = gf_utf8_wcstombs(mtype, 1024, (const u16 **)&srcp);
-               mtype[len] = 0;
-
-               srcp = (u16 *)_updates;
-               len = gf_utf8_wcstombs(NULL, 0, (const u16 **)&srcp);
-               if (len) {
-                       updates = (char *) gf_malloc(sizeof(char) * (len+1));
-                       srcp = (u16 *)_updates;
-                       len = gf_utf8_wcstombs(updates, len, (const u16 **)&srcp);
-                       updates[len] = 0;
-                       gf_term_scene_update(m_term, mtype, updates);
-                       gf_free(updates);
-               }
-       }
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::get_src(BSTR *url)
-{
-       u16 wurl[MAXLEN_URL];
-       const char *sptr;
-       u16 len;
-    if (url==NULL) return E_POINTER;
-
-       sptr = (const char *)m_url;
-       len = gf_utf8_mbstowcs(wurl, MAXLEN_URL, &sptr);
-    *url = SysAllocStringLen(NULL, len+1);
-       memcpy(*url, wurl, len*sizeof(u16));
-       *url[len] = 0;
-    return S_OK;
-}
-STDMETHODIMP CGPAXPlugin::put_src(BSTR url)
-{
-       const u16 *srcp = (const u16 *)url;
-       u32 len = gf_utf8_wcstombs(m_url, MAXLEN_URL, &srcp);
-       m_url[len] = 0;
-       UpdateURL();
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::get_AutoStart(VARIANT_BOOL *as)
-{
-    if (as==NULL) return E_POINTER;
-    *as = m_bAutoStart ? VARIANT_TRUE: VARIANT_FALSE;
-    return S_OK;
-}
-STDMETHODIMP CGPAXPlugin::put_AutoStart(VARIANT_BOOL as)
-{
-    m_bAutoStart = (as !=VARIANT_FALSE) ? TRUE: FALSE;
-    return S_OK;
-}
-
-STDMETHODIMP CGPAXPlugin::GetInterfaceSafetyOptions(      
-    REFIID riid,
-    DWORD *pdwSupportedOptions,
-    DWORD *pdwEnabledOptions
-)
-{
-    if( (NULL == pdwSupportedOptions) || (NULL == pdwEnabledOptions) )
-        return E_POINTER;
-
-    *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACESAFE_FOR_UNTRUSTED_CALLER;
-
-    if ((IID_IDispatch == riid) || (IID_IGPAX == riid)) {
-        *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
-        return NOERROR;
-    }
-    else if (IID_IPersistPropertyBag == riid)  {
-        *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
-        return NOERROR;
-    }
-    *pdwEnabledOptions = 0;
-    return E_NOINTERFACE;
-};
-
-STDMETHODIMP CGPAXPlugin::SetInterfaceSafetyOptions(      
-    REFIID riid,
-    DWORD dwOptionSetMask,
-    DWORD dwEnabledOptions
-)
-{
-    if ((IID_IDispatch == riid) || (IID_IGPAX == riid) ) {
-        if( (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask)
-         && (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions) ) {
-            return NOERROR;
-        }
-        return E_FAIL;
-    }
-    else if (IID_IPersistPropertyBag == riid) {
-        if( (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask)
-         && (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions) ) {
-            return NOERROR;
-        }
-        return E_FAIL;
-    }
-    return E_FAIL;
-};
-
diff --git a/applications/GPAX/GPAXPlugin.h b/applications/GPAX/GPAXPlugin.h
deleted file mode 100644 (file)
index 8bda8e4..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- *                     GPAC - Multimedia Framework C SDK
- *
- *                     Authors: Y.XI, X. ZHAO, J. Le Feuvre
- *                     Copyright (c) ENST 2006-200x
- *                                     All rights reserved
- *
- *  This file is part of GPAC / ActiveX control
- *
- *  GPAC is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  GPAC 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 Lesser General Public License for more details.
- *   
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *             
- */
-
-#ifndef __GPAXPLUGIN_H_
-#define __GPAXPLUGIN_H_
-
-#define MAXLEN_URL     300
-
-#include "resource.h"       // main symbols
-#include <atlctl.h>
-#include <SHLGUID.h>
-
-
-
-#include <gpac/terminal.h>
-#include <gpac/user.h>
-#include <gpac/config_file.h>
-#include <gpac/module.h>
-#include <gpac/options.h>
-
-#if (_MSC_VER >= 1300)
-using namespace ATL;
-#endif
-
-
-Bool GPAX_EventProc(void *ptr, GF_Event *evt);
-
-/////////////////////////////////////////////////////////////////////////////
-// CGPAXPlugin
-class ATL_NO_VTABLE CGPAXPlugin :
-            public CComObjectRootEx<CComSingleThreadModel>,
-            public IDispatchImpl<IGPAX, &IID_IGPAX, &LIBID_GPAXLib>,
-            public CComControl<CGPAXPlugin>,
-            public CComCoClass<CGPAXPlugin, &CLSID_GPAX>,
-            public IOleControlImpl<CGPAXPlugin>,
-            public IOleObjectImpl<CGPAXPlugin>,
-            public IOleInPlaceActiveObjectImpl<CGPAXPlugin>,
-            public IViewObjectExImpl<CGPAXPlugin>,
-            public IOleInPlaceObjectWindowlessImpl<CGPAXPlugin>,
-            public IProvideClassInfo2Impl<&CLSID_GPAX, &DIID_IGPAXEvents, &LIBID_GPAXLib>,
-
-                       public IPersistStreamInitImpl<CGPAXPlugin>,
-            public ISupportErrorInfo,
-            public IConnectionPointContainerImpl<CGPAXPlugin>,
-            public IPersistStorageImpl<CGPAXPlugin>,
-            public ISpecifyPropertyPagesImpl<CGPAXPlugin>,
-            public IQuickActivateImpl<CGPAXPlugin>,
-            public IDataObjectImpl<CGPAXPlugin>,
-            public IPropertyNotifySinkCP<CGPAXPlugin>,
-
-                       public IPersistPropertyBagImpl<CGPAXPlugin>,
-                       public IObjectSafetyImpl<CGPAXPlugin, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
-
-{
-public:
-    CGPAXPlugin() {
-               m_term = NULL;
-               m_bAutoStart = TRUE;
-               m_bInitialDraw = TRUE;
-               m_bWindowOnly = TRUE;  //to declare that the control is a window control in order
-                                                          //to inherit the member variable m_hWnd which contains the window handler
-               m_bIsConnected = 0;
-               m_bUse3D = 0;
-               m_AR = GF_ASPECT_RATIO_KEEP;
-               m_url[0] = 0;
-#ifndef _WIN32_WCE
-               m_pBrowser = NULL;
-#endif
-               memset(&m_user, 0, sizeof(m_user));
-
-               m_dwCurrentSafety = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
-    }
-
-       ~CGPAXPlugin();
-
-       Bool EventProc(GF_Event *evt);
-
-       BOOL PreTranslateMessage(MSG* pMsg);
-
-    DECLARE_REGISTRY_RESOURCEID(IDR_GPAXPLUGIN)
-    DECLARE_PROTECT_FINAL_CONSTRUCT()
-#if (_MSC_VER >= 1300)
-       DECLARE_OLEMISC_STATUS(OLEMISC_ACTSLIKEBUTTON | OLEMISC_ACTIVATEWHENVISIBLE)
-#endif
-
-    static LPCTSTR GetWindowClassName() { return TEXT("GPAC ActiveX"); }
-
-    BEGIN_COM_MAP(CGPAXPlugin)
-    COM_INTERFACE_ENTRY(IGPAX)
-    COM_INTERFACE_ENTRY(IDispatch)
-    COM_INTERFACE_ENTRY(IViewObjectEx)
-    COM_INTERFACE_ENTRY(IProvideClassInfo)
-    COM_INTERFACE_ENTRY(IOleControl)
-    COM_INTERFACE_ENTRY(IOleObject)
-
-    COM_INTERFACE_ENTRY_IMPL(IViewObjectEx)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject2, IViewObjectEx)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject, IViewObjectEx)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceObjectWindowless)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceActiveObject)
-    
-       COM_INTERFACE_ENTRY_IMPL(IOleInPlaceActiveObject)
-    COM_INTERFACE_ENTRY_IMPL(IOleInPlaceObjectWindowless)
-       
-//     COM_INTERFACE_ENTRY(IObjectSafety)
-       COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
-       COM_INTERFACE_ENTRY(IPersistPropertyBag)
-    COM_INTERFACE_ENTRY_IMPL_IID(IID_IPersist, IPersistPropertyBag)
-       
-/*     COM_INTERFACE_ENTRY(IViewObject)
-    COM_INTERFACE_ENTRY(IViewObject2)
-    COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
-    COM_INTERFACE_ENTRY(IOleInPlaceObject)
-       */
-
-       COM_INTERFACE_ENTRY(IProvideClassInfo2)
-    COM_INTERFACE_ENTRY(IPersistStreamInit)
-    COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
-    COM_INTERFACE_ENTRY(ISupportErrorInfo)
-    COM_INTERFACE_ENTRY(IConnectionPointContainer)
-    COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
-    COM_INTERFACE_ENTRY(IQuickActivate)
-    COM_INTERFACE_ENTRY(IPersistStorage)
-    COM_INTERFACE_ENTRY(IDataObject)
-
-    END_COM_MAP()
-
-    BEGIN_PROP_MAP(CGPAXPlugin)
-    END_PROP_MAP()
-
-    BEGIN_CONNECTION_POINT_MAP(CGPAXPlugin)
-    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
-    END_CONNECTION_POINT_MAP()
-
-    BEGIN_MSG_MAP(CGPAXPlugin)
-    CHAIN_MSG_MAP(CComControl<CGPAXPlugin>)
-    DEFAULT_REFLECTION_HANDLER()
-       MESSAGE_HANDLER(WM_CREATE, OnCreate)
-       MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
-
-    END_MSG_MAP()
-    // Handler prototypes:
-    //  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    //  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
-    //  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
-
-
-
-    // ISupportsErrorInfo
-    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
-    {
-        static const IID* arr[] =
-            {
-                &IID_IGPAX,
-            };
-        for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
-        {
-#if (_MSC_VER < 1300)
-                       if (::ATL::InlineIsEqualGUID(*arr[i], riid))
-#else
-                       if (::InlineIsEqualGUID(*arr[i], riid))
-#endif
-                               return S_OK;
-        }
-        return S_FALSE;
-    }
-    STDMETHODIMP GetInterfaceSafetyOptions(      
-        REFIID riid,
-        DWORD *pdwSupportedOptions,
-        DWORD *pdwEnabledOptions
-    );
-
-    STDMETHODIMP SetInterfaceSafetyOptions(      
-        REFIID riid,
-        DWORD dwOptionSetMask,
-        DWORD dwEnabledOptions
-    );
-
-    // IViewObjectEx
-    DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
-
-    // IGPAX
-public:
-       //Interface methods
-       STDMETHOD(Stop)();
-       STDMETHOD(Pause)();
-       STDMETHOD(Play)();
-    STDMETHOD(Update)(BSTR mtype,BSTR updates);
-
-       //Interface properties
-    STDMETHODIMP get_src(BSTR *url);
-    STDMETHODIMP put_src(BSTR url);
-    STDMETHODIMP get_AutoStart(VARIANT_BOOL *as);
-    STDMETHODIMP put_AutoStart(VARIANT_BOOL as);
-
-       //Customed Window Message functions: OnCreate and OnDestroy are called when a window
-       //is created or destroyed. OnDraw is to establish inital connection.
-    HRESULT OnDraw(ATL_DRAWINFO& di);
-    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-
-       //IPersistPropertyBag method: to handle persist property packed and transfered by MSIE
-       //in html doc, the ActiveX control is added by tags
-       //   <object CLSID=...>
-       //              <PARAM name="..." value="...">
-       //   </object>
-       //the interface IPersistPropertyBag enable MSIE and ActiveX Control to communicate these
-       //properties included in tags <PARAM> 
-    STDMETHODIMP Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog);
-    STDMETHODIMP Save(LPPROPERTYBAG, BOOL, BOOL);
-
-
-private:
-       Bool ReadParamString(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, WCHAR *name, char *buf, int bufsize);
-       void SetStatusText(char *msg);
-       void UpdateURL();
-       void UnloadTerm();
-       void LoadDATAUrl();
-
-       GF_Terminal *m_term;
-    GF_User m_user;
-       char m_url[MAXLEN_URL];
-#ifndef _WIN32_WCE
-       /*pointer to the parent browser if any*/
-       IWebBrowser2 *m_pBrowser;
-#endif
-
-       u32 m_width, m_height, m_AR;
-       Bool m_bIsConnected, m_bInitialDraw, m_bAutoStart, m_bUse3D, m_bLoop;
-
-};
-
-
-
-#endif //__GPAXPLUGIN_H_
diff --git a/applications/GPAX/GPAX_i.c b/applications/GPAX/GPAX_i.c
deleted file mode 100644 (file)
index 3be5d97..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-
-#pragma warning( disable: 4049 )  /* more than 64k source lines */
-
-/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
-
-/* link this file in with the server and any clients */
-
-
- /* File created by MIDL compiler version 5.03.0286 */
-/* at Thu Jul 20 19:14:15 2006
- */
-/* Compiler settings for \CVS\gpac\applications\GPAX\GPAX.idl:
-    Oicf (OptLev=i2), W1, Zp8, env=Win32 (32b run), ms_ext, c_ext
-    error checks: allocation ref bounds_check enum stub_data 
-    VC __declspec() decoration level: 
-         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
-         DECLSPEC_UUID(), MIDL_INTERFACE()
-*/
-//@@MIDL_FILE_HEADING(  )
-
-#if !defined(_M_IA64) && !defined(_M_AXP64)
-
-#ifdef __cplusplus
-extern "C"{
-#endif 
-
-
-#include <rpc.h>
-#include <rpcndr.h>
-
-#ifdef _MIDL_USE_GUIDDEF_
-
-#ifndef INITGUID
-#define INITGUID
-#include <guiddef.h>
-#undef INITGUID
-#else
-#include <guiddef.h>
-#endif
-
-#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
-        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
-
-#else // !_MIDL_USE_GUIDDEF_
-
-#ifndef __IID_DEFINED__
-#define __IID_DEFINED__
-
-typedef struct _IID
-{
-    unsigned long x;
-    unsigned short s1;
-    unsigned short s2;
-    unsigned char  c[8];
-} IID;
-
-#endif // __IID_DEFINED__
-
-#ifndef CLSID_DEFINED
-#define CLSID_DEFINED
-typedef IID CLSID;
-#endif // CLSID_DEFINED
-
-#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
-        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-
-#endif !_MIDL_USE_GUIDDEF_
-
-MIDL_DEFINE_GUID(IID, LIBID_GPAXLib,0xE64FAC7F,0x0134,0x4A75,0xA7,0xDA,0x80,0xD5,0x3E,0xBC,0x56,0xA6);
-
-
-MIDL_DEFINE_GUID(IID, IID_IGPAX,0xE2A9A937,0xBB35,0x47E0,0x89,0x42,0x96,0x48,0x06,0x29,0x9A,0xB4);
-
-
-MIDL_DEFINE_GUID(IID, DIID_IGPAXEvents,0x1FDA32FC,0x4C9A,0x461F,0xB3,0x3B,0x07,0x15,0xB0,0x34,0x30,0x06);
-
-
-MIDL_DEFINE_GUID(CLSID, CLSID_GPAX,0x181D18E6,0x4DC1,0x4B55,0xB7,0x2E,0xBE,0x2A,0x10,0x06,0x49,0x95);
-
-#undef MIDL_DEFINE_GUID
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-#endif /* !defined(_M_IA64) && !defined(_M_AXP64)*/
-
-
-#pragma warning( disable: 4049 )  /* more than 64k source lines */
-
-/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
-
-/* link this file in with the server and any clients */
-
-
- /* File created by MIDL compiler version 5.03.0286 */
-/* at Thu Jul 20 19:14:15 2006
- */
-/* Compiler settings for \CVS\gpac\applications\GPAX\GPAX.idl:
-    Oicf (OptLev=i2), W1, Zp8, env=Win64 (32b run,appending), ms_ext, c_ext, robust
-    error checks: allocation ref bounds_check enum stub_data 
-    VC __declspec() decoration level: 
-         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
-         DECLSPEC_UUID(), MIDL_INTERFACE()
-*/
-//@@MIDL_FILE_HEADING(  )
-
-#if defined(_M_IA64) || defined(_M_AXP64)
-
-#ifdef __cplusplus
-extern "C"{
-#endif 
-
-
-#include <rpc.h>
-#include <rpcndr.h>
-
-#ifdef _MIDL_USE_GUIDDEF_
-
-#ifndef INITGUID
-#define INITGUID
-#include <guiddef.h>
-#undef INITGUID
-#else
-#include <guiddef.h>
-#endif
-
-#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
-        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
-
-#else // !_MIDL_USE_GUIDDEF_
-
-#ifndef __IID_DEFINED__
-#define __IID_DEFINED__
-
-typedef struct _IID
-{
-    unsigned long x;
-    unsigned short s1;
-    unsigned short s2;
-    unsigned char  c[8];
-} IID;
-
-#endif // __IID_DEFINED__
-
-#ifndef CLSID_DEFINED
-#define CLSID_DEFINED
-typedef IID CLSID;
-#endif // CLSID_DEFINED
-
-#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
-        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-
-#endif !_MIDL_USE_GUIDDEF_
-
-MIDL_DEFINE_GUID(IID, LIBID_GPAXLib,0xE64FAC7F,0x0134,0x4A75,0xA7,0xDA,0x80,0xD5,0x3E,0xBC,0x56,0xA6);
-
-
-MIDL_DEFINE_GUID(IID, IID_IGPAX,0xE2A9A937,0xBB35,0x47E0,0x89,0x42,0x96,0x48,0x06,0x29,0x9A,0xB4);
-
-
-MIDL_DEFINE_GUID(IID, DIID_IGPAXEvents,0x1FDA32FC,0x4C9A,0x461F,0xB3,0x3B,0x07,0x15,0xB0,0x34,0x30,0x06);
-
-
-MIDL_DEFINE_GUID(CLSID, CLSID_GPAX,0x181D18E6,0x4DC1,0x4B55,0xB7,0x2E,0xBE,0x2A,0x10,0x06,0x49,0x95);
-
-#undef MIDL_DEFINE_GUID
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-#endif /* defined(_M_IA64) || defined(_M_AXP64)*/
-
diff --git a/applications/GPAX/GPAX_p.c b/applications/GPAX/GPAX_p.c
deleted file mode 100644 (file)
index 64594b3..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-/* this ALWAYS GENERATED file contains the proxy stub code */
-
-
-/* File created by MIDL compiler version 5.01.0164 */
-/* at Mon Jul 17 15:58:48 2006
- */
-/* Compiler settings for D:\CVS\gpac\applications\GPAX\GPAX.idl:
-    Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext
-    error checks: allocation ref bounds_check enum stub_data 
-*/
-//@@MIDL_FILE_HEADING(  )
-
-#define USE_STUBLESS_PROXY
-
-
-/* verify that the <rpcproxy.h> version is high enough to compile this file*/
-#ifndef __REDQ_RPCPROXY_H_VERSION__
-#define __REQUIRED_RPCPROXY_H_VERSION__ 440
-#endif
-
-
-#include "rpcproxy.h"
-#ifndef __RPCPROXY_H_VERSION__
-#error this stub requires an updated version of <rpcproxy.h>
-#endif // __RPCPROXY_H_VERSION__
-
-
-#include "GPAX.h"
-
-#define TYPE_FORMAT_STRING_SIZE   59                                
-#define PROC_FORMAT_STRING_SIZE   213                               
-
-typedef struct _MIDL_TYPE_FORMAT_STRING
-    {
-    short          Pad;
-    unsigned char  Format[ TYPE_FORMAT_STRING_SIZE ];
-    } MIDL_TYPE_FORMAT_STRING;
-
-typedef struct _MIDL_PROC_FORMAT_STRING
-    {
-    short          Pad;
-    unsigned char  Format[ PROC_FORMAT_STRING_SIZE ];
-    } MIDL_PROC_FORMAT_STRING;
-
-
-extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;
-extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;
-
-
-/* Standard interface: __MIDL_itf_GPAX_0000, ver. 0.0,
-   GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */
-
-
-/* Object interface: IUnknown, ver. 0.0,
-   GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
-
-
-/* Object interface: IDispatch, ver. 0.0,
-   GUID={0x00020400,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
-
-
-/* Object interface: IGPAX, ver. 0.0,
-   GUID={0xE2A9A937,0xBB35,0x47E0,{0x89,0x42,0x96,0x48,0x06,0x29,0x9A,0xB4}} */
-
-
-extern const MIDL_STUB_DESC Object_StubDesc;
-
-
-extern const MIDL_SERVER_INFO IGPAX_ServerInfo;
-
-#pragma code_seg(".orpc")
-extern const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[1];
-
-static const MIDL_STUB_DESC Object_StubDesc = 
-    {
-    0,
-    NdrOleAllocate,
-    NdrOleFree,
-    0,
-    0,
-    0,
-    0,
-    0,
-    __MIDL_TypeFormatString.Format,
-    1, /* -error bounds_check flag */
-    0x20000, /* Ndr library version */
-    0,
-    0x50100a4, /* MIDL Version 5.1.164 */
-    0,
-    UserMarshalRoutines,
-    0,  /* notify & notify_flag routine table */
-    1,  /* Flags */
-    0,  /* Reserved3 */
-    0,  /* Reserved4 */
-    0   /* Reserved5 */
-    };
-
-static const unsigned short IGPAX_FormatStringOffsetTable[] = 
-    {
-    (unsigned short) -1,
-    (unsigned short) -1,
-    (unsigned short) -1,
-    (unsigned short) -1,
-    0,
-    22,
-    44,
-    66,
-    100,
-    128,
-    156,
-    184
-    };
-
-static const MIDL_SERVER_INFO IGPAX_ServerInfo = 
-    {
-    &Object_StubDesc,
-    0,
-    __MIDL_ProcFormatString.Format,
-    &IGPAX_FormatStringOffsetTable[-3],
-    0,
-    0,
-    0,
-    0
-    };
-
-static const MIDL_STUBLESS_PROXY_INFO IGPAX_ProxyInfo =
-    {
-    &Object_StubDesc,
-    __MIDL_ProcFormatString.Format,
-    &IGPAX_FormatStringOffsetTable[-3],
-    0,
-    0,
-    0
-    };
-
-CINTERFACE_PROXY_VTABLE(15) _IGPAXProxyVtbl = 
-{
-    &IGPAX_ProxyInfo,
-    &IID_IGPAX,
-    IUnknown_QueryInterface_Proxy,
-    IUnknown_AddRef_Proxy,
-    IUnknown_Release_Proxy ,
-    0 /* (void *)-1 /* IDispatch::GetTypeInfoCount */ ,
-    0 /* (void *)-1 /* IDispatch::GetTypeInfo */ ,
-    0 /* (void *)-1 /* IDispatch::GetIDsOfNames */ ,
-    0 /* IDispatch_Invoke_Proxy */ ,
-    (void *)-1 /* IGPAX::Play */ ,
-    (void *)-1 /* IGPAX::Pause */ ,
-    (void *)-1 /* IGPAX::Stop */ ,
-    (void *)-1 /* IGPAX::Update */ ,
-    (void *)-1 /* IGPAX::get_URL */ ,
-    (void *)-1 /* IGPAX::put_URL */ ,
-    (void *)-1 /* IGPAX::get_AutoStart */ ,
-    (void *)-1 /* IGPAX::put_AutoStart */
-};
-
-
-static const PRPC_STUB_FUNCTION IGPAX_table[] =
-{
-    STUB_FORWARDING_FUNCTION,
-    STUB_FORWARDING_FUNCTION,
-    STUB_FORWARDING_FUNCTION,
-    STUB_FORWARDING_FUNCTION,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2,
-    NdrStubCall2
-};
-
-CInterfaceStubVtbl _IGPAXStubVtbl =
-{
-    &IID_IGPAX,
-    &IGPAX_ServerInfo,
-    15,
-    &IGPAX_table[-3],
-    CStdStubBuffer_DELEGATING_METHODS
-};
-
-#pragma data_seg(".rdata")
-
-static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[1] = 
-        {
-            
-            {
-            BSTR_UserSize
-            ,BSTR_UserMarshal
-            ,BSTR_UserUnmarshal
-            ,BSTR_UserFree
-            }
-
-        };
-
-
-#if !defined(__RPC_WIN32__)
-#error  Invalid build platform for this stub.
-#endif
-
-#if !(TARGET_IS_NT40_OR_LATER)
-#error You need a Windows NT 4.0 or later to run this stub because it uses these features:
-#error   -Oif or -Oicf, [wire_marshal] or [user_marshal] attribute, more than 32 methods in the interface.
-#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
-#error This app will die there with the RPC_X_WRONG_STUB_VERSION error.
-#endif
-
-
-static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
-    {
-        0,
-        {
-
-       /* Procedure Play */
-
-                       0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/*  2 */       NdrFcLong( 0x0 ),       /* 0 */
-/*  6 */       NdrFcShort( 0x7 ),      /* 7 */
-#ifndef _ALPHA_
-/*  8 */       NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 10 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 12 */       NdrFcShort( 0x8 ),      /* 8 */
-/* 14 */       0x4,            /* Oi2 Flags:  has return, */
-                       0x1,            /* 1 */
-
-       /* Return value */
-
-/* 16 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 18 */       NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 20 */       0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure Pause */
-
-/* 22 */       0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 24 */       NdrFcLong( 0x0 ),       /* 0 */
-/* 28 */       NdrFcShort( 0x8 ),      /* 8 */
-#ifndef _ALPHA_
-/* 30 */       NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 32 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 34 */       NdrFcShort( 0x8 ),      /* 8 */
-/* 36 */       0x4,            /* Oi2 Flags:  has return, */
-                       0x1,            /* 1 */
-
-       /* Return value */
-
-/* 38 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 40 */       NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 42 */       0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure Stop */
-
-/* 44 */       0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 46 */       NdrFcLong( 0x0 ),       /* 0 */
-/* 50 */       NdrFcShort( 0x9 ),      /* 9 */
-#ifndef _ALPHA_
-/* 52 */       NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 54 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 56 */       NdrFcShort( 0x8 ),      /* 8 */
-/* 58 */       0x4,            /* Oi2 Flags:  has return, */
-                       0x1,            /* 1 */
-
-       /* Return value */
-
-/* 60 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 62 */       NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 64 */       0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure Update */
-
-/* 66 */       0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 68 */       NdrFcLong( 0x0 ),       /* 0 */
-/* 72 */       NdrFcShort( 0xa ),      /* 10 */
-#ifndef _ALPHA_
-/* 74 */       NdrFcShort( 0x10 ),     /* x86, MIPS, PPC Stack size/offset = 16 */
-#else
-                       NdrFcShort( 0x20 ),     /* Alpha Stack size/offset = 32 */
-#endif
-/* 76 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 78 */       NdrFcShort( 0x8 ),      /* 8 */
-/* 80 */       0x6,            /* Oi2 Flags:  clt must size, has return, */
-                       0x3,            /* 3 */
-
-       /* Parameter mtype */
-
-/* 82 */       NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */
-#ifndef _ALPHA_
-/* 84 */       NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 86 */       NdrFcShort( 0x1a ),     /* Type Offset=26 */
-
-       /* Parameter updates */
-
-/* 88 */       NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */
-#ifndef _ALPHA_
-/* 90 */       NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 92 */       NdrFcShort( 0x1a ),     /* Type Offset=26 */
-
-       /* Return value */
-
-/* 94 */       NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 96 */       NdrFcShort( 0xc ),      /* x86, MIPS, PPC Stack size/offset = 12 */
-#else
-                       NdrFcShort( 0x18 ),     /* Alpha Stack size/offset = 24 */
-#endif
-/* 98 */       0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure get_URL */
-
-/* 100 */      0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 102 */      NdrFcLong( 0x0 ),       /* 0 */
-/* 106 */      NdrFcShort( 0xb ),      /* 11 */
-#ifndef _ALPHA_
-/* 108 */      NdrFcShort( 0xc ),      /* x86, MIPS, PPC Stack size/offset = 12 */
-#else
-                       NdrFcShort( 0x18 ),     /* Alpha Stack size/offset = 24 */
-#endif
-/* 110 */      NdrFcShort( 0x0 ),      /* 0 */
-/* 112 */      NdrFcShort( 0x8 ),      /* 8 */
-/* 114 */      0x5,            /* Oi2 Flags:  srv must size, has return, */
-                       0x2,            /* 2 */
-
-       /* Parameter mrl */
-
-/* 116 */      NdrFcShort( 0x2113 ),   /* Flags:  must size, must free, out, simple ref, srv alloc size=8 */
-#ifndef _ALPHA_
-/* 118 */      NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 120 */      NdrFcShort( 0x2c ),     /* Type Offset=44 */
-
-       /* Return value */
-
-/* 122 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 124 */      NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 126 */      0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure put_URL */
-
-/* 128 */      0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 130 */      NdrFcLong( 0x0 ),       /* 0 */
-/* 134 */      NdrFcShort( 0xc ),      /* 12 */
-#ifndef _ALPHA_
-/* 136 */      NdrFcShort( 0xc ),      /* x86, MIPS, PPC Stack size/offset = 12 */
-#else
-                       NdrFcShort( 0x18 ),     /* Alpha Stack size/offset = 24 */
-#endif
-/* 138 */      NdrFcShort( 0x0 ),      /* 0 */
-/* 140 */      NdrFcShort( 0x8 ),      /* 8 */
-/* 142 */      0x6,            /* Oi2 Flags:  clt must size, has return, */
-                       0x2,            /* 2 */
-
-       /* Parameter mrl */
-
-/* 144 */      NdrFcShort( 0x8b ),     /* Flags:  must size, must free, in, by val, */
-#ifndef _ALPHA_
-/* 146 */      NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 148 */      NdrFcShort( 0x1a ),     /* Type Offset=26 */
-
-       /* Return value */
-
-/* 150 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 152 */      NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 154 */      0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure get_AutoStart */
-
-/* 156 */      0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 158 */      NdrFcLong( 0x0 ),       /* 0 */
-/* 162 */      NdrFcShort( 0xd ),      /* 13 */
-#ifndef _ALPHA_
-/* 164 */      NdrFcShort( 0xc ),      /* x86, MIPS, PPC Stack size/offset = 12 */
-#else
-                       NdrFcShort( 0x18 ),     /* Alpha Stack size/offset = 24 */
-#endif
-/* 166 */      NdrFcShort( 0x0 ),      /* 0 */
-/* 168 */      NdrFcShort( 0xe ),      /* 14 */
-/* 170 */      0x4,            /* Oi2 Flags:  has return, */
-                       0x2,            /* 2 */
-
-       /* Parameter autoplay */
-
-/* 172 */      NdrFcShort( 0x2150 ),   /* Flags:  out, base type, simple ref, srv alloc size=8 */
-#ifndef _ALPHA_
-/* 174 */      NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 176 */      0x6,            /* FC_SHORT */
-                       0x0,            /* 0 */
-
-       /* Return value */
-
-/* 178 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 180 */      NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 182 */      0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-       /* Procedure put_AutoStart */
-
-/* 184 */      0x33,           /* FC_AUTO_HANDLE */
-                       0x6c,           /* Old Flags:  object, Oi2 */
-/* 186 */      NdrFcLong( 0x0 ),       /* 0 */
-/* 190 */      NdrFcShort( 0xe ),      /* 14 */
-#ifndef _ALPHA_
-/* 192 */      NdrFcShort( 0xc ),      /* x86, MIPS, PPC Stack size/offset = 12 */
-#else
-                       NdrFcShort( 0x18 ),     /* Alpha Stack size/offset = 24 */
-#endif
-/* 194 */      NdrFcShort( 0x6 ),      /* 6 */
-/* 196 */      NdrFcShort( 0x8 ),      /* 8 */
-/* 198 */      0x4,            /* Oi2 Flags:  has return, */
-                       0x2,            /* 2 */
-
-       /* Parameter autoplay */
-
-/* 200 */      NdrFcShort( 0x48 ),     /* Flags:  in, base type, */
-#ifndef _ALPHA_
-/* 202 */      NdrFcShort( 0x4 ),      /* x86, MIPS, PPC Stack size/offset = 4 */
-#else
-                       NdrFcShort( 0x8 ),      /* Alpha Stack size/offset = 8 */
-#endif
-/* 204 */      0x6,            /* FC_SHORT */
-                       0x0,            /* 0 */
-
-       /* Return value */
-
-/* 206 */      NdrFcShort( 0x70 ),     /* Flags:  out, return, base type, */
-#ifndef _ALPHA_
-/* 208 */      NdrFcShort( 0x8 ),      /* x86, MIPS, PPC Stack size/offset = 8 */
-#else
-                       NdrFcShort( 0x10 ),     /* Alpha Stack size/offset = 16 */
-#endif
-/* 210 */      0x8,            /* FC_LONG */
-                       0x0,            /* 0 */
-
-                       0x0
-        }
-    };
-
-static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
-    {
-        0,
-        {
-                       NdrFcShort( 0x0 ),      /* 0 */
-/*  2 */       
-                       0x12, 0x0,      /* FC_UP */
-/*  4 */       NdrFcShort( 0xc ),      /* Offset= 12 (16) */
-/*  6 */       
-                       0x1b,           /* FC_CARRAY */
-                       0x1,            /* 1 */
-/*  8 */       NdrFcShort( 0x2 ),      /* 2 */
-/* 10 */       0x9,            /* Corr desc: FC_ULONG */
-                       0x0,            /*  */
-/* 12 */       NdrFcShort( 0xfffc ),   /* -4 */
-/* 14 */       0x6,            /* FC_SHORT */
-                       0x5b,           /* FC_END */
-/* 16 */       
-                       0x17,           /* FC_CSTRUCT */
-                       0x3,            /* 3 */
-/* 18 */       NdrFcShort( 0x8 ),      /* 8 */
-/* 20 */       NdrFcShort( 0xfffffff2 ),       /* Offset= -14 (6) */
-/* 22 */       0x8,            /* FC_LONG */
-                       0x8,            /* FC_LONG */
-/* 24 */       0x5c,           /* FC_PAD */
-                       0x5b,           /* FC_END */
-/* 26 */       0xb4,           /* FC_USER_MARSHAL */
-                       0x83,           /* 131 */
-/* 28 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 30 */       NdrFcShort( 0x4 ),      /* 4 */
-/* 32 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 34 */       NdrFcShort( 0xffffffe0 ),       /* Offset= -32 (2) */
-/* 36 */       
-                       0x11, 0x4,      /* FC_RP [alloced_on_stack] */
-/* 38 */       NdrFcShort( 0x6 ),      /* Offset= 6 (44) */
-/* 40 */       
-                       0x13, 0x0,      /* FC_OP */
-/* 42 */       NdrFcShort( 0xffffffe6 ),       /* Offset= -26 (16) */
-/* 44 */       0xb4,           /* FC_USER_MARSHAL */
-                       0x83,           /* 131 */
-/* 46 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 48 */       NdrFcShort( 0x4 ),      /* 4 */
-/* 50 */       NdrFcShort( 0x0 ),      /* 0 */
-/* 52 */       NdrFcShort( 0xfffffff4 ),       /* Offset= -12 (40) */
-/* 54 */       
-                       0x11, 0xc,      /* FC_RP [alloced_on_stack] [simple_pointer] */
-/* 56 */       0x6,            /* FC_SHORT */
-                       0x5c,           /* FC_PAD */
-
-                       0x0
-        }
-    };
-
-const CInterfaceProxyVtbl * _GPAX_ProxyVtblList[] = 
-{
-    ( CInterfaceProxyVtbl *) &_IGPAXProxyVtbl,
-    0
-};
-
-const CInterfaceStubVtbl * _GPAX_StubVtblList[] = 
-{
-    ( CInterfaceStubVtbl *) &_IGPAXStubVtbl,
-    0
-};
-
-PCInterfaceName const _GPAX_InterfaceNamesList[] = 
-{
-    "IGPAX",
-    0
-};
-
-const IID *  _GPAX_BaseIIDList[] = 
-{
-    &IID_IDispatch,
-    0
-};
-
-
-#define _GPAX_CHECK_IID(n)     IID_GENERIC_CHECK_IID( _GPAX, pIID, n)
-
-int __stdcall _GPAX_IID_Lookup( const IID * pIID, int * pIndex )
-{
-    
-    if(!_GPAX_CHECK_IID(0))
-        {
-        *pIndex = 0;
-        return 1;
-        }
-
-    return 0;
-}
-
-const ExtendedProxyFileInfo GPAX_ProxyFileInfo = 
-{
-    (PCInterfaceProxyVtblList *) & _GPAX_ProxyVtblList,
-    (PCInterfaceStubVtblList *) & _GPAX_StubVtblList,
-    (const PCInterfaceName * ) & _GPAX_InterfaceNamesList,
-    (const IID ** ) & _GPAX_BaseIIDList,
-    & _GPAX_IID_Lookup, 
-    1,
-    2,
-    0, /* table of [async_uuid] interfaces */
-    0, /* Filler1 */
-    0, /* Filler2 */
-    0  /* Filler3 */
-};
diff --git a/applications/GPAX/GPAXps.def b/applications/GPAX/GPAXps.def
deleted file mode 100644 (file)
index c4ab3de..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-
-LIBRARY      "GPAXPS"
-
-DESCRIPTION  'Proxy/Stub DLL'
-
-EXPORTS
-       DllGetClassObject       @1      PRIVATE
-       DllCanUnloadNow         @2      PRIVATE
-       GetProxyDllInfo         @3      PRIVATE
-       DllRegisterServer               @4      PRIVATE
-       DllUnregisterServer             @5      PRIVATE
diff --git a/applications/GPAX/GPAXps.mk b/applications/GPAX/GPAXps.mk
deleted file mode 100644 (file)
index 70cf327..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-
-GPAXps.dll: dlldata.obj GPAX_p.obj GPAX_i.obj
-       link /dll /out:GPAXps.dll /def:GPAXps.def /entry:DllMain dlldata.obj GPAX_p.obj GPAX_i.obj \
-               kernel32.lib rpcndr.lib rpcns4.lib rpcrt4.lib oleaut32.lib uuid.lib \
-
-.c.obj:
-       cl /c /Ox /DWIN32 /D_WIN32_WINNT=0x0400 /DREGISTER_PROXY_DLL \
-               $<
-
-clean:
-       @del GPAXps.dll
-       @del GPAXps.lib
-       @del GPAXps.exp
-       @del dlldata.obj
-       @del GPAX_p.obj
-       @del GPAX_i.obj
diff --git a/applications/GPAX/StdAfx.cpp b/applications/GPAX/StdAfx.cpp
deleted file mode 100644 (file)
index a5eea17..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// stdafx.cpp : source file that includes just the standard includes
-//  stdafx.pch will be the pre-compiled header
-//  stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
-
-#ifdef _ATL_STATIC_REGISTRY
-#include <statreg.h>
-#include <statreg.cpp>
-#endif
-
-#include <atlimpl.cpp>
diff --git a/applications/GPAX/StdAfx.h b/applications/GPAX/StdAfx.h
deleted file mode 100644 (file)
index 597b3ca..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// stdafx.h : include file for standard system include files,
-//      or project specific include files that are used frequently,
-//      but are changed infrequently
-
-#if !defined(AFX_STDAFX_H__2CD656F1_059C_4EC4_9EAA_8FECF66BB748__INCLUDED_)
-#define AFX_STDAFX_H__2CD656F1_059C_4EC4_9EAA_8FECF66BB748__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#define STRICT
-
-#ifndef _WIN32_WCE
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#define _ATL_APARTMENT_THREADED
-
-#endif //_WIN32_WCE
-
-
-#include <atlbase.h>
-//You may derive a class from CComModule and use it if you want to override
-//something, but do not change the name of _Module
-extern CComModule _Module;
-#include <atlcom.h>
-#include <atlctl.h>
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STDAFX_H__2CD656F1_059C_4EC4_9EAA_8FECF66BB748__INCLUDED)
diff --git a/applications/GPAX/dlldata.c b/applications/GPAX/dlldata.c
deleted file mode 100644 (file)
index 86db18b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*********************************************************
-   DllData file -- generated by MIDL compiler 
-
-        DO NOT ALTER THIS FILE
-
-   This file is regenerated by MIDL on every IDL file compile.
-
-   To completely reconstruct this file, delete it and rerun MIDL
-   on all the IDL files in this DLL, specifying this file for the
-   /dlldata command line option
-
-*********************************************************/
-
-#define PROXY_DELEGATION
-
-#include <rpcproxy.h>
-
-#ifdef __cplusplus
-extern "C"   {
-#endif
-
-EXTERN_PROXY_FILE( GPAX )
-
-
-PROXYFILE_LIST_START
-/* Start of list */
-  REFERENCE_PROXY_FILE( GPAX ),
-/* End of list */
-PROXYFILE_LIST_END
-
-
-DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
-
-#ifdef __cplusplus
-}  /*extern "C" */
-#endif
-
-/* end of generated dlldata file */
diff --git a/applications/GPAX/gpax.bmp b/applications/GPAX/gpax.bmp
deleted file mode 100644 (file)
index 3ff99ff..0000000
Binary files a/applications/GPAX/gpax.bmp and /dev/null differ
diff --git a/applications/GPAX/resource.h b/applications/GPAX/resource.h
deleted file mode 100644 (file)
index a96e6d1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by GPAX.rc
-//
-#define IDS_PROJNAME                    100
-#define IDB_GPAXPLUGIN                  101
-#define IDR_GPAXPLUGIN                  102
-#define IDS_TITLEGPAXProp               103
-#define IDS_HELPFILEGPAXProp            104
-#define IDS_DOCSTRINGGPAXProp           105
-#define IDR_GPAXPROP                    106
-#define IDD_GPAXPROP                    107
-#define IDC_EDIT_URLs                   201
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        202
-#define _APS_NEXT_COMMAND_VALUE         32768
-#define _APS_NEXT_CONTROL_VALUE         202
-#define _APS_NEXT_SYMED_VALUE           108
-#endif
-#endif
index a5f449b22d0a050c7084752178c7dcb9eb6f7f18..872a402e37259069309847550db54d38ae805d16 100644 (file)
@@ -1,10 +1,10 @@
 include ../config.mak
 
-APPDIRS= mp4client 
-APPDIRS+=mp42ts
+APPDIRS=mp4client 
 
 ifeq ($(DISABLE_ISOFF), no)
-APPDIRS += mp4box
+APPDIRS+=mp4box
+APPDIRS+=mp42ts
 endif
 
 V4STUDIODIR=
index 5c023114f7da5e791f9616690221904bfff3e232..980ec6f062d24108ede0b8f48953921a255c0cd1 100644 (file)
@@ -353,6 +353,10 @@ void WriteNodesFile(GF_List *BNodes, GF_List *NDTs, u32 NumVersions)
                                fprintf(f, "\tu8 *data;\n");
                                fprintf(f, "\tu32 data_len;\n");
                }
+               if (!strcmp(n->name, "BitWrapper")) {
+                               fprintf(f, "\t/*GPAC private*/\n");
+                               fprintf(f, "\tu32 buffer_len;\n");
+               }
                fprintf(f, "} M_%s;\n\n\n", n->name);
        }
 
@@ -789,12 +793,12 @@ void WriteNodeQuant(FILE *f, BNode *n)
                if (bf->hasBounds) {
                        if (!strcmp(bf->b_min, "+I") || !strcmp(bf->b_min, " +I") || !strcmp(bf->b_min, "I")) {
                                fprintf(f, "\t\t*b_min = FIX_MAX;\n");
-                       } else if (!strcmp(bf->b_min, "-I")) {
+                       } else if (!strcmp(bf->b_min, "-I")  || !strcmp(bf->b_min, "-65536")) {
                                fprintf(f, "\t\t*b_min = FIX_MIN;\n");
                        } else {
                                fprintf(f, "\t\t*b_min = %s;\n", GetFixedPrintout(bf->b_min));
                        }
-                       if (!strcmp(bf->b_max, "+I") || !strcmp(bf->b_max, " +I") || !strcmp(bf->b_max, "I")) {
+                       if (!strcmp(bf->b_max, "+I") || !strcmp(bf->b_max, " +I") || !strcmp(bf->b_max, "I") || !strcmp(bf->b_max, "65535")) {
                                fprintf(f, "\t\t*b_max = FIX_MAX;\n");
                        } else {
                                fprintf(f, "\t\t*b_max = %s;\n", GetFixedPrintout(bf->b_max));
diff --git a/applications/hbbtvplayer/README.txt b/applications/hbbtvplayer/README.txt
new file mode 100644 (file)
index 0000000..c050ddb
--- /dev/null
@@ -0,0 +1,15 @@
+/*****************************************************************************/\r
+\r
+Documentation summary\r
+\r
+ 'doc/introduction.txt' to know the purpose of the project\r
+\r
+ 'doc/projectmanangement.txt' to know the organisation of files and directories.\r
+\r
+ 'doc/avancement.txt' to know the progress in the development of the project\r
+\r
+/*****************************************************************************/\r
+\r
+1. Run getsources.sh (without sudo) to get the sources of gpac and/or webkit if necessary\r
+\r
+2. Run 'sudo ./install.sh' with the appropriate parameter (full, player, gpac, webkit or dependencies)\r
diff --git a/applications/hbbtvplayer/REQUIREMENT b/applications/hbbtvplayer/REQUIREMENT
new file mode 100644 (file)
index 0000000..328c4d0
--- /dev/null
@@ -0,0 +1,10 @@
+
+install.sh script will work on the follwoing conditions of execution : 
+
+linux ubuntu 11.04 environnement
+graphic drivers supporting transparency
+installed xulrunner with correct library path (that could be not the default case in old version of xulrunner)
+
+the execution of hbbtvplayer require a enought large screen to display several windows, including a main window able in 720p resolution (1280x720)
+
+
diff --git a/applications/hbbtvplayer/doc/avancement.txt b/applications/hbbtvplayer/doc/avancement.txt
new file mode 100644 (file)
index 0000000..0b196b9
--- /dev/null
@@ -0,0 +1,17 @@
+\r
+mardi 12 avril 2011, 09:09:57 (UTC+0200)\r
+\r
+- video on TVview : bug of displaying, video truncated\r
+\r
+jeudi 2 décembre 2010, 14:14:23 (UTC+0100)\r
+\r
+- adding Remote Control keys as buttons, simulating the RCU\r
+\r
+lundi 22 novembre 2010, 09:50:31 (UTC+0100)\r
+\r
+- construction du GTK global, liaison avec Webkit par le GTKWidget dedie... liaosion avec GPAC , en fenetre\r
+- would be nice to find a way to do all in one window.\r
+\r
+jeudi 14 octobre 2010, 10:15:36 (UTC+0200)\r
+\r
+- création\r
diff --git a/applications/hbbtvplayer/doc/introduction.txt b/applications/hbbtvplayer/doc/introduction.txt
new file mode 100644 (file)
index 0000000..a9953ac
--- /dev/null
@@ -0,0 +1,5 @@
+\r
+HbbTV Player\r
+\r
+the goal is to get a HbbTVTerminal emulation on a PC and be able to play HbbTV applications,  that could be include in a Stream.\r
+The player will receveive input  of HbbtvApplication entry files, or TS-stream featuring HBBTV.\r
diff --git a/applications/hbbtvplayer/doc/projectmanagement.txt b/applications/hbbtvplayer/doc/projectmanagement.txt
new file mode 100644 (file)
index 0000000..a94288d
--- /dev/null
@@ -0,0 +1,16 @@
+\r
+the project include 2 sub-project : \r
+\r
+- hbbtvterminal : a terminal able to play Video/Audio, an RCU emulation,  and display a webbrowser linking to the hbbtvbrowserplugin (see below)\r
+\r
+- hbbtvbrowserplugin : a NPAPI plugin able to play HbbtvApps in a webbrowser .\r
+\r
+\r
+CODEBLOCKS : \r
+\r
+for the use of codeblocks , you can find a workspace in /projectmanager/codeblocks/hbbtvplayer/\r
+\r
+each project contains a projectmanager directory, including a codeblocks specification projects :\r
+\r
+/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/hbbtvterminal.cbp\r
+/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.cbp\r
diff --git a/applications/hbbtvplayer/getsources.sh b/applications/hbbtvplayer/getsources.sh
new file mode 100644 (file)
index 0000000..b8a7447
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh -e
+
+WEBKIT=0
+GPAC=0  
+
+if [ -z $1 ] ; then
+       echo "\nDO NOT USE sudo FOR THIS SCRIPT"
+       echo "\nUsage: You must choose options :"
+       echo "\n\033[31m full - build the whole package (gpac+webkit+hbbtvplayer) Recommended for computer without gpac \033[0m"
+       echo "\n\033[33m webkit - download Webkit sources and install it\033[0m"
+       echo "\n\033[33m gpac - download gpac sources and install it\033[0m"
+       exit 1
+fi
+
+for i in $* ; do
+       if [ "$i" = "full" ] ; then 
+               echo -e "\033[31m Usage: $0 Full Building : Activated \033[0m" 
+               WEBKIT=1
+               GPAC=1  
+       fi
+
+       if [ "$i" = "webkit" ] ; then 
+               echo -e "\033[33m Usage: $0 Webkit Building : Activated \033[0m" 
+               WEBKIT=1 
+       fi
+
+       if [ "$i" = "gpac" ] ; then 
+               echo -e "\033[33m Usage: $0 gpac Building : Activated \033[0m" 
+               WEBKIT=1 
+       fi
+done
+
+if [ $GPAC -eq 1 ] ; then
+       svn checkout https://gpac.svn.sourceforge.net/svnroot/gpac/trunk/gpac gpac
+fi
+
+if [ $WEBKIT -eq 1 ] ; then
+       svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit --depth files -r 97300 # 98458 ?
+       svn checkout http://svn.webkit.org/repository/webkit/trunk/Source WebKit/Source  -r 97300
+       svn checkout http://svn.webkit.org/repository/webkit/trunk/Tools WebKit/Tools  -r 97300
+       svn checkout http://svn.webkit.org/repository/webkit/trunk/WebKitLibraries WebKit/WebKitLibraries  -r 97300
+fi
+
+
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/README b/applications/hbbtvplayer/hbbtvbrowserplugin/README
new file mode 100644 (file)
index 0000000..d3b8d3f
--- /dev/null
@@ -0,0 +1,14 @@
+******************************************
+HBBTVBROWSERPLUGIN  v0.01
+
+To build :
+
+       make
+
+To install : 
+
+       sudo make install
+
+*******************************************
+
+
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/autogen.sh b/applications/hbbtvplayer/hbbtvbrowserplugin/autogen.sh
new file mode 100644 (file)
index 0000000..124f59c
--- /dev/null
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+autoreconf --install -v
+
+./configure
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/configure.ac b/applications/hbbtvplayer/hbbtvbrowserplugin/configure.ac
new file mode 100644 (file)
index 0000000..ff93781
--- /dev/null
@@ -0,0 +1,19 @@
+
+
+AC_INIT([hbbtvbrowserplugin], [0.1.0], [stanislas.selle@telecom-paristech.fr])
+
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_MACRO_DIR([m4])
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AM_INIT_AUTOMAKE([foreign -Wall -Werror])
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28.0])
+PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.20.1])
+AC_SUBST([PLUGINDIR], [/usr/lib/mozilla/plugins])
+LT_INIT
+AC_CONFIG_FILES([makefile src/makefile hbbtvbrowserplugin.pc])
+AC_OUTPUT
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/doc/hbbtvBrowserPlugin-NPAPI-20111108.pptx b/applications/hbbtvplayer/hbbtvbrowserplugin/doc/hbbtvBrowserPlugin-NPAPI-20111108.pptx
new file mode 100644 (file)
index 0000000..90203fa
Binary files /dev/null and b/applications/hbbtvplayer/hbbtvbrowserplugin/doc/hbbtvBrowserPlugin-NPAPI-20111108.pptx differ
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/doc/listeOIPFProfile.xlsx b/applications/hbbtvplayer/hbbtvbrowserplugin/doc/listeOIPFProfile.xlsx
new file mode 100644 (file)
index 0000000..b5302b4
Binary files /dev/null and b/applications/hbbtvplayer/hbbtvbrowserplugin/doc/listeOIPFProfile.xlsx differ
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.pc.in b/applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.pc.in
new file mode 100644 (file)
index 0000000..d67b557
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+plugindir=/usr/lib/mozilla/plugins/
+
+Name: hbbtvbrowserplugin
+Description: The Hbbtv BrowserPlugin (NPAPI)
+Version:@PACKAGE_VERSION@
+Cflags: -I${includedir}/hbbtvbrowserplugin
+Libs: -L${libdir} -L${plugindir} -lhbbtvbrowserplugin
+
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.vcproj b/applications/hbbtvplayer/hbbtvbrowserplugin/hbbtvbrowserplugin.vcproj
new file mode 100644 (file)
index 0000000..c54579b
--- /dev/null
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9,00"\r
+       Name="hbbtvbrowserplugin"\r
+       ProjectGUID="{CBFCB6F1-4877-4CBA-9F59-9B9ADD1D64E5}"\r
+       RootNamespace="hbbtvbrowserplugin"\r
+       Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories=".\src;&quot;.\src\webkit-plugin-header&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gtk-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gio-win32-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\cairo&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\gio&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\glib&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\glib-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\pango-1.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\gtk-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gdk-pixbuf-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\atk-1.0&quot;"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_WIN32;_WIN32_;HBBTVBROWSERPLUGIN_EXPORTS"\r
+                               GeneratePreprocessedFile="0"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                               CompileAs="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\libhbbtvbrowserplugin.lib"\r
+                               AdditionalLibraryDirectories=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories=".\src;&quot;.\src\webkit-plugin-header&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gtk-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gio-win32-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\cairo&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\gio&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\glib-2.0\glib&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\glib-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\pango-1.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\gtk-2.0\include&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\gdk-pixbuf-2.0&quot;;&quot;..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\include\atk-1.0&quot;"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_WIN32;_WIN32_;HBBTVBROWSERPLUGIN_EXPORTS"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="..\hbbtvterminal\Win32Build\WebKitGTK-Bundle\lib\libhbbtvbrowserplugin.lib"                         \r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Fichiers sources"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\src\applicationclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\applicationprivatedataclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\configurationclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\downloadclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\downloadcollectionclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\drmcontrolinfocollectionclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\drmcontrolinformationclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvbrowserplugin.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvbrowserpluginapi.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\keysetclass.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfapplicationmanager.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfconfiguration.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfdownloadmanager.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfdownloadtrigger.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\videobroadcast.c"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Fichiers d&apos;en-tête"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\src\applicationclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\applicationprivatedataclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\configurationclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\downloadclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\downloadcollectionclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\drmcontrolinfocollectionclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\drmcontrolinformationclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvbrowserplugin.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvbrowserpluginapi.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvkeyset.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\keysetclass.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfapplicationmanager.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfconfiguration.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfdownloadmanager.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\oipfdownloadtrigger.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\videobroadcast.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Fichiers de ressources"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"\r
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/makefile.am b/applications/hbbtvplayer/hbbtvbrowserplugin/makefile.am
new file mode 100644 (file)
index 0000000..585a151
--- /dev/null
@@ -0,0 +1,7 @@
+SUBDIRS = src
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = hbbtvbrowserplugin.pc
+
+
+
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/makefile.old b/applications/hbbtvplayer/hbbtvbrowserplugin/makefile.old
new file mode 100644 (file)
index 0000000..cea09b8
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+####
+#### MAKEFILE
+####
+#### Copyright Telecom Paristech 2011  
+####
+#### Author : Stanislas Selle
+####
+###############################################################################
+
+###############################################################################
+## Files and Path
+
+PLUGINDIR = /usr/lib/mozilla/plugins
+INSTALL_INCLUDEDIR = /usr/local/include/hbbtvbrowserplugin
+INSTALL_LIBDIR = /usr/local/lib
+INSTALL_PKGDIR = /usr/lib/pkgconfig
+
+PKGFILE = hbbtvbrowserplugin.pc
+
+MAINTARGET = bin/libhbbtvbrowserplugin.so
+
+SRCDIR = src
+HEADERSDIR = src
+
+OBJ =  obj/hbbtvbrowserplugin.o\
+               obj/oipfapplicationmanager.o\
+               obj/applicationclass.o\
+               obj/applicationprivatedataclass.o\
+               obj/oipfconfiguration.o\
+               obj/configurationclass.o\
+               obj/oipfdownloadmanager.o\
+               obj/oipfdownloadtrigger.o\
+               obj/downloadclass.o\
+               obj/downloadcollectionclass.o\
+               obj/drmcontrolinfocollectionclass.o\
+               obj/drmcontrolinformationclass.o\
+               obj/videobroadcast.o\
+               obj/keysetclass.o
+
+EXPORTHEADERS = hbbtvbrowserpluginapi.h
+
+#TESTURL = file:///home/selle/ressources/HbbTVapps/TPT/app1/index.html
+TESTURL = http://aquila.enst.fr:8080/subwebsite/hbbtvtest/test0003/index.php
+TESTLOG = /tmp/test-err.txt
+###############################################################################
+## Programs
+
+COMPILER       = cc
+DELETER                = rm -f
+BROWSERTEST    = firefox
+
+
+###############################################################################
+## Options, Flags and LinkS
+
+CFLAGS = -Wall -DXP_UNIX=1 -DMOZ_X11=1 -fPIC -g
+
+INCLUDEFLAGS = -Isrc
+LIBRARYFLAGS =
+
+FROMPKG = libxul
+
+PKGFLAGS = `pkg-config --cflags $(FROMPKG) `
+PKGLIBS = `pkg-config --libs $(FROMPKG) `
+
+INCLUDEFLAGS += $(PKGFLAGS)
+LIBRARYFLAGS += $(PKGLIBS)
+
+###############################################################################
+## Rules
+
+all : $(MAINTARGET)
+
+$(MAINTARGET) : $(OBJ)
+       @echo "====> Compiling $(MAINTARGET)"
+       $(COMPILER) $(CFLAGS) $(LIBRARYFLAGS) -shared $(OBJ) -o $(MAINTARGET)
+
+obj/%.o: $(SRCDIR)/%.c $(HEADERSDIR)/%.h
+       @echo "====> Compiling $< "
+       $(COMPILER) $(CFLAGS) -c $< $(INCLUDEFLAGS) -o $@
+
+test : all
+       $(BROWSERTEST) $(TESTURL)  2> $(TESTLOG); cat $(TESTLOG)
+
+install : all
+       @echo "====> Installing"
+       cp $(MAINTARGET) $(PLUGINDIR)
+       @if test -d $(INSTALL_INCLUDEDIR);\
+               then echo " ===> $(INSTALL_INCLUDEDIR) existing already" ; \
+       else mkdir $(INSTALL_INCLUDEDIR); fi;
+       cp $(HEADERSDIR)/$(EXPORTHEADERS) $(INSTALL_INCLUDEDIR)
+       cp $(PKGFILE) $(INSTALL_PKGDIR)
+       @echo "Done."
+
+uninstall :
+       @echo "====> Uninstalling"
+       $(DELETER) $(INSTALL_PKGDIR)/$(PKGFILE) $(INSTALL_INCLUDEDIR)/$(EXPORTHEADERS) $(INSTALL_INCLUDEDIR)/$(MAINTARGET)
+       if test -d $(INSTALL_INCLUDEDIR);\
+               then rmdir $(INSTALL_INCLUDEDIR); fi;
+
+clean :
+       @echo "====> Cleaning"
+       @$(DELETER) $(OBJ)
+       @echo "Deleting objects"
+       @$(DELETER) $(MAINTARGET)
+       @echo "Deleting $(MAINTARGET)"
+
+###############################################################################
+###############################################################################
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.cbp b/applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.cbp
new file mode 100644 (file)
index 0000000..54b6c97
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="hbbtvbrowserplugin" />
+               <Option pch_mode="2" />
+               <Option compiler="gcc" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin/Debug/hbbtvbrowserplugin" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj/Debug/" />
+                               <Option type="1" />
+                               <Option compiler="gcc" />
+                               <Compiler>
+                                       <Add option="-g" />
+                               </Compiler>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+               </Compiler>
+               <Unit filename="../../../autogen.sh" />
+               <Unit filename="../../../configure.ac" />
+               <Unit filename="../../../makefile.am" />
+               <Unit filename="../../../makefile.old" />
+               <Unit filename="../../../src/applicationclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/applicationclass.h" />
+               <Unit filename="../../../src/applicationprivatedataclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/applicationprivatedataclass.h" />
+               <Unit filename="../../../src/configurationclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/configurationclass.h" />
+               <Unit filename="../../../src/downloadclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/downloadclass.h" />
+               <Unit filename="../../../src/downloadcollectionclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/downloadcollectionclass.h" />
+               <Unit filename="../../../src/drmcontrolinfocollectionclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/drmcontrolinfocollectionclass.h" />
+               <Unit filename="../../../src/drmcontrolinformationclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/drmcontrolinformationclass.h" />
+               <Unit filename="../../../src/hbbtvbrowserplugin.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/hbbtvbrowserplugin.h" />
+               <Unit filename="../../../src/hbbtvbrowserpluginapi.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/hbbtvbrowserpluginapi.h" />
+               <Unit filename="../../../src/keysetclass.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/keysetclass.h" />
+               <Unit filename="../../../src/makefile.am" />
+               <Unit filename="../../../src/oipfapplicationmanager.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/oipfapplicationmanager.h" />
+               <Unit filename="../../../src/oipfconfiguration.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/oipfconfiguration.h" />
+               <Unit filename="../../../src/oipfdownloadmanager.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/oipfdownloadmanager.h" />
+               <Unit filename="../../../src/oipfdownloadtrigger.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/oipfdownloadtrigger.h" />
+               <Unit filename="../../../src/videobroadcast.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../../../src/videobroadcast.h" />
+               <Extensions>
+                       <code_completion />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.layout b/applications/hbbtvplayer/hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.layout
new file mode 100644 (file)
index 0000000..5c17549
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+       <ActiveTarget name="Debug" />
+       <File name="../../../autogen.sh" open="1" top="0" tabpos="5">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../configure.ac" open="1" top="0" tabpos="4">
+               <Cursor position="443" topLine="0" />
+       </File>
+       <File name="../../../makefile.am" open="1" top="1" tabpos="1">
+               <Cursor position="116" topLine="0" />
+       </File>
+       <File name="../../../makefile.old" open="1" top="0" tabpos="3">
+               <Cursor position="2670" topLine="56" />
+       </File>
+       <File name="../../../src/applicationclass.c" open="0" top="0" tabpos="4">
+               <Cursor position="5525" topLine="169" />
+       </File>
+       <File name="../../../src/applicationclass.h" open="0" top="0" tabpos="4">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/applicationprivatedataclass.c" open="0" top="0" tabpos="3">
+               <Cursor position="0" topLine="72" />
+       </File>
+       <File name="../../../src/applicationprivatedataclass.h" open="0" top="0" tabpos="8">
+               <Cursor position="1066" topLine="0" />
+       </File>
+       <File name="../../../src/configurationclass.c" open="0" top="0" tabpos="6">
+               <Cursor position="2608" topLine="0" />
+       </File>
+       <File name="../../../src/configurationclass.h" open="0" top="0" tabpos="7">
+               <Cursor position="1064" topLine="0" />
+       </File>
+       <File name="../../../src/downloadclass.c" open="0" top="0" tabpos="13">
+               <Cursor position="904" topLine="12" />
+       </File>
+       <File name="../../../src/downloadclass.h" open="0" top="0" tabpos="10">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/downloadcollectionclass.c" open="0" top="0" tabpos="15">
+               <Cursor position="567" topLine="0" />
+       </File>
+       <File name="../../../src/downloadcollectionclass.h" open="0" top="0" tabpos="9">
+               <Cursor position="68" topLine="0" />
+       </File>
+       <File name="../../../src/drmcontrolinfocollectionclass.c" open="0" top="0" tabpos="1">
+               <Cursor position="44" topLine="0" />
+       </File>
+       <File name="../../../src/drmcontrolinfocollectionclass.h" open="0" top="0" tabpos="38">
+               <Cursor position="78" topLine="0" />
+       </File>
+       <File name="../../../src/drmcontrolinformationclass.c" open="0" top="0" tabpos="2">
+               <Cursor position="44" topLine="0" />
+       </File>
+       <File name="../../../src/drmcontrolinformationclass.h" open="0" top="0" tabpos="39">
+               <Cursor position="72" topLine="0" />
+       </File>
+       <File name="../../../src/hbbtvbrowserplugin.c" open="1" top="0" tabpos="7">
+               <Cursor position="3316" topLine="104" />
+       </File>
+       <File name="../../../src/hbbtvbrowserplugin.h" open="0" top="0" tabpos="1">
+               <Cursor position="117" topLine="0" />
+       </File>
+       <File name="../../../src/hbbtvbrowserpluginapi.c" open="1" top="0" tabpos="6">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/keysetclass.c" open="0" top="0" tabpos="16">
+               <Cursor position="26" topLine="0" />
+       </File>
+       <File name="../../../src/keysetclass.h" open="0" top="0" tabpos="5">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/makefile.am" open="1" top="0" tabpos="2">
+               <Cursor position="1283" topLine="0" />
+       </File>
+       <File name="../../../src/oipfapplicationmanager.c" open="0" top="0" tabpos="3">
+               <Cursor position="3766" topLine="128" />
+       </File>
+       <File name="../../../src/oipfapplicationmanager.h" open="0" top="0" tabpos="12">
+               <Cursor position="374" topLine="0" />
+       </File>
+       <File name="../../../src/oipfconfiguration.c" open="0" top="0" tabpos="5">
+               <Cursor position="3172" topLine="100" />
+       </File>
+       <File name="../../../src/oipfconfiguration.h" open="0" top="0" tabpos="11">
+               <Cursor position="960" topLine="0" />
+       </File>
+       <File name="../../../src/oipfdownloadmanager.c" open="0" top="0" tabpos="5">
+               <Cursor position="5717" topLine="169" />
+       </File>
+       <File name="../../../src/oipfdownloadmanager.h" open="0" top="0" tabpos="11">
+               <Cursor position="840" topLine="0" />
+       </File>
+       <File name="../../../src/oipfdownloadtrigger.c" open="0" top="0" tabpos="4">
+               <Cursor position="158" topLine="0" />
+       </File>
+       <File name="../../../src/oipfdownloadtrigger.h" open="0" top="0" tabpos="9">
+               <Cursor position="103" topLine="0" />
+       </File>
+       <File name="../../../src/videobroadcast.c" open="0" top="0" tabpos="2">
+               <Cursor position="5797" topLine="185" />
+       </File>
+       <File name="../../../src/videobroadcast.h" open="0" top="0" tabpos="13">
+               <Cursor position="274" topLine="0" />
+       </File>
+</CodeBlocks_layout_file>
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/releases/hbbtvbrowserplugin-0.01.tar.gz b/applications/hbbtvplayer/hbbtvbrowserplugin/releases/hbbtvbrowserplugin-0.01.tar.gz
new file mode 100644 (file)
index 0000000..c8595c8
Binary files /dev/null and b/applications/hbbtvplayer/hbbtvbrowserplugin/releases/hbbtvbrowserplugin-0.01.tar.gz differ
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.c
new file mode 100644 (file)
index 0000000..f804fcd
--- /dev/null
@@ -0,0 +1,265 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "applicationprivatedataclass.h"\r
+#include "applicationclass.h"\r
+\r
+#define kAPPLICATION_ID_PROPERTY_VISIBLE                           0\r
+#define kAPPLICATION_ID_PROPERTY_PRIVATEDATA                   1\r
+#define kAPPLICATION_NUM_PROPERTY_IDENTIFIERS                   2\r
+\r
+#define kAPPLICATION_ID_METHOD_CREATEAPPLICATION               0\r
+#define kAPPLICATION_ID_METHOD_DESTROYAPPLICATION              1\r
+#define kAPPLICATION_ID_METHOD_SHOW                             2\r
+#define kAPPLICATION_ID_METHOD_HIDE                             3\r
+#define kAPPLICATION_NUM_METHOD_IDENTIFIERS                            4\r
+\r
+\r
+static  bool            v_bAPPLICATIONIdentifiersInitialized = false;\r
+\r
+static  NPIdentifier    v_APPLICATIONPropertyIdentifiers[kAPPLICATION_NUM_PROPERTY_IDENTIFIERS];\r
+static  const NPUTF8 *  v_APPLICATIONPropertyNames[kAPPLICATION_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "visible",\r
+       "privateData"\r
+};\r
+\r
+static  NPIdentifier    v_APPLICATIONMethodIdentifiers[kAPPLICATION_NUM_METHOD_IDENTIFIERS];\r
+static  const NPUTF8 *  v_APPLICATIONMethodNames[kAPPLICATION_NUM_METHOD_IDENTIFIERS] = {\r
+    "createApplication",\r
+    "destroyApplication",\r
+    "show",\r
+    "hide"\r
+};\r
+\r
+\r
+static  void    APPLICATIONinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_APPLICATIONPropertyNames, kAPPLICATION_NUM_PROPERTY_IDENTIFIERS, v_APPLICATIONPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_APPLICATIONMethodNames,   kAPPLICATION_NUM_METHOD_IDENTIFIERS,   v_APPLICATIONMethodIdentifiers );\r
+}\r
+\r
+NPClass  stAPPLICATIONclass;\r
+NPClass* pAPPLICATIONclass = NULL;\r
+\r
+NPClass* fillAPPLICATIONpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pAPPLICATIONclass == NULL)\r
+    {\r
+        stAPPLICATIONclass.allocate          = APPLICATION_Allocate;\r
+        stAPPLICATIONclass.deallocate        = APPLICATION_Deallocate;\r
+        stAPPLICATIONclass.invalidate        = APPLICATION_Invalidate;\r
+        stAPPLICATIONclass.hasMethod         = APPLICATION_HasMethod;\r
+        stAPPLICATIONclass.invoke            = APPLICATION_Invoke;\r
+        stAPPLICATIONclass.invokeDefault     = APPLICATION_InvokeDefault;\r
+        stAPPLICATIONclass.hasProperty       = APPLICATION_HasProperty;\r
+        stAPPLICATIONclass.getProperty       = APPLICATION_GetProperty;\r
+        stAPPLICATIONclass.setProperty       = APPLICATION_SetProperty;\r
+        stAPPLICATIONclass.removeProperty    = APPLICATION_RemoveProperty;\r
+        stAPPLICATIONclass.enumerate         = APPLICATION_Enumerate;\r
+        pAPPLICATIONclass = &stAPPLICATIONclass;\r
+    }\r
+\r
+    return pAPPLICATIONclass;\r
+}\r
+\r
+\r
+NPObject *          APPLICATION_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+    if (!v_bAPPLICATIONIdentifiersInitialized)\r
+    {\r
+        v_bAPPLICATIONIdentifiersInitialized = true;\r
+        APPLICATIONinitializeIdentifiers();\r
+    }\r
+    \r
+    NPObj_Application* newapplication = (NPObj_Application*)MEMALLOC(sizeof(NPObj_Application));\r
+    fprintf(stderr, "\t%s : Allocation at \x1b[%i;3%im%p\n\x1b[0m",__FUNCTION__, 1, 1, newapplication );\r
+       newapplication->npp = npp;      \r
+       newapplication->visible = true;\r
+    newapplication->privateData = sBrowserFuncs->createobject(npp, fillAPPPRIVDATApclass());\r
+    fprintf(stderr, "\t%s : Create privateData property at \x1b[%i;3%im%p\n\x1b[0m ",__FUNCTION__,  1, 1, newapplication->privateData );\r
+       newapplication->visible = true;\r
+    return (NPObject*)newapplication;\r
+}\r
+\r
+  void        APPLICATION_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    NPObj_Application* applicationobj = (NPObj_Application*)obj;\r
+    sBrowserFuncs->releaseobject(applicationobj->privateData);\r
+    MEMFREE(applicationobj);\r
+    return;\r
+}\r
+\r
+  void        APPLICATION_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        APPLICATION_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kAPPLICATION_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_APPLICATIONMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+       \r
+    return result;\r
+}\r
+\r
+bool        APPLICATION_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+       bool fctresult = false;\r
+    if (name == v_APPLICATIONMethodIdentifiers[kAPPLICATION_ID_METHOD_CREATEAPPLICATION])\r
+    {\r
+               APPLICATION_Invoke_CreateApplication(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else if (name == v_APPLICATIONMethodIdentifiers[kAPPLICATION_ID_METHOD_DESTROYAPPLICATION])\r
+    {\r
+               APPLICATION_Invoke_DestroyApplication(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else if (name == v_APPLICATIONMethodIdentifiers[kAPPLICATION_ID_METHOD_HIDE])\r
+    {\r
+               APPLICATION_Invoke_Hide(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+       else if (name == v_APPLICATIONMethodIdentifiers[kAPPLICATION_ID_METHOD_SHOW])\r
+    {\r
+               APPLICATION_Invoke_Show(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {       \r
+        fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+ bool        APPLICATION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        APPLICATION_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kAPPLICATION_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_APPLICATIONPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+  \r
+    return result;\r
+}\r
+\r
+bool        APPLICATION_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+   \r
+    bool fctresult = false;\r
+    NPObj_Application* AppliObj = (NPObj_Application*)obj;\r
+    \r
+    if (name == v_APPLICATIONPropertyIdentifiers[kAPPLICATION_ID_PROPERTY_PRIVATEDATA])\r
+    {                          \r
+               sBrowserFuncs->retainobject(AppliObj->privateData);\r
+               OBJECT_TO_NPVARIANT(AppliObj->privateData, *result);    \r
+       fctresult = true;\r
+    }\r
+    else  if (name == v_APPLICATIONPropertyIdentifiers[kAPPLICATION_ID_PROPERTY_VISIBLE])\r
+    {                          \r
+               BOOLEAN_TO_NPVARIANT(AppliObj->visible, *result);\r
+               fctresult = true;\r
+    }\r
+    else\r
+               \r
+    return fctresult;\r
+}\r
+\r
+  bool        APPLICATION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        APPLICATION_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        APPLICATION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+/** implementation **/\r
+\r
+void APPLICATION_Invoke_CreateApplication(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void APPLICATION_Invoke_DestroyApplication(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void APPLICATION_Invoke_Show(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;      \r
+       NPObj_Application* AppliObj = (NPObj_Application*)obj;\r
+       OnAPPLICATION_Show();\r
+       AppliObj->visible = true;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void APPLICATION_Invoke_Hide(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       \r
+       NPObj_Application* AppliObj = (NPObj_Application*)obj;\r
+       OnAPPLICATION_Hide();\r
+       AppliObj->visible = false;\r
+       NOTIMPLEMENTED; \r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationclass.h
new file mode 100644 (file)
index 0000000..967c1f5
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __APPLICATIONCLASS_H__\r
+#define __APPLICATIONCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+typedef struct\r
+{\r
+       NPObject header;        \r
+       NPP npp; \r
+       \r
+       NPBool      visible;\r
+       NPObject*   privateData;\r
+       \r
+} NPObj_Application;\r
+\r
+\r
+NPClass* fillAPPLICATIONpclass(void);\r
+\r
+NPObject *  APPLICATION_Allocate(NPP npp, NPClass *aClass);\r
+void        APPLICATION_Deallocate(NPObject *obj);\r
+void        APPLICATION_Invalidate(NPObject *obj);\r
+bool        APPLICATION_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        APPLICATION_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        APPLICATION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        APPLICATION_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        APPLICATION_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        APPLICATION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        APPLICATION_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        APPLICATION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+\r
+void APPLICATION_Invoke_CreateApplication(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void APPLICATION_Invoke_DestroyApplication(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void APPLICATION_Invoke_Show(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void APPLICATION_Invoke_Hide(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.c
new file mode 100644 (file)
index 0000000..fdb8443
--- /dev/null
@@ -0,0 +1,219 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "applicationprivatedataclass.h"\r
+\r
+#define kAPPPRIVDATA_ID_PROPERTY_KEYSET                                                0\r
+#define kAPPPRIVDATA_ID_PROPERTY_CURRENTCHANNEL                                1\r
+#define kAPPPRIVDATA_NUM_PROPERTY_IDENTIFIERS                   2\r
+\r
+#define kAPPPRIVDATA_ID_METHOD_GETMEMFREE                          0\r
+#define kAPPPRIVDATA_NUM_METHOD_IDENTIFIERS                        1\r
+\r
+\r
+\r
+bool            v_bAPPPRIVDATAIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_APPPRIVDATAPropertyIdentifiers[kAPPPRIVDATA_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_APPPRIVDATAPropertyNames[kAPPPRIVDATA_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "keyset",\r
+    "currentChannel"\r
+    };\r
+\r
+NPIdentifier    v_APPPRIVDATAMethodIdentifiers[kAPPPRIVDATA_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_APPPRIVDATAMethodNames[kAPPPRIVDATA_NUM_METHOD_IDENTIFIERS] = {\r
+       "getMEMFREE"\r
+       };\r
+\r
+static  void    APPPRIVDATAinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_APPPRIVDATAPropertyNames, kAPPPRIVDATA_NUM_PROPERTY_IDENTIFIERS, v_APPPRIVDATAPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_APPPRIVDATAMethodNames,   kAPPPRIVDATA_NUM_METHOD_IDENTIFIERS,   v_APPPRIVDATAMethodIdentifiers );\r
+}\r
+\r
+\r
+NPClass  stAPPPRIVDATAclass;\r
+NPClass* pAPPPRIVDATAclass = NULL;\r
+\r
+NPClass* fillAPPPRIVDATApclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pAPPPRIVDATAclass == NULL)\r
+    {\r
+        stAPPPRIVDATAclass.allocate          = APPPRIVDATA_Allocate;\r
+        stAPPPRIVDATAclass.deallocate        = APPPRIVDATA_Deallocate;\r
+        stAPPPRIVDATAclass.invalidate        = APPPRIVDATA_Invalidate;\r
+        stAPPPRIVDATAclass.hasMethod         = APPPRIVDATA_HasMethod;\r
+        stAPPPRIVDATAclass.invoke            = APPPRIVDATA_Invoke;\r
+        stAPPPRIVDATAclass.invokeDefault     = APPPRIVDATA_InvokeDefault;\r
+        stAPPPRIVDATAclass.hasProperty       = APPPRIVDATA_HasProperty;\r
+        stAPPPRIVDATAclass.getProperty       = APPPRIVDATA_GetProperty;\r
+        stAPPPRIVDATAclass.setProperty       = APPPRIVDATA_SetProperty;\r
+        stAPPPRIVDATAclass.removeProperty    = APPPRIVDATA_RemoveProperty;\r
+        stAPPPRIVDATAclass.enumerate         = APPPRIVDATA_Enumerate;\r
+        pAPPPRIVDATAclass = &stAPPPRIVDATAclass;\r
+    }\r
+\r
+    return pAPPPRIVDATAclass;\r
+}\r
+\r
+\r
+NPObject *          APPPRIVDATA_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    NPObject* result;\r
+\r
+    \r
+    if (!v_bAPPPRIVDATAIdentifiersInitialized)\r
+    {\r
+        v_bAPPPRIVDATAIdentifiersInitialized = true;\r
+        APPPRIVDATAinitializeIdentifiers();\r
+    }\r
+               \r
+       NPObj_AppPrivData* newappprivdata = (NPObj_AppPrivData*)MEMALLOC(sizeof(NPObj_AppPrivData));    \r
+       fprintf(stderr, "\t%s : Allocation at \x1b[%i;3%im%p\n\x1b[0m",__FUNCTION__, 1, 1, newappprivdata);    \r
+    newappprivdata->npp = npp;\r
+    newappprivdata->keyset = sBrowserFuncs->createobject(npp, fillKEYSETpclass());    \r
+    fprintf(stderr, "\t%s : Create keyset property at \x1b[%i;3%im%p\n\x1b[0m",__FUNCTION__, 1, 1, newappprivdata->keyset );\r
+    result = (NPObject*)newappprivdata;\r
+    return result;\r
+}\r
+\r
+\r
+void        APPPRIVDATA_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    NPObj_AppPrivData* appprivdataobj = (NPObj_AppPrivData*)obj;\r
+    sBrowserFuncs->releaseobject(appprivdataobj->keyset);\r
+    MEMFREE(appprivdataobj);\r
+    return;\r
+}\r
+\r
+void        APPPRIVDATA_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+bool        APPPRIVDATA_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+       bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kAPPPRIVDATA_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_APPPRIVDATAMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+bool        APPPRIVDATA_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    if (name == v_APPPRIVDATAMethodIdentifiers[kAPPPRIVDATA_ID_METHOD_GETMEMFREE])\r
+    {\r
+               APPPRIVDATA_Invoke_GetFreeMen(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {          \r
+       fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+bool        APPPRIVDATA_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        APPPRIVDATA_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kAPPPRIVDATA_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_APPPRIVDATAPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+   \r
+    return result;\r
+}\r
+\r
+bool        APPPRIVDATA_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+   \r
+    bool fctresult = false;\r
+       NPObj_AppPrivData* AppPrivDataObj = (NPObj_AppPrivData*)obj;\r
+       if (!strcmp(sBrowserFuncs->utf8fromidentifier(name), v_APPPRIVDATAPropertyNames[kAPPPRIVDATA_ID_PROPERTY_KEYSET]))    \r
+    {          \r
+               sBrowserFuncs->retainobject(AppPrivDataObj->keyset);\r
+               OBJECT_TO_NPVARIANT(AppPrivDataObj->keyset, *result);\r
+               \r
+       fctresult = true;\r
+    }\r
+    else\r
+               \r
+    return fctresult;\r
+}\r
+\r
+bool        APPPRIVDATA_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    return fctresult;\r
+}\r
+\r
+bool        APPPRIVDATA_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+bool        APPPRIVDATA_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+/** implementation **/\r
+void APPPRIVDATA_Invoke_GetFreeMen(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/applicationprivatedataclass.h
new file mode 100644 (file)
index 0000000..fc8a867
--- /dev/null
@@ -0,0 +1,54 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __APPLICATIONPRIVATEDATACLASS_H__\r
+#define __APPLICATIONPRIVATEDATACLASS_H__\r
+\r
+#include "keysetclass.h"\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+typedef struct\r
+{\r
+       NPObject header;        \r
+       NPP npp; \r
+\r
+    NPObject*   keyset;        \r
+    NPObject*   currentChannel;        \r
+} NPObj_AppPrivData;\r
+\r
+NPClass* fillAPPPRIVDATApclass(void);\r
+\r
+NPObject *  APPPRIVDATA_Allocate(NPP npp, NPClass *aClass);\r
+void        APPPRIVDATA_Deallocate(NPObject *obj);\r
+void        APPPRIVDATA_Invalidate(NPObject *obj);\r
+bool        APPPRIVDATA_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        APPPRIVDATA_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        APPPRIVDATA_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        APPPRIVDATA_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        APPPRIVDATA_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        APPPRIVDATA_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        APPPRIVDATA_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        APPPRIVDATA_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+void APPPRIVDATA_Invoke_GetFreeMen(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.c
new file mode 100644 (file)
index 0000000..b4f14ff
--- /dev/null
@@ -0,0 +1,182 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle                \r
+ *                             \r
+ */\r
+#include "configurationclass.h"\r
+\r
+\r
+#define kCONFIGURATION_ID_PROPERTY_PREFERREDAUDIOLANGUAGE              0\r
+#define kCONFIGURATION_ID_PROPERTY_PREFERREDSUBTITLELANGUAGE   1\r
+#define kCONFIGURATION_ID_PROPERTY_COUNTRYID                                   2\r
+#define kCONFIGURATION_NUM_PROPERTY_IDENTIFIERS                                    3\r
+\r
+#define kCONFIGURATION_NUM_METHOD_IDENTIFIERS                  0\r
+\r
+\r
+\r
+bool            v_bCONFIGURATIONIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_CONFIGURATIONPropertyIdentifiers[kCONFIGURATION_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_CONFIGURATIONPropertyNames[kCONFIGURATION_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "preferredAudioLanguage",\r
+    "preferredSubtitleLanguage",\r
+    "countryId"\r
+    };\r
+\r
+NPIdentifier    v_CONFIGURATIONMethodIdentifiers[kCONFIGURATION_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_CONFIGURATIONMethodNames[kCONFIGURATION_NUM_METHOD_IDENTIFIERS] = {};\r
+\r
+static  void    CONFIGURATIONinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_CONFIGURATIONPropertyNames, kCONFIGURATION_NUM_PROPERTY_IDENTIFIERS, v_CONFIGURATIONPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_CONFIGURATIONMethodNames,   kCONFIGURATION_NUM_METHOD_IDENTIFIERS,   v_CONFIGURATIONMethodIdentifiers );\r
+}\r
+\r
+\r
+NPClass  stCONFIGURATIONclass;\r
+NPClass* pCONFIGURATIONclass = NULL;\r
+\r
+NPClass* fillCONFIGURATIONpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pCONFIGURATIONclass == NULL)\r
+    {\r
+        stCONFIGURATIONclass.allocate          = CONFIGURATION_Allocate;\r
+        stCONFIGURATIONclass.deallocate        = CONFIGURATION_Deallocate;\r
+        stCONFIGURATIONclass.invalidate        = CONFIGURATION_Invalidate;\r
+        stCONFIGURATIONclass.hasMethod         = CONFIGURATION_HasMethod;\r
+        stCONFIGURATIONclass.invoke            = CONFIGURATION_Invoke;\r
+        stCONFIGURATIONclass.invokeDefault     = CONFIGURATION_InvokeDefault;\r
+        stCONFIGURATIONclass.hasProperty       = CONFIGURATION_HasProperty;\r
+        stCONFIGURATIONclass.getProperty       = CONFIGURATION_GetProperty;\r
+        stCONFIGURATIONclass.setProperty       = CONFIGURATION_SetProperty;\r
+        stCONFIGURATIONclass.removeProperty    = CONFIGURATION_RemoveProperty;\r
+        stCONFIGURATIONclass.enumerate         = CONFIGURATION_Enumerate;\r
+        pCONFIGURATIONclass = &stCONFIGURATIONclass;\r
+    }\r
+\r
+    return pCONFIGURATIONclass;\r
+}\r
+\r
+\r
+NPObject *          CONFIGURATION_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+    \r
+    if (!v_bCONFIGURATIONIdentifiersInitialized)\r
+    {\r
+        v_bCONFIGURATIONIdentifiersInitialized = true;\r
+        CONFIGURATIONinitializeIdentifiers();\r
+    }\r
+       NPObject* newconfiguration = NULL;\r
+       \r
+    newconfiguration = (NPObject *)MEMALLOC(sizeof(NPObject));\r
+\r
+    return newconfiguration;\r
+}\r
+\r
+\r
+void        CONFIGURATION_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+     MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+void        CONFIGURATION_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+bool        CONFIGURATION_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+       bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kCONFIGURATION_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_CONFIGURATIONMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+bool        CONFIGURATION_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        CONFIGURATION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        CONFIGURATION_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kCONFIGURATION_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_CONFIGURATIONPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    \r
+    return result;\r
+}\r
+\r
+bool        CONFIGURATION_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        CONFIGURATION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        CONFIGURATION_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+bool        CONFIGURATION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/configurationclass.h
new file mode 100644 (file)
index 0000000..ddba67b
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __CONFIGURATIONCLASS_H__\r
+#define __CONFIGURATIONCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+NPClass* fillCONFIGURATIONpclass(void);\r
+\r
+NPObject *  CONFIGURATION_Allocate(NPP npp, NPClass *aClass);\r
+void        CONFIGURATION_Deallocate(NPObject *obj);\r
+void        CONFIGURATION_Invalidate(NPObject *obj);\r
+bool        CONFIGURATION_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        CONFIGURATION_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        CONFIGURATION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        CONFIGURATION_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        CONFIGURATION_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        CONFIGURATION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        CONFIGURATION_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        CONFIGURATION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.c
new file mode 100644 (file)
index 0000000..6cfb967
--- /dev/null
@@ -0,0 +1,209 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle                \r
+ *                             \r
+ */\r
+#include "downloadclass.h"\r
+\r
+#define kDOWNLOAD_ID_PROPERTY_TOTALIZE                     0\r
+#define kDOWNLOAD_ID_PROPERTY_STATE                                    1\r
+#define kDOWNLOAD_ID_PROPERTY_AMOUNTDOWNLOADED         2\r
+#define kDOWNLOAD_ID_PROPERTY_NAME                                     3\r
+#define kDOWNLOAD_ID_PROPERTY_ID                                       4\r
+#define kDOWNLOAD_ID_PROPERTY_CONTENTURL                       5\r
+#define kDOWNLOAD_ID_PROPERTY_DESCRIPTION                      6\r
+#define kDOWNLOAD_ID_PROPERTY_PARENTALRATINGS          7\r
+#define kDOWNLOAD_ID_PROPERTY_DRMCONTROL                       8\r
+#define kDOWNLOAD_ID_PROPERTY_STARTTIME                                9\r
+#define kDOWNLOAD_ID_PROPERTY_TIMEELAPSED                      10\r
+#define kDOWNLOAD_ID_PROPERTY_TIMEREMAINING                    11\r
+#define kDOWNLOAD_ID_PROPERTY_TRANSFERTYPE                     12\r
+#define kDOWNLOAD_ID_PROPERTY_ORIGINSITE                       13\r
+#define kDOWNLOAD_ID_PROPERTY_ORIGINSITENAME           14\r
+#define kDOWNLOAD_ID_PROPERTY_CONTENTID                                15\r
+#define kDOWNLOAD_ID_PROPERTY_ICONURL                          16\r
+#define kDOWNLOAD_NUM_PROPERTY_IDENTIFIERS                     17\r
+\r
+\r
+#define kDOWNLOAD_NUM_METHOD_IDENTIFIERS               0\r
+\r
+\r
+bool            v_bDOWNLOADIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_DOWNLOADPropertyIdentifiers[kDOWNLOAD_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_DOWNLOADPropertyNames[kDOWNLOAD_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "totalize",\r
+       "state",\r
+       "amountDownloaded",\r
+       "name",\r
+       "id",\r
+       "contentURL",\r
+       "description",\r
+       "parentalRatings",\r
+       "drmControl",\r
+       "startTime",\r
+       "timeElapsed",\r
+       "timeRemaining",\r
+       "transferType",\r
+       "originSite",\r
+       "originSiteName",\r
+       "contentID",\r
+       "iconURL"\r
+       };\r
+\r
+NPIdentifier    v_DOWNLOADMethodIdentifiers[kDOWNLOAD_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_DOWNLOADMethodNames[kDOWNLOAD_NUM_METHOD_IDENTIFIERS] = {\r
+};\r
+\r
+\r
+static  void    DOWNLOADinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_DOWNLOADPropertyNames, kDOWNLOAD_NUM_PROPERTY_IDENTIFIERS, v_DOWNLOADPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_DOWNLOADMethodNames,   kDOWNLOAD_NUM_METHOD_IDENTIFIERS,   v_DOWNLOADMethodIdentifiers );\r
+}\r
+\r
+NPClass  stDOWNLOADclass;\r
+NPClass* pDOWNLOADclass = NULL;\r
+\r
+NPClass* fillDOWNLOADpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pDOWNLOADclass == NULL)\r
+    {\r
+        stDOWNLOADclass.allocate          = DOWNLOAD_Allocate;\r
+        stDOWNLOADclass.deallocate        = DOWNLOAD_Deallocate;\r
+        stDOWNLOADclass.invalidate        = DOWNLOAD_Invalidate;\r
+        stDOWNLOADclass.hasMethod         = DOWNLOAD_HasMethod;\r
+        stDOWNLOADclass.invoke            = DOWNLOAD_Invoke;\r
+        stDOWNLOADclass.invokeDefault     = DOWNLOAD_InvokeDefault;\r
+        stDOWNLOADclass.hasProperty       = DOWNLOAD_HasProperty;\r
+        stDOWNLOADclass.getProperty       = DOWNLOAD_GetProperty;\r
+        stDOWNLOADclass.setProperty       = DOWNLOAD_SetProperty;\r
+        stDOWNLOADclass.removeProperty    = DOWNLOAD_RemoveProperty;\r
+        stDOWNLOADclass.enumerate         = DOWNLOAD_Enumerate;\r
+        pDOWNLOADclass = &stDOWNLOADclass;\r
+    }\r
+\r
+    return pDOWNLOADclass;\r
+}\r
+\r
+\r
+NPObject *          DOWNLOAD_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    \r
+    if (!v_bDOWNLOADIdentifiersInitialized)\r
+    {\r
+        v_bDOWNLOADIdentifiersInitialized = true;\r
+        DOWNLOADinitializeIdentifiers();\r
+    }\r
+\r
+    NPObject* newdownload = (NPObject *)MEMALLOC(sizeof(NPObject));\r
+\r
+    return newdownload;\r
+}\r
+\r
+  void        DOWNLOAD_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+  void        DOWNLOAD_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        DOWNLOAD_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kDOWNLOAD_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_DOWNLOADMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+bool        DOWNLOAD_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        DOWNLOAD_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        DOWNLOAD_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kDOWNLOAD_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_DOWNLOADPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+  bool        DOWNLOAD_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        DOWNLOAD_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        DOWNLOAD_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        DOWNLOAD_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadclass.h
new file mode 100644 (file)
index 0000000..a7e5673
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __DOWNLOADCLASS_H__\r
+#define __DOWNLOADCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+NPClass* fillDOWNLOADpclass(void);\r
+\r
+NPObject *  DOWNLOAD_Allocate(NPP npp, NPClass *aClass);\r
+void        DOWNLOAD_Deallocate(NPObject *obj);\r
+void        DOWNLOAD_Invalidate(NPObject *obj);\r
+bool        DOWNLOAD_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        DOWNLOAD_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        DOWNLOAD_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        DOWNLOAD_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        DOWNLOAD_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        DOWNLOAD_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        DOWNLOAD_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        DOWNLOAD_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.c
new file mode 100644 (file)
index 0000000..40524f6
--- /dev/null
@@ -0,0 +1,194 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "downloadcollectionclass.h"\r
+\r
+\r
+#define kDWLDCOLLECTION_ID_PROPERTY_LENGH                                              0\r
+#define kDWLDCOLLECTION_NUM_PROPERTY_IDENTIFIERS                   1\r
+\r
+#define kDWLDCOLLECTION_ID_METHOD_ITEM                                     0\r
+#define kDWLDCOLLECTION_NUM_METHOD_IDENTIFIERS                     1\r
+\r
+bool            v_bDWLDCOLLECTIONIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_DWLDCOLLECTIONPropertyIdentifiers[kDWLDCOLLECTION_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_DWLDCOLLECTIONPropertyNames[kDWLDCOLLECTION_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "lengh"\r
+    };\r
+\r
+NPIdentifier    v_DWLDCOLLECTIONMethodIdentifiers[kDWLDCOLLECTION_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_DWLDCOLLECTIONMethodNames[kDWLDCOLLECTION_NUM_METHOD_IDENTIFIERS] = {\r
+       "item"\r
+       };\r
+\r
+static  void    DWLDCOLLECTIONinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_DWLDCOLLECTIONPropertyNames, kDWLDCOLLECTION_NUM_PROPERTY_IDENTIFIERS, v_DWLDCOLLECTIONPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_DWLDCOLLECTIONMethodNames,   kDWLDCOLLECTION_NUM_METHOD_IDENTIFIERS,   v_DWLDCOLLECTIONMethodIdentifiers );\r
+}\r
+\r
+\r
+NPClass  stDWLDCOLLECTIONclass;\r
+NPClass* pDWLDCOLLECTIONclass = NULL;\r
+\r
+NPClass* fillDWLDCOLLECTIONpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pDWLDCOLLECTIONclass == NULL)\r
+    {\r
+        stDWLDCOLLECTIONclass.allocate          = DWLDCOLLECTION_Allocate;\r
+        stDWLDCOLLECTIONclass.deallocate        = DWLDCOLLECTION_Deallocate;\r
+        stDWLDCOLLECTIONclass.invalidate        = DWLDCOLLECTION_Invalidate;\r
+        stDWLDCOLLECTIONclass.hasMethod         = DWLDCOLLECTION_HasMethod;\r
+        stDWLDCOLLECTIONclass.invoke            = DWLDCOLLECTION_Invoke;\r
+        stDWLDCOLLECTIONclass.invokeDefault     = DWLDCOLLECTION_InvokeDefault;\r
+        stDWLDCOLLECTIONclass.hasProperty       = DWLDCOLLECTION_HasProperty;\r
+        stDWLDCOLLECTIONclass.getProperty       = DWLDCOLLECTION_GetProperty;\r
+        stDWLDCOLLECTIONclass.setProperty       = DWLDCOLLECTION_SetProperty;\r
+        stDWLDCOLLECTIONclass.removeProperty    = DWLDCOLLECTION_RemoveProperty;\r
+        stDWLDCOLLECTIONclass.enumerate         = DWLDCOLLECTION_Enumerate;\r
+        pDWLDCOLLECTIONclass = &stDWLDCOLLECTIONclass;\r
+    }\r
+\r
+    return pDWLDCOLLECTIONclass;\r
+}\r
+\r
+\r
+NPObject *          DWLDCOLLECTION_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    if (!v_bDWLDCOLLECTIONIdentifiersInitialized)\r
+    {\r
+        v_bDWLDCOLLECTIONIdentifiersInitialized = true;\r
+        DWLDCOLLECTIONinitializeIdentifiers();\r
+    }\r
+\r
+    NPObject* newdwldcollection = (NPObject *)MEMALLOC(sizeof(NPObject));\r
+\r
+    return newdwldcollection;\r
+}\r
+\r
+\r
+void        DWLDCOLLECTION_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+void        DWLDCOLLECTION_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+bool        DWLDCOLLECTION_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+       bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kDWLDCOLLECTION_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_DWLDCOLLECTIONMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+bool        DWLDCOLLECTION_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    if (name == v_DWLDCOLLECTIONMethodIdentifiers[kDWLDCOLLECTION_ID_METHOD_ITEM ])\r
+    {\r
+               DWLDCOLLECTION_Invoke_Item(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {          \r
+       fctresult = false;\r
+    }\r
+    return fctresult;\r
+\r
+}\r
+\r
+bool        DWLDCOLLECTION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        DWLDCOLLECTION_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kDWLDCOLLECTION_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_DWLDCOLLECTIONPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    \r
+    return result;\r
+}\r
+\r
+bool        DWLDCOLLECTION_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        DWLDCOLLECTION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        DWLDCOLLECTION_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+bool        DWLDCOLLECTION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+/** implementation **/\r
+void DWLDCOLLECTION_Invoke_Item(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/downloadcollectionclass.h
new file mode 100644 (file)
index 0000000..c178d1b
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __DWLDCOLLECTIONCOLLECTIONCLASS_H__\r
+#define __DWLDCOLLECTIONCOLLECTIONCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+NPClass* fillDWLDCOLLECTIONpclass(void);\r
+\r
+NPObject *  DWLDCOLLECTION_Allocate(NPP npp, NPClass *aClass);\r
+void        DWLDCOLLECTION_Deallocate(NPObject *obj);\r
+void        DWLDCOLLECTION_Invalidate(NPObject *obj);\r
+bool        DWLDCOLLECTION_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        DWLDCOLLECTION_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        DWLDCOLLECTION_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        DWLDCOLLECTION_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        DWLDCOLLECTION_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        DWLDCOLLECTION_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        DWLDCOLLECTION_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        DWLDCOLLECTION_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+void DWLDCOLLECTION_Invoke_Item(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.c
new file mode 100644 (file)
index 0000000..0dc0bd0
--- /dev/null
@@ -0,0 +1,20 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "drmcontrolinfocollectionclass.h"\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinfocollectionclass.h
new file mode 100644 (file)
index 0000000..cb20d97
--- /dev/null
@@ -0,0 +1,26 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __DRMCONTROLINFOCOLLECTIONCLASS_H__\r
+#define __DRMCONTROLINFOCOLLECTIONCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.c
new file mode 100644 (file)
index 0000000..0dc0bd0
--- /dev/null
@@ -0,0 +1,20 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "drmcontrolinfocollectionclass.h"\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/drmcontrolinformationclass.h
new file mode 100644 (file)
index 0000000..b9a2121
--- /dev/null
@@ -0,0 +1,26 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __DRMCONTROLINFORMATIONCLASS_H__\r
+#define __DRMCONTROLINFORMATIONCLASS_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.c
new file mode 100644 (file)
index 0000000..82c6425
--- /dev/null
@@ -0,0 +1,335 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+/*\r
+** HbbTV Plugin PC\r
+*/\r
+\r
+\r
+#include <gdk/gdk.h>\r
+#ifdef XP_UNIX\r
+#include <gdk/gdkx.h>\r
+#include <X11/Xlib.h>\r
+#endif\r
+#include <gtk/gtk.h>\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+#include "oipfapplicationmanager.h"\r
+#include "oipfconfiguration.h"\r
+#include "videobroadcast.h"\r
+\r
+#define MIMETYPEDESCRIPTION "application/hbbtvbrowserplugin::Hbbtv Browser Plugin;" \\r
+                                                       "video/broadcast::Video Broadcast;"\\r
+                            "application/oipfapplicationmanager::Oipf Application Manager;"\\r
+                            "application/oipfconfiguration::Oipf Configuration;"\r
+\r
+\r
+#define PLUGIN_NAME                    "hbbtvbrowserplugin"\r
+#define PLUGIN_DESCRIPTION     "HbbTV browser plugin "\r
+#define PLUGIN_VERSION         "0.20110704"\r
+\r
+\r
+\r
+static void\r
+fillPluginFunctionTable(NPPluginFuncs* pFuncs)\r
+{\r
+  TRACEINFO;\r
+  pFuncs->version = 11;\r
+  pFuncs->size = sizeof(*pFuncs);\r
+  pFuncs->newp = OIPF_NPP_New;\r
+  pFuncs->destroy = OIPF_NPP_Destroy;\r
+  pFuncs->setwindow = OIPF_NPP_SetWindow;\r
+  pFuncs->newstream = OIPF_NPP_NewStream;\r
+//  pFuncs->destroystream = NPP_DestroyStream;\r
+//  pFuncs->asfile = NPP_StreamAsFile;\r
+//  pFuncs->writeready = NPP_WriteReady;\r
+//  pFuncs->write = NPP_Write;\r
+//  pFuncs->print = NPP_Print;\r
+  pFuncs->event = OIPF_NPP_HandleEvent;\r
+//  pFuncs->urlnotify = NPP_URLNotify;\r
+  pFuncs->getvalue = OIPF_NPP_GetValue;\r
+  pFuncs->setvalue = OIPF_NPP_SetValue;\r
+}\r
+\r
+char* booltostr(bool data)\r
+{\r
+    char *result;\r
+    if (data)\r
+        result = "true";\r
+    else\r
+        result = "false";\r
+    return result;\r
+}\r
+\r
+/*\r
+ void drawWindow (HBBTVPluginData* instanceData, GdkDrawable* gdkWindow)\r
+{\r
+  TRACEINFO;\r
+  NPWindow window = *(instanceData->window);\r
+  int x = window.x;\r
+  int y = window.y;\r
+  int width = window.width;\r
+  int height = window.height;\r
+  fprintf(stderr,"%p, x = %i  y=%i, width = %i height = %i\n",gdkWindow, x ,y,width,height);\r
+\r
+  NPP npp = instanceData->npp;\r
+  if (!npp)\r
+    return;\r
+\r
+  const char* uaString = "DemoPlug"; // sBrowserFuncs->uagent(npp);\r
+  if (!uaString)\r
+    return;\r
+\r
+  GdkGC* gdkContext = gdk_gc_new(gdkWindow);\r
+\r
+  // draw a grey background for the plugin frame\r
+  GdkColor grey;\r
+  grey.red = 24000; grey.blue = 24000; grey.green = 24000;\r
+  gdk_gc_set_rgb_fg_color(gdkContext, &grey);\r
+  gdk_draw_rectangle(gdkWindow, gdkContext, TRUE, x, y, width, height);\r
+\r
+  // draw a 3-pixel-thick black frame around the plugin\r
+  GdkColor black;\r
+  black.red = black.green = black.blue = 0;\r
+  gdk_gc_set_rgb_fg_color(gdkContext, &black);\r
+  gdk_gc_set_line_attributes(gdkContext, 3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);\r
+  gdk_draw_rectangle(gdkWindow, gdkContext, FALSE, x + 1, y + 1,\r
+                     width - 3, height - 3);\r
+\r
+  // paint the UA string\r
+  PangoContext* pangoContext = gdk_pango_context_get();\r
+  PangoLayout* pangoTextLayout = pango_layout_new(pangoContext);\r
+  pango_layout_set_width(pangoTextLayout, (width - 10) * PANGO_SCALE);\r
+  pango_layout_set_text(pangoTextLayout, uaString, -1);\r
+  gdk_draw_layout(gdkWindow, gdkContext, x + 5, y + 5, pangoTextLayout);\r
+  g_object_unref(pangoTextLayout);\r
+\r
+  g_object_unref(gdkContext);\r
+}\r
+*/\r
+\r
+\r
+NPError NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs)\r
+{\r
+       TRACEINFO;\r
+\r
+    sBrowserFuncs = bFuncs;\r
+    \r
+       fillPluginFunctionTable(pFuncs);\r
+\r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+char* NP_GetPluginVersion()\r
+{\r
+    TRACEINFO;\r
+       return PLUGIN_VERSION;\r
+}\r
+\r
+NPError NP_Shutdown()\r
+{\r
+    TRACEINFO;\r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+char* NP_GetMIMEDescription()\r
+{\r
+    TRACEINFO;\r
+       return MIMETYPEDESCRIPTION;\r
+}\r
+\r
+\r
+NPError NP_GetValue(void *instance, NPPVariable variable, void *value)\r
+{\r
+    TRACEINFO;\r
+       switch (variable)\r
+       {\r
+               case NPPVpluginNameString :\r
+                       *(char**)value = PLUGIN_NAME;\r
+                       break;\r
+               case NPPVpluginDescriptionString :\r
+                       *(char**)value = PLUGIN_DESCRIPTION;\r
+                       break;\r
+               default :\r
+                       break;\r
+       }\r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+NPError OIPF_NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved)\r
+{\r
+       TRACEINFO;\r
+       int i = 0;\r
+       \r
+       NPBool browserSupportsWindowless = false;\r
+       sBrowserFuncs->getvalue(instance, NPNVSupportsWindowless, &browserSupportsWindowless);\r
+       if (!browserSupportsWindowless)\r
+       {               \r
+               return NPERR_GENERIC_ERROR;\r
+       }\r
+       sBrowserFuncs->setvalue(instance, NPPVpluginWindowBool, (void*)false);\r
+       sBrowserFuncs->setvalue(instance, NPPVpluginTransparentBool, (void*)false);\r
+       \r
+\r
+    NPObject* obj;\r
+    for(i = 0 ; i<argc ; i++ ){\r
+               if((strcmp(argn[i],"type")) == 0){\r
+                       instance->pdata = (HBBTVPluginData*)MEMALLOC(sizeof(HBBTVPluginData));\r
+                       HBBTVPluginData* pdata = ((HBBTVPluginData*)instance->pdata);\r
+                       \r
+                       if (strcmp(argv[i], "application/oipfApplicationManager") == 0)\r
+                       {\r
+                               obj = sBrowserFuncs->createobject(instance, fillOAMpclass());                           \r
+                       }\r
+                       else if (strcmp(argv[i], "application/oipfConfiguration") == 0)\r
+                       {\r
+                               obj = sBrowserFuncs->createobject(instance, fillOCFGpclass());                          \r
+                       }\r
+                       else if (strcmp(argv[i], "video/broadcast") == 0)\r
+                       {\r
+                               obj = sBrowserFuncs->createobject(instance, fillVIDBRCpclass());                                                                \r
+                       }else{\r
+                               \r
+                               obj = NULL;\r
+                       }\r
+                       pdata->type = (char*)MEMALLOC(strlen(argv[i]));\r
+                       strcpy(pdata->type, argv[i] );\r
+                       pdata->obj = obj;\r
+                       pdata->npp = instance;\r
+                       \r
+               }else{\r
+                       \r
+                       obj = NULL;\r
+               }\r
+       }\r
+\r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+NPError OIPF_NPP_Destroy(NPP instance, NPSavedData **save)\r
+{\r
+    TRACEINFO;\r
+    HBBTVPluginData* pdata = (HBBTVPluginData*)instance->pdata;\r
+    if (pdata)\r
+    {          \r
+        sBrowserFuncs->releaseobject(pdata->obj);\r
+        MEMFREE(pdata->type);\r
+        MEMFREE(pdata);\r
+    }\r
+    return NPERR_NO_ERROR;\r
+}\r
+\r
+\r
+NPError OIPF_NPP_SetWindow(NPP instance, NPWindow *window)\r
+{\r
+       TRACEINFO;\r
+       \r
+       \r
+       \r
+       HBBTVPluginData* pdata = (HBBTVPluginData*)instance->pdata;\r
+       if(pdata)\r
+       {\r
+               pdata->window = window;\r
+               if (pdata->type)\r
+               {\r
+                       if (strcmp(pdata->type, "video/broadcast") == 0)\r
+                       {\r
+                               fprintf(stderr, "%s found \n", pdata->type);\r
+                               if (pdata->obj)\r
+                               {\r
+                                       NPObj_VidBrc* vidbrcobj  = (NPObj_VidBrc*)pdata->obj;\r
+                                       if (!(vidbrcobj->fullscreen))\r
+                                       {\r
+                                               OnNoFullscreenSetWindow(pdata->window->x,\r
+                                                                                       pdata->window->y,\r
+                                                                                       pdata->window->width,\r
+                                                                                       pdata->window->height);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               /*fprintf(stderr, "\tWindow found : %p\n", window);\r
+               fprintf(stderr, "\twindow = %p ws_info %p \n\tx = %d, y= %d\n\tclipRect.left = %d clipRect.top= %d\n\twidth=%d,  height= %d\n",\r
+                       pdata->window->window,\r
+                       pdata->window->ws_info,\r
+                       pdata->window->x,\r
+                       pdata->window->y,\r
+                       pdata->window->clipRect.left,\r
+                       pdata->window->clipRect.top,\r
+                       pdata->window->width,\r
+                       pdata->window->height);*/\r
+       }\r
+       \r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+NPError OIPF_NPP_HandleEvent(NPP instance, void* event)\r
+{\r
+        //TRACEINFO; // frequent event, avoid over log...\r
+\r
+       XEvent *nativeEvent = (XEvent*)event;\r
+       if (nativeEvent->type == GraphicsExpose)\r
+       {\r
+               XGraphicsExposeEvent *expose = &nativeEvent->xgraphicsexpose;\r
+               GC gc = XCreateGC(expose->display, expose->drawable, 0, 0);     \r
+               XFillRectangle(expose->display, expose->drawable, gc, expose->x, expose->y,expose->width, expose->height);\r
+               XFreeGC(expose->display, gc);\r
+               return true;\r
+       }\r
+\r
+       \r
+       return false;\r
+}\r
+\r
+\r
+\r
+NPError OIPF_NPP_GetValue(NPP instance, NPPVariable variable, void *value)\r
+{\r
+    TRACEINFO;\r
+\r
+    if ( variable == NPPVpluginScriptableNPObject )\r
+    {                  \r
+        void ** v = (void **)value;        \r
+        if(instance->pdata)\r
+        {\r
+        NPObject* obj = ((HBBTVPluginData*)instance->pdata)->obj;\r
+               if(obj == NULL){                        \r
+               }else{                  \r
+                       sBrowserFuncs->retainobject(obj);\r
+               }       \r
+               *v = obj;\r
+               }\r
+    }\r
+       return NPERR_NO_ERROR;\r
+}\r
+\r
+\r
+NPError OIPF_NPP_SetValue(NPP instance, NPNVariable variable, void *value)\r
+{\r
+    TRACEINFO;\r
+       return NPERR_GENERIC_ERROR;\r
+}\r
+\r
+\r
+NPError OIPF_NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype)\r
+{\r
+    TRACEINFO;\r
+       return NPERR_GENERIC_ERROR;\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserplugin.h
new file mode 100644 (file)
index 0000000..87e61c0
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef hbbtvbrowserplugin_h\r
+#define hbbtvbrowserplugin_h\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <npapi.h>\r
+#include <npfunctions.h>\r
+#include <npruntime.h>\r
+\r
+#include "hbbtvbrowserpluginapi.h"\r
+\r
+#ifndef DEBUG\r
+       #define DEBUG  true\r
+       #define PROJECTNAME "HbbTVBrowserPlugin"\r
+       #define TRACEINFO if (DEBUG) { fprintf(stderr,"\x1b[%i;3%im%s\x1b[0m : call %s\n", 1, 3, PROJECTNAME, __FUNCTION__); }\r
+       #define NOTIMPLEMENTED if (DEBUG) { printf("%s : %s is \x1b[1;31mNOT IMPLEMENTED\x1b[0m : TODO \n", PROJECTNAME, __FUNCTION__); }\r
+#endif\r
+\r
+typedef struct\r
+{      \r
+       NPObject* obj;\r
+       char* type;\r
+       NPWindow* window;\r
+       NPP npp;\r
+}HBBTVPluginData;\r
+\r
+NPNetscapeFuncs* sBrowserFuncs;\r
+\r
+#define ALLOCBROWSERMEMORY  true\r
+\r
+#ifdef ALLOCBROWSERMEMORY\r
+       #define MEMALLOC sBrowserFuncs->memalloc\r
+       #define MEMFREE  sBrowserFuncs->memfree\r
+#else \r
+       #define MEMALLOC malloc\r
+       #define MEMFREE  free\r
+#endif\r
+\r
+char* booltostr(bool data);\r
+\r
+NPError NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);\r
+NPError NP_Shutdown();\r
+NPError NP_GetValue(void *instance, NPPVariable variable, void *value);\r
+char*  NP_GetPluginVersion();\r
+char*  NP_GetMIMEDescription();\r
+\r
+NPError OIPF_NPP_New(NPMIMEType    pluginType, NPP instance, uint16_t mode, int16_t argc,   char *argn[], char *argv[], NPSavedData *saved);\r
+NPError OIPF_NPP_Destroy(NPP instance, NPSavedData **save);\r
+NPError OIPF_NPP_SetWindow(NPP instance, NPWindow *window);\r
+NPError OIPF_NPP_HandleEvent(NPP instance, void* Event);\r
+NPError OIPF_NPP_GetValue(NPP instance, NPPVariable variable, void *value);\r
+NPError OIPF_NPP_SetValue(NPP instance, NPNVariable variable, void *value);\r
+NPError OIPF_NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.c
new file mode 100644 (file)
index 0000000..aa7ff81
--- /dev/null
@@ -0,0 +1,45 @@
+
+/*
+ *             Copyright (c) 2010-2011 Telecom-Paristech
+ *                 All Rights Reserved
+ *     GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *             Authors:    Stanislas Selle             
+ *                             
+ */#include "hbbtvbrowserpluginapi.h"
+
+
+void OnNoFullscreenSetWindow(int x, int y, int width, int height)
+{
+}
+
+void OnAPPLICATION_Show()
+{
+}
+
+void OnAPPLICATION_Hide()
+{
+}
+
+void OnVIDBRC_SetFullScreen(int fullscreenparam)
+{
+}
+
+void OnKEYSET_SetValue(double param)
+{
+}
+
+void OnKEYSET_Allocate()
+{
+}
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/hbbtvbrowserpluginapi.h
new file mode 100644 (file)
index 0000000..70408a1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *             Copyright (c) 2010-2011 Telecom-Paristech
+ *                 All Rights Reserved
+ *     GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *             Authors:    Stanislas Selle             
+ *                             
+ */
+#ifndef hbbtvbrowserpluginapi_h
+#define hbbtvbrowserpluginapi_h
+
+#include <stdlib.h>
+
+///Callbacks
+void OnNoFullscreenSetWindow(int x, int y, int width, int height);
+void OnAPPLICATION_Show();
+void OnAPPLICATION_Hide();
+void OnVIDBRC_SetFullScreen(int fullscreenparam);
+void OnKEYSET_SetValue(double param);
+void OnKEYSET_Allocate();
+#endif
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.c
new file mode 100644 (file)
index 0000000..6e9a9d1
--- /dev/null
@@ -0,0 +1,330 @@
+\r
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */#include "keysetclass.h"\r
+\r
+#define kKEYSET_ID_PROPERTY_VALUE                                              0\r
+#define kKEYSET_ID_PROPERTY_MAXIMUMVALUE                                       1\r
+#define kKEYSET_ID_PROPERTY_RED                                                        2\r
+#define kKEYSET_ID_PROPERTY_GREEN                                              3\r
+#define kKEYSET_ID_PROPERTY_YELLOW                                             4\r
+#define kKEYSET_ID_PROPERTY_BLUE                                                       5\r
+#define kKEYSET_ID_PROPERTY_NAVIGATION                                         6\r
+#define kKEYSET_ID_PROPERTY_VCR                                                        7\r
+#define kKEYSET_ID_PROPERTY_SCROLL                                             8\r
+#define kKEYSET_ID_PROPERTY_INFO                                                       9\r
+#define kKEYSET_ID_PROPERTY_NUMERIC                                            10\r
+#define kKEYSET_ID_PROPERTY_ALPHA                                                      11\r
+#define kKEYSET_ID_PROPERTY_OTHER                                              12\r
+#define kKEYSET_NUM_PROPERTY_IDENTIFIERS                    13\r
+\r
+#define kKEYSET_ID_METHOD_SETVALUE                             0\r
+#define kKEYSET_NUM_METHOD_IDENTIFIERS                     1\r
+\r
+\r
+\r
+bool            v_bKEYSETIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_KEYSETPropertyIdentifiers[kKEYSET_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_KEYSETPropertyNames[kKEYSET_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "value",\r
+    "maximumValue",\r
+    "RED",\r
+    "GREEN",\r
+    "YELLOW",\r
+    "BLUE",\r
+    "NAVIGATION",\r
+    "VCR",\r
+    "SCROLL",\r
+    "INFO",\r
+    "NUMERIC",\r
+    "ALPHA",\r
+    "OTHER"\r
+    };\r
+\r
+NPIdentifier    v_KEYSETMethodIdentifiers[kKEYSET_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_KEYSETMethodNames[kKEYSET_NUM_METHOD_IDENTIFIERS] = {\r
+       "setValue"\r
+       };\r
+\r
+static  void    KEYSETinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_KEYSETPropertyNames, kKEYSET_NUM_PROPERTY_IDENTIFIERS, v_KEYSETPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_KEYSETMethodNames,   kKEYSET_NUM_METHOD_IDENTIFIERS,   v_KEYSETMethodIdentifiers );\r
+}\r
+\r
+\r
+NPClass  stKEYSETclass;\r
+NPClass* pKEYSETclass = NULL;\r
+\r
+NPClass* fillKEYSETpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pKEYSETclass == NULL)\r
+    {\r
+        stKEYSETclass.allocate          = KEYSET_Allocate;\r
+        stKEYSETclass.deallocate        = KEYSET_Deallocate;\r
+        stKEYSETclass.invalidate        = KEYSET_Invalidate;\r
+        stKEYSETclass.hasMethod         = KEYSET_HasMethod;\r
+        stKEYSETclass.invoke            = KEYSET_Invoke;\r
+        stKEYSETclass.invokeDefault     = KEYSET_InvokeDefault;\r
+        stKEYSETclass.hasProperty       = KEYSET_HasProperty;\r
+        stKEYSETclass.getProperty       = KEYSET_GetProperty;\r
+        stKEYSETclass.setProperty       = KEYSET_SetProperty;\r
+        stKEYSETclass.removeProperty    = KEYSET_RemoveProperty;\r
+        stKEYSETclass.enumerate         = KEYSET_Enumerate;\r
+        pKEYSETclass = &stKEYSETclass;\r
+    }\r
+\r
+    return pKEYSETclass;\r
+}\r
+\r
+\r
+NPObject *          KEYSET_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    NPObject* result;\r
+\r
+    \r
+    if (!v_bKEYSETIdentifiersInitialized)\r
+    {\r
+        v_bKEYSETIdentifiersInitialized = true;\r
+        KEYSETinitializeIdentifiers();\r
+    }\r
+       \r
+       NPObj_KeySet* newkeyset = (NPObj_KeySet *)MEMALLOC(sizeof(NPObj_KeySet));\r
+       newkeyset->npp = npp;\r
+       newkeyset->value = (double*)MEMALLOC(sizeof(double));\r
+    newkeyset->maximumValue = (double*)MEMALLOC(sizeof(double));\r
+       result = (NPObject*)newkeyset;\r
+       OnKEYSET_Allocate();\r
+    return  result;\r
+}\r
+\r
+\r
+void        KEYSET_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    NPObj_KeySet* keysetobj = (NPObj_KeySet*)obj;\r
+    MEMFREE(keysetobj->value);\r
+    MEMFREE(keysetobj->maximumValue);\r
+    MEMFREE(keysetobj);\r
+    return;\r
+}\r
+\r
+void        KEYSET_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+bool        KEYSET_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+       bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kKEYSET_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_KEYSETMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+bool        KEYSET_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    if (name == v_KEYSETMethodIdentifiers[kKEYSET_ID_METHOD_SETVALUE])\r
+    {\r
+               KEYSET_Invoke_SetValue(obj, args, argCount, result);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {          \r
+       fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+bool        KEYSET_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        KEYSET_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kKEYSET_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_KEYSETPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    \r
+    return result;\r
+}\r
+\r
+bool        KEYSET_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    NPObj_KeySet* keysetobj = (NPObj_KeySet*)obj;\r
+    \r
+    double     KEYMASK_RED             = 0x1;\r
+       double  KEYMASK_GREEN           = 0x2;\r
+       double  KEYMASK_YELLOW          = 0x4;\r
+       double  KEYMASK_BLUE            = 0x8;\r
+       double  KEYMASK_NAVIGATION      = 0x10;\r
+       double  KEYMASK_VCR             = 0x20;\r
+       double  KEYMASK_SCROLL          = 0x40;\r
+       double  KEYMASK_INFO            = 0x80;\r
+       double  KEYMASK_NUMERIC         = 0x100;\r
+       double  KEYMASK_ALPHA           = 0x200;\r
+       double  KEYMASK_OTHER           = 0x400;\r
+       \r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_RED])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_RED, *result);\r
+       fctresult = true;\r
+       }\r
+       else\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_GREEN])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_GREEN, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_YELLOW])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_YELLOW, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_BLUE])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_BLUE, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_NAVIGATION])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_NAVIGATION, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_VCR])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_VCR, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_SCROLL])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_SCROLL, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_INFO])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_INFO, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_NUMERIC])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_NUMERIC, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_ALPHA])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_ALPHA, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_OTHER])\r
+       {                       \r
+               DOUBLE_TO_NPVARIANT(KEYMASK_OTHER, *result);\r
+       fctresult = true;\r
+       }\r
+       if (name == v_KEYSETPropertyIdentifiers[kKEYSET_ID_PROPERTY_VALUE])\r
+       {                       \r
+               double* value = keysetobj->value;\r
+               DOUBLE_TO_NPVARIANT(*value, *result);\r
+       fctresult = true;\r
+       }\r
+       \r
+       if (fctresult)\r
+       {\r
+                                                       \r
+       }\r
+    \r
+               \r
+    \r
+    return fctresult;    \r
+}\r
+\r
+bool        KEYSET_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    \r
+    return fctresult;\r
+}\r
+\r
+bool        KEYSET_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+bool        KEYSET_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+/** implementation **/\r
+void KEYSET_Invoke_SetValue(NPObject* obj,const NPVariant* args, uint32_t argCount, NPVariant *result)\r
+{\r
+       TRACEINFO;\r
+       //~ NOTIMPLEMENTED; // in progress\r
+       double param;\r
+       NPObj_KeySet* keysetobj = (NPObj_KeySet*)obj;\r
+       double* value = keysetobj->value;\r
+       fprintf(stderr,"nb args : %i, %f", argCount,NPVARIANT_TO_DOUBLE(args[0]) );\r
+       if (!NPVARIANT_IS_DOUBLE(args[0])) {\r
+               fprintf(stderr,"\t%s : error\n",__FUNCTION__);\r
+               return;\r
+    }\r
+    else {\r
+               param = NPVARIANT_TO_DOUBLE( args[0] );\r
+               fprintf(stderr, "\t%s : param to transmit %f \n", __FUNCTION__, param);\r
+               *value = param;\r
+               OnKEYSET_SetValue(param);\r
+       }\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/keysetclass.h
new file mode 100644 (file)
index 0000000..5448d64
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef    __HBBTVKEYSET_H__\r
+#define    __HBBTVKEYSET_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+typedef struct\r
+{\r
+       NPObject header;        \r
+       NPP npp; \r
+       \r
+       double* value;\r
+       double* maximumValue;   \r
+} NPObj_KeySet;\r
+\r
+NPClass* fillKEYSETpclass(void);\r
+\r
+NPObject *  KEYSET_Allocate(NPP npp, NPClass *aClass);\r
+void        KEYSET_Deallocate(NPObject *obj);\r
+void        KEYSET_Invalidate(NPObject *obj);\r
+bool        KEYSET_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        KEYSET_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        KEYSET_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        KEYSET_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        KEYSET_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        KEYSET_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+bool        KEYSET_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+bool        KEYSET_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+void           KEYSET_Invoke_SetValue(NPObject* obj,const NPVariant* args, uint32_t argCount, NPVariant *result);\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/makefile.am b/applications/hbbtvplayer/hbbtvbrowserplugin/src/makefile.am
new file mode 100644 (file)
index 0000000..59c0d4c
--- /dev/null
@@ -0,0 +1,47 @@
+
+lib_LTLIBRARIES = libhbbtvbrowserplugin.la
+
+libhbbtvbrowserplugin_la_SOURCES = hbbtvbrowserplugin.c\
+               hbbtvbrowserpluginapi.c\
+               oipfapplicationmanager.c\
+               applicationclass.c\
+               applicationprivatedataclass.c\
+               oipfconfiguration.c\
+               configurationclass.c\
+               oipfdownloadmanager.c\
+               oipfdownloadtrigger.c\
+               downloadclass.c\
+               downloadcollectionclass.c\
+               drmcontrolinfocollectionclass.c\
+               drmcontrolinformationclass.c\
+               videobroadcast.c\
+               keysetclass.c\
+               hbbtvbrowserplugin.h\
+               hbbtvbrowserpluginapi.h\
+               oipfapplicationmanager.h\
+               applicationclass.h\
+               applicationprivatedataclass.h\
+               oipfconfiguration.h\
+               configurationclass.h\
+               oipfdownloadmanager.h\
+               oipfdownloadtrigger.h\
+               downloadclass.h\
+               downloadcollectionclass.h\
+               drmcontrolinfocollectionclass.h\
+               drmcontrolinformationclass.h\
+               videobroadcast.h\
+               keysetclass.h
+
+library_includedir=$(includedir)/@PACKAGE_NAME@
+library_include_HEADERS = hbbtvbrowserpluginapi.h
+
+SPECIALCFLAGS =  -g -Wall -DXP_UNIX=1 -DMOZ_X11=1 -fPIC
+libhbbtvbrowserplugin_la_CFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(NPAPI_CFLAGS) $(SPECIALCFLAGS) -I./webkit-plugin-header/ -I./src/webkit-plugin-header/
+libhbbtvbrowserplugin_la_LDFLAGS = $(GLIB_LIBS) $(GTK_LIBS) $(NPAPI_LIBS) $(SPECIALCFLAGS)
+libhbbtvbrowserplugin_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(NPAPI_LIBS)
+
+install-exec-local :
+       ln -fs $(libdir)/lib@PACKAGE_NAME@.so.0.0.0 $(PLUGINDIR)/lib@PACKAGE_NAME@.so
+
+uninstall-local :
+       rm -f $(PLUGINDIR)/lib@PACKAGE_NAME@.so
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.c
new file mode 100644 (file)
index 0000000..5adebaf
--- /dev/null
@@ -0,0 +1,203 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "oipfapplicationmanager.h"\r
+#include "applicationclass.h"\r
+\r
+#define kOAM_ID_PROPERTY_ON_LOW_MEMORY                  0\r
+#define kOAM_NUM_PROPERTY_IDENTIFIERS                   1\r
+\r
+#define kOAM_ID_METHOD_GET_OWNER_APPLICATION            0\r
+#define kOAM_NUM_METHOD_IDENTIFIERS                     1\r
+\r
+bool            v_bOAMIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_OAMPropertyIdentifiers[kOAM_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_OAMPropertyNames[kOAM_NUM_PROPERTY_IDENTIFIERS] = {\r
+    "onLowMemory"\r
+       };\r
+\r
+NPIdentifier    v_OAMMethodIdentifiers[kOAM_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_OAMMethodNames[kOAM_NUM_METHOD_IDENTIFIERS] = {\r
+    "getOwnerApplication"\r
+};\r
+\r
+\r
+\r
+\r
+static  void    OAMinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_OAMPropertyNames, kOAM_NUM_PROPERTY_IDENTIFIERS, v_OAMPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_OAMMethodNames,   kOAM_NUM_METHOD_IDENTIFIERS,   v_OAMMethodIdentifiers );\r
+}\r
+\r
+NPClass  stOAMclass;\r
+NPClass* pOAMclass = NULL;\r
+\r
+NPClass* fillOAMpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pOAMclass == NULL)\r
+    {\r
+        stOAMclass.allocate          = OAM_Allocate;\r
+        stOAMclass.deallocate        = OAM_Deallocate;\r
+        stOAMclass.invalidate        = OAM_Invalidate;\r
+        stOAMclass.hasMethod         = OAM_HasMethod;\r
+        stOAMclass.invoke            = OAM_Invoke;\r
+        stOAMclass.invokeDefault     = OAM_InvokeDefault;\r
+        stOAMclass.hasProperty       = OAM_HasProperty;\r
+        stOAMclass.getProperty       = OAM_GetProperty;\r
+        stOAMclass.setProperty       = OAM_SetProperty;\r
+        stOAMclass.removeProperty    = OAM_RemoveProperty;\r
+        stOAMclass.enumerate         = OAM_Enumerate;\r
+        pOAMclass = &stOAMclass;\r
+    }\r
+\r
+    return pOAMclass;\r
+}\r
+\r
+\r
+NPObject *          OAM_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+       \r
+    if (!v_bOAMIdentifiersInitialized)\r
+    {\r
+        v_bOAMIdentifiersInitialized = true;\r
+        OAMinitializeIdentifiers();\r
+    }\r
+    \r
+    NPObj_OAM* newapplicationmanager = (NPObj_OAM*)MEMALLOC(sizeof(NPObj_OAM));\r
+       fprintf(stderr, "\t%s : Allocation at \x1b[%i;3%im%p\n\x1b[0m ",__FUNCTION__, 1, 1, newapplicationmanager );\r
+    newapplicationmanager->npp = npp;\r
+    newapplicationmanager->ownerApplication = sBrowserFuncs->createobject(npp, fillAPPLICATIONpclass());\r
+    fprintf(stderr, "\t%s : Create ownerApplication member at \x1b[%i;3%im%p\n\x1b[0m ",__FUNCTION__, 1, 1, newapplicationmanager->ownerApplication );\r
+    return (NPObject *)newapplicationmanager;\r
+}\r
+\r
+  void        OAM_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    NPObj_OAM* oamobj = (NPObj_OAM*)obj;\r
+    sBrowserFuncs->releaseobject(oamobj->ownerApplication);    \r
+    MEMFREE(oamobj);\r
+    return;\r
+}\r
+\r
+  void        OAM_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        OAM_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kOAM_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_OAMMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+       \r
+    return result;\r
+}\r
+\r
+bool        OAM_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+       //OAM_ObjectMain * pMainObj = reinterpret_cast<tWOTVe_OAM_ObjectMain*>(obj);\r
+       bool fctresult = false;\r
+    if (name == v_OAMMethodIdentifiers[kOAM_ID_METHOD_GET_OWNER_APPLICATION])\r
+    {\r
+               OAM_ObjectMain_Invoke_GetOwnerApplication((NPObj_OAM*)obj, args, argCount, result);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {\r
+        \r
+        fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+ bool        OAM_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        OAM_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kOAM_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_OAMPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+   \r
+    return result;\r
+}\r
+\r
+bool          OAM_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        OAM_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        OAM_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        OAM_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+/** implementation **/\r
+void           OAM_ObjectMain_Invoke_GetOwnerApplication(NPObj_OAM* obj,const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+       TRACEINFO;\r
+       sBrowserFuncs->retainobject(obj->ownerApplication);\r
+       OBJECT_TO_NPVARIANT((NPObject*)(obj->ownerApplication), *result);       \r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfapplicationmanager.h
new file mode 100644 (file)
index 0000000..4334fe4
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef    __OIPFAPPLICATIONMANAGER_H__\r
+#define    __OIPFAPPLICATIONMANAGER_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+typedef struct {\r
+    NPObject    header;\r
+    NPP         npp;\r
+    \r
+    NPObject*   ownerApplication; \r
+}  NPObj_OAM;\r
+\r
+NPClass* fillOAMpclass(void);\r
+\r
+NPObject *  OAM_Allocate(NPP npp, NPClass *aClass);\r
+void        OAM_Deallocate(NPObject *obj);\r
+void        OAM_Invalidate(NPObject *obj);\r
+bool        OAM_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        OAM_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        OAM_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        OAM_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        OAM_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        OAM_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+bool        OAM_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+bool        OAM_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+void           OAM_ObjectMain_Invoke_GetOwnerApplication(NPObj_OAM* obj,const NPVariant* args, uint32_t argCount, NPVariant* result);\r
+\r
+/*\r
+typedef struct{\r
+       NPObject        headear;\r
+       NPP                     npp;\r
+       NPObject*       onLowMemory;\r
+       NPObject*       ownerApplication;\r
+       NPObject*       newApplication;\r
+} OAM_ObjectMain;\r
+*/\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.c
new file mode 100644 (file)
index 0000000..cb20c44
--- /dev/null
@@ -0,0 +1,182 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "oipfconfiguration.h"\r
+\r
+#define kOCFG_ID_PROPERTY_CONFIGURATION                                        0\r
+#define kOCFG_NUM_PROPERTY_IDENTIFIERS                         1\r
+\r
+#define kOCFG_NUM_METHOD_IDENTIFIERS                       0\r
+\r
+bool            v_bOCFGIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_OCFGPropertyIdentifiers[kOCFG_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_OCFGPropertyNames[kOCFG_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "configuration"\r
+    };\r
+\r
+NPIdentifier    v_OCFGMethodIdentifiers[kOCFG_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_OCFGMethodNames[kOCFG_NUM_METHOD_IDENTIFIERS] = {};\r
+\r
+static  void    OCFGinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_OCFGPropertyNames, kOCFG_NUM_PROPERTY_IDENTIFIERS, v_OCFGPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_OCFGMethodNames,   kOCFG_NUM_METHOD_IDENTIFIERS,   v_OCFGMethodIdentifiers );\r
+}\r
+\r
+\r
+NPClass  stOCFGclass;\r
+NPClass* pOCFGclass = NULL;\r
+\r
+NPClass* fillOCFGpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pOCFGclass == NULL)\r
+    {\r
+        stOCFGclass.allocate          = OCFG_Allocate;\r
+        stOCFGclass.deallocate        = OCFG_Deallocate;\r
+        stOCFGclass.invalidate        = OCFG_Invalidate;\r
+        stOCFGclass.hasMethod         = OCFG_HasMethod;\r
+        stOCFGclass.invoke            = OCFG_Invoke;\r
+        stOCFGclass.invokeDefault     = OCFG_InvokeDefault;\r
+        stOCFGclass.hasProperty       = OCFG_HasProperty;\r
+        stOCFGclass.getProperty       = OCFG_GetProperty;\r
+        stOCFGclass.setProperty       = OCFG_SetProperty;\r
+        stOCFGclass.removeProperty    = OCFG_RemoveProperty;\r
+        stOCFGclass.enumerate         = OCFG_Enumerate;\r
+        pOCFGclass = &stOCFGclass;\r
+    }\r
+\r
+    return pOCFGclass;\r
+}\r
+\r
+\r
+NPObject *          OCFG_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    NPObject* result;\r
+\r
+    \r
+    if (!v_bOCFGIdentifiersInitialized)\r
+    {\r
+        v_bOCFGIdentifiersInitialized = true;\r
+        OCFGinitializeIdentifiers();\r
+    }\r
+\r
+    NPObject* newocfg = (NPObject*)MEMALLOC(sizeof(NPObject));\r
+    result = newocfg;\r
+    \r
+    return result;\r
+}\r
+\r
+\r
+void        OCFG_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+void        OCFG_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+bool        OCFG_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+       bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kOCFG_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_OCFGMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+bool        OCFG_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool fctresult;\r
+   \r
+    fctresult = false;\r
+\r
+    return fctresult;\r
+\r
+}\r
+\r
+bool        OCFG_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        OCFG_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kOCFG_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_OCFGPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+   \r
+    return result;\r
+}\r
+\r
+bool        OCFG_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        OCFG_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+bool        OCFG_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+bool        OCFG_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfconfiguration.h
new file mode 100644 (file)
index 0000000..25f8cf3
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef    __OIPFCONFIGURATION_H__\r
+#define    __OIPFCONFIGURATION_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+NPClass* fillOCFGpclass(void);\r
+\r
+NPObject *  OCFG_Allocate(NPP npp, NPClass *aClass);\r
+void        OCFG_Deallocate(NPObject *obj);\r
+void        OCFG_Invalidate(NPObject *obj);\r
+bool        OCFG_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        OCFG_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        OCFG_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        OCFG_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        OCFG_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        OCFG_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        OCFG_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        OCFG_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.c
new file mode 100644 (file)
index 0000000..cfe9e0f
--- /dev/null
@@ -0,0 +1,233 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "oipfdownloadmanager.h"\r
+\r
+#define kODWLDMAN_ID_PROPERTY_ONDOWNLOADSTATECHANGE 0\r
+#define kODWLDMAN_NUM_PROPERTY_IDENTIFIERS                     1\r
+\r
+#define kODWLDMAN_ID_METHOD_PAUSE                                      0\r
+#define kODWLDMAN_ID_METHOD_RESUME                                     1\r
+#define kODWLDMAN_ID_METHOD_REMOVE                                     2\r
+#define kODWLDMAN_ID_METHOD_GETDOWNLOADS                       3\r
+#define kODWLDMAN_NUM_METHOD_IDENTIFIERS               4\r
+\r
+bool            v_bODWLDMANIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_ODWLDMANPropertyIdentifiers[kODWLDMAN_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_ODWLDMANPropertyNames[kODWLDMAN_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "onDownloadStateChange"\r
+       };\r
+\r
+NPIdentifier    v_ODWLDMANMethodIdentifiers[kODWLDMAN_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_ODWLDMANMethodNames[kODWLDMAN_NUM_METHOD_IDENTIFIERS] = {\r
+    "pause",\r
+    "resume",\r
+    "remove",\r
+    "getDownloads"\r
+};\r
+\r
+\r
+static  void    ODWLDMANinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_ODWLDMANPropertyNames, kODWLDMAN_NUM_PROPERTY_IDENTIFIERS, v_ODWLDMANPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_ODWLDMANMethodNames,   kODWLDMAN_NUM_METHOD_IDENTIFIERS,   v_ODWLDMANMethodIdentifiers );\r
+}\r
+\r
+NPClass  stODWLDMANclass;\r
+NPClass* pODWLDMANclass = NULL;\r
+\r
+NPClass* fillODWLDMANpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pODWLDMANclass == NULL)\r
+    {\r
+        stODWLDMANclass.allocate          = ODWLDMAN_Allocate;\r
+        stODWLDMANclass.deallocate        = ODWLDMAN_Deallocate;\r
+        stODWLDMANclass.invalidate        = ODWLDMAN_Invalidate;\r
+        stODWLDMANclass.hasMethod         = ODWLDMAN_HasMethod;\r
+        stODWLDMANclass.invoke            = ODWLDMAN_Invoke;\r
+        stODWLDMANclass.invokeDefault     = ODWLDMAN_InvokeDefault;\r
+        stODWLDMANclass.hasProperty       = ODWLDMAN_HasProperty;\r
+        stODWLDMANclass.getProperty       = ODWLDMAN_GetProperty;\r
+        stODWLDMANclass.setProperty       = ODWLDMAN_SetProperty;\r
+        stODWLDMANclass.removeProperty    = ODWLDMAN_RemoveProperty;\r
+        stODWLDMANclass.enumerate         = ODWLDMAN_Enumerate;\r
+        pODWLDMANclass = &stODWLDMANclass;\r
+    }\r
+\r
+    return pODWLDMANclass;\r
+}\r
+\r
+\r
+NPObject *          ODWLDMAN_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    NPObject* newdwldman = NULL;\r
+    if (!v_bODWLDMANIdentifiersInitialized)\r
+    {\r
+        v_bODWLDMANIdentifiersInitialized = true;\r
+        ODWLDMANinitializeIdentifiers();\r
+    }\r
+\r
+    newdwldman = (NPObject*)MEMALLOC(sizeof(NPObject));\r
+\r
+    return newdwldman;\r
+}\r
+\r
+  void        ODWLDMAN_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+  void        ODWLDMAN_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        ODWLDMAN_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kODWLDMAN_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_ODWLDMANMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }  \r
+\r
+    return result;\r
+}\r
+\r
+bool        ODWLDMAN_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    bool fctresult = false;\r
+    if (name == v_ODWLDMANMethodIdentifiers[kODWLDMAN_ID_METHOD_GETDOWNLOADS])\r
+    {\r
+               ODWLDMAN_Invoke_GetDownloads(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else if (name == v_ODWLDMANMethodIdentifiers[kODWLDMAN_ID_METHOD_PAUSE])\r
+    {\r
+               ODWLDMAN_Invoke_Pause(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else if (name == v_ODWLDMANMethodIdentifiers[kODWLDMAN_ID_METHOD_REMOVE])\r
+    {\r
+               ODWLDMAN_Invoke_Remove(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+       else if (name == v_ODWLDMANMethodIdentifiers[kODWLDMAN_ID_METHOD_RESUME])\r
+    {\r
+               ODWLDMAN_Invoke_Resume(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else\r
+    {        \r
+        fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+ bool        ODWLDMAN_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        ODWLDMAN_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kODWLDMAN_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_ODWLDMANPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+    \r
+    return result;\r
+}\r
+\r
+  bool        ODWLDMAN_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        ODWLDMAN_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        ODWLDMAN_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        ODWLDMAN_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+/** implementation */\r
+\r
+\r
+void ODWLDMAN_Invoke_GetDownloads(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void ODWLDMAN_Invoke_Pause(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void ODWLDMAN_Invoke_Remove(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void ODWLDMAN_Invoke_Resume(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadmanager.h
new file mode 100644 (file)
index 0000000..e9c3226
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef __OIPFDOWNLOADMANAGER_H__\r
+#define __OIPFDOWNLOADMANAGER_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+NPClass* fillODWLDMANpclass(void);\r
+\r
+NPObject *  ODWLDMAN_Allocate(NPP npp, NPClass *aClass);\r
+void        ODWLDMAN_Deallocate(NPObject *obj);\r
+void        ODWLDMAN_Invalidate(NPObject *obj);\r
+bool        ODWLDMAN_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        ODWLDMAN_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        ODWLDMAN_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        ODWLDMAN_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        ODWLDMAN_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        ODWLDMAN_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        ODWLDMAN_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        ODWLDMAN_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+\r
+void ODWLDMAN_Invoke_GetDownloads(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void ODWLDMAN_Invoke_Pause(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void ODWLDMAN_Invoke_Remove(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void ODWLDMAN_Invoke_Resume(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.c
new file mode 100644 (file)
index 0000000..ae17f4b
--- /dev/null
@@ -0,0 +1,205 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle                \r
+ *                             \r
+ */\r
+#include "oipfdownloadtrigger.h"\r
+\r
+\r
+#define kODWLDTRG_NUM_PROPERTY_IDENTIFIERS                   0\r
+\r
+#define kODWLDTRG_ID_METHOD_REGISTER_DOWNLOAD               0\r
+#define kODWLDTRG_ID_METHOD_REGISTER_DOWNLOADURL            1\r
+#define kODWLDTRG_NUM_METHOD_IDENTIFIERS                     2\r
+\r
+bool            v_bODWLDTRGIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_ODWLDTRGPropertyIdentifiers[kODWLDTRG_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_ODWLDTRGPropertyNames[kODWLDTRG_NUM_PROPERTY_IDENTIFIERS] = {\r
+};\r
+\r
+NPIdentifier    v_ODWLDTRGMethodIdentifiers[kODWLDTRG_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_ODWLDTRGMethodNames[kODWLDTRG_NUM_METHOD_IDENTIFIERS] = {\r
+    "registerDownload",\r
+    "registerDownloadURL"\r
+};\r
+\r
+\r
+\r
+static  void    ODWLDTRGinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_ODWLDTRGPropertyNames, kODWLDTRG_NUM_PROPERTY_IDENTIFIERS, v_ODWLDTRGPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_ODWLDTRGMethodNames,   kODWLDTRG_NUM_METHOD_IDENTIFIERS,   v_ODWLDTRGMethodIdentifiers );\r
+}\r
+\r
+NPClass  stODWLDTRGclass;\r
+NPClass* pODWLDTRGclass = NULL;\r
+\r
+NPClass* fillODWLDTRGpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pODWLDTRGclass == NULL)\r
+    {\r
+        stODWLDTRGclass.allocate          = ODWLDTRG_Allocate;\r
+        stODWLDTRGclass.deallocate        = ODWLDTRG_Deallocate;\r
+        stODWLDTRGclass.invalidate        = ODWLDTRG_Invalidate;\r
+        stODWLDTRGclass.hasMethod         = ODWLDTRG_HasMethod;\r
+        stODWLDTRGclass.invoke            = ODWLDTRG_Invoke;\r
+        stODWLDTRGclass.invokeDefault     = ODWLDTRG_InvokeDefault;\r
+        stODWLDTRGclass.hasProperty       = ODWLDTRG_HasProperty;\r
+        stODWLDTRGclass.getProperty       = ODWLDTRG_GetProperty;\r
+        stODWLDTRGclass.setProperty       = ODWLDTRG_SetProperty;\r
+        stODWLDTRGclass.removeProperty    = ODWLDTRG_RemoveProperty;\r
+        stODWLDTRGclass.enumerate         = ODWLDTRG_Enumerate;\r
+        pODWLDTRGclass = &stODWLDTRGclass;\r
+    }\r
+\r
+    return pODWLDTRGclass;\r
+}\r
+\r
+\r
+NPObject *          ODWLDTRG_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    NPObject* newdwldtrg = NULL;\r
+    if (!v_bODWLDTRGIdentifiersInitialized)\r
+    {\r
+        v_bODWLDTRGIdentifiersInitialized = true;\r
+        ODWLDTRGinitializeIdentifiers();\r
+    }\r
+\r
+    newdwldtrg = (NPObject*)MEMALLOC(sizeof(NPObject));\r
+\r
+    return newdwldtrg;\r
+}\r
+\r
+  void        ODWLDTRG_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+  void        ODWLDTRG_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        ODWLDTRG_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kODWLDTRG_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_ODWLDTRGMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+       \r
+    return result;\r
+}\r
+\r
+bool        ODWLDTRG_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+       bool fctresult = false;\r
+    if (name == v_ODWLDTRGMethodIdentifiers[kODWLDTRG_ID_METHOD_REGISTER_DOWNLOAD])\r
+    {\r
+               ODWLDTRG_Invoke_registerDownload(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+    else if (name == v_ODWLDTRGMethodIdentifiers[kODWLDTRG_ID_METHOD_REGISTER_DOWNLOADURL])\r
+    {\r
+               ODWLDTRG_Invoke_registerDownloadURL(obj, args, argCount);\r
+               fctresult = true;\r
+    }\r
+       else\r
+    {        \r
+        fctresult = false;\r
+    }\r
+    return fctresult;\r
+}\r
+\r
+ bool        ODWLDTRG_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        ODWLDTRG_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+\r
+    int i = 0;\r
+    while ((i < kODWLDTRG_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_ODWLDTRGPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+  \r
+    return result;\r
+}\r
+\r
+  bool        ODWLDTRG_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        ODWLDTRG_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+ bool        ODWLDTRG_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        ODWLDTRG_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+void ODWLDTRG_Invoke_registerDownload(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
+\r
+void ODWLDTRG_Invoke_registerDownloadURL(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/oipfdownloadtrigger.h
new file mode 100644 (file)
index 0000000..cd7c337
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle                \r
+ *                             \r
+ */\r
+#ifndef __OIPFDOWNLOADTRIGGER_H__\r
+#define __OIPFDOWNLOADTRIGGER_H__\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+\r
+\r
+NPClass* fillODWLDTRGpclass(void);\r
+\r
+NPObject *  ODWLDTRG_Allocate(NPP npp, NPClass *aClass);\r
+void        ODWLDTRG_Deallocate(NPObject *obj);\r
+void        ODWLDTRG_Invalidate(NPObject *obj);\r
+bool        ODWLDTRG_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        ODWLDTRG_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        ODWLDTRG_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        ODWLDTRG_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        ODWLDTRG_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        ODWLDTRG_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+\r
+bool        ODWLDTRG_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+\r
+bool        ODWLDTRG_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+void ODWLDTRG_Invoke_registerDownload(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void ODWLDTRG_Invoke_registerDownloadURL(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.c b/applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.c
new file mode 100644 (file)
index 0000000..bfcfed7
--- /dev/null
@@ -0,0 +1,431 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#include "videobroadcast.h"\r
+\r
+#define kVIDBRC_ID_PROPERTY_WIDTH                              0\r
+#define kVIDBRC_ID_PROPERTY_HEIGHT                             1\r
+#define kVIDBRC_ID_PROPERTY_FULLSCREEN                                 2\r
+#define kVIDBRC_ID_PROPERTY_ONCHANNELCHANGEERROR               3\r
+#define kVIDBRC_ID_PROPERTY_PLAYSTATE                                  4\r
+#define kVIDBRC_ID_PROPERTY_ONPLAYSTATECHANGE                  5\r
+#define kVIDBRC_ID_PROPERTY_ONCHANNELCHANGESUCCEEDED   6\r
+#define kVIDBRC_ID_PROPERTY_ONFULLSCREENCHANGE                 7\r
+#define kVIDBRC_ID_PROPERTY_ONFOCUS                                            8\r
+#define kVIDBRC_ID_PROPERTY_ONBLUR                                             9\r
+#define kVIDBRC_NUM_PROPERTY_IDENTIFIERS                10\r
+\r
+#define kVIDBRC_ID_METHOD_GETCHANNELCONFIG              0\r
+#define kVIDBRC_ID_METHOD_BINDTOCURRENTCHANNEL          1\r
+#define kVIDBRC_ID_METHOD_CREATECHANNELOBJECT                  2\r
+#define kVIDBRC_ID_METHOD_CREATECHANNELOBJECT2             3\r
+#define kVIDBRC_ID_METHOD_SETCHANNEL                           4\r
+#define kVIDBRC_ID_METHOD_PREVCHANNEL                                  5\r
+#define kVIDBRC_ID_METHOD_NEXTCHANNEL                                  6\r
+#define kVIDBRC_ID_METHOD_SETFULLSCREEN                                        7\r
+#define kVIDBRC_ID_METHOD_GETVOLUME                                            8\r
+#define kVIDBRC_ID_METHOD_RELEASE                                              9\r
+#define kVIDBRC_NUM_METHOD_IDENTIFIERS                                 10\r
+\r
+\r
+bool            v_bVIDBRCIdentifiersInitialized = false;\r
+\r
+NPIdentifier    v_VIDBRCPropertyIdentifiers[kVIDBRC_NUM_PROPERTY_IDENTIFIERS];\r
+const NPUTF8 *  v_VIDBRCPropertyNames[kVIDBRC_NUM_PROPERTY_IDENTIFIERS] = {\r
+       "width",\r
+       "height",\r
+       "fullScreen",\r
+       "onChannelChangeError",\r
+       "playState",\r
+       "onPlayStateChange",\r
+       "onChannelChangeSucceeded",\r
+       "onFullScreenChange",\r
+       "onFocus",\r
+       "onBlur"\r
+       };\r
+\r
+NPIdentifier    v_VIDBRCMethodIdentifiers[kVIDBRC_NUM_METHOD_IDENTIFIERS];\r
+const NPUTF8 *  v_VIDBRCMethodNames[kVIDBRC_NUM_METHOD_IDENTIFIERS] = {\r
+       "getChannelConfig",\r
+       "bindToCurrentChannel",\r
+       "createChannelObject",\r
+       "createChannelObject2",\r
+       "setChannel",\r
+       "prevChannel",\r
+       "nextChannel",\r
+       "setFullScreen",\r
+       "getVolume",\r
+       "release"\r
+};\r
+\r
+static  void    VIDBRCinitializeIdentifiers(void)\r
+{\r
+    sBrowserFuncs->getstringidentifiers( v_VIDBRCPropertyNames, kVIDBRC_NUM_PROPERTY_IDENTIFIERS, v_VIDBRCPropertyIdentifiers );\r
+    sBrowserFuncs->getstringidentifiers( v_VIDBRCMethodNames,   kVIDBRC_NUM_METHOD_IDENTIFIERS,   v_VIDBRCMethodIdentifiers );\r
+}\r
+\r
+NPClass  stVIDBRCclass;\r
+NPClass* pVIDBRCclass = NULL;\r
+\r
+NPClass* fillVIDBRCpclass(void)\r
+{\r
+    TRACEINFO;\r
+    if (pVIDBRCclass == NULL)\r
+    {\r
+        stVIDBRCclass.allocate          = VIDBRC_Allocate;\r
+        stVIDBRCclass.deallocate        = VIDBRC_Deallocate;\r
+        stVIDBRCclass.invalidate        = VIDBRC_Invalidate;\r
+        stVIDBRCclass.hasMethod         = VIDBRC_HasMethod;\r
+        stVIDBRCclass.invoke            = VIDBRC_Invoke;\r
+        stVIDBRCclass.invokeDefault     = VIDBRC_InvokeDefault;\r
+        stVIDBRCclass.hasProperty       = VIDBRC_HasProperty;\r
+        stVIDBRCclass.getProperty       = VIDBRC_GetProperty;\r
+        stVIDBRCclass.setProperty       = VIDBRC_SetProperty;\r
+        stVIDBRCclass.removeProperty    = VIDBRC_RemoveProperty;\r
+        stVIDBRCclass.enumerate         = VIDBRC_Enumerate;\r
+        pVIDBRCclass = &stVIDBRCclass;\r
+    }\r
+\r
+    return pVIDBRCclass;\r
+}\r
+\r
+\r
+NPObject *          VIDBRC_Allocate(NPP npp, NPClass *theClass)\r
+{\r
+    TRACEINFO;\r
+\r
+    \r
+    if (!v_bVIDBRCIdentifiersInitialized)\r
+    {\r
+        v_bVIDBRCIdentifiersInitialized = true;\r
+        VIDBRCinitializeIdentifiers();\r
+    }\r
+       \r
+       NPObj_VidBrc* newvidbrc = (NPObj_VidBrc*)MEMALLOC(sizeof(NPObj_VidBrc));\r
+    newvidbrc->npp = npp;\r
+    \r
+    return (NPObject*) newvidbrc;\r
+}\r
+\r
+void           VIDBRC_Deallocate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    OnVIDBRC_SetFullScreen(true); \r
+    NPObj_VidBrc* vidbrc = (NPObj_VidBrc*)obj;\r
+    /*\r
+    if (vidbrc->pcArg_onChannelChangeSucceeded)\r
+    {\r
+        MEMFREE(vidbrc->pcArg_onChannelChangeSucceeded);\r
+ //       vidbrc->pcArg_onChannelChangeSucceeded = NULL;        \r
+    }  \r
+       if ( vidbrc->onChannelChangeSucceeded )\r
+       {\r
+               // sBrowserFuncs->releaseobject(vidbrc->onChannelChangeSucceeded);              \r
+       //      vidbrc->onChannelChangeSucceeded = NULL;\r
+       }\r
\r
+    */\r
+    MEMFREE(obj);\r
+    return;\r
+}\r
+\r
+  void        VIDBRC_Invalidate(NPObject* obj)\r
+{\r
+    TRACEINFO;\r
+    return;\r
+}\r
+\r
+  bool        VIDBRC_HasMethod(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+\r
+    bool result = false;\r
+    int i = 0;\r
+    NPUTF8* utf8methodname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    while ((i < kVIDBRC_NUM_METHOD_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_VIDBRCMethodIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+       \r
+    return result;\r
+}\r
+\r
+bool        VIDBRC_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+       bool fctresult = false;\r
+\r
+       if (name == v_VIDBRCMethodIdentifiers[kVIDBRC_ID_METHOD_GETCHANNELCONFIG])\r
+    {\r
+       VIDBRC_Invoke_getChannelConfig((NPObj_VidBrc*)obj, args, argCount, result);\r
+       fctresult = true;\r
+    }\r
+    \r
+    if (name == v_VIDBRCMethodIdentifiers[kVIDBRC_ID_METHOD_SETFULLSCREEN])\r
+    {\r
+       VIDBRC_Invoke_setFullScreen((NPObj_VidBrc*)obj, args, argCount);\r
+       fctresult = true;\r
+    }\r
+\r
+    if (name == v_VIDBRCMethodIdentifiers[kVIDBRC_ID_METHOD_BINDTOCURRENTCHANNEL])\r
+    {\r
+       VIDBRC_Invoke_bindToCurrentChannel(obj, args, argCount);\r
+       fctresult = true;\r
+    }\r
+    \r
+    \r
+    return fctresult;\r
+}\r
+\r
+ bool        VIDBRC_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+  bool        VIDBRC_HasProperty(NPObject* obj, NPIdentifier name)\r
+{\r
+    TRACEINFO;    bool result = false;\r
+    NPUTF8* utf8propertyname = (char*)sBrowserFuncs->utf8fromidentifier(name);\r
+    int i = 0;\r
+    while ((i < kVIDBRC_NUM_PROPERTY_IDENTIFIERS) && (result == false))\r
+    {\r
+        if ( name == v_VIDBRCPropertyIdentifiers[i] )\r
+        {\r
+            result= true;\r
+        }\r
+        i++;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+ bool        VIDBRC_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
+{\r
+    TRACEINFO;\r
+       bool fctresult = false;\r
+       NPObj_VidBrc* vidbrc = (NPObj_VidBrc*)obj;\r
+       \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_WIDTH]) {    \r
+               INT32_TO_NPVARIANT(vidbrc->width,*result);\r
+       fctresult = true;\r
+    } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_HEIGHT]) {\r
+               INT32_TO_NPVARIANT(vidbrc->height,*result);\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_FULLSCREEN]) {\r
+               BOOLEAN_TO_NPVARIANT(vidbrc->fullscreen, *result);\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_PLAYSTATE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONPLAYSTATECHANGE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONCHANNELCHANGEERROR]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONCHANNELCHANGESUCCEEDED]) {           \r
+   /*         if ( vidbrc->pcArg_onChannelChangeSucceeded != NULL )\r
+            {\r
+               char*  dup_str = strdup(vidbrc->pcArg_onChannelChangeSucceeded);                              \r
+               NPString npstr = { dup_str, (uint32_t)(strlen(dup_str)) }; \r
+               result->type = NPVariantType_String;\r
+               result->value.stringValue = npstr;               \r
+               fctresult = true;\r
+            }\r
+            else\r
+            {\r
+                OBJECT_TO_NPVARIANT(vidbrc->onPlayStateChange,*result);\r
+            }*/                                        \r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONFULLSCREENCHANGE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONFOCUS]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONBLUR]) {\r
+               fctresult = true;\r
+       }\r
+    \r
+    return fctresult;\r
+}\r
+\r
+  bool        VIDBRC_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
+{\r
+       TRACEINFO;\r
+       bool fctresult = false;\r
+       NPObj_VidBrc* vidbrc = (NPObj_VidBrc*)obj;\r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_WIDTH]) {    \r
+               vidbrc->width = NPVARIANT_TO_INT32(*value);\r
+               VIDBRC_setsize(vidbrc, vidbrc->width, vidbrc->height);\r
+       fctresult = true;\r
+    } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_HEIGHT]) {\r
+               vidbrc->height = NPVARIANT_TO_INT32(*value);\r
+               VIDBRC_setsize(vidbrc, vidbrc->width, vidbrc->height);\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_FULLSCREEN]) {         \r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_PLAYSTATE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONPLAYSTATECHANGE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONCHANNELCHANGEERROR]) {\r
+               fctresult = true;\r
+       } else \r
+       if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONCHANNELCHANGESUCCEEDED]) {\r
+    /*    if ( vidbrc->onChannelChangeSucceeded != NULL )\r
+        {\r
+            sBrowserFuncs->releaseobject(vidbrc->onChannelChangeSucceeded);\r
+            vidbrc->onChannelChangeSucceeded = NULL;\r
+        }\r
+        if ( vidbrc->pcArg_onChannelChangeSucceeded )\r
+        {\r
+            MEMFREE( vidbrc->pcArg_onChannelChangeSucceeded );\r
+            vidbrc->pcArg_onChannelChangeSucceeded = NULL;\r
+        }        \r
+        vidbrc->onChannelChangeSucceeded = NPVARIANT_TO_OBJECT(*value);\r
+        sBrowserFuncs->retainobject( vidbrc->onChannelChangeSucceeded);*/\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONFULLSCREENCHANGE]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONFOCUS]) {\r
+               fctresult = true;\r
+       } else \r
+    if (name == v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_ONBLUR]) {\r
+               fctresult = true;\r
+       }\r
+    return fctresult;\r
+}\r
+\r
+ bool        VIDBRC_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+\r
+ bool        VIDBRC_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
+{\r
+    TRACEINFO;\r
+    return true;\r
+}\r
+\r
+/** implementation of methods **/\r
+void           VIDBRC_Invoke_getChannelConfig(NPObj_VidBrc* obj,const NPVariant* args, uint32_t argCount, NPVariant* result)\r
+{\r
+       NOTIMPLEMENTED;\r
+       NULL_TO_NPVARIANT(*result);\r
+       return;\r
+}\r
+\r
+void           VIDBRC_Invoke_setFullScreen(NPObj_VidBrc* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       //NOTIMPLEMENTED; ///inprogress\r
+       \r
+       NPP npp = obj->npp;\r
+       int param;\r
+       if (argCount != 1 || !NPVARIANT_IS_BOOLEAN(args[0])) {\r
+               return;\r
+    }\r
+    else {\r
+               param = NPVARIANT_TO_BOOLEAN( args[0] );                \r
+               if (param != obj->fullscreen)\r
+               {\r
+                       if (param){\r
+                               obj->fullscreen = true;\r
+                               VIDBRC_setsize(obj, FULLSIZE_WIDTH, FULLSIZE_HEIGHT);\r
+                       }\r
+                       else{\r
+                               obj->fullscreen = false;\r
+                       }\r
+                       \r
+                       HBBTVPluginData* pdata = (HBBTVPluginData*)npp->pdata;\r
+                       if(pdata){\r
+                               if (pdata->window){                                             \r
+                                       OnVIDBRC_SetFullScreen(param);                  \r
+                               }\r
+                       }                                                                               \r
+               }       \r
+}\r
+    \r
+}\r
+\r
+void           VIDBRC_Invoke_bindToCurrentChannel(NPObject* obj,const NPVariant* args, uint32_t argCount)\r
+{\r
+       TRACEINFO;\r
+       NOTIMPLEMENTED;\r
+       //OnBindToCurrentChannel();\r
+}\r
+\r
+/** implementation of intermediary function **/\r
+\r
+void           VIDBRC_setsize(NPObj_VidBrc* obj,int32_t width, int32_t height)\r
+{\r
+               ///set the size\r
+               obj->width = width;\r
+               obj->height = height;\r
+               \r
+               /// get the plugin object and his style object\r
+               NPIdentifier    npIdent;\r
+               NPVariant       npVar;          \r
+               NPObject *      npObjPlugin = NULL;\r
+               NPObject *      npObjStyle = NULL;\r
+               \r
+               if (obj->npp)\r
+               {\r
+                       sBrowserFuncs->getvalue( obj->npp ,\r
+                                     NPNVPluginElementNPObject ,\r
+                                     &npObjPlugin );\r
+               }\r
+               if (npObjPlugin)\r
+               {\r
+                       npIdent = sBrowserFuncs->getstringidentifier( (const NPUTF8 *)"style" );\r
+                       sBrowserFuncs->getproperty( obj->npp ,\r
+                                                  npObjPlugin,\r
+                                                  npIdent ,\r
+                                                  &npVar );\r
+            npObjStyle = NPVARIANT_TO_OBJECT(npVar);\r
+          }\r
+          if (npObjStyle)\r
+          {\r
+                  INT32_TO_NPVARIANT(width,npVar);\r
+                  npIdent = v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_WIDTH];\r
+                  sBrowserFuncs->setproperty( obj->npp,npObjStyle, npIdent, &npVar);\r
+                  INT32_TO_NPVARIANT(height,npVar);\r
+                  npIdent = v_VIDBRCPropertyIdentifiers[kVIDBRC_ID_PROPERTY_HEIGHT];\r
+                  sBrowserFuncs->setproperty( obj->npp,npObjStyle, npIdent, &npVar);\r
+          }\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/videobroadcast.h
new file mode 100644 (file)
index 0000000..0027b76
--- /dev/null
@@ -0,0 +1,70 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ *             Authors:    Stanislas Selle             \r
+ *                             \r
+ */\r
+#ifndef    __VIDEOBROADCAST_H__\r
+#define    __VIDEOBROADCAST_H__\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <npapi.h>\r
+#include <nptypes.h>\r
+#include <npfunctions.h>\r
+#include <npruntime.h>\r
+\r
+#include "hbbtvbrowserplugin.h"\r
+\r
+#define FULLSIZE_WIDTH 1280\r
+#define FULLSIZE_HEIGHT 720\r
+\r
+typedef struct\r
+{\r
+       NPObject header;        \r
+       NPP npp; \r
+       NPBool      fullscreen;\r
+       int32_t     width;              \r
+    int32_t     height; \r
+    \r
+    \r
+    //~ char*           pcArg_onChannelChangeSucceeded;\r
+    //~ NPObject*       onChannelChangeSucceeded;\r
+    //NPObject*   channelConfig;\r
+    \r
+} NPObj_VidBrc;\r
+\r
+NPClass* fillVIDBRCpclass(void);\r
+\r
+NPObject *  VIDBRC_Allocate(NPP npp, NPClass *aClass);\r
+void        VIDBRC_Deallocate(NPObject *obj);\r
+void        VIDBRC_Invalidate(NPObject *obj);\r
+bool        VIDBRC_HasMethod(NPObject *obj, NPIdentifier name);\r
+bool        VIDBRC_Invoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        VIDBRC_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);\r
+bool        VIDBRC_HasProperty(NPObject *obj, NPIdentifier name);\r
+bool        VIDBRC_GetProperty(NPObject *obj, NPIdentifier name, NPVariant *result);\r
+bool        VIDBRC_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value);\r
+bool        VIDBRC_RemoveProperty(NPObject *npobj, NPIdentifier name);\r
+bool        VIDBRC_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);\r
+\r
+void           VIDBRC_Invoke_setFullScreen(NPObj_VidBrc* obj,const NPVariant* args, uint32_t argCount);\r
+void           VIDBRC_Invoke_bindToCurrentChannel(NPObject* obj,const NPVariant* args, uint32_t argCount);\r
+void           VIDBRC_Invoke_getChannelConfig(NPObj_VidBrc* obj,const NPVariant* args, uint32_t argCount, NPVariant* result);\r
+\r
+void           VIDBRC_setsize(NPObj_VidBrc* obj,int32_t witdh, int32_t height);\r
+#endif\r
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npapi.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npapi.h
new file mode 100644 (file)
index 0000000..c217718
--- /dev/null
@@ -0,0 +1,901 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef npapi_h_
+#define npapi_h_
+
+#if defined(__OS2__)
+#pragma pack(1)
+#endif
+
+#include "nptypes.h"
+
+#if defined(__OS2__) || defined(OS2)
+#ifndef XP_OS2
+#define XP_OS2 1
+#endif
+#endif
+
+#ifdef INCLUDE_JAVA
+#include "jri.h"                /* Java Runtime Interface */
+#else
+#define jref    void *
+#define JRIEnv  void
+#endif
+
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+#include <windows.h>
+#ifndef XP_WIN
+#define XP_WIN 1
+#endif
+#endif
+
+#if defined(__SYMBIAN32__)
+#ifndef XP_SYMBIAN
+#define XP_SYMBIAN 1
+#endif
+#endif
+
+#if defined(__APPLE_CC__) && !defined(XP_UNIX)
+#ifndef XP_MACOSX
+#define XP_MACOSX 1
+#endif
+#endif
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#define NP_NO_QUICKDRAW
+#define NP_NO_CARBON
+#endif
+
+#if defined(XP_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#include <OpenGL/OpenGL.h>
+#ifndef NP_NO_CARBON
+#include <Carbon/Carbon.h>
+#endif
+#endif
+
+#if defined(XP_UNIX)
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#endif
+
+#if defined(XP_SYMBIAN)
+#include <QEvent>
+#include <QRegion>
+#endif
+
+/*----------------------------------------------------------------------*/
+/*                        Plugin Version Constants                      */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 24
+
+
+/* The OS/2 version of Netscape uses RC_DATA to define the
+   mime types, file extensions, etc that are required.
+   Use a vertical bar to separate types, end types with \0.
+   FileVersion and ProductVersion are 32bit ints, all other
+   entries are strings that MUST be terminated with a \0.
+
+AN EXAMPLE:
+
+RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
+
+RCDATA NP_INFO_MIMEType    { "video/x-video|",
+                             "video/x-flick\0" }
+RCDATA NP_INFO_FileExtents { "avi|",
+                             "flc\0" }
+RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
+                             "MMOS2 Flc/Fli player(*.flc)\0" }
+
+RCDATA NP_INFO_FileVersion       { 1,0,0,1 }
+RCDATA NP_INFO_CompanyName       { "Netscape Communications\0" }
+RCDATA NP_INFO_FileDescription   { "NPAVI32 Extension DLL\0"
+RCDATA NP_INFO_InternalName      { "NPAVI32\0" )
+RCDATA NP_INFO_LegalCopyright    { "Copyright Netscape Communications \251 1996\0"
+RCDATA NP_INFO_OriginalFilename  { "NVAPI32.DLL" }
+RCDATA NP_INFO_ProductName       { "NPAVI32 Dynamic Link Library\0" }
+*/
+/* RC_DATA types for version info - required */
+#define NP_INFO_ProductVersion      1
+#define NP_INFO_MIMEType            2
+#define NP_INFO_FileOpenName        3
+#define NP_INFO_FileExtents         4
+/* RC_DATA types for version info - used if found */
+#define NP_INFO_FileDescription     5
+#define NP_INFO_ProductName         6
+/* RC_DATA types for version info - optional */
+#define NP_INFO_CompanyName         7
+#define NP_INFO_FileVersion         8
+#define NP_INFO_InternalName        9
+#define NP_INFO_LegalCopyright      10
+#define NP_INFO_OriginalFilename    11
+
+#ifndef RC_INVOKED
+
+/*----------------------------------------------------------------------*/
+/*                       Definition of Basic Types                      */
+/*----------------------------------------------------------------------*/
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef NULL
+#define NULL (0L)
+#endif
+
+typedef unsigned char NPBool;
+typedef int16_t       NPError;
+typedef int16_t       NPReason;
+typedef char*         NPMIMEType;
+
+/*----------------------------------------------------------------------*/
+/*                       Structures and definitions                     */
+/*----------------------------------------------------------------------*/
+
+#if !defined(__LP64__)
+#if defined(XP_MACOSX)
+#pragma options align=mac68k
+#endif
+#endif /* __LP64__ */
+
+/*
+ *  NPP is a plug-in's opaque instance handle
+ */
+typedef struct _NPP
+{
+  void* pdata;      /* plug-in private data */
+  void* ndata;      /* netscape private data */
+} NPP_t;
+
+typedef NPP_t*  NPP;
+
+typedef struct _NPStream
+{
+  void*    pdata; /* plug-in private data */
+  void*    ndata; /* netscape private data */
+  const    char* url;
+  uint32_t end;
+  uint32_t lastmodified;
+  void*    notifyData;
+  const    char* headers; /* Response headers from host.
+                           * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
+                           * Used for HTTP only; NULL for non-HTTP.
+                           * Available from NPP_NewStream onwards.
+                           * Plugin should copy this data before storing it.
+                           * Includes HTTP status line and all headers,
+                           * preferably verbatim as received from server,
+                           * headers formatted as in HTTP ("Header: Value"),
+                           * and newlines (\n, NOT \r\n) separating lines.
+                           * Terminated by \n\0 (NOT \n\n\0). */
+} NPStream;
+
+typedef struct _NPByteRange
+{
+  int32_t  offset; /* negative offset means from the end */
+  uint32_t length;
+  struct _NPByteRange* next;
+} NPByteRange;
+
+typedef struct _NPSavedData
+{
+  int32_t len;
+  void*   buf;
+} NPSavedData;
+
+typedef struct _NPRect
+{
+  uint16_t top;
+  uint16_t left;
+  uint16_t bottom;
+  uint16_t right;
+} NPRect;
+
+typedef struct _NPSize
+{
+  int32_t width;
+  int32_t height;
+} NPSize;
+
+typedef enum {
+  NPFocusNext = 0,
+  NPFocusPrevious = 1
+} NPFocusDirection;
+
+/* Return values for NPP_HandleEvent */
+#define kNPEventNotHandled 0
+#define kNPEventHandled 1
+/* Exact meaning must be spec'd in event model. */
+#define kNPEventStartIME 2
+
+#if defined(XP_UNIX)
+/*
+ * Unix specific structures and definitions
+ */
+
+/*
+ * Callback Structures.
+ *
+ * These are used to pass additional platform specific information.
+ */
+enum {
+  NP_SETWINDOW = 1,
+  NP_PRINT
+};
+
+typedef struct
+{
+  int32_t type;
+} NPAnyCallbackStruct;
+
+typedef struct
+{
+  int32_t      type;
+  Display*     display;
+  Visual*      visual;
+  Colormap     colormap;
+  unsigned int depth;
+} NPSetWindowCallbackStruct;
+
+typedef struct
+{
+  int32_t type;
+  FILE* fp;
+} NPPrintCallbackStruct;
+
+#endif /* XP_UNIX */
+
+#if defined(XP_MACOSX)
+typedef enum {
+#ifndef NP_NO_QUICKDRAW
+  NPDrawingModelQuickDraw = 0,
+#endif
+  NPDrawingModelCoreGraphics = 1,
+  NPDrawingModelOpenGL = 2,
+  NPDrawingModelCoreAnimation = 3
+} NPDrawingModel;
+
+typedef enum {
+#ifndef NP_NO_CARBON
+  NPEventModelCarbon = 0,
+#endif
+  NPEventModelCocoa = 1
+} NPEventModel;
+#endif
+
+/*
+ *   The following masks are applied on certain platforms to NPNV and
+ *   NPPV selectors that pass around pointers to COM interfaces. Newer
+ *   compilers on some platforms may generate vtables that are not
+ *   compatible with older compilers. To prevent older plugins from
+ *   not understanding a new browser's ABI, these masks change the
+ *   values of those selectors on those platforms. To remain backwards
+ *   compatible with different versions of the browser, plugins can
+ *   use these masks to dynamically determine and use the correct C++
+ *   ABI that the browser is expecting. This does not apply to Windows
+ *   as Microsoft's COM ABI will likely not change.
+ */
+
+#define NP_ABI_GCC3_MASK  0x10000000
+/*
+ *   gcc 3.x generated vtables on UNIX and OSX are incompatible with
+ *   previous compilers.
+ */
+#if (defined(XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
+#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_GCC3 0
+#endif
+
+#if defined(XP_MACOSX)
+#define NP_ABI_MACHO_MASK 0x01000000
+#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_MACHO 0
+#endif
+
+#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
+
+/*
+ * List of variable names for which NPP_GetValue shall be implemented
+ */
+typedef enum {
+  NPPVpluginNameString = 1,
+  NPPVpluginDescriptionString,
+  NPPVpluginWindowBool,
+  NPPVpluginTransparentBool,
+  NPPVjavaClass,                /* Not implemented in WebKit */
+  NPPVpluginWindowSize,         /* Not implemented in WebKit */
+  NPPVpluginTimerInterval,      /* Not implemented in WebKit */
+  NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
+  NPPVpluginScriptableIID = 11, /* Not implemented in WebKit */
+  NPPVjavascriptPushCallerBool = 12,  /* Not implemented in WebKit */
+  NPPVpluginKeepLibraryInMemory = 13, /* Not implemented in WebKit */
+  NPPVpluginNeedsXEmbed         = 14, /* Not implemented in WebKit */
+
+  /* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14.
+   */
+  NPPVpluginScriptableNPObject  = 15,
+
+  /* Get the plugin value (as \0-terminated UTF-8 string data) for
+   * form submission if the plugin is part of a form. Use
+   * NPN_MemAlloc() to allocate memory for the string data. Introduced
+   * in NPAPI minor version 15.
+   */
+  NPPVformValue = 16,    /* Not implemented in WebKit */
+
+  NPPVpluginUrlRequestsDisplayedBool = 17, /* Not implemented in WebKit */
+
+  /* Checks if the plugin is interested in receiving the http body of
+   * all http requests (including failed ones, http status != 200).
+   */
+  NPPVpluginWantsAllNetworkStreams = 18,
+
+  /* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
+  NPPVpluginNativeAccessibleAtkPlugId = 19,
+
+  /* Checks to see if the plug-in would like the browser to load the "src" attribute. */
+  NPPVpluginCancelSrcStream = 20
+
+#if defined(XP_MACOSX)
+  /* Used for negotiating drawing models */
+  , NPPVpluginDrawingModel = 1000
+  /* Used for negotiating event models */
+  , NPPVpluginEventModel = 1001
+  /* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
+  , NPPVpluginCoreAnimationLayer = 1003
+#endif
+
+#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
+  , NPPVpluginWindowlessLocalBool = 2002
+#endif
+} NPPVariable;
+
+/*
+ * List of variable names for which NPN_GetValue should be implemented.
+ */
+typedef enum {
+  NPNVxDisplay = 1,
+  NPNVxtAppContext,
+  NPNVnetscapeWindow,
+  NPNVjavascriptEnabledBool,
+  NPNVasdEnabledBool,
+  NPNVisOfflineBool,
+
+  NPNVserviceManager = (10 | NP_ABI_MASK),  /* Not implemented in WebKit */
+  NPNVDOMElement     = (11 | NP_ABI_MASK),  /* Not implemented in WebKit */
+  NPNVDOMWindow      = (12 | NP_ABI_MASK),  /* Not implemented in WebKit */
+  NPNVToolkit        = (13 | NP_ABI_MASK),  /* Not implemented in WebKit */
+  NPNVSupportsXEmbedBool = 14,              /* Not implemented in WebKit */
+
+  /* Get the NPObject wrapper for the browser window. */
+  NPNVWindowNPObject = 15,
+
+  /* Get the NPObject wrapper for the plugins DOM element. */
+  NPNVPluginElementNPObject = 16,
+
+  NPNVSupportsWindowless = 17,
+
+  NPNVprivateModeBool = 18
+
+#if defined(XP_MACOSX)
+  /* Used for negotiating drawing models */
+  , NPNVpluginDrawingModel = 1000
+#ifndef NP_NO_QUICKDRAW
+  , NPNVsupportsQuickDrawBool = 2000
+#endif
+  , NPNVsupportsCoreGraphicsBool = 2001
+  , NPNVsupportsOpenGLBool = 2002
+  , NPNVsupportsCoreAnimationBool = 2003
+#ifndef NP_NO_CARBON
+  , NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
+#endif
+  , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
+#endif /* XP_MACOSX */
+#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
+  , NPNVSupportsWindowlessLocal = 2002
+#endif
+} NPNVariable;
+
+typedef enum {
+  NPNURLVCookie = 501,
+  NPNURLVProxy
+} NPNURLVariable;
+
+/*
+ * The type of Toolkit the widgets use
+ */
+typedef enum {
+  NPNVGtk12 = 1,
+  NPNVGtk2
+} NPNToolkitType;
+
+/*
+ * The type of a NPWindow - it specifies the type of the data structure
+ * returned in the window field.
+ */
+typedef enum {
+  NPWindowTypeWindow = 1,
+  NPWindowTypeDrawable
+} NPWindowType;
+
+typedef struct _NPWindow
+{
+  void* window;  /* Platform specific window handle */
+                 /* OS/2: x - Position of bottom left corner */
+                 /* OS/2: y - relative to visible netscape window */
+  int32_t  x;      /* Position of top left corner relative */
+  int32_t  y;      /* to a netscape page. */
+  uint32_t width;  /* Maximum window size */
+  uint32_t height;
+  NPRect   clipRect; /* Clipping rectangle in port coordinates */
+#if defined(XP_UNIX) || defined(XP_SYMBIAN)
+  void * ws_info; /* Platform-dependent additonal data */
+#endif /* XP_UNIX || XP_SYMBIAN */
+  NPWindowType type; /* Is this a window or a drawable? */
+} NPWindow;
+
+typedef struct _NPImageExpose
+{
+  char*    data;       /* image pointer */
+  int32_t  stride;     /* Stride of data image pointer */
+  int32_t  depth;      /* Depth of image pointer */
+  int32_t  x;          /* Expose x */
+  int32_t  y;          /* Expose y */
+  uint32_t width;      /* Expose width */
+  uint32_t height;     /* Expose height */
+  NPSize   dataSize;   /* Data buffer size */
+  float    translateX; /* translate X matrix value */
+  float    translateY; /* translate Y matrix value */
+  float    scaleX;     /* scale X matrix value */
+  float    scaleY;     /* scale Y matrix value */
+} NPImageExpose;
+
+typedef struct _NPFullPrint
+{
+  NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
+  NPBool printOne;     /* TRUE if plugin should print one copy to default
+                          printer */
+  void* platformPrint; /* Platform-specific printing info */
+} NPFullPrint;
+
+typedef struct _NPEmbedPrint
+{
+  NPWindow window;
+  void* platformPrint; /* Platform-specific printing info */
+} NPEmbedPrint;
+
+typedef struct _NPPrint
+{
+  uint16_t mode;               /* NP_FULL or NP_EMBED */
+  union
+  {
+    NPFullPrint fullPrint;   /* if mode is NP_FULL */
+    NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
+  } print;
+} NPPrint;
+
+#if defined(XP_MACOSX)
+#ifndef NP_NO_CARBON
+typedef EventRecord NPEvent;
+#else
+typedef void*  NPEvent;
+#endif
+#elif defined(XP_SYMBIAN)
+typedef QEvent NPEvent;
+#elif defined(XP_WIN)
+typedef struct _NPEvent
+{
+  uint16_t event;
+  uintptr_t wParam;
+  uintptr_t lParam;
+} NPEvent;
+#elif defined(XP_OS2)
+typedef struct _NPEvent
+{
+  uint32_t event;
+  uint32_t wParam;
+  uint32_t lParam;
+} NPEvent;
+#elif defined(XP_UNIX)
+typedef XEvent NPEvent;
+#else
+typedef void*  NPEvent;
+#endif
+
+#if defined(XP_MACOSX)
+typedef void* NPRegion;
+#ifndef NP_NO_QUICKDRAW
+typedef RgnHandle NPQDRegion;
+#endif
+typedef CGPathRef NPCGRegion;
+#elif defined(XP_WIN)
+typedef HRGN NPRegion;
+#elif defined(XP_UNIX)
+typedef Region NPRegion;
+#elif defined(XP_SYMBIAN)
+typedef QRegion* NPRegion;
+#else
+typedef void *NPRegion;
+#endif
+
+typedef struct _NPNSString NPNSString;
+typedef struct _NPNSWindow NPNSWindow;
+typedef struct _NPNSMenu   NPNSMenu;
+
+#if defined(XP_MACOSX)
+typedef NPNSMenu NPMenu;
+#else
+typedef void *NPMenu;
+#endif
+
+typedef enum {
+  NPCoordinateSpacePlugin = 1,
+  NPCoordinateSpaceWindow,
+  NPCoordinateSpaceFlippedWindow,
+  NPCoordinateSpaceScreen,
+  NPCoordinateSpaceFlippedScreen
+} NPCoordinateSpace;
+
+#if defined(XP_MACOSX)
+
+#ifndef NP_NO_QUICKDRAW
+typedef struct NP_Port
+{
+  CGrafPtr port;
+  int32_t portx; /* position inside the topmost window */
+  int32_t porty;
+} NP_Port;
+#endif /* NP_NO_QUICKDRAW */
+
+/*
+ * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
+ * as its drawing model.
+ */
+
+typedef struct NP_CGContext
+{
+  CGContextRef context;
+#ifdef NP_NO_CARBON
+  NPNSWindow *window;
+#else
+  void *window; /* A WindowRef or NULL for the Cocoa event model. */
+#endif
+} NP_CGContext;
+
+/*
+ * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
+ * drawing model.
+ */
+
+typedef struct NP_GLContext
+{
+  CGLContextObj context;
+#ifdef NP_NO_CARBON
+  NPNSWindow *window;
+#else
+  void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */
+#endif
+} NP_GLContext;
+
+typedef enum {
+  NPCocoaEventDrawRect = 1,
+  NPCocoaEventMouseDown,
+  NPCocoaEventMouseUp,
+  NPCocoaEventMouseMoved,
+  NPCocoaEventMouseEntered,
+  NPCocoaEventMouseExited,
+  NPCocoaEventMouseDragged,
+  NPCocoaEventKeyDown,
+  NPCocoaEventKeyUp,
+  NPCocoaEventFlagsChanged,
+  NPCocoaEventFocusChanged,
+  NPCocoaEventWindowFocusChanged,
+  NPCocoaEventScrollWheel,
+  NPCocoaEventTextInput
+} NPCocoaEventType;
+
+typedef struct _NPCocoaEvent {
+  NPCocoaEventType type;
+  uint32_t version;
+  union {
+    struct {
+      uint32_t modifierFlags;
+      double   pluginX;
+      double   pluginY;
+      int32_t  buttonNumber;
+      int32_t  clickCount;
+      double   deltaX;
+      double   deltaY;
+      double   deltaZ;
+    } mouse;
+    struct {
+      uint32_t    modifierFlags;
+      NPNSString *characters;
+      NPNSString *charactersIgnoringModifiers;
+      NPBool      isARepeat;
+      uint16_t    keyCode;
+    } key;
+    struct {
+      CGContextRef context;
+      double x;
+      double y;
+      double width;
+      double height;
+    } draw;
+    struct {
+      NPBool hasFocus;
+    } focus;
+    struct {
+      NPNSString *text;
+    } text;
+  } data;
+} NPCocoaEvent;
+
+#ifndef NP_NO_CARBON
+/* Non-standard event types that can be passed to HandleEvent */
+enum NPEventType {
+  NPEventType_GetFocusEvent = (osEvt + 16),
+  NPEventType_LoseFocusEvent,
+  NPEventType_AdjustCursorEvent,
+  NPEventType_MenuCommandEvent,
+  NPEventType_ClippingChangedEvent,
+  NPEventType_ScrollingBeginsEvent = 1000,
+  NPEventType_ScrollingEndsEvent
+};
+#endif /* NP_NO_CARBON */
+
+#endif /* XP_MACOSX */
+
+/*
+ * Values for mode passed to NPP_New:
+ */
+#define NP_EMBED 1
+#define NP_FULL  2
+
+/*
+ * Values for stream type passed to NPP_NewStream:
+ */
+#define NP_NORMAL     1
+#define NP_SEEK       2
+#define NP_ASFILE     3
+#define NP_ASFILEONLY 4
+
+#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
+
+/*
+ * Flags for NPP_ClearSiteData.
+ */
+#define NP_CLEAR_ALL   0
+#define NP_CLEAR_CACHE (1 << 0)
+
+#if !defined(__LP64__)
+#if defined(XP_MACOSX)
+#pragma options align=reset
+#endif
+#endif /* __LP64__ */
+
+/*----------------------------------------------------------------------*/
+/*       Error and Reason Code definitions                              */
+/*----------------------------------------------------------------------*/
+
+/*
+ * Values of type NPError:
+ */
+#define NPERR_BASE                         0
+#define NPERR_NO_ERROR                    (NPERR_BASE + 0)
+#define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
+#define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
+#define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
+#define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
+#define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
+#define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
+#define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
+#define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
+#define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
+#define NPERR_INVALID_URL                 (NPERR_BASE + 10)
+#define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
+#define NPERR_NO_DATA                     (NPERR_BASE + 12)
+#define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
+
+/*
+ * Values of type NPReason:
+ */
+#define NPRES_BASE          0
+#define NPRES_DONE         (NPRES_BASE + 0)
+#define NPRES_NETWORK_ERR  (NPRES_BASE + 1)
+#define NPRES_USER_BREAK   (NPRES_BASE + 2)
+
+/*
+ * Don't use these obsolete error codes any more.
+ */
+#define NP_NOERR  NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
+#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
+#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
+
+/*
+ * Version feature information
+ */
+#define NPVERS_HAS_STREAMOUTPUT             8
+#define NPVERS_HAS_NOTIFICATION             9
+#define NPVERS_HAS_LIVECONNECT              9
+#define NPVERS_WIN16_HAS_LIVECONNECT        9
+#define NPVERS_68K_HAS_LIVECONNECT          11
+#define NPVERS_HAS_WINDOWLESS               11
+#define NPVERS_HAS_XPCONNECT_SCRIPTING      13  /* Not implemented in WebKit */
+#define NPVERS_HAS_NPRUNTIME_SCRIPTING      14
+#define NPVERS_HAS_FORM_VALUES              15  /* Not implemented in WebKit; see bug 13061 */
+#define NPVERS_HAS_POPUPS_ENABLED_STATE     16  /* Not implemented in WebKit */
+#define NPVERS_HAS_RESPONSE_HEADERS         17
+#define NPVERS_HAS_NPOBJECT_ENUM            18
+#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
+#define NPVERS_HAS_ALL_NETWORK_STREAMS      20
+#define NPVERS_HAS_URL_AND_AUTH_INFO        21
+#define NPVERS_HAS_PRIVATE_MODE             22
+#define NPVERS_MACOSX_HAS_EVENT_MODELS      23
+#define NPVERS_HAS_CANCEL_SRC_STREAM        24
+#define NPVERS_HAS_ADVANCED_KEY_HANDLING    25
+#define NPVERS_HAS_URL_REDIRECT_HANDLING    26
+#define NPVERS_HAS_CLEAR_SITE_DATA          27
+
+/*----------------------------------------------------------------------*/
+/*                        Function Prototypes                           */
+/*----------------------------------------------------------------------*/
+
+#if defined(__OS2__)
+#define NP_LOADDS _System
+#else
+#define NP_LOADDS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NPP_* functions are provided by the plugin and called by the navigator. */
+
+#if defined(XP_UNIX)
+char* NPP_GetMIMEDescription(void);
+#endif
+
+NPError NP_LOADDS NPP_Initialize(void);
+void    NP_LOADDS NPP_Shutdown(void);
+NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
+                          uint16_t mode, int16_t argc, char* argn[],
+                          char* argv[], NPSavedData* saved);
+NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
+NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
+NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
+                                NPStream* stream, NPBool seekable,
+                                uint16_t* stype);
+NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
+                                    NPReason reason);
+int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
+int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset,
+                            int32_t len, void* buffer);
+void    NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
+                                   const char* fname);
+void    NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
+int16_t NP_LOADDS NPP_HandleEvent(NPP instance, void* event);
+void    NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
+                                NPReason reason, void* notifyData);
+jref    NP_LOADDS NPP_GetJavaClass(void);
+NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
+NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
+NPBool  NP_LOADDS NPP_GotFocus(NPP instance, NPFocusDirection direction);
+void    NP_LOADDS NPP_LostFocus(NPP instance);
+void    NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData);
+NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge);
+char**  NP_LOADDS NPP_GetSitesWithData(void);
+
+/* NPN_* functions are provided by the navigator and called by the plugin. */
+void        NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
+                                  int* netscape_major, int* netscape_minor);
+NPError     NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
+                                       const char* target, void* notifyData);
+NPError     NP_LOADDS NPN_GetURL(NPP instance, const char* url,
+                                 const char* target);
+NPError     NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
+                                        const char* target, uint32_t len,
+                                        const char* buf, NPBool file,
+                                        void* notifyData);
+NPError     NP_LOADDS NPN_PostURL(NPP instance, const char* url,
+                                  const char* target, uint32_t len,
+                                  const char* buf, NPBool file);
+NPError     NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
+NPError     NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
+                                    const char* target, NPStream** stream);
+int32_t     NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len,
+                                void* buffer);
+NPError     NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream,
+                                        NPReason reason);
+void        NP_LOADDS NPN_Status(NPP instance, const char* message);
+const char* NP_LOADDS NPN_UserAgent(NPP instance);
+void*       NP_LOADDS NPN_MemAlloc(uint32_t size);
+void        NP_LOADDS NPN_MemFree(void* ptr);
+uint32_t    NP_LOADDS NPN_MemFlush(uint32_t size);
+void        NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
+JRIEnv*     NP_LOADDS NPN_GetJavaEnv(void);
+jref        NP_LOADDS NPN_GetJavaPeer(NPP instance);
+NPError     NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable,
+                                   void *value);
+NPError     NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable,
+                                   void *value);
+void        NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
+void        NP_LOADDS NPN_InvalidateRegion(NPP instance,
+                                           NPRegion invalidRegion);
+void        NP_LOADDS NPN_ForceRedraw(NPP instance);
+void        NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
+void        NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
+void        NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
+                                                void (*func) (void *),
+                                                void *userData);
+NPError     NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable,
+                                         const char *url, char **value,
+                                         uint32_t *len);
+NPError     NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable,
+                                         const char *url, const char *value,
+                                         uint32_t len);
+NPError     NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
+                                                const char *protocol,
+                                                const char *host, int32_t port,
+                                                const char *scheme,
+                                                const char *realm,
+                                                char **username, uint32_t *ulen,
+                                                char **password,
+                                                uint32_t *plen);
+uint32_t    NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
+void        NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
+NPError     NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
+NPBool      NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* RC_INVOKED */
+#if defined(__OS2__)
+#pragma pack()
+#endif
+
+#endif /* npapi_h_ */
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npfunctions.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npfunctions.h
new file mode 100644 (file)
index 0000000..c54e473
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+#ifndef NPFUNCTIONS_H
+#define NPFUNCTIONS_H
+
+
+#include "npruntime.h"
+#include "npapi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(XP_WIN)
+#define EXPORTED_CALLBACK(_type, _name) _type (__stdcall * _name)
+#else
+#define EXPORTED_CALLBACK(_type, _name) _type (* _name)
+#endif
+
+typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, void* notifyData);
+typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData);
+typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList);
+typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream);
+typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer);
+typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
+typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message);
+typedef const char*(*NPN_UserAgentProcPtr)(NPP instance);
+typedef void* (*NPN_MemAllocProcPtr)(uint32_t size);
+typedef void (*NPN_MemFreeProcPtr)(void* ptr);
+typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size);
+typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
+typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
+typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
+typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect);
+typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
+typedef void (*NPN_ForceRedrawProcPtr)(NPP instance);
+typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* URL, const char* window);
+typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* URL, const char* window, uint32_t len, const char* buf, NPBool file);
+typedef void* (*NPN_GetJavaEnvProcPtr)(void);
+typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance);
+typedef void  (*NPN_PushPopupsEnabledStateProcPtr)(NPP instance, NPBool enabled);
+typedef void  (*NPN_PopPopupsEnabledStateProcPtr)(NPP instance);
+typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP npp, void (*func)(void *), void *userData);
+typedef NPError (*NPN_GetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len);
+typedef NPError (*NPN_SetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len);
+typedef NPError (*NPN_GetAuthenticationInfoProcPtr)(NPP npp, const char* protocol, const char* host, int32_t port, const char* scheme, const char *realm, char** username, uint32_t* ulen, char** password, uint32_t* plen);
+
+typedef uint32_t (*NPN_ScheduleTimerProcPtr)(NPP npp, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
+typedef void (*NPN_UnscheduleTimerProcPtr)(NPP npp, uint32_t timerID);
+typedef NPError (*NPN_PopUpContextMenuProcPtr)(NPP instance, NPMenu* menu);
+typedef NPBool (*NPN_ConvertPointProcPtr)(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
+
+typedef void (*NPN_ReleaseVariantValueProcPtr) (NPVariant *variant);
+
+typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr) (const NPUTF8 *name);
+typedef void (*NPN_GetStringIdentifiersProcPtr) (const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr) (int32_t intid);
+typedef int32_t (*NPN_IntFromIdentifierProcPtr) (NPIdentifier identifier);
+typedef bool (*NPN_IdentifierIsStringProcPtr) (NPIdentifier identifier);
+typedef NPUTF8 *(*NPN_UTF8FromIdentifierProcPtr) (NPIdentifier identifier);
+
+typedef NPObject* (*NPN_CreateObjectProcPtr) (NPP, NPClass *aClass);
+typedef NPObject* (*NPN_RetainObjectProcPtr) (NPObject *obj);
+typedef void (*NPN_ReleaseObjectProcPtr) (NPObject *obj);
+typedef bool (*NPN_InvokeProcPtr) (NPP npp, NPObject *obj, NPIdentifier methodName, const NPVariant *args, unsigned argCount, NPVariant *result);
+typedef bool (*NPN_InvokeDefaultProcPtr) (NPP npp, NPObject *obj, const NPVariant *args, unsigned argCount, NPVariant *result);
+typedef bool (*NPN_EvaluateProcPtr) (NPP npp, NPObject *obj, NPString *script, NPVariant *result);
+typedef bool (*NPN_GetPropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier  propertyName, NPVariant *result);
+typedef bool (*NPN_SetPropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier  propertyName, const NPVariant *value);
+typedef bool (*NPN_HasPropertyProcPtr) (NPP, NPObject *npobj, NPIdentifier propertyName);
+typedef bool (*NPN_HasMethodProcPtr) (NPP npp, NPObject *npobj, NPIdentifier methodName);
+typedef bool (*NPN_RemovePropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier propertyName);
+typedef void (*NPN_SetExceptionProcPtr) (NPObject *obj, const NPUTF8 *message);
+typedef bool (*NPN_EnumerateProcPtr) (NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);    
+
+typedef NPError (*NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
+typedef NPError (*NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
+typedef NPError (*NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
+typedef NPError (*NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
+typedef NPError (*NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
+typedef void (*NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname);
+typedef int32_t (*NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
+typedef int32_t (*NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
+typedef void (*NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
+typedef int16_t (*NPP_HandleEventProcPtr)(NPP instance, void* event);
+typedef void (*NPP_URLNotifyProcPtr)(NPP instance, const char* URL, NPReason reason, void* notifyData);
+typedef NPError (*NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value);
+typedef NPError (*NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value);
+typedef NPBool (*NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction);
+typedef void (*NPP_LostFocusPtr)(NPP instance);
+typedef void (*NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData);
+typedef NPError (*NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge);
+typedef char** (*NPP_GetSitesWithDataPtr)(void);
+
+typedef void *(*NPP_GetJavaClassProcPtr)(void);
+typedef void* JRIGlobalRef; //not using this right now
+
+typedef struct _NPNetscapeFuncs {
+    uint16_t size;
+    uint16_t version;
+    
+    NPN_GetURLProcPtr geturl;
+    NPN_PostURLProcPtr posturl;
+    NPN_RequestReadProcPtr requestread;
+    NPN_NewStreamProcPtr newstream;
+    NPN_WriteProcPtr write;
+    NPN_DestroyStreamProcPtr destroystream;
+    NPN_StatusProcPtr status;
+    NPN_UserAgentProcPtr uagent;
+    NPN_MemAllocProcPtr memalloc;
+    NPN_MemFreeProcPtr memfree;
+    NPN_MemFlushProcPtr memflush;
+    NPN_ReloadPluginsProcPtr reloadplugins;
+    NPN_GetJavaEnvProcPtr getJavaEnv;
+    NPN_GetJavaPeerProcPtr getJavaPeer;
+    NPN_GetURLNotifyProcPtr geturlnotify;
+    NPN_PostURLNotifyProcPtr posturlnotify;
+    NPN_GetValueProcPtr getvalue;
+    NPN_SetValueProcPtr setvalue;
+    NPN_InvalidateRectProcPtr invalidaterect;
+    NPN_InvalidateRegionProcPtr invalidateregion;
+    NPN_ForceRedrawProcPtr forceredraw;
+    
+    NPN_GetStringIdentifierProcPtr getstringidentifier;
+    NPN_GetStringIdentifiersProcPtr getstringidentifiers;
+    NPN_GetIntIdentifierProcPtr getintidentifier;
+    NPN_IdentifierIsStringProcPtr identifierisstring;
+    NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
+    NPN_IntFromIdentifierProcPtr intfromidentifier;
+    NPN_CreateObjectProcPtr createobject;
+    NPN_RetainObjectProcPtr retainobject;
+    NPN_ReleaseObjectProcPtr releaseobject;
+    NPN_InvokeProcPtr invoke;
+    NPN_InvokeDefaultProcPtr invokeDefault;
+    NPN_EvaluateProcPtr evaluate;
+    NPN_GetPropertyProcPtr getproperty;
+    NPN_SetPropertyProcPtr setproperty;
+    NPN_RemovePropertyProcPtr removeproperty;
+    NPN_HasPropertyProcPtr hasproperty;
+    NPN_HasMethodProcPtr hasmethod;
+    NPN_ReleaseVariantValueProcPtr releasevariantvalue;
+    NPN_SetExceptionProcPtr setexception;
+    NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
+    NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
+    NPN_EnumerateProcPtr enumerate;
+    NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
+    NPN_ConstructProcPtr construct;
+    NPN_GetValueForURLProcPtr getvalueforurl;
+    NPN_SetValueForURLProcPtr setvalueforurl;
+    NPN_GetAuthenticationInfoProcPtr getauthenticationinfo;
+    NPN_ScheduleTimerProcPtr scheduletimer;
+    NPN_UnscheduleTimerProcPtr unscheduletimer;
+    NPN_PopUpContextMenuProcPtr popupcontextmenu;
+    NPN_ConvertPointProcPtr convertpoint;
+} NPNetscapeFuncs;
+
+typedef struct _NPPluginFuncs {
+    uint16_t size;
+    uint16_t version;
+    NPP_NewProcPtr newp;
+    NPP_DestroyProcPtr destroy;
+    NPP_SetWindowProcPtr setwindow;
+    NPP_NewStreamProcPtr newstream;
+    NPP_DestroyStreamProcPtr destroystream;
+    NPP_StreamAsFileProcPtr asfile;
+    NPP_WriteReadyProcPtr writeready;
+    NPP_WriteProcPtr write;
+    NPP_PrintProcPtr print;
+    NPP_HandleEventProcPtr event;
+    NPP_URLNotifyProcPtr urlnotify;
+    JRIGlobalRef javaClass;
+    NPP_GetValueProcPtr getvalue;
+    NPP_SetValueProcPtr setvalue;
+    NPP_GotFocusPtr gotfocus;
+    NPP_LostFocusPtr lostfocus;
+    NPP_URLRedirectNotifyPtr urlredirectnotify;
+    NPP_ClearSiteDataPtr clearsitedata;
+    NPP_GetSitesWithDataPtr getsiteswithdata;
+} NPPluginFuncs;
+
+typedef EXPORTED_CALLBACK(NPError, NP_GetEntryPointsFuncPtr)(NPPluginFuncs*);
+typedef EXPORTED_CALLBACK(void, NPP_ShutdownProcPtr)(void);    
+
+#if defined(XP_MACOSX)
+typedef void (*BP_CreatePluginMIMETypesPreferencesFuncPtr)(void);
+typedef NPError (*MainFuncPtr)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownProcPtr*);
+#endif
+
+#if defined(XP_UNIX)
+typedef EXPORTED_CALLBACK(NPError, NP_InitializeFuncPtr)(NPNetscapeFuncs*, NPPluginFuncs*);
+typedef EXPORTED_CALLBACK(char*, NP_GetMIMEDescriptionFuncPtr)(void);
+#else
+typedef EXPORTED_CALLBACK(NPError, NP_InitializeFuncPtr)(NPNetscapeFuncs*);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npruntime.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/npruntime.h
new file mode 100644 (file)
index 0000000..828a340
--- /dev/null
@@ -0,0 +1,393 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation. 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
+ * Foundation ("Mozilla") nor the names of their contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
+ * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _NP_RUNTIME_H_
+#define _NP_RUNTIME_H_
+
+#include "npapi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+    This API is used to facilitate binding code written in C to script
+    objects.  The API in this header does not assume the presence of a
+    user agent.  That is, it can be used to bind C code to scripting
+    environments outside of the context of a user agent.
+    
+    However, the normal use of the this API is in the context of a
+    scripting environment running in a browser or other user agent.
+    In particular it is used to support the extended Netscape
+    script-ability API for plugins (NP-SAP).  NP-SAP is an extension
+    of the Netscape plugin API.  As such we have adopted the use of
+    the "NP" prefix for this API.
+
+    The following NP{N|P}Variables were added to the Netscape plugin
+    API (in npapi.h):
+
+    NPNVWindowNPObject
+    NPNVPluginElementNPObject
+    NPPVpluginScriptableNPObject
+
+    These variables are exposed through NPN_GetValue() and
+    NPP_GetValue() (respectively) and are used to establish the
+    initial binding between the user agent and native code.  The DOM
+    objects in the user agent can be examined and manipulated using
+    the NPN_ functions that operate on NPObjects described in this
+    header.
+
+    To the extent possible the assumptions about the scripting
+    language used by the scripting environment have been minimized.
+*/
+
+#define NP_BEGIN_MACRO  do {
+#define NP_END_MACRO    } while (0)
+
+/*
+    Objects (non-primitive data) passed between 'C' and script is
+    always wrapped in an NPObject.  The 'interface' of an NPObject is
+    described by an NPClass.
+*/
+typedef struct NPObject NPObject;
+typedef struct NPClass NPClass;
+
+typedef char NPUTF8;
+typedef struct _NPString {
+    const NPUTF8 *UTF8Characters;
+    uint32_t UTF8Length;
+} NPString;
+
+typedef enum {
+    NPVariantType_Void,
+    NPVariantType_Null,
+    NPVariantType_Bool,
+    NPVariantType_Int32,
+    NPVariantType_Double,
+    NPVariantType_String,
+    NPVariantType_Object
+} NPVariantType;
+
+typedef struct _NPVariant {
+    NPVariantType type;
+    union {
+        bool boolValue;
+        int32_t intValue;
+        double doubleValue;
+        NPString stringValue;
+        NPObject *objectValue;
+    } value;
+} NPVariant;
+
+/*
+    NPN_ReleaseVariantValue is called on all 'out' parameters
+    references.  Specifically it is to be called on variants that own
+    their value, as is the case with all non-const NPVariant*
+    arguments after a successful call to any methods (except this one)
+    in this API.
+
+    After calling NPN_ReleaseVariantValue, the type of the variant
+    will be NPVariantType_Void.
+*/
+void NPN_ReleaseVariantValue(NPVariant *variant);
+
+#define NPVARIANT_IS_VOID(_v)    ((_v).type == NPVariantType_Void)
+#define NPVARIANT_IS_NULL(_v)    ((_v).type == NPVariantType_Null)
+#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
+#define NPVARIANT_IS_INT32(_v)   ((_v).type == NPVariantType_Int32)
+#define NPVARIANT_IS_DOUBLE(_v)  ((_v).type == NPVariantType_Double)
+#define NPVARIANT_IS_STRING(_v)  ((_v).type == NPVariantType_String)
+#define NPVARIANT_IS_OBJECT(_v)  ((_v).type == NPVariantType_Object)
+
+#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
+#define NPVARIANT_TO_INT32(_v)   ((_v).value.intValue)
+#define NPVARIANT_TO_DOUBLE(_v)  ((_v).value.doubleValue)
+#define NPVARIANT_TO_STRING(_v)  ((_v).value.stringValue)
+#define NPVARIANT_TO_OBJECT(_v)  ((_v).value.objectValue)
+
+#define VOID_TO_NPVARIANT(_v)                                                 \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Void;                                           \
+    (_v).value.objectValue = NULL;                                            \
+NP_END_MACRO
+
+#define NULL_TO_NPVARIANT(_v)                                                 \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Null;                                           \
+    (_v).value.objectValue = NULL;                                            \
+NP_END_MACRO
+
+#define BOOLEAN_TO_NPVARIANT(_val, _v)                                        \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Bool;                                           \
+    (_v).value.boolValue = !!(_val);                                          \
+NP_END_MACRO
+
+#define INT32_TO_NPVARIANT(_val, _v)                                          \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Int32;                                          \
+    (_v).value.intValue = _val;                                               \
+NP_END_MACRO
+
+#define DOUBLE_TO_NPVARIANT(_val, _v)                                         \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Double;                                         \
+    (_v).value.doubleValue = _val;                                            \
+NP_END_MACRO
+
+#define STRINGZ_TO_NPVARIANT(_val, _v)                                        \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_String;                                         \
+    NPString str = { _val, uint32_t(strlen(_val)) };                          \
+    (_v).value.stringValue = str;                                             \
+NP_END_MACRO
+
+#define STRINGN_TO_NPVARIANT(_val, _len, _v)                                  \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_String;                                         \
+    NPString str = { _val, uint32_t(_len) };                                  \
+    (_v).value.stringValue = str;                                             \
+NP_END_MACRO
+
+#define OBJECT_TO_NPVARIANT(_val, _v)                                         \
+NP_BEGIN_MACRO                                                                \
+    (_v).type = NPVariantType_Object;                                         \
+    (_v).value.objectValue = _val;                                            \
+NP_END_MACRO
+
+
+/*
+  Type mappings (JavaScript types have been used for illustration
+    purposes):
+
+  JavaScript       to             C (NPVariant with type:)
+  undefined                       NPVariantType_Void
+  null                            NPVariantType_Null
+  Boolean                         NPVariantType_Bool
+  Number                          NPVariantType_Double or NPVariantType_Int32
+  String                          NPVariantType_String
+  Object                          NPVariantType_Object
+
+  C (NPVariant with type:)   to   JavaScript
+  NPVariantType_Void              undefined
+  NPVariantType_Null              null
+  NPVariantType_Bool              Boolean
+  NPVariantType_Int32             Number
+  NPVariantType_Double            Number
+  NPVariantType_String            String
+  NPVariantType_Object            Object
+*/
+
+typedef void *NPIdentifier;
+
+/*
+    NPObjects have methods and properties.  Methods and properties are
+    identified with NPIdentifiers.  These identifiers may be reflected
+    in script.  NPIdentifiers can be either strings or integers, IOW,
+    methods and properties can be identified by either strings or
+    integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
+    compared using ==.  In case of any errors, the requested
+    NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled
+    by the browser. Plugins do not need to worry about memory management
+    with regards to NPIdentifiers.
+*/
+NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
+void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
+                              NPIdentifier *identifiers);
+NPIdentifier NPN_GetIntIdentifier(int32_t intid);
+bool NPN_IdentifierIsString(NPIdentifier identifier);
+
+/*
+    The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
+*/
+NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
+
+/*
+    Get the integer represented by identifier. If identifier is not an
+    integer identifier, the behaviour is undefined.
+*/
+int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
+
+/*
+    NPObject behavior is implemented using the following set of
+    callback functions.
+
+    The NPVariant *result argument of these functions (where
+    applicable) should be released using NPN_ReleaseVariantValue().
+*/
+typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
+typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj);
+typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj);
+typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name,
+                                    const NPVariant *args, uint32_t argCount,
+                                    NPVariant *result);
+typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj,
+                                           const NPVariant *args,
+                                           uint32_t argCount,
+                                           NPVariant *result);
+typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
+                                         NPVariant *result);
+typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
+                                         const NPVariant *value);
+typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
+                                            NPIdentifier name);
+typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
+                                         uint32_t *count);
+typedef bool (*NPConstructFunctionPtr)(NPObject *npobj,
+                                       const NPVariant *args,
+                                       uint32_t argCount,
+                                       NPVariant *result);
+
+/*
+    NPObjects returned by create, retain, invoke, and getProperty pass
+    a reference count to the caller.  That is, the callee adds a
+    reference count which passes to the caller.  It is the caller's
+    responsibility to release the returned object.
+
+    NPInvokeFunctionPtr function may return 0 to indicate a void
+    result.
+
+    NPInvalidateFunctionPtr is called by the scripting environment
+    when the native code is shutdown.  Any attempt to message a
+    NPObject instance after the invalidate callback has been
+    called will result in undefined behavior, even if the native code
+    is still retaining those NPObject instances.  (The runtime
+    will typically return immediately, with 0 or NULL, from an attempt
+    to dispatch to a NPObject, but this behavior should not be
+    depended upon.)
+
+    The NPEnumerationFunctionPtr function may pass an array of
+    NPIdentifiers back to the caller. The callee allocs the memory of
+    the array using NPN_MemAlloc(), and it's the caller's responsibility
+    to release it using NPN_MemFree().
+*/
+struct NPClass
+{
+    uint32_t structVersion;
+    NPAllocateFunctionPtr allocate;
+    NPDeallocateFunctionPtr deallocate;
+    NPInvalidateFunctionPtr invalidate;
+    NPHasMethodFunctionPtr hasMethod;
+    NPInvokeFunctionPtr invoke;
+    NPInvokeDefaultFunctionPtr invokeDefault;
+    NPHasPropertyFunctionPtr hasProperty;
+    NPGetPropertyFunctionPtr getProperty;
+    NPSetPropertyFunctionPtr setProperty;
+    NPRemovePropertyFunctionPtr removeProperty;
+    NPEnumerationFunctionPtr enumerate;
+    NPConstructFunctionPtr construct;
+};
+
+#define NP_CLASS_STRUCT_VERSION      3
+
+#define NP_CLASS_STRUCT_VERSION_ENUM 2
+#define NP_CLASS_STRUCT_VERSION_CTOR 3
+
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass)   \
+        ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+
+#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass)   \
+        ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
+
+struct NPObject {
+    NPClass *_class;
+    uint32_t referenceCount;
+    /*
+     * Additional space may be allocated here by types of NPObjects
+     */
+};
+
+/*
+    If the class has an allocate function, NPN_CreateObject invokes
+    that function, otherwise a NPObject is allocated and
+    returned. This method will initialize the referenceCount member of
+    the NPObject to 1.
+*/
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
+
+/*
+    Increment the NPObject's reference count.
+*/
+NPObject *NPN_RetainObject(NPObject *npobj);
+
+/*
+    Decremented the NPObject's reference count.  If the reference
+    count goes to zero, the class's destroy function is invoke if
+    specified, otherwise the object is freed directly.
+*/
+void NPN_ReleaseObject(NPObject *npobj);
+
+/*
+    Functions to access script objects represented by NPObject.
+
+    Calls to script objects are synchronous.  If a function returns a
+    value, it will be supplied via the result NPVariant
+    argument. Successful calls will return true, false will be
+    returned in case of an error.
+    
+    Calls made from plugin code to script must be made from the thread
+    on which the plugin was initialized.
+*/
+
+bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName,
+                const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args,
+                       uint32_t argCount, NPVariant *result);
+bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script,
+                  NPVariant *result);
+bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
+                     NPVariant *result);
+bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
+                     const NPVariant *value);
+bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
+                   uint32_t *count);
+bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
+                   uint32_t argCount, NPVariant *result);
+
+/*
+    NPN_SetException may be called to trigger a script exception upon
+    return from entry points into NPObjects.  Typical usage:
+
+    NPN_SetException (npobj, message);
+*/
+void NPN_SetException(NPObject *npobj, const NPUTF8 *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/nptypes.h b/applications/hbbtvplayer/hbbtvbrowserplugin/src/webkit-plugin-header/nptypes.h
new file mode 100644 (file)
index 0000000..4ebeb97
--- /dev/null
@@ -0,0 +1,122 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Johnny Stenback <jst@mozilla.org> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nptypes_h_
+#define nptypes_h_
+
+/*
+ * Header file for ensuring that C99 types ([u]int32_t, [u]int64_t and bool) and
+ * true/false macros are available.
+ */
+
+#if defined(WIN32) || defined(OS2)
+  /*
+   * Win32 and OS/2 don't know C99, so define [u]int_16/32/64 here. The bool
+   * is predefined tho, both in C and C++.
+   */
+  typedef short int16_t;
+  typedef unsigned short uint16_t;
+  typedef int int32_t;
+  typedef unsigned int uint32_t;
+  typedef long long int64_t;
+  typedef unsigned long long uint64_t;
+
+#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
+  /*
+   * AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
+   * but not bool for C.
+   */
+  #include <inttypes.h>
+
+  #ifndef __cplusplus
+    typedef int bool;
+    #define true   1
+    #define false  0
+  #endif
+#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
+  /*
+   * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and 
+   * u_int32_t.
+   */
+  #include <sys/types.h>
+
+  /*
+   * BSD/OS ships no header that defines uint32_t, nor bool (for C)
+   */
+  #if defined(bsdi)
+  typedef u_int32_t uint32_t;
+  typedef u_int64_t uint64_t;
+
+  #if !defined(__cplusplus)
+    typedef int bool;
+    #define true   1
+    #define false  0
+  #endif
+  #else
+  /*
+   * FreeBSD and OpenBSD define uint32_t and bool.
+   */
+    #include <inttypes.h>
+    #include <stdbool.h>
+  #endif
+#elif defined(BEOS)
+  #include <inttypes.h>
+#else
+  /*
+   * For those that ship a standard C99 stdint.h header file, include
+   * it. Can't do the same for stdbool.h tho, since some systems ship
+   * with a stdbool.h file that doesn't compile!
+   */
+  #include <stdint.h>
+
+  #ifndef __cplusplus
+    #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
+      #include <stdbool.h>
+    #else
+      /*
+       * GCC 2.91 can't deal with a typedef for bool, but a #define
+       * works.
+       */
+      #define bool int
+      #define true   1
+      #define false  0
+    #endif
+  #endif
+#endif
+
+#endif /* nptypes_h_ */
diff --git a/applications/hbbtvplayer/hbbtvterminal/autogen.sh b/applications/hbbtvplayer/hbbtvterminal/autogen.sh
new file mode 100644 (file)
index 0000000..cad4e11
--- /dev/null
@@ -0,0 +1,6 @@
+
+#! /bin/sh
+
+autoreconf --install -v
+
+./configure
diff --git a/applications/hbbtvplayer/hbbtvterminal/configure.ac b/applications/hbbtvplayer/hbbtvterminal/configure.ac
new file mode 100644 (file)
index 0000000..866a299
--- /dev/null
@@ -0,0 +1,40 @@
+###########################################################################################
+##
+## Copyright 2011 Telecom Paristech
+## Author : Stanislas Selle
+##
+###########################################################################################
+
+###  Configure.ac for hbbtvterminal
+
+
+AC_INIT([hbbtvterminal], [0.1.0], [stanislas.selle@telecom-paristech.fr])
+
+AC_CONFIG_AUX_DIR([build-aux])
+
+AC_CONFIG_MACRO_DIR([m4])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AM_INIT_AUTOMAKE([foreign -Wall -Werror])
+
+#check programs
+AC_PROG_CXX
+
+#check modules
+PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28.0])
+PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.20.1])
+PKG_CHECK_MODULES([WEBKIT], [webkit-1.0 >= 1.5.2])
+PKG_CHECK_MODULES([PIXMAN], [pixman-1 >= 0.16.4])
+PKG_CHECK_MODULES([HBBTVBROWSERPLUGIN], [hbbtvbrowserplugin >= 0.0.3])
+
+# Checks for header files.
+AC_PATH_X
+
+# check header
+AC_HEADER_STDBOOL
+
+# makefiles
+AC_CONFIG_FILES([makefile src/makefile])
+
+
+AC_OUTPUT
diff --git a/applications/hbbtvplayer/hbbtvterminal/hbbtv_terminal.vcproj b/applications/hbbtvplayer/hbbtvterminal/hbbtv_terminal.vcproj
new file mode 100644 (file)
index 0000000..987a985
--- /dev/null
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9,00"\r
+       Name="hbbtv_terminal"\r
+       ProjectGUID="{247BE3AF-EC92-4892-A7AC-0C51E42A5A44}"\r
+       RootNamespace="hbbtv_terminal"\r
+       Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..\..\..\include;&quot;./Win32Build\WebKitGTK-Bundle\include\&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\glib-2.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\atk-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\cairo&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gail-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gdk-pixbuf-2.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gtk-2.0&quot;;&quot;./Win32Build\\WebKitGTK-Bundle\include\libpng14&quot;;&quot;./Win32Build\\WebKitGTK-Bundle\include\pango-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\webkit-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\libsoup-2.4&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\glib-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gdk-pixbuf-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gtk-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\pango\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gettext\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gio\include&quot;;../hbbtvbrowserplugin\src;$(NOINHERIT)"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;G_HAVE_ISO_VARARGS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                               CompileAs="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="libasprintf-0.lib libatk-1.0-0.lib libcairo-2.lib libenchant.lib libexpat-1.lib libexslt-0.lib libfontconfig-1.lib libfreetype-6.lib libgailutil-18.lib libgdk-win32-2.0-0.lib libgdk_pixbuf-2.0-0.lib libgettextlib-0-17.lib libgettextpo-0.lib libgettextsrc-0-17.lib libgio-2.0-0.lib libglib-2.0-0.lib libgmodule-2.0-0.lib libgobject-2.0-0.lib libgthread-2.0-0.lib libgtk-win32-2.0-0.lib libintl-8.lib libjpeg-7.lib libpango-1.0-0.lib libpangocairo-1.0-0.lib libpangoft2-1.0-0.lib libpangowin32-1.0-0.lib libpixman-1-0.lib libpng14-14.lib libsoup-2.4-1.lib libwebkitgtk-1.0-0.lib libxslt-1.lib zlib1.lib"\r
+                               OutputFile="../../../bin/win32/debug/$(ProjectName).exe"\r
+                               LinkIncremental="2"\r
+                               AdditionalLibraryDirectories="../../gpac_public/bin/win32/debug;&quot;./Win32Build\WebKitGTK-Bundle\lib&quot;"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="..\..\..\include;&quot;./Win32Build\WebKitGTK-Bundle\include\&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\glib-2.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\atk-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\cairo&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gail-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gdk-pixbuf-2.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\gtk-2.0&quot;;&quot;./Win32Build\\WebKitGTK-Bundle\include\libpng14&quot;;&quot;./Win32Build\\WebKitGTK-Bundle\include\pango-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\webkit-1.0&quot;;&quot;./Win32Build\WebKitGTK-Bundle\include\libsoup-2.4&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\glib-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gdk-pixbuf-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gtk-2.0\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\pango\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gettext\include&quot;;&quot;./Win32Build\WebKitGTK-Bundle\lib\gio\include&quot;;../hbbtvbrowserplugin\src;$(NOINHERIT)"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;G_HAVE_ISO_VARARGS"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="libasprintf-0.lib libatk-1.0-0.lib libcairo-2.lib libenchant.lib libexpat-1.lib libexslt-0.lib libfontconfig-1.lib libfreetype-6.lib libgailutil-18.lib libgdk-win32-2.0-0.lib libgdk_pixbuf-2.0-0.lib libgettextlib-0-17.lib libgettextpo-0.lib libgettextsrc-0-17.lib libgio-2.0-0.lib libglib-2.0-0.lib libgmodule-2.0-0.lib libgobject-2.0-0.lib libgthread-2.0-0.lib libgtk-win32-2.0-0.lib libintl-8.lib libjpeg-7.lib libpango-1.0-0.lib libpangocairo-1.0-0.lib libpangoft2-1.0-0.lib libpangowin32-1.0-0.lib libpixman-1-0.lib libpng14-14.lib libsoup-2.4-1.lib libwebkitgtk-1.0-0.lib libxslt-1.lib zlib1.lib"\r
+                               OutputFile="../../../bin/win32/release/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               AdditionalLibraryDirectories="../../gpac_public/bin/win32/debug;&quot;./Win32Build\WebKitGTK-Bundle\lib&quot;"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Fichiers sources"\r
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\src\hbbtv_channel.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtv_demux.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtv_keycontrol.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtv_tools.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\src\hbbtvterminal.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Fichiers d&apos;en-tête"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\src\hbbtvterminal.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/makefile.am b/applications/hbbtvplayer/hbbtvterminal/makefile.am
new file mode 100644 (file)
index 0000000..e21b6f2
--- /dev/null
@@ -0,0 +1,17 @@
+
+SUBDIRS = src
+
+#TESTTS = /home/selle/ressources/mpeg2-ts-hbbtv/TPT/OpenHbb-ch4.ts
+TESTTS = /home/selle/ressources/OpenHbbDemo-3ch2app/OpenHbbDemo-3ch2app.ts
+
+
+TESTURL1 = http://cairhblog.free.fr/menu.html
+TESTURL2 = http://aquila.enst.fr:8080/subwebsite/hbbtvtest/oha0005web/index.php
+TESTLOG = /tmp/test-err.txt
+
+test : all
+       ./src/hbbtvterminal -input=$(TESTTS) 
+test1 : all
+       ./src/hbbtvterminal -input=$(TESTTS) -url=$(TESTURL1)
+test2 : all
+       ./src/hbbtvterminal -input=$(TESTTS) -url=$(TESTURL2)
diff --git a/applications/hbbtvplayer/hbbtvterminal/makefile.old b/applications/hbbtvplayer/hbbtvterminal/makefile.old
new file mode 100644 (file)
index 0000000..b56fe1b
--- /dev/null
@@ -0,0 +1,81 @@
+##
+## Copyright : Telecom Paristech - 2011
+##
+## Author : Stanislas Selle 
+##
+
+###############################################################################
+## Programs
+
+COMPILER       = g++
+DELETER                = rm -f
+
+
+CFLAGS = -g
+
+CFLAGS += -DXP_UNIX
+CFLAGS += -fPIC
+
+###############################################################################
+## Options, Flags and LinkS
+
+INCLUDEFLAGS = -I/usr/include/xulrunner-lastest/                                               \
+                               -I../../gpac_public/include/                                            \
+                               -I../hbbtvbrowserplugin/src/                            \
+                               -I../../gpac_public/
+
+LIBRARYPATHS =         -L/usr/lib/xulrunner-devel-lastest/sdk/lib/                     \
+                               -L../../gpac_public/bin/gcc/                                            \
+                               -L../hbbtvbrowserplugin/bin/
+
+LIBRARYNAMES = -lgpac                                                                                                  \
+                               -lmozjs                                                                                                 \
+                               -lxpcom                                                                                                 \
+                               -lxul                                                                                                   \
+                               ../hbbtvbrowserplugin/bin/hbbtvbrowserplugin.so
+
+
+LIBRARYFLAGS = $(LIBRARYPATHS) $(LIBRARYNAMES)
+
+FROMPKG = webkit-1.0 gtk+-2.0 pixman-1
+
+ifneq ($(strip $(FROMPKG)),)
+PKGFLAGS = `pkg-config --cflags $(FROMPKG) `
+PKGLIBS = `pkg-config --libs $(FROMPKG) `
+INCLUDEFLAGS += $(PKGFLAGS)
+LIBRARYFLAGS += $(PKGLIBS)
+endif
+
+
+###############################################################################
+## Files
+
+
+MAINTARGET = bin/hbbtvterminal
+
+OBJ =  obj/hbbtvterminal.o \
+               obj/hbbtv_demux.o \
+               obj/hbbtv_channel.o
+
+#TESTTS = /home/selle/ressources/OpenHbbDemo-3ch2app/OpenHbbDemo-3ch2app.ts
+TESTTS = /home/selle/ressources/mpeg2-ts-hbbtv/TPT/OpenHbb-ch4.ts
+TESTURL = http://aquila.enst.fr:8080/subwebsite/hbbtvtest/oha0005web/index.php
+TESTLOG = /tmp/test-err.txt
+
+###############################################################################
+## Rules
+
+
+all : $(MAINTARGET)
+
+$(MAINTARGET) : $(OBJ)
+       $(COMPILER) $(CFLAGS) $(LIBRARYFLAGS) $(OBJ) -o $(MAINTARGET)
+
+obj/%.o : src/%.cpp
+       $(COMPILER) $(CFLAGS) $(INCLUDEFLAGS) -c $^ -o $@
+
+test : all
+       $(MAINTARGET) -input=$(TESTTS)
+
+clean :
+       rm -f $(OBJ) $(MAINTARGET)
diff --git a/applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.cbp b/applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.cbp
new file mode 100644 (file)
index 0000000..8f32993
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="HbbtvTerminal" />
+               <Option pch_mode="2" />
+               <Option compiler="gcc" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin/Debug/HbbtvTerminal" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj/Debug/" />
+                               <Option type="1" />
+                               <Option compiler="gcc" />
+                               <Compiler>
+                                       <Add option="-g" />
+                               </Compiler>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+               </Compiler>
+               <Unit filename="../../../autogen.sh" />
+               <Unit filename="../../../configure.ac" />
+               <Unit filename="../../../makefile.am" />
+               <Unit filename="../../../src/hbbtv_channel.cpp" />
+               <Unit filename="../../../src/hbbtv_demux.cpp" />
+               <Unit filename="../../../src/hbbtvterminal.cpp" />
+               <Unit filename="../../../src/hbbtvterminal.h" />
+               <Unit filename="../../../src/makefile.am" />
+               <Extensions>
+                       <code_completion />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
diff --git a/applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.layout b/applications/hbbtvplayer/hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.layout
new file mode 100644 (file)
index 0000000..c091bfa
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+       <ActiveTarget name="Debug" />
+       <File name="../../../autogen.sh" open="1" top="0" tabpos="3">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../configure.ac" open="1" top="0" tabpos="2">
+               <Cursor position="781" topLine="0" />
+       </File>
+       <File name="../../../makefile.am" open="1" top="0" tabpos="7">
+               <Cursor position="40" topLine="0" />
+       </File>
+       <File name="../../../src/hbbtv_channel.cpp" open="1" top="0" tabpos="5">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/hbbtv_demux.cpp" open="0" top="0" tabpos="7">
+               <Cursor position="0" topLine="0" />
+       </File>
+       <File name="../../../src/hbbtvterminal.cpp" open="1" top="0" tabpos="4">
+               <Cursor position="44068" topLine="1111" />
+       </File>
+       <File name="../../../src/hbbtvterminal.h" open="1" top="0" tabpos="1">
+               <Cursor position="354" topLine="0" />
+       </File>
+       <File name="../../../src/makefile.am" open="1" top="0" tabpos="6">
+               <Cursor position="388" topLine="0" />
+       </File>
+</CodeBlocks_layout_file>
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_channel.cpp b/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_channel.cpp
new file mode 100644 (file)
index 0000000..37e4427
--- /dev/null
@@ -0,0 +1,253 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors:  Jonathan Sillan               \r
+ *                             \r
+ */\r
+\r
+#include "hbbtvterminal.h"\r
+\r
+static Bool app_priority_test(GF_M2TS_AIT_APPLICATION*,u8 app_priority,u8 app_transport, u8 MaxPriority);\r
+\r
+/* Constructor */\r
+Channel::Channel(u32 TSservice_ID, char* TSchannel_name){  \r
+       \r
+       u8 i;\r
+       service_ID = TSservice_ID;\r
+       if(TSchannel_name){\r
+         channel_name = gf_strdup(channel_name);\r
+       }else{\r
+         channel_name = NULL;\r
+       }\r
+       \r
+       video_ID = 0;\r
+       for(i=0 ; i<MAX_audio_index ; i++){\r
+         audio_ID[i] = 0;  \r
+       }\r
+       ChannelApp = NULL;\r
+       AIT_PID = 0;\r
+       PMT_PID = 0;\r
+       processed = 0;\r
+       current_audio_index = 0;\r
+       nb_chan_audio_stream =0;\r
+}\r
+\r
+/* Destructor */\r
+void Channel::Destroy_Channel(){  \r
+       \r
+       service_ID = 0;\r
+       if(channel_name){\r
+         gf_free(channel_name);\r
+       }\r
+       gf_free(this);\r
+       \r
+}\r
+/* Getter */\r
+u32 Channel::Get_service_id(){  \r
+       return service_ID; \r
+}\r
+\r
+char* Channel::Get_channel_name(){\r
+       return channel_name;\r
+}\r
+\r
+u32 Channel::Get_video_ID(){\r
+       return video_ID; \r
+}\r
+\r
+u32 Channel::Get_audio_ID(u32 indice){\r
+       if(audio_ID[indice] == 0 || indice >= nb_chan_audio_stream){\r
+               indice = 0;\r
+       }\r
+       current_audio_index = indice;\r
+       return audio_ID[indice];\r
+}\r
+\r
+u32 Channel::Get_ait_pid(){\r
+       return AIT_PID;\r
+}\r
+\r
+u32 Channel::Get_pmt_pid(){\r
+       return PMT_PID;\r
+}\r
+\r
+Bool Channel::Get_processed(){\r
+       return processed;\r
+}\r
+\r
+u32 Channel::Get_audio_index(){\r
+       return current_audio_index;\r
+}\r
+\r
+u32 Channel::Get_nb_chan_audio_stream(){\r
+       return nb_chan_audio_stream;\r
+}\r
+\r
+GF_M2TS_CHANNEL_APPLICATION_INFO*Channel::Get_App_info(){\r
+       return ChannelApp;\r
+}\r
+\r
+GF_M2TS_AIT_APPLICATION* Channel::App_to_play(Bool isConnected,u8 MaxPriority){\r
+       u32 i;\r
+       Bool App_selected;\r
+       u32 app_index;\r
+       u8 app_priority;\r
+       u8 app_transport;\r
+       \r
+       App_selected = 0;\r
+       app_priority = 0;\r
+       app_index = 0;\r
+       app_transport = 0;\r
+               \r
+       for(i = 0 ; i<ChannelApp->nb_application; i++){ \r
+               GF_M2TS_AIT_APPLICATION* App_info = (GF_M2TS_AIT_APPLICATION*)gf_list_get(ChannelApp->Application,i);\r
+               if((isConnected && App_info->broadband) || App_info->broadcast){\r
+                       if(App_info->application_control_code == AUTOSTART){\r
+                               if(app_priority_test(App_info,app_priority,isConnected,MaxPriority)){\r
+                                       app_priority = App_info->priority;\r
+                                       app_index = i;\r
+                                       App_selected = 1;\r
+                                       if(!app_transport && App_info->broadband && isConnected){\r
+                                               app_transport = BROADBAND;\r
+                                       }else{\r
+                                               app_transport = BROADCAST;\r
+                                       }\r
+                                       \r
+                               }                               \r
+                       }\r
+               }               \r
+       }\r
+       if(App_selected){\r
+               GF_M2TS_AIT_APPLICATION* App_info = (GF_M2TS_AIT_APPLICATION*)gf_list_get(ChannelApp->Application,app_index);\r
+               return App_info;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+GF_M2TS_AIT_APPLICATION* Channel::Get_App(u32 application_id){\r
+       u32 i;\r
+               \r
+       for(i = 0 ; i<ChannelApp->nb_application; i++){ \r
+               GF_M2TS_AIT_APPLICATION* App_info = (GF_M2TS_AIT_APPLICATION*)gf_list_get(ChannelApp->Application,i);\r
+               if(App_info->application_id == application_id){\r
+                       return App_info;\r
+               }               \r
+       }\r
+       return NULL;\r
+}\r
+\r
+\r
+\r
+/* Class Fonction */\r
+\r
+u32 Channel::Add_service_id(u32 service_id){\r
+  if(service_id){\r
+       service_ID = service_id;\r
+       return GF_OK;\r
+  }\r
+  return GF_BAD_PARAM;\r
+}\r
+\r
+u32 Channel::Add_channel_name(char* chan_name){\r
+    if(chan_name != NULL){\r
+       channel_name = gf_strdup(chan_name);\r
+       return GF_OK;\r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+u32 Channel::Add_video_ID(u32 video_index){\r
+    if(video_index){\r
+       video_ID = video_index;\r
+       return GF_OK;\r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+\r
+u32 Channel::Add_audio_ID(u32 audio_index){\r
+       if(audio_index){\r
+       u32 i;\r
+       for(i = 0; i<MAX_audio_index;i++){\r
+         if(audio_ID[i]==0){\r
+                nb_chan_audio_stream++;\r
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("Add audio ID[%d] %d to channel %d -- total of %d audio stream on this channel\n",i,audio_index,service_ID,nb_chan_audio_stream));                 \r
+           audio_ID[i] = audio_index;\r
+           return GF_OK;\r
+         }\r
+       }       \r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+\r
+u32 Channel::Add_ait_pid(u32 ait_pid){\r
+    if(ait_pid){       \r
+       AIT_PID = ait_pid;\r
+       return GF_OK;\r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+\r
+u32 Channel::Add_pmt_pid(u32 pmt_pid){\r
+    if(pmt_pid){       \r
+       PMT_PID = pmt_pid;\r
+       return GF_OK;\r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+\r
+u32 Channel::Add_App_info(GF_M2TS_CHANNEL_APPLICATION_INFO*chan_app){\r
+    if(chan_app){      \r
+               ChannelApp = chan_app;\r
+               return GF_OK;\r
+    }\r
+    return GF_BAD_PARAM;\r
+}\r
+\r
+\r
+void Channel::Check_Info_Done(){\r
+       processed = 1;\r
+}\r
+\r
+void Channel::Set_audio_index(u32 index){\r
+       current_audio_index = index;\r
+}\r
+\r
+/* Incr_audio_index\r
+ * \r
+ * int mode : 1 ou 0\r
+ * \r
+ * Increment ou decrement the audio stream index\r
+ */\r
+void Channel::Incr_audio_index(int mode){\r
+       if(mode){\r
+               current_audio_index--;\r
+       }else{\r
+               current_audio_index++;\r
+       }\r
+}\r
+       \r
+/* Global Functions */\r
+\r
+static Bool app_priority_test(GF_M2TS_AIT_APPLICATION* App_info,u8 app_priority,u8 isConnected,u8 MaxPriority){\r
+\r
+       if(!(App_info->priority >= MaxPriority && (MaxPriority >0)) && \r
+       ((app_priority < App_info->priority) || (app_priority == App_info->priority))\r
+       && ((isConnected && App_info->broadband)||App_info->broadcast)){\r
+               return 1;\r
+       }\r
+       \r
+       return 0;\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_demux.cpp b/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_demux.cpp
new file mode 100644 (file)
index 0000000..9bdaebf
--- /dev/null
@@ -0,0 +1,388 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors:     Jonathan Sillan            \r
+ *                             \r
+ */\r
+\r
+#include "hbbtvterminal.h"\r
+\r
+static u32 New_ait_received(HbbtvDemuxer* hbbtv_demuxer,GF_M2TS_AIT *ait, char  *data, u32 data_size, u32 table_id);\r
+static u32 On_hbbtv_ait_section(sPlayerInterface* player_interf, GF_Event *event);\r
+static u32 On_hbbtv_dsmcc_section(sPlayerInterface* player_interf, GF_Event *event);\r
+static u32 On_hbbtv_get_tsdemuxer(sPlayerInterface* player_interf, GF_Event *event);\r
+\r
+\r
+\r
+/* Constructor */\r
+HbbtvDemuxer::HbbtvDemuxer(char *input_data, char* url, Bool dsmcc, Bool no_url,sPlayerInterface* player_interf)\r
+{\r
+\r
+       Demuxts = NULL;\r
+\r
+       Channels = gf_list_new();\r
+       Input_data = gf_strdup(input_data);     \r
+       user = player_interf;\r
+       player_interf->Demuxer = this;\r
+       ait_to_process = 0;\r
+       nb_prog_pmt_received = 0;\r
+       all_prog_pmt_received =0;\r
+       No_URL = 0;\r
+       Ignore_TS_URL = 0;      \r
+       if(dsmcc){\r
+               process_dsmcc = 1;\r
+       }else{\r
+               process_dsmcc = 0;\r
+       }\r
+\r
+       if(no_url){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] No URL \n"));\r
+               No_URL = 1;\r
+       }else if(url){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Forced URL %s \n",url));\r
+               Force_URL = gf_strdup(url);\r
+               Ignore_TS_URL = 1;\r
+       }\r
+       nb_ait = 0;\r
+       ts_demux_mutex = gf_mx_new("HBBTV_TS_Demux_Mutex");\r
+\r
+       ts_demux_thread = gf_th_new("HBBTV_TS_Demux_Thread");\r
+       \r
+}\r
+\r
+/* Destructor */\r
+\r
+/* Getter */\r
+\r
+GF_M2TS_Demuxer* HbbtvDemuxer::Get_Ts()\r
+{\r
+       return Demuxts;\r
+}\r
+\r
+GF_List* HbbtvDemuxer::Get_AIT_To_Process_list()\r
+{\r
+       return Ait_To_Process;\r
+}\r
+\r
+char* HbbtvDemuxer::Get_Input_data()\r
+{\r
+       return Input_data;\r
+}\r
+\r
+Bool HbbtvDemuxer::Get_if_dsmcc_process()\r
+{\r
+       return process_dsmcc;\r
+}\r
+\r
+GF_Thread * HbbtvDemuxer::Get_Demux_Thread()\r
+{\r
+       return ts_demux_thread;\r
+}\r
+\r
+GF_Mutex * HbbtvDemuxer::Get_Demux_Mutex()\r
+{\r
+       return ts_demux_mutex;\r
+}\r
+\r
+GF_List * HbbtvDemuxer::Get_ChannelList(){\r
+       return Channels;\r
+}\r
+\r
+\r
+Channel* HbbtvDemuxer::Get_Channel(u32 service_id){\r
+       u32 nb_channel,i;\r
+\r
+       nb_channel = gf_list_count(Channels);\r
+\r
+       for(i=0;i<nb_channel;i++){\r
+               Channel* Chan = (Channel*)gf_list_get(Channels,i);\r
+               if(Chan->Get_service_id() == service_id){\r
+                       return Chan;\r
+               }\r
+       }\r
+       return NULL;\r
+}\r
+\r
+void* HbbtvDemuxer::Get_User(){\r
+\r
+       return user;    \r
+}\r
+\r
+\r
+char* HbbtvDemuxer::Get_Force_URL(){\r
+       return Force_URL;\r
+}\r
+\r
+Bool HbbtvDemuxer::Get_Ignore_TS_URL(){\r
+       return Ignore_TS_URL;\r
+}\r
+\r
+Bool HbbtvDemuxer::Get_ait_to_proces(){\r
+       return ait_to_process;\r
+}\r
+\r
+\r
+/* Setter */\r
+void HbbtvDemuxer::Set_Ts(GF_M2TS_Demuxer *on_ts){     \r
+       Demuxts = on_ts;\r
+}\r
+\r
+void HbbtvDemuxer::Set_ait_to_process(Bool on){\r
+       ait_to_process = on;\r
+}\r
+\r
+/* Class Fonction */\r
+GF_Err HbbtvDemuxer::Get_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO*ChannelApp)\r
+{\r
+       if(!Ignore_TS_URL && !No_URL){  \r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Get application for service %d \n",ChannelApp->service_id));\r
+               return get_app_url((sPlayerInterface*)user,ChannelApp); \r
+      }else{\r
+      \r
+       if(!No_URL){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Forced URL %s \n",Force_URL));\r
+       }else{\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] URL blocked by the user. No Application to play  \n"));;\r
+       }\r
+       return GF_OK;\r
+       \r
+      }\r
+}\r
+\r
+Channel* HbbtvDemuxer::Zap_channel(u32 service_id,int zap){\r
+         u32 count_list;\r
+         u32 i ;\r
+         \r
+         count_list = gf_list_count(Channels);\r
+//        GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] list: %d\n",count_list));\r
+         for(i=0;i<count_list;i++){\r
+             Channel* chan = ( Channel*)gf_list_get(Channels,i);\r
+             if(chan->Get_service_id() == service_id){\r
+               if(zap != 0){\r
+                 /* zap is use for changing channel. It could be +1 or -1 in order to take the next/previous service */\r
+                 GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] i: %d zap %d\n",i,zap));\r
+                                   \r
+                  i= (i+zap+count_list)%count_list; /* loop on the channels */\r
+                 \r
+                 GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] i: %d list %d\n",i,count_list));\r
+               }\r
+               Channel* chan = ( Channel*)gf_list_get(Channels,i);             \r
+               return chan;\r
+             }\r
+         }\r
+         \r
+         /* If the prog goes here that means Channels list is empty or \r
+         no object from this current service_id has already been processed */\r
+//       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] add service_id: %d \n",service_id));\r
+         Channel* chan = new Channel(service_id,NULL);\r
+         gf_list_add(Channels,chan);\r
+         return chan;\r
+}\r
+\r
+void HbbtvDemuxer::Channel_check(){\r
+         u32 count_list;\r
+         u32 i ;\r
+         \r
+         count_list = gf_list_count(Channels);\r
+         for(i=0;i<count_list;i++){\r
+             Channel* chan = ( Channel*)gf_list_get(Channels,i);\r
+             chan->Check_Info_Done();\r
+         }\r
+  }\r
+             \r
+\r
+int HbbtvDemuxer::Check_all_channel_info_received(int Timer){\r
+       \r
+       if(!Demuxts){\r
+           GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTV]No PAT received \n"));\r
+           return 0;\r
+       }       \r
+       /* Check if all the PMT have been processed or wait until 5 secondes to starts the program */\r
+       if(all_prog_pmt_received || Timer == 5){          \r
+           GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] nb_prog_pmt_received %d\n",nb_prog_pmt_received));       \r
+           return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+void HbbtvDemuxer::Create_Channel(GF_M2TS_Program *prog){  \r
+\r
+       Channel* chan = new Channel(prog->number,NULL);\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal]Service number:%d\n",prog->number));\r
+       chan->Add_pmt_pid(prog->pmt_pid);\r
+       gf_list_add(Channels,chan);\r
+       \r
+}\r
+\r
+void HbbtvDemuxer::Check_PMT_Processing(){     \r
+       nb_prog_pmt_received++; \r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("Demuxts->programs %d\n",gf_list_count(Demuxts->programs)));       \r
+       if(nb_prog_pmt_received == gf_list_count(Demuxts->programs)){\r
+               all_prog_pmt_received = 1;\r
+       }       \r
+}\r
+\r
+\r
+/* Global Functions */\r
+\r
+u32 DemuxThreadStart(HbbtvDemuxer *hbbtv_demuxer){\r
+\r
+       return gf_th_run(hbbtv_demuxer->Get_Demux_Thread(),DemuxStart,(void*)hbbtv_demuxer);\r
+}\r
+\r
+u32 On_hbbtv_received_section(void *ptr, GF_Event *event){\r
+       u32 e;\r
+       \r
+       e = GF_OK;\r
+       HbbtvDemuxer* hbbtv_demuxer = (HbbtvDemuxer*)ptr;\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)hbbtv_demuxer->Get_User(); \r
+       \r
+\r
+       if (event->type == GF_EVENT_FORWARDED)\r
+       {\r
+               if(event->forwarded_event.service_event_type == GF_M2TS_EVT_PAT_FOUND && hbbtv_demuxer->Get_Ts() == NULL){\r
+                       e = On_hbbtv_get_tsdemuxer(player_interf,event);                        \r
+                       if(e != 0){\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Error in receiving the TS Demuxer \n"));\r
+\r
+                       }\r
+               }\r
+               if(event->forwarded_event.service_event_type == GF_M2TS_EVT_AIT_FOUND){\r
+                       e = On_hbbtv_ait_section(player_interf,event);\r
+               }\r
+               if(event->forwarded_event.service_event_type == GF_M2TS_EVT_DSMCC_FOUND){\r
+                       e = On_hbbtv_dsmcc_section(player_interf,event);\r
+               }\r
+               if(event->forwarded_event.service_event_type == GF_M2TS_EVT_PMT_FOUND){ \r
+                       gf_mx_p(hbbtv_demuxer->Get_Demux_Mutex());\r
+                       GF_M2TS_Program * prog = (GF_M2TS_Program*)event->forwarded_event.param;                        \r
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("PMT PID %d \n",prog->pmt_pid));\r
+                       hbbtv_demuxer->Create_Channel(prog);    \r
+                       hbbtv_demuxer->Check_PMT_Processing();\r
+                       gf_mx_v(hbbtv_demuxer->Get_Demux_Mutex());\r
+               }               \r
+       }       \r
+       return e;\r
+\r
+  \r
+}\r
\r
+static u32 On_hbbtv_ait_section(sPlayerInterface* player_interf, GF_Event *event) \r
+{\r
+       HbbtvDemuxer* hbbtv_demuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+       GF_M2TS_AIT_CARRY* ait_carry;\r
+       \r
+       \r
+       ait_carry = (GF_M2TS_AIT_CARRY*)event->forwarded_event.param;   \r
+       \r
+       /* Make sure we are not modifying the AIT List at the same time */\r
+       gf_mx_p(hbbtv_demuxer->Get_Demux_Mutex());\r
+       if(player_interf->init){                \r
+               Get_application_for_channel(hbbtv_demuxer,ait_carry->service_id);                       \r
+       }\r
+               \r
+       /* Unlock the mutex */\r
+       gf_mx_v(hbbtv_demuxer->Get_Demux_Mutex());\r
+\r
+       return 0;\r
+}\r
+\r
+u32 Get_application_for_channel(HbbtvDemuxer* hbbtv_demuxer,u32 service_id){\r
+       u32 nb_channel;\r
+       Channel* Chan;\r
+       GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo;\r
+       GF_Err e;\r
+\r
+       Chan = hbbtv_demuxer->Get_Channel(service_id);\r
+       if(!Chan){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] service ID %d is not available\n",service_id));\r
+               return GF_BAD_PARAM;\r
+       }       \r
+\r
+       ChanAppInfo = gf_m2ts_get_channel_application_info(hbbtv_demuxer->Get_Ts()->ChannelAppList,service_id); \r
+       \r
+       if(!ChanAppInfo){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] service ID %d no application available\n",service_id));\r
+               return GF_BAD_PARAM;\r
+       }       \r
+       \r
+       Chan->Add_App_info(ChanAppInfo);        \r
+       e = hbbtv_demuxer->Get_application_info(ChanAppInfo);\r
+       if(e == GF_OK){\r
+         GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Application found for the service ID %d is ON\n",ChanAppInfo->service_id));\r
+       }else{\r
+         GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] This application for this service ID %d does not belong to the current one.\n\n",ChanAppInfo->service_id));\r
+       }\r
+       \r
+       return GF_OK;\r
+       \r
+} \r
+\r
+static u32 On_hbbtv_dsmcc_section(sPlayerInterface* player_interf, GF_Event *event) \r
+{\r
+       HbbtvDemuxer* hbbtv_demuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+       GF_M2TS_Demuxer* ts = hbbtv_demuxer->Get_Ts();          \r
+       GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord;\r
+\r
+       GF_M2TS_SL_PCK* pck = (GF_M2TS_SL_PCK*)event->forwarded_event.param;\r
+       \r
+       dsmcc_overlord = gf_m2ts_get_dmscc_overlord(ts->dsmcc_controler,pck->stream->service_id);\r
+\r
+       if (dsmcc_overlord && dsmcc_overlord->get_index){\r
+                       GF_M2TS_AIT_APPLICATION* Application;\r
+                       Channel* Chan;\r
+                       Chan = (Channel*)hbbtv_demuxer->Get_Channel(dsmcc_overlord->service_id);\r
+                       //if(!Chan)\r
+                       Application = Chan->Get_App(dsmcc_overlord->application_id);    \r
+                       Application->url_received = 1;                  \r
+                       put_app_url(player_interf);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static u32 On_hbbtv_get_tsdemuxer(sPlayerInterface* player_interf, GF_Event *event) \r
+{\r
+       HbbtvDemuxer* hbbtv_demuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+       GF_M2TS_Demuxer *ts = (GF_M2TS_Demuxer*)event->forwarded_event.param;\r
+       hbbtv_demuxer->Set_Ts(ts);      \r
+       if(hbbtv_demuxer->Get_Ts() != NULL){\r
+               if(hbbtv_demuxer->Get_if_dsmcc_process() && !ts->process_dmscc){        \r
+                       gf_m2ts_demux_dmscc_init(ts);\r
+               }\r
+               return GF_OK;\r
+       }\r
+               \r
+       return GF_BAD_PARAM;\r
+}\r
+\r
+u32 DemuxStart(void *par){\r
+\r
+       GF_Err e;\r
+       HbbtvDemuxer* hbbtv_demuxer = (HbbtvDemuxer*) par;\r
+       e = TSDemux_Demux_Setup(hbbtv_demuxer->Get_Ts(), hbbtv_demuxer->Get_Input_data(), 0);\r
+       if(e)\r
+       {\r
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HBBTV] Error during TS demux \n"));\r
+       }\r
+       return e;\r
+\r
+}\r
+\r
+Channel* ZapChannel(HbbtvDemuxer *hbbtv_demuxer,u32 service_id,int zap){  \r
+       return hbbtv_demuxer->Zap_channel(service_id,zap);\r
+}\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_keycontrol.cpp b/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_keycontrol.cpp
new file mode 100644 (file)
index 0000000..b6108e6
--- /dev/null
@@ -0,0 +1,354 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle - Jonathan Sillan              \r
+ *                             \r
+ */\r
+#include "hbbtvterminal.h"\r
+\r
+\r
+\r
+void gtksendkey(sPlayerInterface* player_interf,int keycode);\r
+\r
+void gtksendkey(sPlayerInterface* player_interf,int keycode)\r
+{\r
+       TRACEINFO;\r
+       GdkEvent *KeyEvent;\r
+       \r
+       fprintf(stderr, "\x1b[%i;3%imKeyCode\x1b[0m: %d\n",1, 4,keycode);\r
+       \r
+       KeyEvent = gdk_event_new (GDK_KEY_PRESS);\r
+       /* Key Value */\r
+       KeyEvent->key.keyval = gdk_unicode_to_keyval(keycode);  \r
+       /* GDK_BUTTON1_MASK refers to left mouse button */\r
+       KeyEvent->key.state = GDK_BUTTON1_MASK;\r
+       /* Send the key event to Web Window */\r
+       \r
+       KeyEvent->key.window = player_interf->ui->pWebWindow->window;\r
+       gtk_main_do_event (KeyEvent);\r
+       //gdk_event_free(KeyEvent);\r
+}\r
+\r
+/* HBBTV Button */\r
+\r
+void on_redbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       fprintf(stderr, "\x1b[%i;3%imBOUTON PRESSED\n\x1b[0m", 1, 5);\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_RED]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("RED is registered by the application : send HBBTV_VK_RED to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_RED);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("RED is not registered by the application\n"));\r
+       }\r
+       \r
+}\r
+\r
+void on_greenbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+       if (player_interf->keyregistered[RK_GREEN]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("GREEN is registered by the application : send HBBTV_VK_GREEN to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_GREEN);       \r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("GREEN is not registered by the application\n"));\r
+       }\r
+}\r
+\r
+void on_yellowbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+       if (player_interf->keyregistered[RK_YELLOW]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("YELLOW is registered by the application : send HBBTV_VK_YELLOW to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_YELLOW);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("YELLOW is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+void on_bluebuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+       if (player_interf->keyregistered[RK_BLUE]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("BLUE is registered by the application : send HBBTV_VK_BLUE to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_BLUE);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("BLUE is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+/* Navigation */\r
+\r
+void on_returnbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_NAVIGATION]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is registered by the application : send HBBTV_VK_ENTER to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_ENTER);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+void on_exitbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       int posx,posy;\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       //~ gtk_window_set_transient_for(GTK_WINDOW(player_interf->ui->pWebWindow),GTK_WINDOW(player_interf->ui->pTVWindow));\r
+       get_window_position(player_interf->ui->pWebWindow, &posx, &posy);       \r
+       resizevideoplayer(player_interf, HBBTV_VIDEO_WIDTH, HBBTV_VIDEO_HEIGHT);        \r
+       set_window_position(player_interf->ui->pTVWindow, posx, posy);\r
+       gtk_window_set_position(GTK_WINDOW(player_interf->ui->pTVWindow),GTK_WIN_POS_CENTER_ALWAYS);\r
+       webkit_web_view_load_uri(player_interf->ui->pWebView, player_interf->url);\r
+}\r
+\r
+void on_upbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_NAVIGATION]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is registered by the application : send HBBTV_VK_UP to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_UP);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is not registered by the application\n"));\r
+       }\r
+}\r
+\r
+void on_downbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_NAVIGATION]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is registered by the application : send HBBTV_VK_DOWN to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_DOWN);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+void on_leftbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_NAVIGATION]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is registered by the application : send HBBTV_VK_LEFT to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_LEFT);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE,("NAVIGATION is not registered by the application\n"));\r
+       }\r
+}\r
+\r
+void on_rightbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;      \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       if (player_interf->keyregistered[RK_NAVIGATION]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is registered by the application : send HBBTV_VK_RIGHT to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_RIGHT);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NAVIGATION is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+\r
+\r
+/* Control */\r
+\r
+void on_playpausebuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;      \r
+       set_window_position(player_interf->ui->pTVWindow, 0, 0);\r
+}\r
+\r
+void on_playbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+       if (player_interf->keyregistered[RK_VCR]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("VCR is registered by the application : send HBBTV_VK_PLAY to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_PLAY);\r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("VCR is not registered by the application\n"));\r
+       }       \r
+       \r
+}\r
+\r
+void on_pausebuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+       if (player_interf->keyregistered[RK_VCR]){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("VCR is registered by the application : send HBBTV_VK_PAUSE to the Application\n"));\r
+               gtksendkey(player_interf,HBBTV_VK_PAUSE); \r
+       }else{\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("VCR is not registered by the application\n"));\r
+       }       \r
+}\r
+\r
+void on_onoffbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       player_interf = (sPlayerInterface*)data;\r
+\r
+       if (player_interf->TVwake == FALSE) {\r
+               init_gpac(player_interf);\r
+               player_interf->TVwake = TRUE;\r
+       }\r
+       else {\r
+               stop_gpac(player_interf);\r
+               player_interf->TVwake = FALSE;\r
+       }\r
+       TRACEINFO;\r
+}\r
+\r
+void on_langbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       u32 current_service_id;\r
+       HbbtvDemuxer *hbbtvdemuxer;\r
+       GF_MediaInfo odi;\r
+       u32 index_audio,audio_ID;       \r
+       \r
+       player_interf = (sPlayerInterface*)data;\r
+       hbbtvdemuxer = ( HbbtvDemuxer *)player_interf->Demuxer;\r
+       current_service_id = index_audio = audio_ID = 0;        \r
+       \r
+       /* Get the current channel struct */\r
+       current_service_id = gf_term_get_current_service_id(player_interf->m_term);\r
+       Channel* chan = (Channel*)ZapChannel(hbbtvdemuxer,current_service_id,0);        \r
+       if(chan->Get_nb_chan_audio_stream() > 1){\r
+               GF_ObjectManager *root_odm = gf_term_get_root_object(player_interf->m_term);\r
+               if (root_odm){\r
+                       if (gf_term_get_object_info(player_interf->m_term, root_odm, &odi) == GF_OK){ \r
+                               if (odi.od) {\r
+                                       /* Increment the audio index to get the next audio stream */\r
+                                       chan->Incr_audio_index(0);                                      \r
+                                       gf_term_select_object(player_interf->m_term, gf_term_get_object(player_interf->m_term, root_odm, chan->Get_audio_ID(chan->Get_audio_index())));\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+void on_teletextbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       player_interf = (sPlayerInterface*)data;\r
+       gtksendkey(player_interf,HBBTV_VK_TELETEXT);\r
+\r
+}\r
+\r
+void on_channelbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       GtkButton* button;\r
+       int key_code;\r
+       char* label;\r
+       player_interf = (sPlayerInterface*)data;\r
+       button = (GtkButton*) widget;\r
+       label = (char*)gtk_button_get_label(button);\r
+               \r
+       switch(atoi(label)){\r
+               case 0:\r
+                       key_code = HBBTV_VK_0;\r
+                       break;\r
+               case 1:\r
+                       key_code = HBBTV_VK_1;\r
+                       break;\r
+               case 2:\r
+                       key_code = HBBTV_VK_2;\r
+                       break;\r
+               case 3:\r
+                       key_code = HBBTV_VK_3;\r
+                       break;\r
+               case 4:\r
+                       key_code = HBBTV_VK_4;\r
+                       break;\r
+               case 5:\r
+                       key_code = HBBTV_VK_5;\r
+                       break;\r
+               case 6:\r
+                       key_code = HBBTV_VK_6;\r
+                       break;\r
+               case 7:\r
+                       key_code = HBBTV_VK_7;\r
+                       break;\r
+               case 8:\r
+                       key_code = HBBTV_VK_8;\r
+                       break;\r
+               case 9:\r
+                       key_code = HBBTV_VK_9;\r
+                       break;\r
+               default:\r
+                        GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Wrong Key Code %d Defaut channel 1 \n",atoi(label)));\r
+                       key_code = HBBTV_VK_1;\r
+                       break;\r
+               }\r
+       if (player_interf->keyregistered[RK_NUMERIC]){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NUMERIC is registered by the application : send HBBTV_VK_%i to the Application\n",atoi(label)));\r
+               gtksendkey(player_interf,key_code);\r
+       }else{\r
+               hbbtvterm_get_channel_on_air(player_interf,atoi(label),0);\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("NUMERIC is not registered by the application, change channel function\n"));\r
+       }                               \r
+       \r
+       \r
+}\r
+\r
+\r
+void on_chanupbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       player_interf = (sPlayerInterface*)data;\r
+\r
+       hbbtvterm_channel_zap(player_interf,1);\r
+\r
+       TRACEINFO;\r
+}\r
+\r
+\r
+void on_chandownbuttonclicked(GtkWidget *widget, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sPlayerInterface* player_interf;\r
+       player_interf = (sPlayerInterface*)data;\r
+\r
+       hbbtvterm_channel_zap(player_interf,-1);\r
+\r
+       TRACEINFO;\r
+}\r
+\r
+int playpause(sPlayerInterface* player_interf)\r
+{\r
+       int  is_pause = gf_term_get_option( player_interf->m_term, GF_OPT_PLAY_STATE);\r
+       fprintf(stdout, "[Status: %s]\n", is_pause ? "Playing" : "Paused");\r
+       gf_term_set_option( player_interf->m_term, GF_OPT_PLAY_STATE, is_pause ? GF_STATE_PLAYING : GF_STATE_PAUSED);\r
+       return 1;\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_tools.cpp b/applications/hbbtvplayer/hbbtvterminal/src/hbbtv_tools.cpp
new file mode 100644 (file)
index 0000000..ddf8cad
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors:      Jonathan Sillan           \r
+ *                             \r
+ */\r
+#include "hbbtvterminal.h"\r
+\r
+\r
+GF_Config* check_config_file(){\r
+       Bool firstlaunch;\r
+       \r
+       firstlaunch = 0;\r
+       /*init config and modules*/\r
+       return gf_cfg_init(NULL,&firstlaunch);\r
+}\r
+\r
+Bool is_connected(){   \r
+       GF_Err e;\r
+       \r
+       GF_Socket* sock;         \r
+       \r
+       sock = gf_sk_new(GF_SOCK_TYPE_UDP);\r
+       if (sock == NULL) {                     \r
+               return 0;\r
+       }               \r
+       e = gf_sk_connect(sock, "www.google.fr", 4096, NULL);\r
+       gf_sk_del(sock); \r
+       \r
+       if(e){\r
+               return 0;\r
+       }else{\r
+               return 1;\r
+       }\r
+}\r
+\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.cpp b/applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.cpp
new file mode 100644 (file)
index 0000000..f44a95c
--- /dev/null
@@ -0,0 +1,1081 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle - Jonathan Sillan              \r
+ *                             \r
+ */\r
+\r
+#include "hbbtvterminal.h"\r
+#ifdef XP_UNIX\r
+#include <gdk/gdkx.h>\r
+#include <X11/Xlib.h>\r
+#else\r
+#include <gdk/gdk.h>\r
+#include <gdk/gdkwin32.h> \r
+#endif\r
+\r
+#include <JavaScriptCore/JSStringRef.h>\r
+#include <JavaScriptCore/JSContextRef.h>\r
+\r
+//static XID handler;\r
+static void activate_uri_entry_cb (GtkWidget* entry, gpointer data);\r
+\r
+sPlayerInterface* player_interf;\r
+\r
+static gboolean on_deleteevent( GtkWidget *widget, GdkEvent  *event, gpointer   data)\r
+{\r
+       g_print ("delete event occurred\n");\r
+       TRACEINFO;\r
+       return TRUE;\r
+}\r
+\r
+static gboolean on_windowconfigure(GtkWidget * widget, GdkEvent  *event, gpointer data)\r
+{\r
+       TRACEINFO;\r
+\r
+       static int oldx = 0;\r
+       static int oldy = 0;\r
+       int x, y, olddatax, olddatay;\r
+       \r
+       sPlayerInterface* player_interf = (sPlayerInterface*)data;\r
+\r
+       gtk_window_get_position(GTK_WINDOW(player_interf->ui->pWebWindow), &olddatax, &olddatay);\r
+\r
+       x = event->configure.x;\r
+       y = event->configure.y;\r
+\r
+       int deltax = x - oldx;\r
+       int deltay = y - oldy;\r
+\r
+       gtk_window_move(GTK_WINDOW(player_interf->ui->pTVWindow),olddatax + deltax, olddatay + deltay);\r
+       gtk_window_move(GTK_WINDOW(player_interf->ui->pBackgroundWindow),olddatax + deltax, olddatay + deltay);\r
+\r
+       oldx = x;\r
+       oldy = y;\r
+       return TRUE;\r
+}\r
+\r
+\r
+static void on_destroyevent(GtkWidget *widget, gpointer data)\r
+{\r
+       gtk_main_quit();\r
+       TRACEINFO;\r
+}\r
+\r
+\r
+int ui_init(sPlayerInterface* player_interf)\r
+{\r
+       GtkWidget   *pWindow;\r
+       GtkWidget   *pTVWindow;\r
+       GtkWidget   *pWebWindow;\r
+       GtkWidget   *pMainPositionTable;\r
+       GtkWidget   *pBrowserPositionTable;\r
+       GtkWidget   *pRCUPositionTable;\r
+       GtkWidget   *pColorButtonTable;\r
+       GtkWidget   *pRedButton;\r
+       GtkWidget   *pGreenButton;\r
+       GtkWidget   *pYellowButton;\r
+       GtkWidget   *pBlueButton;\r
+       GtkWidget   *pArrowButtonTable;\r
+       GtkWidget   *pUpButton;\r
+       GtkWidget   *pDownButton;\r
+       GtkWidget   *pLeftButton;\r
+       GtkWidget   *pRightButton;\r
+       GtkWidget   *pUpArrow;\r
+       GtkWidget   *pDownArrow;\r
+       GtkWidget   *pLeftArrow;\r
+       GtkWidget   *pRightArrow;\r
+       GtkWidget   *pEnterButton;\r
+       GtkWidget   *pBackButton;\r
+       GtkWidget   *pEntry;\r
+       GtkWidget   *pNumPadTable;\r
+       GtkWidget   *pNumber[10];\r
+       GtkWidget   *pPlayButton;\r
+       GtkWidget   *pStopButton;\r
+       GtkWidget   *pPauseButton;\r
+       GtkWidget   *pPlayPauseButton;\r
+       GtkWidget   *pFastMoveTable;\r
+       GtkWidget   *pFastForwardButton;\r
+       GtkWidget   *pFastRewindButton;\r
+       GtkWidget   *pLangButton;\r
+       GtkWidget   *pExitButton;\r
+       GtkWidget   *pOnOffButton;\r
+       GtkWidget   *pTeletextButton;\r
+       GtkWidget   *pProgramSelectionTable;\r
+       GtkWidget   *pPreviousProgramButton;\r
+       GtkWidget   *pNextProgramButton;\r
+       GtkWidget   *pQuitButton;\r
+       GtkWidget   *pTestButton;\r
+       GtkWidget   *pTest2Button;\r
+       GtkWidget   *pGoButton;\r
+       GtkWidget   *pWebScrollWindow;\r
+       GtkWidget   *pBackgroundWindow;\r
+\r
+       GdkColor color;\r
+       int Error,posx,posy;\r
+\r
+       TRACEINFO;\r
+\r
+       sGraphicInterface* ui = player_interf->ui;\r
+\r
+       /** Main window **/\r
+       pBackgroundWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);\r
+       pTVWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);\r
+       pWebWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);\r
+       pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);\r
+\r
+       ui->pMainWindow = pWindow;\r
+       ui->pTVWindow = pTVWindow;\r
+       ui->pWebWindow = pWebWindow;\r
+       ui->pBackgroundWindow = pBackgroundWindow;\r
+        \r
+       gtk_window_set_title(GTK_WINDOW(pWindow), "RCU");\r
+       gtk_window_set_title(GTK_WINDOW(pTVWindow), "TV");\r
+       gtk_window_set_title(GTK_WINDOW(pWebWindow), "WEB");\r
+       gtk_window_set_title(GTK_WINDOW(pBackgroundWindow), "BACK");\r
+\r
+       gtk_window_set_decorated(GTK_WINDOW(pWebWindow), false);\r
+       gtk_window_set_decorated(GTK_WINDOW(pTVWindow), false);\r
+       gtk_window_set_decorated(GTK_WINDOW(pBackgroundWindow), false);\r
+       gtk_window_set_transient_for(GTK_WINDOW(pTVWindow),GTK_WINDOW(pBackgroundWindow));\r
+       gtk_window_set_transient_for(GTK_WINDOW(pWebWindow),GTK_WINDOW(pTVWindow));\r
+       \r
+       gtk_window_set_resizable(GTK_WINDOW(pTVWindow), false);\r
+       gtk_window_set_resizable(GTK_WINDOW(pWebWindow), false);\r
+       gtk_window_set_resizable(GTK_WINDOW(pBackgroundWindow), false);\r
+       \r
+       /** Quit button **/\r
+       pQuitButton =  gtk_button_new_with_label("Quit");\r
+\r
+       /** Tests button **/\r
+       pTestButton =  gtk_button_new_with_label("Test");\r
+       pTest2Button =  gtk_button_new_with_label("Test2");\r
+\r
+       /** Entry bar for URL **/\r
+       pEntry = gtk_entry_new();\r
+       ui->pEntry = pEntry;\r
+\r
+       /** GO Button **/\r
+       pGoButton =  gtk_button_new_with_label("Go");\r
+\r
+       /** Browser Zone **/\r
+       pWebScrollWindow = gtk_scrolled_window_new(NULL, NULL);\r
+       //gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pWebScrollWindow), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);\r
+\r
+       ui->pWebView = WEBKIT_WEB_VIEW(webkit_web_view_new());\r
+       \r
+       webkit_web_view_set_transparent(ui->pWebView, TRUE);\r
+\r
+       if (ui->pWebView)\r
+               gtk_container_add(GTK_CONTAINER(pWebScrollWindow), GTK_WIDGET(ui->pWebView));\r
+\r
+       /** Background Zone **/\r
+       ui->pBackgroundView = gtk_drawing_area_new();\r
+       gdk_color_parse("#000044", &color);\r
+       gtk_widget_modify_bg ( GTK_WIDGET(ui->pBackgroundView), GTK_STATE_NORMAL, &color);\r
+\r
+       /** TV zone **/\r
+       ui->pTVView = gtk_drawing_area_new();\r
+\r
+       /** RCU zone **/\r
+\r
+       /* create Red color */\r
+       gdk_color_parse("#FF0000", &color);\r
+       pRedButton = gtk_button_new();\r
+       gtk_widget_modify_bg ( GTK_WIDGET(pRedButton), GTK_STATE_NORMAL, &color);\r
+       gtk_button_set_label(GTK_BUTTON(pRedButton)," ");\r
+       /* create Green color */\r
+       gdk_color_parse("#00FF00", &color);\r
+       pGreenButton = gtk_button_new();\r
+       gtk_widget_modify_bg ( GTK_WIDGET(pGreenButton), GTK_STATE_NORMAL, &color);\r
+       gtk_button_set_label(GTK_BUTTON(pGreenButton)," ");\r
+       /* create Yellow color */\r
+       gdk_color_parse("#FFFF00", &color);\r
+       pYellowButton = gtk_button_new();\r
+       gtk_widget_modify_bg ( GTK_WIDGET(pYellowButton), GTK_STATE_NORMAL, &color);\r
+       gtk_button_set_label(GTK_BUTTON(pYellowButton)," ");\r
+       /* create Blue color */\r
+       gdk_color_parse("#0000FF", &color);\r
+       pBlueButton = gtk_button_new();\r
+       gtk_widget_modify_bg ( GTK_WIDGET(pBlueButton), GTK_STATE_NORMAL, &color);\r
+       gtk_button_set_label(GTK_BUTTON(pBlueButton)," ");\r
+\r
+       pUpButton       = gtk_button_new();\r
+       pDownButton     = gtk_button_new();\r
+       pLeftButton     = gtk_button_new();\r
+       pRightButton    = gtk_button_new();\r
+\r
+       pUpArrow        = gtk_arrow_new(GTK_ARROW_UP,GTK_SHADOW_OUT);\r
+       pDownArrow      = gtk_arrow_new(GTK_ARROW_DOWN,GTK_SHADOW_OUT);\r
+       pLeftArrow      = gtk_arrow_new(GTK_ARROW_LEFT,GTK_SHADOW_OUT);\r
+       pRightArrow     = gtk_arrow_new(GTK_ARROW_RIGHT,GTK_SHADOW_OUT);\r
+\r
+       gtk_container_add(GTK_CONTAINER(pUpButton), pUpArrow);\r
+       gtk_container_add(GTK_CONTAINER(pDownButton), pDownArrow);\r
+       gtk_container_add(GTK_CONTAINER(pLeftButton), pLeftArrow);\r
+       gtk_container_add(GTK_CONTAINER(pRightButton), pRightArrow);\r
+\r
+       pEnterButton    = gtk_button_new_with_label("Enter");\r
+       pBackButton     = gtk_button_new_with_label("Back");\r
+\r
+       pNumber[0] = gtk_button_new_with_label("0");\r
+       pNumber[1] = gtk_button_new_with_label("1");\r
+       pNumber[2] = gtk_button_new_with_label("2");\r
+       pNumber[3] = gtk_button_new_with_label("3");\r
+       pNumber[4] = gtk_button_new_with_label("4");\r
+       pNumber[5] = gtk_button_new_with_label("5");\r
+       pNumber[6] = gtk_button_new_with_label("6");\r
+       pNumber[7] = gtk_button_new_with_label("7");\r
+       pNumber[8] = gtk_button_new_with_label("8");\r
+       pNumber[9] = gtk_button_new_with_label("9");\r
+\r
+       pPreviousProgramButton  = gtk_button_new_with_label("P-");\r
+       pNextProgramButton      = gtk_button_new_with_label("P+");\r
+\r
+       pPlayButton         = gtk_button_new_with_label("Play");\r
+       pStopButton         = gtk_button_new_with_label("Stop");\r
+       pPauseButton        = gtk_button_new_with_label("Pause");\r
+       pPlayPauseButton        = gtk_button_new_with_label("PlayPause");\r
+\r
+       pFastForwardButton      = gtk_button_new_with_label(">>");\r
+       pFastRewindButton       = gtk_button_new_with_label("<<");\r
+       pTeletextButton         = gtk_button_new_with_label("Teletext");\r
+       pLangButton          = gtk_button_new_with_label("Language");\r
+       pExitButton         = gtk_button_new_with_label("Exit");\r
+       pOnOffButton        = gtk_button_new_with_label("OnOff");\r
+\r
+       pColorButtonTable = gtk_table_new(4,1,false);\r
+       gtk_table_attach(GTK_TABLE(pColorButtonTable),pRedButton,    0,1,0,1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+       gtk_table_attach(GTK_TABLE(pColorButtonTable),pGreenButton,  0,1,1,2, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+       gtk_table_attach(GTK_TABLE(pColorButtonTable),pYellowButton, 0,1,2,3, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+       gtk_table_attach(GTK_TABLE(pColorButtonTable),pBlueButton,   0,1,3,4, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+\r
+       pArrowButtonTable = gtk_table_new(3,3, false);\r
+       gtk_table_attach(GTK_TABLE(pArrowButtonTable), pUpButton,    1,2,0,1,GtkAttachOptions(GTK_FILL|GTK_EXPAND), GtkAttachOptions(GTK_FILL|GTK_EXPAND), 0,0 );\r
+       gtk_table_attach(GTK_TABLE(pArrowButtonTable), pDownButton,  1,2,2,3,GtkAttachOptions(GTK_FILL|GTK_EXPAND), GtkAttachOptions(GTK_FILL|GTK_EXPAND), 0,0 );\r
+       gtk_table_attach(GTK_TABLE(pArrowButtonTable), pLeftButton,  0,1,1,2,GtkAttachOptions(GTK_FILL|GTK_EXPAND), GtkAttachOptions(GTK_FILL|GTK_EXPAND), 0,0 );\r
+       gtk_table_attach(GTK_TABLE(pArrowButtonTable), pRightButton, 2,3,1,2,GtkAttachOptions(GTK_FILL|GTK_EXPAND), GtkAttachOptions(GTK_FILL|GTK_EXPAND), 0,0 );\r
+\r
+       pNumPadTable = gtk_table_new(4,3,false);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[0], 1, 2, 3, 4, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[1], 0, 1, 0, 1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[2], 1, 2, 0, 1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[3], 2, 3, 0, 1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[4], 0, 1, 1, 2, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[5], 1, 2, 1, 2, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[6], 2, 3, 1, 2, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[7], 0, 1, 2, 3, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[8], 1, 2, 2, 3, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pNumPadTable), pNumber[9], 2, 3, 2, 3, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+\r
+       pFastMoveTable = gtk_table_new(1,2,false);\r
+       gtk_table_attach(GTK_TABLE(pFastMoveTable), pFastRewindButton,  0,1,0,1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+       gtk_table_attach(GTK_TABLE(pFastMoveTable), pFastForwardButton, 1,2,0,1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+\r
+       pProgramSelectionTable = gtk_table_new(1,2, false);\r
+       gtk_table_attach(GTK_TABLE(pProgramSelectionTable), pPreviousProgramButton, 0,1,0,1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+       gtk_table_attach(GTK_TABLE(pProgramSelectionTable), pNextProgramButton,     1,2,0,1, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL),0,0);\r
+\r
+       /** create the toplevel tables **/\r
+       pRCUPositionTable = gtk_table_new(24,1,false);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pColorButtonTable,       0, 1,  0,  4, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pArrowButtonTable,       0, 1,  4,  7, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pEnterButton,            0, 1,  7,  8, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pBackButton,             0, 1,  8,  9, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pNumPadTable,            0, 1,  9, 13, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pPlayButton,             0, 1, 13, 14, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pStopButton,             0, 1, 14, 15, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pPauseButton,            0, 1, 15, 16, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pPlayPauseButton,        0, 1, 16, 17, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pFastMoveTable,          0, 1, 17, 18, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pProgramSelectionTable,  0, 1, 18, 19, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pTeletextButton,         0, 1, 19, 20, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pLangButton,              0, 1, 20, 21, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pExitButton,             0, 1, 21, 22, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pOnOffButton,            0, 1, 22, 23, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+       gtk_table_attach(GTK_TABLE(pRCUPositionTable), pQuitButton,             0, 1, 23, 24, GtkAttachOptions(GTK_FILL|GTK_EXPAND),GtkAttachOptions(GTK_FILL|GTK_EXPAND),0,0);\r
+\r
+       pBrowserPositionTable = gtk_table_new(3,3,false);\r
+       //gtk_table_attach(GTK_TABLE(pBrowserPositionTable), pEntry,          0, 2, 0, 1, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GTK_FILL, 0,0);\r
+       //gtk_table_attach(GTK_TABLE(pBrowserPositionTable), pGoButton,       2, 3, 0, 1, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GTK_FILL, 0,0);\r
+       gtk_table_attach(GTK_TABLE(pBrowserPositionTable), pWebScrollWindow, 0, 3, 1, 3, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GtkAttachOptions(GTK_EXPAND | GTK_FILL), 0,0);\r
+\r
+       /** Group toplevel tables in the main table **/\r
+       pMainPositionTable =  gtk_table_new(4,7,false);\r
+       gtk_table_attach(GTK_TABLE(pMainPositionTable), pRCUPositionTable,      6, 7, 0, 3, GtkAttachOptions(NULL), GtkAttachOptions(NULL), 0,0);\r
+       //gtk_table_attach(GTK_TABLE(pMainPositionTable), pBottomBarTable,        0, 7, 3, 4, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GtkAttachOptions(GTK_EXPAND | GTK_FILL), 0,0);\r
+\r
+       gtk_container_add(GTK_CONTAINER(pWindow), pMainPositionTable);\r
+       gtk_container_add(GTK_CONTAINER(pTVWindow), ui->pTVView);\r
+       gtk_container_add(GTK_CONTAINER(pBackgroundWindow), ui->pBackgroundView);\r
+       //~ gtk_container_add(GTK_CONTAINER(pWebWindow), ui->pWebView);\r
+       gtk_container_add(GTK_CONTAINER(pWebWindow), pBrowserPositionTable);\r
+\r
+       /** SET SIZE **/\r
+       gtk_widget_set_size_request(GTK_WIDGET(ui->pTVView),  HBBTV_VIDEO_WIDTH,HBBTV_VIDEO_HEIGHT);\r
+       gtk_widget_set_size_request(GTK_WIDGET(ui->pBackgroundView),  HBBTV_VIDEO_WIDTH,HBBTV_VIDEO_HEIGHT);\r
+       gtk_widget_set_size_request(GTK_WIDGET(pBrowserPositionTable), HBBTV_VIDEO_WIDTH,HBBTV_VIDEO_HEIGHT);\r
+       \r
+       gtk_window_set_position(GTK_WINDOW(pWebWindow), GTK_WIN_POS_CENTER_ALWAYS);     \r
+       gtk_window_set_position(GTK_WINDOW(pBackgroundWindow), GTK_WIN_POS_CENTER_ALWAYS);\r
+       gtk_window_set_position(GTK_WINDOW(pTVWindow),  GTK_WIN_POS_CENTER_ALWAYS);\r
+\r
+       /** Connect Callback **/\r
+       //** expose drawable\r
+\r
+       // connect to deleteevent function\r
+       g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(on_deleteevent), NULL);\r
+\r
+       // connect to destroy function\r
+       g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(on_destroyevent), NULL);\r
+       g_signal_connect(G_OBJECT(pWebWindow), "destroy", G_CALLBACK(on_destroyevent), NULL);\r
+       g_signal_connect(G_OBJECT(pQuitButton), "clicked", G_CALLBACK(on_destroyevent), NULL);\r
+\r
+       //connect button and entry\r
+       /* Control */\r
+       g_signal_connect (G_OBJECT(pEntry), "activate", G_CALLBACK (activate_uri_entry_cb), ui);\r
+       g_signal_connect (G_OBJECT(pGoButton), "clicked", G_CALLBACK (activate_uri_entry_cb), ui);\r
+       g_signal_connect (G_OBJECT(pOnOffButton), "clicked", G_CALLBACK (on_onoffbuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pPlayPauseButton), "clicked", G_CALLBACK (on_playpausebuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pPlayButton), "clicked", G_CALLBACK (on_playbuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pPauseButton), "clicked", G_CALLBACK (on_pausebuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pLangButton), "clicked", G_CALLBACK (on_langbuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pNextProgramButton), "clicked", G_CALLBACK (on_chanupbuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pPreviousProgramButton), "clicked", G_CALLBACK (on_chandownbuttonclicked), player_interf );\r
+       g_signal_connect (G_OBJECT(pNumber[1]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[2]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[3]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[4]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[5]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[6]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[7]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[8]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[9]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pNumber[0]), "clicked", G_CALLBACK (on_channelbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pTeletextButton), "clicked", G_CALLBACK (on_teletextbuttonclicked), player_interf);\r
+       \r
+       \r
+       /* HBBTV Button */\r
+       g_signal_connect (G_OBJECT(pRedButton),         "clicked", G_CALLBACK (on_redbuttonclicked),    player_interf);\r
+       g_signal_connect (G_OBJECT(pGreenButton),       "clicked", G_CALLBACK (on_greenbuttonclicked),  player_interf);\r
+       g_signal_connect (G_OBJECT(pYellowButton),      "clicked", G_CALLBACK (on_yellowbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pBlueButton),        "clicked", G_CALLBACK (on_bluebuttonclicked),   player_interf);\r
+       \r
+       /* Navigation */\r
+       g_signal_connect (G_OBJECT(pUpButton),  "clicked", G_CALLBACK (on_upbuttonclicked),     player_interf);\r
+       g_signal_connect (G_OBJECT(pDownButton),        "clicked", G_CALLBACK (on_downbuttonclicked),   player_interf);\r
+       g_signal_connect (G_OBJECT(pLeftButton),        "clicked", G_CALLBACK (on_leftbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pRightButton),       "clicked", G_CALLBACK (on_rightbuttonclicked),  player_interf);\r
+       g_signal_connect (G_OBJECT(pEnterButton),       "clicked", G_CALLBACK (on_returnbuttonclicked), player_interf);\r
+       g_signal_connect (G_OBJECT(pExitButton),        "clicked", G_CALLBACK (on_exitbuttonclicked),   player_interf);\r
+       \r
+\r
+       //      gtk_widget_add_events(GTK_WIDGET(pWebWindow), GDK_CONFIGURE);\r
+       // g_signal_connect(G_OBJECT(pTVWindow), "configure-event", G_CALLBACK(on_windowconfigure), pBackgroundWindow);\r
+       // g_signal_connect(G_OBJECT(pWebWindow), "configure-event", G_CALLBACK(on_windowconfigure), player_interf);\r
+\r
+       /** realisation, map  and show **/\r
+       gtk_widget_realize(ui->pBackgroundView);\r
+       gtk_widget_realize(ui->pTVView);\r
+\r
+       Error = init_gpac(player_interf);\r
+       if(Error){\r
+                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Error during gpac intialization \n"));\r
+                return GF_IO_ERR;\r
+       }\r
+\r
+       GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(ui->pWebView));\r
+       GdkColormap *rgba = gdk_screen_get_rgba_colormap (screen);\r
+\r
+       gtk_widget_set_colormap(GTK_WIDGET(ui->pWebView), rgba);\r
+       gtk_widget_set_colormap(GTK_WIDGET(pBrowserPositionTable), rgba);\r
+\r
+       /** center the windows **/\r
+       \r
+       gtk_widget_set_default_colormap(rgba);\r
+       gtk_widget_show_all(pWindow);\r
+       gtk_widget_show_all(pBackgroundWindow);\r
+       gtk_widget_show_all(pTVWindow);\r
+       gtk_widget_show_all(pWebWindow);\r
+       gtk_window_present (GTK_WINDOW(pWebWindow));\r
+\r
+       return GF_OK;\r
+}\r
+\r
+\r
+int init_playerinterface(sPlayerInterface* player_interf, char* input_data, char* url, Bool no_url)\r
+{\r
+\r
+       HbbtvDemuxer *hbbtv_demuxer;\r
+       int Error;\r
+       int ChannelScanTimer;\r
+       u32 i,nb_chan;\r
+\r
+       hbbtv_demuxer = ( HbbtvDemuxer *)player_interf->Demuxer;\r
+       ChannelScanTimer = 0;\r
+\r
+       player_interf->ui = (sGraphicInterface*) gf_calloc(1,sizeof(sGraphicInterface));\r
+\r
+       \r
+       player_interf->input_data = (char*)gf_calloc(strlen(input_data)+1,sizeof(char));\r
+       sprintf(player_interf->input_data,"%s",input_data);\r
+       player_interf->input_data[strlen(input_data)] = 0;\r
+\r
+       player_interf->url = url;\r
+       player_interf->no_url = no_url;\r
+       player_interf->TVwake = FALSE;\r
+       player_interf->is_connected = is_connected();\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("player_interf->is_connected %d\n",player_interf->is_connected));\r
+\r
+\r
+       Error = ui_init(player_interf);\r
+       if(Error){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Initialization error \n"));\r
+               return GF_IO_ERR;\r
+       }\r
+\r
+       if(player_interf->url) {\r
+               init_browser(player_interf);\r
+       }\r
+\r
+       while(!hbbtv_demuxer->Check_all_channel_info_received(ChannelScanTimer)) {\r
+               ChannelScanTimer++;\r
+               gf_sleep(1000);\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Wainting for the PMTs \n"));                                       \r
+       }\r
+       \r
+       hbbtvterm_scan_channel(player_interf);\r
+\r
+       /* The check for init is made inside this function. AIT received have to be processed before getting new ones */\r
+       \r
+       nb_chan = gf_list_count(hbbtv_demuxer->Get_ChannelList());\r
+\r
+       for(i=0;i<nb_chan;i++){         \r
+             Channel* chan = ( Channel*)gf_list_get(hbbtv_demuxer->Get_ChannelList(),i);             \r
+             Get_application_for_channel(hbbtv_demuxer,chan->Get_service_id());                \r
+       }\r
+       player_interf->init = 1;        \r
+       \r
+       put_app_url(player_interf);       \r
+       \r
+       \r
+\r
+       return GF_OK;\r
+\r
+}\r
+\r
+\r
+int init_gpac(sPlayerInterface* player_interf)\r
+{\r
+       TRACEINFO;      \r
+       char config_path[GF_MAX_PATH];\r
+       const char *str;\r
+       const char *gpac_cfg;\r
+       sGraphicInterface *ui = player_interf->ui;\r
+       \r
+\r
+#ifdef XP_UNIX\r
+       gpac_cfg = (char *) ".gpacrc";\r
+       strcpy((char *) config_path, getenv("HOME"));\r
+#else\r
+       gpac_cfg = "GPAC.cfg";\r
+       strcpy((char*)config_path,"D:\\code\\trunk\\gpac_public\\bin\\win32\\debug");\r
+#endif\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Configuration path : %s/%s \n",config_path,gpac_cfg));\r
+\r
+       player_interf->m_user = (GF_User*)gf_malloc(sizeof(GF_User));\r
+       memset(player_interf->m_user, 0, sizeof(GF_User));\r
+       //~ player_interf->m_user->config = gf_cfg_new((const char *) config_path, gpac_cfg);\r
+                               \r
+       /*init config and modules*/\r
+       player_interf->m_user->config = check_config_file();\r
+       if(!player_interf->m_user->config){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Configuration failed. COnfiguration file not found \n"));\r
+                       return GF_BAD_PARAM;\r
+       }\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Configuration initialized \n"));\r
+\r
+       str = gf_cfg_get_key( player_interf->m_user->config, "General", "ModulesDirectory");\r
+       player_interf->m_user->modules = gf_modules_new(str,  player_interf->m_user->config);\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] %d modules loaded \n",gf_modules_get_count( player_interf->m_user->modules)));\r
+\r
+       player_interf->m_user->opaque =  player_interf->Demuxer;\r
+       player_interf->m_user->EventProc = On_hbbtv_received_section;\r
+\r
+#ifdef XP_UNIX\r
+       player_interf->m_user->os_window_handler = (void*)GDK_WINDOW_XID(gtk_widget_get_window(ui->pTVView));\r
+       player_interf->m_user->os_display = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(ui->pTVView));\r
+       XSynchronize((Display *)  player_interf->m_user->os_display, True);\r
+#else\r
+       player_interf->m_user->os_window_handler = (void*)GDK_WINDOW_HWND(gtk_widget_get_window(ui->pTVView));\r
+       player_interf->m_user->os_display = gdk_drawable_get_display (gtk_widget_get_window(ui->pTVView));\r
+       gdk_display_sync((GdkDisplay *)player_interf->m_user->os_display);\r
+#endif\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] User initialized \n"));\r
+\r
+       if (( player_interf->m_term = gf_term_new(player_interf->m_user))) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Terminal created.\n"));\r
+       }\r
+       else {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Error when creating terminal\n"));\r
+               return GF_IO_ERR;\r
+       }\r
+\r
+       gf_term_set_size( player_interf->m_term, HBBTV_VIDEO_WIDTH,HBBTV_VIDEO_HEIGHT);\r
+\r
+\r
+       if (strnicmp(player_interf->input_data, "udp://", 6)\r
+               && strnicmp(player_interf->input_data, "mpegts-udp://", 13)\r
+               && strnicmp(player_interf->input_data, "mpegts-tcp://", 13)\r
+               && strnicmp(player_interf->input_data, "dvb://", 6)\r
+       && strnicmp(player_interf->input_data, "http://", 6)) {\r
+\r
+               FILE *test = fopen(player_interf->input_data, "rb");\r
+               if (!test) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] %s  file cannot be oppened \n",player_interf->input_data));\r
+                       return GF_BAD_PARAM;\r
+               }\r
+               else {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] %s file oppened successfully \n", player_interf->input_data));\r
+                       fclose(test);\r
+               }\r
+\r
+       }\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Input URL : %s\n", player_interf->input_data));\r
+       gf_term_connect( player_interf->m_term, (const char*)player_interf->input_data );\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Terminal connected\n"));\r
+       \r
+       return GF_OK;\r
+}\r
+\r
+\r
+int stop_gpac(sPlayerInterface* player_interf)\r
+{\r
+       TRACEINFO;\r
+       gf_term_disconnect( player_interf->m_term);\r
+       gf_term_del( player_interf->m_term);\r
+       gf_modules_del( player_interf->m_user->modules);\r
+       gf_cfg_del( player_interf->m_user->config);\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+static void activate_uri_entry_cb (GtkWidget* entry, gpointer data)\r
+{\r
+       TRACEINFO;\r
+       sGraphicInterface *pUI;\r
+\r
+       pUI = (sGraphicInterface*)data;\r
+       const gchar* uri = gtk_entry_get_text (GTK_ENTRY(pUI->pEntry));\r
+       g_assert (uri);\r
+       webkit_web_view_load_uri (pUI->pWebView, uri);\r
+}\r
+\r
+int term_play(sPlayerInterface* player_interf)\r
+{\r
+       gf_term_set_option(player_interf->m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);\r
+       return 1;\r
+}\r
+\r
+\r
+int term_pause(sPlayerInterface* player_interf)\r
+{\r
+       gf_term_set_option(player_interf->m_term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);\r
+       return 1;\r
+}\r
+\r
+\r
+int init_browser(sPlayerInterface* player_interf)\r
+{\r
+       if(!player_interf->no_url) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Initialized the browser with HBBTV Application URL : %s   \n",player_interf->url));\r
+               webkit_web_view_load_uri(player_interf->ui->pWebView, player_interf->url);\r
+               return GF_OK;\r
+       }\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] URL blocked by the user. No Application to play  \n"));\r
+       return GF_OK;\r
+}\r
+\r
+\r
+int init_player(sPlayerInterface* player_interf)\r
+{\r
+       /* Init the player with the fisrt channel of the stream */\r
+\r
+       HbbtvDemuxer* hbbtvdemuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+       Channel* chan = (Channel*)gf_list_get(hbbtvdemuxer->Get_ChannelList(),0);\r
+       hbbtvterm_get_channel_on_air(player_interf,chan->Get_service_id(),0);\r
+\r
+       return GF_OK;\r
+}\r
+\r
+GF_Err get_app_url(sPlayerInterface* player_interf, GF_M2TS_CHANNEL_APPLICATION_INFO*ChannelApp)\r
+{\r
+       u32 current_service_id; \r
+\r
+       current_service_id = player_interf->m_term->root_scene->selected_service_id;\r
+       \r
+       if(!ChannelApp){\r
+               return GF_IO_ERR;\r
+       }\r
+       \r
+       if((ChannelApp->service_id == current_service_id)) {\r
+               GF_M2TS_AIT_APPLICATION* app_info;\r
+               Channel* Chan;  \r
+               \r
+               HbbtvDemuxer* hbbtvdemuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+               Chan = (Channel*)ZapChannel(hbbtvdemuxer,current_service_id,0);\r
+                               \r
+               app_info = Chan->App_to_play(player_interf->is_connected,0);    \r
+\r
+               if(!app_info){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] This service id %d does not have an autostart application. \n",ChannelApp->service_id,current_service_id));\r
+                       return GF_IO_ERR;\r
+               }               \r
+       \r
+               if(player_interf->init){\r
+                       if(app_info->broadband){\r
+                               player_interf->url = app_info->http_url;\r
+                       }else if(app_info->broadcast){\r
+                               player_interf->url = app_info->carousel_url;\r
+                       }               \r
+                       webkit_web_view_load_uri(player_interf->ui->pWebView, player_interf->url);                              \r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] HBBTV Application URL : %s   \n",player_interf->url));                     \r
+                       return GF_OK;\r
+               }\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Cannot start the application until player initialization is finished \n"));\r
+               return GF_IO_ERR;\r
+       }       \r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("ChannelApp->service_id %d is wrong current_service_id %d !!\n",ChannelApp->service_id,current_service_id));\r
+       return GF_IO_ERR;\r
+\r
+\r
+}\r
+\r
+int put_app_url(sPlayerInterface* player_interf)\r
+{\r
+       u32 current_service_id;\r
+       Bool ignore_TS_url;\r
+       GF_Err e;\r
+       HbbtvDemuxer* hbbtvdemux = (HbbtvDemuxer*)player_interf->Demuxer;\r
+\r
+       ignore_TS_url = hbbtvdemux->Get_Ignore_TS_URL();\r
+       e = GF_OK;\r
+       \r
+       if(!ignore_TS_url && !player_interf->no_url){\r
+               \r
+               current_service_id = player_interf->m_term->root_scene->selected_service_id;\r
+               Channel* chan = (Channel*)ZapChannel(hbbtvdemux,current_service_id,0);          \r
+               e = get_app_url(player_interf,chan->Get_App_info());\r
+               if(e == GF_OK) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Application started\n"));\r
+                               return GF_OK;\r
+               }                   \r
+           player_interf->url = "";\r
+           webkit_web_view_load_uri(player_interf->ui->pWebView, player_interf->url);\r
+           GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal]No Application found for this service ID %d \n",current_service_id));\r
+           return GF_IO_ERR;\r
+\r
+       }else{\r
+\r
+           if(!player_interf->no_url){\r
+                   GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Forced URL %s  Reaload Application \n",player_interf->url));              \r
+                    webkit_web_view_load_uri(player_interf->ui->pWebView, player_interf->url);\r
+           }else{\r
+                   GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] URL blocked by the user. \n"));                    \r
+           }\r
+           return GF_OK;\r
+       }\r
+}\r
+\r
+\r
+int hbbtvterm_scan_channel(sPlayerInterface* player_interf)\r
+{\r
+\r
+       GF_MediaInfo odi;\r
+       u32 i, count;\r
+       \r
+       HbbtvDemuxer* HbbtvDemux = (HbbtvDemuxer*)player_interf->Demuxer;\r
+\r
+       GF_ObjectManager *root_odm = gf_term_get_root_object(player_interf->m_term);\r
+       if (!root_odm){         \r
+                return GF_IO_ERR;\r
+        }\r
+\r
+       if (gf_term_get_object_info(player_interf->m_term, root_odm, &odi) != GF_OK) return GF_IO_ERR;\r
+       if (!odi.od) {  \r
+               return GF_IO_ERR;\r
+       }\r
+       count = gf_term_get_object_count(player_interf->m_term, root_odm);      \r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Count: %d \n",count));\r
+\r
+       for (i=0; i<count; i++) {               \r
+               GF_ObjectManager *odm;\r
+               odm = gf_term_get_object(player_interf->m_term, root_odm, i);\r
+               if (!odm) break;\r
+               if (gf_term_get_object_info(player_interf->m_term, odm, &odi) == GF_OK) {\r
+                       u32 service_id = odi.od->ServiceID;\r
+                       Channel* chan = (Channel*)ZapChannel(HbbtvDemux,service_id,0);\r
+                       \r
+                       if (odi.od_type==GF_STREAM_VISUAL && !chan->Get_processed()) {                          \r
+                               chan->Add_video_ID(i);\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Service: %d chan->video_index : %d \n",service_id,chan->Get_video_ID()));\r
+                       }else if(odi.od_type==GF_STREAM_AUDIO && !chan->Get_processed()) {                              \r
+                               chan->Add_audio_ID(i);\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal]Service:%d chan->current_audio_index : %d \n",service_id,chan->Get_audio_ID(0)));;\r
+                       }\r
+                       \r
+               }\r
+       }\r
+       HbbtvDemux->Channel_check();\r
+\r
+       return GF_OK;\r
+\r
+}\r
+\r
+\r
+int hbbtvterm_channel_zap(sPlayerInterface* player_interf,int up_down)\r
+{\r
+\r
+       u32 current_service_id;\r
+\r
+       current_service_id = gf_term_get_current_service_id(player_interf->m_term);\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Current_service_id : %d \n",current_service_id));\r
+       hbbtvterm_get_channel_on_air(player_interf,current_service_id,up_down);\r
+\r
+       return GF_OK;\r
+\r
+}\r
+\r
+\r
+int hbbtvterm_get_channel_on_air(sPlayerInterface* player_interf, u32 service_id, int zap)\r
+{\r
+\r
+       GF_MediaInfo odi;\r
+\r
+       HbbtvDemuxer* hbbtvdemuxer = (HbbtvDemuxer*)player_interf->Demuxer;\r
+       Channel* chan = (Channel*)ZapChannel(hbbtvdemuxer,service_id,zap);\r
+       GF_ObjectManager *root_odm = gf_term_get_root_object(player_interf->m_term);\r
+       if (!root_odm) return GF_IO_ERR;\r
+\r
+       if (gf_term_get_object_info(player_interf->m_term, root_odm, &odi) != GF_OK) return GF_IO_ERR;\r
+       if (!odi.od) {\r
+               return GF_IO_ERR;\r
+       }\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal]service_id:%d video pid : %d audio pid:%d\n",chan->Get_service_id(),chan->Get_video_ID(),chan->Get_audio_ID(0)));\r
+               \r
+       gf_term_select_object(player_interf->m_term, gf_term_get_object(player_interf->m_term, root_odm, chan->Get_video_ID()));\r
+       gf_term_select_object(player_interf->m_term, gf_term_get_object(player_interf->m_term, root_odm, chan->Get_audio_ID(0)));       \r
+               \r
+       put_app_url(player_interf);\r
+\r
+       return GF_OK;\r
+\r
+}\r
+\r
+/** On Windows Functions **/\r
+\r
+void resizevideoplayer(sPlayerInterface* player_interf, int width, int height)\r
+{\r
+       TRACEINFO;\r
+       gf_term_set_size(player_interf->m_term,width,height);\r
+       gtk_widget_set_size_request(GTK_WIDGET(player_interf->ui->pTVWindow),width,height);\r
+\r
+}\r
+\r
+void get_window_position(GtkWidget* Widget, int* x, int* y)\r
+{\r
+       //TRACEINFO;\r
+       gtk_window_get_position(GTK_WINDOW(Widget), &(*x), &(*y));\r
+}\r
+\r
+void set_window_position(GtkWidget* Widget, int x, int y)\r
+{\r
+       //~ //TRACEINFO;\r
+       gtk_window_move(GTK_WINDOW(Widget), x, y);\r
+}\r
+\r
+\r
+void OnAPPLICATION_Show()\r
+{\r
+       TRACEINFO;\r
+       gtk_window_set_opacity(GTK_WINDOW(player_interf->ui->pWebWindow),1);\r
+}\r
+\r
+void OnAPPLICATION_Hide()\r
+{\r
+       TRACEINFO;\r
+       gtk_window_set_opacity(GTK_WINDOW(player_interf->ui->pWebWindow),0);\r
+}\r
+\r
+\r
+void OnVIBRC_SetChannel(int channel_number){\r
+       //~ hbbtvterm_get_channel_on_air(player_interf, service_id, 0);\r
+}\r
+\r
+void OnKEYSET_SetValue(double param)\r
+{\r
+       TRACEINFO;\r
+       fprintf(stderr, "\t param transmitted : %i\n", (int)param);\r
+       \r
+       int     KEYMASK_RED             = 0x1;\r
+       int     KEYMASK_GREEN           = 0x2;\r
+       int     KEYMASK_YELLOW          = 0x4;\r
+       int     KEYMASK_BLUE            = 0x8;\r
+       int     KEYMASK_NAVIGATION      = 0x10;\r
+       int     KEYMASK_VCR             = 0x20;\r
+       int     KEYMASK_SCROLL          = 0x40;\r
+       int     KEYMASK_INFO            = 0x80;\r
+       int     KEYMASK_NUMERIC         = 0x100;\r
+       int     KEYMASK_ALPHA           = 0x200;\r
+       int     KEYMASK_OTHER           = 0x400;\r
+       \r
+       player_interf->keyregistered[RK_RED]        = (((int)param & KEYMASK_RED))            ? true : false;\r
+       player_interf->keyregistered[RK_GREEN]      = (((int)param & KEYMASK_GREEN))      ? true : false;\r
+       player_interf->keyregistered[RK_YELLOW]     = (((int)param & KEYMASK_YELLOW))     ? true : false;\r
+       player_interf->keyregistered[RK_BLUE]       = (((int)param & KEYMASK_BLUE))               ? true : false;\r
+       player_interf->keyregistered[RK_NAVIGATION] = (((int)param & KEYMASK_NAVIGATION)) ? true : false;\r
+       player_interf->keyregistered[RK_VCR]            = (((int)param & KEYMASK_VCR))            ? true : false;\r
+       player_interf->keyregistered[RK_SCROLL]         = (((int)param & KEYMASK_SCROLL))         ? true : false;\r
+       player_interf->keyregistered[RK_INFO]           = (((int)param & KEYMASK_INFO))           ? true : false;\r
+       player_interf->keyregistered[RK_NUMERIC]        = (((int)param & KEYMASK_NUMERIC))        ? true : false;\r
+       player_interf->keyregistered[RK_ALPHA]          = (((int)param & KEYMASK_ALPHA))      ? true : false;\r
+       player_interf->keyregistered[RK_OTHER]          = (((int)param & KEYMASK_OTHER))          ? true : false;       \r
+}\r
+\r
+void OnNoFullscreenSetWindow(int x, int y, int width, int height)\r
+{\r
+       TRACEINFO;\r
+       OnVIDBRC_SetFullScreen(false);\r
+}\r
+void OnVIDBRC_SetFullScreen(int fullscreenparam)\r
+{\r
+       TRACEINFO;\r
+       fprintf(stderr,"SET FULLSCREEN OnVIDBRC_SetFullScreen Param : %d\n",fullscreenparam);\r
+       \r
+       ///Getting the videobroadcast element.\r
+       WebKitDOMDocument *pDOMdoc  = webkit_web_view_get_dom_document(player_interf->ui->pWebView);\r
+       WebKitDOMNodeList *objectslist = webkit_dom_document_get_elements_by_tag_name(pDOMdoc,"object");\r
+       gulong l = webkit_dom_node_list_get_length(objectslist);\r
+       gulong i = 0;\r
+       bool videofound = false;\r
+       WebKitDOMNode* videonode;\r
+       char *videonodetype;    \r
+       while ((i < l) && !videofound)\r
+       {\r
+                       videonode = webkit_dom_node_list_item(objectslist,i);\r
+                       videonodetype = webkit_dom_element_get_attribute(WEBKIT_DOM_ELEMENT(videonode),"type");\r
+                       if (!(strcmp(videonodetype, "video/broadcast")))\r
+                               videofound = true;\r
+                       else\r
+                               i++;\r
+       }\r
+       \r
+       if (!videofound)\r
+       {\r
+               fprintf(stderr,"object video broadcast not found \n");\r
+               return;\r
+       }\r
+       else\r
+       {               \r
+               fprintf(stderr,"object video broadcast found \n");\r
+               WebKitDOMElement* videoelt = WEBKIT_DOM_ELEMENT(videonode);\r
+               \r
+               ///Getting the position of the WebView\r
+               gint posx, posy;\r
+               get_window_position(player_interf->ui->pWebWindow, &posx, &posy);\r
+               fprintf(stderr,"WebWindow Left : %d ,  WebWindow Top : %d \n", posx, posy);\r
+\r
+               ///Getting the videobroadcast geometry\r
+               glong left, top;\r
+               glong eltwidth, eltheight ;\r
+               ///Setting the new size and position of the TVWindow broadcast\r
+               int newx;\r
+               int newy;\r
+\r
+               if (fullscreenparam){\r
+                       left = 0;\r
+                       top = 0;\r
+                       eltwidth = HBBTV_VIDEO_WIDTH;\r
+                       eltheight = HBBTV_VIDEO_HEIGHT;\r
+                       get_window_position(player_interf->ui->pWebWindow, &newx, &newy);                       \r
+               }else{\r
+                       gtk_window_set_position(GTK_WINDOW(player_interf->ui->pTVWindow), GTK_WIN_POS_NONE);\r
+                       ///Getting the top and left values of the video/broadcast element  .\r
+                       left = webkit_dom_element_get_offset_left(videoelt);\r
+                       top = webkit_dom_element_get_offset_top(videoelt);\r
+                       ///Getting the width and height values of the video/broadcast element  .\r
+                       eltwidth = webkit_dom_element_get_offset_width(videoelt);\r
+                       eltheight = webkit_dom_element_get_offset_height(videoelt);\r
+                       newx = posx + left;\r
+                       newy = posy + top;              \r
+               }               \r
+\r
+               fprintf(stderr,"Videoelt offset : Left : %d ,  Top : %d, ", left, top);\r
+               fprintf(stderr,"EltWidth : %d ,  EltHeight : %d \n", eltwidth, eltheight);              \r
+               set_window_position(player_interf->ui->pTVWindow, newx, newy);\r
+               fprintf(stderr,"Supposed TVWindow new position : %d x %d \n", newx, newy);                              \r
+               resizevideoplayer(player_interf, eltwidth, eltheight);  \r
+               if(fullscreenparam){\r
+                       gtk_window_set_position(GTK_WINDOW(player_interf->ui->pTVWindow), GTK_WIN_POS_CENTER_ALWAYS);\r
+               }\r
+               fprintf(stderr,"Checking position : \n ");                      \r
+               gint checkx, checky;\r
+               get_window_position(player_interf->ui->pTVWindow, &checkx, &checky);\r
+               fprintf(stderr,"CHECK TVWindow Left : %d , CHECK TVWindow Top : %d \n", checkx, checky);\r
+       }\r
+                               \r
+}\r
+\r
+void OnKEYSET_Allocate()\r
+{\r
+       webkit_web_view_execute_script(player_interf->ui->pWebView, \r
+       "   var KeyEvent = new Object(); \\r
+               KeyEvent.VK_RED = 403; \\r
+               KeyEvent.VK_YELLOW = 405;\\r
+               KeyEvent.VK_GREEN = 404;\\r
+               KeyEvent.VK_BLUE = 406;\\r
+               KeyEvent.VK_UP = 38;\\r
+               KeyEvent.VK_DOWN = 40;\\r
+               KeyEvent.VK_LEFT = 37;\\r
+               KeyEvent.VK_RIGHT = 39;\\r
+               KeyEvent.VK_PLAY = 415;\\r
+               KeyEvent.VK_STOP        = 413;\\r
+               KeyEvent.VK_PAUSE = 19;\\r
+               KeyEvent.VK_FAST_FWD = 417;\\r
+               KeyEvent.VK_REWIND = 412;\\r
+               KeyEvent.VK_TELETEXT = 459;\\r
+               KeyEvent.VK_ESCAPE = 27;\\r
+               KeyEvent.VK_ENTER = 13;\\r
+               KeyEvent.VK_0 = 48;\\r
+               KeyEvent.VK_1 = 49;\\r
+               KeyEvent.VK_2 = 50;\\r
+               KeyEvent.VK_3 = 51;\\r
+               KeyEvent.VK_4 = 52;\\r
+               KeyEvent.VK_5 = 53;\\r
+               KeyEvent.VK_6 = 54;\\r
+               KeyEvent.VK_7 = 55;\\r
+               KeyEvent.VK_8 = 56;\\r
+               KeyEvent.VK_9 = 57;             ");\r
+}\r
+\r
+\r
+static void usage()\r
+{\r
+       printf("\nUsage: hbbtvterminal -input=input_data [-url=url] [-no_url]\n");\r
+       printf("-input=input_data : input data to process (dvb://, udp://, or file)\n");\r
+       printf("-url=url : force the player to connect to an url. Ignore the url(s) found in the input data\n");\r
+       printf("-no_url : the player will not connect to HBBTV services \n");\r
+       printf("-dsmcc : enable the DSMCC data carousel processing \n");\r
+}\r
+\r
+\r
+/****************************************************************************/\r
+/** getargs                                                                                                                                    */\r
+/** @author Stanislas Selle                                                                                                    */\r
+/** @date 2011/06/15                                                                                                           */\r
+/** gets args from agrv and set the options into the arguments                         */\r
+/****************************************************************************/\r
+\r
+static void getargs(int argc, char *argv[], char* &input_data, Bool* dsmcc, char* &url, Bool* no_url)\r
+{\r
+       u32 i;\r
+\r
+       no_url = 0;\r
+       i = 0;\r
+       input_data = NULL;\r
+       url = NULL;\r
+\r
+       for (i=1; i<(u32) argc; i++) {\r
+               char *arg = argv[i];\r
+               if (arg[0]=='-') {\r
+                       if (!strnicmp(arg, "-input=", 7)) {\r
+                               input_data = arg+7;\r
+                       }else if (!strnicmp(arg, "-url=", 5)) {\r
+                                       url = arg+5;\r
+                       }else if (!strnicmp(arg, "-no_url", 7)) {\r
+                                               *no_url = 1;\r
+                       }else if (!strnicmp(arg, "-dsmcc", 6)) {                                                \r
+                                               *dsmcc = 1;\r
+                       }else {\r
+                               usage();\r
+                               exit(0);\r
+                       }                       \r
+               }else {\r
+                       usage();\r
+                       exit(0);\r
+               }\r
+       }\r
+\r
+       if( !input_data && (!url || *no_url)) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Input data is  needed if no URL is given.\n"));\r
+               usage();\r
+               exit(0);\r
+       }\r
+       if( !*dsmcc) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Ignoring DSMCC data !! \n"));\r
+       }\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Starting the processing of the TS file %s \n",input_data));\r
+\r
+}\r
+\r
+int main (int argc, char* argv[])\r
+{\r
+       char* input_data;\r
+       char* url;\r
+       Bool dsmcc;\r
+       Bool no_url;\r
+       int Error;\r
+\r
+       dsmcc = no_url = 0;\r
+\r
+       url = input_data = NULL;\r
+\r
+       //TRACEINFO;\r
+       gf_sys_init(1);\r
+       gf_log_set_tool_level(GF_LOG_MODULE,GF_LOG_INFO);\r
+       printf("GPAC HBBTV Terminal (c) Telecom ParisTech 2011\n");     \r
+\r
+       getargs(argc, argv, input_data , &dsmcc, url, &no_url);\r
+\r
+       GF_SAFEALLOC(player_interf, sPlayerInterface);\r
+\r
+       HbbtvDemuxer* hbbtv_demuxer = new HbbtvDemuxer(input_data, url,dsmcc, no_url, player_interf);\r
+\r
+       gtk_init(&argc, &argv);\r
+\r
+       if (!g_thread_supported()) {\r
+               g_thread_init(NULL);\r
+       }\r
+\r
+       Error = init_playerinterface(player_interf,input_data,url,no_url);\r
+       if(Error){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[HBBTVTerminal] Error - Aborting the processing \n"));\r
+               return 0;\r
+       }\r
+       //~ gf_term_set_option(player_interf->m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);\r
+\r
+       gtk_main();\r
+       //free(ui);\r
+}\r
+\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.h b/applications/hbbtvplayer/hbbtvterminal/src/hbbtvterminal.h
new file mode 100644 (file)
index 0000000..a258002
--- /dev/null
@@ -0,0 +1,350 @@
+/*\r
+ *             Copyright (c) 2010-2011 Telecom-Paristech\r
+ *                 All Rights Reserved\r
+ *     GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ *             Authors: Stanislas Selle - Jonathan Sillan              \r
+ *                             \r
+ */\r
+\r
+#ifndef __HBBTVTERMINAL__\r
+#define __HBBTVTERMINAL__\r
+\r
+#define _WIN32_WINNT 0x0510 \r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+#include <gpac/configuration.h>\r
+#include <gpac/mpegts.h>\r
+#include <gpac/tools.h>\r
+#include <gpac/events.h>\r
+#include <gpac/options.h>\r
+#include <gpac/terminal.h>\r
+#include <gpac/internal/terminal_dev.h>\r
+#include <gpac/term_info.h>\r
+#include <hbbtvbrowserpluginapi.h>\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#include <iostream>\r
+\r
+#include <webkit/webkit.h>\r
+#include <webkit/WebKitDOMUIEvent.h>\r
+#include <gtk/gtk.h>\r
+#include <gdk/gdkkeysyms.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define DEBUG  true\r
+#define PROJECTNAME "HbbTVTerminal"\r
+#define TRACEINFO if (DEBUG) { fprintf(stderr, " BOB \x1b[%i;3%im%s\x1b[0m : call %s\n", 1, 4, PROJECTNAME, __FUNCTION__); }\r
+#define NOTIMPLEMENTED if (DEBUG) { printf("SEGAR %s :  %s is NOT IMPLEMENTED : TODO \n", PROJECTNAME, __FUNCTION__); }\r
+\r
+#define TRANSPARENCE true\r
+\r
+#define HBBTV_VIDEO_WIDTH 1280\r
+#define HBBTV_VIDEO_HEIGHT 720\r
+\r
+typedef struct GraphicInterface\r
+{\r
+    WebKitWebView      *pWebView;\r
+    GtkWidget       *pTVView;\r
+    GtkWidget       *pBackgroundView;\r
+    GtkWidget       *pMainWindow;\r
+    GtkWidget       *pTVWindow;\r
+    GtkWidget       *pWebWindow;\r
+    GtkWidget       *pBackgroundWindow;\r
+    GtkWidget          *pEntry;\r
+} sGraphicInterface;\r
+\r
+\r
+enum listHBBTVKeys{\r
+       HBBTV_VK_ENTER  = 13,\r
+       HBBTV_VK_PAUSE  = 19,\r
+       HBBTV_VK_ESCAPE = 27,\r
+       HBBTV_VK_LEFT           = 37,\r
+       HBBTV_VK_RIGHT  = 39,\r
+       HBBTV_VK_UP             = 38,\r
+       HBBTV_VK_DOWN           = 40,\r
+       HBBTV_VK_0              = 48,\r
+       HBBTV_VK_1              = 49,\r
+       HBBTV_VK_2              = 50,\r
+       HBBTV_VK_3              = 51,\r
+       HBBTV_VK_4              = 52,\r
+       HBBTV_VK_5              = 53,\r
+       HBBTV_VK_6              = 54,\r
+       HBBTV_VK_7              = 55,\r
+       HBBTV_VK_8              = 56,\r
+       HBBTV_VK_9              = 57,\r
+       HBBTV_VK_RED            = 403,\r
+       HBBTV_VK_YELLOW = 405,\r
+       HBBTV_VK_GREEN  = 404,\r
+       HBBTV_VK_BLUE           = 406,\r
+       HBBTV_VK_REWIND = 412,\r
+       HBBTV_VK_STOP           = 413,\r
+       HBBTV_VK_PLAY           = 415,\r
+       HBBTV_VK_FAST_FWD       = 417,  \r
+       HBBTV_VK_TELETEXT = 459\r
+};\r
+\r
+\r
+enum listRegisteredKeys {\r
+       RK_OTHER =       0,\r
+       RK_RED =                 1,\r
+       RK_GREEN =               2,\r
+       RK_YELLOW =              3,\r
+       RK_BLUE =                4,\r
+       RK_NAVIGATION =  5,\r
+       RK_VCR =                 6,     \r
+       RK_SCROLL =              7,\r
+       RK_INFO =                8,\r
+       RK_NUMERIC =     9,\r
+       RK_ALPHA =              10      \r
+};\r
+\r
+typedef struct PlayerInterface\r
+{\r
+    sGraphicInterface* ui;\r
+    Bool no_url;\r
+    char* input_data;\r
+    char* url;\r
+    GF_Terminal *m_term;\r
+    GF_User *m_user;\r
+    void* Demuxer;\r
+    GF_Mutex *Get_demux_info_mutex;\r
+    int TVwake;\r
+    Bool keyregistered[11];\r
+    Bool init;\r
+    Bool is_connected;\r
+    Bool app_in_action;\r
+\r
+} sPlayerInterface;\r
+\r
+int ui_init(sGraphicInterface *ui);\r
+\r
+int init_gpac(sPlayerInterface* player_interf);\r
+int init_browser(sPlayerInterface* player_interf);\r
+int stop_gpac(sPlayerInterface *player_interf);\r
+int playpause(sPlayerInterface *player_interf);\r
+int term_play(sPlayerInterface *player_interf);\r
+int term_pause(sPlayerInterface *player_interf);\r
+int init_player(sPlayerInterface* player_interf);\r
+\r
+\r
+typedef struct\r
+{\r
+       GF_M2TS_AIT* ait;\r
+\r
+       char* data;\r
+       u32 table_id;\r
+       u32 data_size;\r
+} AIT_TO_PROCESS;\r
+\r
+\r
+typedef struct\r
+{\r
+       GF_M2TS_DSMCC_SECTION* dsmcc_sections;\r
+       char* buff;\r
+\r
+       /*added not in the spec*/\r
+       u8 first_section_received;\r
+}GF_M2TS_GATHER_DSMCC_SECTION;\r
+\r
+#define MAX_audio_index 16\r
+\r
+class Channel\r
+{\r
+public:\r
+    /* Constructor */\r
+    Channel(u32 TSservice_ID, char* TSchannel_name);\r
+    /* Destructor */\r
+    void Destroy_Channel();\r
+    /* Fonctions */\r
+    u32 Add_service_id(u32 service_id);\r
+    u32 Add_channel_name(char* chan_name);\r
+    u32 Add_video_ID(u32 video_index);\r
+    u32 Add_audio_ID(u32 current_audio_index);\r
+    u32 Add_ait_pid(u32 ait_pid);\r
+    u32 Add_pmt_pid(u32 pmt_pid);\r
+    u32 Add_App_info(GF_M2TS_CHANNEL_APPLICATION_INFO*add_ait);\r
+    void Check_Info_Done();\r
+    void Incr_audio_index(int index);\r
+    void Set_audio_index(u32 index);\r
+    /* Getter */\r
+    u32 Get_service_id();\r
+    char* Get_channel_name();\r
+    u32 Get_video_ID();\r
+    u32 Get_audio_ID(u32 indice);\r
+    u32 Get_ait_pid();\r
+    u32 Get_pmt_pid();\r
+    Bool Get_processed();\r
+    u32 Get_audio_index();\r
+    u32 Get_nb_chan_audio_stream();\r
+    GF_M2TS_CHANNEL_APPLICATION_INFO* Get_App_info();\r
+    GF_M2TS_AIT_APPLICATION* App_to_play(Bool isConnected,u8 MaxPriority);\r
+       GF_M2TS_AIT_APPLICATION* Get_App(u32 application_id);\r
+\r
+private:\r
+    u32 service_ID;\r
+    u32 number;\r
+    char* channel_name;\r
+    u32 video_ID;\r
+    u32 audio_ID[MAX_audio_index];\r
+    u32 AIT_PID;\r
+    u32 PMT_PID;\r
+    Bool processed;\r
+    u32 current_audio_index;\r
+    u32 nb_chan_audio_stream;\r
+    GF_M2TS_CHANNEL_APPLICATION_INFO* ChannelApp; \r
+\r
+};\r
+\r
+class HbbtvDemuxer\r
+{\r
+public:\r
+       /* Constructeur */\r
+       HbbtvDemuxer(char *input_data, char* url,  Bool dsmcc, Bool no_url,sPlayerInterface* player_interf);\r
+\r
+       /* Destructeur */\r
+\r
+       /* Fonction */\r
+       u32 HbbtvDemuxer_DemuxStart();\r
+       Bool ait_already_received(char *data,u32 pid);\r
+       void GetAppInfoFromAit(GF_M2TS_AIT* ait);\r
+       Channel* Zap_channel(u32 service_id,int zap);\r
+       void Create_Channel(GF_M2TS_Program* pmt);\r
+       void Check_PMT_Processing();\r
+       void Channel_check();\r
+       u32 Check_application_priority(Channel* chan, GF_M2TS_AIT* ait);\r
+       /* Getter */\r
+       GF_M2TS_Demuxer* Get_Ts();      \r
+       GF_List* Get_ChannelList();\r
+       GF_List* Get_AIT_To_Process_list();\r
+       char* Get_Input_data();\r
+       Bool Get_if_dsmcc_process();\r
+       GF_Thread * Get_Demux_Thread();\r
+       GF_Mutex * Get_Demux_Mutex();\r
+       void* Get_User();\r
+       int Check_all_channel_info_received(int Timer);\r
+       char* Get_Force_URL();\r
+       Bool Get_Ignore_TS_URL();\r
+       Bool Get_ait_to_proces();\r
+       Channel* Get_Channel(u32 service_id);\r
+       GF_Err Get_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO*app_info);\r
+       /* Setter */\r
+       void Set_Ts(GF_M2TS_Demuxer* ts);\r
+       void Set_ait_to_process(Bool on);       \r
+\r
+private:\r
+       /* Fonction */\r
+\r
+       u32 GetDemuxStartFunction();    \r
+\r
+       /* Attribut */\r
+       GF_M2TS_Demuxer *Demuxts;\r
+       GF_List* Channels;\r
+       GF_List* Ait_To_Process;\r
+\r
+       /* Thread for Demux */\r
+       GF_Thread *ts_demux_thread;\r
+       /* Mutex for Demux */\r
+       GF_Mutex *ts_demux_mutex;\r
+\r
+       /*local file playing*/\r
+       char *Input_data;\r
+       char *Service_URL;\r
+       char *Force_URL;\r
+       Bool process_dsmcc;\r
+       Bool Ignore_TS_URL;\r
+       Bool No_URL;\r
+       u32 nb_ait;\r
+       u32 file_size;\r
+       Bool ait_to_process;\r
+       u32 nb_prog_pmt_received;\r
+       Bool all_prog_pmt_received;\r
+\r
+       /*callback to push AIT information when a AIT is received*/\r
+       void (*on_ait_event)(void *player_interf, GF_M2TS_CHANNEL_APPLICATION_INFO*app_info);\r
+       /*private user data - To the PlayerInterface*/\r
+       void *user;\r
+\r
+};\r
+\r
+\r
+/* Global Functions */\r
+\r
+u32 On_hbbtv_received_section(void *ptr, GF_Event *event);\r
+u32 DemuxThreadStart(HbbtvDemuxer *hbbtv_demuxer);\r
+u32 DemuxStart(void *par);\r
+GF_Err get_app_url(sPlayerInterface* player_interf, GF_M2TS_CHANNEL_APPLICATION_INFO*app_info);\r
+int put_app_url(sPlayerInterface* player_interf);\r
+u32 Get_application_for_channel(HbbtvDemuxer* hbbtv_demuxer,u32 service_id);\r
+\r
+int change_geometry( int width, int height);\r
+int hbbtvterm_scan_channel(sPlayerInterface* player_interf);\r
+Channel* ZapChannel(HbbtvDemuxer *hbbtv_demuxer,u32 service_id,int zap);\r
+int hbbtvterm_channel_zap(sPlayerInterface* player_interf,int up_down);\r
+int hbbtvterm_get_channel_on_air(sPlayerInterface* player_interf, u32 service_id, int zap);\r
+void resizevideoplayer(sPlayerInterface* player_interf, int width, int height);\r
+\r
+void get_window_position(GtkWidget* Widget, int* x, int* y);\r
+void set_window_position(GtkWidget* Widget, int x, int y);\r
+\r
+GF_Config* check_config_file();\r
+Bool is_connected();\r
+\r
+/* HBBTV Functions */\r
+\r
+\r
+/* HBBTV Button */\r
+void on_redbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_greenbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_yellowbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_bluebuttonclicked(GtkWidget *widget, gpointer data);\r
+\r
+/*Navigation */\r
+void  on_upbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_downbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_leftbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_rightbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_returnbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_exitbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_2buttonclicked(GtkWidget *widget, gpointer data);\r
+\r
+/* Control */\r
+void on_onoffbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_playpausebuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_playbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_pausebuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_langbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_chanupbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_chandownbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_channelbuttonclicked(GtkWidget *widget, gpointer data);\r
+void on_teletextbuttonclicked(GtkWidget *widget, gpointer data);\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // __HBBTVTERMINAL__\r
diff --git a/applications/hbbtvplayer/hbbtvterminal/src/makefile.am b/applications/hbbtvplayer/hbbtvterminal/src/makefile.am
new file mode 100644 (file)
index 0000000..65c35f3
--- /dev/null
@@ -0,0 +1,25 @@
+###########################################################################################
+##
+## Copyright 2011 Telecom Paristech 
+## Author : Stanislas Selle 
+##
+###########################################################################################
+
+bin_PROGRAMS = hbbtvterminal
+hbbtvterminal_SOURCES =  hbbtvterminal.cpp hbbtv_demux.cpp hbbtv_channel.cpp hbbtv_keycontrol.cpp hbbtv_tools.cpp hbbtvterminal.h
+
+SPECIALCFLAGS =  -g -DXP_UNIX=1 -DMOZ_X11=1 -fPIC
+
+hbbtvterminal_CPPFLAGS = $(SPECIALCFLAGS) $(HBBTVBROWSERPLUGIN_CFLAGS) $(GLIB_CFLAGS) $(GTK_CFLAGS) $(WEBKIT_CFLAGS) $(PIXMAN_CFLAGS) $(NPAPI_CFLAGS)\
+       -g -DXP_UNIX -fPIC \
+       -I /usr/include\
+       -I /usr/include/gpac/\
+       -I /usr/local/include\
+       -I /usr/local/include/gpac/
+
+
+hbbtvterminal_LDFLAGS =        $(SPECIALCFLAGS)
+
+hbbtvterminal_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(WEBKIT_LIBS) $(PIXMAN_LIBS) $(NPAPI_LIBS) $(MOZILLAJS_LIBS) $(HBBTVBROWSERPLUGIN_LIBS) \
+                               -L/usr/local/lib -lgpac
+
diff --git a/applications/hbbtvplayer/install.sh b/applications/hbbtvplayer/install.sh
new file mode 100644 (file)
index 0000000..a5c9883
--- /dev/null
@@ -0,0 +1,78 @@
+#!/bin/sh -e
+
+PLAYER=0
+DEPENDENCIES=0
+WEBKIT=0
+GPAC=0  
+
+if [ -z $1 ] ; then
+       echo "\nUsage: You must choose options :"
+       echo "\n\033[31m full - build the whole package (gpac+webkit+hbbtvplayer) Recommanded for computer without gpac \033[0m"
+       echo "\n\033[32m player - build the HBBTV player \033[0m"
+       echo "\n\033[33m webkit - download Webkit sources and install it\033[0m"
+       echo "\n\033[33m gpac - download gpac sources and install it\033[0m"
+       echo "\n\033[34m dependencies - get the dependencies needed to build the HBBTVPlayer \033[0m"
+       exit 1
+fi
+
+for i in $* ; do
+       if [ "$i" = "full" ] ; then 
+               echo -e "\033[31m Usage: $0 Full Building : Activated \033[0m" 
+               PLAYER=1
+               DEPENDENCIES=1
+               WEBKIT=1
+               GPAC=1  
+       fi
+
+       if [ "$i" = "player" ] ; then 
+               echo -e "\033[32m Usage: $0 Player Building : Activated \033[0m" 
+               PLAYER=1
+       fi
+
+       if [ "$i" = "dependencies" ] ; then 
+               echo -e "\033[34m Usage: $0 Dependecies Building : Activated \033[0m" 
+               DEPENDENCIES=1
+       fi
+
+       if [ "$i" = "webkit" ] ; then 
+               echo -e "\033[33m Usage: $0 Webkit Building : Activated \033[0m" 
+               WEBKIT=1 
+       fi
+
+       if [ "$i" = "gpac" ] ; then 
+               echo -e "\033[33m Usage: $0 gpac Building : Activated \033[0m" 
+               WEBKIT=1 
+       fi
+done
+
+if [ $DEPENDENCIES -eq 1 ] ; then
+       sudo apt-get install `cat listdependencies`
+fi
+
+if [ $GPAC -eq 1 ] ; then
+       cd gpac
+       ./configure --use-js=no
+       make -j2
+       sudo make install
+       sudo make install-lib
+       cd ..
+fi
+
+if [ $WEBKIT -eq 1 ] ; then
+       ./WebKit/Tools/Scripts/build-webkit --gtk --with-gtk=2.0 --no-webkit2 --makeargs="-j2 install"
+fi
+
+
+if [ $PLAYER -eq 1 ] ; then
+       cd hbbtvbrowserplugin
+       ./autogen.sh
+       sudo make install
+       cd ..
+
+       cd hbbtvterminal
+       ./autogen.sh
+       sudo make install
+       cd ..
+fi
+
+
diff --git a/applications/hbbtvplayer/listdependencies b/applications/hbbtvplayer/listdependencies
new file mode 100644 (file)
index 0000000..58c74a3
--- /dev/null
@@ -0,0 +1,79 @@
+autoconf
+automake
+autotools-dev
+bison
+build-essential
+dvb-apps
+flex
+gail-3.0
+glib-networking
+gperf
+gtk-doc-tools
+liba52-0.7.4-dev
+libasound2-dev
+libatk1.0-0
+libavcodec52
+libavcodec-dev
+libavformat52
+libavformat-dev
+libavutil-dev
+libc6
+libcairo2
+libenchant1c2a
+libenchant-dev
+libfaad2
+libfaad-dev
+libfontconfig1
+libfreetype6
+libfreetype6-dev
+libgail18
+libgail-3-dev
+libgail-dev
+libgcc1
+libgdk-pixbuf2.0-0
+libgl1-mesa-dev
+libglib2.0-0
+libglib2.0-dev
+libgpac0.4.5
+libgstreamer0.10-0
+libgstreamer-plugins-base0.10-0
+libgtk2.0-dev
+libicu44
+libjpeg62-dev
+libmad0-dev
+libogg-dev
+libopenjpeg-dev
+libpango1.0-0
+libpng12-dev
+libpulse-dev
+libsdl1.2debian
+libsdl1.2-dev
+libsoup2.4-dev
+libsqlite3-dev
+libssl-dev
+libstdc++6
+libswscale-dev
+libtheora-dev
+libtool
+libvorbis-dev
+libwxbase2.8-dev
+libwxgtk2.8-dev
+libx11-6
+libxml2
+libxslt-dev
+libxt6
+libxv-dev
+libxvidcore-dev
+linux-sound-base
+subversion
+wx2.8-headers
+x11proto-gl-dev
+x11proto-video-dev
+xulrunner-2.0-dev
+zlib1g-dev
+libgeoclue-dev
+icu-doc
+libicu-dev
+libgstreamer0.10-dev
+libgstreamer-plugins-base0.10-dev
+
diff --git a/applications/hbbtvplayer/projectmanager/codeblocks/hbbtvplayer.workspace b/applications/hbbtvplayer/projectmanager/codeblocks/hbbtvplayer.workspace
new file mode 100644 (file)
index 0000000..ab6eb5a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_file>
+       <Workspace title="Workspace">
+               <Project filename="../../hbbtvterminal/projectmanager/codeblocks/hbbtvterminal/HbbtvTerminal.cbp" active="1" />
+               <Project filename="../../hbbtvbrowserplugin/projectmanager/codeblocks/hbbtvbrowserplugin/hbbtvbrowserplugin.cbp" />
+       </Workspace>
+</CodeBlocks_workspace_file>
diff --git a/applications/m3u82mpd/m3u82mpd.vcproj b/applications/m3u82mpd/m3u82mpd.vcproj
new file mode 100644 (file)
index 0000000..1887aca
--- /dev/null
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8,00"\r
+       Name="m3u82mpd"\r
+       ProjectGUID="{91DD3CA8-5C56-4B02-B11C-6FDC373B99DA}"\r
+       RootNamespace="m3u82mpd"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../../include"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="../../bin/$(PlatformName)/$(ConfigurationName)/m3u82mpd.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               AdditionalIncludeDirectories="../../include"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="../../bin/$(PlatformName)/$(ConfigurationName)/m3u82mpd.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="true"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <File\r
+                       RelativePath=".\main.c"\r
+                       >\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index 114c4d4b1067ac2e79f1b134a7f51e7046dc99f3..cb8c8e21a2f526772a23334c10bb239021ac430b 100644 (file)
  *
  */
 
-#include "../modules/mpd_in/m3u8.h"
+
+#include <gpac/internal/m3u8.h>
 #include <gpac/network.h>
 #include <gpac/download.h>
 
+
 int main(int argc, char **argv)
 {
-    GF_Err e;
-    VariantPlaylist * pl = NULL;
-    char *url = argv[1];
-    char *cache_m3u8_file;
+       GF_Err e;
+       VariantPlaylist * pl = NULL;
+       char *url = argv[1];
+       //char *cache_m3u8_file;
        u32 i, count;
-    FILE *fmpd;
-    Bool verbose = 0;
-    u32 update_interval = 0;
-    char *m3u8_local_name = "file.m3u8";
-    Bool is_local = 0;
+       FILE *fmpd;
+       Bool verbose = 0;
+       u32 update_interval = 0;
+       char *m3u8_local_name = "file.m3u8";
+       Bool is_local = 0;
 
-    gf_sys_init(0);
+       gf_sys_init(0);
 
-       gf_log_set_level(verbose ? GF_LOG_DEBUG : GF_LOG_INFO);
-       gf_log_set_tools(GF_LOG_NETWORK);
+       gf_log_set_tool_level(GF_LOG_NETWORK, verbose ? GF_LOG_DEBUG : GF_LOG_INFO);
 
-    while (1) {
+       while (1) {
 
-        if (gf_url_is_local(url)) {
-            m3u8_local_name = url;
-            is_local = 1;
-        } else {
-            e = gf_dm_wget(url, m3u8_local_name);
-            if (e != GF_OK) return -1;
-        }
+               if (gf_url_is_local(url)) {
+                       m3u8_local_name = url;
+                       is_local = 1;
+               } else {
+                       e = gf_dm_wget(url, m3u8_local_name);
+                       if (e != GF_OK) return -1;
+               }
 
-        e = parse_root_playlist(m3u8_local_name, &pl, ".");
-        if (e != GF_OK) return -1;
-        
-        fmpd = fopen(argv[2], "wt");
-        
-        fprintf(fmpd, "<MPD type=\"Live\" xmlns=\"urn:3GPP:ns:PSS:AdaptiveHTTPStreamingMPD:2009\">\n");
-        fprintf(fmpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
-        fprintf(fmpd, "  <Title>Media Presentation Description for file %s</Title>\n", url);
-        fprintf(fmpd, "  <Source>Generated by GPAC %s</Source>\n", GPAC_FULL_VERSION);
+               e = parse_root_playlist(m3u8_local_name, &pl, ".");
+               if (e != GF_OK) return -1;
+               
+               fmpd = fopen(argv[2], "wt");
+               
+               fprintf(fmpd, "<MPD type=\"Live\" xmlns=\"urn:3GPP:ns:PSS:AdaptiveHTTPStreamingMPD:2009\">\n");
+               fprintf(fmpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
+               fprintf(fmpd, "  <Title>Media Presentation Description for file %s</Title>\n", url);
+               fprintf(fmpd, "  <Source>Generated by GPAC %s</Source>\n", GPAC_FULL_VERSION);
 
-        fprintf(fmpd, " </ProgramInformation>\n");
-        fprintf(fmpd, " <Period start=\"PT0S\">\n");   
+               fprintf(fmpd, " </ProgramInformation>\n");
+               fprintf(fmpd, " <Period start=\"PT0S\">\n");    
 
-        count = gf_list_count(pl->programs);
-        for (i=0; i<count; i++) {
-               u32 j, count2;
-            Program *prog = gf_list_get(pl->programs, i);
-            count2 = gf_list_count(prog->bitrates);
-            for (j = 0; j<count2; j++) {
-                PlaylistElement *pe = gf_list_get(prog->bitrates, j);
-                fprintf(stdout, "%d, %d, %s, %s, %d\n", pe->durationInfo, pe->bandwidth, pe->title, pe->url, pe->elementType);
-                if (pe->elementType == TYPE_PLAYLIST) {
-                    u32 k, count3;
-                    char *tmp;
-                    char c;
-                    char baseURL[GF_MAX_PATH]; 
-                    tmp = strrchr(url, '/');
-                    tmp++;
-                    c = tmp[0];
-                    tmp[0] = 0;
-                    strcpy(baseURL, url);
-                    tmp[0] = c;
-                       fprintf(fmpd, "  <Representation mimeType=\"video/mp2t\">\n");  
-                       fprintf(fmpd, "   <SegmentInfo duration=\"PT%dS\" baseURL=\"%s\">\n", pe->durationInfo, baseURL);       
-                    count3 = gf_list_count(pe->element.playlist.elements);
-                    update_interval = (count3 - 1) * pe->durationInfo * 1000;
-                    for (k=0; k<count3; k++) {
-                        PlaylistElement *elt = gf_list_get(pe->element.playlist.elements, k);
-                        if (k) fprintf(fmpd, "    <Url sourceURL=\"%s\"/>\n", elt->url);       
-                        else fprintf(fmpd, "    <InitialisationSegmentURL sourceURL=\"%s\"/>\n", elt->url);    
-                    }
-                    fprintf(fmpd, "   </SegmentInfo>\n");
-                    fprintf(fmpd, "  </Representation>\n");
-                } else if (pe->elementType == TYPE_STREAM) {
-                    fprintf(stdout, "Stream\n");
-                }
-            }
-        }
-        fprintf(fmpd, " </Period>\n");
-        fprintf(fmpd, "</MPD>");
-        fclose(fmpd);
-        variant_playlist_del(pl);
-        if (is_local) break;
-        gf_sleep(update_interval);
-        
-    }
+               count = gf_list_count(pl->programs);
+               for (i=0; i<count; i++) {
+                       u32 j, count2;
+                       Program *prog = gf_list_get(pl->programs, i);
+                       count2 = gf_list_count(prog->bitrates);
+                       for (j = 0; j<count2; j++) {
+                               PlaylistElement *pe = gf_list_get(prog->bitrates, j);
+                               fprintf(stdout, "%d, %d, %s, %s, %d\n", pe->durationInfo, pe->bandwidth, pe->title, pe->url, pe->elementType);
+                               if (pe->elementType == TYPE_PLAYLIST) {
+                                       u32 k, count3;
+                                       char *tmp;
+                                       char c;
+                                       char baseURL[GF_MAX_PATH]; 
+                                       tmp = strrchr(url, '/');
+                                       if (tmp) {
+                                               tmp++;
+                                               c = tmp[0];
+                                               tmp[0] = 0;
+                                               strcpy(baseURL, url);
+                                               tmp[0] = c;
+                                       } else {
+                                               baseURL[0] = 0;
+                                       }
+                                       fprintf(fmpd, "  <Representation mimeType=\"video/mp2t\">\n");  
+                                       fprintf(fmpd, "   <SegmentInfo duration=\"PT%dS\"", pe->durationInfo);  
+                                       if (baseURL[0]) fprintf(fmpd, "baseURL=\"%s\"", baseURL);       
+                                       fprintf(fmpd, ">\n");   
+                                       count3 = gf_list_count(pe->element.playlist.elements);
+                                       update_interval = (count3 - 1) * pe->durationInfo * 1000;
+                                       for (k=0; k<count3; k++) {
+                                               PlaylistElement *elt = gf_list_get(pe->element.playlist.elements, k);
+                                               if (k) fprintf(fmpd, "    <Url sourceURL=\"%s\"/>\n", elt->url);        
+                                               else fprintf(fmpd, "    <InitialisationSegmentURL sourceURL=\"%s\"/>\n", elt->url);     
+                                       }
+                                       fprintf(fmpd, "   </SegmentInfo>\n");
+                                       fprintf(fmpd, "  </Representation>\n");
+                               } else if (pe->elementType == TYPE_STREAM) {
+                                       fprintf(stdout, "Stream\n");
+                               }
+                       }
+               }
+               fprintf(fmpd, " </Period>\n");
+               fprintf(fmpd, "</MPD>");
+               fclose(fmpd);
+               variant_playlist_del(pl);
+               if (is_local) break;
+               gf_sleep(update_interval);
+       }
 
-    gf_sys_close();
-    return 0;
+       gf_sys_close();
+       return 0;
 }
index ad7def4551d2559fe84e32de31a217698fc1531e..dd31812597f900eea94d58e0bb89c00a7d496416 100644 (file)
@@ -164,17 +164,17 @@ void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num)
        fi.biSizeImage = fb->pitch * fb->height;
 
        /*NOT ALIGNED!!*/
-    fwrite(&fh.bfType, 2, 1, fout);
-    fwrite(&fh.bfSize, 4, 1, fout);
-    fwrite(&fh.bfReserved1, 2, 1, fout);
-    fwrite(&fh.bfReserved2, 2, 1, fout);
-    fwrite(&fh.bfOffBits, 4, 1, fout);
+    gf_fwrite(&fh.bfType, 2, 1, fout);
+    gf_fwrite(&fh.bfSize, 4, 1, fout);
+    gf_fwrite(&fh.bfReserved1, 2, 1, fout);
+    gf_fwrite(&fh.bfReserved2, 2, 1, fout);
+    gf_fwrite(&fh.bfOffBits, 4, 1, fout);
 
-       fwrite(&fi, 1, 40, fout);
+       gf_fwrite(&fi, 1, 40, fout);
 
        for (j=fb->height; j>0; j--) {
                ptr = fb->video_buffer + (j-1)*fb->pitch;
-               //fwrite(ptr, 1, fb->width  * 3, fout);
+               //gf_fwrite(ptr, 1, fb->width  * 3, fout);
                for (i=0;i<fb->width; i++) {
                        fputc(ptr[2], fout);
                        fputc(ptr[1], fout);
@@ -201,7 +201,7 @@ void write_raw(GF_VideoSurface *fb, char *rad_name, u32 img_num)
 
        fout = fopen(str, "wb");
        if (!fout) return;
-       fwrite(fb->video_buffer , fb->height*fb->pitch, 1, fout);
+       gf_fwrite(fb->video_buffer , fb->height*fb->pitch, 1, fout);
        fclose(fout);
 }
 
index 4f9261a2c75dc6df98563c5812f39ea8ddca866b..dc4a10ac14a1a9e49e4796b59ff9b6efb6e3adf9 100644 (file)
@@ -52,7 +52,8 @@ static GFINLINE void usage(const char * progname)
                                        "\t-psi-rate=V            sets PSI refresh rate V in ms (default 100ms). If 0, PSI data is only send once at the begining\n"
                                        "\t-time=n                request the program to stop after n ms\n"
                                        "\t-single-au             forces 1 PES = 1 AU (disabled by default)\n"
-
+                                       "\t-rap                   forces RAP/IDR to be aligned with PES start for video streams (disabled by default)\n"
+                                       "                          in this mode, PAT, PMT and PCR will be inserted before the first TS packet of the RAP PES\n"
                                        "\t-prog=filename         specifies an input file used for a TS service\n"
                                        "\t                        * currently only supports ISO files and SDP files\n"
                                        "\t                        * can be used several times, once for each program\n"
@@ -76,9 +77,8 @@ static GFINLINE void usage(const char * progname)
                     "\t-bifs-pes              carries BIFS over PES instead of sections\n"
                     "\t-bifs-pes-ex           carries BIFS over PES without writing timestamps in SL\n"
                                        "\t\n"
-                                       "\t-ll=LogLevel           specifies log level to use (by default error)\n"
-                                       "\t-lt=LogTools           specifies log tools to use (by default all)\n"
-                                       "\t-h or -help             Print this screen\n"
+                                       "\t-logs                  set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
+                                       "\t-h or -help            print this screen\n"
                                        "\n", progname, DEFAULT_PCR_OFFSET
                );
 }
@@ -166,7 +166,9 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                if (!priv->sample) 
                        priv->sample = gf_isom_get_sample(priv->mp4, priv->track, priv->sample_number+1, NULL);
 
-               if (!priv->sample) return GF_IO_ERR;
+               if (!priv->sample) {
+                       return GF_IO_ERR;
+               }
 
                pck.flags = 0;
                pck.flags = GF_ESI_DATA_AU_START | GF_ESI_DATA_HAS_CTS;
@@ -184,14 +186,6 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                        pck.flags |= GF_ESI_DATA_HAS_DTS;
                }
 
-               if (priv->sample->IsRAP && priv->dsi && priv->dsi_size) {
-                       pck.data = priv->dsi;
-                       pck.data_len = priv->dsi_size;
-                       ifce->output_ctrl(ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &pck);
-                       pck.flags = 0;
-               }
-
-
                if (priv->nalu_size) {
                        Bool nalu_delim_sent = 0;
                        u32 remain = priv->sample->dataLength;
@@ -224,15 +218,23 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                                        pck.data_len = 6;
                                        ifce->output_ctrl(ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &pck);
                                        pck.flags &= ~GF_ESI_DATA_AU_START;
-                               }
 
+                                       /*and send SPD / PPS if RAP - it is not clear in the specs whether SPS/PPS should be inserted after
+                                       the AU delimiter NALU*/
+                                       if (priv->sample->IsRAP && priv->dsi && priv->dsi_size) {
+                                               pck.data = priv->dsi;
+                                               pck.data_len = priv->dsi_size;
+                                               ifce->output_ctrl(ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &pck);
+                                               pck.flags &= ~GF_ESI_DATA_AU_START;
+                                       }
+                               }
 
                                pck.data = sc;
                                pck.data_len = 4;
                                ifce->output_ctrl(ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &pck);
 
                                if (!remain) pck.flags |= GF_ESI_DATA_AU_END;
-                                       pck.flags &= ~GF_ESI_DATA_AU_START;
+                               pck.flags &= ~GF_ESI_DATA_AU_START;
 
                                pck.data = ptr;
                                pck.data_len = size;
@@ -241,6 +243,14 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                        }
 
                } else {
+
+                       if (priv->sample->IsRAP && priv->dsi && priv->dsi_size) {
+                               pck.data = priv->dsi;
+                               pck.data_len = priv->dsi_size;
+                               ifce->output_ctrl(ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &pck);
+                               pck.flags &= ~GF_ESI_DATA_AU_START;
+                       }
+
                        pck.flags |= GF_ESI_DATA_AU_END;
                        pck.data = priv->sample->data;
                        pck.data_len = priv->sample->dataLength;
@@ -1418,7 +1428,7 @@ static GFINLINE GF_Err parse_args(int argc, char **argv, u32 *mux_rate, u32 *car
                                                                  Bool *real_time, u32 *run_time, char **video_buffer, u32 *video_buffer_size,
                                                                  u32 *audio_input_type, char **audio_input_ip, u16 *audio_input_port,
                                                                  u32 *output_type, char **ts_out, char **udp_out, char **rtp_out, u16 *output_port, 
-                                                                 char** segment_dir, u32 *segment_duration, char **segment_manifest, u32 *segment_number, char **segment_http_prefix)
+                                                                 char** segment_dir, u32 *segment_duration, char **segment_manifest, u32 *segment_number, char **segment_http_prefix, Bool *split_rap)
 {
        Bool rate_found=0, mpeg4_carousel_found=0, time_found=0, src_found=0, dst_found=0, audio_input_found=0, video_input_found=0, 
                 seg_dur_found=0, seg_dir_found=0, seg_manifest_found=0, seg_number_found=0, seg_http_found = 0, real_time_found=0;
@@ -1520,7 +1530,7 @@ static GFINLINE GF_Err parse_args(int argc, char **argv, u32 *mux_rate, u32 *car
 #ifdef GPAC_MEMORY_TRACKING
                        gf_sys_close();
                        gf_sys_init(1);
-                       gf_log_set_tools(gf_log_get_tools()|GF_LOG_MEMORY);
+                       gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_DEBUG);
 #else
                        fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); 
 #endif
@@ -1556,6 +1566,8 @@ static GFINLINE GF_Err parse_args(int argc, char **argv, u32 *mux_rate, u32 *car
                        *run_time = atoi(arg+6);
                } else if (!stricmp(arg, "-single-au")) {
                        *single_au_pes = 1;
+               } else if (!stricmp(arg, "-rap")) {
+                       *split_rap = 1;
                }
        }
        if (*real_time) force_real_time = 1;
@@ -1565,14 +1577,9 @@ static GFINLINE GF_Err parse_args(int argc, char **argv, u32 *mux_rate, u32 *car
        for (i=1; i<argc; i++) {                
                arg = argv[i];          
                if (arg[0]=='-') {
-                       if (!strnicmp(arg, "-ll=", 4)) {
-                               u32 flags = gf_log_parse_level(argv[i]+4);
-                               if (!flags) return GF_BAD_PARAM;
-                               gf_log_set_level(flags);
-                       } else if (!strnicmp(arg, "-lt=", 4)) {
-                               u32 flags = gf_log_parse_tools(argv[i]+4);
-                               if (!flags) return GF_BAD_PARAM;
-                               gf_log_set_tools(flags);
+                       if (!strnicmp(arg, "-logs=", 6)) {
+                               if (gf_log_set_tools_levels(argv[i+1]+6) != GF_OK)
+                                       return GF_BAD_PARAM;
                        } else if (!strnicmp(arg, "-prog=", 6)) {
                                u32 res;
                                prog_name = arg+6;
@@ -1765,7 +1772,7 @@ int main(int argc, char **argv)
        const char *ts_pck;
        GF_Err e;
        u32 run_time;
-       Bool real_time, single_au_pes;
+       Bool real_time, single_au_pes, split_rap;
        u64 pcr_init_val=0;
        u32 i, j, mux_rate, nb_progs, cur_pid, carrousel_rate, last_print_time, last_video_time, bifs_use_pes, psi_refresh_rate;
        char *ts_out = NULL, *udp_out = NULL, *rtp_out = NULL, *audio_input_ip = NULL;
@@ -1794,9 +1801,8 @@ int main(int argc, char **argv)
        /*   gpac init   */
        /*****************/
        gf_sys_init(0);
-       gf_log_set_level(GF_LOG_WARNING);
-       gf_log_set_tools(GF_LOG_CONTAINER|GF_LOG_SCENE|GF_LOG_PARSER|GF_LOG_AUTHOR|GF_LOG_CODING);
-
+       gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);
+       
        /***********************/
        /*   initialisations   */
        /***********************/
@@ -1829,6 +1835,7 @@ int main(int argc, char **argv)
        muxer = NULL;
        single_au_pes = 0;
        bifs_use_pes = 0;
+       split_rap = 0;
        psi_refresh_rate = GF_M2TS_PSI_DEFAULT_REFRESH_RATE;
        pcr_offset = DEFAULT_PCR_OFFSET;
 
@@ -1839,7 +1846,7 @@ int main(int argc, char **argv)
                                                        &real_time, &run_time, &video_buffer, &video_buffer_size,
                                                        &audio_input_type, &audio_input_ip, &audio_input_port,
                                                        &output_type, &ts_out, &udp_out, &rtp_out, &output_port, 
-                                                       &segment_dir, &segment_duration, &segment_manifest, &segment_number, &segment_http_prefix)) {
+                                                       &segment_dir, &segment_duration, &segment_manifest, &segment_number, &segment_http_prefix, &split_rap)) {
                goto exit;
        }
        
@@ -1969,6 +1976,10 @@ int main(int argc, char **argv)
                        assert(0);
        }
 
+       if (!nb_progs) {
+               fprintf(stderr, "No program to mux, quitting.\n");
+       }
+
        /****************************************/
        /*   declare all streams to the muxer   */
        /****************************************/
@@ -1982,13 +1993,15 @@ int main(int argc, char **argv)
                }
 
                for (j=0; j<progs[i].nb_streams; j++) {
+                       GF_M2TS_Mux_Stream *stream;
                        Bool force_pes_mode = 0;
                        /*likely an OD stream disabled*/
                        if (!progs[i].streams[j].stream_type) continue;
 
                        if (progs[i].streams[j].stream_type==GF_STREAM_SCENE) force_pes_mode = bifs_use_pes ? 1 : 0;
 
-                       gf_m2ts_program_stream_add(program, &progs[i].streams[j], cur_pid+j+1, (progs[i].pcr_idx==j) ? 1 : 0, force_pes_mode);
+                       stream = gf_m2ts_program_stream_add(program, &progs[i].streams[j], cur_pid+j+1, (progs[i].pcr_idx==j) ? 1 : 0, force_pes_mode);
+                       if (split_rap && (progs[i].streams[j].stream_type==GF_STREAM_VISUAL)) stream->start_pes_at_rap = 1;
                }
 
                cur_pid += progs[i].nb_streams;
@@ -2039,7 +2052,7 @@ int main(int argc, char **argv)
                /*flush all packets*/
                while ((ts_pck = gf_m2ts_mux_process(muxer, &status)) != NULL) {
                        if (ts_output_file != NULL) {
-                               fwrite(ts_pck, 1, 188, ts_output_file); 
+                               gf_fwrite(ts_pck, 1, 188, ts_output_file); 
                                if (segment_duration && (muxer->time.sec > prev_seg_time.sec + segment_duration)) {
                                        prev_seg_time = muxer->time;
                                        fclose(ts_output_file);
@@ -2138,7 +2151,8 @@ int main(int argc, char **argv)
        {
                u64 bits = muxer->tot_pck_sent*8*188;
                u32 dur_sec = gf_m2ts_get_ts_clock(muxer) / 1000;
-               fprintf(stdout, "Done muxing - %d sec - average rate %d kbps "LLD" packets written ("LLD" padding)\n", dur_sec, (u32) (bits/dur_sec/1000), muxer->tot_pck_sent, muxer->tot_pad_sent);
+               fprintf(stdout, "Done muxing - %d sec - average rate %d kbps "LLD" packets written\n", dur_sec, (u32) (bits/dur_sec/1000), muxer->tot_pck_sent);
+               fprintf(stdout, "\tPadding: "LLD" packets - "LLD" PES padded bytes (%g kbps)\n", muxer->tot_pad_sent, muxer->tot_pes_pad_bytes, (Double) (muxer->tot_pes_pad_bytes*8.0/dur_sec/1000) );
        }
 
 exit:
diff --git a/applications/mp42ts/mp42ts.dsp b/applications/mp42ts/mp42ts.dsp
deleted file mode 100644 (file)
index 61f3b4b..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mp42ts" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
-\r
-CFG=mp42ts - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "mp42ts.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "mp42ts.mak" CFG="mp42ts - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "mp42ts - Win32 Release" (based on "Win32 (x86) Console Application")\r
-!MESSAGE "mp42ts - Win32 Debug" (based on "Win32 (x86) Console Application")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "mp42ts - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD BASE RSC /l 0x40c /d "NDEBUG"\r
-# ADD RSC /l 0x40c /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"../../../bin/w32_rel/mp42ts.exe" /libpath:"../../../extra_lib/lib/w32_rel"\r
-\r
-!ELSEIF  "$(CFG)" == "mp42ts - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
-# ADD BASE RSC /l 0x40c /d "_DEBUG"\r
-# ADD RSC /l 0x40c /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"../../../bin/w32_deb/mp42ts.exe" /pdbtype:sept /libpath:"../../../extra_lib/lib/w32_deb"\r
-# SUBTRACT LINK32 /nodefaultlib\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "mp42ts - Win32 Release"\r
-# Name "mp42ts - Win32 Debug"\r
-# Begin Source File\r
-\r
-SOURCE=.\main.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mp42ts.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mp42ts.h\r
-# End Source File\r
-# End Target\r
-# End Project\r
diff --git a/applications/mp42ts/mp42ts.vcproj b/applications/mp42ts/mp42ts.vcproj
deleted file mode 100644 (file)
index 7702b04..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>\r
-<VisualStudioProject\r
-       ProjectType="Visual C++"\r
-       Version="8,00"\r
-       Name="mp42ts"\r
-       ProjectGUID="{F728CC74-A7D0-43D2-8A28-05CE9F2EF0D0}"\r
-       >\r
-       <Platforms>\r
-               <Platform\r
-                       Name="Win32"\r
-               />\r
-       </Platforms>\r
-       <ToolFiles>\r
-       </ToolFiles>\r
-       <Configurations>\r
-               <Configuration\r
-                       Name="Debug|Win32"\r
-                       OutputDirectory=".\Debug"\r
-                       IntermediateDirectory=".\Debug"\r
-                       ConfigurationType="1"\r
-                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
-                       UseOfMFC="0"\r
-                       ATLMinimizesCRunTimeLibraryUsage="false"\r
-                       CharacterSet="2"\r
-                       >\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCCustomBuildTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCXMLDataGeneratorTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCMIDLTool"\r
-                               TypeLibraryName=".\Debug/mp42ts.tlb"\r
-                               HeaderFileName=""\r
-                       />\r
-                       <Tool\r
-                               Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
-                               AdditionalIncludeDirectories="../../include"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
-                               PrecompiledHeaderFile=".\Debug/mp42ts.pch"\r
-                               AssemblerListingLocation=".\Debug/"\r
-                               ObjectFile=".\Debug/"\r
-                               ProgramDataBaseFileName=".\Debug/"\r
-                               BrowseInformation="1"\r
-                               WarningLevel="3"\r
-                               SuppressStartupBanner="true"\r
-                               DebugInformationFormat="4"\r
-                       />\r
-                       <Tool\r
-                               Name="VCManagedResourceCompilerTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="_DEBUG"\r
-                               Culture="1036"\r
-                       />\r
-                       <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCLinkerTool"\r
-                               AdditionalDependencies="odbc32.lib odbccp32.lib"\r
-                               OutputFile="../../bin/$(PlatformName)/$(ConfigurationName)/MP42TS.exe"\r
-                               LinkIncremental="2"\r
-                               SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="../../../extra_lib/lib/w32_deb"\r
-                               GenerateDebugInformation="true"\r
-                               ProgramDatabaseFile=".\Debug/mp42ts.pdb"\r
-                               SubSystem="1"\r
-                               TargetMachine="1"\r
-                       />\r
-                       <Tool\r
-                               Name="VCALinkTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCManifestTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCXDCMakeTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCBscMakeTool"\r
-                               SuppressStartupBanner="true"\r
-                               OutputFile=".\Debug/mp42ts.bsc"\r
-                       />\r
-                       <Tool\r
-                               Name="VCFxCopTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCAppVerifierTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"\r
-                       />\r
-               </Configuration>\r
-               <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory=".\Release"\r
-                       IntermediateDirectory=".\Release"\r
-                       ConfigurationType="1"\r
-                       InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"\r
-                       UseOfMFC="0"\r
-                       ATLMinimizesCRunTimeLibraryUsage="false"\r
-                       CharacterSet="2"\r
-                       >\r
-                       <Tool\r
-                               Name="VCPreBuildEventTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCCustomBuildTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCXMLDataGeneratorTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCWebServiceProxyGeneratorTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCMIDLTool"\r
-                               TypeLibraryName=".\Release/mp42ts.tlb"\r
-                               HeaderFileName=""\r
-                       />\r
-                       <Tool\r
-                               Name="VCCLCompilerTool"\r
-                               Optimization="2"\r
-                               InlineFunctionExpansion="1"\r
-                               AdditionalIncludeDirectories="../../include"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE"\r
-                               StringPooling="true"\r
-                               RuntimeLibrary="2"\r
-                               EnableFunctionLevelLinking="true"\r
-                               PrecompiledHeaderFile=".\Release/mp42ts.pch"\r
-                               AssemblerListingLocation=".\Release/"\r
-                               ObjectFile=".\Release/"\r
-                               ProgramDataBaseFileName=".\Release/"\r
-                               WarningLevel="3"\r
-                               SuppressStartupBanner="true"\r
-                       />\r
-                       <Tool\r
-                               Name="VCManagedResourceCompilerTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCResourceCompilerTool"\r
-                               PreprocessorDefinitions="NDEBUG"\r
-                               Culture="1036"\r
-                       />\r
-                       <Tool\r
-                               Name="VCPreLinkEventTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCLinkerTool"\r
-                               AdditionalDependencies="odbc32.lib odbccp32.lib"\r
-                               OutputFile="../../bin/$(PlatformName)/$(ConfigurationName)/MP42TS.exe"\r
-                               LinkIncremental="1"\r
-                               SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="../../../extra_lib/lib/w32_rel"\r
-                               ProgramDatabaseFile=".\Release/mp42ts.pdb"\r
-                               SubSystem="1"\r
-                               TargetMachine="1"\r
-                       />\r
-                       <Tool\r
-                               Name="VCALinkTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCManifestTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCXDCMakeTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCBscMakeTool"\r
-                               SuppressStartupBanner="true"\r
-                               OutputFile=".\Release/mp42ts.bsc"\r
-                       />\r
-                       <Tool\r
-                               Name="VCFxCopTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCAppVerifierTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCWebDeploymentTool"\r
-                       />\r
-                       <Tool\r
-                               Name="VCPostBuildEventTool"\r
-                       />\r
-               </Configuration>\r
-       </Configurations>\r
-       <References>\r
-       </References>\r
-       <Files>\r
-               <File\r
-                       RelativePath="main.c"\r
-                       >\r
-                       <FileConfiguration\r
-                               Name="Debug|Win32"\r
-                               >\r
-                               <Tool\r
-                                       Name="VCCLCompilerTool"\r
-                                       AdditionalIncludeDirectories=""\r
-                                       PreprocessorDefinitions=""\r
-                               />\r
-                       </FileConfiguration>\r
-                       <FileConfiguration\r
-                               Name="Release|Win32"\r
-                               >\r
-                               <Tool\r
-                                       Name="VCCLCompilerTool"\r
-                                       AdditionalIncludeDirectories=""\r
-                                       PreprocessorDefinitions=""\r
-                               />\r
-                       </FileConfiguration>\r
-               </File>\r
-       </Files>\r
-       <Globals>\r
-       </Globals>\r
-</VisualStudioProject>\r
index 0a17d6a33b64e05d4708efd62f2bb8fd15aadc8e..dc7f8d7bceddb52168111bff9472e41ccf0bcbd7 100644 (file)
@@ -34,6 +34,7 @@
 #include <gpac/internal/bifs_dev.h>
 #include <gpac/constants.h>
 #include <gpac/avparse.h>
+#include <gpac/media_tools.h>
 /*for asctime and gmtime*/
 #include <time.h>
 /*ISO 639 languages*/
@@ -113,7 +114,7 @@ GF_Err dump_cover_art(GF_ISOFile *file, char *inName)
 
        sprintf(szName, "%s.%s", inName, (tag_len>>31) ? "png" : "jpg");
        t = gf_f64_open(szName, "wb");
-       fwrite(tag, tag_len & 0x7FFFFFFF, 1, t);
+       gf_fwrite(tag, tag_len & 0x7FFFFFFF, 1, t);
        
        fclose(t);
        return GF_OK;
@@ -153,8 +154,6 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log)
        GF_SceneGraph *sg;
        GF_SceneLoader load;
        u32 ftype;
-       u32 prev_level = gf_log_get_level();
-       u32 prev_tools = gf_log_get_tools();
        gf_log_cbk prev_logs = NULL;
        FILE *logs = NULL;
        e = GF_OK;
@@ -198,16 +197,14 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log)
                sprintf(szLog, "%s_dec.logs", inName);
                logs = gf_f64_open(szLog, "wt");
 
-               gf_log_set_tools(GF_LOG_CODING);
-               gf_log_set_level(GF_LOG_DEBUG);
+               gf_log_set_tool_level(GF_LOG_CODING, GF_LOG_DEBUG);
                prev_logs = gf_log_set_callback(logs, scene_coding_log);
        }
        e = gf_sm_load_init(&load);
        if (!e) e = gf_sm_load_run(&load);
        gf_sm_load_done(&load);
        if (logs) {
-               gf_log_set_tools(prev_tools);
-               gf_log_set_level(prev_level);
+               gf_log_set_tool_level(GF_LOG_CODING, GF_LOG_ERROR);
                gf_log_set_callback(NULL, prev_logs);
                fclose(logs);
        }
@@ -1581,6 +1578,13 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump)
        } else {
                fprintf(stdout, "\tAverage rate %d bps - Max Rate %d bps\n", rate, max_rate);
        }
+
+       {
+               u32 dmin, dmax, davg, smin, smax, savg;
+               gf_isom_get_chunks_infos(file, trackNum, &dmin, &davg, &dmax, &smin, &savg, &smax);
+               fprintf(stdout, "\tChunk durations: min %d ms - max %d ms - average %d ms\n", (1000*dmin)/ts, (1000*dmax)/ts, (1000*davg)/ts);
+               fprintf(stdout, "\tChunk sizes (bytes): min %d - max %d - average %d\n", smin, smax, savg);
+       }
        fprintf(stdout, "\n");
 
        count = gf_isom_get_chapter_count(file, trackNum);
@@ -1654,6 +1658,9 @@ void DumpMovieInfo(GF_ISOFile *file)
        fprintf(stdout, "* Movie Info *\n\tTimescale %d - Duration %s\n\tFragmented File %s - %d track(s)\n",
                timescale, format_duration(gf_isom_get_duration(file), timescale, szDur), gf_isom_is_fragmented(file) ? "yes" : "no", gf_isom_get_track_count(file));
 
+       if (gf_isom_moov_first(file))
+               fprintf(stdout, "\tFile suitable for progressive download (moov before mdat)\n");
+
        if (gf_isom_get_brand_info(file, &brand, &min, NULL) == GF_OK) {
                fprintf(stdout, "\tFile Brand %s - version %d\n", gf_4cc_to_str(brand), min);
        }
@@ -1768,9 +1775,12 @@ typedef struct
        Bool segment_at_rap;
        u32 subsegs_per_segment;
        char *seg_name;
+       char *seg_ext;
        Bool use_url_template;
        char *init_seg_name;
-       Bool use_index_segment;
+       Bool single_segment;
+
+       u32 segment_index;
 
        FILE *index_file;
        char index_file_name[100];
@@ -1781,9 +1791,12 @@ typedef struct
        /* temporary file to store the MPD segment description before writing the header */
        FILE *mpd_segs;
 
+       u32 represantation_idx;
+
        u32 reference_pid;
        GF_M2TS_PES *reference_stream;
        
+       u32 nb_pes_in_segment;
        /* earliest presentation time for the whole segment */
        u64 first_PTS;
 
@@ -1793,6 +1806,8 @@ typedef struct
        u32 base_offset;
        /* last presentation time for the subsegment being processed (before the next subsegment is started) */
        u64 last_PTS;
+       /* last decoding time for the subsegment being processed */
+       u64 last_DTS;
        /* byte offset for the last PES packet for the subsegment being processed */
        u32 last_offset;
 
@@ -1805,16 +1820,18 @@ typedef struct
        /* byte offset for the last PES packet for the previous subsegment */
        u32 prev_last_offset;
 
-       /* boolean indicating if the current subsegment contains a RAP */
-       Bool has_rap;
+       /* indicates if the current subsegment contains a SAP and its SAP type*/
+       u32 SAP_type;
+       /* indicates if the first PES in the current subsegment is a SAP*/
+       Bool first_pes_sap;
        /* Presentation time for the first RAP encountered in the subsegment */
-       u64 first_RAP_PTS;
+       u64 first_SAP_PTS;
        /* byte offset for the first RAP encountered in the subsegment */
-       u32 first_RAP_offset;
-       u64 prev_last_RAP_PTS;
-       u32 prev_last_RAP_offset;
-       u64 last_RAP_PTS;
-       u32 last_RAP_offset;
+       u32 first_SAP_offset;
+       u64 prev_last_SAP_PTS;
+       u32 prev_last_SAP_offset;
+       u64 last_SAP_PTS;
+       u32 last_SAP_offset;
 
        /* information about the first PAT found in the subsegment */
        u32 last_pat_position;
@@ -1852,10 +1869,12 @@ typedef struct
        /* when writing to file */
        FILE *pes_out;
        char dump[100];
+#if 0
        FILE *pes_out_nhml;
        char nhml[100];
        FILE *pes_out_info;
        char info[100];
+#endif
        Bool is_info_dumped;
 
        u32 prog_number;
@@ -1884,18 +1903,19 @@ static GF_SegmentIndexBox *m2ts_sidx_new(u32 pid, u64 PTS, u64 position)
        return sidx;
 }
 
-static void m2ts_sidx_add_entry(GF_SegmentIndexBox *sidx, Bool type, 
-                                                               u32 size, u32 duration, Bool has_rap, u32 RAP_delta_time)
+static void m2ts_sidx_add_entry(GF_SegmentIndexBox *sidx, Bool ref_type, 
+                                                               u32 size, u32 duration, Bool first_is_SAP, u32 sap_type, u32 RAP_delta_time)
 {
        GF_SIDXReference *ref;
        sidx->nb_refs++;
        sidx->refs = gf_realloc(sidx->refs, sidx->nb_refs*sizeof(GF_SIDXReference));
        ref = &(sidx->refs[sidx->nb_refs-1]);
-       ref->reference_type = type;
-       ref->contains_RAP = has_rap;
+       ref->reference_type = ref_type;
        ref->reference_size = size;
        ref->subsegment_duration = duration;
-       ref->RAP_delta_time = (has_rap ? RAP_delta_time: 0);
+       ref->starts_with_SAP = first_is_SAP;
+       ref->SAP_type = sap_type;
+       ref->SAP_delta_time = (sap_type ? RAP_delta_time: 0);
 }
 
 static void m2ts_sidx_update_prev_entry_duration(GF_SegmentIndexBox *sidx, u32 duration)
@@ -1912,22 +1932,21 @@ static void m2ts_sidx_finalize_size(GF_M2TS_IndexingInfo *index_info, u64 file_s
        if (index_info->sidx->nb_refs == 0) return;
        ref = &(index_info->sidx->refs[index_info->sidx->nb_refs-1]);
        ref->reference_size = (u32)(file_size - index_info->prev_base_offset);
-       fprintf(stderr, "Subsegment: position-range ajdustment:%d-%d (%d bytes)\n",
-               index_info->prev_base_offset, (u32)file_size, ref->reference_size);
+
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment: position-range ajdustment:%d-%d (%d bytes)\n", index_info->prev_base_offset, (u32)file_size, ref->reference_size));
 }
 
 static void m2ts_sidx_flush_entry(GF_M2TS_IndexingInfo *index_info) 
 {
        u32 size; 
        u32 duration, prev_duration; 
-       u32 RAP_delta_time; 
-       u32 RAP_offset;
+       u32 SAP_delta_time; 
+       u32 SAP_offset;
 
        u32 end_offset;
 
        if (!index_info->sidx) {
-               fprintf(stderr, "Segment: Reference PID: %d, EPTime: "LLU", Start Offset: %d bytes\n", 
-                       index_info->reference_pid, index_info->base_PTS, index_info->base_offset);
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Segment: Reference PID: %d, EPTime: "LLU", Start Offset: %d bytes\n", index_info->reference_pid, index_info->base_PTS, index_info->base_offset));
                index_info->sidx = m2ts_sidx_new(index_info->reference_pid, index_info->base_PTS, index_info->base_offset);
        }
 
@@ -1943,56 +1962,55 @@ static void m2ts_sidx_flush_entry(GF_M2TS_IndexingInfo *index_info)
        /* close the current index */ 
        size = (u32)(end_offset - index_info->base_offset);
        duration = (u32)(index_info->last_PTS - index_info->base_PTS);
-       RAP_delta_time= (u32)(index_info->first_RAP_PTS - index_info->base_PTS);
-       RAP_offset = (u32)(index_info->first_RAP_offset - index_info->base_offset);
-       m2ts_sidx_add_entry(index_info->sidx, 0, size, duration, index_info->has_rap, RAP_delta_time);
+       SAP_delta_time= (u32)(index_info->first_SAP_PTS - index_info->base_PTS);
+       SAP_offset = (u32)(index_info->first_SAP_offset - index_info->base_offset);
+       m2ts_sidx_add_entry(index_info->sidx, 0, size, duration, index_info->first_pes_sap, index_info->SAP_type, SAP_delta_time);
 
        /* adjust the previous index duration */
        if (index_info->sidx->nb_refs > 0 && (index_info->base_PTS < index_info->prev_last_PTS) ) {
                prev_duration = (u32)(index_info->base_PTS-index_info->prev_base_PTS);
-               fprintf(stderr, "           time-range adj.: %.03f-%.03f / %.03f sec.\n",               
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("           time-range adj.: %.03f-%.03f / %.03f sec.\n",               
                        (index_info->prev_base_PTS - index_info->first_PTS)/90000.0, 
                        (index_info->base_PTS - index_info->first_PTS)/90000.0, prev_duration/90000.0);
-               m2ts_sidx_update_prev_entry_duration(index_info->sidx, prev_duration);
+               m2ts_sidx_update_prev_entry_duration(index_info->sidx, prev_duration));
        }
 
        /* Printing result */
-       fprintf(stderr, "Subsegment:");
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment:"));
        //time-range:position-range: 
-       //fprintf(stderr, LLD"-"LLD,index_info->base_PTS, index_info->last_PTS);
-       fprintf(stderr, " %.03f-%0.3f / %.03f sec., %d-%d / %d bytes, ",
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" %.03f-%0.3f / %.03f sec., %d-%d / %d bytes, ",
                (index_info->base_PTS - index_info->first_PTS)/90000.0, 
                (index_info->last_PTS - index_info->first_PTS)/90000.0, duration/90000.0,
-               index_info->base_offset, end_offset, size);
-       if (index_info->has_rap) {
-               fprintf(stderr, "RAP @ %.03f sec. / %d bytes", (index_info->first_RAP_PTS - index_info->first_PTS)/90000.0, 
-                       RAP_offset);
+               index_info->base_offset, end_offset, size));
+       if (index_info->SAP_type) {
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("RAP @ %.03f sec. / %d bytes", (index_info->first_SAP_PTS - index_info->first_PTS)/90000.0, 
+                       SAP_offset));
        }
        if (index_info->first_pat_position_valid) {
-               fprintf(stderr, ", PAT @ %d bytes", (u32)(index_info->first_pat_position - index_info->base_offset));
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PAT @ %d bytes", (u32)(index_info->first_pat_position - index_info->base_offset)));
        } else {
-               fprintf(stderr, ", No PAT");
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PAT"));
        }
        if (index_info->first_cat_position_valid) {
-               fprintf(stderr, ", CAT @ %d bytes", (u32)(index_info->first_cat_position - index_info->base_offset));
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", CAT @ %d bytes", (u32)(index_info->first_cat_position - index_info->base_offset)));
        } else {
-               fprintf(stderr, ", No CAT");
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No CAT"));
        }
        if (index_info->first_pmt_position_valid) {
-               fprintf(stderr, ", PMT @ %d bytes", (u32)(index_info->first_pmt_position - index_info->base_offset));
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PMT @ %d bytes", (u32)(index_info->first_pmt_position - index_info->base_offset)));
        } else {
-               fprintf(stderr, ", No PMT");
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PMT"));
        }
        if (index_info->first_pcr_position_valid) {
-               fprintf(stderr, ", PCR @ %d bytes", (u32)(index_info->first_pcr_position - index_info->base_offset));
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PCR @ %d bytes", (u32)(index_info->first_pcr_position - index_info->base_offset)));
        } else {
-               fprintf(stderr, ", No PCR");
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PCR"));
        }
-       fprintf(stderr, "\n");
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n"));
 
        /* save the current values for later adjustments */
-       index_info->prev_last_RAP_PTS = index_info->last_RAP_PTS;
-       index_info->prev_last_RAP_offset = index_info->last_RAP_offset;
+       index_info->prev_last_SAP_PTS = index_info->last_SAP_PTS;
+       index_info->prev_last_SAP_offset = index_info->last_SAP_offset;
        index_info->prev_last_PTS = index_info->last_PTS;
        index_info->prev_last_offset = index_info->last_offset;
        index_info->prev_base_PTS = index_info->base_PTS;
@@ -2005,9 +2023,13 @@ static void m2ts_sidx_flush_entry(GF_M2TS_IndexingInfo *index_info)
        
        /* update the values for the new index*/
        index_info->base_offset = end_offset;
-       index_info->has_rap = 0;
-       index_info->first_RAP_PTS = 0;
-       index_info->first_RAP_offset = 0;
+       index_info->SAP_type = 0;
+       index_info->first_SAP_PTS = 0;
+       index_info->first_SAP_offset = 0;
+       index_info->first_pes_sap = 0;
+       index_info->nb_pes_in_segment = 0;
+       index_info->last_DTS = 0;
+
        if (index_info->last_pat_position >= index_info->base_offset) {
                index_info->first_pat_position_valid = 1;
                index_info->first_pat_position = index_info->last_pat_position;
@@ -2058,7 +2080,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
 
        switch (evt_type) {
        case GF_M2TS_EVT_PAT_FOUND:
-               fprintf(stdout, "Initial PAT found - %d programs\n", gf_list_count(ts->programs) );
                if (index_info->start_indexing) {
                        if (!index_info->first_pat_position_valid) {
                                index_info->first_pat_position_valid = 1;
@@ -2071,7 +2092,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                }
                break;
        case GF_M2TS_EVT_PAT_UPDATE:
-               fprintf(stdout, "PAT updated - %d programs\n", gf_list_count(ts->programs) );
                if (index_info->start_indexing) {
                        if (!index_info->first_pat_position_valid) {
                                index_info->first_pat_position_valid = 1;
@@ -2100,7 +2120,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
 //             fprintf(stdout, "Repeated PAT found - %d programs\n", gf_list_count(ts->programs) );
                break;
        case GF_M2TS_EVT_CAT_FOUND:
-               fprintf(stdout, "Initial CAT found\n");
                if (index_info->start_indexing) {
                        if (!index_info->first_cat_position_valid) {
                                index_info->first_cat_position_valid = 1;
@@ -2113,7 +2132,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                }
                break;
        case GF_M2TS_EVT_CAT_UPDATE:
-               fprintf(stdout, "CAT updated\n");
                if (index_info->start_indexing) {
                        if (!index_info->first_cat_position_valid) {
                                index_info->first_cat_position_valid = 1;
@@ -2149,17 +2167,18 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        index_info->last_pmt_position = (ts->pck_number-1)*188;
                }
                count = gf_list_count(prog->streams);
-               fprintf(stdout, "Program number %d found - %d streams:\n", prog->number, count);
+
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Program number %d found - %d streams:\n", prog->number, count));
                for (i=0; i<count; i++) {
                        GF_M2TS_ES *es = gf_list_get(prog->streams, i);
                        if (es->pid == prog->pmt_pid) {
-                               fprintf(stdout, "\tPID %d: Program Map Table\n", es->pid);
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\tPID %d: Program Map Table\n", es->pid));
                        } else {
                                GF_M2TS_PES *pes = (GF_M2TS_PES *)es;
-                               gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
-                               fprintf(stdout, "\tPID %d: %s ", pes->pid, gf_m2ts_get_stream_name(pes->stream_type) );
-                               if (pes->mpeg4_es_id) fprintf(stdout, " - MPEG-4 ES ID %d", pes->mpeg4_es_id);
-                               fprintf(stdout, "\n");
+                               gf_m2ts_set_pes_framing(pes, dumper->pes_out ? GF_M2TS_PES_FRAMING_RAW : GF_M2TS_PES_FRAMING_DEFAULT);
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\tPID %d: %s ", pes->pid, gf_m2ts_get_stream_name(pes->stream_type) ));
+                               if (pes->mpeg4_es_id) GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" - MPEG-4 ES ID %d", pes->mpeg4_es_id));
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n"));
                        } 
                        if (es->pid == prog->pcr_pid) {
                                /* we create indexing information on the stream used for carrying the PCR */
@@ -2175,7 +2194,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                prog = (GF_M2TS_Program*)par;
                if (gf_list_count(ts->programs)>1 && prog->number!=dumper->prog_number)
                        break;
-               fprintf(stdout, "Program list updated - %d streams\n", gf_list_count( ((GF_M2TS_Program*)par)->streams) );
                if (index_info->start_indexing) {
                        if (!index_info->first_pmt_position_valid) {
                                index_info->first_pmt_position_valid = 1;
@@ -2198,29 +2216,27 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        }
                        index_info->last_pmt_position = (ts->pck_number-1)*188;
                }
-//             fprintf(stdout, "Repeated Program list found - %d streams\n", gf_list_count( ((GF_M2TS_Program*)par)->streams) );
                if (dumper->timestamps_info_file) {
                        fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, prog->pmt_pid);
                }
                break;
        case GF_M2TS_EVT_SDT_FOUND:
                count = gf_list_count(ts->SDTs) ;
-               fprintf(stdout, "Program Description found - %d desc:\n", count);
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Program Description found - %d desc:\n", count));
                for (i=0; i<count; i++) {
                        GF_M2TS_SDT *sdt = gf_list_get(ts->SDTs, i);
-                       fprintf(stdout, "\tServiceID %d - Provider %s - Name %s\n", sdt->service_id, sdt->provider, sdt->service);
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\tServiceID %d - Provider %s - Name %s\n", sdt->service_id, sdt->provider, sdt->service));
                }
                break;
        case GF_M2TS_EVT_SDT_UPDATE:
                count = gf_list_count(ts->SDTs) ;
-               fprintf(stdout, "Program Description updated - %d desc\n", count);
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Program Description updated - %d desc\n", count));
                for (i=0; i<count; i++) {
                        GF_M2TS_SDT *sdt = gf_list_get(ts->SDTs, i);
-                       fprintf(stdout, "\tServiceID %d - Provider %s - Name %s\n", sdt->service_id, sdt->provider, sdt->service);
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\tServiceID %d - Provider %s - Name %s\n", sdt->service_id, sdt->provider, sdt->service));
                }
                break;
        case GF_M2TS_EVT_SDT_REPEAT:
-//             fprintf(stdout, "Repeated Program Description - %d desc\n", gf_list_count(ts->SDTs) );
                break;
        case GF_M2TS_EVT_PES_TIMING:
                pck = par;
@@ -2258,16 +2274,25 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        if (pck->stream->pid != index_info->reference_pid) {
                                break;
                        } else {
+                               if (index_info->last_DTS != pck->DTS) {
+                                       index_info->last_DTS = pck->DTS;
+                                       index_info->nb_pes_in_segment++;
+                               }
+
                                /* we store the fact that there is at least a RAP for the index
                                and we store the PTS of the first encountered RAP in the index*/
                                if (pck->flags & GF_M2TS_PES_PCK_RAP) {
-                                       index_info->has_rap = 1;
-                                       if (!index_info->first_RAP_PTS || (index_info->first_RAP_PTS > pck->PTS)) {
-                                               index_info->first_RAP_PTS = pck->PTS;
-                                               index_info->first_RAP_offset = (pck->stream->pes_start_packet_number-1)*188;
+                                       index_info->SAP_type = 1;
+                                       if (!index_info->first_SAP_PTS || (index_info->first_SAP_PTS > pck->PTS)) {
+                                               index_info->first_SAP_PTS = pck->PTS;
+                                               index_info->first_SAP_offset = (pck->stream->pes_start_packet_number-1)*188;
+                                       }
+                                       index_info->last_SAP_PTS = pck->PTS;
+                                       index_info->last_SAP_offset = (pck->stream->pes_start_packet_number-1)*188;
+
+                                       if (index_info->nb_pes_in_segment==1) {
+                                               index_info->first_pes_sap = 1;
                                        }
-                                       index_info->last_RAP_PTS = pck->PTS;
-                                       index_info->last_RAP_offset = (pck->stream->pes_start_packet_number-1)*188;
                                }
                                /* we need to know the earliest PTS value (RAP or not) in the index*/
                                if (!index_info->base_PTS || (index_info->base_PTS > pck->PTS)) {
@@ -2282,11 +2307,12 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        index_info->last_PTS = pck->PTS;
                                        index_info->last_offset = (index_info->reference_stream->pes_start_packet_number-1)*188;
                                }
+
                                m2ts_check_indexing(index_info);
                        }
                }
-               if (dumper->pes_out && (dumper->dump_pid == pck->stream->pid)) {
-                       fwrite(pck->data, pck->data_len, 1, dumper->pes_out);
+               if (dumper->has_seen_pat && dumper->pes_out && (dumper->dump_pid == pck->stream->pid)) {
+                       gf_fwrite(pck->data, pck->data_len, 1, dumper->pes_out);
                }
                break;
        case GF_M2TS_EVT_PES_PCR:
@@ -2314,7 +2340,7 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                if (sl_pck->stream->mpeg4_es_id) {
                                        GF_ESD *esd = ((GF_M2TS_PES*)sl_pck->stream)->esd;
                                        if (!dumper->is_info_dumped) {
-                                               if (esd->decoderConfig->decoderSpecificInfo) fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, dumper->pes_out_info);
+                                               if (esd->decoderConfig->decoderSpecificInfo) gf_fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, dumper->pes_out_info);
                                                dumper->is_info_dumped = 1;
                                                fprintf(dumper->pes_out_nhml, "<NHNTStream version=\"1.0\" ");
                                                fprintf(dumper->pes_out_nhml, "timeScale=\"%d\" ", esd->slConfig->timestampResolution);
@@ -2325,7 +2351,7 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                                fprintf(dumper->pes_out_nhml, "inRootOD=\"yes\">\n");
                                        }
                                        gf_sl_depacketize(esd->slConfig, &header, sl_pck->data, sl_pck->data_len, &header_len);
-                                       fwrite(sl_pck->data+header_len, sl_pck->data_len-header_len, 1, dumper->pes_out);
+                                       gf_fwrite(sl_pck->data+header_len, sl_pck->data_len-header_len, 1, dumper->pes_out);
                                        fprintf(dumper->pes_out_nhml, "<NHNTSample DTS=\""LLD"\" dataLength=\"%d\" isRAP=\"%s\"/>\n", LLD_CAST header.decodingTimeStamp, sl_pck->data_len-header_len, (header.randomAccessPointFlag?"yes":"no"));
                                }
                        }
@@ -2349,117 +2375,266 @@ static void mpd_duration(Double duration, char *duration_string)
        else sprintf(duration_string, "PT0S");  
 }
 
-void mpd_start(FILE *mpd, Bool on_demand, const char *media_file_name, 
-                          Double file_duration, const char *media_mime, const char *media_codecs, 
-                          u32 width, u32 height, u32 sample_rate, u32 nb_channels,  char *langCode,
-                          Bool split_seg_at_rap, u64 file_size, Double bufferTime)
+static void mpd_start(GF_M2TS_IndexingInfo *index_info, Bool on_demand, const char *media_file_name, 
+                          Double file_duration, Bool split_seg_at_rap, u64 file_size, Double bufferTime)
 {
        char duration_string[100];
        char buffer_string[100];
-       u32 bandwidth;
+       u32 bandwidth, i;
+       GF_MediaImporter import;
+       char szCodecs[1000];
+       u32 width, height, sample_rate, nb_channels, langCode;
+       GF_Err e;
+       FILE *mpd = index_info->mpd_file;
+
+       /*get codecs*/  
+       memset(&import, 0, sizeof(GF_MediaImporter));
+       import.trackID = 0;
+       import.flags = GF_IMPORT_PROBE_ONLY;
+       import.in_name = (char *)media_file_name;
+       e = gf_media_import(&import);
+       strcpy(szCodecs, "");
+       width = height = sample_rate = nb_channels = langCode = 0;
+
+       if (!e) {
+               for (i=0; i<import.nb_tracks;i++) {
+                       if (strlen(import.tk_info[i].szCodecProfile)) {
+                               if (strlen(szCodecs)) strcat(szCodecs, ",");
+                               strcat(szCodecs, import.tk_info[i].szCodecProfile);
+                       }
+                       if (import.tk_info[i].type==GF_ISOM_MEDIA_VISUAL) {
+                               if (!width) width = import.tk_info[i].video_info.width;
+                               if (!height) height = import.tk_info[i].video_info.height;
+                       }
+                       else if (import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO) {
+                               if (!sample_rate) sample_rate = import.tk_info[i].audio_info.sample_rate;
+                               if (!nb_channels) nb_channels = import.tk_info[i].audio_info.nb_channels;
+                       }
+                       if (!langCode && import.tk_info[i].lang) langCode = import.tk_info[i].lang;
+               }
+       }
+
        bandwidth = (u32) (file_size * 8 / file_duration);      
-       fprintf(mpd, "<MPD type=\"%s\" xmlns=\"urn:mpeg:mpegB:schema:DASH:MPD:DIS2011\">\n", (on_demand ? "OnDemand": "Live"));
-    fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
-       fprintf(mpd, "  <Title>Media Presentation Description for file %s generated with GPAC </Title>\n", media_file_name);
-    fprintf(mpd, " </ProgramInformation>\n");
        mpd_duration(file_duration, duration_string);
        mpd_duration(bufferTime, buffer_string);
-    fprintf(mpd, " <Period start=\"PT0S\" duration=\"%s\" minBufferTime=\"%s\">\n", duration_string, buffer_string);   
-       fprintf(mpd, "  <Representation id=\"rep1\"");
-       if (!media_codecs) fprintf(mpd, " mimeType=\"%s\"", media_mime);
-       else fprintf(mpd, " mimeType=\"%s; codecs=%s\"", media_mime, media_codecs);
+
+       if (!index_info->represantation_idx) {
+               fprintf(mpd, "<MPD type=\"%s\" xmlns=\"urn:mpeg:DASH:schema:MPD:2011\" profiles=\"urn:mpeg:dash:profile:mp2t-main:2011\" minBufferTime=\"%s\">\n", (on_demand ? "static": "dynamic"), buffer_string);
+               fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
+               fprintf(mpd, "  <Title>MPD for file %s generated with GPAC %s</Title>\n", media_file_name, GPAC_FULL_VERSION);
+               fprintf(mpd, " </ProgramInformation>\n");
+               fprintf(mpd, " <Period start=\"PT0S\" duration=\"%s\" minBufferTime=\"%s\">\n", duration_string, buffer_string);        
+               fprintf(mpd, "  <AdaptationSet segmentAlignment=\"true\" bitstreamSwitching=\"true\" subsegmentAlignment=\"true\">\n");
+       }
+
+       fprintf(mpd, "   <Representation id=\"%d\" mimeType=\"video/mp2t\" codecs=\"%s\"", index_info->represantation_idx+1, szCodecs);
        if (width && height) fprintf(mpd, " width=\"%d\" height=\"%d\"", width, height);
        if (sample_rate && nb_channels) fprintf(mpd, " sampleRate=\"%d\" numChannels=\"%d\"", sample_rate, nb_channels);
-       if (langCode[0]) fprintf(mpd, " lang=\"%s\"", langCode);
-       fprintf(mpd, " startWithRAP=\"%s\"", split_seg_at_rap ? "true" : "false");
+       if (langCode) fprintf(mpd, " lang=\"%s\"", gf_4cc_to_str(langCode) );
+       fprintf(mpd, " startWithRAP=\"%s\"", split_seg_at_rap ? "1" : "false");
        fprintf(mpd, " bandwidth=\"%d\"", bandwidth);
        fprintf(mpd, ">\n");
 
 }
 
-void mpd_end(FILE *mpd)
+void mpd_end(FILE *mpd, Bool is_last_rep)
 {
-    fprintf(mpd, "  </Representation>\n");
-    fprintf(mpd, " </Period>\n");
-    fprintf(mpd, "</MPD>");
+    fprintf(mpd, "   </Representation>\n");
+       if (is_last_rep) {
+               fprintf(mpd, "  </AdaptationSet>\n");
+               fprintf(mpd, " </Period>\n");
+               fprintf(mpd, "</MPD>");
+       }
 }
 
 static void write_mpd_segment_info(GF_M2TS_IndexingInfo *index_info, char *media_file_name)
 {
+       char *sep, SegName[GF_MAX_PATH];
        u32 i;
        u64 start;
-       char duration_string[100];
 
-       mpd_duration(index_info->segment_duration, duration_string);
-       fprintf(index_info->mpd_file, "   <SegmentInfo duration=\"%s\">\n", duration_string); 
+       if (!index_info->seg_name) {
+               fprintf(index_info->mpd_file, "    <BaseURL>%s</BaseURL>\n", media_file_name);
+       }
+
+       if (index_info->single_segment) {
+               fprintf(index_info->mpd_file, "    <SegmentBase>\n");
+               fprintf(index_info->mpd_file, "     <RepresentationIndex>%s</RepresentationIndex>\n", index_info->index_file_name);
+               fprintf(index_info->mpd_file, "    </SegmentBase>\n");
+               return;
+       } 
+
+       if (index_info->seg_name) {
+               char *mfile = strrchr(media_file_name, '/');
+               if (!mfile) mfile = strrchr(media_file_name, '\\');
+               if (mfile) mfile += 1;
+               else mfile = media_file_name;
+
+               if (strstr(index_info->seg_name, "%s")) {
+                       sprintf(SegName, index_info->seg_name, mfile);
+               } else {
+                       strcpy(SegName, index_info->seg_name);
+               }
+               sep = strrchr(SegName, '.');
+               if (sep) sep[0] = 0;
+       }
+
+       if (index_info->seg_name && index_info->use_url_template) {
+               fprintf(index_info->mpd_file, "    <SegmentTemplate timescale=\"1000\" duration=\"%d\" startNumber=\"0\" media=\"%s$Number$.%s\" >\n", (u32) (1000*index_info->segment_duration), SegName, index_info->seg_ext); 
+       } else {
+               fprintf(index_info->mpd_file, "    <SegmentList timescale=\"1000\" duration=\"%d\">\n", (u32) (1000*index_info->segment_duration)); 
+       }
        /* add startIndex for live scenarios */
        
        if (index_info->init_seg_name) {
-               fprintf(index_info->mpd_file, "    <InitialisationSegmentURL sourceURL=\"%s\"/>\n", index_info->init_seg_name);
+               fprintf(index_info->mpd_file, "     <InitialisationSegment sourceURL=\"%s\"/>\n", index_info->init_seg_name);
        }
 
-       if (!index_info->use_index_segment) {
-               fprintf(index_info->mpd_file, "    <BaseURL>%s</BaseURL>\n", media_file_name);
+
+       fprintf(index_info->mpd_file, "     <RepresentationIndex>%s</RepresentationIndex>\n", index_info->index_file_name); 
+
+       if (!index_info->seg_name) {
+               start=index_info->sidx->first_offset;
+               for (i=0; i<index_info->sidx->nb_refs; i++) {
+                       GF_SIDXReference *ref = &index_info->sidx->refs[i];
+                       fprintf(index_info->mpd_file, "     <SegmentURL mediaRange=\""LLD"-"LLD"\"/>\n", start, start+ref->reference_size-1);
+                       start += ref->reference_size;
+               }
+       } else {
+               FILE *src, *dst;
+               u64 pos, end;
+               src= gf_f64_open(media_file_name, "rb");
                start=index_info->sidx->first_offset;
                for (i=0; i<index_info->sidx->nb_refs; i++) {
+                       char szFile[GF_MAX_PATH], buf[4096];
                        GF_SIDXReference *ref = &index_info->sidx->refs[i];
-                       fprintf(index_info->mpd_file, "    <Url range=\""LLD"-"LLD"\"/>\n", start, start+ref->reference_size-1);
+
+                       strcpy(szFile, SegName);
+                       sprintf(buf, "%d", index_info->segment_index);
+                       strcat(szFile, buf);
+                       strcat(szFile, ".ts");
+
+                       if (index_info->use_url_template!=2) {
+                               dst = gf_f64_open(szFile, "wb");
+
+                               gf_f64_seek(src, start, SEEK_SET);
+                               pos = start;
+                               end = start+ref->reference_size;
+                               while (pos<end) {
+                                       u32 res;
+                                       u32 to_read = 4096;
+                                       if (pos+4096 >= end) {
+                                               to_read = (u32) (end-pos);
+                                       }
+                                       res = fread(buf, 1, to_read, src);
+                                       if (res==to_read) {
+                                               res = fwrite(buf, 1, to_read, dst);
+                                       }
+                                       if (res!=to_read) {
+                                               fprintf(stderr, "IO error while Extracting segment %03d / %03d\r", i+1, index_info->sidx->nb_refs);
+                                               break;
+                                       }
+                                       pos += res;
+                               }
+                               fclose(dst);
+                       }
                        start += ref->reference_size;
-               }               
+                       index_info->segment_index++;
+
+                       if (!index_info->use_url_template) 
+                               fprintf(index_info->mpd_file, "     <SegmentURL media=\"%s\"/>\n", szFile);
+
+                       fprintf(stdout, "Extracting segment %03d / %03d\r", i+1, index_info->sidx->nb_refs);
+               }
+               fclose(src);
+       }               
+//             fprintf(index_info->mpd_file, "     <SegmentURL media=\"%s\" index=\"%s\"/>\n", media_file_name, index_info->index_file_name);
+       if (index_info->seg_name && index_info->use_url_template) {
+               fprintf(index_info->mpd_file, "    </SegmentTemplate>\n");
        } else {
-               fprintf(index_info->mpd_file, "    <Url sourceURL=\"%s\"/>\n", media_file_name);
-               fprintf(index_info->mpd_file, "    <Index sourceURL=\"%s\"/>\n", index_info->index_file_name);
+               fprintf(index_info->mpd_file, "    </SegmentList>\n");
        }
-       fprintf(index_info->mpd_file, "   </SegmentInfo>\n");
 }
 
-void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num, 
+void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, 
                                   Double dash_duration, Bool seg_at_rap, u32 subseg_per_seg,
-                                  char *seg_name, char *seg_ext, Bool use_url_template, Bool use_index_segment)
+                                  char *seg_name, char *seg_ext, Bool use_url_template, Bool single_segment, u32 representation_idx, Bool is_last_rep)
 {
        char data[188];
        GF_M2TS_Dump dumper;
+
        u32 size;
        u64 fsize, fdone;
        GF_M2TS_Demuxer *ts;
        FILE *src;
 
        src = gf_f64_open(mpeg2ts_file, "rb");
-
+       if (!src) {
+               fprintf(stderr, "Cannot open %s: no such file\n", mpeg2ts_file);
+               return;
+       }
        ts = gf_m2ts_demux_new();
        ts->on_event = on_m2ts_dump_event;
        memset(&dumper, 0, sizeof(GF_M2TS_Dump));
        ts->user = &dumper;
        dumper.prog_number = prog_num;
-       
+
+
        if (dash_duration) {
-               char *c;
+               char *c, *f;
                dumper.index_info.segment_duration = dash_duration;
                dumper.index_info.segment_at_rap = seg_at_rap;
                dumper.index_info.subsegs_per_segment = subseg_per_seg;
-               dumper.index_info.seg_name = seg_name ? gf_strdup(seg_name) : NULL;
                dumper.index_info.use_url_template = use_url_template;
                dumper.index_info.init_seg_name = NULL;
-               dumper.index_info.use_index_segment = use_index_segment;
+               dumper.index_info.single_segment = single_segment;
+               dumper.index_info.seg_name = seg_name;
+               dumper.index_info.seg_ext = seg_ext ? seg_ext : "ts";
+               
                c = strrchr(mpeg2ts_file, '.');
                if (c) *c = 0;
-               sprintf(dumper.index_info.index_file_name, "%s_index.%s", mpeg2ts_file, (seg_ext?seg_ext:"m4s"));
+               f = strrchr(mpeg2ts_file, '/');
+               if (!f) f = strrchr(mpeg2ts_file, '\\');
+               sprintf(dumper.index_info.index_file_name, "%s_index.%s", f ? f+1 : mpeg2ts_file, (seg_ext?seg_ext:"didx"));
                if (c) *c = '.';
-               dumper.index_info.index_file = gf_f64_open(dumper.index_info.index_file_name, "wb");
-               dumper.index_info.index_bs = gf_bs_from_file(dumper.index_info.index_file, GF_BITSTREAM_WRITE);
-               {
-                       GF_SegmentTypeBox *styp = (GF_SegmentTypeBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_STYP);
-                       styp->majorBrand = GF_4CC('i','s','s','s');
-                       styp->minorVersion = 0;
-                       styp->altBrand = (u32*)gf_malloc(sizeof(u32));
-                       styp->altBrand[0] = styp->majorBrand;
-                       styp->altCount = 1;
-                       gf_isom_box_size((GF_Box *)styp);
-                       gf_isom_box_write((GF_Box *)styp, dumper.index_info.index_bs);
-                       gf_isom_box_del((GF_Box *)styp);
+               
+               dumper.index_info.index_file = NULL;
+               dumper.index_info.index_bs = NULL;
+               if (dumper.index_info.use_url_template!=2) {
+                       dumper.index_info.index_file = gf_f64_open(dumper.index_info.index_file_name, "wb");
+                       dumper.index_info.index_bs = gf_bs_from_file(dumper.index_info.index_file, GF_BITSTREAM_WRITE);
+                       {
+                               GF_SegmentTypeBox *styp = (GF_SegmentTypeBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_STYP);
+                               styp->majorBrand = GF_4CC('s','i','s','x');
+                               styp->minorVersion = 0;
+                               styp->altBrand = (u32*)gf_malloc(sizeof(u32));
+                               styp->altBrand[0] = styp->majorBrand;
+                               styp->altCount = 1;
+                               gf_isom_box_size((GF_Box *)styp);
+                               gf_isom_box_write((GF_Box *)styp, dumper.index_info.index_bs);
+                               gf_isom_box_del((GF_Box *)styp);
+                       }
+               }
+       }
+       /*PES dumping*/
+       else if (out_name) {
+               char *pid = strrchr(out_name, '#');
+               if (pid) {
+                       dumper.dump_pid = atoi(pid+1);
+                       pid[0] = 0;
+                       sprintf(dumper.dump, "%s_%d.raw", out_name, dumper.dump_pid);
+                       dumper.pes_out = gf_f64_open(dumper.dump, "wb");
+#if 0
+                       sprintf(dumper.nhml, "%s_%d.nhml", pes_out_name, dumper.dump_pid);
+                       dumper.pes_out_nhml = gf_f64_open(dumper.nhml, "wt");
+                       sprintf(dumper.info, "%s_%d.info", pes_out_name, dumper.dump_pid);
+                       dumper.pes_out_info = gf_f64_open(dumper.info, "wb");
+#endif
+                       pid[0] = '#';
                }
        }
 
+
        gf_f64_seek(src, 0, SEEK_END);
        fsize = gf_f64_tell(src);
        gf_f64_seek(src, 0, SEEK_SET);
@@ -2484,29 +2659,29 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num,
                fprintf(dumper.timestamps_info_file, "PCK#\tPID\tPCR\tDTS\tPTS\tRAP\tDiscontinuity\n");
        }
 
-       if (pes_out_name) {
-               char *pid = strrchr(pes_out_name, '#');
-               if (pid) {
-                       dumper.dump_pid = atoi(pid+1);
-                       pid[0] = 0;
-                       sprintf(dumper.dump, "%s_%d.media", pes_out_name, dumper.dump_pid);
-                       dumper.pes_out = gf_f64_open(dumper.dump, "wb");
-                       sprintf(dumper.nhml, "%s_%d.nhml", pes_out_name, dumper.dump_pid);
-                       dumper.pes_out_nhml = gf_f64_open(dumper.nhml, "wt");
-                       sprintf(dumper.info, "%s_%d.info", pes_out_name, dumper.dump_pid);
-                       dumper.pes_out_info = gf_f64_open(dumper.info, "wb");
-                       pid[0] = '#';
-               }
-       }
-
        gf_m2ts_reset_parsers(ts);
        gf_f64_seek(src, 0, SEEK_SET);
        fdone = 0;
        if (dumper.index_info.segment_duration) {
+               char *sep;
                dumper.index_info.start_indexing = 1;
                fprintf(stderr, "Starting indexing ...\n");
-               sprintf(dumper.index_info.mpd_file_name, "%s.mpd", mpeg2ts_file);
-               dumper.index_info.mpd_file = gf_f64_open(dumper.index_info.mpd_file_name, "wt");
+               if (out_name) {
+                       strcpy(dumper.index_info.mpd_file_name, out_name);
+               } else {
+                       sep = strrchr(mpeg2ts_file, '/');
+                       if (!sep) sep = strrchr(mpeg2ts_file, '\\');
+                       strcpy(dumper.index_info.mpd_file_name, sep ? sep+1 : mpeg2ts_file);
+                       sep = strrchr(dumper.index_info.mpd_file_name, '.');
+                       if (sep) sep[0] = 0;
+                       strcat(dumper.index_info.mpd_file_name, ".mpd");
+               }
+               if (!representation_idx) {
+                       dumper.index_info.mpd_file = gf_f64_open(dumper.index_info.mpd_file_name, "wt");
+               } else {
+                       dumper.index_info.mpd_file = gf_f64_open(dumper.index_info.mpd_file_name, "a+t");
+               }
+               dumper.index_info.represantation_idx = representation_idx;
        }
        while (!feof(src)) {
                size = fread(data, 1, 188, src);
@@ -2527,27 +2702,27 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num,
                m2ts_sidx_finalize_size(&dumper.index_info, file_size);
                fprintf(stderr, "Indexing done (1 sidx, %d entries).\n", dumper.index_info.sidx->nb_refs);
 
-               mpd_start(dumper.index_info.mpd_file, 1, mpeg2ts_file, (dumper.index_info.last_PTS-dumper.index_info.first_PTS)/90000.0, 
-                       "video/mp2t", NULL, 0, 0, 0, 0, "", dumper.index_info.segment_at_rap, file_size, dumper.index_info.segment_duration);
+               mpd_start(&dumper.index_info, 1, mpeg2ts_file, (dumper.index_info.last_PTS-dumper.index_info.first_PTS)/90000.0, dumper.index_info.segment_at_rap, file_size, dumper.index_info.segment_duration/4);
                write_mpd_segment_info(&dumper.index_info, mpeg2ts_file);
-               mpd_end(dumper.index_info.mpd_file);
+               mpd_end(dumper.index_info.mpd_file, is_last_rep);
        }
 
        fclose(src);
        gf_m2ts_demux_del(ts);
        if (dumper.pes_out) fclose(dumper.pes_out);
+#if 0
        if (dumper.pes_out_nhml) {
                if (dumper.is_info_dumped) fprintf(dumper.pes_out_nhml, "</NHNTStream>\n");
                fclose(dumper.pes_out_nhml);
                fclose(dumper.pes_out_info);
        }
+#endif
        if (dumper.timestamps_info_file) fclose(dumper.timestamps_info_file);
        if (dumper.index_info.sidx) {
                gf_isom_box_size((GF_Box *)dumper.index_info.sidx);
                if (dumper.index_info.index_bs) gf_isom_box_write((GF_Box *)dumper.index_info.sidx, dumper.index_info.index_bs);
                gf_isom_box_del((GF_Box *)dumper.index_info.sidx);
        }
-       if (dumper.index_info.seg_name) gf_free(dumper.index_info.seg_name);
        if (dumper.index_info.mpd_file) fclose(dumper.index_info.mpd_file);
        if (dumper.index_info.index_file) fclose(dumper.index_info.index_file);
        if (dumper.index_info.index_bs) gf_bs_del(dumper.index_info.index_bs);
index b45d9229c80103c1ff91665742aec0391a23d2c5..97fb414d56b1b2da369d04eb9e72e7b25b30da0d 100644 (file)
@@ -75,7 +75,7 @@ void convert_file_info(char *inName, u32 trackID)
                case GF_ISOM_MEDIA_AUDIO: fprintf(stdout, "Audio (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break;
                case GF_ISOM_MEDIA_TEXT: fprintf(stdout, "Text (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break;
                case GF_ISOM_MEDIA_SCENE: fprintf(stdout, "Scene (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break;
-               case GF_ISOM_MEDIA_OD: fprintf(stdout, "ObjectDescriptor (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break;
+               case GF_ISOM_MEDIA_OD: fprintf(stdout, "OD (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break;
                default: fprintf(stdout, "Other (4CC: %s)", gf_4cc_to_str(import.tk_info[i].type)); break;
                }
 
@@ -142,7 +142,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
        const char *szLan;
        GF_Err e;
        GF_MediaImporter import;
-       char *ext, szName[1000], *fmt, *handler_name, *rvc_config;
+       char *ext, szName[1000], *handler_name, *rvc_config;
        rvc_predefined = 0;
 
        memset(&import, 0, sizeof(GF_MediaImporter));
@@ -173,7 +173,6 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
 
        handler_name = NULL;
        rvc_config = NULL;
-       fmt = NULL;
        while (ext) {
                char *ext2 = strchr(ext+1, ':');
                if (ext2 && !strncmp(ext2, "://", 3)) ext2 = strchr(ext2+1, ':');
@@ -206,6 +205,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                else if (!stricmp(ext+1, "svc")) import_flags |= GF_IMPORT_SVC_EXPLICIT;
                else if (!stricmp(ext+1, "nosvc")) import_flags |= GF_IMPORT_SVC_NONE;
                else if (!stricmp(ext+1, "subsamples")) import_flags |= GF_IMPORT_SET_SUBSAMPLES;
+               else if (!stricmp(ext+1, "forcesync")) import_flags |= GF_IMPORT_FORCE_SYNC;
                else if (!stricmp(ext+1, "mpeg4")) import_flags |= GF_IMPORT_FORCE_MPEG4;
                else if (!strnicmp(ext+1, "agg=", 4)) frames_per_sample = atoi(ext+5);
                else if (!strnicmp(ext+1, "dur=", 4)) import.duration = (u32) (atof(ext+5) * 1000);
@@ -299,6 +299,10 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                                }
                        }
                }
+               else if (!strnicmp(ext, "prog_id=", 8)) { 
+                       prog_id = atoi(ext+8);
+                       do_all = 0;
+               }
                else track_id = atoi(ext);
        }
        if (do_audio || do_video || track_id) do_all = 0;
@@ -357,7 +361,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                                if (delay>0) {
                                        gf_isom_append_edit_segment(import.dest, i+1, (timescale*delay)/1000, 0, GF_ISOM_EDIT_EMPTY);
                                        gf_isom_append_edit_segment(import.dest, i+1, tk_dur, 0, GF_ISOM_EDIT_NORMAL);
-                               } else {
+                               } else if (delay<0) {
                                        u64 to_skip = (timescale*(-delay))/1000;
                                        if (to_skip<tk_dur) {
                                                //u64 seg_dur = (-delay)*gf_isom_get_media_timescale(import.dest, i+1) / 1000;
@@ -373,7 +377,13 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                        if (handler_name) gf_isom_set_handler_name(import.dest, i+1, handler_name);
                        else if (!keep_handler) {
                                char szHName[1024];
-                               sprintf(szHName, "%s - Imported with GPAC %s", inName, GPAC_FULL_VERSION);
+                               char *fName = strrchr(inName, '/');
+                               if (!fName) fName = strrchr(inName, '\\');
+
+                               if (!fName) fName = inName;
+                               else fName = fName+1;
+
+                               sprintf(szHName, "%s - Imported with GPAC %s", fName, GPAC_FULL_VERSION);
                                gf_isom_set_handler_name(import.dest, i+1, szHName);
                        }
                        if (handler) gf_isom_set_media_type(import.dest, i+1, handler);
@@ -437,8 +447,8 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                                } else {
                                        u64 to_skip = (timescale*(-delay))/1000;
                                        if (to_skip<tk_dur) {
-                                               //u64 seg_dur = (-delay)*gf_isom_get_media_timescale(import.dest, i+1) / 1000;
-                                               gf_isom_append_edit_segment(import.dest, i+1, tk_dur-to_skip, to_skip, GF_ISOM_EDIT_NORMAL);
+                                               u64 media_time = (-delay)*gf_isom_get_media_timescale(import.dest, track) / 1000;
+                                               gf_isom_append_edit_segment(import.dest, i+1, tk_dur-to_skip, media_time, GF_ISOM_EDIT_NORMAL);
                                        } else {
                                                fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n");
                                        }
@@ -450,7 +460,13 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                        if (handler_name) gf_isom_set_handler_name(import.dest, track, handler_name);
                        else if (!keep_handler) {
                                char szHName[1024];
-                               sprintf(szHName, "%s - Imported with GPAC %s", inName, GPAC_FULL_VERSION);
+                               char *fName = strrchr(inName, '/');
+                               if (!fName) fName = strrchr(inName, '\\');
+
+                               if (!fName) fName = inName;
+                               else fName = fName+1;
+
+                               sprintf(szHName, "%s - Imported with GPAC %s", fName, GPAC_FULL_VERSION);
                                gf_isom_set_handler_name(import.dest, track, szHName);
                        }
                        if (handler) gf_isom_set_media_type(import.dest, track, handler);
@@ -531,7 +547,7 @@ typedef struct
        u32 stop_state;
 } TKInfo;
 
-GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start_time, const char *tmpdir)
+GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start_time, Bool adjust_split_end, const char *tmpdir)
 {
        u32 i, count, nb_tk, needs_rap_sync, cur_file, conv_type, nb_tk_done, nb_samp, nb_done, di;
        Double max_dur, cur_file_time;
@@ -818,7 +834,8 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb,
                                        last_rap_sample_time = (Double) (s64) samp->DTS;
                                        last_rap_sample_time /= tki->time_scale;
                                        e = gf_isom_get_sample_for_media_time(mp4, tki->tk, samp->DTS+tki->firstDTS+2, &sdi, GF_ISOM_SEARCH_SYNC_FORWARD, &next_rap, &next_rap_num);
-                                       if (e==GF_EOS) is_last = 1;
+                                       if (e==GF_EOS)
+                                               is_last = 1;
                                        if (next_rap) {
                                                if (!next_rap->IsRAP) 
                                                        is_last = 1;
@@ -872,8 +889,8 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb,
                                ) {
                                        nb_over++;
                                        tki->stop_state = 1;
-                                       if (tki->last_sample<tki->sample_count) is_last = 0;
-                                       if ((!tki->can_duplicate || all_duplicatable) && (tki->last_sample==tki->sample_count)) is_last = 1;
+                                       if (tki->last_sample<tki->sample_count)
+                                               is_last = 0;
 
                                        if (rap_split && tki->next_sample_is_rap) {
                                                file_split_dur = (Double) ( gf_isom_get_sample_dts(mp4, tki->tk, tki->last_sample+1) - tki->firstDTS);
@@ -920,7 +937,15 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb,
                        fprintf(stdout, "Cannot split file (duration too small or size too small)\n");
                        goto err_exit;
                }
-               if (chunk_extraction) file_split_dur = split_dur;
+               if (chunk_extraction) {
+                       if (adjust_split_end) {
+                               fprintf(stdout, "Adjusting chunk end time to previous random access at %02.2f sec\n", chunk_start + last_rap_sample_time);
+                               file_split_dur = last_rap_sample_time;
+                               sprintf(szFile, "%s_%d_%d%s", szName, (u32) chunk_start, (u32) (chunk_start+file_split_dur), ext);
+                               gf_isom_set_final_name(dest, szFile);
+                       }
+                       else file_split_dur = split_dur;
+               }
 
                /*don't split if eq to copy...*/
                if (is_last && !cur_file && !chunk_start) {
@@ -1157,7 +1182,6 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
        for (i=0; i<nb_tracks; i++) {
                u64 last_DTS, dest_track_dur_before_cat;
                u32 nb_edits = 0;
-               Bool new_track = 0;
                Bool use_ts_dur = 1;
                Bool merge_edits = 0;
                mtype = gf_isom_get_media_type(orig, i+1);
@@ -1191,7 +1215,7 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        /*we only support cat with the same number of sample descriptions*/
                        if (gf_isom_get_sample_description_count(orig, i+1) != gf_isom_get_sample_description_count(dest, dst_tk)) dst_tk = 0;
                        /*if not forcing cat, check the media codec config is the same*/
-                       if (!gf_isom_is_same_sample_description(orig, i+1, dest, dst_tk)) {
+                       if (!gf_isom_is_same_sample_description(orig, i+1, 0, dest, dst_tk, 0)) {
                                dst_tk = 0;
                        } 
                        /*we force the same visual resolution*/
@@ -1282,7 +1306,7 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                if (!dst_tk) {
                        for (j=0; j<gf_isom_get_track_count(dest); j++) {
                                if (mtype != gf_isom_get_media_type(dest, j+1)) continue;
-                               if (gf_isom_is_same_sample_description(orig, i+1, dest, j+1)) {
+                               if (gf_isom_is_same_sample_description(orig, i+1, 0, dest, j+1, 0)) {
                                        if (mtype==GF_ISOM_MEDIA_VISUAL) {
                                                u32 w, h, ow, oh;
                                                gf_isom_get_visual_info(orig, i+1, 1, &ow, &oh);
@@ -1318,7 +1342,6 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        e = gf_isom_clone_track(orig, i+1, dest, 1, &dst_tk);
                        if (e) goto err_exit;
                        gf_isom_clone_pl_indications(orig, dest);
-                       new_track = 1;
                        /*remove cloned edit list, as it will be rewritten after import*/
                        gf_isom_remove_edit_segments(dest, dst_tk);
                } else {
@@ -1637,18 +1660,14 @@ GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *log
                fprintf(stdout, "Error loading file %s\n", gf_error_to_string(e));
                goto err_exit;
        } else {
-               u32 prev_level = gf_log_get_level();
-               u32 prev_tools = gf_log_get_tools();
                gf_log_cbk prev_logs = NULL;
                if (logs) {
-                       gf_log_set_tools(GF_LOG_CODING);
-                       gf_log_set_level(GF_LOG_DEBUG);
+                       gf_log_set_tool_level(GF_LOG_CODING, GF_LOG_DEBUG);
                        prev_logs = gf_log_set_callback(logs, scene_coding_log);
                }
                e = gf_sm_encode_to_file(ctx, mp4, opts);
                if (logs) {
-                       gf_log_set_tools(prev_tools);
-                       gf_log_set_level(prev_level);
+                       gf_log_set_tool_level(GF_LOG_CODING, GF_LOG_ERROR);
                        gf_log_set_callback(NULL, prev_logs);
                }
        }
@@ -1687,7 +1706,7 @@ GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCa
        u32 i, j, count;
        GF_StreamContext *sc;
        GF_ESD *esd;
-       Bool is_in_iod, delete_desc, encode_names, delete_bcfg;
+       Bool encode_names, delete_bcfg;
        GF_BIFSConfig *bcfg;
        GF_AUContext            *au;
        char szRad[GF_MAX_PATH], *ext;
@@ -1722,24 +1741,19 @@ GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCa
                esd = NULL;
                if (sc->streamType != GF_STREAM_SCENE) continue;
 
-               delete_desc = 0;
                esd = NULL;
-               is_in_iod = 1;
                if (iod) {
-                       is_in_iod = 0;
                        for (j=0; j<gf_list_count(iod->ESDescriptors); j++) {
                                esd = gf_list_get(iod->ESDescriptors, j);
                                if (esd->decoderConfig && esd->decoderConfig->streamType == GF_STREAM_SCENE) {
                                        if (!sc->ESID) sc->ESID = esd->ESID;
                                        if (sc->ESID == esd->ESID) {
-                                               is_in_iod = 1;
                                                break;
                                        }
                                }
                                /*special BIFS direct import from NHNT*/
                                else if (gf_list_count(iod->ESDescriptors)==1) {
                                        sc->ESID = esd->ESID;
-                                       is_in_iod = 1;
                                        break;
                                }
                                esd = NULL;
@@ -1747,7 +1761,6 @@ GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCa
                }
 
                if (!esd) {
-                       delete_desc = 1;
                        esd = gf_odf_desc_esd_new(2);
                        gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
                        esd->decoderConfig->decoderSpecificInfo = NULL;
@@ -1811,7 +1824,7 @@ GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCa
                        if (data) {
                                sprintf(szName, "%s%02d.bifs", szRad, j);
                                f = gf_f64_open(szName, "wb");
-                               fwrite(data, data_len, 1, f);
+                               gf_fwrite(data, data_len, 1, f);
                                fclose(f);
                                gf_free(data);
                        }
index ef26ac2036db5cf5584bd8e818166f69b7c8fa3d..aafaf5b989fe350aec907848c826c16039cde6fb 100644 (file)
@@ -89,8 +89,7 @@ int stream_file_rtp(int argc, char **argv)
 
        gf_sys_init(0);
 
-       gf_log_set_tools(GF_LOG_RTP);
-       gf_log_set_level(GF_LOG_WARNING);       //set to debug to have packet list
+       gf_log_set_tool_level(GF_LOG_RTP, GF_LOG_WARNING);      //set to debug to have packet list
 
        file_streamer = gf_isom_streamer_new(inName, ip_dest, port, loop, force_mpeg4, path_mtu, ttl, ifce_addr);
        if (!file_streamer) {
@@ -131,6 +130,7 @@ void PrintLiveUsage()
                "-sdp=Name  ouput SDP file - default: session.sdp\n"
                "\n"
                "-dims      turns on DIMS mode for SVG input - default: off\n"
+               "-no-rap    disabled RAP sending - this also disables carousel generation. Default: off\n"
                "-src=file  source of updates - default: null\n"
                "-rap=time  duration in ms of base carousel - default: 0 (off)\n"
                "            you can specify the RAP period of a single ESID (not in DIMS):\n"
@@ -428,7 +428,7 @@ int live_session(int argc, char **argv)
        s32 next_time;
        u64 last_src_modif, mod_time;
        char *src_name = NULL;
-       Bool run, has_carousel, skip_init_scene;
+       Bool run, has_carousel, no_rap;
     Bool udp = 0;
        u16 sk_port=0;
     GF_Socket *sk = NULL;
@@ -445,13 +445,12 @@ int live_session(int argc, char **argv)
        /* souchay : needs to initialize those two vars... */
        aggregate_au = 1;
        es_id = 0;
-       skip_init_scene = 0;
+       no_rap = 0;
        gf_sys_init(0);
 
        memset(&livesess, 0, sizeof(LiveSession));
        
-       gf_log_set_level(GF_LOG_INFO);
-       gf_log_set_tools(0xFFFFFFFF);
+       gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_INFO);
 
        for (i=1; i<argc; i++) {
                char *arg = argv[i];
@@ -462,15 +461,11 @@ int live_session(int argc, char **argv)
                else if (!strnicmp(arg, "-mtu=", 5)) path_mtu = atoi(arg+5);
                else if (!strnicmp(arg, "-ttl=", 5)) ttl = atoi(arg+5);
                else if (!strnicmp(arg, "-ifce=", 6)) ifce_addr = arg+6;
-
-        else if (!strnicmp(arg, "-dims-stream", 12)) { 
-                       load_type = GF_SM_LOAD_DIMS;
-                       skip_init_scene = 1;
-               }
+        else if (!strnicmp(arg, "-no-rap", 7)) no_rap = 1;
                else if (!strnicmp(arg, "-dims", 5)) load_type = GF_SM_LOAD_DIMS;
                else if (!strnicmp(arg, "-src=", 5)) src_name = arg+5;
         else if (!strnicmp(arg, "-udp=", 5)) { sk_port = atoi(arg+5); udp = 1; }
-        else if (!strnicmp(arg, "-tcp=", 5)) { sk_port = atoi(arg+5); udp = 0; }
+        else if (!strnicmp(arg, "-tcp=", 5)) { sk_port = atoi(arg+5); udp = 0; }               
        }
        if (!filename) {
                fprintf(stdout, "Missing filename\n");
@@ -539,7 +534,7 @@ int live_session(int argc, char **argv)
 
        update_context = 0;
 
-       if (has_carousel || !skip_init_scene) {
+       if (has_carousel || !no_rap) {
                livesess.carousel_generation = 1;
                gf_seng_encode_context(livesess.seng, live_session_callback);
                livesess.carousel_generation = 0;
@@ -685,7 +680,7 @@ int live_session(int argc, char **argv)
                                if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e));
                                e = gf_seng_aggregate_context(livesess.seng, 0);
 
-                               update_context = 1;
+                               update_context = no_rap ? 0 : 1;
                        }
                }
 
@@ -693,7 +688,6 @@ int live_session(int argc, char **argv)
                if (sk) {
                    char buffer[2049];
                    u32 bytes_read;
-                   Bool keep_receive;
                    u32 update_length;
                    u32 bytes_received;
 
@@ -746,14 +740,12 @@ int live_session(int argc, char **argv)
                                        e = gf_sk_receive(sk, buffer, 2048, 0, &bytes_read);
                                        switch (e) {
                                        case GF_IP_NETWORK_EMPTY:
-                                               keep_receive = 0;
                                                break;
                                        case GF_OK:
                                                memcpy(update_buffer+bytes_received, buffer, bytes_read);
                                                bytes_received += bytes_read;
                                                break;
                                        default:
-                                               keep_receive = 0;
                                                fprintf(stderr, "Error with UDP socket : %s\n", gf_error_to_string(e));
                                                break;
                                        }
index a0b0cc38bc74773c5ad7a2320e7d9573110fa498..332aaafb633962820879d8d4511286fdf97ec8e8 100644 (file)
@@ -48,7 +48,7 @@
 #ifndef GPAC_DISABLE_ISOM_WRITE
 void convert_file_info(char *inName, u32 trackID);
 GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample);
-GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start, const char *tmpdir);
+GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start, Bool adjust_split_end, const char *tmpdir);
 GF_Err cat_isomedia_file(GF_ISOFile *mp4, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat);
 
 #ifndef GPAC_DISABLE_SCENE_ENCODER
@@ -102,7 +102,7 @@ const char *GetLanguageCode(char *lang);
 #ifndef GPAC_DISABLE_MPEG2TS
 void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num, 
                                   Double dash_duration, Bool seg_at_rap, u32 subseg_per_seg,
-                                  char *seg_name, char *seg_ext, Bool use_url_template, Bool use_index_segment);
+                                  char *seg_name, char *seg_ext, Bool use_url_template, Bool single_segment, u32 representation_idx, Bool last_rep);
 #endif 
 
 
@@ -214,6 +214,8 @@ void PrintGeneralUsage()
                        "                       * Note: this removes all MPEG-4 Systems media\n"
                        " -split-chunk S:E     extracts a new file from Start to End (in seconds). same as -splitx\n"
                        "                       * Note: this removes all MPEG-4 Systems media\n"
+                       " -splitz S:E          same as -split-chunk, but adjust the end time to be before the last RAP sample\n"
+                       "                       * Note: this removes all MPEG-4 Systems media\n"
                        " -group-add fmt       creates a new grouping information in the file. Format is\n"
                        "                      a colon-separated list of following options:\n"
                        "                      refTrack=ID: ID of the track used as a group reference.\n"
@@ -233,13 +235,15 @@ void PrintGeneralUsage()
                        " -group-rem-track ID  removes track from its group\n"
                        " -group-rem ID        removes the track's group\n"
                        " -group-clean         removes all group information from all tracks\n"
+               " -group-single        puts all tracks in a single group\n"
                        " -ref id:XXXX:refID   adds a reference of type 4CC from track ID to track refID\n"
                        "\n"
                        " -dash dur            enables DASH-ing of the file with a segment duration of DUR\n"
                        "                       Note: the duration of a fragment (subsegment) is set\n"
                        "                                               using the interleaver (-inter) switch.\n"
                        "                       Note: You can specify -rap switch to split segments at RAP boundaries\n"
-                       " -frags-per-sidx N    sets the number of segments to be written in each SIDX box\n"
+                       "                       Note: when single-segment is used, this specifies the duration of a subsegment\n"
+                       " -subsegs-per-sidx N  sets the number of subsegments to be written in each SIDX box\n"
                        "                       If 0, a single SIDX box is used per segment\n"
                        "                       If -1, no SIDX box is used\n"
                        " -rap                 segments begin with random access points\n"
@@ -248,9 +252,10 @@ void PrintGeneralUsage()
                        " -segment-name name   sets the segment name for generated segments\n"
                        "                       If not set (default), segments are concatenated in output file\n"
                        " -segment-ext name    sets the segment extension. Default is m4s\n"
-                       " -url-template        uses UrlTemplate instead of explicit sources in segments.\n"
+                       " -url-template        uses SegmentTemplate instead of explicit sources in segments.\n"
                        "                       Ignored if segments are stored in the output file.\n"
                        " -daisy-chain         Uses daisy-chain SIDX instead of hierarchical. Ignored if frags/sidx is 0.\n"
+                       " -single-segment      Uses a single segment for the whole file (OnDemand profile). \n"
                        " -dash-ctx FILE       Stores/restore DASH timing from FILE.\n"
                        " -dash-ts-prog N      program_number to be considered in case of an MPTS input file.\n"
                        "\n");
@@ -330,6 +335,8 @@ void PrintImportUsage()
                        " \":svc\"               import SVC with explicit signaling (no AVC base compatibility)\n"
                        " \":nosvc\"             discard SVC data when importing\n"
                        " \":subsamples\"        adds SubSample information for AVC+SVC\n"
+                       " \":forcesync\"         forces non IDR samples with I slices to be marked as sync points (AVC GDR)\n"
+                       "       !! RESULTING FILE IS NOT COMPLIANT WITH THE SPEC but will fix seeking in most players\n"
                        " \":font=name\"         specifies font name for text import (default \"Serif\")\n"
                        " \":size=s\"            specifies font size for text import (default 18)\n"
                        " \":stype=4CC\"         forces the sample description type to a different value\n"
@@ -609,6 +616,7 @@ void PrintUsage()
                        " -quiet                quiet mode\n"
                        " -noprog               disables progress\n"
                        " -v                   verbose mode\n"
+                       " -logs                set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
                        " -version             gets build version\n"
                        );
 }
@@ -654,7 +662,7 @@ void SetupClockReferences(GF_ISOFile *file)
 /*base RTP payload type used (you can specify your own types if needed)*/
 #define BASE_PAYT              96
 
-GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 base_flags, Bool copy_data, Bool interleave, Bool regular_iod)
+GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 base_flags, Bool copy_data, Bool interleave, Bool regular_iod, Bool single_group)
 {
        GF_ESD *esd;
        GF_InitialObjectDescriptor *iod;
@@ -682,7 +690,7 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32
        }
 
        spec_type = gf_isom_guess_specification(file);
-       single_av = gf_isom_is_single_av(file);
+       single_av = single_group ? 1 : gf_isom_is_single_av(file);
 
        /*first make sure we use a systems track as base OCR*/
        for (i=0; i<gf_isom_get_track_count(file); i++) {
@@ -1185,6 +1193,8 @@ enum
        GF_ISOM_CONV_TYPE_PSP
 };
 
+/*for dash*/
+#define MAX_DASH_REP   30
 
 int mp4boxMain(int argc, char **argv)
 {
@@ -1199,23 +1209,26 @@ int mp4boxMain(int argc, char **argv)
        TrackAction tracks[MAX_CUMUL_OPS];
        TSELAction tsel_acts[MAX_CUMUL_OPS];
        u64 movie_time;
-       s32 frags_per_sidx;
-       u32 brand_add[MAX_CUMUL_OPS], brand_rem[MAX_CUMUL_OPS];
+       s32 subsegs_per_sidx;
+       u32 brand_add[MAX_CUMUL_OPS];
        u32 i, MTUSize, stat_level, hint_flags, info_track_id, import_flags, nb_add, nb_cat, ismaCrypt, agg_samples, nb_sdp_ex, max_ptime, raw_sample_num, split_size, nb_meta_act, nb_track_act, rtp_rate, major_brand, nb_alt_brand_add, nb_alt_brand_rem, old_interleave, car_dur, minor_version, conv_type, nb_tsel_acts, program_number;
        Bool HintIt, needSave, FullInter, Frag, HintInter, dump_std, dump_rtp, dump_mode, regular_iod, trackID, HintCopy, remove_sys_tracks, remove_hint, force_new, remove_root_od, import_subtitle, dump_chap;
-       Bool print_sdp, print_info, open_edit, track_dump_type, dump_isom, dump_cr, force_ocr, encode, do_log, do_flat, dump_srt, dump_ttxt, x3d_info, chunk_mode, dump_ts, do_saf, do_mpd, dump_m2ts, dump_cart, do_hash, verbose, force_cat, pack_wgt, dash_ts_use_index;
+       Bool print_sdp, print_info, open_edit, track_dump_type, dump_isom, dump_cr, force_ocr, encode, do_log, do_flat, dump_srt, dump_ttxt, chunk_mode, dump_ts, do_saf, do_mpd, dump_m2ts, dump_cart, do_hash, verbose, force_cat, pack_wgt, single_group;
        char *inName, *outName, *arg, *mediaSource, *tmpdir, *input_ctx, *output_ctx, *drm_file, *avi2raw, *cprt, *chap_file, *pes_dump, *itunes_tags, *pack_file, *raw_cat, *seg_name, *dash_ctx;
        GF_ISOFile *file;
        Bool stream_rtp=0;
        Bool live_scene=0;
-#ifdef GPAC_MEMORY_TRACKING
        Bool enable_mem_tracker = 0;
-#endif
        Bool dump_iod=0;
        Bool daisy_chain_sidx=0;
+       Bool single_segment=0;
        Bool use_url_template=0;
        Bool seg_at_rap =0;
-       char *seg_ext = "m4s";
+       Bool adjust_split_end = 0;
+       char *dash_inputs[MAX_DASH_REP];
+       u32 nb_dash_inputs = 0;
+       char *gf_logs = NULL;
+       char *seg_ext = NULL;
 
        if (argc < 2) {
                PrintUsage();
@@ -1228,16 +1241,15 @@ int mp4boxMain(int argc, char **argv)
        split_start = -1.0;
        InterleavingTime = 0.5;
        dash_duration = 0.0;
-       dash_ts_use_index = 0;
        import_fps = 0;
        import_flags = 0;
        split_size = 0;
        movie_time = 0;
        MTUSize = 1450;
        HintCopy = FullInter = HintInter = encode = do_log = old_interleave = do_saf = do_mpd = do_hash = verbose = 0;
-       chunk_mode = dump_mode = Frag = force_ocr = remove_sys_tracks = agg_samples = remove_hint = keep_sys_tracks = remove_root_od = 0;
-       x3d_info = conv_type = HintIt = needSave = print_sdp = print_info = regular_iod = dump_std = open_edit = dump_isom = dump_rtp = dump_cr = dump_chap = dump_srt = dump_ttxt = force_new = dump_ts = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = 0;
-       frags_per_sidx = 0;
+       chunk_mode = dump_mode = Frag = force_ocr = remove_sys_tracks = agg_samples = remove_hint = keep_sys_tracks = remove_root_od = single_group = 0;
+       conv_type = HintIt = needSave = print_sdp = print_info = regular_iod = dump_std = open_edit = dump_isom = dump_rtp = dump_cr = dump_chap = dump_srt = dump_ttxt = force_new = dump_ts = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = 0;
+       subsegs_per_sidx = 0;
        track_dump_type = 0;
        ismaCrypt = 0;
        file = NULL;
@@ -1264,13 +1276,38 @@ int mp4boxMain(int argc, char **argv)
                /*main file*/
 //             if (isalnum(arg[0]) || (arg[0]=='/') || (arg[0]=='.') || (arg[0]=='\\') ) {
                if (arg[0] != '-') {
-                       if (inName) { fprintf(stdout, "Error - 2 input names specified, please check usage\n"); return 1; }
-                       inName = arg;
+                       if (argc < 3) {
+                               fprintf(stdout, "Error - only one input file found as argument, please check usage\n"); 
+                               return 1; 
+                       } else if (inName) { 
+                               if (dash_duration) {
+                                       if (!nb_dash_inputs) {
+                                               dash_inputs[nb_dash_inputs] = inName;
+                                               nb_dash_inputs++;
+                                       }
+                                       if (MAX_DASH_REP<=nb_dash_inputs) {
+                                               fprintf(stdout, "Error - Max %d representations can be DASH'ed\n", MAX_DASH_REP);
+                                               return 1; 
+                                       }
+                                       dash_inputs[nb_dash_inputs] = arg;
+                                       nb_dash_inputs++;                                       
+                               } else {
+                                       fprintf(stdout, "Error - 2 input names specified, please check usage\n");
+                                       return 1; 
+                               }
+                       } else {
+                               inName = arg;
+                       }
                }
                else if (!stricmp(arg, "-?")) { PrintUsage(); return 0; }
                else if (!stricmp(arg, "-version")) { PrintVersion(); return 0; }
                else if (!stricmp(arg, "-sdp")) print_sdp = 1;
                else if (!stricmp(arg, "-quiet")) quiet = 2;
+               else if (!stricmp(arg, "-logs")) {
+                       CHECK_NEXT_ARG
+                       gf_logs = argv[i+1];
+                       i++;
+               }
                else if (!stricmp(arg, "-noprog")) quiet = 1;
                else if (!stricmp(arg, "-info")) {
                        print_info = 1;
@@ -1471,24 +1508,21 @@ int mp4boxMain(int argc, char **argv)
                } else if (!stricmp(arg, "-frag")) {
                        CHECK_NEXT_ARG
                        InterleavingTime = atof(argv[i+1]) / 1000;
-                       open_edit = 1;
                        needSave = 1;
                        i++;
                        Frag = 1;
                } else if (!stricmp(arg, "-dash")) {
                        CHECK_NEXT_ARG
-                       dash_duration = atof(argv[i+1]) / 1000;
+                       dash_duration = atof(argv[i+1]) /        1000;
                        needSave = 1;
                        i++;
                } else if (!stricmp(arg, "-dash-ts-prog")) {
                        CHECK_NEXT_ARG
                        program_number = atoi(argv[i+1]);
                        i++;
-               } else if (!stricmp(arg, "-dash-ts-use-index")) {
-                       dash_ts_use_index = 1;
-               } else if (!stricmp(arg, "-frags-per-sidx")) {
+               } else if (!stricmp(arg, "-subsegs-per-sidx") || !stricmp(arg, "-frags-per-sidx")) {
                        CHECK_NEXT_ARG
-                       frags_per_sidx = atoi(argv[i+1]);
+                       subsegs_per_sidx = atoi(argv[i+1]);
                        i++;
                } else if (!stricmp(arg, "-segment-name")) {
                        CHECK_NEXT_ARG
@@ -1504,8 +1538,13 @@ int mp4boxMain(int argc, char **argv)
                        i++;
                } else if (!stricmp(arg, "-daisy-chain")) {
                        daisy_chain_sidx = 1;
-               } else if (!stricmp(arg, "-url-template")) {
+               } else if (!stricmp(arg, "-single-segment")) {
+                       single_segment = 1;
+               } else if (!strnicmp(arg, "-url-template", 13)) {
                        use_url_template = 1;
+                       if ((arg[13]=='=') && arg[14]) {
+                               if (!strcmp( &arg[14], "simulate")) use_url_template = 2;
+                       }
                }               
                else if (!stricmp(arg, "-itags")) { CHECK_NEXT_ARG itunes_tags = argv[i+1]; i++; open_edit = 1; }
 #ifndef GPAC_DISABLE_ISOM_HINTING
@@ -1789,6 +1828,7 @@ int mp4boxMain(int argc, char **argv)
                        outName = argv[i+1]; 
                        i++; 
                }
+               
 #ifndef GPAC_DISABLE_SCENE_ENCODER
                else if (!stricmp(arg, "-def")) opts.flags |= GF_SM_ENCODE_USE_NAMES;
                else if (!stricmp(arg, "-sync")) {
@@ -1905,7 +1945,7 @@ int mp4boxMain(int argc, char **argv)
                        i++; 
                        split_duration = 0;
                }
-               else if (!stricmp(arg, "-split-chunk") || !stricmp(arg, "-splitx")) { 
+               else if (!stricmp(arg, "-split-chunk") || !stricmp(arg, "-splitx") || !stricmp(arg, "-splitz")) { 
                        CHECK_NEXT_ARG 
                        if (!strstr(argv[i+1], ":")) {
                                fprintf(stdout, "Chunk extraction usage: \"-splitx start->end\" expressed in seconds\n");
@@ -1914,6 +1954,7 @@ int mp4boxMain(int argc, char **argv)
                        sscanf(argv[i+1], "%lf:%lf", &split_start, &split_duration);
                        split_duration -= split_start; 
                        split_size = 0;
+                       if (!stricmp(arg, "-splitz")) adjust_split_end = 1;
                        i++;
                }
                /*meta*/
@@ -1992,7 +2033,9 @@ int mp4boxMain(int argc, char **argv)
                        nb_tsel_acts++;
                        open_edit=1;
                }
-
+               else if (!stricmp(arg, "-group-single")) {
+                   single_group = 1;
+               }
                else if (!stricmp(arg, "-package")) {
                        CHECK_NEXT_ARG 
                        pack_file  = argv[i+1];
@@ -2026,13 +2069,11 @@ int mp4boxMain(int argc, char **argv)
                        i++;
                }
                else if (!stricmp(arg, "-rb")) { 
-                       char *b = argv[i+1];
                        CHECK_NEXT_ARG 
                        if (nb_alt_brand_rem>=MAX_CUMUL_OPS) {
                                fprintf(stdout, "Sorry - no more than %d brand remove operations allowed\n", MAX_CUMUL_OPS);
                                return 1;
                        }
-                       brand_rem[nb_alt_brand_rem] = GF_4CC(b[0], b[1], b[2], b[3]);
                        nb_alt_brand_rem++;
                        open_edit = 1;
                        i++;
@@ -2116,7 +2157,7 @@ int mp4boxMain(int argc, char **argv)
                done = 0;
                while (1) {
                        u32 nb_bytes = fread(chunk, 1, 4096, fin);
-                       fwrite(chunk, 1, nb_bytes, fout);
+                       gf_fwrite(chunk, 1, nb_bytes, fout);
                        done += nb_bytes;
                        fprintf(stdout, "Appending file %s - %02.2f done\r", raw_cat, 100.0*done/to_copy);
                        if (done >= to_copy) break;
@@ -2126,34 +2167,33 @@ int mp4boxMain(int argc, char **argv)
                return 0;
        }
 
-       {
-               u32 logtools = GF_LOG_CONTAINER|GF_LOG_SCENE|GF_LOG_PARSER|GF_LOG_AUTHOR|GF_LOG_CODING;
+       /*init libgpac*/
+       gf_sys_init(enable_mem_tracker);
+
+       if (gf_logs) {
+               gf_log_set_tools_levels(gf_logs);
+       } else {
+               u32 level = verbose ? GF_LOG_DEBUG : GF_LOG_INFO;
+               gf_log_set_tool_level(GF_LOG_CONTAINER, level);
+               gf_log_set_tool_level(GF_LOG_SCENE, level);
+               gf_log_set_tool_level(GF_LOG_PARSER, level);
+               gf_log_set_tool_level(GF_LOG_AUTHOR, level);
+               gf_log_set_tool_level(GF_LOG_CODING, level);
 #ifdef GPAC_MEMORY_TRACKING
-               if (enable_mem_tracker) logtools |= GF_LOG_MEMORY;
+               if (enable_mem_tracker)
+                       gf_log_set_tool_level(GF_LOG_MEMORY, level);
 #endif
-
-               //gf_log_set_level((verbose>1) ? GF_LOG_DEBUG : (verbose ? GF_LOG_INFO : GF_LOG_WARNING) );
-               gf_log_set_level(verbose ? GF_LOG_DEBUG : GF_LOG_INFO);
-               gf_log_set_tools(logtools);
                if (quiet) {
-                       if (quiet==2) gf_log_set_level(0);
+                       if (quiet==2) gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_QUIET);
                        gf_set_progress_callback(NULL, progress_quiet);
 
                }
-
        }
 
-       /*init libgpac*/
-#ifdef GPAC_MEMORY_TRACKING
-       gf_sys_init(enable_mem_tracker);
-#else
-       gf_sys_init(0);
-#endif
-
        if (do_mpd) {
                Bool remote = 0;
                char *mpd_base_url = gf_strdup(inName);
-               if (strcmp(inName, "http://")) {
+               if (!strnicmp(inName, "http://", 7)) {
                        e = gf_dm_wget(inName, "tmp_main.m3u8");
                        if (e != GF_OK) {
                                fprintf(stdout, "Cannot retrieve M3U8 (%s): %s\n", inName, gf_error_to_string(e));
@@ -2163,7 +2203,7 @@ int mp4boxMain(int argc, char **argv)
                        inName = "tmp_main.m3u8";
                        remote = 1;
                }
-               e = gf_m3u8_to_mpd(NULL, inName, mpd_base_url, (outName ? outName : inName), 0, "video/mp2t");
+               e = gf_m3u8_to_mpd(inName, mpd_base_url, (outName ? outName : inName), 0, "video/mp2t", NULL, 1, use_url_template);
                gf_free(mpd_base_url);
                if (remote) {
                        //gf_delete_file("tmp_main.m3u8");
@@ -2172,10 +2212,17 @@ int mp4boxMain(int argc, char **argv)
                        fprintf(stdout, "Error converting M3U8 (%s) to MPD (%s): %s\n", inName, outName, gf_error_to_string(e));
                        return 1;
                } else {
+                       fprintf(stdout, "Done converting M3U8 (%s) to MPD (%s)\n", inName, outName);
                        return 0;
                }
        }
 
+       if (dash_duration && !nb_dash_inputs) {
+               dash_inputs[nb_dash_inputs] = inName;
+               nb_dash_inputs++;
+       }
+
+
        if (do_saf && !encode) {
                switch (get_file_type_by_ext(inName)) {
                case 2: case 3: case 4: 
@@ -2385,7 +2432,7 @@ int mp4boxMain(int argc, char **argv)
                        file = gf_isom_open(inName, (u8) (open_edit ? GF_ISOM_OPEN_EDIT : ( (dump_isom>0) ? GF_ISOM_OPEN_READ_DUMP : GF_ISOM_OPEN_READ) ), tmpdir);
                        if (!file && (gf_isom_last_error(NULL) == GF_ISOM_INCOMPLETE_FILE) && !open_edit) {
                                u64 missing_bytes;
-                               e = gf_isom_open_progressive(inName, &file, &missing_bytes);
+                               e = gf_isom_open_progressive(inName, 0, 0, &file, &missing_bytes);
                                fprintf(stdout, "Truncated file - missing "LLD" bytes\n", missing_bytes);
                        }
 
@@ -2441,18 +2488,20 @@ int mp4boxMain(int argc, char **argv)
                                }
 
                                if (dash_duration) {
-                                       if (frags_per_sidx<0) frags_per_sidx = 0;
+                                       if (subsegs_per_sidx<0) subsegs_per_sidx = 0;
 #ifndef GPAC_DISABLE_MPEG2TS
-                                       dump_mpeg2_ts(inName, NULL, program_number, dash_duration, seg_at_rap, frags_per_sidx,
-                                               seg_name, seg_ext, use_url_template, dash_ts_use_index);
+                                       for (i=0; i<nb_dash_inputs; i++) {
+                                               dump_mpeg2_ts(dash_inputs[i], outName, program_number, dash_duration, seg_at_rap, subsegs_per_sidx,
+                                                       seg_name, seg_ext, use_url_template, single_segment, i, (i+1 == nb_dash_inputs) ? 1 : 0);
+                                       }
 #endif
                                } else if (dump_m2ts) {
 #ifndef GPAC_DISABLE_MPEG2TS
-                                       dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0);
+                                       dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0, 0, 0);
 #endif
                                } else if (dump_ts) { /* dump_ts means dump time stamp information */
 #ifndef GPAC_DISABLE_MPEG2TS
-                                       dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0);
+                                       dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0, 0, 0);
 #endif
                                } else {
                                        convert_file_info(inName, info_track_id);
@@ -2569,7 +2618,7 @@ int mp4boxMain(int argc, char **argv)
                } else {
                        char szName[GF_MAX_PATH];
                        FILE *iodf;
-                       GF_BitStream *bs;
+                       GF_BitStream *bs = NULL;
 
                        sprintf(szName, "%s.iod", outfile);
                        iodf = gf_f64_open(szName, "wb");
@@ -2580,19 +2629,20 @@ int mp4boxMain(int argc, char **argv)
                                u32 size;
                                bs = gf_bs_from_file(iodf, GF_BITSTREAM_WRITE);
                                if (gf_odf_desc_write((GF_Descriptor *)iod, &desc, &size)==GF_OK) {
-                                       fwrite(desc, 1, size, iodf);
+                                       gf_fwrite(desc, 1, size, iodf);
                                        gf_free(desc);
                                } else {
                                        fprintf(stdout, "Error writing IOD %s\n", szName);
                                }
                                fclose(iodf);
                        }
+                        gf_free(bs);
                }
        }
 
 #ifndef GPAC_DISABLE_ISOM_WRITE
        if (split_duration || split_size) {
-               split_isomedia_file(file, split_duration, split_size, inName, InterleavingTime, split_start, tmpdir);
+               split_isomedia_file(file, split_duration, split_size, inName, InterleavingTime, split_start, adjust_split_end, tmpdir);
                /*never save file when splitting is desired*/
                open_edit = 0;
                needSave = 0;
@@ -2898,8 +2948,11 @@ int mp4boxMain(int argc, char **argv)
                case 2:
                        if (tka->delay_ms) {
                                u64 tk_dur;
+
                                gf_isom_remove_edit_segments(file, track);
                                tk_dur = gf_isom_get_track_duration(file, track);
+                               if (gf_isom_get_edit_segment_count(file, track))
+                                       needSave = 1;
                                if (tka->delay_ms>0) {
                                        gf_isom_append_edit_segment(file, track, (timescale*tka->delay_ms)/1000, 0, GF_ISOM_EDIT_EMPTY);
                                        gf_isom_append_edit_segment(file, track, tk_dur, 0, GF_ISOM_EDIT_NORMAL);
@@ -2907,8 +2960,9 @@ int mp4boxMain(int argc, char **argv)
                                } else {
                                        u64 to_skip = (timescale*(-tka->delay_ms))/1000;
                                        if (to_skip<tk_dur) {
-                                               u64 seg_dur = (-tka->delay_ms)*gf_isom_get_media_timescale(file, track) / 1000;
-                                               gf_isom_append_edit_segment(file, track, tk_dur-to_skip, seg_dur, GF_ISOM_EDIT_NORMAL);
+                                               u64 media_time = (-tka->delay_ms)*gf_isom_get_media_timescale(file, track) / 1000;
+                                               gf_isom_append_edit_segment(file, track, tk_dur-to_skip, media_time, GF_ISOM_EDIT_NORMAL);
+                                               needSave = 1;
                                        } else {
                                                fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n");
                                        }
@@ -3078,20 +3132,172 @@ int mp4boxMain(int argc, char **argv)
 
        /*split file*/
        if (dash_duration) {
-
-               fprintf(stdout, "DASH-ing file with %.3f secs segments - fragments: %.3f secs - ", dash_duration, InterleavingTime);
-               if (frags_per_sidx<0) fprintf(stdout, "no sidx");
-               else if (frags_per_sidx) fprintf(stdout, "%d per sidx", frags_per_sidx);
-               else fprintf(stdout, "single sidx");
-               if (seg_at_rap) fprintf(stdout, " at GOP boundaries");
+               char szMPD[GF_MAX_PATH];
+               char szInit[GF_MAX_PATH];
+               GF_ISOFile *init_seg;
+               Bool sps_merge_failed = 0;
+               Double period_duration = 0;
+
+               if (single_segment) {
+                       fprintf(stdout, "DASH-ing file%s with single segment\nSubsegment duration %.3f - Fragment duration: %.3f secs\n", (nb_dash_inputs>1) ? "s" : "", dash_duration, InterleavingTime);
+                       subsegs_per_sidx = 0;
+                       seg_name = seg_ext = NULL;
+               } else {
+                       if (!seg_ext) seg_ext = "m4s";
+                       fprintf(stdout, "DASH-ing file with %.3f secs segments - fragments: %.3f secs\n", dash_duration, InterleavingTime);
+                       if (subsegs_per_sidx<0) fprintf(stdout, "No sidx used");
+                       else if (subsegs_per_sidx) fprintf(stdout, "%d subsegments per sidx", subsegs_per_sidx);
+                       else fprintf(stdout, "Single sidx used");
+               }
                fprintf(stdout, "\n");
+               if (seg_at_rap) fprintf(stdout, "Spliting segments at GOP boundaries\n");
 
                strcpy(outfile, outName ? outName : inName);
                while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0;
                outfile[strlen(outfile)-1] = 0;
                if (!outName) strcat(outfile, "_dash");
-               e = gf_media_fragment_file(file, outfile, InterleavingTime, seg_at_rap ? 2 : 1, dash_duration, seg_name, seg_ext, frags_per_sidx, daisy_chain_sidx, use_url_template, dash_ctx);
-               if (e) fprintf(stdout, "Error while DASH-ing file: %s\n", gf_error_to_string(e));
+
+               strcpy(szInit, outfile);
+               strcat(szInit, "_init.mp4");
+               strcpy(szMPD, outfile);
+               strcat(szMPD, ".mpd");
+
+               init_seg = gf_isom_open(szInit, GF_ISOM_OPEN_WRITE, tmpdir);
+               for (i=0; i<nb_dash_inputs; i++) {
+                       u32 j;
+                       Double dur;
+                       GF_ISOFile *in = file;
+                       if (i) {
+                               in = gf_isom_open(dash_inputs[i], GF_ISOM_OPEN_READ, NULL);
+                               if (!in) {
+                                       fprintf(stdout, "Error while opening %s: %s\n", dash_inputs[i], gf_error_to_string( gf_isom_last_error(NULL) ));
+                                       gf_isom_delete(file);
+                                       gf_sys_close();
+                                       return 1;
+                               }
+                       }
+                       for (j=0; j<gf_isom_get_track_count(in); j++) {
+                               u32 track = gf_isom_get_track_by_id(init_seg, gf_isom_get_track_id(in, j+1));
+                               if (track) {                                    
+                                       u32 outDescIndex;
+                                       assert( gf_isom_get_sample_description_count(in, j+1) == 1);
+
+                                       /*if not the same sample desc we might need to clone it*/
+                                       if (! gf_isom_is_same_sample_description(in, j+1, 1, init_seg, track, 1)) {
+                                               Bool do_merge = 1;
+                                               u32 stype1, stype2;
+                                               stype1 = gf_isom_get_media_subtype(in, j+1, 1);
+                                               stype2 = gf_isom_get_media_subtype(init_seg, track, 1);
+                                               if (stype1 != stype2) do_merge = 0;
+                                               switch (stype1) {
+                                               case GF_4CC( 'a', 'v', 'c', '1'):
+                                               case GF_4CC( 'a', 'v', 'c', '2'):
+                                               case GF_4CC( 's', 'v', 'c', '1'):
+                                                       break;
+                                               default:
+                                                       do_merge = 0;
+                                                       break;
+                                               }
+                                               if (do_merge) {
+                                                       u32 k, l, sps_id1, sps_id2;
+                                                       GF_AVCConfig *avccfg1 = gf_isom_avc_config_get(in, j+1, 1);
+                                                       GF_AVCConfig *avccfg2 = gf_isom_avc_config_get(init_seg, track, 1);
+                                                       for (k=0; k<gf_list_count(avccfg2->sequenceParameterSets); k++) {
+                                                               GF_AVCConfigSlot *slc = gf_list_get(avccfg2->sequenceParameterSets, k);
+                                                               gf_avc_get_sps_info(slc->data, slc->size, &sps_id1, NULL, NULL, NULL, NULL);
+                                                               for (l=0; l<gf_list_count(avccfg1->sequenceParameterSets); l++) {
+                                                                       GF_AVCConfigSlot *slc_orig = gf_list_get(avccfg1->sequenceParameterSets, l);
+                                                                       gf_avc_get_sps_info(slc_orig->data, slc_orig->size, &sps_id2, NULL, NULL, NULL, NULL);
+                                                                       if (sps_id2==sps_id1) {
+                                                                               do_merge = 0;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                                       /*no conflicts in SPS ids, merge all SPS in a single sample desc*/
+                                                       if (do_merge) {
+                                                               while (gf_list_count(avccfg1->sequenceParameterSets)) {
+                                                                       GF_AVCConfigSlot *slc = gf_list_get(avccfg1->sequenceParameterSets, 0);
+                                                                       gf_list_rem(avccfg1->sequenceParameterSets, 0);
+                                                                       gf_list_add(avccfg2->sequenceParameterSets, slc);
+                                                               }
+                                                               while (gf_list_count(avccfg1->pictureParameterSets)) {
+                                                                       GF_AVCConfigSlot *slc = gf_list_get(avccfg1->pictureParameterSets, 0);
+                                                                       gf_list_rem(avccfg1->pictureParameterSets, 0);
+                                                                       gf_list_add(avccfg2->pictureParameterSets, slc);
+                                                               }
+                                                               gf_isom_avc_config_update(init_seg, track, 1, avccfg2);
+                                                       } else {
+                                                               sps_merge_failed = 1;
+                                                       }
+                                                       gf_odf_avc_cfg_del(avccfg1);
+                                                       gf_odf_avc_cfg_del(avccfg2);
+                                               }
+
+                                               /*cannot merge, clone*/
+                                               if (!do_merge)
+                                                       gf_isom_clone_sample_description(init_seg, track, in, j+1, 1, NULL, NULL, &outDescIndex);
+                                       }
+                               } else {
+                                       gf_isom_clone_track(in, j+1, init_seg, 0, &track);
+                               }
+                               dur = (Double) gf_isom_get_track_duration(in, j+1);
+                               dur /= gf_isom_get_timescale(in);
+                               if (dur>period_duration) period_duration = dur;
+                       }
+
+                       if (i) gf_isom_close(in);
+               }
+               if (sps_merge_failed) {
+                       fprintf(stdout, "Couldnt merge AVC|H264 SPS from different files (same SPS ID used) - different sample descriptions will be used\n");
+               }
+               if (!seg_name) use_url_template = 0;
+
+               gf_media_mpd_start(szMPD, (char *)gf_isom_get_filename(file), use_url_template, single_segment, dash_ctx, szInit, period_duration);
+
+               for (i=0; i<nb_dash_inputs; i++) {
+                       char szSegName[GF_MAX_PATH], *segment_name;
+                       GF_ISOFile *in = file;
+                       if (i) in = gf_isom_open(dash_inputs[i], GF_ISOM_OPEN_READ, NULL);
+
+                       segment_name = seg_name;
+
+                       if (nb_dash_inputs>1) {
+                               char *sep = strrchr(dash_inputs[i], '/');
+                               if (!sep) sep = strrchr(dash_inputs[i], '\\');
+                               if (sep) strcpy(outfile, sep+1);
+                               else strcpy(outfile, dash_inputs[i]);
+                               sep = strrchr(outfile, '.');
+                               if (sep) sep[0] = 0;
+       
+                               if (seg_name) {
+                                       if (strstr(seg_name, "%s")) sprintf(szSegName, seg_name, outfile);
+                                       else strcpy(szSegName, seg_name);
+                                       segment_name = szSegName;
+                               }
+                               strcat(outfile, "_dash");
+                       }
+                       if (nb_dash_inputs>1) {
+                               fprintf(stdout, "DASHing file %s\n", dash_inputs[i]);
+                       }
+                       e = gf_media_fragment_file(in, outfile, szMPD, InterleavingTime, seg_at_rap ? 2 : 1, dash_duration, segment_name, seg_ext, subsegs_per_sidx, daisy_chain_sidx, use_url_template, single_segment, dash_ctx, init_seg, i+1);
+                       if (e) {
+                               fprintf(stdout, "Error while DASH-ing file: %s\n", gf_error_to_string(e));
+                               break;
+                       }
+                       if (i) gf_isom_close(in);
+               }
+               /*close MPD*/
+               gf_media_mpd_end(szMPD);
+               
+               /*if init segment shared, write to file*/
+               if (nb_dash_inputs>1) {
+                       gf_isom_close(init_seg);
+               } else {
+                       gf_isom_delete(init_seg);
+                       gf_delete_file(szInit);
+               }
+
                gf_isom_delete(file);
                gf_sys_close();
                return (e!=GF_OK) ? 1 : 0;
@@ -3099,7 +3305,7 @@ int mp4boxMain(int argc, char **argv)
                if (!InterleavingTime) InterleavingTime = 0.5;
                if (HintIt) fprintf(stdout, "Warning: cannot hint and fragment - ignoring hint\n");
                fprintf(stdout, "Fragmenting file (%.3f seconds fragments)\n", InterleavingTime);
-               e = gf_media_fragment_file(file, outfile, InterleavingTime, 0, 0, NULL, NULL, 0, 0, 0, NULL);
+               e = gf_media_fragment_file(file, outfile, NULL, InterleavingTime, 0, 0, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0);
                if (e) fprintf(stdout, "Error while fragmenting file: %s\n", gf_error_to_string(e));
                gf_isom_delete(file);
                if (!e && !outName && !force_new) {
@@ -3115,7 +3321,7 @@ int mp4boxMain(int argc, char **argv)
                if (force_ocr) SetupClockReferences(file);
                fprintf(stdout, "Hinting file with Path-MTU %d Bytes\n", MTUSize);
                MTUSize -= 12;          
-               e = HintFile(file, MTUSize, max_ptime, rtp_rate, hint_flags, HintCopy, HintInter, regular_iod);
+               e = HintFile(file, MTUSize, max_ptime, rtp_rate, hint_flags, HintCopy, HintInter, regular_iod, single_group);
                if (e) goto err_exit;
                needSave = 1;
                if (print_sdp) DumpSDP(file, dump_std ? NULL : outfile);
index 2458dcf5f96d2e2e49ebf759472bb2a0732dcd4c..2ce04e3fa0037f4a990c8ab4335d09b11f801cdb 100644 (file)
@@ -183,13 +183,13 @@ void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num)
        fi.biSizeImage = fb->pitch_y * fb->height;
 
        /*NOT ALIGNED!!*/
-    fwrite(&fh.bfType, 2, 1, fout);
-    fwrite(&fh.bfSize, 4, 1, fout);
-    fwrite(&fh.bfReserved1, 2, 1, fout);
-    fwrite(&fh.bfReserved2, 2, 1, fout);
-    fwrite(&fh.bfOffBits, 4, 1, fout);
+    gf_fwrite(&fh.bfType, 2, 1, fout);
+    gf_fwrite(&fh.bfSize, 4, 1, fout);
+    gf_fwrite(&fh.bfReserved1, 2, 1, fout);
+    gf_fwrite(&fh.bfReserved2, 2, 1, fout);
+    gf_fwrite(&fh.bfOffBits, 4, 1, fout);
 
-       fwrite(&fi, 1, 40, fout);
+       gf_fwrite(&fi, 1, 40, fout);
 //#ifndef GPAC_USE_TINYGL
        for (j=fb->height; j>0; j--) {
                ptr = fb->video_buffer + (j-1)*fb->pitch_y;
@@ -243,7 +243,7 @@ void write_png(GF_VideoSurface *fb, char *rad_name, u32 img_num)
        if (fout) {
                GF_Err e = gf_img_png_enc(fb->video_buffer, fb->width, fb->height, fb->pitch_y, fb->pixel_format, dst, &dst_size);
                if (!e) {
-                       fwrite(dst, dst_size, 1, fout);
+                       gf_fwrite(dst, dst_size, 1, fout);
                        fclose(fout);
                }
        }
index 5de99c2f723c2f3b80e698a480305657968c2abf..7185f6966d9ac985570f22acd518663e3e5c0c01 100644 (file)
@@ -58,6 +58,7 @@ void PrintGPACConfig();
 static Bool gui_mode = 0;
 
 static Bool restart = 0;
+static Bool reload = 0;
 #if defined(__DARWIN__) || defined(__APPLE__)
 //we keep no decoder thread because of JS_GC deadlocks between threads ...
 static u32 threading_flags = GF_TERM_NO_COMPOSITOR_THREAD | GF_TERM_NO_DECODER_THREAD;
@@ -133,13 +134,14 @@ void PrintUsage()
                "\t-strict-error:  exit when the player reports its first error\n"
                "\t-opt option:    Overrides an option in the configuration file. String format is section:key=value\n"
                "\t-log-file file: sets output log file. Also works with -lf\n"
-               "\t-log-level lev: sets log level. Also works with -ll. Possible values are:\n"
+               "\t-logs log_args: sets log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n"
+               "\t                 levelX can be one of:\n"
+               "\t        \"quiet\"      : skip logs\n"
                "\t        \"error\"      : logs only error messages\n"
                "\t        \"warning\"    : logs error+warning messages\n"
                "\t        \"info\"       : logs error+warning+info messages\n"
                "\t        \"debug\"      : logs all messages\n"
-               "\n"
-               "\t-log-tools lt:  sets tool(s) to log. Also works with -lt. List of \':\'-separated values:\n"
+               "\t                 toolX can be one of:\n"
                "\t        \"core\"       : libgpac core\n"
                "\t        \"coding\"     : bitstream formats (audio, video, scene)\n"
                "\t        \"container\"  : container formats (ISO File, MPEG-2 TS, AVI, ...)\n"
@@ -153,11 +155,18 @@ void PrintUsage()
                "\t        \"scene\"      : scene graph and scene manager\n"
                "\t        \"script\"     : scripting engine messages\n"
                "\t        \"interact\"   : interaction engine (events, scripts, etc)\n"
+               "\t        \"smil\"       : SMIL timing engine\n"
                "\t        \"compose\"    : composition engine (2D, 3D, etc)\n"
-               "\t        \"service\"    : network service management\n"
                "\t        \"mmio\"       : Audio/Video HW I/O management\n"
-               "\t        \"none\"       : no tool logged\n"
-               "\t        \"all\"        : all tools logged\n"
+               "\t        \"rti\"        : various run-time stats\n"
+               "\t        \"cache\"      : HTTP cache subsystem\n"
+               "\t        \"audio\"      : Audio renderer and mixers\n"
+#ifdef GPAC_MEMORY_TRACKING
+               "\t        \"mem\"        : GPAC memory tracker\n"
+#endif
+               "\t        \"module\"     : GPAC modules debugging\n"
+               "\t        \"mutex\"      : mutex\n"
+               "\t        \"all\"        : all tools logged - other tools can be specified afterwards.\n"
                "\n"
                "\t-size WxH:      specifies visual size (default: scene size)\n"
 #if defined(__DARWIN__) || defined(__APPLE__)
@@ -204,10 +213,12 @@ void PrintUsage()
                "\n"
                "\t-help:          show this screen\n"
                "\n"
-               "MP4Client - GPAC command line player and dumper - version %s\n"
-               "GPAC Written by Jean Le Feuvre (c) 2001-2005 - ENST (c) 2005-200X\n",
+               "MP4Client - GPAC command line player and dumper - version "GPAC_FULL_VERSION"\n"
+               "GPAC Written by Jean Le Feuvre (c) 2001-2005 - ENST (c) 2005-200X\n"
+               "GPAC Configuration: " GPAC_CONFIGURATION "\n"
+               "Features: %s\n", 
                GF_IMPORT_DEFAULT_FPS,
-               GPAC_FULL_VERSION
+               gpac_features()
                );
 }
 
@@ -285,7 +296,7 @@ static void PrintTime(u64 time)
        m = (u32) (time / 1000 / 60 - h*60);
        s = (u32) (time / 1000 - h*3600 - m*60);
        ms = (u32) (time - (h*3600 + m*60 + s) * 1000);
-       fprintf(stdout, "%02d:%02d:%02d.%02d", h, m, s, ms);
+       fprintf(stdout, "%02d:%02d:%02d.%03d", h, m, s, ms);
 }
 
 
@@ -451,7 +462,7 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt)
 {
        if (!term) return 0;
        
-       if (gui_mode) {
+       if (gui_mode==1) {
                if (evt->type==GF_EVENT_QUIT) Run = 0;
                return 0;
        }
@@ -475,14 +486,15 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt)
 
                if (!evt->message.message) return 0;
 
-               if (evt->message.error==GF_SCRIPT_INFO) {
-                       GF_LOG(GF_LOG_INFO, GF_LOG_SCRIPT, ("[Script] %s\n", evt->message.message));
-               } else if (evt->message.error) {
+               if (evt->message.error) {
                        if (!is_connected) last_error = evt->message.error;
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_ALL, ("%s %s: %s\n", evt->message.message, servName, gf_error_to_string(evt->message.error)));
+                       if (evt->message.error==GF_SCRIPT_INFO) {
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONSOLE, ("%s\n", evt->message.message));
+                       } else {
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("%s %s: %s\n", servName, evt->message.message, gf_error_to_string(evt->message.error)));
+                       }
                } else if (!be_quiet) 
-                       /*TODO: put a GF_LOG here*/
-                       fprintf(stdout, "%s %s\r", evt->message.message, servName);
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONSOLE, ("%s %s\n", servName, evt->message.message));
        }
                break;
        case GF_EVENT_PROGRESS:
@@ -606,6 +618,10 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt)
                        if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected)
                                gf_term_switch_quality(term, 0);
                        break;
+               case GF_KEY_F5:
+                       if (is_connected)
+                               reload = 1;
+                       break;
                }
                break;
 
@@ -624,7 +640,7 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt)
                ResetCaption();
                break;
        case GF_EVENT_EOS:
-               if (loop_at_end) restart = 1;
+               if (!playlist && loop_at_end) restart = 1;
                break;
        case GF_EVENT_SIZE:
                if (user.init_flags & GF_TERM_WINDOWLESS) {
@@ -844,8 +860,7 @@ static void init_rti_logs(char *rti_file, char *url, Bool use_rtix)
                /*turn on RTI loging*/
                if (use_rtix) {
                        gf_log_set_callback(NULL, on_gpac_log);
-                       gf_log_set_level(GF_LOG_DEBUG);
-                       gf_log_set_tools(GF_LOG_RTI);
+                       gf_log_set_tool_level(GF_LOG_RTI, GF_LOG_DEBUG);
 
                        GF_LOG(GF_LOG_DEBUG, GF_LOG_RTI, ("[RTI] System state when enabling log\n"));
                } else if (log_time_start) {
@@ -876,7 +891,7 @@ int main (int argc, char **argv)
        Bool enable_mem_tracker = 0;
 #endif
        Double fps = GF_IMPORT_DEFAULT_FPS;
-       Bool ret, fill_ar, visible;
+       Bool fill_ar, visible;
        char *url_arg, *the_cfg, *rti_file, *views;
        FILE *logfile = NULL;
        Float scale = 1;
@@ -924,10 +939,17 @@ int main (int argc, char **argv)
        cfg_file = gf_cfg_init(the_cfg, NULL);
        if (!cfg_file) {
                fprintf(stdout, "Error: Configuration File not found\n");
-               if (logfile) fclose(logfile);
+               return 1;
+       }
+       /*if logs are specified, use them*/
+       if (gf_log_set_tools_levels( gf_cfg_get_key(cfg_file, "General", "Logs") ) != GF_OK) {
                return 1;
        }
 
+       if( gf_cfg_get_key(cfg_file, "General", "Logs") != NULL ){
+               logs_set = 1;
+       }
+
        for (i=1; i<(u32) argc; i++) {
                char *arg = argv[i];
 //             if (isalnum(arg[0]) || (arg[0]=='/') || (arg[0]=='.') || (arg[0]=='\\') ) {
@@ -1001,16 +1023,10 @@ int main (int argc, char **argv)
                        logfile = gf_f64_open(argv[i+1], "wt");
                        gf_log_set_callback(logfile, on_gpac_log);
                        i++;
-               } else if (!strcmp(arg, "-log-level") || !strcmp(arg, "-ll")) {
-                       u32 flags = gf_log_parse_level(argv[i+1]);
-                       if (!flags) return 1;
-                       gf_log_set_level(flags);
-                       logs_set = 1;
-                       i++;
-               } else if (!strcmp(arg, "-log-tools") || !strcmp(arg, "-lt")) {
-                       u32 flags = gf_log_parse_tools(argv[i+1]);
-                       if (!flags) return 1;
-                       gf_log_set_tools(flags);
+               } else if (!strcmp(arg, "-logs") ) {
+                       if (gf_log_set_tools_levels(argv[i+1]) != GF_OK) {
+                               return 1;
+                       }
                        logs_set = 1;
                        i++;
                } else if (!strcmp(arg, "-log-clock") || !strcmp(arg, "-lc")) {
@@ -1106,8 +1122,7 @@ int main (int argc, char **argv)
        if (dump_mode) rti_file = NULL;
 
        if (!logs_set) {
-               gf_log_set_level(GF_LOG_ERROR);
-               gf_log_set_tools(0xFFFFFFFF);
+               //gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_ERROR);
        }
 
        if (rti_file) init_rti_logs(rti_file, url_arg, use_rtix);
@@ -1193,14 +1208,13 @@ int main (int argc, char **argv)
        }
 
        Run = 1;
-       ret = 1;
 
        if (dump_mode) {
                if (!nb_times) {
                        times[0] = 0;
                        nb_times++;
                }
-               ret = dump_file(url_arg, dump_mode, fps, forced_width, forced_height, scale, times, nb_times);
+               dump_file(url_arg, dump_mode, fps, forced_width, forced_height, scale, times, nb_times);
                Run = 0;
        } else
 
@@ -1256,6 +1270,11 @@ int main (int argc, char **argv)
        while (Run) {           
                /*we don't want getchar to block*/
                if (gui_mode || !gf_prompt_has_input()) {
+                       if (reload) {
+                               reload = 0;
+                               gf_term_disconnect(term);
+                               gf_term_connect(term, startup_file ? gf_cfg_get_key(cfg_file, "General", "StartupFile") : the_url);
+                       }
                        if (restart) {
                                restart = 0;
                                gf_term_play_from_time(term, 0, 0);
@@ -1326,9 +1345,15 @@ force_input:
                case '\n':
                case 'N':
                        if (playlist) {
+                               int res;
                                gf_term_disconnect(term);
 
-                               if (fscanf(playlist, "%s", the_url) == EOF) {
+                               res = fscanf(playlist, "%s", the_url);
+                               if ((res == EOF) && loop_at_end) {
+                                       fseek(playlist, 0, SEEK_SET);
+                                       res = fscanf(playlist, "%s", the_url);
+                               }
+                               if (res == EOF) {
                                        fprintf(stdout, "No more items - exiting\n");
                                        Run = 0;
                                } else {
@@ -1357,10 +1382,8 @@ force_input:
                        }
                        break;
                case 'r':
-                       if (is_connected) {
-                               gf_term_disconnect(term);
-                               gf_term_connect(term, startup_file ? gf_cfg_get_key(cfg_file, "General", "StartupFile") : the_url);
-                       }
+                       if (is_connected) 
+                               reload = 1;
                        break;
                
                case 'D':
@@ -1572,36 +1595,18 @@ force_input:
 
                case 'L':
                {
-                       u32 flags;
-                       char szLog[1024];
-                       fprintf(stdout, "Enter new log level:\n");
-                       if (1 > scanf("%s", szLog)){
+                       char szLog[1024], *cur_logs;
+                       cur_logs = gf_log_get_tools_levels();
+                       fprintf(stdout, "Enter new log level (current tools %s):\n", cur_logs);
+                       gf_free(cur_logs);
+                       if (scanf("%s", szLog) < 1) {
                            fprintf(stderr, "Cannot read new log level, aborting.\n");
                            break;
                        }
-                       flags = gf_log_parse_level(szLog);
-                       if (!flags)
-                               fprintf(stderr, "Wrong log level specified, aborting.\n");
-                       else
-                               gf_log_set_level(flags);
-               }
-                       break;
-               case 'T':
-               {
-                       u32 flags;
-                       char szLog[1024];
-                       fprintf(stdout, "Enter new log tools:\n");
-                       if (1 > scanf("%s", szLog)) {
-                           fprintf(stderr, "Cannot read new log tools, aborting.\n");
-                           break;
-                       }
-                       flags = gf_log_parse_tools(szLog);
-                       if (!flags)
-                               fprintf(stderr, "Wrong log tools specified, aborting.\n");
-                       else
-                               gf_log_set_tools(flags);
+                       gf_log_modify_tools_levels(szLog);
                }
                        break;
+
                case 'g':
                {
                        GF_SystemRTInfo rti;
@@ -1677,7 +1682,7 @@ force_input:
                                                        fprintf(stdout, "Error writing file %s\n", szFileName);
                                                        nb_pass = 0;
                                                } else {
-                                                       fwrite(dst, dst_size, 1, png);
+                                                       gf_fwrite(dst, dst_size, 1, png);
                                                        fclose(png);
                                                        fprintf(stdout, "Dump to %s\n", szFileName);
                                                }
diff --git a/applications/osmo4_ios/Resources/icon.png b/applications/osmo4_ios/Resources/icon.png
new file mode 100644 (file)
index 0000000..13f1dee
Binary files /dev/null and b/applications/osmo4_ios/Resources/icon.png differ
diff --git a/applications/osmo4_ios/Resources/osmo.icns b/applications/osmo4_ios/Resources/osmo.icns
new file mode 100644 (file)
index 0000000..da7226f
Binary files /dev/null and b/applications/osmo4_ios/Resources/osmo.icns differ
diff --git a/applications/osmo4_ios/extract.c b/applications/osmo4_ios/extract.c
new file mode 100644 (file)
index 0000000..8d100c8
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                     Copyright (c) 2005-200X ENST
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / command-line client
+ *
+ *  GPAC is gf_free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+#include "libgpac_symbols.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+typedef struct tagBITMAPFILEHEADER 
+{
+    u16        bfType;
+    u32        bfSize;
+    u16        bfReserved1;
+    u16        bfReserved2;
+    u32 bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPINFOHEADER{
+       u32     biSize;
+       s32     biWidth;
+       s32     biHeight;
+       u16     biPlanes;
+       u16     biBitCount;
+       u32     biCompression;
+       u32     biSizeImage;
+       s32     biXPelsPerMeter;
+       s32     biYPelsPerMeter;
+       u32     biClrUsed;
+       u32     biClrImportant;
+} BITMAPINFOHEADER;
+
+#define BI_RGB        0L
+
+#endif
+
+
+#include <gpac/internal/avilib.h>
+#include <gpac/internal/terminal_dev.h>
+#include <gpac/internal/compositor_dev.h>
+
+extern Bool is_connected;
+extern GF_Terminal *term;
+extern u32 Duration;
+extern GF_Err last_error;
+
+static GFINLINE u8 colmask(s32 a, s32 n)
+{
+    s32 mask = (1 << n) - 1;
+    return (u8) (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
+}
+
+static u32 put_pixel(FILE *fout, u32 type, u32 pf, char *ptr)
+{
+       u16 col;
+       switch (pf) {
+       case GF_PIXEL_RGB_32:
+       case GF_PIXEL_ARGB:
+               fputc(ptr[0], fout);
+               fputc(ptr[1], fout);
+               fputc(ptr[2], fout);
+               return 4;
+
+       case GF_PIXEL_BGR_32:
+       case GF_PIXEL_RGBA:
+                //probably due to tinygl bug - verify
+#ifndef GPAC_USE_TINYGL
+               fputc(ptr[3], fout);
+               fputc(ptr[2], fout);
+               fputc(ptr[1], fout);
+#else
+               fputc(ptr[2], fout);
+               fputc(ptr[1], fout);
+               fputc(ptr[0], fout);
+#endif
+               return 4;
+
+       case GF_PIXEL_RGB_24:
+               fputc(ptr[2], fout);
+               fputc(ptr[1], fout);
+               fputc(ptr[0], fout);
+               return 3;
+
+       case GF_PIXEL_BGR_24:
+               fputc(ptr[2], fout);
+               fputc(ptr[1], fout);
+               fputc(ptr[0], fout);
+               return 3;
+       case GF_PIXEL_RGB_565:
+               col = * (u16 *)ptr;
+               fputc(colmask(col << 3, 3), fout);
+               fputc(colmask(col >> (5 - 2), 2), fout);
+               fputc(colmask(col >> (11 - 3), 3), fout);
+               return 2;
+
+       case GF_PIXEL_RGB_555:
+               col = * (u16 *)ptr;
+               fputc(colmask(col << 3, 3), fout);
+               fputc(colmask(col >> (5 - 3), 3), fout);
+               fputc(colmask(col >> (10 - 3), 3), fout);
+               return 2;
+       /* this is used to write the byte depthbuffer in greyscale when dumping depth*/ 
+       case GF_PIXEL_GREYSCALE:
+               /* bmp always needs 3 pixels */
+               fputc(ptr[0], fout);
+               fputc(ptr[0], fout);
+               fputc(ptr[0], fout); 
+               /* if printing the characters corresponding to the float depth buffer: */
+               /*
+               {
+               u32 i=0;
+               while (ptr[i]!='\0') {
+                       fputc(ptr[i], fout);
+                       i++;
+               }
+               fputc('\b', fout);
+               }
+               */
+               return 1;
+
+
+       case 0:
+               fputc(ptr[0], fout);
+               return 1;
+       }
+       return 0;
+}
+
+void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num)
+{
+       char str[GF_MAX_PATH];
+       BITMAPFILEHEADER fh;
+       BITMAPINFOHEADER fi;
+       FILE *fout;
+       u32 j, i;
+       char *ptr, *prev;
+
+       prev = strrchr(rad_name, '.');
+       //if (prev) prev[0] = '\0'; 
+
+       if (fb->pixel_format==GF_PIXEL_GREYSCALE) sprintf(str, "%s_%d_depth.bmp", rad_name, img_num);
+       else sprintf(str, "%s_%d.bmp", rad_name, img_num);
+
+       fout = gf_f64_open(str, "wb");
+       if (!fout) return;
+
+       memset(&fh, 0, sizeof(fh));
+       fh.bfType = 19778;
+       fh.bfOffBits = 14 + 40;
+
+       memset(&fi, 0, sizeof(char)*40);
+       fi.biSize = sizeof(char)*40;
+       fi.biWidth = fb->width;
+       fi.biHeight = fb->height;
+       fi.biPlanes = 1;
+       if (fb->pixel_format==GF_PIXEL_GREYSCALE) fi.biBitCount = 24;
+       else fi.biBitCount = 24;
+       fi.biCompression = BI_RGB;
+       fi.biSizeImage = fb->pitch_y * fb->height;
+
+       /*NOT ALIGNED!!*/
+    gf_fwrite(&fh.bfType, 2, 1, fout);
+    gf_fwrite(&fh.bfSize, 4, 1, fout);
+    gf_fwrite(&fh.bfReserved1, 2, 1, fout);
+    gf_fwrite(&fh.bfReserved2, 2, 1, fout);
+    gf_fwrite(&fh.bfOffBits, 4, 1, fout);
+
+       gf_fwrite(&fi, 1, 40, fout);
+//#ifndef GPAC_USE_TINYGL
+       for (j=fb->height; j>0; j--) {
+               ptr = fb->video_buffer + (j-1)*fb->pitch_y;
+               for (i=0;i<fb->width; i++) {
+                       u32 res = put_pixel(fout, 0, fb->pixel_format, ptr);
+                       assert(res);
+                       ptr += res;
+               }
+       }
+//#else
+#if 0
+       for (j=0; j<fb->height; j++) {
+               ptr = fb->video_buffer + j*fb->pitch;
+               for (i=0;i<fb->width; i++) {
+                       u32 res = put_pixel(fout, 0, fb->pixel_format, ptr);
+                       assert(res);
+                       ptr += res;
+               }
+       }
+#endif
+
+       fclose(fout);
+}
+
+/*writes onto a file the content of the framebuffer in *fb interpreted as the byte depthbuffer */
+/*it's also possible to write a float depthbuffer by passing the floats to strings and writing chars in putpixel - see comments*/
+void write_depthfile(GF_VideoSurface *fb, char *rad_name, u32 img_num)
+{
+       FILE *fout;
+       u32 i, j;
+       char val;
+       unsigned char *depth;
+
+       depth = (unsigned char *) fb->video_buffer;
+       
+       fout = gf_f64_open("dump_depth", "wb");
+       if (!fout) return;
+       for (j=0; j<fb->height;  j++) {
+               for (i=0;i<fb->width; i++) {
+
+#ifdef GPAC_USE_TINYGL
+                       val = fputc(depth[2*i+j*fb->width*sizeof(unsigned short)], fout);
+                       val = fputc(depth[2*i+j*fb->width*sizeof(unsigned short) + 1], fout);
+#else
+                       val = fputc(depth[i+j*fb->width], fout);
+#endif
+               }
+       }
+       fclose(fout);
+}
+
+void write_texture_file(GF_VideoSurface *fb, char *rad_name, u32 img_num, u32 dump_mode)
+{
+
+       FILE *fout;
+       u32 i, j;
+       char val;
+       unsigned char *buf;
+
+       buf = (unsigned char *) fb->video_buffer;
+       
+       if (dump_mode==6) fout = gf_f64_open("dump_rgbds", "wb");
+       else if (dump_mode==9) fout = gf_f64_open("dump_rgbd", "wb");
+       else return;
+       
+       if (!fout) return;
+       for (j=0; j<fb->height;  j++) {
+               for (i=0;i<fb->width*4; i++) {
+                       val = fputc(buf[i+j*fb->pitch_y], fout);
+               }
+       }
+       fclose(fout);
+}
+
+
+void write_raw(GF_VideoSurface *fb, char *rad_name, u32 img_num)
+{
+       u32 j, i;
+       char *ptr, *prev;
+       char str[GF_MAX_PATH];
+       FILE *fout;
+       prev = strrchr(rad_name, '.');
+       if (prev) prev[0] = '\0'; 
+       if (img_num<10) {
+               sprintf(str, "%s_00%d.raw", rad_name, img_num);
+       } else if (img_num<100) {
+               sprintf(str, "%s_0%d.raw", rad_name, img_num);
+       } else {
+               sprintf(str, "%s_%d.raw", rad_name, img_num);
+       }
+
+       fout = gf_f64_open(str, "wb");
+       if (!fout) return;
+
+       
+       for (j=0;j<fb->height; j++) {
+               ptr = fb->video_buffer + j*fb->pitch_y;
+               for (i=0;i<fb->width; i++) {
+                       u32 res = put_pixel(fout, 0, fb->pixel_format, ptr);
+                       assert(res);
+                       ptr += res;
+               }
+       }
+       fclose(fout);
+}
+
+
+/* creates a .bmp format greyscale image of the byte depthbuffer and a binary with only the content of the depthbuffer */
+void dump_depth (GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, char *conv_buf, void *avi_out)
+{
+       GF_Err e;
+       u32 i, k;
+       GF_VideoSurface fb;
+
+       /*lock it*/
+       e = gf_sc_get_screen_buffer(term->compositor, &fb, 1);
+       if (e) fprintf(stdout, "Error grabbing depth buffer: %s\n", gf_error_to_string(e));
+       else  fprintf(stdout, "OK\n");
+       /*export frame*/
+       switch (dump_type) {
+       case 1:
+       case 8:
+               /*reverse frame*/
+               for (k=0; k<fb.height; k++) {
+                       char *dst, *src;
+                       u16 src_16;
+                       dst = conv_buf + k*fb.width*3;
+                       src = fb.video_buffer + (fb.height-k-1) * fb.pitch_y;
+                       
+                       for (i=0;i<fb.width; i++) {
+                               switch (fb.pixel_format) {
+                               case GF_PIXEL_RGB_32:
+                               case GF_PIXEL_ARGB:
+                                       dst[0] = src[0];
+                                       dst[1] = src[1];
+                                       dst[2] = src[2];
+                                       src+=4;
+                                       break;
+                       
+                               case GF_PIXEL_BGR_32:
+                               case GF_PIXEL_RGBA:
+                                       dst[0] = src[3];
+                                       dst[1] = src[2];
+                                       dst[2] = src[1];
+                                       src+=4;
+                                       break;
+                               case GF_PIXEL_RGB_24:
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       src+=3;
+                                       break;
+                               case GF_PIXEL_BGR_24:
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       src+=3;
+                                       break;
+                               case GF_PIXEL_RGB_565:
+                                       src_16 = * ( (u16 *)src );
+                                       dst[2] = colmask(src_16 >> 8/*(11 - 3)*/, 3);
+                                       dst[1] = colmask(src_16 >> 3/*(5 - 2)*/, 2);
+                                       dst[0] = colmask(src_16 << 3, 3);
+                                       src+=2;
+                                       break;
+                               case GF_PIXEL_RGB_555:
+                                       src_16 = * (u16 *)src;
+                                       dst[2] = colmask(src_16 >> 7/*(10 - 3)*/, 3);
+                                       dst[1] = colmask(src_16 >> 2/*(5 - 3)*/, 3);
+                                       dst[0] = colmask(src_16 << 3, 3);
+                                       src+=2;
+                                       break;
+                                       /*for depth .avi*/
+                               case GF_PIXEL_GREYSCALE:
+                                       dst[0] = src[0];
+                                       dst[1] = src[0];
+                                       dst[2] = src[0];
+                                       src+=1;
+                                       break;
+                               }
+                               dst += 3;
+                       }
+               }
+#ifndef GPAC_DISABLE_AVILIB
+               if (AVI_write_frame(avi_out, conv_buf, fb.height*fb.width*3, 1) <0)
+                       printf("Error writing frame\n");
+#endif
+               break;
+       case 2:
+               write_bmp(&fb, rad_name, frameNum);
+               break;
+       case 3:
+               write_raw(&fb, rad_name, frameNum);
+               break;
+       case 4:
+               write_depthfile(&fb, rad_name, frameNum);
+               break;
+       case 7:
+               write_bmp(&fb, rad_name, frameNum);
+               break;  
+               
+       }
+       /*unlock it*/
+       /*in -depth -avi mode, do not release it yet*/
+       if (dump_type!=8) gf_sc_release_screen_buffer(term->compositor, &fb);
+}
+
+void dump_frame(GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, char *conv_buf, void *avi_out)
+{
+       GF_Err e = GF_OK;
+       u32 i, k, out_size;
+       GF_VideoSurface fb;
+
+       /*lock it*/
+       if (dump_type==5 || dump_type==6) e = gf_sc_get_screen_buffer(term->compositor, &fb, 2);
+       else if (dump_type== 9 || dump_type==10) e = gf_sc_get_screen_buffer(term->compositor, &fb, 3);
+       else e = gf_sc_get_screen_buffer(term->compositor, &fb, 0);
+       if (e) fprintf(stdout, "Error grabbing frame buffer: %s\n", gf_error_to_string(e));
+
+       if (dump_type!=5 && dump_type!= 10) { 
+               out_size = fb.height*fb.width*3;
+       } else {
+               out_size = fb.height*fb.width*4;
+       }
+       /*export frame*/
+       switch (dump_type) {
+       case 1:
+       case 5:
+       case 10:
+       case 8:
+               /*reverse frame*/
+               for (k=0; k<fb.height; k++) {
+                       char *dst, *src;
+                       u16 src_16;
+                       if (dump_type==5 || dump_type==10) dst = conv_buf + k*fb.width*4;
+                       else dst = conv_buf + k*fb.width*3;
+                       src = fb.video_buffer + (fb.height-k-1) * fb.pitch_y;
+
+                       switch (fb.pixel_format) {
+                       case GF_PIXEL_RGB_32:
+                       case GF_PIXEL_ARGB:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[0];
+                                       dst[1] = src[1];
+                                       dst[2] = src[2];
+                                       src+=4;
+                                       dst += 3;
+                               }
+                               break;
+                       case GF_PIXEL_RGBDS:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       dst[3] = src[3];
+                                       dst +=4;
+                                       src+=4;
+                               }
+                               break;          
+                       case GF_PIXEL_RGBD:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       dst[3] = src[3];
+                                       dst += 4;
+                                       src+=4;
+                               }
+                               break;                          
+                       case GF_PIXEL_BGR_32:
+                       case GF_PIXEL_RGBA:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[3];
+                                       dst[1] = src[2];
+                                       dst[2] = src[1];
+                                       src+=4;
+                                       dst+=3;
+                               }
+                               break;
+                       case GF_PIXEL_RGB_24:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       src+=3;
+                                       dst+=3;
+                               }
+                               break;
+                       case GF_PIXEL_BGR_24:
+                               for (i=0;i<fb.width; i++) {
+                                       dst[0] = src[2];
+                                       dst[1] = src[1];
+                                       dst[2] = src[0];
+                                       src+=3;
+                                       dst+=3;
+                               }
+                               break;
+                       case GF_PIXEL_RGB_565:
+                               for (i=0;i<fb.width; i++) {
+                                       src_16 = * ( (u16 *)src );
+                                       dst[2] = colmask(src_16 >> 8/*(11 - 3)*/, 3);
+                                       dst[1] = colmask(src_16 >> 3/*(5 - 2)*/, 2);
+                                       dst[0] = colmask(src_16 << 3, 3);
+                                       src+=2;
+                                       dst+=3;
+                               }
+                               break;
+                       case GF_PIXEL_RGB_555:
+                               for (i=0;i<fb.width; i++) {
+                                       src_16 = * (u16 *)src;
+                                       dst[2] = colmask(src_16 >> 7/*(10 - 3)*/, 3);
+                                       dst[1] = colmask(src_16 >> 2/*(5 - 3)*/, 3);
+                                       dst[0] = colmask(src_16 << 3, 3);
+                                       src+=2;
+                                       dst +=3;
+                               }
+                               break;
+                       }
+               }
+#ifndef GPAC_DISABLE_AVILIB
+               if (dump_type!=5 && dump_type!= 10) { 
+                       if (AVI_write_frame(avi_out, conv_buf, out_size, 1) <0)
+                       printf("Error writing frame\n");
+               } else {
+                       if (AVI_write_frame(avi_out, conv_buf, out_size, 1) <0)
+                       printf("Error writing frame\n");                                
+               }
+#endif
+               break;
+       case 2:
+               write_bmp(&fb, rad_name, frameNum);
+               break;
+       case 6:
+       case 9:
+               write_texture_file(&fb, rad_name, frameNum, dump_type);
+               break;
+       
+       case 3:
+               write_raw(&fb, rad_name, frameNum);
+               break;
+       }
+       /*unlock it*/
+       gf_sc_release_screen_buffer(term->compositor, &fb);
+}
+
+Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Float scale, u32 *times, u32 nb_times)
+{
+       GF_Err e;
+       u32 i = 0;
+       GF_VideoSurface fb;
+       char szPath[GF_MAX_PATH];
+       char *prev=NULL;  
+
+       prev = strstr(url, "://");
+       if (prev) {
+               prev = strrchr(url, '/');
+               if (prev) prev++;
+       }
+
+       if (!prev) prev = url; 
+       strcpy(szPath, prev);
+       prev = strrchr(szPath, '.');
+       if (prev) prev[0] = 0;
+
+       fprintf(stdout, "Opening URL %s\n", url);
+       /*connect in pause mode*/
+       gf_term_connect_from_time(term, url, 0, 1);
+
+       while (!term->compositor->scene 
+               || term->compositor->msg_type
+               || (gf_term_get_option(term, GF_OPT_PLAY_STATE) == GF_STATE_STEP_PAUSE)
+       ) {
+               if (last_error) return 1;
+               gf_term_process_flush(term);
+               gf_sleep(10);
+       }
+       
+       if (width && height) {
+               gf_term_set_size(term, width, height);
+               gf_term_process_flush(term);
+       } 
+#ifndef GPAC_USE_TINYGL
+        printf("not tinygl\n");
+       e = gf_sc_get_screen_buffer(term->compositor, &fb, 0);
+#else
+        printf("tinygl\n");
+       e = gf_sc_get_screen_buffer(term->compositor, &fb, 1);
+#endif
+       if (e != GF_OK) {
+               fprintf(stdout, "Error grabbing screen buffer: %s\n", gf_error_to_string(e));
+               return 0;
+       }
+       width = fb.width;
+       height = fb.height;
+       gf_sc_release_screen_buffer(term->compositor, &fb);
+
+       if (scale != 1) {
+               width = (u32)(width * scale);
+               height = (u32)(height * scale);
+               gf_term_set_size(term, width, height);
+               gf_term_process_flush(term);
+       }
+
+       /*we work in RGB24, and we must make sure the pitch is %4*/
+       if ((width*3)%4) {
+               fprintf(stdout, "Adjusting width (%d) to have a stride multiple of 4\n", width);
+               while ((width*3)%4) width--;
+
+               gf_term_set_size(term, width, height);
+               gf_term_process_flush(term);
+
+               gf_sc_get_screen_buffer(term->compositor, &fb, 0);
+               width = fb.width;
+               height = fb.height;
+               gf_sc_release_screen_buffer(term->compositor, &fb);
+       }
+
+       if (dump_mode==1 || dump_mode==5 || dump_mode==8 || dump_mode==10) {
+#ifdef GPAC_DISABLE_AVILIB
+               fprintf(stdout, "AVILib is disabled in this build of GPAC\n");
+               return 0;
+#else
+               u32 time, prev_time, nb_frames, dump_dur;
+               char *conv_buf;
+               avi_t *avi_out = NULL; 
+               avi_t *depth_avi_out = NULL; 
+               char szPath_depth[GF_MAX_PATH];
+               char comp[5];
+               strcpy(szPath_depth, szPath);
+               strcat(szPath, ".avi");
+               avi_out = AVI_open_output_file(szPath);
+               if (!avi_out) {
+                       fprintf(stdout, "Error creating AVI file %s\n", szPath);
+                       return 1;
+               }
+               if (dump_mode==8) {
+                       strcat(szPath_depth, "_depth.avi");
+                       depth_avi_out = AVI_open_output_file(szPath_depth);
+                       if (!depth_avi_out) {
+                               fprintf(stdout, "Error creating AVI file %s\n", szPath);
+                               return 1;
+                       }       
+               }
+               
+               if (!fps) fps = 25.0;
+               time = prev_time = 0;
+               nb_frames = 0;
+
+               if (nb_times==2) {
+                       prev_time = times[0];
+                       dump_dur = times[1] - times[0];
+               } else {
+                       dump_dur = times[0] ? times[0] : Duration;
+               }
+               if (!dump_dur) {
+                       fprintf(stdout, "Warning: file has no duration, defaulting to 1 sec\n");
+                       dump_dur = 1000;
+               }
+
+               comp[0] = comp[1] = comp[2] = comp[3] = comp[4] = 0;
+               AVI_set_video(avi_out, width, height, fps, comp);
+               if (dump_mode==8) AVI_set_video(depth_avi_out, width, height, fps, comp);
+               if (dump_mode != 5 && dump_mode!=10) conv_buf = gf_malloc(sizeof(char) * width * height * 3);
+               else conv_buf = gf_malloc(sizeof(char) * width * height * 4);
+               /*step to first frame*/
+               if (prev_time) gf_term_step_clocks(term, prev_time);
+
+               while (time < dump_dur) {
+                       while ((gf_term_get_option(term, GF_OPT_PLAY_STATE) == GF_STATE_STEP_PAUSE)) {
+                               gf_term_process_flush(term);
+                       }
+                       fprintf(stdout, "Dumping %02d/100\r", (u32) ((100.0*prev_time)/dump_dur) );
+
+                       if (dump_mode==8) {
+                               /*we'll dump both buffers at once*/
+                               gf_mx_p(term->compositor->mx);
+                               dump_depth(term, szPath_depth, dump_mode, i+1, conv_buf, depth_avi_out);
+                               dump_frame(term, szPath, dump_mode, i+1, conv_buf, avi_out);
+                               gf_mx_v(term->compositor->mx);
+
+                       }
+                       else dump_frame(term, szPath, dump_mode, i+1, conv_buf, avi_out);
+                       
+                       nb_frames++;
+                       time = (u32) (nb_frames*1000/fps);
+                       gf_term_step_clocks(term, time - prev_time);
+                       prev_time = time;
+               }
+               AVI_close(avi_out);
+               if (dump_mode==8) AVI_close(depth_avi_out);
+               gf_free(conv_buf);
+               fprintf(stdout, "AVI Extraction 100/100\n");
+#endif /*GPAC_DISABLE_AVILIB*/
+       } else {
+               if (times[0]) gf_term_step_clocks(term, times[0]);
+
+               for (i=0; i<nb_times; i++) {
+                       while ((gf_term_get_option(term, GF_OPT_PLAY_STATE) == GF_STATE_STEP_PAUSE)) {
+                               gf_term_process_flush(term);
+                       }
+
+                       if (dump_mode==4 || dump_mode==7) {
+                               dump_depth(term, szPath, dump_mode, i+1, NULL, NULL);
+                       } else {
+                               dump_frame(term, url, dump_mode, i+1, NULL, NULL);
+                       }
+                       
+                       if (i+1<nb_times) gf_term_step_clocks(term, times[i+1] - times[i]);
+               }
+       }
+       return 0;
+}
+
diff --git a/applications/osmo4_ios/main.c b/applications/osmo4_ios/main.c
new file mode 100644 (file)
index 0000000..4f80231
--- /dev/null
@@ -0,0 +1,2117 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / command-line client
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+
+#include "libgpac_symbols.h"
+void (*gf_log_lt)(u32 ll, u32 lt);
+int (*AVI_close)(avi_t *AVI);
+GF_Err (*gf_term_del)(GF_Terminal *term);
+void (*gf_sleep)(u32 ms);
+GF_Err (*gf_sc_release_screen_buffer)(GF_Compositor *sr, GF_VideoSurface *framebuffer);
+char (*gf_prompt_get_char)();
+void (*gf_set_progress)(char *title, u32 done, u32 total);
+GF_Terminal *(*gf_term_new)(GF_User *user);
+GF_Err (*gf_term_process_step)(GF_Terminal *term);
+GF_Err (*gf_sc_get_screen_buffer)(GF_Compositor *sr, GF_VideoSurface *framebuffer, Bool depth_buffer);
+void (*gf_iphone_set_sdl_audio_module)(void* (*SDL_Module) (void));
+GF_Err (*gf_term_step_clocks)(GF_Terminal * term, u32 ms_diff);
+void (*gf_prompt_set_echo_off)(Bool echo_off);
+u32 (*gf_log_tool_level_on)();
+GF_Err (*gf_cfg_set_key)(GF_Config *cfgFile, const char *secName, const char *keyName, const char *keyValue);
+u32 (*gf_cfg_get_section_count)(GF_Config *cfgFile);
+GF_Err (*gf_term_get_service_info)(GF_Terminal *term, GF_ObjectManager *odm, NetInfoCommand *netcom);
+GF_Err (*gf_term_set_size)(GF_Terminal *term, u32 NewWidth, u32 NewHeight);
+Bool (*gf_sys_get_rti)(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags);
+u32 (*gf_term_play_from_time)(GF_Terminal *term, u64 from_time, u32 pause_at_first_frame);
+void *(*gf_malloc)(size_t size);
+void (*gf_log_set_tools_levels)(const char *);
+void (*gf_log_set_tool_level)(u32, u32);
+void (*gf_log_modify_tools_level)(const char *);
+void (*gf_iphone_set_sdl_video_module)(void* (*SDL_Module) (void));
+u32 (*gf_term_get_option)(GF_Terminal *term, u32 opt_type);
+Bool (*gf_term_user_event)(GF_Terminal *term, GF_Event *event);
+const char *(*gf_modules_get_file_name)(GF_ModuleManager *pm, u32 index);
+GF_Mutex *(*gf_mx_new)(const char *name);
+u32 (*gf_list_count)(GF_List *ptr);
+void (*gf_free)(void *ptr);
+const char *(*gf_term_get_world_info)(GF_Terminal *term, GF_ObjectManager *scene_od, GF_List *descriptions);
+const char *(*gf_cfg_get_section_name)(GF_Config *cfgFile, u32 secIndex);
+void (*gf_term_navigate_to)(GF_Terminal *term, const char *toURL);
+void (*gf_modules_del)(GF_ModuleManager *pm);
+GF_ModuleManager *(*gf_modules_new)(const char *directory, GF_Config *cfgFile);
+void (*gf_sys_init)(Bool enable_memory_tracker);
+void (*gf_log)(const char *fmt, ...);
+GF_Err (*gf_term_get_object_info)(GF_Terminal *term, GF_ObjectManager *odm, GF_MediaInfo *info);
+u32 (*gf_mx_p)(GF_Mutex *mx);
+u32 (*gf_mx_v)(GF_Mutex *mx);
+void (*gf_mx_del)(GF_Mutex *mx);
+GF_Err (*gf_term_process_flush)(GF_Terminal *term);
+const char *(*gf_cfg_get_key_name)(GF_Config *cfgFile, const char *secName, u32 keyIndex);
+int (*AVI_write_frame)(avi_t *AVI, char *data, long bytes, int keyframe);
+void (*gf_cfg_del)(GF_Config *iniFile);
+Bool (*gf_term_get_channel_net_info)(GF_Terminal *term, GF_ObjectManager *odm, u32 *d_enum, u32 *chid, NetStatCommand *netcom, GF_Err *ret_code);
+void (*gf_term_process_shortcut)(GF_Terminal *term, GF_Event *ev);
+GF_Config *(*gf_cfg_init)(const char *fileName, Bool *is_new);
+Bool (*gf_term_get_download_info)(GF_Terminal *term, GF_ObjectManager *odm, u32 *d_enum, const char **server, const char **path, u32 *bytes_done, u32 *total_bytes, u32 *bytes_per_sec);
+u32 (*gf_sys_clock)();
+GF_ObjectManager *(*gf_term_get_object)(GF_Terminal *term, GF_ObjectManager *scene_od, u32 index);
+GF_Err (*gf_term_set_option)(GF_Terminal *term, u32 opt_type, u32 opt_value);
+void (*gf_sys_close)();
+void (*gf_term_connect_from_time)(GF_Terminal *term, const char *URL, u64 time_in_ms, Bool pause_at_first_frame);
+avi_t* (*AVI_open_output_file)(char * filename);
+const char *(*gf_cfg_get_key)(GF_Config *cfgFile, const char *secName, const char *keyName);
+void (*AVI_set_video)(avi_t *AVI, int width, int height, double fps, char *compressor);
+void (*gf_term_set_speed)(GF_Terminal *term, Fixed speed);
+u32 (*gf_cfg_get_key_count)(GF_Config *cfgFile, const char *secName);
+u32 (*gf_term_object_subscene_type)(GF_Terminal *term, GF_ObjectManager *odm);
+Double (*gf_term_get_framerate)(GF_Terminal *term, Bool absoluteFPS);
+const char *(*gf_error_to_string)(GF_Err e);
+GF_Err (*gf_stretch_bits)(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *dst_wnd, GF_Window *src_wnd, u8 alpha, Bool flip, GF_ColorKey *colorKey, GF_ColorMatrix * cmat);
+void (*gf_list_del)(GF_List *ptr);
+void *(*gf_list_get)(GF_List *ptr, u32 itemNumber);
+void (*gf_term_disconnect)(GF_Terminal *term);
+Bool (*gf_term_is_supported_url)(GF_Terminal *term, const char *fileName, Bool use_parent_url, Bool no_mime_check);
+GF_List *(*gf_list_new)(void);
+const char *(*gf_modules_get_option)(GF_BaseInterface *interface_obj, const char *secName, const char *keyName);
+GF_Err (*gf_term_dump_scene)(GF_Terminal *term, char *rad_name, char **filename, Bool xml_dump, Bool skip_proto, GF_ObjectManager *odm);
+Bool (*gf_prompt_has_input)();
+GF_Err (*gf_term_scene_update)(GF_Terminal *term, char *type, char *com);
+void (*gf_term_connect)(GF_Terminal *term, const char *URL);
+u32 (*gf_term_get_object_count)(GF_Terminal *term, GF_ObjectManager *scene_od);
+u32 (*gf_modules_get_count)(GF_ModuleManager *pm);
+GF_ObjectManager *(*gf_term_get_root_object)(GF_Terminal *term);
+u32 (*gf_term_get_time_in_ms)(GF_Terminal *term);
+void (*gf_term_connect_with_path)(GF_Terminal *term, const char *URL, const char *parent_URL);
+gf_log_cbk (*gf_log_set_callback)(void *usr_cbk, gf_log_cbk cbk);
+GF_Err (*gf_log_modify_tools_levels)(const char *val);
+void (*gf_term_switch_quality)(GF_Terminal *term, Bool up);
+GF_Err (*gf_term_release_screen_buffer)(GF_Terminal *term, GF_VideoSurface *framebuffer);
+GF_Err (*gf_term_get_screen_buffer)(GF_Terminal *term, GF_VideoSurface *framebuffer);
+FILE *(*gf_f64_open)(const char *file_name, const char *mode);
+size_t (*gf_fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+GF_Err (*gf_img_png_enc)(char *data, u32 width, u32 height, s32 stride, u32 pixel_format, char *dst, u32 *dst_size);
+u32 (*utf8_to_ucs4)(u32 *ucs4_buf, u32 utf8_len, unsigned char *utf8_buf);
+
+#ifndef WIN32
+#include <pwd.h>
+#include <unistd.h>
+
+#else
+#include <windows.h> /*for GetModuleFileName*/
+#include <direct.h>  /*for _mkdir*/
+#include <shlobj.h>  /*for getting user-dir*/
+#ifndef SHGFP_TYPE_CURRENT
+#define SHGFP_TYPE_CURRENT 0 /*needed for MinGW*/
+#endif
+
+#ifdef _MSC_VER 
+/*get rid of console*/
+#if 0
+#pragma comment(linker,"/SUBSYSTEM:WINDOWS")
+#pragma comment(linker,"/ENTRY:main")
+#else
+#pragma comment(linker,"/SUBSYSTEM:CONSOLE") 
+#endif
+
+#endif // _MSC_VER
+
+#endif //WIN32
+
+
+/*local prototypes*/
+void PrintWorldInfo(GF_Terminal *term);
+void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number);
+void PrintODList(GF_Terminal *term, GF_ObjectManager *root_odm, u32 num, u32 indent, char *root_name);
+
+void ViewODs(GF_Terminal *term, Bool show_timing);
+void PrintGPACConfig();
+
+static Bool restart = 0;
+#if defined(__DARWIN__) || defined(__APPLE__)
+static Bool not_threaded = 1;
+#else
+static Bool not_threaded = 0;
+#endif
+static Bool no_audio = 0;
+static Bool no_regulation = 0;
+static Bool bench_mode = 0;
+Bool is_connected = 0;
+Bool startup_file = 0;
+GF_User user;
+GF_Terminal *term;
+u64 Duration;
+GF_Err last_error = GF_OK;
+
+static Fixed bench_speed = FLT2FIX(20);
+
+static Bool request_next_playlist_item = 0;
+
+static GF_Config *cfg_file;
+static Bool display_rti = 0;
+static Bool Run;
+static Bool CanSeek = 0;
+static u32 Volume=100;
+static char the_url[GF_MAX_PATH];
+static char pl_path[GF_MAX_PATH];
+static Bool no_mime_check = 1;
+static Bool be_quiet = 0;
+static u32 log_time_start = 0;
+
+static u32 forced_width=0;
+static u32 forced_height=0;
+
+/*windowless options*/
+u32 align_mode = 0;
+u32 init_w = 0;
+u32 init_h = 0;
+u32 last_x, last_y;
+Bool right_down = 0;
+
+void dump_frame(GF_Terminal *term, char *rad_path, u32 dump_type, u32 frameNum);
+Bool dump_file(char *the_url, u32 dump_mode, Double fps, u32 width, u32 height, Float scale, u32 *times, u32 nb_times);
+
+void PrintUsage()
+{
+       fprintf(stdout, "Usage Osmo4iOS [options] [filename]\n"
+               "\t-c fileName:    user-defined configuration file\n"
+               "\t-rti fileName:  logs run-time info (FPS, CPU, Mem usage) to file\n"
+               "\t-rtix fileName: same as -rti but driven by GPAC logs\n"
+               "\t-quiet:         removes script message, buffering and downloading status\n"
+               "\t-opt option:    Overrides an option in the configuration file. String format is section:key=value\n"
+               "\t-log-file file: sets output log file.\n"
+               "\t-log-level lev: sets log level. Possible values are:\n"
+               "\t        \"error\"      : logs only error messages\n"
+               "\t        \"warning\"    : logs error+warning messages\n"
+               "\t        \"info\"       : logs error+warning+info messages\n"
+               "\t        \"debug\"      : logs all messages\n"
+               "\n"
+               "\t-log-tools lt:  sets tool(s) to log. List of \':\'-separated values:\n"
+               "\t        \"core\"       : libgpac core\n"
+               "\t        \"coding\"     : bitstream formats (audio, video, scene)\n"
+               "\t        \"container\"  : container formats (ISO File, MPEG-2 TS, AVI, ...)\n"
+               "\t        \"network\"    : network data exept RTP trafic\n"
+               "\t        \"rtp\"        : rtp trafic\n"
+               "\t        \"author\"     : authoring tools (hint, import, export)\n"
+               "\t        \"sync\"       : terminal sync layer\n"
+               "\t        \"codec\"      : terminal codec messages\n"
+               "\t        \"parser\"     : scene parsers (svg, xmt, bt) and other\n"
+               "\t        \"media\"      : terminal media object management\n"
+               "\t        \"scene\"      : scene graph and scene manager\n"
+               "\t        \"script\"     : scripting engine messages\n"
+               "\t        \"interact\"   : interaction engine (events, scripts, etc)\n"
+               "\t        \"compose\"    : composition engine (2D, 3D, etc)\n"
+               "\t        \"service\"    : network service management\n"
+               "\t        \"mmio\"       : Audio/Video HW I/O management\n"
+               "\t        \"none\"       : no tool logged\n"
+               "\t        \"all\"        : all tools logged\n"
+               "\n"
+               "\t-size WxH:      specifies visual size (default: scene size)\n"
+               "\t-scale s:      scales the visual size (default: 1)\n"
+#if defined(__DARWIN__) || defined(__APPLE__)
+               "\t-thread:        enables thread usage for terminal and compositor \n"
+#else
+               "\t-no-thread:     disables thread usage (except for audio)\n"
+#endif
+               "\t-no-audio:      disables audio \n"
+               "\t-no-wnd:        uses windowless mode (Win32 only)\n"
+               "\t-align vh:      specifies v and h alignment for windowless mode\n"
+               "                   possible v values: t(op), m(iddle), b(ottom)\n"
+               "                   possible h values: l(eft), m(iddle), r(ight)\n"
+               "                   default alignment is top-left\n"
+               "                   default alignment is top-left\n"
+               "\t-pause:         pauses at first frame\n"
+               "\n"
+               "Dumper Options:\n"
+               "\t-bmp [times]:   dumps given frames to bmp\n"
+               "\t-raw [times]:   dumps given frames to bmp\n"
+               "\t-avi [times]:   dumps given file to raw avi\n"
+               "\t-rgbds:         dumps the RGBDS pixel format texture\n"
+               "                   with -avi [times]: dumps an rgbds-format .avi\n"
+               "\t-rgbd:          dumps the RGBD pixel format texture\n"
+               "                                       with -avi [times]: dumps an rgbd-format .avi\n"         
+               "\t-depth:         dumps depthmap (z-buffer) frames\n"
+               "                   with -avi [times]: dumps depthmap in grayscale .avi\n"              
+               "                   with -bmp: dumps depthmap in grayscale .bmp\n"              
+               "\t-fps FPS:       specifies frame rate for AVI dumping (default: 25.0)\n"
+               "\t-2d:            uses 2D compositor\n"
+               "\t-3d:            uses 3D compositor\n"
+               "\t-fill:          uses fill aspect ratio for dumping (default: none)\n"
+               "\t-show:          show window while dumping (default: no)\n"
+               "MP4Client - GPAC command line player and dumper - version %s\n"
+               "GPAC Written by Jean Le Feuvre (c) 2001-2005 - ENST (c) 2005-200X\n",
+
+               GPAC_FULL_VERSION
+               );
+}
+
+void PrintHelp()
+{
+       fprintf(stdout, "MP4Client command keys:\n"
+               "\to: connect to the specified URL\n"
+               "\tO: connect to the specified URL in playlist mode\n"
+               "\tN: switch to the next URL in the playlist (works with return key as well)\n"
+               "\tr: restart current presentation\n"
+               "\tp: play/pause the presentation\n"
+               "\ts: step one frame ahead\n"
+               "\tz: seek into presentation\n"
+               "\tt: print current timing\n"
+               "\n"
+               "\tw: view world info\n"
+               "\tv: view Object Descriptor list\n"
+               "\ti: view Object Descriptor info (by ID)\n"
+               "\tj: view Object Descriptor info (by number)\n"
+               "\tb: view media objects timing and buffering info\n"
+               "\tm: view media objects buffering and memory info\n"
+               "\td: dumps scene graph\n"
+               "\n"
+               "\tC: Enable Streaming Cache\n"
+               "\tS: Stops Streaming Cache and save to file\n"
+               "\tA: Aborts Streaming Cache\n"
+               "\n"
+               "\tk: turns stress mode on/off\n"
+               "\tn: changes navigation mode\n"
+               "\tx: reset to last active viewpoint\n"
+               "\n"
+               "\t2: restart using 2D compositor\n"
+               "\t3: restart using 3D compositor\n"
+               "\n"
+               "\t4: forces 4/3 Aspect Ratio\n"
+               "\t5: forces 16/9 Aspect Ratio\n"
+               "\t6: forces no Aspect Ratio (always fill screen)\n"
+               "\t7: forces original Aspect Ratio (default)\n"
+               "\n"
+               "\tL: changes to new log level. CF MP4Client usage for possible values\n"
+               "\tT: select new tools to log. CF MP4Client usage for possible values\n"
+               "\n"
+               "\tl: list available modules\n"
+               "\tc: prints some GPAC configuration info\n"
+               "\tR: toggles run-time info display on/off\n"
+               "\tq: exit the application\n"
+               "\th: print this message\n"
+               "\n"
+               "MP4Client - GPAC command line player - version %s\n"
+               "GPAC Written by Jean Le Feuvre (c) 2001-2005 - ENST (c) 2005-200X\n",
+
+               GPAC_FULL_VERSION
+               );
+}
+
+
+static void PrintTime(u64 time)
+{
+       u32 ms, h, m, s;
+       h = (u32) (time / 1000 / 3600);
+       m = (u32) (time / 1000 / 60 - h*60);
+       s = (u32) (time / 1000 - h*3600 - m*60);
+       ms = (u32) (time - (h*3600 + m*60 + s) * 1000);
+       fprintf(stdout, "%02d:%02d:%02d.%02d", h, m, s, ms);
+}
+
+
+static u32 rti_update_time_ms = 200;
+static FILE *rti_logs = NULL;
+static u64 memory_at_gpac_startup = 0;
+
+static void UpdateRTInfo(const char *legend)
+{
+       GF_SystemRTInfo rti;
+
+       /*refresh every second*/
+       if (!display_rti && !rti_logs) return;
+       if (!gf_sys_get_rti(rti_update_time_ms, &rti, 0) && !legend) 
+               return;
+
+       if (display_rti) {
+               if (!rti.process_memory) rti.process_memory = (u32) (memory_at_gpac_startup-rti.physical_memory_avail);
+               if (!rti.gpac_memory) rti.gpac_memory = (u32) (memory_at_gpac_startup-rti.physical_memory_avail);
+
+               if (display_rti==2) {
+                       fprintf(stdout, "FPS %02.2f - CPU %02d (%02d) - Mem %d kB\r", 
+                               gf_term_get_framerate(term, 0), rti.total_cpu_usage, rti.process_cpu_usage, (u32) (rti.gpac_memory / 1024) );
+               } else {
+                       char szMsg[1024];
+                       GF_Event evt;
+
+                       sprintf(szMsg, "FPS %02.2f - CPU %02d (%02d) - Mem %d kB", 
+                               gf_term_get_framerate(term, 0), rti.total_cpu_usage, rti.process_cpu_usage, (u32) (rti.gpac_memory / 1024) );
+                       evt.type = GF_EVENT_SET_CAPTION;
+                       evt.caption.caption = szMsg;
+                       gf_term_user_event(term, &evt);
+               }
+       }
+       if (rti_logs) {
+               fprintf(rti_logs, "% 8d\t% 8d\t% 8d\t% 4d\t% 8d\t%s", 
+                       gf_sys_clock(),
+                       gf_term_get_time_in_ms(term),
+                       rti.total_cpu_usage,
+                       (u32) gf_term_get_framerate(term, 0),
+                       (u32) (rti.gpac_memory / 1024), 
+                       legend ? legend : ""
+                       );
+               if (!legend) fprintf(rti_logs, "\n");
+       }
+}
+
+static void ResetCaption()
+{
+       GF_Event event;
+       if (display_rti) return;
+       event.type = GF_EVENT_SET_CAPTION;
+       if (is_connected) {
+               char szName[1024];
+               NetInfoCommand com;
+
+               event.caption.caption = NULL;
+               /*get any service info*/
+               if (!startup_file && gf_term_get_service_info(term, gf_term_get_root_object(term), &com) == GF_OK) {
+                       strcpy(szName, "");
+                       if (com.track_info) { 
+                               char szBuf[10];
+                               sprintf(szBuf, "%02d ", (u32) (com.track_info>>16) );
+                               strcat(szName, szBuf);
+                       }
+                       if (com.artist) { strcat(szName, com.artist); strcat(szName, " "); }
+                       if (com.name) { strcat(szName, com.name); strcat(szName, " "); }
+                       if (com.album) { strcat(szName, "("); strcat(szName, com.album); strcat(szName, ")"); }
+                       
+                       if (strlen(szName)) event.caption.caption = szName;
+               }
+               if (!event.caption.caption) {
+                       char *str = strrchr(the_url, '\\');
+                       if (!str) str = strrchr(the_url, '/');
+                       event.caption.caption = str ? str+1 : the_url;
+               }
+       } else {
+               event.caption.caption = "GPAC MP4Client " GPAC_FULL_VERSION;
+       }
+       gf_term_user_event(term, &event);
+}
+
+#ifdef WIN32
+u32 get_sys_col(int idx)
+{
+       u32 res;
+       DWORD val = GetSysColor(idx);
+       res = (val)&0xFF; res<<=8;
+       res |= (val>>8)&0xFF; res<<=8;
+       res |= (val>>16)&0xFF;
+       return res;
+}
+#endif
+
+void switch_bench()
+{
+       if (is_connected) {
+               bench_mode = !bench_mode;
+               display_rti = !display_rti;
+               ResetCaption();
+               gf_term_set_speed(term, bench_mode ? bench_speed : FIX_ONE);
+       }
+}
+
+Bool GPAC_EventProc(void *ptr, GF_Event *evt)
+{
+       if (!term) return 0;
+
+       switch (evt->type) {
+       case GF_EVENT_DURATION:
+               Duration = 1000;
+               Duration = (u64) (((s64) Duration) * evt->duration.duration);
+               CanSeek = evt->duration.can_seek;
+               break;
+       case GF_EVENT_MESSAGE:
+       {
+               const char *servName;
+               if (!evt->message.service || !strcmp(evt->message.service, the_url)) {
+                       servName = "main service";
+               } else if (!strnicmp(evt->message.service, "data:", 5)) {
+                       servName = "";
+               } else {
+                       servName = evt->message.service;
+               }
+               if (!evt->message.message) return 0;
+               if (evt->message.error) {
+                       if (!is_connected) last_error = evt->message.error;
+                       fprintf(stderr, "%s (%s): %s\n", evt->message.message, servName, gf_error_to_string(evt->message.error));
+               } else if (!be_quiet) 
+                       fprintf(stderr, "(%s) %s\r", servName, evt->message.message);
+       }
+               break;
+       case GF_EVENT_PROGRESS:
+       {
+               char *szTitle = "";
+               if (evt->progress.progress_type==0) szTitle = "Buffer ";
+               else if (evt->progress.progress_type==1) szTitle = "Download ";
+               else if (evt->progress.progress_type==2) szTitle = "Import ";
+               gf_set_progress(szTitle, evt->progress.done, evt->progress.total);
+       }
+               break;
+       
+
+       case GF_EVENT_DBLCLICK:
+               gf_term_set_option(term, GF_OPT_FULLSCREEN, !gf_term_get_option(term, GF_OPT_FULLSCREEN));
+               return 0;
+
+       case GF_EVENT_MOUSEDOWN:
+               if (evt->mouse.button==GF_MOUSE_RIGHT) {
+                       right_down = 1;
+                       last_x = evt->mouse.x;
+                       last_y = evt->mouse.y;
+               }
+               return 0;
+       case GF_EVENT_MOUSEUP:
+               if (evt->mouse.button==GF_MOUSE_RIGHT) {
+                       right_down = 0;
+                       last_x = evt->mouse.x;
+                       last_y = evt->mouse.y;
+               }
+               return 0;
+       case GF_EVENT_MOUSEMOVE:
+               if (right_down && (user.init_flags & GF_TERM_WINDOWLESS) ) {
+                       GF_Event move;
+                       move.move.x = evt->mouse.x - last_x;
+                       move.move.y = last_y-evt->mouse.y;
+                       move.type = GF_EVENT_MOVE;
+                       move.move.relative = 1;
+                       gf_term_user_event(term, &move);
+               }
+               return 0;
+
+       case GF_EVENT_KEYUP:
+               switch (evt->key.key_code) {
+               case GF_KEY_SPACE:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL) switch_bench();
+                       break;
+               }
+               break;
+       case GF_EVENT_KEYDOWN:
+               gf_term_process_shortcut(term, evt);
+               switch (evt->key.key_code) {
+               case GF_KEY_SPACE:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL) {
+                               /*ignore key repeat*/
+                               if (!bench_mode) switch_bench();
+                       }
+                       break;
+               case GF_KEY_PAGEDOWN:
+               case GF_KEY_MEDIANEXTTRACK:
+                       request_next_playlist_item = 1;
+                       break;
+               case GF_KEY_MEDIAPREVIOUSTRACK:
+                       break;
+               case GF_KEY_ESCAPE:
+                       gf_term_set_option(term, GF_OPT_FULLSCREEN, !gf_term_get_option(term, GF_OPT_FULLSCREEN));
+                       break;
+               case GF_KEY_F:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stderr, "Rendering rate: %f FPS\n", gf_term_get_framerate(term, 0));
+                       break;
+               case GF_KEY_T:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stderr, "Scene Time: %f \n", gf_term_get_time_in_ms(term)/1000.0);
+                       break;
+               case GF_KEY_D:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL) gf_term_set_option(term, GF_OPT_DRAW_MODE, (gf_term_get_option(term, GF_OPT_DRAW_MODE)==GF_DRAW_MODE_DEFER) ? GF_DRAW_MODE_IMMEDIATE : GF_DRAW_MODE_DEFER );
+                       break;
+               case GF_KEY_4: 
+                       if (evt->key.flags & GF_KEY_MOD_CTRL)
+                               gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_4_3); 
+                       break;
+               case GF_KEY_5: 
+                       if (evt->key.flags & GF_KEY_MOD_CTRL)
+                               gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_16_9); 
+                       break;
+               case GF_KEY_6: 
+                       if (evt->key.flags & GF_KEY_MOD_CTRL)
+                               gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_FILL_SCREEN); 
+                       break;
+               case GF_KEY_7: 
+                       if (evt->key.flags & GF_KEY_MOD_CTRL)
+                               gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_KEEP); 
+                       break;
+               case GF_KEY_P:
+                       if (evt->key.flags & GF_KEY_MOD_CTRL && is_connected) {
+                               Bool is_pause = gf_term_get_option(term, GF_OPT_PLAY_STATE);
+                               fprintf(stderr, "[Status: %s]\n", is_pause ? "Playing" : "Paused");
+                               gf_term_set_option(term, GF_OPT_PLAY_STATE, (gf_term_get_option(term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED) ? GF_STATE_PLAYING : GF_STATE_PAUSED);
+                       }
+                       break;
+               case GF_KEY_S:
+                       if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected) {
+                               gf_term_set_option(term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE);
+                               fprintf(stderr, "Step time: ");
+                               PrintTime(gf_term_get_time_in_ms(term));
+                               fprintf(stderr, "\n");
+                       }
+                       break;
+               case GF_KEY_B:
+                       if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected)
+                               ViewODs(term, 1);
+                       break;
+               case GF_KEY_M:
+                       if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected)
+                               ViewODs(term, 0);
+                       break;
+               case GF_KEY_H:
+                       if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected)
+                               gf_term_switch_quality(term, 1);
+                       break;
+               case GF_KEY_L:
+                       if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected)
+                               gf_term_switch_quality(term, 0);
+                       break;
+               }
+               break;
+
+       case GF_EVENT_CONNECT:
+               if (evt->connect.is_connected) {
+                       is_connected = 1;
+                       fprintf(stderr, "Service Connected\n");
+               } else if (is_connected) {
+                       fprintf(stderr, "Service %s\n", is_connected ? "Disconnected" : "Connection Failed");
+                       is_connected = 0;
+                       Duration = 0;
+               }
+               if (init_w && init_h) {
+                       gf_term_set_size(term, init_w, init_h);
+               }
+               ResetCaption();
+               break;
+       case GF_EVENT_EOS:
+               restart = 1;
+               break;
+       case GF_EVENT_SIZE:
+               if (user.init_flags & GF_TERM_WINDOWLESS) {
+                       GF_Event move;
+                       move.type = GF_EVENT_MOVE;
+                       move.move.align_x = align_mode & 0xFF;
+                       move.move.align_y = (align_mode>>8) & 0xFF;
+                       move.move.relative = 2;
+                       gf_term_user_event(term, &move);
+               } 
+               break;
+       case GF_EVENT_SCENE_SIZE:
+               if (forced_width && forced_height) {
+                       GF_Event size;
+                       size.type = GF_EVENT_SIZE;
+                       size.size.width = forced_width;
+                       size.size.height = forced_height;
+                       gf_term_user_event(term, &size);
+               }
+               break;
+
+       case GF_EVENT_METADATA:
+               ResetCaption();
+               break;
+
+       case GF_EVENT_QUIT:
+               Run = 0;
+               break;
+       case GF_EVENT_DISCONNECT:
+               gf_term_disconnect(term);
+               break;
+       case GF_EVENT_MIGRATE:
+       {
+       }
+               break;
+       case GF_EVENT_NAVIGATE_INFO:
+               if (evt->navigate.to_url) fprintf(stderr, "Go to URL: \"%s\"\r", evt->navigate.to_url);
+               break;
+       case GF_EVENT_NAVIGATE:
+               if (gf_term_is_supported_url(term, evt->navigate.to_url, 1, no_mime_check)) {
+                       strcpy(the_url, evt->navigate.to_url);
+                       fprintf(stderr, "Navigating to URL %s\n", the_url);
+                       gf_term_navigate_to(term, evt->navigate.to_url);
+                       return 1;
+               } else {
+                       fprintf(stderr, "Navigation destination not supported\nGo to URL: %s\n", evt->navigate.to_url);
+               }
+               break;
+       case GF_EVENT_SET_CAPTION:
+               gf_term_user_event(term, evt);
+               break;
+       case GF_EVENT_AUTHORIZATION:
+               if (!strlen(evt->auth.user)) {
+                       fprintf(stderr, "Authorization required for site %s\n", evt->auth.site_url);
+                       fprintf(stderr, "login: ");
+                       scanf("%s", evt->auth.user);
+               } else {
+                       fprintf(stderr, "Authorization required for %s@%s\n", evt->auth.user, evt->auth.site_url);
+               }
+               fprintf(stderr, "password: ");
+               gf_prompt_set_echo_off(1);
+               scanf("%s", evt->auth.password);
+               gf_prompt_set_echo_off(0);
+               return 1;
+       case GF_EVENT_SYS_COLORS:
+#ifdef WIN32
+               evt->sys_cols.sys_colors[0] = get_sys_col(COLOR_ACTIVEBORDER);
+               evt->sys_cols.sys_colors[1] = get_sys_col(COLOR_ACTIVECAPTION);
+               evt->sys_cols.sys_colors[2] = get_sys_col(COLOR_APPWORKSPACE);
+               evt->sys_cols.sys_colors[3] = get_sys_col(COLOR_BACKGROUND);
+               evt->sys_cols.sys_colors[4] = get_sys_col(COLOR_BTNFACE);
+               evt->sys_cols.sys_colors[5] = get_sys_col(COLOR_BTNHIGHLIGHT);
+               evt->sys_cols.sys_colors[6] = get_sys_col(COLOR_BTNSHADOW);
+               evt->sys_cols.sys_colors[7] = get_sys_col(COLOR_BTNTEXT);
+               evt->sys_cols.sys_colors[8] = get_sys_col(COLOR_CAPTIONTEXT);
+               evt->sys_cols.sys_colors[9] = get_sys_col(COLOR_GRAYTEXT);
+               evt->sys_cols.sys_colors[10] = get_sys_col(COLOR_HIGHLIGHT);
+               evt->sys_cols.sys_colors[11] = get_sys_col(COLOR_HIGHLIGHTTEXT);
+               evt->sys_cols.sys_colors[12] = get_sys_col(COLOR_INACTIVEBORDER);
+               evt->sys_cols.sys_colors[13] = get_sys_col(COLOR_INACTIVECAPTION);
+               evt->sys_cols.sys_colors[14] = get_sys_col(COLOR_INACTIVECAPTIONTEXT);
+               evt->sys_cols.sys_colors[15] = get_sys_col(COLOR_INFOBK);
+               evt->sys_cols.sys_colors[16] = get_sys_col(COLOR_INFOTEXT);
+               evt->sys_cols.sys_colors[17] = get_sys_col(COLOR_MENU);
+               evt->sys_cols.sys_colors[18] = get_sys_col(COLOR_MENUTEXT);
+               evt->sys_cols.sys_colors[19] = get_sys_col(COLOR_SCROLLBAR);
+               evt->sys_cols.sys_colors[20] = get_sys_col(COLOR_3DDKSHADOW);
+               evt->sys_cols.sys_colors[21] = get_sys_col(COLOR_3DFACE);
+               evt->sys_cols.sys_colors[22] = get_sys_col(COLOR_3DHIGHLIGHT);
+               evt->sys_cols.sys_colors[23] = get_sys_col(COLOR_3DLIGHT);
+               evt->sys_cols.sys_colors[24] = get_sys_col(COLOR_3DSHADOW);
+               evt->sys_cols.sys_colors[25] = get_sys_col(COLOR_WINDOW);
+               evt->sys_cols.sys_colors[26] = get_sys_col(COLOR_WINDOWFRAME);
+               evt->sys_cols.sys_colors[27] = get_sys_col(COLOR_WINDOWTEXT);
+               return 1;
+#else
+               memset(evt->sys_cols.sys_colors, 0, sizeof(u32)*28);
+               return 1;
+#endif
+               break;
+       }
+       return 0;
+}
+
+
+void list_modules(GF_ModuleManager *modules)
+{
+       u32 i;
+       fprintf(stderr, "\rAvailable modules:\n");
+       for (i=0; i<gf_modules_get_count(modules); i++) {
+               char *str = (char *) gf_modules_get_file_name(modules, i);
+               if (str) fprintf(stderr, "\t%s\n", str);
+       }
+       fprintf(stderr, "\n");
+}
+
+
+void set_navigation()
+{
+       GF_Err e;
+       char navstr[20], nav;
+       u32 type = gf_term_get_option(term, GF_OPT_NAVIGATION_TYPE);
+       e = GF_OK;
+       if (!type) {
+               fprintf(stdout, "Content/compositor doesn't allow user-selectable navigation\n");
+       } else if (type==1) {
+               fprintf(stdout, "Select Navigation (\'N\'one, \'E\'xamine, \'S\'lide): ");
+               scanf("%s", navstr);
+               nav = navstr[0];
+               if (nav=='N') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_NONE);
+               else if (nav=='E') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_EXAMINE);
+               else if (nav=='S') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_SLIDE);
+               else fprintf(stdout, "Unknown selector \'%c\' - only \'N\',\'E\',\'S\' allowed\n", nav);
+       } else if (type==2) {
+               fprintf(stdout, "Select Navigation (\'N\'one, \'W\'alk, \'F\'ly, \'E\'xamine, \'P\'an, \'S\'lide, \'G\'ame, \'V\'R, \'O\'rbit): ");
+               scanf("%s", navstr);
+               nav = navstr[0];
+               if (nav=='N') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_NONE);
+               else if (nav=='W') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_WALK);
+               else if (nav=='F') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_FLY);
+               else if (nav=='E') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_EXAMINE);
+               else if (nav=='P') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_PAN);
+               else if (nav=='S') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_SLIDE);
+               else if (nav=='G') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_GAME);
+               else if (nav=='O') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_ORBIT);
+               else if (nav=='V') e = gf_term_set_option(term, GF_OPT_NAVIGATION, GF_NAVIGATE_VR);
+               else fprintf(stdout, "Unknown selector %c - only \'N\',\'W\',\'F\',\'E\',\'P\',\'S\',\'G\', \'V\', \'O\' allowed\n", nav);
+       }
+       if (e) fprintf(stdout, "Error setting mode: %s\n", gf_error_to_string(e));
+}
+
+
+static Bool get_time_list(char *arg, u32 *times, u32 *nb_times)
+{
+       char *str;
+       Float var;
+       Double sec;
+       u32 h, m, s, ms, f, fps;
+       if (!arg || (arg[0]=='-') || !isdigit(arg[0])) return 0;
+
+       /*SMPTE time code*/
+       if (strchr(arg, ':') && strchr(arg, ';') && strchr(arg, '/')) {
+               if (sscanf(arg, "%02d:%02d:%02d;%02d/%02d", &h, &m, &s, &f, &fps)==5) {
+                       sec = 0;
+                       if (fps) sec = ((Double)f) / fps;
+                       sec += 3600*h + 60*m + s;
+                       times[*nb_times] = (u32) (1000*sec);
+                       (*nb_times) ++;
+                       return 1;
+               }
+       }
+       while (arg) {
+               str = strchr(arg, '-');
+               if (str) str[0] = 0;
+               /*HH:MM:SS:MS time code*/
+               if (strchr(arg, ':') && (sscanf(arg, "%02d:%02d:%02d:%02d", &h, &m, &s, &ms)==4)) {
+                       sec = ms;
+                       sec /= 1000;
+                       sec += 3600*h + 60*m + s;
+                       times[*nb_times] = (u32) (1000*sec);
+                       (*nb_times) ++;
+               } else if (sscanf(arg, "%f", &var)==1) {
+                       sec = atof(arg);
+                       times[*nb_times] = (u32) (1000*sec);
+                       (*nb_times) ++;
+               }
+               if (!str) break;
+               str[0] = '-';
+               arg = str+1;
+       }
+       return 1;
+}
+
+static void on_gpac_log(void *cbk, u32 ll, u32 lm, const char *fmt, va_list list)
+{
+       FILE *logs = cbk;
+
+       if (rti_logs && (lm & GF_LOG_RTI)) {
+               char szMsg[2048];
+               vsprintf(szMsg, fmt, list);
+               UpdateRTInfo(szMsg + 6 /*"[RTI] "*/);
+       } else {
+               if (log_time_start) fprintf(logs, "[At %d]", gf_sys_clock() - log_time_start);
+               vfprintf(logs, fmt, list);
+               fflush(logs);
+       }
+}
+
+static void init_rti_logs(char *rti_file, char *url, Bool use_rtix)
+{
+       if (rti_logs) fclose(rti_logs);
+       rti_logs = gf_f64_open(rti_file, "wt");
+       if (rti_logs) {
+               fprintf(rti_logs, "!! GPAC RunTime Info ");
+               if (url) fprintf(rti_logs, "for file %s", url);
+               fprintf(rti_logs, " !!\n");
+               fprintf(rti_logs, "SysTime(ms)\tSceneTime(ms)\tCPU\tFPS\tMemory(kB)\tObservation\n");
+
+               /*turn on RTI loging*/
+               if (use_rtix) {
+                       gf_log_set_callback(NULL, on_gpac_log);
+                       gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_ERROR);
+                       gf_log_set_tool_level(GF_LOG_RTI, GF_LOG_DEBUG);
+
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_RTI, ("[RTI] System state when enabling log\n"));
+               } else if (log_time_start) {
+                       log_time_start = gf_sys_clock();
+               }
+       }
+}
+
+#ifdef GPAC_IPHONE
+int SDL_main (int argc, char *argv[])
+#else
+int main (int argc, char *argv[])
+#endif
+{
+       char c;
+       const char *str;
+       u32 i, times[100], nb_times, dump_mode;
+       u32 simulation_time = 0;
+       Bool auto_exit = 0;
+       Bool start_fs = 0;
+       Bool use_rtix = 0;
+       Bool rgbds_dump = 0;
+       Bool rgbd_dump = 0;
+       Bool depth_dump = 0;
+       Bool pause_at_first = 0;
+       Bool enable_mem_tracker = 0;
+       Double fps = 25.0;
+       Bool ret, fill_ar, visible;
+       char *url_arg, *the_cfg, *rti_file;
+       GF_SystemRTInfo rti;
+       FILE *playlist = NULL;
+       FILE *logfile = NULL;
+       Float scale = 1;
+       int *libgpac_so = NULL;
+       
+       libgpac_so = dlopen("/Applications/osmo4ios.app/libgpac_dynamic.dylib", RTLD_LAZY);
+       fprintf(stderr, "dlopen libgpac_so: %p\n", libgpac_so);
+       fprintf(stderr, "dlsym: %p gf_log_lt\n", gf_log_lt = dlsym(libgpac_so, "gf_log_lt"));
+       fprintf(stderr, "dlsym: %p AVI_close\n", AVI_close = dlsym(libgpac_so, "AVI_close"));
+       fprintf(stderr, "dlsym: %p gf_sleep\n", gf_sleep = dlsym(libgpac_so, "gf_sleep"));
+       fprintf(stderr, "dlsym: %p gf_term_del\n", gf_term_del = dlsym(libgpac_so, "gf_term_del"));
+       fprintf(stderr, "dlsym: %p gf_sc_release_screen_buffer\n", gf_sc_release_screen_buffer = dlsym(libgpac_so, "gf_sc_release_screen_buffer"));
+       fprintf(stderr, "dlsym: %p gf_prompt_get_char\n", gf_prompt_get_char = dlsym(libgpac_so, "gf_prompt_get_char"));
+       fprintf(stderr, "dlsym: %p gf_set_progress\n", gf_set_progress = dlsym(libgpac_so, "gf_set_progress"));
+       fprintf(stderr, "dlsym: %p gf_term_new\n", gf_term_new = dlsym(libgpac_so, "gf_term_new"));
+       fprintf(stderr, "dlsym: %p gf_term_process_step\n", gf_term_process_step = dlsym(libgpac_so, "gf_term_process_step"));
+       fprintf(stderr, "dlsym: %p gf_sc_get_screen_buffer\n", gf_sc_get_screen_buffer = dlsym(libgpac_so, "gf_sc_get_screen_buffer"));
+       fprintf(stderr, "dlsym: %p gf_iphone_set_sdl_audio_module\n", gf_iphone_set_sdl_audio_module = dlsym(libgpac_so, "gf_iphone_set_sdl_audio_module"));
+       fprintf(stderr, "dlsym: %p gf_term_step_clocks\n", gf_term_step_clocks = dlsym(libgpac_so, "gf_term_step_clocks"));
+       fprintf(stderr, "dlsym: %p gf_prompt_set_echo_off\n", gf_prompt_set_echo_off = dlsym(libgpac_so, "gf_prompt_set_echo_off"));
+       fprintf(stderr, "dlsym: %p gf_log_tool_level_on\n", gf_log_tool_level_on = dlsym(libgpac_so, "gf_log_tool_level_on"));
+       fprintf(stderr, "dlsym: %p gf_cfg_set_key\n", gf_cfg_set_key = dlsym(libgpac_so, "gf_cfg_set_key"));
+       fprintf(stderr, "dlsym: %p gf_cfg_get_section_count\n", gf_cfg_get_section_count = dlsym(libgpac_so, "gf_cfg_get_section_count"));
+       fprintf(stderr, "dlsym: %p gf_term_get_service_info\n", gf_term_get_service_info = dlsym(libgpac_so, "gf_term_get_service_info"));
+       fprintf(stderr, "dlsym: %p gf_term_set_size\n", gf_term_set_size = dlsym(libgpac_so, "gf_term_set_size"));
+       fprintf(stderr, "dlsym: %p gf_sys_get_rti\n", gf_sys_get_rti = dlsym(libgpac_so, "gf_sys_get_rti"));
+       fprintf(stderr, "dlsym: %p gf_term_play_from_time\n", gf_term_play_from_time = dlsym(libgpac_so, "gf_term_play_from_time"));
+       fprintf(stderr, "dlsym: %p gf_malloc\n", gf_malloc = dlsym(libgpac_so, "gf_malloc"));
+       fprintf(stderr, "dlsym: %p gf_log_set_tool_level\n", gf_log_set_tool_level = dlsym(libgpac_so, "gf_log_set_tool_level"));
+       fprintf(stderr, "dlsym: %p gf_log_set_tools_levels\n", gf_log_set_tools_levels = dlsym(libgpac_so, "gf_log_set_tools_levels"));
+       fprintf(stderr, "dlsym: %p gf_log_modify_tools_levels\n", gf_log_modify_tools_levels = dlsym(libgpac_so, "gf_log_modify_tools_levels"));
+       fprintf(stderr, "dlsym: %p gf_iphone_set_sdl_video_module\n", gf_iphone_set_sdl_video_module = dlsym(libgpac_so, "gf_iphone_set_sdl_video_module"));
+       fprintf(stderr, "dlsym: %p gf_term_get_option\n", gf_term_get_option = dlsym(libgpac_so, "gf_term_get_option"));
+       fprintf(stderr, "dlsym: %p gf_term_user_event\n", gf_term_user_event = dlsym(libgpac_so, "gf_term_user_event"));
+       fprintf(stderr, "dlsym: %p gf_modules_get_file_name\n", gf_modules_get_file_name = dlsym(libgpac_so, "gf_modules_get_file_name"));
+       fprintf(stderr, "dlsym: %p gf_mx_new\n", gf_mx_new = dlsym(libgpac_so, "gf_mx_new"));
+       fprintf(stderr, "dlsym: %p gf_list_count\n", gf_list_count = dlsym(libgpac_so, "gf_list_count"));
+       fprintf(stderr, "dlsym: %p gf_free\n", gf_free = dlsym(libgpac_so, "gf_free"));
+       fprintf(stderr, "dlsym: %p gf_term_get_world_info\n", gf_term_get_world_info = dlsym(libgpac_so, "gf_term_get_world_info"));
+       fprintf(stderr, "dlsym: %p gf_cfg_get_section_name\n", gf_cfg_get_section_name = dlsym(libgpac_so, "gf_cfg_get_section_name"));
+       fprintf(stderr, "dlsym: %p gf_term_navigate_to\n", gf_term_navigate_to = dlsym(libgpac_so, "gf_term_navigate_to"));
+       fprintf(stderr, "dlsym: %p gf_modules_del\n", gf_modules_del = dlsym(libgpac_so, "gf_modules_del"));
+       fprintf(stderr, "dlsym: %p gf_modules_new\n", gf_modules_new = dlsym(libgpac_so, "gf_modules_new"));
+       fprintf(stderr, "dlsym: %p gf_sys_init\n", gf_sys_init = dlsym(libgpac_so, "gf_sys_init"));
+       fprintf(stderr, "dlsym: %p gf_log\n", gf_log = dlsym(libgpac_so, "gf_log"));
+       fprintf(stderr, "dlsym: %p gf_term_get_object_info\n", gf_term_get_object_info = dlsym(libgpac_so, "gf_term_get_object_info"));
+       fprintf(stderr, "dlsym: %p gf_mx_p\n", gf_mx_p = dlsym(libgpac_so, "gf_mx_p"));
+       fprintf(stderr, "dlsym: %p gf_mx_v\n", gf_mx_v = dlsym(libgpac_so, "gf_mx_v"));
+       fprintf(stderr, "dlsym: %p gf_mx_del\n", gf_mx_del = dlsym(libgpac_so, "gf_mx_del"));
+       fprintf(stderr, "dlsym: %p gf_term_process_flush\n", gf_term_process_flush = dlsym(libgpac_so, "gf_term_process_flush"));
+       fprintf(stderr, "dlsym: %p gf_cfg_get_key_name\n", gf_cfg_get_key_name = dlsym(libgpac_so, "gf_cfg_get_key_name"));
+       fprintf(stderr, "dlsym: %p AVI_write_frame\n", AVI_write_frame = dlsym(libgpac_so, "AVI_write_frame"));
+       fprintf(stderr, "dlsym: %p gf_cfg_del\n", gf_cfg_del = dlsym(libgpac_so, "gf_cfg_del"));
+       fprintf(stderr, "dlsym: %p gf_term_get_channel_net_info\n", gf_term_get_channel_net_info = dlsym(libgpac_so, "gf_term_get_channel_net_info"));
+       fprintf(stderr, "dlsym: %p gf_term_process_shortcut\n", gf_term_process_shortcut = dlsym(libgpac_so, "gf_term_process_shortcut"));
+       fprintf(stderr, "dlsym: %p gf_cfg_init\n", gf_cfg_init = dlsym(libgpac_so, "gf_cfg_init"));
+       fprintf(stderr, "dlsym: %p gf_term_get_download_info\n", gf_term_get_download_info = dlsym(libgpac_so, "gf_term_get_download_info"));
+       fprintf(stderr, "dlsym: %p gf_sys_clock\n", gf_sys_clock = dlsym(libgpac_so, "gf_sys_clock"));
+       fprintf(stderr, "dlsym: %p gf_term_get_object\n", gf_term_get_object = dlsym(libgpac_so, "gf_term_get_object"));
+       fprintf(stderr, "dlsym: %p gf_term_set_option\n", gf_term_set_option = dlsym(libgpac_so, "gf_term_set_option"));
+       fprintf(stderr, "dlsym: %p gf_sys_close\n", gf_sys_close = dlsym(libgpac_so, "gf_sys_close"));
+       fprintf(stderr, "dlsym: %p gf_term_connect_from_time\n", gf_term_connect_from_time = dlsym(libgpac_so, "gf_term_connect_from_time"));
+       fprintf(stderr, "dlsym: %p AVI_open_output_file\n", AVI_open_output_file = dlsym(libgpac_so, "AVI_open_output_file"));
+       fprintf(stderr, "dlsym: %p gf_cfg_get_key\n", gf_cfg_get_key = dlsym(libgpac_so, "gf_cfg_get_key"));
+       fprintf(stderr, "dlsym: %p AVI_set_video\n", AVI_set_video = dlsym(libgpac_so, "AVI_set_video"));
+       fprintf(stderr, "dlsym: %p gf_term_set_speed\n", gf_term_set_speed = dlsym(libgpac_so, "gf_term_set_speed"));
+       fprintf(stderr, "dlsym: %p gf_cfg_get_key_count\n", gf_cfg_get_key_count = dlsym(libgpac_so, "gf_cfg_get_key_count"));
+       fprintf(stderr, "dlsym: %p gf_term_object_subscene_type\n", gf_term_object_subscene_type = dlsym(libgpac_so, "gf_term_object_subscene_type"));
+       fprintf(stderr, "dlsym: %p gf_term_get_framerate\n", gf_term_get_framerate = dlsym(libgpac_so, "gf_term_get_framerate"));
+       fprintf(stderr, "dlsym: %p gf_error_to_string\n", gf_error_to_string = dlsym(libgpac_so, "gf_error_to_string"));
+       fprintf(stderr, "dlsym: %p gf_stretch_bits\n", gf_stretch_bits = dlsym(libgpac_so, "gf_stretch_bits"));
+       fprintf(stderr, "dlsym: %p gf_list_del\n", gf_list_del = dlsym(libgpac_so, "gf_list_del"));
+       fprintf(stderr, "dlsym: %p gf_list_get\n", gf_list_get = dlsym(libgpac_so, "gf_list_get"));
+       fprintf(stderr, "dlsym: %p gf_term_disconnect\n", gf_term_disconnect = dlsym(libgpac_so, "gf_term_disconnect"));
+       fprintf(stderr, "dlsym: %p gf_term_is_supported_url\n", gf_term_is_supported_url = dlsym(libgpac_so, "gf_term_is_supported_url"));
+       fprintf(stderr, "dlsym: %p gf_list_new\n", gf_list_new = dlsym(libgpac_so, "gf_list_new"));
+       fprintf(stderr, "dlsym: %p gf_modules_get_option\n", gf_modules_get_option = dlsym(libgpac_so, "gf_modules_get_option"));
+       fprintf(stderr, "dlsym: %p gf_term_dump_scene\n", gf_term_dump_scene = dlsym(libgpac_so, "gf_term_dump_scene"));
+       fprintf(stderr, "dlsym: %p gf_prompt_has_input\n", gf_prompt_has_input = dlsym(libgpac_so, "gf_prompt_has_input"));
+       fprintf(stderr, "dlsym: %p gf_term_scene_update\n", gf_term_scene_update = dlsym(libgpac_so, "gf_term_scene_update"));
+       fprintf(stderr, "dlsym: %p gf_term_connect\n", gf_term_connect = dlsym(libgpac_so, "gf_term_connect"));
+       fprintf(stderr, "dlsym: %p gf_term_get_object_count\n", gf_term_get_object_count = dlsym(libgpac_so, "gf_term_get_object_count"));
+       fprintf(stderr, "dlsym: %p gf_modules_get_count\n", gf_modules_get_count = dlsym(libgpac_so, "gf_modules_get_count"));
+       fprintf(stderr, "dlsym: %p gf_term_get_root_object\n", gf_term_get_root_object = dlsym(libgpac_so, "gf_term_get_root_object"));
+       fprintf(stderr, "dlsym: %p gf_term_get_time_in_ms\n", gf_term_get_time_in_ms = dlsym(libgpac_so, "gf_term_get_time_in_ms"));
+       fprintf(stderr, "dlsym: %p gf_term_connect_with_path\n", gf_term_connect_with_path = dlsym(libgpac_so, "gf_term_connect_with_path"));
+       fprintf(stderr, "dlsym: %p gf_log_set_callback\n", gf_log_set_callback = dlsym(libgpac_so, "gf_log_set_callback"));
+       fprintf(stderr, "dlsym: %p gf_term_switch_quality\n", gf_term_switch_quality = dlsym(libgpac_so, "gf_term_switch_quality"));
+       fprintf(stderr, "dlsym: %p gf_term_release_screen_buffer\n", gf_term_release_screen_buffer = dlsym(libgpac_so, "gf_term_release_screen_buffer"));
+       fprintf(stderr, "dlsym: %p gf_term_get_screen_buffer\n", gf_term_get_screen_buffer = dlsym(libgpac_so, "gf_term_get_screen_buffer"));
+       fprintf(stderr, "dlsym: %p gf_f64_open\n", gf_f64_open = dlsym(libgpac_so, "gf_f64_open"));
+       fprintf(stderr, "dlsym: %p gf_fwrite\n", gf_fwrite = dlsym(libgpac_so, "gf_fwrite"));
+       fprintf(stderr, "dlsym: %p gf_img_png_enc\n", gf_img_png_enc = dlsym(libgpac_so, "gf_img_png_enc"));
+       fprintf(stderr, "dlsym: %p utf8_to_ucs4\n", utf8_to_ucs4 = dlsym(libgpac_so, "utf8_to_ucs4"));
+
+       /*by default use current dir*/
+       strcpy(the_url, ".");
+
+       memset(&user, 0, sizeof(GF_User));
+
+       dump_mode = 0;
+       fill_ar = visible = 0;
+       url_arg = the_cfg = rti_file = NULL;
+       nb_times = 0;
+       times[0] = 0;
+
+       /*first locate config file if specified*/
+       for (i=1; i<(u32) argc; i++) {
+               char *arg = argv[i];
+               if (!strcmp(arg, "-c") || !strcmp(arg, "-cfg")) {
+                       the_cfg = argv[i+1];
+                       i++;
+               }
+               else if (!strcmp(arg, "-mem-track")) enable_mem_tracker = 1;
+       }
+
+       gf_sys_init(enable_mem_tracker);
+       gf_iphone_set_sdl_video_module(SDL_NewVideo);
+       gf_iphone_set_sdl_audio_module(SDL_NewAudio);
+       
+       cfg_file = gf_cfg_init(the_cfg, NULL);
+       if (!cfg_file) {
+               fprintf(stdout, "Error: Configuration File \"GPAC.cfg\" not found\n");
+               if (logfile) fclose(logfile);
+               return 1;
+       }
+
+       gf_log_set_tools_levels( gf_cfg_get_key(cfg_file, "General", "Logs") );
+
+       for (i=1; i<(u32) argc; i++) {
+               char *arg = argv[i];
+//             if (isalnum(arg[0]) || (arg[0]=='/') || (arg[0]=='.') || (arg[0]=='\\') ) {
+               if (arg[0] != '-') {
+                       url_arg = arg;
+               } else if (!strcmp(arg, "-c") || !strcmp(arg, "-cfg")) {
+                       the_cfg = argv[i+1];
+                       i++;
+               } else if (!strcmp(arg, "-rti")) {
+                       rti_file = argv[i+1];
+                       i++;
+               } else if (!strcmp(arg, "-rtix")) {
+                       rti_file = argv[i+1];
+                       i++;
+                       use_rtix = 1;
+               } else if (!strcmp(arg, "-fill")) {
+                       fill_ar = 1;
+               } else if (!strcmp(arg, "-show")) {
+                       visible = 1;
+               } else if (!strcmp(arg, "-avi")) {
+                       if (rgbds_dump) dump_mode = 5;
+                       else if (depth_dump) dump_mode = 8;
+                       else if (rgbd_dump) dump_mode = 10;
+                       else dump_mode=1;
+                       if ((url_arg || (i+2<(u32)argc)) && get_time_list(argv[i+1], times, &nb_times)) i++;
+               } else if (!strcmp(arg, "-rgbds")) { /*get dump in rgbds pixel format*/
+                       rgbds_dump = 1;
+                       dump_mode=6;                    /* rgbds texture directly*/
+                       if (dump_mode==1) dump_mode = 5;    /* .avi rgbds dump*/
+               } else if (!strcmp(arg, "-rgbd")) { /*get dump in rgbd pixel format*/
+                       rgbd_dump = 1;
+                       dump_mode=9;  /* rgbd texture directly*/
+                       if (dump_mode==1) dump_mode = 10;    /* .avi rgbds dump*/
+               } else if (!strcmp(arg, "-depth")) {
+                       depth_dump = 1;        
+                       if (dump_mode==2) dump_mode=7; /* grayscale .bmp depth dump*/
+                       else if (dump_mode==1) dump_mode=8; /* .avi depth dump*/
+                       else dump_mode=4;   /*depth dump*/
+               } else if (!strcmp(arg, "-bmp")) {
+                       if(depth_dump) dump_mode=7; /*grayscale depth .bmp dump*/
+                       else dump_mode=2;
+                       if ((url_arg || (i+2<(u32)argc)) && get_time_list(argv[i+1], times, &nb_times)) i++;
+               } else if (!strcmp(arg, "-raw")) {
+                       dump_mode = 3;
+                       if ((url_arg || (i+2<(u32)argc)) && get_time_list(argv[i+1], times, &nb_times)) i++;
+
+               } else if (!stricmp(arg, "-size")) {
+                       if (sscanf(argv[i+1], "%dx%d", &forced_width, &forced_height) != 2) {
+                               forced_width = forced_height = 0;
+                       }
+                       i++;
+               } else if (!stricmp(arg, "-scale")) {
+                       sscanf(argv[i+1], "%f", &scale);
+                       i++;
+               } else if (!stricmp(arg, "-fps")) {
+                       fps = atof(argv[i+1]);
+                       i++;
+               } else if (!strcmp(arg, "-quiet")) {
+                       be_quiet = 1;
+               } else if (!strcmp(arg, "-log-file") || !strcmp(arg, "-lf")) {
+                       logfile = gf_f64_open(argv[i+1], "wt");
+                       gf_log_set_callback(logfile, on_gpac_log);
+                       i++;
+               } else if (!strcmp(arg, "-logs")) {
+                       gf_log_set_tools_levels( argv[i+1] );
+                       i++;
+               } else if (!strcmp(arg, "-log-clock") || !strcmp(arg, "-lc")) {
+                       log_time_start = 1;
+               } else if (!strcmp(arg, "-align")) {
+                       if (argv[i+1][0]=='m') align_mode = 1;
+                       else if (argv[i+1][0]=='b') align_mode = 2;
+                       align_mode <<= 8;
+                       if (argv[i+1][1]=='m') align_mode |= 1;
+                       else if (argv[i+1][1]=='r') align_mode |= 2;
+                       i++;
+               }
+               else if (!strcmp(arg, "-no-wnd")) user.init_flags |= GF_TERM_WINDOWLESS;
+#if defined(__DARWIN__) || defined(__APPLE__)
+               else if (!strcmp(arg, "-thread")) not_threaded = 0;
+#else
+               else if (!strcmp(arg, "-no-thread")) not_threaded = 1;
+#endif
+               else if (!strcmp(arg, "-no-audio")) no_audio = 1;
+               else if (!strcmp(arg, "-no-regulation")) no_regulation = 1;
+               else if (!strcmp(arg, "-fs")) start_fs = 1;
+               else if (!strcmp(arg, "-pause")) pause_at_first = 1;
+               else if (!strcmp(arg, "-exit")) auto_exit = 1;
+               else if (!strcmp(arg, "-mem-track")) enable_mem_tracker = 1;
+               else if (!strcmp(arg, "-opt")) {
+                       char *sep, *sep2, szSec[1024], szKey[1024], szVal[1024];
+                       sep = strchr(argv[i+1], ':');
+                       if (sep) {
+                               sep[0] = 0;
+                               strcpy(szSec, argv[i+1]);
+                               sep[0] = ':'; sep ++;
+                               sep2 = strchr(sep, '=');
+                               if (sep2) {
+                                       sep2[0] = 0;
+                                       strcpy(szKey, sep);
+                                       strcpy(szVal, sep2+1);
+                                       sep2[0] = '='; 
+                                       if (!stricmp(szVal, "null")) szVal[0]=0;
+                                       gf_cfg_set_key(cfg_file, szSec, szKey, szVal[0] ? szVal : NULL);
+                               }
+                       }
+                       i++;
+               }
+               else if (!strncmp(arg, "-run-for=", 9)) simulation_time = atoi(arg+9);
+               else {
+                       PrintUsage();
+                       return 1;
+               }
+       }
+       if (dump_mode && !url_arg) {
+               fprintf(stdout, "Missing argument for dump\n");
+               PrintUsage();
+               if (logfile) fclose(logfile);
+               return 1;
+       }
+       if (dump_mode) rti_file = NULL;
+
+       gf_sys_get_rti(500, &rti, GF_RTI_SYSTEM_MEMORY_ONLY);
+       memory_at_gpac_startup = rti.physical_memory_avail;
+       if (rti_file) init_rti_logs(rti_file, url_arg, use_rtix);
+
+       /*setup dumping options*/
+       if (dump_mode) {
+               user.init_flags |= GF_TERM_NO_AUDIO | GF_TERM_NO_COMPOSITOR_THREAD | GF_TERM_NO_REGULATION /*| GF_TERM_INIT_HIDE*/;
+               if (visible || dump_mode==8) user.init_flags |= GF_TERM_INIT_HIDE;
+       } else {
+               init_w = forced_width;
+               init_h = forced_height;
+       }
+
+       fprintf(stderr, "Loading modules\n");
+       str = gf_cfg_get_key(cfg_file, "General", "ModulesDirectory");
+
+       user.modules = gf_modules_new((const unsigned char *) str, cfg_file);
+       if (user.modules) i = gf_modules_get_count(user.modules);
+       if (!i || !user.modules) {
+               fprintf(stdout, "Error: no modules found in %s - exiting\n", str);
+               if (user.modules) gf_modules_del(user.modules);
+               gf_cfg_del(cfg_file);
+               gf_sys_close();
+               if (logfile) fclose(logfile);
+               return 1;
+       }
+       fprintf(stderr, "Modules Loaded (%d found in %s)\n", i, str);
+       
+       user.config = cfg_file;
+       user.EventProc = GPAC_EventProc;
+       /*dummy in this case (global vars) but MUST be non-NULL*/
+       user.opaque = user.modules;
+       if (not_threaded) user.init_flags |= GF_TERM_NO_COMPOSITOR_THREAD;
+       if (no_audio) user.init_flags |= GF_TERM_NO_AUDIO;
+       if (no_regulation) user.init_flags |= GF_TERM_NO_REGULATION;
+
+       fprintf(stderr, "Loading GPAC Terminal\n");     
+       term = gf_term_new(&user);
+       if (!term) {
+               fprintf(stderr, "\nInit error - check you have at least one video out and one rasterizer...\nFound modules:\n");
+               list_modules(user.modules);
+               gf_modules_del(user.modules);
+               gf_cfg_del(cfg_file);
+               gf_sys_close();
+               if (logfile) fclose(logfile);
+               return 1;
+       }
+       fprintf(stderr, "Terminal Loaded\n");
+
+
+       if (dump_mode) {
+//             gf_term_set_option(term, GF_OPT_VISIBLE, 0);
+               if (fill_ar) gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_FILL_SCREEN);
+       } else {
+               /*check video output*/
+               str = gf_cfg_get_key(cfg_file, "Video", "DriverName");
+               if (!strcmp(str, "Raw Video Output")) fprintf(stdout, "WARNING: using raw output video (memory only) - no display used\n");
+               /*check audio output*/
+               str = gf_cfg_get_key(cfg_file, "Audio", "DriverName");
+               if (!str || !strcmp(str, "No Audio Output Available")) fprintf(stdout, "WARNING: no audio output availble - make sure no other program is locking the sound card\n");
+
+               str = gf_cfg_get_key(cfg_file, "General", "NoMIMETypeFetch");
+               no_mime_check = (str && !stricmp(str, "yes")) ? 1 : 0;
+       }
+
+       str = gf_cfg_get_key(cfg_file, "HTTPProxy", "Enabled");
+       if (str && !strcmp(str, "yes")) {
+               str = gf_cfg_get_key(cfg_file, "HTTPProxy", "Name");
+               if (str) fprintf(stdout, "HTTP Proxy %s enabled\n", str);
+       }
+
+       if (rti_file) {
+               str = gf_cfg_get_key(cfg_file, "General", "RTIRefreshPeriod");
+               if (str) {
+                       rti_update_time_ms = atoi(str);
+               } else {
+                       gf_cfg_set_key(cfg_file, "General", "RTIRefreshPeriod", "200");
+               }
+               UpdateRTInfo("At GPAC load time\n");
+       }
+
+       Run = 1;
+       ret = 1;
+
+       if (dump_mode) {
+               if (!nb_times) {
+                       times[0] = 0;
+                       nb_times++;
+               }
+               ret = dump_file(url_arg, dump_mode, fps, forced_width, forced_height, scale, times, nb_times);
+               Run = 0;
+       } else
+
+       /*connect if requested*/
+       if (url_arg) {
+               char *ext;
+               strcpy(the_url, url_arg);
+               ext = strrchr(the_url, '.');
+               if (ext && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls"))) {
+                       fprintf(stdout, "Opening Playlist %s\n", the_url);
+                       playlist = gf_f64_open(the_url, "rt");
+                       if (playlist) {
+                               strcpy(pl_path, the_url);
+                               fscanf(playlist, "%s", the_url);
+                               fprintf(stdout, "Opening URL %s\n", the_url);
+                               gf_term_connect_with_path(term, the_url, pl_path);
+                       } else {
+                               fprintf(stdout, "Hit 'h' for help\n\n");
+                       }
+               } else {
+                       fprintf(stdout, "Opening URL %s\n", the_url);
+                       if (pause_at_first) fprintf(stdout, "[Status: Paused]\n");
+                       gf_term_connect_from_time(term, the_url, 0, pause_at_first);
+               }
+       } else {
+               fprintf(stdout, "Hit 'h' for help\n\n");
+               str = gf_cfg_get_key(cfg_file, "General", "StartupFile");
+               if (str) {
+                       strcpy(the_url, "MP4Client "GPAC_FULL_VERSION);
+                       gf_term_connect(term, str);
+                       startup_file = 1;
+               }
+       }
+       /*force fullscreen*/
+       if (start_fs) 
+               gf_term_set_option(term, GF_OPT_FULLSCREEN, 1);
+
+       while (Run) {
+               /*we don't want getchar to block*/
+               if (1 || !gf_prompt_has_input()) {
+                       if (restart) {
+                               restart = 0;
+                               gf_term_play_from_time(term, 0, 0);
+                       }
+                       if (request_next_playlist_item) {
+                               c = '\n';
+                               request_next_playlist_item = 0;
+                               goto force_input;
+                       }
+                       if (!use_rtix || display_rti) UpdateRTInfo(NULL);
+                       if (not_threaded) {
+                               //printf("gf_term_process_step from run loop\n");
+                               gf_term_process_step(term);
+                               if (auto_exit && gf_term_get_option(term, GF_OPT_IS_OVER)) {
+                                       Run = 0;
+                               } 
+                       } else {
+                               gf_sleep(rti_update_time_ms);
+                       }
+                       /*sim time*/
+                       if (simulation_time && (gf_term_get_time_in_ms(term)>simulation_time)) {
+                               Run = 0;
+                       }
+                       continue;
+               }
+               c = gf_prompt_get_char();
+
+force_input:
+               switch (c) {
+               case 'q':
+                       Run = 0;
+                       break;
+               case 'X':
+                       exit(0);
+                       break;
+               case 'Q':
+                       break;
+               case 'o':
+                       startup_file = 0;
+                       gf_term_disconnect(term);
+                       fprintf(stdout, "Enter the absolute URL\n");
+                       scanf("%s", the_url);
+                       if (rti_file) init_rti_logs(rti_file, the_url, use_rtix);
+                       gf_term_connect(term, the_url);
+                       break;
+               case 'O':
+                       gf_term_disconnect(term);
+                       fprintf(stdout, "Enter the absolute URL to the playlist\n");
+                       scanf("%s", the_url);
+                       playlist = gf_f64_open(the_url, "rt");
+                       if (playlist) {
+                               fscanf(playlist, "%s", the_url);
+                               fprintf(stdout, "Opening URL %s\n", the_url);
+                               gf_term_connect(term, the_url);
+                       }
+                       break;
+               case '\n':
+               case 'N':
+                       if (playlist) {
+                               gf_term_disconnect(term);
+
+                               if (fscanf(playlist, "%s", the_url) == EOF) {
+                                       fprintf(stdout, "No more items - exiting\n");
+                                       Run = 0;
+                               } else {
+                                       fprintf(stdout, "Opening URL %s\n", the_url);
+                                       gf_term_connect_with_path(term, the_url, pl_path);
+                               }
+                       }
+                       break;
+               case 'P':
+                       if (playlist) {
+                               u32 count;
+                               gf_term_disconnect(term);
+                               scanf("%d", &count);
+                               while (count) {
+                                       fscanf(playlist, "%s", the_url);
+                                       count--;
+                               }
+                               fprintf(stdout, "Opening URL %s\n", the_url);
+                               gf_term_connect(term, the_url);
+                       }
+                       break;
+               case 'r':
+                       if (is_connected) {
+                               gf_term_disconnect(term);
+                               gf_term_connect(term, startup_file ? gf_cfg_get_key(cfg_file, "General", "StartupFile") : the_url);
+                       }
+                       break;
+               
+               case 'D':
+                       if (is_connected) gf_term_disconnect(term);
+                       break;
+
+               case 'p':
+                       if (is_connected) {
+                               Bool is_pause = gf_term_get_option(term, GF_OPT_PLAY_STATE);
+                               fprintf(stdout, "[Status: %s]\n", is_pause ? "Playing" : "Paused");
+                               gf_term_set_option(term, GF_OPT_PLAY_STATE, is_pause ? GF_STATE_PLAYING : GF_STATE_PAUSED);
+                       }
+                       break;
+               case 's':
+                       if (is_connected) {
+                               gf_term_set_option(term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE);
+                               fprintf(stdout, "Step time: ");
+                               PrintTime(gf_term_get_time_in_ms(term));
+                               fprintf(stdout, "\n");
+                       }
+                       break;
+
+               case 'z':
+                       if (!CanSeek || (Duration<=2000)) {
+                               fprintf(stdout, "scene not seekable\n");
+                       } else {
+                               Double res;
+                               s32 seekTo;
+                               fprintf(stdout, "Duration: ");
+                               PrintTime(Duration);
+                               res = gf_term_get_time_in_ms(term);
+                               res *= 100; res /= (s64)Duration;
+                               fprintf(stdout, " (current %.2f %%)\nEnter Seek percentage:\n", res);
+                               if (scanf("%d", &seekTo) == 1) { 
+                                       if (seekTo > 100) seekTo = 100;
+                                       res = (Double)(s64)Duration; res /= 100; res *= seekTo;
+                                       gf_term_play_from_time(term, (u64) (s64) res, 0);
+                               }
+                       }
+                       break;
+
+               case 't':
+               {
+                       if (is_connected) {
+                               fprintf(stdout, "Current Time: ");
+                               PrintTime(gf_term_get_time_in_ms(term));
+                               fprintf(stdout, " - Duration: ");
+                               PrintTime(Duration);
+                               fprintf(stdout, "\n");
+                       }
+               }
+                       break;
+               case 'w':
+                       if (is_connected) PrintWorldInfo(term);
+                       break;
+               case 'v':
+                       if (is_connected) PrintODList(term, NULL, 0, 0, "Root");
+                       break;
+               case 'i':
+                       if (is_connected) {
+                               u32 ID;
+                               fprintf(stdout, "Enter OD ID (0 for main OD): ");
+                               fflush(stdout);
+                               scanf("%d", &ID);
+                               ViewOD(term, ID, (u32)-1);
+                       }
+                       break;
+               case 'j':
+                       if (is_connected) {
+                               u32 num;
+                               fprintf(stdout, "Enter OD number (0 for main OD): ");
+                               fflush(stdout);
+                               scanf("%d", &num);
+                               ViewOD(term, (u32)-1, num);
+                       }
+                       break;
+               case 'b':
+                       if (is_connected) ViewODs(term, 1);
+                       break;
+
+               case 'm':
+                       if (is_connected) ViewODs(term, 0);
+                       break;
+
+               case 'l':
+                       list_modules(user.modules);
+                       break;
+
+               case 'n':
+                       if (is_connected) set_navigation();
+                       break;
+               case 'x':
+                       if (is_connected) gf_term_set_option(term, GF_OPT_NAVIGATION_TYPE, 0);
+                       break;
+
+               case 'd':
+                       if (is_connected) {
+                               GF_ObjectManager *odm = NULL;
+                               char radname[GF_MAX_PATH], *sExt;
+                               GF_Err e;
+                               u32 i, count, odid;
+                               Bool xml_dump, std_out;
+                               fprintf(stdout, "Enter Inline OD ID if any or 0");
+                               fflush(stdout);
+                               radname[0] = 0;
+                               scanf("%d", &odid);
+                               if (odid) {
+                                       GF_ObjectManager *root_odm = gf_term_get_root_object(term);
+                                       if (!root_odm) break;
+                                       count = gf_term_get_object_count(term, root_odm);
+                                       for (i=0; i<count; i++) {
+                                               GF_MediaInfo info;
+                                               odm = gf_term_get_object(term, root_odm, i);
+                                               if (gf_term_get_object_info(term, odm, &info) == GF_OK) {
+                                                       if (info.od->objectDescriptorID==odid) break;
+                                               }
+                                               odm = NULL;
+                                       }
+                               }
+                               fprintf(stdout, "Enter file radical name (+\'.x\' for XML dumping) - \"std\" for stdout: ");
+                               fflush(stdout);
+                               scanf("%s", radname);
+                               sExt = strrchr(radname, '.');
+                               xml_dump = 0;
+                               if (sExt) {
+                                       if (!stricmp(sExt, ".x")) xml_dump = 1;
+                                       sExt[0] = 0;
+                               }
+                               std_out = strnicmp(radname, "std", 3) ? 0 : 1;
+                               e = gf_term_dump_scene(term, std_out ? NULL : radname, NULL, xml_dump, 0, odm);
+                               fprintf(stdout, "Dump done (%s)\n", gf_error_to_string(e));
+                       }
+                       break;
+
+               case 'c':
+                       PrintGPACConfig();
+                       break;
+               case '3':
+               {
+                       Bool use_3d = !gf_term_get_option(term, GF_OPT_USE_OPENGL);
+                       if (gf_term_set_option(term, GF_OPT_USE_OPENGL, use_3d)==GF_OK) {
+                               fprintf(stdout, "Using %s for 2D drawing\n", use_3d ? "OpenGL" : "2D rasterizer");
+                       }
+               }
+                       break;
+               case 'k':
+               {
+                       Bool opt = gf_term_get_option(term, GF_OPT_STRESS_MODE);
+                       opt = !opt;
+                       fprintf(stdout, "Turning stress mode %s\n", opt ? "on" : "off");
+                       gf_term_set_option(term, GF_OPT_STRESS_MODE, opt);
+               }
+                       break;
+               case '4': gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_4_3); break;
+               case '5': gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_16_9); break;
+               case '6': gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_FILL_SCREEN); break;
+               case '7': gf_term_set_option(term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_KEEP); break;
+
+               case 'C':
+                       switch (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)) {
+                       case GF_MEDIA_CACHE_DISABLED: gf_term_set_option(term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_ENABLED); break;
+                       case GF_MEDIA_CACHE_ENABLED: gf_term_set_option(term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_DISABLED); break;
+                       case GF_MEDIA_CACHE_RUNNING: fprintf(stdout, "Streaming Cache is running - please stop it first\n"); continue;
+                       }
+                       switch (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)) {
+                       case GF_MEDIA_CACHE_ENABLED: fprintf(stdout, "Streaming Cache Enabled\n"); break;
+                       case GF_MEDIA_CACHE_DISABLED: fprintf(stdout, "Streaming Cache Disabled\n"); break;
+                       case GF_MEDIA_CACHE_RUNNING: fprintf(stdout, "Streaming Cache Running\n"); break;
+                       }
+                       break;
+               case 'S':
+               case 'A':
+                       if (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)==GF_MEDIA_CACHE_RUNNING) {
+                               gf_term_set_option(term, GF_OPT_MEDIA_CACHE, (c=='S') ? GF_MEDIA_CACHE_DISABLED : GF_MEDIA_CACHE_DISCARD);
+                               fprintf(stdout, "Streaming Cache stopped\n");
+                       } else {
+                               fprintf(stdout, "Streaming Cache not running\n");
+                       }
+                       break;
+               case 'R':
+                       display_rti = !display_rti;
+                       ResetCaption();
+                       break;
+               case 'F':
+                       if (display_rti) display_rti = 0;
+                       else display_rti = 2;
+                       ResetCaption();
+                       break;
+
+               case 'u':
+               {
+                       GF_Err e;
+                       char szCom[8192];
+                       fprintf(stdout, "Enter command to send:\n");
+                       fflush(stdin);
+                       szCom[0] = 0;
+                       scanf("%[^\t\n]", szCom);
+                       e = gf_term_scene_update(term, NULL, szCom);
+                       if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e));
+               }
+                       break;
+
+               case 'L':
+               {
+                       char szLog[1024];
+                       fprintf(stdout, "Enter new log level:\n");
+                       scanf("%s", szLog);
+                       gf_log_modify_tools_levels( szLog );
+               }
+                       break;
+               case 'g':
+               {
+                       GF_SystemRTInfo rti;
+                       gf_sys_get_rti(rti_update_time_ms, &rti, 0);
+                       fprintf(stdout, "GPAC allocated memory "LLD"\n", rti.gpac_memory);
+               }
+                       break;
+               case 'M':
+               {
+                       u32 size;
+                       fprintf(stdout, "Enter new video cache memory in kBytes (current %d):\n", gf_term_get_option(term, GF_OPT_VIDEO_CACHE_SIZE));
+                       scanf("%d", &size);
+                       gf_term_set_option(term, GF_OPT_VIDEO_CACHE_SIZE, size);
+               }
+                       break;
+
+               case 'E':
+                       gf_term_set_option(term, GF_OPT_RELOAD_CONFIG, 1); 
+                       break;
+
+               case 'B':
+                       switch_bench();
+                       break;
+
+               /*extract to PNG*/
+               case 'Z':
+               {
+                       GF_VideoSurface fb;
+                       GF_Err e;
+                       e = gf_term_get_screen_buffer(term, &fb);
+                       if (e) {
+                               fprintf(stdout, "Error dumping screen buffer %s\n", gf_error_to_string(e) );
+                       } else {
+                               u32 dst_size = fb.width*fb.height*3;
+                               char *dst=malloc(sizeof(char)*dst_size);
+
+                               e = gf_img_png_enc(fb.video_buffer, fb.width, fb.height, fb.pitch_y, fb.pixel_format, dst, &dst_size);
+                               if (e) {
+                                       fprintf(stdout, "Error encoding PNG %s\n", gf_error_to_string(e) );
+                               } else {
+                                       FILE *png = gf_f64_open("dump.png", "wb");
+                                       if (!png) {
+                                               fprintf(stdout, "Error writing file dump.png\n");
+                                       } else {
+                                               gf_fwrite(dst, dst_size, 1, png);
+                                               fclose(png);
+                                               fprintf(stdout, "Writing file dump.png\n");
+                                       }
+                               }
+                               if (dst) free(dst);
+                               gf_term_release_screen_buffer(term, &fb);
+                       }
+               }
+                       break;
+
+               case 'h':
+                       PrintHelp();
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       gf_term_disconnect(term);
+       if (rti_file) UpdateRTInfo("Disconnected\n");
+
+       fprintf(stdout, "Deleting terminal... ");
+       if (playlist) fclose(playlist);
+       gf_term_del(term);
+       fprintf(stdout, "OK\n");
+
+       fprintf(stdout, "GPAC cleanup ...\n");
+       gf_modules_del(user.modules);
+       gf_cfg_del(cfg_file);
+
+#ifdef GPAC_MEMORY_TRACKING
+       if (enable_mem_tracker) {
+               gf_memory_print();
+               fprintf(stdout, "print any key\n");
+               while (!gf_prompt_has_input()) {
+                       gf_sleep(100);
+               }
+       }
+#endif
+
+       gf_sys_close();
+       if (rti_logs) fclose(rti_logs);
+       if (logfile) fclose(logfile);
+       fprintf(stdout, "Bye\n");
+       return 0;
+}
+
+void PrintWorldInfo(GF_Terminal *term)
+{
+       u32 i;
+       const char *title;
+       GF_List *descs;
+       descs = gf_list_new();
+       title = gf_term_get_world_info(term, NULL, descs);
+       if (!title && !gf_list_count(descs)) {
+               fprintf(stdout, "No World Info available\n");
+       } else {
+               fprintf(stdout, "\t%s\n", title ? title : "No title available");
+               for (i=0; i<gf_list_count(descs); i++) {
+                       char *str = gf_list_get(descs, i);
+                       fprintf(stdout, "%s\n", str);
+               }
+       }
+       gf_list_del(descs);
+}
+
+void PrintODList(GF_Terminal *term, GF_ObjectManager *root_odm, u32 num, u32 indent, char *root_name)
+{
+       GF_MediaInfo odi;
+       u32 i, count;
+       char szIndent[50];
+       GF_ObjectManager *odm;
+
+       if (!root_odm) {
+               fprintf(stdout, "Currently loaded objects:\n");
+               root_odm = gf_term_get_root_object(term);
+       }
+       if (!root_odm) return;
+       if (gf_term_get_object_info(term, root_odm, &odi) != GF_OK) return;
+       if (!odi.od) {
+               fprintf(stdout, "Service not attached\n");
+               return;
+       }
+
+       for (i=0;i<indent;i++) szIndent[i]=' ';
+       szIndent[indent]=0;
+       
+       fprintf(stdout, "%s", szIndent);
+       fprintf(stdout, "#%d %s - ", num, root_name);
+       if (odi.media_url) {
+               fprintf(stdout, "%s\n", odi.media_url);
+       } else {
+               fprintf(stdout, "OD ID %d\n", odi.od->objectDescriptorID);
+       }
+
+       szIndent[indent]=' ';
+       szIndent[indent+1]=0;
+       indent++;
+
+       count = gf_term_get_object_count(term, root_odm);
+       for (i=0; i<count; i++) {
+               odm = gf_term_get_object(term, root_odm, i);
+               if (!odm) break;
+               num++;
+               if (gf_term_get_object_info(term, odm, &odi) == GF_OK) {
+                       switch (gf_term_object_subscene_type(term, odm)) {
+                       case 1:
+                               PrintODList(term, odm, num, indent, "Root");
+                               break;
+                       case 2:
+                               PrintODList(term, odm, num, indent, "Inline Scene");
+                               break;
+                       case 3:
+                               PrintODList(term, odm, num, indent, "EXTERNPROTO Library");
+                               break;
+                       default:
+                               fprintf(stdout, "%s", szIndent);
+                               fprintf(stdout, "#%d - ", num);
+                               if (odi.media_url) {
+                                       fprintf(stdout, "%s", odi.media_url);
+                               } else {
+                                       fprintf(stdout, "ID %d", odi.od->objectDescriptorID);
+                               }
+                               fprintf(stdout, " - %s\n", (odi.od_type==GF_STREAM_VISUAL) ? "Video" : (odi.od_type==GF_STREAM_AUDIO) ? "Audio" : "Systems");
+                               break;
+                       }
+               }
+       }
+}
+
+void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number)
+{
+       GF_MediaInfo odi;
+       u32 i, j, count, d_enum,id;
+       GF_Err e;
+       char code[5];
+       NetStatCommand com;
+       GF_ObjectManager *odm, *root_odm = gf_term_get_root_object(term);
+       if (!root_odm) return;
+
+       odm = NULL;
+       if ((!OD_ID && (number == (u32)(-1))) ||
+               ((OD_ID == (u32)(-1)) && !number)) {
+               odm = root_odm;
+               if ((gf_term_get_object_info(term, odm, &odi) != GF_OK)) odm=NULL;
+       } else {
+               count = gf_term_get_object_count(term, root_odm);
+               for (i=0; i<count; i++) {
+                       odm = gf_term_get_object(term, root_odm, i);
+                       if (!odm) break;
+                       if (gf_term_get_object_info(term, odm, &odi) == GF_OK) {
+                               if ((number == (u32)(-1)) && (odi.od->objectDescriptorID == OD_ID)) break;
+                               else if (i == (u32)(number-1)) break;
+                       }
+                       odm = NULL;
+               }
+       }
+       if (!odm) {
+               if (number == (u32)-1) fprintf(stdout, "cannot find OD with ID %d\n", OD_ID);
+               else fprintf(stdout, "cannot find OD with number %d\n", number);
+               return;
+       }
+       if (!odi.od) {
+               if (number == (u32)-1) fprintf(stdout, "Object %d not attached yet\n", OD_ID);
+               else fprintf(stdout, "Object #%d not attached yet\n", number);          
+               return;
+       }
+
+       if (!odi.od) {
+               fprintf(stdout, "Service not attached\n");
+               return;
+       }
+
+       if (odi.od->tag==GF_ODF_IOD_TAG) {
+               fprintf(stdout, "InitialObjectDescriptor %d\n", odi.od->objectDescriptorID);
+               fprintf(stdout, "Profiles and Levels: Scene %x - Graphics %x - Visual %x - Audio %x - OD %x\n", 
+                       odi.scene_pl, odi.graphics_pl, odi.visual_pl, odi.audio_pl, odi.OD_pl);
+               fprintf(stdout, "Inline Profile Flag %d\n", odi.inline_pl);
+       } else {
+               fprintf(stdout, "ObjectDescriptor %d\n", odi.od->objectDescriptorID);
+       }
+
+       fprintf(stdout, "Object Duration: ");
+       if (odi.duration) {
+         PrintTime((u32) (odi.duration*1000));
+       } else {
+         fprintf(stdout, "unknown");
+       }
+       fprintf(stdout, "\n");
+
+       if (odi.owns_service) {
+               fprintf(stdout, "Service Handler: %s\n", odi.service_handler);
+               fprintf(stdout, "Service URL: %s\n", odi.service_url);
+       }               
+       if (odi.codec_name) {
+               Float avg_dec_time;
+               switch (odi.od_type) {
+               case GF_STREAM_VISUAL:
+                       fprintf(stdout, "Video Object: Width %d - Height %d\r\n", odi.width, odi.height);
+                       fprintf(stdout, "Media Codec: %s\n", odi.codec_name);
+                       if (odi.par) fprintf(stdout, "Pixel Aspect Ratio: %d:%d\n", (odi.par>>16)&0xFF, (odi.par)&0xFF);
+                       break;
+               case GF_STREAM_AUDIO:
+                       fprintf(stdout, "Audio Object: Sample Rate %d - %d channels\r\n", odi.sample_rate, odi.num_channels);
+                       fprintf(stdout, "Media Codec: %s\n", odi.codec_name);
+                       break;
+               case GF_STREAM_SCENE:
+               case GF_STREAM_PRIVATE_SCENE:
+                       if (odi.width && odi.height) {
+                               fprintf(stdout, "Scene Description - Width %d - Height %d\n", odi.width, odi.height);
+                       } else {
+                               fprintf(stdout, "Scene Description - no size specified\n");
+                       }
+                       fprintf(stdout, "Scene Codec: %s\n", odi.codec_name);
+                       break;
+               case GF_STREAM_TEXT:
+                       if (odi.width && odi.height) {
+                               fprintf(stdout, "Text Object: Width %d - Height %d\n", odi.width, odi.height);
+                       } else {
+                               fprintf(stdout, "Text Object: No size specified\n");
+                       }
+                       fprintf(stdout, "Text Codec %s\n", odi.codec_name);
+                       break;
+               }
+       
+               avg_dec_time = 0;
+               if (odi.nb_dec_frames) { 
+                       avg_dec_time = (Float) odi.total_dec_time; 
+                       avg_dec_time /= odi.nb_dec_frames; 
+               }
+               fprintf(stdout, "\tBitrate over last second: %d kbps\n\tMax bitrate over one second: %d kbps\n\tAverage Decoding Time %.2f ms (%d max)\n\tTotal decoded frames %d\n", 
+                       (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time, odi.nb_dec_frames);
+       }
+       if (odi.protection) fprintf(stdout, "Encrypted Media%s\n", (odi.protection==2) ? " NOT UNLOCKED" : "");
+
+       count = gf_list_count(odi.od->ESDescriptors);
+       fprintf(stdout, "%d streams in OD\n", count);
+       for (i=0; i<count; i++) {
+               GF_ESD *esd = (GF_ESD *) gf_list_get(odi.od->ESDescriptors, i);
+
+               fprintf(stdout, "\nStream ID %d - Clock ID %d\n", esd->ESID, esd->OCRESID);
+               if (esd->dependsOnESID) fprintf(stdout, "\tDepends on Stream ID %d for decoding\n", esd->dependsOnESID);
+
+               switch (esd->decoderConfig->streamType) {
+               case GF_STREAM_OD: fprintf(stdout, "\tOD Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_OCR: fprintf(stdout, "\tOCR Stream\n"); break;
+               case GF_STREAM_SCENE: fprintf(stdout, "\tScene Description Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_VISUAL:
+                       fprintf(stdout, "\tVisual Stream - media type: ");
+                       switch (esd->decoderConfig->objectTypeIndication) {
+                       case GPAC_OTI_VIDEO_MPEG4_PART2: fprintf(stdout, "MPEG-4\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SIMPLE: fprintf(stdout, "MPEG-2 Simple Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_MAIN: fprintf(stdout, "MPEG-2 Main Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SNR: fprintf(stdout, "MPEG-2 SNR Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SPATIAL: fprintf(stdout, "MPEG-2 Spatial Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_HIGH: fprintf(stdout, "MPEG-2 High Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_422: fprintf(stdout, "MPEG-2 422 Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG1: fprintf(stdout, "MPEG-1\n"); break;
+                       case GPAC_OTI_IMAGE_JPEG: fprintf(stdout, "JPEG\n"); break;
+                       case GPAC_OTI_IMAGE_PNG: fprintf(stdout, "PNG\n"); break;
+                       case GPAC_OTI_IMAGE_JPEG_2000: fprintf(stdout, "JPEG2000\n"); break;
+                               
+                       case GPAC_OTI_MEDIA_GENERIC:
+                               memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
+                               code[4] = 0;
+                               fprintf(stdout, "GPAC Intern (%s)\n", code);
+                               break;
+                       default:
+                               fprintf(stdout, "Private Type (0x%x)\n", esd->decoderConfig->objectTypeIndication);
+                               break;
+                       }
+                       break;
+
+               case GF_STREAM_AUDIO:
+                       fprintf(stdout, "\tAudio Stream - media type: ");
+                       switch (esd->decoderConfig->objectTypeIndication) {
+                       case GPAC_OTI_AUDIO_AAC_MPEG4: fprintf(stdout, "MPEG-4\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_MP: fprintf(stdout, "MPEG-2 AAC Main Profile\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_LCP: fprintf(stdout, "MPEG-2 AAC LowComplexity Profile\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP: fprintf(stdout, "MPEG-2 AAC Scalable Sampling Rate Profile\n"); break;
+                       case GPAC_OTI_AUDIO_MPEG2_PART3: fprintf(stdout, "MPEG-2 Audio\n"); break;
+                       case GPAC_OTI_AUDIO_MPEG1: fprintf(stdout, "MPEG-1 Audio\n"); break;
+                       case GPAC_OTI_AUDIO_EVRC_VOICE: fprintf(stdout, "EVRC Audio\n"); break;
+                       case GPAC_OTI_AUDIO_SMV_VOICE: fprintf(stdout, "SMV Audio\n"); break;
+                       case GPAC_OTI_AUDIO_13K_VOICE: fprintf(stdout, "QCELP Audio\n"); break;
+                       case GPAC_OTI_MEDIA_GENERIC:
+                               memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
+                               code[4] = 0;
+                               fprintf(stdout, "GPAC Intern (%s)\n", code);
+                               break;
+                       default:
+                               fprintf(stdout, "Private Type (0x%x)\n", esd->decoderConfig->objectTypeIndication);
+                               break;
+                       }
+                       break;
+               case GF_STREAM_MPEG7: fprintf(stdout, "\tMPEG-7 Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_IPMP: fprintf(stdout, "\tIPMP Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_OCI: fprintf(stdout, "\tOCI Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_MPEGJ: fprintf(stdout, "\tMPEGJ Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_INTERACT: fprintf(stdout, "\tUser Interaction Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               case GF_STREAM_TEXT: fprintf(stdout, "\tStreaming Text Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break;
+               default: fprintf(stdout, "Unknown Stream\r\n"); break;
+               }
+
+               fprintf(stdout, "\tBuffer Size %d\n\tAverage Bitrate %d bps\n\tMaximum Bitrate %d bps\n", esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate, esd->decoderConfig->maxBitrate);
+               if (esd->slConfig->predefined==SLPredef_SkipSL) {
+                       fprintf(stdout, "\tNot using MPEG-4 Synchronization Layer\n");
+               } else {
+                       fprintf(stdout, "\tStream Clock Resolution %d\n", esd->slConfig->timestampResolution);
+               }
+               if (esd->URLString) fprintf(stdout, "\tStream Location: %s\n", esd->URLString);
+
+               /*check language*/
+               if (esd->langDesc) {
+                       u32 i=0;
+                       char lan[4], *szLang;
+                       lan[0] = esd->langDesc->langCode>>16;
+                       lan[1] = (esd->langDesc->langCode>>8)&0xFF;
+                       lan[2] = (esd->langDesc->langCode)&0xFF;
+                       lan[3] = 0;
+
+                       if ((lan[0]=='u') && (lan[1]=='n') && (lan[2]=='d')) szLang = "Undetermined";
+                       else {
+                               szLang = lan;
+                               while (GF_ISO639_Lang[i]) {
+                                       if (GF_ISO639_Lang[i+2][0] && strstr(GF_ISO639_Lang[i+1], lan)) {
+                                               szLang = (char*) GF_ISO639_Lang[i];
+                                               break;
+                                       }
+                                       i+=3;
+                               }
+                       }
+                       fprintf(stdout, "\tStream Language: %s\n", szLang);
+               }
+       }
+       fprintf(stdout, "\n");
+       /*check OCI (not everything interests us) - FIXME: support for unicode*/
+       count = gf_list_count(odi.od->OCIDescriptors);
+       if (count) {
+               fprintf(stdout, "%d Object Content Information descriptors in OD\n", count);
+               for (i=0; i<count; i++) {
+                       GF_Descriptor *desc = (GF_Descriptor *) gf_list_get(odi.od->OCIDescriptors, i);
+                       switch (desc->tag) {
+                       case GF_ODF_SEGMENT_TAG:
+                       {
+                               GF_Segment *sd = (GF_Segment *) desc;
+                               fprintf(stdout, "Segment Descriptor: Name: %s - start time %g sec - duration %g sec\n", sd->SegmentName, sd->startTime, sd->Duration);
+                       }
+                               break;
+                       case GF_ODF_CC_NAME_TAG:
+                       {
+                               GF_CC_Name *ccn = (GF_CC_Name *)desc;
+                               fprintf(stdout, "Content Creators:\n");
+                               for (j=0; j<gf_list_count(ccn->ContentCreators); j++) {
+                                       GF_ContentCreatorInfo *ci = (GF_ContentCreatorInfo *) gf_list_get(ccn->ContentCreators, j);
+                                       if (!ci->isUTF8) continue;
+                                       fprintf(stdout, "\t%s\n", ci->contentCreatorName);
+                               }
+                       }
+                               break;
+
+                       case GF_ODF_SHORT_TEXT_TAG:
+                               {
+                                       GF_ShortTextual *std = (GF_ShortTextual *)desc;
+                                       fprintf(stdout, "Description:\n\tEvent: %s\n\t%s\n", std->eventName, std->eventText);
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               fprintf(stdout, "\n");
+       }
+
+       switch (odi.status) {
+       case 0: fprintf(stdout, "Stopped - "); break;
+       case 1: fprintf(stdout, "Playing - "); break;
+       case 2: fprintf(stdout, "Paused - "); break;
+       case 3: fprintf(stdout, "Not setup yet\n"); return;
+       default: fprintf(stdout, "Setup Failed\n"); return;
+       }
+       if (odi.buffer>=0) fprintf(stdout, "Buffer: %d ms - ", odi.buffer);
+       else fprintf(stdout, "Not buffering - ");
+       fprintf(stdout, "Clock drift: %d ms\n", odi.clock_drift);
+       if (odi.db_unit_count) fprintf(stdout, "%d AU in DB\n", odi.db_unit_count);
+       if (odi.cb_max_count) fprintf(stdout, "Composition Buffer: %d CU (%d max)\n", odi.cb_unit_count, odi.cb_max_count);
+       fprintf(stdout, "\n");
+
+       if (odi.owns_service) {
+               const char *url;
+               u32 done, total, bps;
+               d_enum = 0;
+               while (gf_term_get_download_info(term, odm, &d_enum, &url, NULL, &done, &total, &bps)) {
+                       if (d_enum==1) fprintf(stdout, "Current Downloads in service:\n");
+                       if (done && total) {
+                               fprintf(stdout, "%s: %d / %d bytes (%.2f %%) - %.2f kBps\n", url, done, total, (100.0f*done)/total, ((Float)bps)/1024.0f);
+                       } else {
+                               fprintf(stdout, "%s: %.2f kbps\n", url, ((Float)8*bps)/1024.0f);
+                       }
+               }
+               if (!d_enum) fprintf(stdout, "No Downloads in service\n");
+               fprintf(stdout, "\n");
+       }
+       d_enum = 0;
+       while (gf_term_get_channel_net_info(term, odm, &d_enum, &id, &com, &e)) {
+               if (e) continue;
+               if (!com.bw_down && !com.bw_up) continue;
+
+               fprintf(stdout, "Stream ID %d statistics:\n", id);
+               if (com.multiplex_port) {
+                       fprintf(stdout, "\tMultiplex Port %d - multiplex ID %d\n", com.multiplex_port, com.port);
+               } else {
+                       fprintf(stdout, "\tPort %d\n", com.port);
+               }
+               fprintf(stdout, "\tPacket Loss Percentage: %.4f\n", com.pck_loss_percentage);
+               fprintf(stdout, "\tDown Bandwidth: %d bps\n", com.bw_down);
+               if (com.bw_up) fprintf(stdout, "\tUp Bandwidth: %d bps\n", com.bw_up);
+               if (com.ctrl_port) {
+                       if (com.multiplex_port) {
+                               fprintf(stdout, "\tControl Multiplex Port: %d - Control Multiplex ID %d\n", com.multiplex_port, com.ctrl_port);
+                       } else {
+                               fprintf(stdout, "\tControl Port: %d\n", com.ctrl_port);
+                       }
+                       fprintf(stdout, "\tDown Bandwidth: %d bps\n", com.ctrl_bw_down);
+                       fprintf(stdout, "\tUp Bandwidth: %d bps\n", com.ctrl_bw_up);
+               }
+               fprintf(stdout, "\n");
+       }
+}
+
+void PrintODTiming(GF_Terminal *term, GF_ObjectManager *odm)
+{
+       GF_MediaInfo odi;
+       if (!odm) return;
+
+       if (gf_term_get_object_info(term, odm, &odi) != GF_OK) return;
+       if (!odi.od) {
+               fprintf(stdout, "Service not attached\n");
+               return;
+       }
+
+       fprintf(stdout, "OD %d: ", odi.od->objectDescriptorID);
+       switch (odi.status) {
+       case 1: fprintf(stdout, "Playing - "); break;
+       case 2: fprintf(stdout, "Paused - "); break;
+       default: fprintf(stdout, "Stopped - "); break;
+       }
+       if (odi.buffer>=0) fprintf(stdout, "Buffer: %d ms - ", odi.buffer);
+       else fprintf(stdout, "Not buffering - ");
+       fprintf(stdout, "Clock drift: %d ms", odi.clock_drift);
+       fprintf(stdout, " - time: ");
+       PrintTime((u32) (odi.current_time*1000));
+       fprintf(stdout, "\n");
+}
+
+void PrintODBuffer(GF_Terminal *term, GF_ObjectManager *odm)
+{
+       Float avg_dec_time;
+       GF_MediaInfo odi;
+       if (!odm) return;
+
+       if (gf_term_get_object_info(term, odm, &odi) != GF_OK) return;
+       if (!odi.od) {
+               fprintf(stdout, "Service not attached\n");
+               return;
+       }
+
+       fprintf(stdout, "OD %d: ", odi.od->objectDescriptorID);
+       switch (odi.status) {
+       case 1: fprintf(stdout, "Playing"); break;
+       case 2: fprintf(stdout, "Paused"); break;
+       default: fprintf(stdout, "Stopped"); break;
+       }
+       if (odi.buffer>=0) fprintf(stdout, " - Buffer: %d ms", odi.buffer);
+       if (odi.db_unit_count) fprintf(stdout, " - DB: %d AU", odi.db_unit_count);
+       if (odi.cb_max_count) fprintf(stdout, " - CB: %d/%d CUs", odi.cb_unit_count, odi.cb_max_count);
+       
+       fprintf(stdout, "\n * %d decoded frames - %d dropped frames\n", odi.nb_dec_frames, odi.nb_droped);
+       avg_dec_time = 0;
+       if (odi.nb_dec_frames) { avg_dec_time = (Float) odi.total_dec_time; avg_dec_time /= odi.nb_dec_frames; }
+       fprintf(stdout, " * Avg Bitrate %d kbps (%d max) - Avg Decoding Time %.2f ms (%d max)\n",
+                                                               (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time);
+}
+
+void ViewODs(GF_Terminal *term, Bool show_timing)
+{
+       u32 i, count;
+       GF_ObjectManager *odm, *root_odm = gf_term_get_root_object(term);
+       if (!root_odm) return;
+
+       if (show_timing) {
+               PrintODTiming(term, root_odm);
+       } else {
+               PrintODBuffer(term, root_odm);
+       }
+       count = gf_term_get_object_count(term, root_odm);
+       for (i=0; i<count; i++) {
+               odm = gf_term_get_object(term, root_odm, i);
+               if (show_timing) {
+                       PrintODTiming(term, odm);
+               } else {
+                       PrintODBuffer(term, odm);
+               }
+       }
+       fprintf(stdout, "\n");
+}
+
+
+void PrintGPACConfig()
+{
+       u32 i, j, cfg_count, key_count;
+       char szName[200];
+       char *secName = NULL;
+
+       fprintf(stdout, "Enter section name (\"*\" for complete dump):\n");
+       scanf("%s", szName);
+       if (strcmp(szName, "*")) secName = szName;
+
+       fprintf(stdout, "\n\n*** GPAC Configuration ***\n\n");
+
+       cfg_count = gf_cfg_get_section_count(cfg_file);
+       for (i=0; i<cfg_count; i++) {
+               const char *sec = gf_cfg_get_section_name(cfg_file, i);
+               if (secName) {
+                       if (stricmp(sec, secName)) continue;
+               } else {
+                       if (!stricmp(sec, "General")) continue;
+                       if (!stricmp(sec, "MimeTypes")) continue;
+                       if (!stricmp(sec, "RecentFiles")) continue;
+               }
+               fprintf(stdout, "[%s]\n", sec);
+               key_count = gf_cfg_get_key_count(cfg_file, sec);
+               for (j=0; j<key_count; j++) {
+                       const char *key = gf_cfg_get_key_name(cfg_file, sec, j);
+                       const char *val = gf_cfg_get_key(cfg_file, sec, key);
+                       fprintf(stdout, "%s=%s\n", key, val);
+               }
+               fprintf(stdout, "\n");
+       }
+}
diff --git a/applications/osmo4_ios/osmo4ios-Info.plist b/applications/osmo4_ios/osmo4ios-Info.plist
new file mode 100644 (file)
index 0000000..2c7f467
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>${EXECUTABLE_NAME}</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.gpac.${PRODUCT_NAME:identifier}</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>Osmo4</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>9.9.9</string><!-- VERSION_REV_REPLACE -->
+       <key>CFBundleSignature</key>
+       <string>gpac</string>
+       <key>CFBundleVersion</key>
+       <string>9999</string><!-- BUILD_REV_REPLACE -->
+</dict>
+</plist>
diff --git a/applications/osmo4_wx/Darwin.Info.plist b/applications/osmo4_wx/Darwin.Info.plist
new file mode 100644 (file)
index 0000000..710c02d
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>Osmo4</string>
+       <key>CFBundleGetInfoString</key>
+       <string>Osmo4 0.4.2</string>
+       <key>CFBundleIconFile</key>
+       <string>Osmo</string>
+       <key>CFBundleIdentifier</key>
+       <string>org.gpac.Osmo4</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>0.4.2</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>0.4.2</string>
+       <key>CFBundleSignature</key>
+       <string>Omo4</string>
+       <key>CFBundleVersion</key>
+       <string>0.4.2</string>
+       <key>NSHumanReadableCopyright</key>
+       <string>Copyright (c) 2003-2005 gpac</string>
+       <key>NSMainNibFile</key>
+       <string>NSMainNibFile</string>
+       <key>NSPrincipalClass</key>
+       <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/applications/osmo4_wx/Darwin.InfoPlist.strings b/applications/osmo4_wx/Darwin.InfoPlist.strings
new file mode 100644 (file)
index 0000000..2efc670
Binary files /dev/null and b/applications/osmo4_wx/Darwin.InfoPlist.strings differ
diff --git a/applications/osmo4_wx/Darwin.Osmo.icns b/applications/osmo4_wx/Darwin.Osmo.icns
new file mode 100644 (file)
index 0000000..a598061
Binary files /dev/null and b/applications/osmo4_wx/Darwin.Osmo.icns differ
diff --git a/applications/osmo4_wx/Makefile b/applications/osmo4_wx/Makefile
new file mode 100644 (file)
index 0000000..e15bdac
--- /dev/null
@@ -0,0 +1,94 @@
+include ../../config.mak
+
+vpath %.cpp $(SRC_PATH)/applications/osmo4_wx
+
+CFLAGS= $(CPPFLAGS) -I"$(SRC_PATH)/include"
+
+ifeq ($(DEBUGBUILD), yes)
+CFLAGS+=-g
+LDFLAGS+=-g
+endif
+
+ifeq ($(GPROFBUILD), yes)
+CFLAGS+=-pg
+LDFLAGS+=-pg
+endif
+
+ifeq ($(GPACREADONLY), yes)
+CFLAGS+=-DGPAC_READ_ONLY
+endif
+
+#common obj
+OBJS= wxOsmo4.o wxGPACControl.o fileprops.o Playlist.o menubtn.o
+
+ifeq ($(CONFIG_WIN32),yes)
+EXE=.exe
+PROG=Osmo4$(EXE)
+else
+EXT=
+PROG=Osmo4
+endif
+
+#3 - spidermonkey support
+ifeq ($(CONFIG_JS),no)
+else
+SCENEGRAPH_CFLAGS+=$(JS_FLAGS)
+ifeq ($(CONFIG_JS),local)
+NEED_LOCAL_LIB="yes"
+endif
+LINKFLAGS+=$(JS_LIBS)
+endif
+
+
+SRCS := $(OBJS:.o=.cpp) 
+
+all: $(PROG)
+
+Osmo4$(EXE): $(OBJS)
+       $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc -lgpac $(WX_LFLAGS) $(LINKFLAGS)
+
+%.o: %.cpp
+       $(CXX) $(CFLAGS) $(WX_CFLAGS) -c -o $@ $< 
+
+clean: 
+       rm -f $(OBJS) ../../bin/gcc/$(PROG)
+
+install: 
+ifeq ($(CONFIG_DARWIN),yes)
+       mkdir -p $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/MacOS
+       mkdir -p $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/Resources/English.lproj
+       cp ./Darwin.Info.plist \
+          $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/Info.plist
+       cp ./Darwin.InfoPlist.strings \
+          $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/Resources/English.lproj/InfoPlist.strings
+       cp ./Darwin.Osmo.icns \
+          $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/Resources/Osmo.icns
+       install -m 755 $(INSTFLAGS) ../../bin/gcc/Osmo4 \
+             $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/MacOS
+       echo -n 'APPLOsm4' > $(DESTDIR)$(mac_apps)/Osmo4.app/Contents/PkgInfo
+else
+       rm -f wxOsmo4.o
+       mkdir -p $(DESTDIR)$(prefix)/bin
+       install -m 755 $(INSTFLAGS) ../../bin/gcc/Osmo4 "$(DESTDIR)$(prefix)/bin"
+endif
+
+uninstall:
+       rm -rf $(DESTDIR)$(prefix)/bin/Osmo4
+
+dep:
+
+depend:
+       rm -f .depend   
+       $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+distclean: clean
+       rm -f Makefile.bak .depend
+
+
+
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
+
diff --git a/applications/osmo4_wx/Playlist.cpp b/applications/osmo4_wx/Playlist.cpp
new file mode 100644 (file)
index 0000000..7ed47a6
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is gf_free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#include "wxOsmo4.h"
+#include "Playlist.h"
+
+
+#include "playlist.xpm"
+
+PLEntry::PLEntry(wxString url)
+{
+       m_url = gf_strdup(url.mb_str(wxConvUTF8));
+       Bool is_remote = 0;;
+       wxCharBuffer the_url = (const char *) url.mb_str(wxConvUTF8);
+       const char *_url = strstr(the_url, "://");
+       if (_url) {_url += 3; is_remote = 1; }
+       else _url = (const char *) the_url;
+
+       char *str = (char*)strrchr(_url, '\\');
+       if (!str) str = (char*)strrchr(_url, '/');
+       if (str && strlen(str+1)) {
+               m_disp_name = gf_strdup(str+1);
+               str = strrchr(m_disp_name, '.');
+               if (str) str[0] = 0;
+       } else {
+               m_disp_name = gf_strdup(_url);
+               if (!is_remote) {
+                       str = strrchr(m_disp_name, '.');
+                       if (str) str[0] = 0;
+               }
+       }
+       m_duration = 0;
+       m_bIsDead = 0;
+       m_bIsPlaying = 0;
+       m_bIsSelected = 0;
+}
+
+PLEntry::~PLEntry()
+{
+       if (m_url) gf_free(m_url);
+       if (m_disp_name) gf_free(m_disp_name);
+
+}
+
+wxPlaylist::wxPlaylist(wxWindow *parent)
+             : wxFrame(parent, -1, wxString(_T("Osmo4 Playlist")), wxDefaultPosition, wxDefaultSize, 
+                        wxCLOSE_BOX | wxSYSTEM_MENU | wxCAPTION | wxRESIZE_BORDER)
+{
+
+       m_pApp = (wxOsmo4Frame *)parent;
+
+       m_pOpen = new wxBitmap(pl_open);
+       m_pSave = new wxBitmap(pl_save);
+       m_pAdd = new wxBitmap(pl_add);
+       m_pRem = new wxBitmap(pl_rem);
+       m_pUp = new wxBitmap(pl_up);
+       m_pDown = new wxBitmap(pl_down);
+       m_pSort = new wxBitmap(pl_sort);
+
+       m_pToolBar = CreateToolBar(wxTB_HORIZONTAL);
+       m_pAddBut = new wxMenuButton(m_pToolBar, ID_PL_ADD_FILE, *m_pAdd);
+       wxMenu *menu = new wxMenu();
+       menu->Append(ID_PL_ADD_URL, wxT("&Url"));
+       menu->Append(ID_PL_ADD_DIR, wxT("&Directory"));
+       menu->Append(ID_PL_ADD_DIR_REC, wxT("&Directory and subfolders"));
+       m_pAddBut->AssignMenu(menu);
+       m_pAddBut->SetToolTip(wxString(wxT("Add Files")));
+
+       m_pRemBut = new wxMenuButton(m_pToolBar, ID_PL_REM_FILE, *m_pRem);
+       menu = new wxMenu();
+       menu->Append(ID_PL_REM_ALL, wxT("&Clear"));
+       menu->Append(ID_PL_REM_DEAD, wxT("&Remove dead entries"));
+       m_pRemBut->AssignMenu(menu);
+       m_pRemBut->SetToolTip(wxString(wxT("Remove Selected Files")));
+
+       m_pSortBut = new wxMenuButton(m_pToolBar, ID_PL_SORT_FILE, *m_pSort);
+       menu = new wxMenu();
+       menu->Append(ID_PL_SORT_TITLE, wxT("&Sort by Title"));
+       menu->Append(ID_PL_SORT_FILE, wxT("&Sort by file name"));
+       menu->Append(ID_PL_SORT_DUR, wxT("&Sort by Duration"));
+       menu->AppendSeparator();
+       menu->Append(ID_PL_REVERSE, wxT("&Reverse"));
+       menu->Append(ID_PL_RANDOMIZE, wxT("&Randomize"));
+       m_pSortBut->AssignMenu(menu);
+       m_pSortBut->SetToolTip(wxString(wxT("Sort Playlist by filename")));
+
+       m_pToolBar->AddTool(ID_PL_OPEN, wxT(""), *m_pOpen, wxT("Open Playlist"));
+       m_pToolBar->AddTool(ID_PL_SAVE, wxT(""), *m_pSave, wxT("Save Playlist"));
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddControl(m_pAddBut);
+       m_pToolBar->AddControl(m_pRemBut);
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddTool(ID_PL_UP, wxT(""), *m_pUp, wxT("Moves Selected Files Up"));
+       m_pToolBar->AddTool(ID_PL_DOWN, wxT(""), *m_pDown, wxT("Moves Selected Files Down"));
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddControl(m_pSortBut);
+       m_pToolBar->Realize();
+
+       m_FileList = new wxListCtrl(this, ID_FILE_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);
+
+       m_FileList->InsertColumn(0, wxT(""), wxLIST_FORMAT_LEFT, 1);
+       m_FileList->InsertColumn(1, wxT("Title"), wxLIST_FORMAT_LEFT, 1);
+       m_FileList->InsertColumn(2, wxT("Duration"), wxLIST_FORMAT_LEFT, 1);
+
+       m_entries = gf_list_new();
+       m_cur_entry = -1;
+       m_all_dead_entries = -1;
+
+       SetSize(220, 380);
+       Centre();
+}
+
+wxPlaylist::~wxPlaylist()
+{
+       Clear();
+       gf_list_del(m_entries);
+       delete m_pAddBut;
+       delete m_pRemBut;
+       delete m_pSortBut;
+       delete m_pOpen;
+       delete m_pSave;
+       delete m_pAdd;
+       delete m_pRem;
+       delete m_pUp;
+       delete m_pDown;
+       delete m_pSort;
+}
+
+
+BEGIN_EVENT_TABLE(wxPlaylist, wxWindow)
+       EVT_CLOSE(wxPlaylist::OnClose)
+       EVT_SIZE(wxPlaylist::OnSize)
+       EVT_TOOL(ID_PL_ADD_FILE, wxPlaylist::OnAddFile) 
+       EVT_TOOL(ID_PL_ADD_URL, wxPlaylist::OnAddURL) 
+       EVT_TOOL(ID_PL_ADD_DIR, wxPlaylist::OnAddDir) 
+       EVT_TOOL(ID_PL_ADD_DIR_REC, wxPlaylist::OnAddDirRec) 
+       EVT_TOOL(ID_PL_REM_FILE, wxPlaylist::OnRemFile) 
+       EVT_TOOL(ID_PL_REM_ALL, wxPlaylist::OnRemAll) 
+       EVT_TOOL(ID_PL_REM_DEAD, wxPlaylist::OnRemDead) 
+       EVT_TOOL(ID_PL_UP, wxPlaylist::OnSelUp) 
+       EVT_TOOL(ID_PL_DOWN, wxPlaylist::OnSelDown) 
+       EVT_TOOL(ID_PL_SAVE, wxPlaylist::OnSave) 
+       EVT_TOOL(ID_PL_OPEN, wxPlaylist::OnOpen) 
+       EVT_MENU(ID_PL_PLAY, wxPlaylist::OnPlay) 
+       EVT_MENU(ID_PL_RANDOMIZE, wxPlaylist::OnRandomize) 
+       EVT_MENU(ID_PL_REVERSE, wxPlaylist::OnReverseList) 
+       EVT_MENU(ID_PL_SEL_REV, wxPlaylist::OnReverseSelection) 
+       EVT_MENU(ID_PL_SORT_TITLE, wxPlaylist::OnSortTitle) 
+       EVT_MENU(ID_PL_SORT_FILE, wxPlaylist::OnSortFile) 
+       EVT_MENU(ID_PL_SORT_DUR, wxPlaylist::OnSortDuration) 
+       EVT_LIST_ITEM_ACTIVATED(ID_FILE_LIST, wxPlaylist::OnItemActivate) 
+       EVT_LIST_ITEM_RIGHT_CLICK(ID_FILE_LIST, wxPlaylist::OnRightClick)
+END_EVENT_TABLE()
+
+void wxPlaylist::OnClose(wxCloseEvent &event)
+{
+       if (event.CanVeto()) {
+               event.Veto();
+               Hide();
+       }
+}
+
+void wxPlaylist::OnSize(wxSizeEvent &event)
+{
+       wxSize s = event.GetSize();
+       m_FileList->SetSize(0, 0, s.GetWidth()-2, s.GetHeight());
+       m_FileList->SetColumnWidth(0, 30);
+       m_FileList->SetColumnWidth(2, 60);
+       m_FileList->SetColumnWidth(1, s.GetWidth()-96);
+}
+
+void wxPlaylist::Clear()
+{
+       m_FileList->DeleteAllItems();
+       while (gf_list_count(m_entries)) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, 0);
+               gf_list_rem(m_entries, 0);
+               delete ple;
+       }
+       m_cur_entry = -1;
+}
+
+void wxPlaylist::ClearButPlaying()
+{
+       PLEntry *p = NULL;
+       if (m_cur_entry >= 0) {
+               p = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+               gf_list_rem(m_entries, m_cur_entry);
+       }
+       Clear();
+       if (p) {
+               gf_list_add(m_entries, p);
+               m_cur_entry = 0;
+       }
+       RefreshList();
+}
+
+void wxPlaylist::UpdateEntry(u32 idx)
+{
+       char szText[20];
+
+       PLEntry *ple = (PLEntry *) gf_list_get(m_entries, idx);
+       if (idx+1<10) sprintf(szText, "00%d", idx+1);
+       else if (idx+1<100) sprintf(szText, "0%d", idx+1);
+       else sprintf(szText, "%d", idx+1);
+       m_FileList->SetItem(idx, 0, wxString(szText, wxConvUTF8));
+
+       wxString str;
+       if (ple->m_bIsDead) str = wxT("!! ") + wxString(ple->m_disp_name, wxConvUTF8) + wxT(" (DEAD)!!)");
+       else if (ple->m_bIsPlaying) str = wxT(">> ") + wxString(ple->m_disp_name, wxConvUTF8) + wxT(" >>");
+       else str = wxString(ple->m_disp_name, wxConvUTF8);
+       m_FileList->SetItem(idx, 1, str);
+       
+       if (ple->m_duration) {
+               u32 h = (u32) (ple->m_duration / 3600);
+               u32 m = (u32) (ple->m_duration / 60) - h*60;
+               u32 s = (u32) (ple->m_duration) - h*3600 - m*60;
+               m_FileList->SetItem(idx, 2, wxString::Format(wxT("%02d:%02d:%02d"), h, m, s) );
+       } else {
+               m_FileList->SetItem(idx, 2, wxT("Unknown"));
+       }
+}
+
+void wxPlaylist::RefreshList()
+{
+       u32 i, top_idx;
+       char szPath[GF_MAX_PATH];
+       Bool first_sel;
+
+       top_idx = m_FileList->GetTopItem();
+       m_FileList->DeleteAllItems();
+
+       first_sel = 0;
+       for (i=0; i<gf_list_count(m_entries); i++) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
+               m_FileList->InsertItem(i, wxT(""));
+               /*cast for 64-bit compilation*/
+               m_FileList->SetItemData(i, (unsigned long) ple);
+               UpdateEntry(i);
+
+               if (ple->m_bIsPlaying) m_cur_entry = i;
+
+               if (ple->m_bIsSelected) {
+                       m_FileList->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED | wxLIST_MASK_STATE);
+                       ple->m_bIsSelected = 0;
+                       /*ensure first item of selection is visible*/
+                       if (!first_sel) {
+                               first_sel = 1;
+                               top_idx = i;
+                       }
+               }
+       }
+       
+       if (m_cur_entry >= (s32) gf_list_count(m_entries)-1) m_cur_entry = gf_list_count(m_entries)-1;
+       else {
+               s32 last_idx = top_idx + m_FileList->GetCountPerPage();
+               m_FileList->EnsureVisible(top_idx);
+               if (gf_list_count(m_entries)<1+ (u32) last_idx) last_idx = gf_list_count(m_entries)-1;
+               m_FileList->EnsureVisible(last_idx);
+       }
+
+       strcpy((char *) szPath, m_pApp->szAppPath);
+#ifdef WIN32
+       strcat(szPath, "gpac_pl.m3u");
+#else
+       strcat(szPath, ".gpac_pl.m3u");
+#endif
+       Save(szPath, 1);
+}
+
+void wxPlaylist::OnAddFile(wxCommandEvent &WXUNUSED(event)) 
+{
+       wxFileDialog dlg(this, wxT("Select file(s)"), wxT(""), wxT(""), m_pApp->GetFileFilter(), wxOPEN | wxCHANGE_DIR | /*wxHIDE_READONLY |*/ wxMULTIPLE);
+
+       if (dlg.ShowModal() == wxID_OK) {
+               wxArrayString stra;
+               dlg.GetPaths(stra);
+               for (u32 i=0; i<stra.GetCount(); i++) {
+                       PLEntry *ple = new PLEntry(stra[i]);
+                       gf_list_add(m_entries, ple);
+               }
+               m_all_dead_entries = -1;
+               RefreshList();
+       }
+}
+
+
+static Bool pl_enum_dir_item(void *cbck, char *item_name, char *item_path)
+{
+       wxPlaylist *_this = (wxPlaylist *)cbck;
+
+       if (gf_term_is_supported_url(_this->m_pApp->m_term, item_name, 0, 1)) {
+               PLEntry *ple = new PLEntry(wxString(item_path, wxConvUTF8) );
+               gf_list_add(_this->m_entries, ple);
+       }
+       return 0;
+}
+
+static Bool pl_enum_dir_dirs(void *cbck, char *item_name, char *item_path)
+{
+       gf_enum_directory(item_path, 0, pl_enum_dir_item, cbck, NULL);
+       gf_enum_directory(item_path, 1, pl_enum_dir_dirs, cbck, NULL);
+       return 0;
+}
+
+
+void wxPlaylist::AddDir(Bool do_recurse) 
+{
+       wxDirDialog dlg(this);
+       dlg.SetPath(wxString(szCacheDir, wxConvUTF8) );
+       if (dlg.ShowModal() != wxID_OK) return;
+
+       strcpy(szCacheDir, dlg.GetPath().mb_str(wxConvUTF8));
+       gf_enum_directory(szCacheDir, 0, pl_enum_dir_item, this, NULL);
+       if (do_recurse) gf_enum_directory(szCacheDir, 1, pl_enum_dir_dirs, this, NULL);
+       m_all_dead_entries = -1;
+       RefreshList();
+}
+void wxPlaylist::OnAddDir(wxCommandEvent &WXUNUSED(event)) 
+{
+       AddDir(0);
+}
+void wxPlaylist::OnAddDirRec(wxCommandEvent &WXUNUSED(event)) 
+{
+       AddDir(1);
+}
+
+void wxPlaylist::OnAddURL(wxCommandEvent &WXUNUSED(event)) 
+{
+       OpenURLDlg dlg(this, m_pApp->m_user.config);
+       if (dlg.ShowModal() != wxID_OK) return;
+       PLEntry *ple = new PLEntry(dlg.m_urlVal);
+       gf_list_add(m_entries, ple);
+       m_all_dead_entries = -1;
+       RefreshList();
+}
+
+void wxPlaylist::OnRemFile(wxCommandEvent &WXUNUSED(event)) 
+{
+       if (!m_FileList->GetSelectedItemCount()) return;
+
+       long item = -1;
+       for (;;) {
+        item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) break;
+               PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item);
+               gf_list_del_item(m_entries, ple);
+               delete ple;
+    }
+       RefreshList();
+}
+
+void wxPlaylist::OnRemAll(wxCommandEvent &WXUNUSED(event)) 
+{
+       Clear();
+       RefreshList();
+       m_cur_entry = -1;
+       m_all_dead_entries = 1;
+}
+
+void wxPlaylist::OnRemDead(wxCommandEvent &WXUNUSED(event)) 
+{
+       for (u32 i=0; i<gf_list_count(m_entries); i++) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
+               if (!ple->m_bIsDead) continue;
+               gf_list_rem(m_entries, i);
+               i--;
+               delete ple;
+       }
+       m_all_dead_entries = gf_list_count(m_entries) ? 0 : 1;
+       RefreshList();
+}
+
+
+void wxPlaylist::OnSelUp(wxCommandEvent &WXUNUSED(event)) 
+{
+       s32 i;
+       if (!m_FileList->GetSelectedItemCount()) return;
+       long item = -1;
+       item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (item <= 0) return;
+       
+       item = -1;
+       for (;;) {
+        item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) break;
+               PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item);
+               i = gf_list_del_item(m_entries, ple);
+               assert(i>=1);
+               gf_list_insert(m_entries, ple, i-1);
+               ple->m_bIsSelected = 1;
+    }
+       RefreshList();
+}
+
+void wxPlaylist::OnSelDown(wxCommandEvent &WXUNUSED(event)) 
+{
+       s32 i;
+
+       if (!m_FileList->GetSelectedItemCount()) return;
+       long item = -1;
+       for (;;) {
+               item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) break;
+       }
+       if ((u32) item + 1 == gf_list_count(m_entries)) return;
+       
+       item = -1;
+       for (;;) {
+        item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) break;
+               PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item);
+               i = gf_list_del_item(m_entries, ple);
+               assert(i>=1);
+               gf_list_insert(m_entries, ple, i+1);
+               ple->m_bIsSelected = 1;
+    }
+       RefreshList();
+}
+
+
+
+void wxPlaylist::OnSave(wxCommandEvent & WXUNUSED(event)) 
+{
+       Bool save_m3u;
+       char szPath[GF_MAX_PATH];
+       if (!gf_list_count(m_entries)) return;
+
+       wxFileDialog dlg(this, wxT("Select file(s)"), wxT(""), wxT(""), wxT("M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|"), wxSAVE | wxCHANGE_DIR | wxOVERWRITE_PROMPT);
+       if (dlg.ShowModal() != wxID_OK) return;
+
+       strcpy(szPath, dlg.GetPath().mb_str(wxConvUTF8));
+       strlwr(szPath);
+       save_m3u = (dlg.GetFilterIndex()==0) ? 1 : 0;
+       if (save_m3u) {
+               if (!strstr(szPath, ".m3u")) {
+                       strcpy(szPath, dlg.GetPath().mb_str(wxConvUTF8));
+                       strcat(szPath, ".m3u");
+               } else {
+                       strcpy(szPath, dlg.GetPath().mb_str(wxConvUTF8));
+               }
+       } else {
+               if (!strstr(szPath, ".pls")) {
+                       strcpy(szPath, dlg.GetPath().mb_str(wxConvUTF8));
+                       strcat(szPath, ".pls");
+               } else {
+                       strcpy(szPath, dlg.GetPath().mb_str(wxConvUTF8));
+               }
+       }
+       Save(szPath, save_m3u);
+}
+
+void wxPlaylist::Save(char *szPath, Bool save_m3u)
+{
+       FILE *out = fopen(szPath, "wt");
+       if (!save_m3u) 
+               fprintf(out, "[playlist]\nNumberOfEntries=%d\n", gf_list_count(m_entries));
+
+       for (u32 i=0; i<gf_list_count(m_entries); i++) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
+               if (save_m3u) {
+                       fprintf(out, "%s\n", ple->m_url);
+               } else {
+                       fprintf(out, "File%d=%s\n", i+1, ple->m_url);
+                       fprintf(out, "Title%d=%s\n", i+1, ple->m_disp_name);
+                       if (ple->m_duration) fprintf(out, "Length%d=%d\n", i+1, ple->m_duration);
+                       else fprintf(out, "Length%d=-1\n", i+1);
+               }
+       }
+       if (!save_m3u) fprintf(out, "Version=2\n");
+
+       fprintf(out, "\n");
+       fclose(out);
+}
+
+void wxPlaylist::OnOpen(wxCommandEvent & WXUNUSED(event)) 
+{
+       wxFileDialog dlg(this, wxT("Select file(s)"), wxT(""), wxT(""), wxT("M3U & PLS Playlists|*.m3u;*.pls|M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|"), wxOPEN | wxCHANGE_DIR/* | wxHIDE_READONLY*/);
+       if (dlg.ShowModal() != wxID_OK) return;
+
+       Clear();
+       OpenPlaylist(dlg.GetPath());
+       m_cur_entry = 0;
+       Play();
+}
+
+void wxPlaylist::OpenPlaylist(wxString filename)
+{
+       FILE *pl;
+       PLEntry *ple;
+       Bool load_m3u, go;
+       char szLine[GF_MAX_PATH];
+       pl = fopen(filename.mb_str(wxConvUTF8) , "rt");
+       if (!pl) return;
+
+       ple = NULL;
+       load_m3u = 1;
+       while (!feof(pl)) {
+               fgets(szLine, GF_MAX_PATH, pl);
+               go = 1;
+               while (go) {
+                       switch (szLine[strlen(szLine)-1]) {
+                       case '\n':
+                       case '\r':
+                       case ' ':
+                               szLine[strlen(szLine)-1] = 0;
+                               break;
+                       default:
+                               go = 0;
+                               break;
+                       }
+               }
+               if (!strlen(szLine)) continue;
+               if (!stricmp(szLine, "[playlist]")) {
+                       load_m3u = 0;
+               } else if (load_m3u) {
+                       ple = new PLEntry(wxString(szLine, wxConvUTF8) );
+                       gf_list_add(m_entries, ple);
+               } else if (!strnicmp(szLine, "file", 4)) {
+                       char *st = strchr(szLine, '=');
+                       if (!st) ple = NULL;
+                       else {
+                               ple = new PLEntry(wxString(st + 1, wxConvUTF8) );
+                               gf_list_add(m_entries, ple);
+                       }
+               } else if (ple && !strnicmp(szLine, "Length", 6)) {
+                       char *st = strchr(szLine, '=');
+                       s32 d = atoi(st + 1);
+                       if (d>0) ple->m_duration = d;
+               } else if (ple && !strnicmp(szLine, "Title", 5)) {
+                       char *st = strchr(szLine, '=');
+                       gf_free(ple->m_disp_name);
+                       ple->m_disp_name = gf_strdup(st + 6);
+               }
+       }
+       fclose(pl);
+       m_all_dead_entries = -1;
+       m_cur_entry = -1;
+       RefreshList();
+}
+
+void wxPlaylist::OnRightClick(wxListEvent & event) 
+{
+       if (!m_FileList->GetItemCount()) return;
+
+       wxMenu *popup = new wxMenu();   
+
+       if (m_FileList->GetSelectedItemCount()==1) {
+               popup->Append(ID_PL_PLAY, wxT("Play"));
+               popup->AppendSeparator();
+       }
+       popup->Append(ID_PL_SEL_REV, wxT("Inverse Selection"));
+       if (m_FileList->GetSelectedItemCount()) popup->Append(ID_PL_REM_FILE, wxT("Remove File(s)"));
+       if (m_FileList->GetItemCount()>1) {
+               popup->AppendSeparator();
+               popup->Append(ID_PL_SORT_TITLE, wxT("Sort By Title"));
+               popup->Append(ID_PL_SORT_FILE, wxT("Sort By File Name"));
+               popup->Append(ID_PL_SORT_DUR, wxT("Sort By Duration"));
+               popup->AppendSeparator();
+               popup->Append(ID_PL_REVERSE, wxT("Reverse List"));
+               popup->Append(ID_PL_RANDOMIZE, wxT("Randomize"));
+       }
+       
+       PopupMenu(popup, event.GetPoint());
+       delete popup;
+}
+
+void wxPlaylist::OnReverseSelection(wxCommandEvent &WXUNUSED(event) ) 
+{
+       u32 i;
+       long item = -1;
+       for (;;) {
+               item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) break;
+               PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item);
+               ple->m_bIsSelected = 1;
+       }
+       for (i=0; i<gf_list_count(m_entries); i++) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
+               ple->m_bIsSelected = !ple->m_bIsSelected;
+       }
+       RefreshList();
+}
+
+void wxPlaylist::OnReverseList(wxCommandEvent &WXUNUSED(event) )
+{
+       u32 count = gf_list_count(m_entries);
+       u32 hcount = count / 2;
+       count--;
+       for (u32 i=0; i<hcount; i++) {
+               PLEntry *ple1 = (PLEntry *) gf_list_get(m_entries, i);
+               PLEntry *ple2 = (PLEntry *) gf_list_get(m_entries, count-i);
+               gf_list_rem(m_entries, i);
+               gf_list_insert(m_entries, ple2, i);
+               gf_list_rem(m_entries, count-i);
+               gf_list_insert(m_entries, ple1, count-i);
+       }
+       RefreshList();
+}
+
+void wxPlaylist::OnRandomize(wxCommandEvent &WXUNUSED(event) )
+{
+       GF_List *new_entries = gf_list_new();
+
+       gf_rand_init(0);
+
+       while (gf_list_count(m_entries)>1) {
+               u32 pos = gf_rand() % (gf_list_count(m_entries)-1);
+               PLEntry *ple = (PLEntry *)gf_list_get(m_entries, pos);
+               gf_list_rem(m_entries, pos);
+               gf_list_add(new_entries, ple);
+       }
+       PLEntry *ple = (PLEntry *)gf_list_get(m_entries, 0);
+       gf_list_rem(m_entries, 0);
+       gf_list_add(new_entries, ple);
+
+       gf_list_del(m_entries);
+       m_entries = new_entries;
+       m_cur_entry = -1;
+       RefreshList();
+}
+
+void wxPlaylist::Sort(u32 type)
+{
+       u32 i, j, smallest;
+
+       for (i=0; i<gf_list_count(m_entries)-1; i++) {
+               smallest = i;
+               for (j=i+1; j<gf_list_count(m_entries); j++) {
+                       PLEntry *ple2 = (PLEntry *) gf_list_get(m_entries, smallest);
+                       PLEntry *ple1 = (PLEntry *) gf_list_get(m_entries, j);
+                       s32 test = 0;
+                       switch (type) {
+                       case 0:
+                test = stricmp(ple1->m_url, ple2->m_url);
+                               break;
+                       case 1:
+                test = stricmp(ple1->m_disp_name, ple2->m_disp_name);
+                               break;
+                       case 2:
+                test = ple1->m_duration - ple2->m_duration;
+                               break;
+                       }
+                       if (test<0) smallest = j;
+               }
+               PLEntry *ple = (PLEntry *)gf_list_get(m_entries, smallest);
+               gf_list_rem(m_entries, smallest);
+               gf_list_insert(m_entries, ple, i);
+       }
+       m_cur_entry = -1;
+       RefreshList();
+}
+
+void wxPlaylist::OnSortFile(wxCommandEvent &WXUNUSED(event) ) { Sort(0); }
+void wxPlaylist::OnSortTitle(wxCommandEvent &WXUNUSED(event) ) { Sort(1); }
+void wxPlaylist::OnSortDuration(wxCommandEvent &WXUNUSED(event) ) { Sort(2); }
+
+void wxPlaylist::RefreshCurrent()
+{
+       PLEntry *ple;
+       if (m_cur_entry<0) return;
+       ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+       if (ple && ple->m_bIsPlaying) {
+               ple->m_bIsPlaying = 0;
+               UpdateEntry(m_cur_entry);
+       }
+}
+
+Bool wxPlaylist::HasValidEntries()
+{
+       u32 nb_dead = 0;
+       if (m_all_dead_entries==-1) {
+               for (u32 i=0; i<gf_list_count(m_entries); i++) {
+                       PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
+                       ple->m_bIsPlaying = 0;
+                       if (ple->m_bIsDead) nb_dead ++;
+               }
+               m_all_dead_entries = (nb_dead==gf_list_count(m_entries)) ? 1 : 0;
+       }
+       return !m_all_dead_entries;
+}
+
+void wxPlaylist::Play()
+{
+       PLEntry *ple;
+
+       if (!HasValidEntries()) return;
+
+       RefreshCurrent();
+
+       if (m_cur_entry >= (s32)gf_list_count(m_entries)) {
+               if (!m_pApp->m_loop) return;
+               m_cur_entry = 0;
+       }
+
+       ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+       if (!ple || ple->m_bIsDead) {
+               m_cur_entry++;
+               Play();
+       } else {
+               char szPLE[20];
+               ple->m_bIsPlaying = 1;
+               UpdateEntry(m_cur_entry);
+               sprintf(szPLE, "%d", m_cur_entry);
+               gf_cfg_set_key(m_pApp->m_user.config, "General", "PLEntry", szPLE);
+               m_pApp->DoConnect();
+       }
+}
+
+void wxPlaylist::OnItemActivate(wxListEvent &WXUNUSED(event) ) 
+{
+       long item = m_FileList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (item==-1) return;
+       RefreshCurrent();
+       m_cur_entry = item;
+       Play();
+}
+
+
+void wxPlaylist::OnPlay(wxCommandEvent &WXUNUSED(event))
+{
+       long item = m_FileList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (item==-1) return;
+
+       RefreshCurrent();
+       m_cur_entry = item;
+       Play();
+}
+
+void wxPlaylist::Truncate()
+{
+       if (m_cur_entry<0) return;
+       while ((u32) m_cur_entry+1 < gf_list_count(m_entries)) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry+1);
+               gf_list_rem(m_entries, m_cur_entry+1);
+               delete ple;
+       }
+       RefreshList();
+}
+
+void wxPlaylist::QueueURL(wxString filename)
+{
+       char *ext = (char*)strrchr(filename.mb_str(wxConvUTF8), '.');
+       if (ext && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls")) ) {
+               OpenPlaylist(filename);
+       } else {
+               PLEntry *ple = new PLEntry(filename);
+               gf_list_add(m_entries, ple);
+       }
+}
+
+void wxPlaylist::PlayNext()
+{
+       RefreshCurrent();
+       if (1+m_cur_entry < (s32)gf_list_count(m_entries)) {
+               m_cur_entry++;
+               Play();
+       }
+}
+
+void wxPlaylist::PlayPrev()
+{
+       RefreshCurrent();
+       if (m_cur_entry>0) {
+               m_cur_entry--;
+               Play();
+       }
+}
+
+void wxPlaylist::SetDead()
+{
+       PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+       if (ple) {
+               ple->m_bIsDead = 1;
+               UpdateEntry(m_cur_entry);
+               if (ple->m_bIsPlaying) PlayNext();
+               m_all_dead_entries = -1;
+       }
+}
+void wxPlaylist::SetDuration(u32 duration)
+{
+       PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+       if (ple) {
+               ple->m_duration = duration;
+               UpdateEntry(m_cur_entry);
+       }
+}
+
+wxString wxPlaylist::GetDisplayName()
+{
+       if (m_cur_entry>=0) {
+               PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+               if (ple) return wxString(wxString(ple->m_disp_name, wxConvUTF8) );
+       }
+       return wxT("");
+}
+
+wxString wxPlaylist::GetURL()
+{
+       PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
+       if (ple) return wxString(ple->m_url, wxConvUTF8);
+       return wxT("");
+}
+
diff --git a/applications/osmo4_wx/Playlist.h b/applications/osmo4_wx/Playlist.h
new file mode 100644 (file)
index 0000000..0ebb230
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#ifndef _PLAYLIST_H
+#define _PLAYLIST_H
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+  #include "wx/wx.h"
+#endif
+
+#include "menubtn.h"
+
+enum
+{
+       ID_FILE_LIST = 1000,
+};
+
+class wxOsmo4Frame;
+
+class PLEntry 
+{
+public:
+       PLEntry(wxString url);
+       ~PLEntry();
+
+       char *m_url;
+       char *m_disp_name;
+       u32 m_duration;
+
+       Bool m_bIsSelected;
+       Bool m_bIsDead;
+       Bool m_bIsPlaying;
+};
+
+
+class wxPlaylist : public wxFrame
+{
+public:
+    wxPlaylist(wxWindow *parent);
+       virtual ~wxPlaylist();
+
+       void Clear();
+       void ClearButPlaying();
+       void RefreshList();
+
+       void Truncate();
+       void QueueURL(wxString filename);
+       void Play();
+       void PlayNext();
+       void PlayPrev();
+       void SetDead();
+       void SetDuration(u32 duration);
+       Bool HasValidEntries();
+       void OpenPlaylist(wxString fileName);
+
+       /*for current entry played*/
+       wxString GetDisplayName();
+       wxString GetURL();
+
+       s32 m_cur_entry;
+       GF_List *m_entries;
+
+       wxOsmo4Frame *m_pApp;
+
+private:
+       DECLARE_EVENT_TABLE()
+
+       void OnClose(wxCloseEvent &event);
+       void OnSize(wxSizeEvent &event);
+       void OnAddFile(wxCommandEvent &event);
+       void OnAddURL(wxCommandEvent &event);
+       void OnAddDir(wxCommandEvent &event);
+       void OnAddDirRec(wxCommandEvent &event);
+       void OnRemFile(wxCommandEvent &event);
+       void OnRemAll(wxCommandEvent &event);
+       void OnRemDead(wxCommandEvent &event);
+       void OnSelUp(wxCommandEvent &event);
+       void OnSelDown(wxCommandEvent &event);
+       void OnSave(wxCommandEvent &event);
+       void OnOpen(wxCommandEvent &event);
+       void OnRightClick(wxListEvent & event);
+       void OnReverseSelection(wxCommandEvent &event); 
+       void OnReverseList(wxCommandEvent &event);
+       void OnRandomize(wxCommandEvent &event);
+       void OnSortFile(wxCommandEvent &event);
+       void OnSortTitle(wxCommandEvent &event);
+       void OnSortDuration(wxCommandEvent &event);
+       void OnItemActivate(wxListEvent &event);
+       void OnPlay(wxCommandEvent &event);
+
+
+       void Sort(u32 type);
+       void UpdateEntry(u32 idx);
+       void RefreshCurrent();
+       void Save(char *szPath, Bool save_m3u);
+
+       wxBitmap *m_pOpen, *m_pSave, *m_pAdd, *m_pRem, *m_pUp, *m_pDown, *m_pSort;
+       wxMenuButton *m_pAddBut, *m_pRemBut, *m_pSortBut;
+       wxToolBar *m_pToolBar;
+       wxListCtrl *m_FileList;
+       char szCacheDir[GF_MAX_PATH];
+       s32 m_all_dead_entries;
+
+       void AddDir(Bool do_recurse);
+};
+
+
+
+#endif
+
diff --git a/applications/osmo4_wx/fileprops.cpp b/applications/osmo4_wx/fileprops.cpp
new file mode 100644 (file)
index 0000000..4697d55
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#include "fileprops.h"
+#include "wxOsmo4.h"
+#include "Playlist.h"
+#include <wx/filename.h>
+#include <gpac/modules/codec.h>
+#include <gpac/modules/service.h>
+#include <gpac/constants.h>
+/*ISO 639 languages*/
+#include <gpac/iso639.h>
+
+
+wxFileProps::wxFileProps(wxWindow *parent)
+             : wxDialog(parent, -1, wxString(_T("File Properties")))
+{
+
+       m_pApp = (wxOsmo4Frame *)parent;
+       SetSize(540, 260);
+       assert(m_pApp->m_pPlayList);
+
+       m_pTreeView = new wxTreeCtrl(this, ID_TREE_VIEW, wxPoint(4, 2), wxSize(200, 180), wxTR_DEFAULT_STYLE | wxSUNKEN_BORDER);
+       
+       new wxStaticText(this, 0, _T("Information"), wxPoint(210, 2), wxSize(60, 20));
+    m_pViewSel = new wxComboBox(this, ID_VIEW_SEL, _T(""), wxPoint(280, 2), wxSize(120, 24), 0, NULL, wxCB_READONLY);
+       m_pViewSel->Append(wxT("General"));
+       m_pViewSel->Append(wxT("Streams"));
+       m_pViewSel->Append(wxT("Playback"));
+       m_pViewSel->Append(wxT("Network"));
+       m_pViewSel->SetSelection(0);
+
+    m_pViewInfo = new wxTextCtrl(this, -1, wxT(""), wxPoint(210, 30), wxSize(320, 200), wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL | wxSUNKEN_BORDER);
+
+#ifdef WIN32
+       m_pViewInfo->SetBackgroundColour(wxColour(wxT("LIGHT GREY")));
+#endif
+
+       m_pViewWI = new wxButton(this, ID_VIEW_WI, wxT("View World Info"), wxPoint(4, 174), wxSize(200, 40));
+       m_pViewSG = new wxButton(this, ID_VIEW_SG, wxT("View Scene Graph"), wxPoint(4, 220), wxSize(200, 40));
+
+
+       wxString str = m_pApp->m_pPlayList->GetDisplayName();
+       str += wxT(" Properties");
+       SetTitle(str);
+
+       m_pTimer = new wxTimer();
+       m_pTimer->SetOwner(this, ID_OD_TIMER);
+       m_pTimer->Start(500, 0);
+       RewriteODTree();
+
+}
+
+wxFileProps::~wxFileProps()
+{
+       m_pTimer->Stop();
+       delete m_pTimer;
+}
+
+
+BEGIN_EVENT_TABLE(wxFileProps, wxDialog)
+       EVT_TREE_ITEM_ACTIVATED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
+       EVT_TREE_SEL_CHANGED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
+       EVT_TREE_ITEM_EXPANDED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
+       EVT_TREE_ITEM_COLLAPSED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
+       EVT_TIMER(ID_OD_TIMER, wxFileProps::OnTimer)
+       EVT_BUTTON(ID_VIEW_SG, wxFileProps::OnViewSG)
+       EVT_BUTTON(ID_VIEW_WI, wxFileProps::OnViewWorld)
+       EVT_COMBOBOX(ID_VIEW_SEL, wxFileProps::OnSelectInfo)
+END_EVENT_TABLE()
+
+void wxFileProps::RewriteODTree()
+{
+       GF_ObjectManager *root_odm = gf_term_get_root_object(m_pApp->m_term);
+       if (!root_odm) return;
+
+       m_pTreeView->DeleteAllItems();
+       ODTreeData *root = new ODTreeData(root_odm);
+       m_pTreeView->AddRoot(wxT("Root OD"), -1, -1, root);
+       wxTreeItemId rootId = m_pTreeView->GetRootItem();
+
+       WriteInlineTree(root);
+       SetInfo(root_odm);
+}
+
+void wxFileProps::WriteInlineTree(ODTreeData *root)
+{
+       /*browse all ODs*/
+       u32 count = gf_term_get_object_count(m_pApp->m_term, root->m_pODMan);
+
+       for (u32 i=0; i<count; i++) {
+               GF_ObjectManager *odm = gf_term_get_object(m_pApp->m_term, root->m_pODMan, i);
+               if (!odm) return;
+               ODTreeData *odd = new ODTreeData(odm);
+               m_pTreeView->AppendItem(root->GetId(), wxT("Object Descriptor"), -1, -1, odd);
+
+               /*if inline propagate*/
+               switch (gf_term_object_subscene_type(m_pApp->m_term, odm)) {
+               case 1:
+                       m_pTreeView->SetItemText(odd->GetId(), wxT("Root Scene"));
+                       WriteInlineTree(odd);
+                       break;
+               case 2:
+                       m_pTreeView->SetItemText(odd->GetId(), wxT("Inline Scene"));
+                       WriteInlineTree(odd);
+                       break;
+               case 3:
+                       m_pTreeView->SetItemText(odd->GetId(), wxT("Extern Proto Lib"));
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+void wxFileProps::OnSetSelection(wxTreeEvent& event)
+{
+       ODTreeData *odd = (ODTreeData *) m_pTreeView->GetItemData(event.GetItem());
+       SetInfo(odd->m_pODMan);
+}
+
+void wxFileProps::SetInfo(GF_ObjectManager *odm)
+{
+       m_current_odm = odm;
+
+       switch (m_pViewSel->GetSelection()) {
+       case 3: SetNetworkInfo(); break;
+       case 2: SetDecoderInfo(); break;
+       case 1: SetStreamsInfo(); break;
+       default: SetGeneralInfo(); break;
+       }
+}
+
+void wxFileProps::OnTimer(wxTimerEvent& WXUNUSED(event))
+{
+       switch (m_pViewSel->GetSelection()) {
+       case 2: SetDecoderInfo(); break;
+       }
+}
+void wxFileProps::OnSelectInfo(wxCommandEvent & WXUNUSED(event) )
+{
+       SetInfo(m_current_odm);
+}
+
+void wxFileProps::SetGeneralInfo()
+{
+       wxString info;
+       GF_MediaInfo odi;
+       u32 h, m, s;
+       u32 i, j;
+
+       info = wxT("");
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+
+       if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
+
+       if (odi.has_profiles) info += wxT("Initial ");
+       info += wxString::Format(wxT("Object Descriptor ID %d\n"), odi.od->objectDescriptorID);
+       if (odi.duration) {
+               h = (u32) (odi.duration / 3600);
+               m = (u32) (odi.duration / 60) - h*60;
+               s = (u32) (odi.duration) - h*3600 - m*60;
+               info += wxString::Format(wxT("Duration %02d:%02d:%02d\n"), h, m, s);
+       } else {
+               info += wxT("Unknown duration\n");
+       }
+
+       if (odi.owns_service) {
+               info += wxT("Service Handler: ") + wxString(odi.service_handler, wxConvUTF8) + wxT("\n");
+               info += wxT("Service URL: ") + wxString(odi.service_url, wxConvUTF8) + wxT("\n");
+       }
+       
+       if (odi.od->URLString) {
+               info += wxT("Remote OD - URL: ") + wxString(odi.od->URLString, wxConvUTF8) + wxT("\n");
+       } 
+
+       if (odi.codec_name) {
+               switch (odi.od_type) {
+               case GF_STREAM_VISUAL:
+                       info += wxString::Format(wxT("Video Object: Width %d - Height %d\n"), odi.width, odi.height);
+                       info += wxT("Media Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
+                       break;
+               case GF_STREAM_AUDIO:
+                       info += wxString::Format(wxT("Audio Object: Sample Rate %d - %d channels\n"), odi.sample_rate, odi.num_channels);
+                       info += wxT("Media Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
+                       break;
+               case GF_STREAM_PRIVATE_SCENE:
+               case GF_STREAM_SCENE:
+                       if (odi.width && odi.height) {
+                               info += wxString::Format(wxT("Scene Description: Width %d - Height %d\n"), odi.width, odi.height);
+                       } else {
+                               info += wxT("Scene Description: No size specified\n");
+                       }
+                       info += wxT("Scene Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
+                       break;
+               case GF_STREAM_TEXT:
+                       if (odi.width && odi.height) {
+                               info += wxString::Format(wxT("Text Object: Width %d - Height %d\n"), odi.width, odi.height);
+                       } else {
+                               info += wxString::Format(wxT("Text Object: No size specified\n"));
+                       }
+                       info += wxT("Text Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
+                       break;
+               }
+       }
+       if (odi.protection==2) info += wxT("Encrypted Media NOT UNLOCKED"); 
+       else if (odi.protection==1) info += wxT("Encrypted Media"); 
+
+       if (!gf_list_count(odi.od->OCIDescriptors)) {
+               m_pViewInfo->Clear();
+               m_pViewInfo->AppendText(info);
+               return;
+       }
+
+       info += wxT("\nObject Content Information:\n");
+
+       /*check OCI (not everything interests us) - FIXME: support for unicode*/
+       for (i=0; i<gf_list_count(odi.od->OCIDescriptors); i++) {
+               GF_Descriptor *desc = (GF_Descriptor *) gf_list_get(odi.od->OCIDescriptors, i);
+               switch (desc->tag) {
+               case GF_ODF_SEGMENT_TAG:
+               {
+                       GF_Segment *sd = (GF_Segment *) desc;
+                       info += wxT("\nSegment Descriptor:\nName: ") + wxString((char *) sd->SegmentName, wxConvUTF8);
+                       info += wxString::Format(wxT(" - start time %g sec - duration %g sec\n"), sd->startTime, sd->Duration);
+               }
+                       break;
+               case GF_ODF_CC_NAME_TAG:
+               {
+                       GF_CC_Name *ccn = (GF_CC_Name *)desc;
+                       info += wxT("\nContent Creators:\n");
+                       for (j=0; j<gf_list_count(ccn->ContentCreators); j++) {
+                               GF_ContentCreatorInfo *ci = (GF_ContentCreatorInfo *) gf_list_get(ccn->ContentCreators, j);
+                               if (!ci->isUTF8) continue;
+                               info += wxT("\t") + wxString(ci->contentCreatorName, wxConvUTF8) + wxT("\n");
+                       }
+               }
+                       break;
+
+               case GF_ODF_SHORT_TEXT_TAG:
+                       {
+                               GF_ShortTextual *std = (GF_ShortTextual *)desc;
+                               info += wxT("\n") + wxString(std->eventName, wxConvUTF8) + wxT(": ") + wxString(std->eventText, wxConvUTF8) + wxT("\n");
+                       }
+                       break;
+               /*todo*/
+               case GF_ODF_CC_DATE_TAG:
+                       break;
+               default:
+                       break;
+               }
+
+       }
+
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+}
+
+void wxFileProps::SetStreamsInfo()
+{
+       u32 i, count;
+       wxString info;
+       GF_MediaInfo odi;
+       char code[5];
+
+       info = wxT("");
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+
+       if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
+
+       if (odi.has_profiles) {
+               info += wxString::Format(wxT("\tOD Profile@Level %d\n"), odi.OD_pl);
+               info += wxString::Format(wxT("\tScene Profile@Level %d\n"), odi.scene_pl);
+               info += wxString::Format(wxT("\tGraphics Profile@Level %d\n"), odi.graphics_pl);
+               info += wxString::Format(wxT("\tAudio Profile@Level %d\n"), odi.audio_pl);
+               info += wxString::Format(wxT("\tVisual Profile@Level %d\n"), odi.scene_pl);
+               if (odi.inline_pl) info += wxT("\tInline Content use same profiles\n");
+               info += wxT("\n");
+       }
+
+       count = gf_list_count(odi.od->ESDescriptors);
+
+       for (i=0; i<count; i++) {
+               GF_ESD *esd = (GF_ESD *) gf_list_get(odi.od->ESDescriptors, i);
+               
+               info += wxString::Format(wxT("Stream ID %d - Clock ID %d\n"), esd->ESID, esd->OCRESID);
+               if (esd->dependsOnESID) {
+                       info += wxString::Format(wxT("\tDepends on Stream ID %d for decoding\n"), esd->dependsOnESID);
+               }
+               switch (esd->decoderConfig->streamType) {
+               case GF_STREAM_OD:
+                       info += wxString::Format(wxT("\tOD Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_OCR:
+                       info += wxT("\tObject Clock Reference Stream\n");
+                       break;
+               case GF_STREAM_SCENE:
+                       info += wxString::Format(wxT("\tScene Description Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_PRIVATE_SCENE:
+                       info += wxString::Format(wxT("\tGPAC Private Scene Description Stream\n"));
+                       break;
+               case GF_STREAM_VISUAL:
+                       info += wxT("\tVisual Stream - media type: ");
+                       switch (esd->decoderConfig->objectTypeIndication) {
+                       case GPAC_OTI_VIDEO_MPEG4_PART2: info += wxT("MPEG-4\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SIMPLE: info += wxT("MPEG-2 Simple Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_MAIN: info += wxT("MPEG-2 Main Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SNR: info += wxT("MPEG-2 SNR Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_SPATIAL: info += wxT("MPEG-2 Spatial Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_HIGH: info += wxT("MPEG-2 High Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG2_422: info += wxT("MPEG-2 422 Profile\n"); break;
+                       case GPAC_OTI_VIDEO_MPEG1: info += wxT("MPEG-1\n"); break;
+                       case GPAC_OTI_IMAGE_JPEG: info += wxT("JPEG\n"); break;
+                       case GPAC_OTI_IMAGE_PNG: info += wxT("PNG\n"); break;
+                       case GPAC_OTI_IMAGE_JPEG_2000: info += wxT("JPEG2000\n"); break;
+                       case 0x80:
+                               memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
+                               code[4] = 0;
+                               info += wxT("GPAC Intern (") + wxString(code, wxConvUTF8) + wxT(")\n");
+                               break;
+                       default: 
+                               info += wxString::Format(wxT("Private/Unknown Type (0x%x)\n"), esd->decoderConfig->objectTypeIndication); 
+                               break;
+                       }
+                       break;
+
+               case GF_STREAM_AUDIO:
+                       info += wxT("\tAudio Stream - media type: ");
+                       switch (esd->decoderConfig->objectTypeIndication) {
+                       case GPAC_OTI_AUDIO_AAC_MPEG4: info += wxT("MPEG-4\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_MP: info += wxT("MPEG-2 AAC Main Profile\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_LCP: info += wxT("MPEG-2 AAC LowComplexity Profile\n"); break;
+                       case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP: info += wxT("MPEG-2 AAC Scalable Sampling Rate Profile\n"); break;
+                       case GPAC_OTI_AUDIO_MPEG2_PART3: info += wxT("MPEG-2 Audio\n"); break;
+                       case GPAC_OTI_AUDIO_MPEG1: info += wxT("MPEG-1 Audio\n"); break;
+                       case 0xA0: info += wxT("EVRC Audio\n"); break;
+                       case 0xA1: info += wxT("SMV Audio\n"); break;
+                       case 0xE1: info += wxT("QCELP Audio\n"); break;
+                       case 0x80:
+                               memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
+                               code[4] = 0;
+                               info += wxT("GPAC Intern (") + wxString(code, wxConvUTF8) + wxT(")\n");
+                               break;
+                       default: 
+                               info += wxString::Format(wxT("Private/Unknown Type (0x%x)\n"), esd->decoderConfig->objectTypeIndication); 
+                               break;
+                       }
+                       break;
+               case GF_STREAM_MPEG7:
+                       info += wxString::Format(wxT("\tMPEG-7 Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_IPMP:
+                       info += wxString::Format(wxT("\tIPMP Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_OCI:
+                       info += wxString::Format(wxT("\tOCI Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_MPEGJ:
+                       info += wxString::Format(wxT("\tMPEGJ Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               case GF_STREAM_INTERACT:
+                       info += wxString::Format(wxT("\tUser Interaction Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
+                       break;
+               default:
+                       info += wxT("Private/Unknown\n");
+                       break;
+               }
+
+               info += wxString::Format(wxT("\tBuffer Size %d\n\tAverage Bitrate %d bps\n\tMaximum Bitrate %d bps\n"), esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate, esd->decoderConfig->maxBitrate);
+               if (esd->slConfig->predefined==SLPredef_SkipSL) {
+                       info += wxString::Format(wxT("\tNot using MPEG-4 Synchronization Layer\n"));
+               } else {
+                       info += wxString::Format(wxT("\tStream Clock Resolution %d\n"), esd->slConfig->timestampResolution);
+               }
+               if (esd->URLString) 
+                       info += wxT("\tStream Location: ") + wxString(esd->URLString, wxConvUTF8) + wxT("\n");
+
+               /*check language*/
+               if (esd->langDesc) {
+                       u32 i=0;
+                       char lan[4], *szLang;
+                       lan[0] = esd->langDesc->langCode>>16;
+                       lan[1] = (esd->langDesc->langCode>>8)&0xFF;
+                       lan[2] = (esd->langDesc->langCode)&0xFF;
+                       lan[3] = 0;
+
+                       if ((lan[0]=='u') && (lan[1]=='n') && (lan[2]=='d')) szLang = (char*) "Undetermined";
+                       else {
+                               szLang = lan;
+                               while (GF_ISO639_Lang[i]) {
+                                       if (GF_ISO639_Lang[i+2][0] && strstr(GF_ISO639_Lang[i+1], lan)) {
+                                               szLang = (char*) GF_ISO639_Lang[i];
+                                               break;
+                                       }
+                                       i+=3;
+                               }
+                       }
+                       info += wxString::Format(wxT("\tStream Language: %s\n"), szLang);
+               }
+
+       }
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+}
+
+
+void wxFileProps::SetDecoderInfo()
+{
+       GF_MediaInfo odi;
+       wxString info;
+       u32 h, m, s;
+
+       if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi)) {
+         m_pViewInfo->Clear();
+         m_pViewInfo->AppendText(info);
+         return;
+       }
+
+       info = wxT("Status: ");
+       switch (odi.status) {
+       case 0:
+       case 1:
+       case 2:
+               h = (u32) (odi.current_time / 3600);
+               m = (u32) (odi.current_time / 60) - h*60;
+               s = (u32) (odi.current_time) - h*3600 - m*60;
+               if (odi.status==0) info += wxT("Stopped");
+               else if (odi.status==1) info += wxT("Playing");
+               else info += wxT("Paused");
+               info += wxString::Format(wxT("\nObject Time: %02d:%02d:%02d\n"), h, m, s);
+               break;
+       case 3:
+               info += wxT("Not Setup\n");
+               m_pViewInfo->Clear();
+               m_pViewInfo->AppendText(info);
+               return;
+       default:
+               info += wxT("Setup Failed\n");
+               m_pViewInfo->Clear();
+               m_pViewInfo->AppendText(info);
+               return;
+       }
+       /*get clock drift*/
+       info += wxString::Format(wxT("Clock drift: %d ms\n"), odi.clock_drift);
+       /*get buffering*/
+       if (odi.buffer>=0) info += wxString::Format(wxT("Buffering Time: %d ms\n"), odi.buffer);
+       else if (odi.buffer==-1) info += wxT("Not buffering\n");
+       else info += wxT("Not Playing\n");
+
+       /*get DB occupation*/
+       if (odi.buffer>=0) info += wxString::Format(wxT("Decoding Buffer: %d Access Units\n"), odi.db_unit_count);
+       /*get CB occupation*/
+       if (odi.cb_max_count) 
+               info += wxString::Format(wxT("Composition Memory: %d/%d Units\n"), odi.cb_unit_count, odi.cb_max_count);
+
+       Float avg_dec_time = 0;
+       if (odi.nb_dec_frames) {
+               avg_dec_time = (Float) odi.total_dec_time; 
+               avg_dec_time /= odi.nb_dec_frames; 
+       }
+       info += wxString::Format(wxT("Average Bitrate %d kbps (%d max)\nAverage Decoding Time %.2f ms (%d max)\nTotal decoded frames %d - %d dropped\n"),
+                                                               (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time, odi.nb_dec_frames, odi.nb_droped);
+
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+}
+
+void wxFileProps::SetNetworkInfo()
+{
+       wxString info;
+       u32 id;
+       NetStatCommand com;
+       GF_MediaInfo odi;
+       u32 d_enum;
+       GF_Err e;
+
+       info = wxT("");
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(wxT(""));
+
+       if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
+
+       if (odi.owns_service) {
+               const char *url, *path;
+               u32 done, total, bps;
+               info = wxT("Current Downloads in service:\n");
+               d_enum = 0;
+               while (gf_term_get_download_info(m_pApp->m_term, m_current_odm, &d_enum, &url, &path, &done, &total, &bps)) {
+                       info += wxString(url, wxConvUTF8);
+                       if (total) {
+                               info += wxString::Format(wxT(": %d / %d bytes (%.2f %%) - %.2f kBps\n"), done, total, (100.0*done)/total, ((Double)bps)/1024);
+                       } else {
+                               info += wxString::Format(wxT(": %.2f kBps\n"), ((Double)bps)/1024);
+                       }
+               }
+               if (!d_enum) info = wxT("No Downloads in service\n");
+               info += wxT("\n");
+       }
+
+       d_enum = 0;
+       while (gf_term_get_channel_net_info(m_pApp->m_term, m_current_odm, &d_enum, &id, &com, &e)) {
+               if (e) continue;
+               if (!com.bw_down && !com.bw_up) continue;
+
+               info += wxString::Format(wxT("Stream ID %d statistics:\n"), id);
+               if (com.multiplex_port) {
+                       info += wxString::Format(wxT("\tMultiplex Port %d - multiplex ID %d\n"), com.multiplex_port, com.port);
+               } else {
+                       info += wxString::Format(wxT("\tPort %d\n"), com.port);
+               }
+               info += wxString::Format(wxT("\tPacket Loss Percentage: %.4f\n"), com.pck_loss_percentage);
+               info += wxString::Format(wxT("\tDown Bandwidth: %.3f bps\n"), ((Float)com.bw_down)/1024);
+               if (com.bw_up) info += wxString::Format(wxT("\tUp Bandwidth: %d bps\n"), com.bw_up);
+               if (com.ctrl_port) {
+                       if (com.multiplex_port) {
+                               info += wxString::Format(wxT("\tControl Multiplex Port: %d - Control Multiplex ID %d\n"), com.multiplex_port, com.ctrl_port);
+                       } else {
+                               info += wxString::Format(wxT("\tControl Port: %d\n"), com.ctrl_port);
+                       }
+                       info += wxString::Format(wxT("\tControl Down Bandwidth: %d bps\n"), com.ctrl_bw_down);
+                       info += wxString::Format(wxT("\tControl Up Bandwidth: %d bps\n"), com.ctrl_bw_up);
+               }
+               info += wxT("\n");
+       }
+       m_pViewInfo->Clear();
+       m_pViewInfo->AppendText(info);
+}
+
+
+void wxFileProps::OnViewWorld(wxCommandEvent &WXUNUSED(event)) 
+{
+       wxString wit;
+       const char *str;
+       GF_List *descs;
+       descs = gf_list_new();
+       str = gf_term_get_world_info(m_pApp->m_term, m_current_odm, descs);
+
+       if (!str) {
+               wxMessageDialog(this, wxT("No World Info available"), wxT("Sorry!"), wxOK).ShowModal();
+               return;
+       }
+
+       wit = wxT("");
+       for (u32 i=0; gf_list_count(descs); i++) {
+               const char *d = (const char *) gf_list_get(descs, i);
+               wit += wxString(d, wxConvUTF8);
+               wit += wxT("\n");
+       }
+       wxMessageDialog(this, wit, wxString(str, wxConvUTF8), wxOK).ShowModal();
+       gf_list_del(descs);
+}
+
+void wxFileProps::OnViewSG(wxCommandEvent &WXUNUSED(event)) 
+{
+       const char *sOpt;
+       Bool dump_xmt;
+       wxFileName out_file;
+       char szOutFile[GF_MAX_PATH];
+       wxString fname;
+
+       sOpt = gf_cfg_get_key(m_pApp->m_user.config, "General", "CacheDirectory");
+       out_file.AssignDir(wxString(sOpt, wxConvUTF8) );
+
+       sOpt = gf_cfg_get_key(m_pApp->m_user.config, "General", "ViewXMT");
+       out_file.SetFullName(wxT("scene_dump"));
+       if (sOpt && !stricmp(sOpt, "yes")) {
+               dump_xmt = 1;
+       } else {
+               dump_xmt = 0;
+       }
+       strcpy(szOutFile, out_file.GetFullName().mb_str(wxConvUTF8));
+
+       GF_Err e = gf_term_dump_scene(m_pApp->m_term, szOutFile, NULL, dump_xmt, 0, m_current_odm);
+       if (e) {
+               wxMessageDialog dlg(this, wxString(gf_error_to_string(e), wxConvUTF8), wxT("Error while dumping"), wxOK);
+               dlg.ShowModal();
+       } else {
+               wxString cmd = get_pref_browser(m_pApp->m_user.config);
+               cmd += wxT(" ");
+               cmd += wxString(szOutFile, wxConvUTF8);
+               wxExecute(cmd);
+       }
+}
diff --git a/applications/osmo4_wx/fileprops.h b/applications/osmo4_wx/fileprops.h
new file mode 100644 (file)
index 0000000..a1ba51b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#ifndef _FILEPROPS_H
+#define _FILEPROPS_H
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+  #include "wx/wx.h"
+#endif
+
+#include <wx/treectrl.h>
+
+#include <gpac/terminal.h>
+
+/*abstract class for all items in the tree*/
+class ODTreeData : public wxTreeItemData
+{
+public:
+       ODTreeData(GF_ObjectManager *odm) : wxTreeItemData(), m_pODMan(odm) {}
+       GF_ObjectManager *m_pODMan;
+};
+
+
+class wxOsmo4Frame;
+class wxFileProps : public wxDialog 
+{
+public:
+    wxFileProps(wxWindow *parent);
+    virtual ~wxFileProps();
+
+private:
+       DECLARE_EVENT_TABLE()
+
+       wxOsmo4Frame *m_pApp;
+
+       wxTreeCtrl *m_pTreeView;
+       wxTextCtrl *m_pViewInfo;
+       wxComboBox *m_pViewSel;
+       wxButton *m_pViewWI, *m_pViewSG;
+       wxTimer *m_pTimer;
+
+       GF_ObjectManager *m_current_odm;
+
+       void RewriteODTree();
+       void SetGeneralInfo();
+       void SetStreamsInfo();
+       void SetDecoderInfo();
+       void SetNetworkInfo();
+       void WriteInlineTree(ODTreeData *pRoot);
+       void OnSetSelection(wxTreeEvent &event);
+       void OnSelectInfo(wxCommandEvent &event);
+       void OnTimer(wxTimerEvent &event);
+       void OnViewWorld(wxCommandEvent &event);
+       void OnViewSG(wxCommandEvent &event);
+       void SetInfo(GF_ObjectManager *odm);
+};
+
+#endif
+
diff --git a/applications/osmo4_wx/menubtn.cpp b/applications/osmo4_wx/menubtn.cpp
new file mode 100644 (file)
index 0000000..a13e58c
--- /dev/null
@@ -0,0 +1,863 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxMenuButton
+// Purpose:     A button with a dropdown wxMenu
+// Author:      John Labenski
+// Modified by:
+// Created:     11/05/2002
+// RCS-ID:
+// Copyright:   (c) John Labenki
+// Licence:     wxWidgets licence
+/////////////////////////////////////////////////////////////////////////////
+
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+    #pragma implementation "menubtn.h"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/control.h"
+    #include "wx/menu.h"
+    #include "wx/settings.h"
+    #include "wx/bitmap.h"
+    #include "wx/pen.h"
+    #include "wx/dc.h"
+#endif // WX_PRECOMP
+
+#include <wx/tglbtn.h>
+#include <wx/dcclient.h>
+#include <wx/timer.h>
+#include <wx/image.h>
+
+#include "menubtn.h"
+
+
+
+// ==========================================================================
+// wxCustomButton
+// ==========================================================================
+IMPLEMENT_DYNAMIC_CLASS( wxCustomButton, wxControl )
+
+BEGIN_EVENT_TABLE(wxCustomButton,wxControl)
+    EVT_MOUSE_EVENTS ( wxCustomButton::OnMouseEvents )
+    EVT_PAINT        ( wxCustomButton::OnPaint )
+    EVT_SIZE         ( wxCustomButton::OnSize )
+END_EVENT_TABLE()
+
+wxCustomButton::~wxCustomButton()
+{
+    if (HasCapture()) ReleaseMouse();
+    if (m_timer) delete m_timer;
+}
+
+void wxCustomButton::Init()
+{
+    m_focused = FALSE;
+    m_labelMargin = wxSize(4,4);
+    m_bitmapMargin = wxSize(2,2);
+    m_down = 0;
+    m_timer = NULL;
+    m_eventType = 0;
+    m_button_style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM;
+}
+
+bool wxCustomButton::Create(wxWindow* parent, wxWindowID id,
+                            const wxString& label, const wxBitmap &bitmap,
+                            const wxPoint& pos, const wxSize& size,
+                            long style, const wxValidator& val,
+                            const wxString& name)
+{
+    if (!wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name))
+        return FALSE;
+    
+    wxControl::SetLabel(label);    
+    wxControl::SetBackgroundColour(parent->GetBackgroundColour());
+    wxControl::SetForegroundColour(parent->GetForegroundColour());
+    wxControl::SetFont(parent->GetFont());
+
+    if (bitmap.Ok()) m_bmpLabel = bitmap;
+    
+    if (!SetButtonStyle(style)) return FALSE;
+
+    wxSize bestSize = DoGetBestSize();
+    SetSize(wxSize(size.x<0 ? bestSize.x:size.x, size.y<0 ? bestSize.y:size.y));
+#if (wxMINOR_VERSION<8) 
+    SetBestSize(GetSize());
+#else
+    SetInitialSize(GetSize());
+#endif
+    
+    CalcLayout(TRUE);
+    return TRUE;
+}
+
+void wxCustomButton::SetValue(bool depressed)
+{
+    wxCHECK_RET(!(m_button_style & wxCUSTBUT_NOTOGGLE), wxT("can't set button state"));
+    m_down = depressed ? 1 : 0;
+    Refresh(FALSE);
+}
+
+bool wxCustomButton::SetButtonStyle(long style)
+{
+    int n_styles = 0;
+    if ((style & wxCUSTBUT_LEFT) != 0)   n_styles++;
+    if ((style & wxCUSTBUT_RIGHT) != 0)  n_styles++;
+    if ((style & wxCUSTBUT_TOP) != 0)    n_styles++;
+    if ((style & wxCUSTBUT_BOTTOM) != 0) n_styles++;
+    wxCHECK_MSG(n_styles < 2, FALSE, wxT("Only one wxCustomButton label position allowed"));
+    
+    n_styles = 0;
+    if ((style & wxCUSTBUT_NOTOGGLE) != 0)       n_styles++;
+    if ((style & wxCUSTBUT_BUTTON) != 0)         n_styles++;
+    if ((style & wxCUSTBUT_TOGGLE) != 0)         n_styles++;
+    if ((style & wxCUSTBUT_BUT_DCLICK_TOG) != 0) n_styles++;
+    if ((style & wxCUSTBUT_TOG_DCLICK_BUT) != 0) n_styles++;
+    wxCHECK_MSG(n_styles < 2, FALSE, wxT("Only one wxCustomButton style allowed"));
+
+    m_button_style = style;
+    
+    if ((m_button_style & wxCUSTBUT_BUTTON) != 0) 
+        m_down = 0;
+    
+    CalcLayout(TRUE);
+    return TRUE;
+}
+
+void wxCustomButton::SetLabel( const wxString &label )
+{
+    wxControl::SetLabel(label);
+    CalcLayout(TRUE);
+}
+
+// sequence of events in GTK is up, dclick, up.
+
+void wxCustomButton::OnMouseEvents(wxMouseEvent& event)
+{
+    if (m_button_style & wxCUSTBUT_NOTOGGLE) return;
+    
+    if (event.LeftDown() || event.RightDown())
+    {
+        if (!HasCapture()) 
+            CaptureMouse(); // keep depressed until up
+        
+        m_down++;
+        Redraw();
+    }
+    else if (event.LeftDClick() || event.RightDClick())
+    {
+        m_down++; // GTK eats second down event
+        Redraw();
+    }
+    else if (event.LeftUp())
+    {
+        if (HasCapture()) 
+            ReleaseMouse();
+        
+        m_eventType = wxEVT_LEFT_UP;
+        
+#if (wxMINOR_VERSION<8) 
+        if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition()))
+#else
+        if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition()))
+#endif
+        {
+            if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0))
+            {
+                m_down = 0;
+                Redraw();
+                SendEvent();
+                return;
+            }
+            else
+            {
+                if (!m_timer)
+                {
+                    m_timer = new wxTimer(this, m_down+1);
+                    m_timer->Start(200, TRUE);
+                }
+                else
+                {
+                    m_eventType = wxEVT_LEFT_DCLICK;
+                }
+                
+                if ((m_button_style & wxCUSTBUT_TOGGLE) && 
+                    (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT)) m_down++;
+            }
+        }
+
+        Redraw();
+    }
+    else if (event.RightUp())
+    {
+        if (HasCapture()) 
+            ReleaseMouse();
+        
+        m_eventType = wxEVT_RIGHT_UP;
+
+#if (wxMINOR_VERSION<8) 
+        if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition()))
+#else
+        if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition()))
+#endif
+        {
+            if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0))
+            {
+                m_down = 0;
+                Redraw();
+                SendEvent();
+                return;
+            }
+            else
+            {
+                m_down++;
+            
+                if (!m_timer)
+                {
+                    m_timer = new wxTimer(this, m_down);
+                    m_timer->Start(250, TRUE);
+                }
+                else
+                {
+                    m_eventType = wxEVT_RIGHT_DCLICK;
+                }
+            }
+        }
+        
+        Redraw();
+    }
+    else if (event.Entering())
+    {
+        m_focused = TRUE;
+        if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) 
+            m_down++;
+        
+        Redraw();
+    }
+    else if (event.Leaving())
+    {
+        m_focused = FALSE;
+        if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture())
+            m_down--;
+        
+        Redraw();
+    }
+}
+
+
+
+void wxCustomButton::SendEvent()
+{
+    if (((m_button_style & wxCUSTBUT_TOGGLE) && (m_eventType == wxEVT_LEFT_UP)) || 
+        ((m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) && (m_eventType == wxEVT_LEFT_DCLICK)) ||
+        ((m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) && (m_eventType == wxEVT_LEFT_UP)))
+    {
+        wxCommandEvent eventOut(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, GetId());
+        eventOut.SetInt(m_down%2 ? 1 : 0);
+        eventOut.SetExtraLong(m_eventType);
+        eventOut.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(eventOut);
+    }
+    else
+    {
+        wxCommandEvent eventOut(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
+        eventOut.SetInt(0);
+        eventOut.SetExtraLong(m_eventType);
+        eventOut.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(eventOut);
+    }
+}
+
+wxBitmap wxCustomButton::CreateBitmapDisabled(const wxBitmap &bitmap) const
+{    
+    wxCHECK_MSG(bitmap.Ok(), wxNullBitmap, wxT("invalid bitmap"));
+    
+    unsigned char br = GetBackgroundColour().Red();
+    unsigned char bg = GetBackgroundColour().Green();
+    unsigned char bb = GetBackgroundColour().Blue();
+        
+    wxImage image = bitmap.ConvertToImage();
+    int pos, width = image.GetWidth(), height = image.GetHeight();
+    unsigned char *img_data = image.GetData();
+
+    for (int j=0; j<height; j++)
+    {
+        for (int i=j%2; i<width; i+=2)
+        {   
+            pos = (j*width+i)*3;
+            img_data[pos  ] = br; 
+            img_data[pos+1] = bg; 
+            img_data[pos+2] = bb; 
+        }
+    }
+        
+    return wxBitmap(image);
+}
+
+void wxCustomButton::SetBitmapLabel(const wxBitmap& bitmap)
+{ 
+    m_bmpLabel = bitmap; 
+    CalcLayout(TRUE); 
+}
+
+void wxCustomButton::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+    wxPaintDC dc(this);
+    Paint(dc);
+}
+
+void wxCustomButton::Redraw()
+{
+    wxClientDC dc(this);
+    Paint(dc);
+}
+
+void wxCustomButton::Paint( wxDC &dc )
+{
+#if (wxMINOR_VERSION<8) 
+    dc.BeginDrawing();
+#endif
+
+    int w, h;
+    GetSize(&w,&h);
+    wxColour foreColour = GetForegroundColour();
+    wxColour backColour = GetBackgroundColour();
+
+    if (m_focused)
+    {
+        backColour.Set( wxMin(backColour.Red()   + 20, 255),
+                        wxMin(backColour.Green() + 20, 255),
+                        wxMin(backColour.Blue()  + 20, 255) );
+    }
+
+    wxBitmap bitmap;
+    
+    if (IsEnabled())
+    {
+        if (GetValue() && m_bmpSelected.Ok()) 
+            bitmap = m_bmpSelected;
+        else if (m_focused && m_bmpFocus.Ok()) 
+            bitmap = m_bmpFocus;
+        else if (m_bmpLabel.Ok())  
+            bitmap = m_bmpLabel;
+    }
+    else
+    {
+        // try to create disabled if it doesn't exist
+        if (!m_bmpDisabled.Ok() && m_bmpLabel.Ok())
+            m_bmpDisabled = CreateBitmapDisabled(m_bmpLabel);
+
+        if (m_bmpDisabled.Ok())
+            bitmap = m_bmpDisabled;
+        else if (m_bmpLabel.Ok()) 
+            bitmap = m_bmpLabel;
+
+        foreColour = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
+    }
+
+    wxBrush brush(backColour, wxSOLID);
+    dc.SetBackground(brush);
+    dc.SetBrush(brush);
+    dc.SetPen(*wxTRANSPARENT_PEN);
+
+    dc.DrawRectangle(0, 0, w, h);
+
+    if (bitmap.Ok()) 
+        dc.DrawBitmap(bitmap, m_bitmapPos.x, m_bitmapPos.y, TRUE );
+
+    if (!GetLabel().IsEmpty())
+    {
+        dc.SetFont(GetFont());
+        dc.SetTextBackground(backColour);
+        dc.SetTextForeground(foreColour);
+        dc.DrawText(GetLabel(), m_labelPos.x, m_labelPos.y);
+    }
+    
+    if (GetValue())                                        // draw sunken border
+    {
+        dc.SetPen(*wxGREY_PEN);
+        dc.DrawLine(0,h-1,0,0);     dc.DrawLine(0,0,w,0);
+        dc.SetPen(*wxWHITE_PEN);
+        dc.DrawLine(w-1,1,w-1,h-1); dc.DrawLine(w-1,h-1,0,h-1);
+        dc.SetPen(*wxBLACK_PEN);
+        dc.DrawLine(1,h-2,1,1);     dc.DrawLine(1,1,w-1,1);
+    }
+    else if (((m_button_style & wxCUSTBUT_FLAT) == 0) || m_focused) // draw raised border
+    {
+        dc.SetPen(*wxWHITE_PEN);
+        dc.DrawLine(0,h-2,0,0);     dc.DrawLine(0,0,w-1,0);
+        dc.SetPen(*wxBLACK_PEN);
+        dc.DrawLine(w-1,0,w-1,h-1); dc.DrawLine(w-1,h-1,-1,h-1);
+        dc.SetPen(*wxGREY_PEN);
+        dc.DrawLine(2,h-2,w-2,h-2); dc.DrawLine(w-2,h-2,w-2,1);
+    }
+
+    dc.SetBackground(wxNullBrush);
+    dc.SetBrush(wxNullBrush);
+    dc.SetPen(wxNullPen);
+#if (wxMINOR_VERSION<8) 
+    dc.EndDrawing();
+#endif
+}
+
+void wxCustomButton::OnSize( wxSizeEvent &event )
+{
+    CalcLayout(TRUE);
+    event.Skip();
+}
+
+void wxCustomButton::SetMargins(const wxSize &margin, bool fit)
+{ 
+    m_labelMargin = margin; 
+    m_bitmapMargin = margin; 
+    CalcLayout(TRUE); 
+    if (fit) SetSize(DoGetBestSize());
+}
+void wxCustomButton::SetLabelMargin(const wxSize &margin, bool fit) 
+{ 
+    m_labelMargin = margin; 
+    CalcLayout(TRUE); 
+    if (fit) SetSize(DoGetBestSize());
+}
+void wxCustomButton::SetBitmapMargin(const wxSize &margin, bool fit) 
+{ 
+    m_bitmapMargin = margin; 
+    CalcLayout(TRUE); 
+    if (fit) SetSize(DoGetBestSize());
+}
+
+wxSize wxCustomButton::DoGetBestSize() const
+{
+    int lw=0, lh=0;
+    int bw=0, bh=0;
+    bool has_bitmap = FALSE;
+    bool has_label = FALSE;
+    
+    if (!GetLabel().IsEmpty())
+    {
+        GetTextExtent(GetLabel(), &lw, &lh);
+        lw += 2*m_labelMargin.x;
+        lh += 2*m_labelMargin.y;
+        has_label = TRUE;
+    }
+    if (m_bmpLabel.Ok())
+    {
+        bw = m_bmpLabel.GetWidth() + 2*m_bitmapMargin.x;
+        bh = m_bmpLabel.GetHeight() + 2*m_bitmapMargin.y;
+        has_bitmap = TRUE;
+    }
+
+    if ((m_button_style & wxCUSTBUT_LEFT) || (m_button_style & wxCUSTBUT_RIGHT))
+    {
+        int h = bh > lh ? bh : lh;
+        if (has_bitmap && has_label) lw -= wxMin(m_labelMargin.x, m_bitmapMargin.x);
+        return wxSize(lw+bw, h);
+    }
+
+    int w = bw > lw ? bw : lw;
+    if (has_bitmap && has_label) lh -= wxMin(m_labelMargin.y, m_bitmapMargin.y);
+    return wxSize(w, lh+bh);
+}
+
+void wxCustomButton::CalcLayout(bool refresh)
+{
+    int w, h;
+    GetSize(&w,&h);
+
+    int bw = 0, bh = 0;
+    int lw = 0, lh = 0;
+
+    if (m_bmpLabel.Ok()) // assume they're all the same size
+    {
+        bw = m_bmpLabel.GetWidth();
+        bh = m_bmpLabel.GetHeight();
+    }
+    wxString label = GetLabel();
+    if (!label.IsEmpty())
+    {
+        GetTextExtent(label, &lw, &lh);
+    }
+    
+    // Center the label or bitmap if only one or the other
+    if (!m_bmpLabel.Ok())
+    {
+        m_bitmapPos = wxPoint(0,0);
+        m_labelPos = wxPoint((w-lw)/2, (h-lh)/2);
+    }
+    else if (label.IsEmpty())
+    {
+        m_bitmapPos = wxPoint((w-bw)/2, (h-bh)/2);
+        m_labelPos = wxPoint(0,0);
+    }
+    else if (m_button_style & wxCUSTBUT_LEFT)
+    {
+        int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x);
+        m_labelPos  = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_labelMargin.x, (h - lh)/2);
+        m_bitmapPos = wxPoint(m_labelPos.x + lw + mid_margin,         (h - bh)/2);
+    }
+    else if (m_button_style & wxCUSTBUT_RIGHT)
+    {
+        int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x);
+        m_bitmapPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_bitmapMargin.x, (h - bh)/2);
+        m_labelPos  = wxPoint(m_bitmapPos.x + bw + mid_margin,        (h - lh)/2);
+    }
+    else if (m_button_style & wxCUSTBUT_TOP)
+    {
+        int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y);
+        m_labelPos  = wxPoint((w - lw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_labelMargin.y);
+        m_bitmapPos = wxPoint((w - bw)/2, m_labelPos.y + lh + mid_margin);
+    }
+    else // if (m_button_style & wxCUSTBUT_BOTTOM)  DEFAULT
+    {
+        int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y);
+        m_bitmapPos = wxPoint((w - bw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_bitmapMargin.y);
+        m_labelPos  = wxPoint((w - lw)/2, m_bitmapPos.y + bh + mid_margin);
+    }
+    
+    if (refresh) Refresh(FALSE);
+}
+
+
+/* XPM */
+static const char *down_arrow_xpm_data[] = {
+/* columns rows colors chars-per-pixel */
+"5 3 2 1",
+"  c None",
+"a c Black",
+/* pixels */
+"aaaaa",
+" aaa ",
+"  a  "};
+
+static wxBitmap s_dropdownBitmap; // all buttons share the same bitmap
+
+enum
+{
+    IDD_DROPDOWN_BUTTON = 100
+};
+
+//-----------------------------------------------------------------------------
+// wxMenuButtonEvents
+//-----------------------------------------------------------------------------
+
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_MENUBUTTON_OPEN)
+
+// ==========================================================================
+// MenuDropButton
+// ==========================================================================
+
+class MenuDropButton : public wxCustomButton
+{
+public:
+    MenuDropButton( wxWindow *parent, wxWindowID id, long style) : wxCustomButton()
+    {
+        if (!s_dropdownBitmap.Ok())
+            s_dropdownBitmap = wxBitmap(down_arrow_xpm_data);
+        
+        Create( parent, id, wxEmptyString, s_dropdownBitmap, wxDefaultPosition, 
+                wxSize(wxMENUBUTTON_DROP_WIDTH, wxMENUBUTTON_DROP_HEIGHT), style);    
+    }
+    
+    virtual void Paint( wxDC &dc )
+    {
+        wxCustomButton *labelBut = ((wxMenuButton*)GetParent())->GetLabelButton();
+        
+        // pretend that both buttons have focus (for flat style)
+        if (labelBut)
+        {
+            wxPoint p = GetParent()->ScreenToClient(wxGetMousePosition());
+        
+#if (wxMINOR_VERSION<8) 
+            if (GetRect().Inside(p) || labelBut->GetRect().Inside(p))
+#else
+            if (GetRect().Contains(p) || labelBut->GetRect().Contains(p))
+#endif
+            {
+                m_focused = TRUE;
+                
+                if (!labelBut->GetFocused())
+                    labelBut->SetFocused(TRUE);
+            }
+            else
+            {
+                m_focused = FALSE;
+                
+                if (labelBut->GetFocused())
+                    labelBut->SetFocused(FALSE);
+            }
+        }
+        
+        wxCustomButton::Paint(dc);
+    }
+};
+
+// ==========================================================================
+// MenuLabelButton
+// ==========================================================================
+
+class MenuLabelButton : public wxCustomButton
+{
+public:
+    MenuLabelButton( wxWindow* parent, wxWindowID id, 
+                     const wxString &label, 
+                     const wxBitmap &bitmap,
+                     long style ) : wxCustomButton()
+    {
+        Create(parent, id, label, bitmap, wxDefaultPosition, wxDefaultSize, style);    
+    }
+    
+    virtual void Paint( wxDC &dc )
+    {
+        wxCustomButton *dropBut = ((wxMenuButton*)GetParent())->GetDropDownButton();
+
+        // pretend that both buttons have focus (for flat style)
+        if (dropBut) 
+        {
+            wxPoint p = GetParent()->ScreenToClient(wxGetMousePosition());
+        
+#if (wxMINOR_VERSION<8) 
+            if (GetRect().Inside(p) || dropBut->GetRect().Inside(p))
+#else
+            if (GetRect().Contains(p) || dropBut->GetRect().Contains(p))
+#endif
+            {
+                m_focused = TRUE;
+                
+                if (!dropBut->GetFocused())
+                    dropBut->SetFocused(TRUE);
+            }
+            else
+            {
+                m_focused = FALSE;
+                
+                if (dropBut->GetFocused())
+                    dropBut->SetFocused(FALSE);
+            }
+        }
+
+        wxCustomButton::Paint(dc);
+    }
+};
+
+// ==========================================================================
+// wxMenuButton
+// ==========================================================================
+
+IMPLEMENT_DYNAMIC_CLASS( wxMenuButton, wxControl )
+
+BEGIN_EVENT_TABLE(wxMenuButton,wxControl)
+    EVT_BUTTON(wxID_ANY, wxMenuButton::OnButton)
+
+#ifdef __WXMSW__
+    EVT_MENU(wxID_ANY, wxMenuButton::OnMenu)
+#endif
+END_EVENT_TABLE()
+
+wxMenuButton::~wxMenuButton()
+{
+    AssignMenu(NULL, TRUE);
+}
+
+void wxMenuButton::Init()
+{
+    m_labelButton = NULL;
+    m_dropdownButton = NULL;
+    m_menu = NULL;
+    m_menu_static = FALSE;
+    m_style = 0;
+}
+
+bool wxMenuButton::Create( wxWindow* parent, wxWindowID id,
+                           const wxString &label, 
+                           const wxBitmap &bitmap,
+                           const wxPoint& pos, 
+                           const wxSize& size,
+                           long style, 
+                           const wxValidator& val,
+                           const wxString& name)
+{
+    m_style = style;
+    
+    long flat = style & wxMENUBUT_FLAT;
+    
+    wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name);
+    wxControl::SetLabel(label);
+    SetBackgroundColour(parent->GetBackgroundColour());
+    SetForegroundColour(parent->GetForegroundColour());
+    SetFont(parent->GetFont());
+
+    m_labelButton = new MenuLabelButton(this, id, label, bitmap, wxCUSTBUT_BUTTON|flat);
+    m_dropdownButton = new MenuDropButton(this, IDD_DROPDOWN_BUTTON, wxCUSTBUT_BUTTON|flat);
+    
+    wxSize bestSize = DoGetBestSize();
+    SetSize( wxSize(size.x < 0 ? bestSize.x : size.x, 
+                    size.y < 0 ? bestSize.y : size.y) );
+   
+#if (wxMINOR_VERSION<8) 
+    SetBestSize(GetSize());
+#else
+    SetInitialSize(GetSize());
+#endif
+    
+    return TRUE;
+}
+
+#ifdef __WXMSW__
+// FIXME - I think there was a patch to fix this
+void wxMenuButton::OnMenu( wxCommandEvent &event ) 
+{
+    event.Skip();    
+    wxMenuItem *mi = m_menu->FindItem(event.GetId());
+    if (mi && (mi->GetKind() == wxITEM_RADIO))
+        m_menu->Check(event.GetId(), TRUE);    
+}
+#endif // __WXMSW__
+
+void wxMenuButton::OnButton( wxCommandEvent &event)
+{
+    int win_id = event.GetId();
+    
+    if (win_id == IDD_DROPDOWN_BUTTON)
+    {
+        wxNotifyEvent mevent(wxEVT_MENUBUTTON_OPEN, GetId());
+        mevent.SetEventObject(this);
+        if (GetEventHandler()->ProcessEvent(mevent) && !mevent.IsAllowed())
+            return;
+
+        if (!m_menu) 
+            return;
+        
+        PopupMenu(m_menu, wxPoint(0, GetSize().y));
+        
+        m_labelButton->Refresh(FALSE);
+        m_dropdownButton->Refresh(FALSE);
+    }
+    else if (win_id == m_labelButton->GetId())
+    {
+
+        wxCommandEvent cevent(wxEVT_COMMAND_MENU_SELECTED, win_id);
+        cevent.SetEventObject(this);
+        cevent.SetId(win_id);
+               GetParent()->GetEventHandler()->ProcessEvent(cevent);
+
+        if (!m_menu) return;
+        
+        const wxMenuItemList &items = m_menu->GetMenuItems();
+        int first_radio_id = -1;
+        int checked_id = -1;
+        bool check_next = FALSE;
+        
+        // find the next available radio item to check
+        for (wxMenuItemList::Node *node = items.GetFirst(); node; node = node->GetNext())
+        {
+            wxMenuItem *mi = (wxMenuItem*)node->GetData();
+            if (mi && (mi->GetKind() == wxITEM_RADIO))
+            {
+                if (first_radio_id == -1) 
+                    first_radio_id = mi->GetId();
+                
+                if (check_next) 
+                {
+                    check_next = FALSE;
+                    checked_id = mi->GetId();
+                    break;
+                }
+                else if (mi->IsChecked()) 
+                    check_next = TRUE;
+            }
+        }
+        // the last item was checked, go back to the first
+        if (check_next && (first_radio_id != -1))
+            checked_id = first_radio_id;
+        
+        if (checked_id != -1)
+        {
+            m_menu->Check(checked_id, TRUE);
+            
+            wxCommandEvent mevent( wxEVT_COMMAND_MENU_SELECTED, checked_id);
+            mevent.SetEventObject( m_menu );
+            mevent.SetInt(1);
+            GetEventHandler()->ProcessEvent(mevent);
+        }
+    }
+}
+
+int wxMenuButton::GetSelection() const
+{
+    wxCHECK_MSG(m_menu != NULL, wxNOT_FOUND, wxT("No attached menu in wxMenuButton::GetSelection"));
+        
+    const wxMenuItemList &items = m_menu->GetMenuItems();
+        
+    for (wxMenuItemList::Node *node = items.GetFirst(); node; node = node->GetNext())
+    {
+        wxMenuItem *mi = (wxMenuItem*)node->GetData();
+        if (mi && (mi->GetKind() == wxITEM_RADIO))
+        {
+            if (mi->IsChecked())
+                return mi->GetId();
+        }
+    }
+    
+    return wxNOT_FOUND;    
+}
+
+void wxMenuButton::AssignMenu(wxMenu *menu, bool static_menu)
+{
+    if (!m_menu_static && m_menu) 
+        delete m_menu;
+    
+    m_menu = menu;
+    m_menu_static = static_menu;
+}
+
+void wxMenuButton::SetToolTip(const wxString &tip) 
+{ 
+    wxWindow::SetToolTip(tip);
+    ((wxWindow*)m_labelButton)->SetToolTip(tip); 
+    ((wxWindow*)m_dropdownButton)->SetToolTip(tip);
+}
+void wxMenuButton::SetToolTip(wxToolTip *tip) 
+{ 
+    wxWindow::SetToolTip(tip);
+    ((wxWindow*)m_labelButton)->SetToolTip(tip); 
+    ((wxWindow*)m_dropdownButton)->SetToolTip(tip);
+}
+
+void wxMenuButton::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+{
+    wxSize curSize( GetSize() );
+    wxSize bestSize( DoGetBestSize() );
+
+    if (width == -1)
+        width = curSize.GetWidth();
+    if (width < 10) 
+        width = bestSize.GetWidth();
+
+    if (height == -1)
+        height = curSize.GetHeight();
+    if (height < 5) 
+        height = bestSize.GetHeight();
+    
+    wxWindow::DoSetSize(x, y, width, height, sizeFlags);    
+
+    if (m_labelButton)
+        m_labelButton->SetSize(0, 0, width - wxMENUBUTTON_DROP_WIDTH, height);
+    if (m_dropdownButton)
+        m_dropdownButton->SetSize(width-wxMENUBUTTON_DROP_WIDTH, 0, wxMENUBUTTON_DROP_WIDTH, height);    
+}
+
+wxSize wxMenuButton::DoGetBestSize()
+{
+    if (!m_labelButton || !m_dropdownButton) 
+        return wxSize(wxMENUBUTTON_DROP_WIDTH+wxMENUBUTTON_DROP_HEIGHT, wxMENUBUTTON_DROP_HEIGHT);
+
+    wxSize size = m_labelButton->GetBestSize();
+    size.x += wxMENUBUTTON_DROP_WIDTH;
+    return size;
+}
diff --git a/applications/osmo4_wx/menubtn.h b/applications/osmo4_wx/menubtn.h
new file mode 100644 (file)
index 0000000..441c7b7
--- /dev/null
@@ -0,0 +1,314 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxMenuButton
+// Purpose:     A button with a dropdown wxMenu
+// Author:      John Labenski
+// Modified by:
+// Created:     11/05/2002
+// Copyright:   (c) John Labenski
+// Licence:     wxWidgets licence
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+
+wxMenuButton is a button that drops down an assigned wxMenu
+
+Create the button with either a text or bitmap label.
+    Create a new wxMenu and call AssignMenu and thats it. When you press the 
+    dropdown button the menu appears. When you press the label button the next
+    wxITEM_RADIO (ie wxMenuItem::GetKind) in the menu is selected round robin.
+    If there are no radio items then it really just acts like a menubar, though
+    this is probably not too useful. The events sent in this case are EVT_MENUs
+    either generated by the menu when you click on it or created when you click
+    on the label to select the next radio item.
+*/
+
+#ifndef _WX_MENUBTN_H_
+#define _WX_MENUBTN_H_
+
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+    #pragma interface "menubtn.h"
+#endif
+
+class wxMenu;
+class wxBitmap;
+class wxCustomButton;
+
+//-----------------------------------------------------------------------------
+// wxCustomButton styles
+//-----------------------------------------------------------------------------
+
+enum wxCustomButton_Style
+{
+    // Position of the label, use only one
+    wxCUSTBUT_LEFT           = 0x0001,
+    wxCUSTBUT_RIGHT          = 0x0002,
+    wxCUSTBUT_TOP            = 0x0004,
+    wxCUSTBUT_BOTTOM         = 0x0008,
+    // Button style, use only one
+    wxCUSTBUT_NOTOGGLE       = 0x0100,
+    wxCUSTBUT_BUTTON         = 0x0200,
+    wxCUSTBUT_TOGGLE         = 0x0400,
+    wxCUSTBUT_BUT_DCLICK_TOG = 0x0800,
+    wxCUSTBUT_TOG_DCLICK_BUT = 0x1000, 
+    // drawing styles
+    wxCUSTBUT_FLAT           = 0x2000 // flat, mouseover raises if not depressed
+};
+
+//-----------------------------------------------------------------------------
+// wxCustomButton
+//-----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxCustomButton : public wxControl
+{
+public:
+
+    wxCustomButton() : wxControl() { Init(); }
+    
+    // wxToggleButton or wxButton compatible constructor (also wxTextCtrl)
+    wxCustomButton(wxWindow* parent, wxWindowID id,
+                   const wxString& label,
+                   const wxPoint& pos = wxDefaultPosition,
+                   const wxSize& size = wxDefaultSize,
+                   long style = wxCUSTBUT_TOGGLE,
+                   const wxValidator& val = wxDefaultValidator,
+                   const wxString& name = wxT("wxCustomButton"))
+                   : wxControl()
+    {
+        Init();
+        Create(parent,id,label,wxNullBitmap,pos,size,style,val,name);
+    }
+
+    // wxBitmapButton compatible constructor
+    wxCustomButton(wxWindow *parent, wxWindowID id,
+                   const wxBitmap& bitmap,
+                   const wxPoint& pos = wxDefaultPosition,
+                   const wxSize& size = wxDefaultSize,
+                   long style = wxCUSTBUT_TOGGLE,
+                   const wxValidator& val = wxDefaultValidator,
+                   const wxString& name = wxT("wxCustomButton"))
+                   : wxControl()
+    {
+        Init();
+        Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name);
+    }
+
+    // Native constructor
+    wxCustomButton(wxWindow *parent, wxWindowID id,
+                   const wxString& label, const wxBitmap& bitmap,
+                   const wxPoint& pos = wxDefaultPosition,
+                   const wxSize& size = wxDefaultSize,
+                   long style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM,
+                   const wxValidator& val = wxDefaultValidator,
+                   const wxString& name = wxT("wxCustomButton"))
+                   : wxControl()
+    {
+        Init();
+        Create(parent,id,label,bitmap,pos,size,style,val,name);
+    }
+
+    virtual ~wxCustomButton();
+        
+    bool Create(wxWindow* parent,
+                wxWindowID id,
+                const wxString& label,
+                const wxBitmap &bitmap,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = 0,
+                const wxValidator& val = wxDefaultValidator,
+                const wxString& name = wxT("wxCustomButton"));
+
+    bool GetValue() const { return m_down%2 != 0; }
+    void SetValue( bool depressed );
+
+    // Use combinations of wxCustomButton_Style(s)
+    long GetButtonStyle() const { return m_button_style; }
+    bool SetButtonStyle( long style );
+    
+    // Set the text label, wxEmptyString for none
+    void SetLabel( const wxString &label );
+
+    // set the bitmaps, ONLY this Label bitmap is used for calculating control size
+    //   all bitmaps will be centered accordingly in any case
+    //   call SetSet(GetBestSize()) if you change their size and want the control to resize appropriately
+    void SetBitmapLabel(const wxBitmap& bitmap);
+    void SetBitmapSelected(const wxBitmap& sel)      { m_bmpSelected = sel; CalcLayout(TRUE); };
+    void SetBitmapFocus(const wxBitmap& focus)       { m_bmpFocus = focus; CalcLayout(TRUE); };
+    void SetBitmapDisabled(const wxBitmap& disabled) { m_bmpDisabled = disabled; CalcLayout(TRUE); };
+    // wxBitmapButton compatibility
+    void SetLabel(const wxBitmap& bitmap)            { SetBitmapLabel(bitmap); }
+
+    // retrieve the bitmaps
+    const wxBitmap& GetBitmapLabel()    const { return m_bmpLabel;    }
+    const wxBitmap& GetBitmapSelected() const { return m_bmpSelected; }
+    const wxBitmap& GetBitmapFocus()    const { return m_bmpFocus;    }
+    const wxBitmap& GetBitmapDisabled() const { return m_bmpDisabled; }
+
+    // Creates a "disabled" bitmap by dithering it with the background colour
+    wxBitmap CreateBitmapDisabled(const wxBitmap &bitmap) const;
+    
+    // set/get the margins (in pixels) around the label and bitmap
+    //    if fit = TRUE then resize the button to fit
+    void SetMargins(const wxSize &margin, bool fit = FALSE); 
+    
+    // set/get the margins around the text label
+    //    the inter bitmap/label margin is the max of either margin, not the sum
+    void SetLabelMargin(const wxSize &margin, bool fit = FALSE);
+    wxSize GetLabelMargin() const { return m_labelMargin; }
+    // set/get the margins around the bitmap
+    //    the inter bitmap/label margin is the max of either margin, not the sum
+    void SetBitmapMargin(const wxSize &margin, bool fit = FALSE);
+    wxSize GetBitmapMargin() const { return m_bitmapMargin; }
+    
+    // can be used to activate the focused behavior (see MenuButton)
+    void SetFocused(bool focused) { m_focused = focused; Refresh(FALSE); }
+    bool GetFocused() const { return m_focused; }
+    
+protected:
+    void OnPaint(wxPaintEvent &event);
+    void Redraw();
+    virtual void Paint( wxDC &dc );
+
+    virtual wxSize DoGetBestSize() const;
+
+    virtual void SendEvent();
+    
+    void OnMouseEvents(wxMouseEvent &event);
+
+    void OnSize( wxSizeEvent &event );
+
+    virtual void CalcLayout(bool refresh);
+
+    long m_down;         // toggle state if m_down%2 then depressed
+    bool m_focused;     // mouse in window
+    long m_button_style;
+
+    // the bitmaps for various states
+    wxBitmap m_bmpLabel,
+             m_bmpSelected,
+             m_bmpFocus,
+             m_bmpDisabled;
+
+    // the margins around the label/bitmap
+    wxSize m_labelMargin,
+           m_bitmapMargin;
+
+    wxPoint m_bitmapPos,
+            m_labelPos;
+
+    wxTimer *m_timer;
+    
+    wxEventType m_eventType;     // store the mouse event type
+
+private:
+    void Init();
+    DECLARE_DYNAMIC_CLASS(wxCustomButton)
+    DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxMenuButton styles
+//-----------------------------------------------------------------------------
+
+#define wxMENUBUTTON_DROP_WIDTH  10
+#define wxMENUBUTTON_DROP_HEIGHT 22
+
+enum wxMenuButton_Styles
+{
+    wxMENUBUT_FLAT = wxCUSTBUT_FLAT
+};
+
+//-----------------------------------------------------------------------------
+// wxMenuButton
+//-----------------------------------------------------------------------------
+
+class wxMenuButton : public wxControl
+{
+public:
+
+    wxMenuButton() : wxControl() { Init(); }
+
+    // Use this constructor if you need one compatible with a wxBitmapButton
+    //   setup the button later with AssignMenu
+    wxMenuButton( wxWindow* parent, wxWindowID id,
+                  const wxBitmap &bitmap, 
+                  const wxPoint& pos = wxDefaultPosition,
+                  const wxSize& size = wxDefaultSize,
+                  long style = 0, 
+                                 const wxValidator& val = wxDefaultValidator,
+                  const wxString& name = wxT("wxMenuButton"))
+                  : wxControl()
+    {
+        Init();
+        Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name);
+    }
+
+    virtual ~wxMenuButton();
+        
+    bool Create( wxWindow* parent,
+                 wxWindowID id,
+                 const wxString &label,
+                 const wxBitmap &bitmap,
+                 const wxPoint& pos = wxDefaultPosition,
+                 const wxSize& size = wxDefaultSize,
+                 long style = wxNO_BORDER,
+                 const wxValidator& val = wxDefaultValidator,
+                 const wxString& name = wxT("wxMenuButton"));
+
+    // Gets the id of the first selected radio item or wxNOT_FOUND (-1) if none
+    int GetSelection() const;
+    
+    // This menu will be displayed when the dropdown button is pressed.
+    //   if static_menu is FALSE it will be deleted when the buttton is destroyed.
+    void AssignMenu(wxMenu *menu, bool static_menu = FALSE); 
+    
+    wxMenu *GetMenu() const { return m_menu; }
+    
+    // get a pointer to the label button, for turning it into a toggle perhaps
+    wxCustomButton *GetLabelButton() const { return m_labelButton; }
+    wxCustomButton *GetDropDownButton() const { return m_dropdownButton; }
+    
+    void SetToolTip(const wxString &tip);
+    void SetToolTip(wxToolTip *tip);
+    
+protected:
+    void OnButton(wxCommandEvent &event);    
+
+    virtual void DoSetSize(int x, int y, int width, int height,
+                           int sizeFlags = wxSIZE_AUTO);
+
+    virtual wxSize DoGetBestSize();
+
+// FIXME! - in MSW the radio items don't check themselves
+#ifdef __WXMSW__
+    void OnMenu( wxCommandEvent &event );
+#endif
+
+    wxCustomButton *m_labelButton;
+    wxCustomButton *m_dropdownButton;
+
+    wxMenu *m_menu;
+    bool m_menu_static;
+    long m_style;
+
+private:
+    void Init();
+    DECLARE_DYNAMIC_CLASS(wxMenuButton)
+    DECLARE_EVENT_TABLE()
+};
+
+//-----------------------------------------------------------------------------
+// wxMenuButtonEvents
+// 
+// EVT_MENUBUTTON_OPEN(id, fn) - menu is about to be opened, (dis)(en)able items
+//                               or call Veto() to stop menu from popping up
+//                               this is a wxNotifyEvent
+//-----------------------------------------------------------------------------
+
+BEGIN_DECLARE_EVENT_TYPES()
+    DECLARE_LOCAL_EVENT_TYPE( wxEVT_MENUBUTTON_OPEN, 0 )
+END_DECLARE_EVENT_TYPES()
+
+#define EVT_MENUBUTTON_OPEN(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_MENUBUTTON_OPEN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) & fn, (wxObject *) NULL ),
+
+#endif  // _WX_MENUBTN_H_
diff --git a/applications/osmo4_wx/osmo4.ico b/applications/osmo4_wx/osmo4.ico
new file mode 100644 (file)
index 0000000..36ff667
Binary files /dev/null and b/applications/osmo4_wx/osmo4.ico differ
diff --git a/applications/osmo4_wx/osmo4.xpm b/applications/osmo4_wx/osmo4.xpm
new file mode 100644 (file)
index 0000000..bec8e6a
--- /dev/null
@@ -0,0 +1,301 @@
+/* XPM */
+static const char * osmo4[] = {
+"32 32 266 2",
+"      c None",
+".     c #990909",
+"+     c #A10505",
+"@     c #AB0404",
+"#     c #AF0202",
+"$     c #B10303",
+"%     c #AE0202",
+"&     c #A90505",
+"*     c #A10606",
+"=     c #990E0E",
+"-     c #990D0D",
+";     c #A80303",
+">     c #BD0000",
+",     c #D40000",
+"'     c #DE0000",
+")     c #E20000",
+"!     c #E10000",
+"~     c #DC0000",
+"{     c #CD0000",
+"]     c #B80101",
+"^     c #A40909",
+"/     c #A20505",
+"(     c #BD0101",
+"_     c #E00000",
+":     c #CB0000",
+"<     c #A80000",
+"[     c #7E0101",
+"}     c #6B0202",
+"|     c #670202",
+"1     c #720202",
+"2     c #920000",
+"3     c #B70000",
+"4     c #D70000",
+"5     c #B80303",
+"6     c #9D0B0B",
+"7     c #980909",
+"8     c #B00202",
+"9     c #DB0000",
+"0     c #B50909",
+"a     c #8A1313",
+"b     c #1C0505",
+"c     c #070505",
+"d     c #080808",
+"e     c #0A0A0A",
+"f     c #090909",
+"g     c #070707",
+"h     c #0C0404",
+"i     c #5B1414",
+"j     c #A70F0F",
+"k     c #CC0303",
+"l     c #CC0000",
+"m     c #AB0505",
+"n     c #950D0D",
+"o     c #B60101",
+"p     c #DD0000",
+"q     c #CF0202",
+"r     c #9C1414",
+"s     c #141414",
+"t     c #0C0C0C",
+"u     c #0F0F0F",
+"v     c #111111",
+"w     c #101010",
+"x     c #0E0E0E",
+"y     c #B70707",
+"z     c #DF0000",
+"A     c #D50000",
+"B     c #A90606",
+"C     c #970E0E",
+"D     c #B30202",
+"E     c #C50505",
+"F     c #812121",
+"G     c #191919",
+"H     c #161616",
+"I     c #181818",
+"J     c #171717",
+"K     c #151515",
+"L     c #AF0A0A",
+"M     c #D70101",
+"N     c #D60000",
+"O     c #AD0606",
+"P     c #AA0303",
+"Q     c #DA0000",
+"R     c #C80505",
+"S     c #8E1E1E",
+"T     c #1D1D1D",
+"U     c #1F1F1F",
+"V     c #202020",
+"W     c #B00909",
+"X     c #CE0000",
+"Y     c #9F0A0A",
+"Z     c #9B0808",
+"`     c #D20000",
+" .    c #D80101",
+"..    c #8B1B1B",
+"+.    c #2D2D2D",
+"@.    c #272727",
+"#.    c #262626",
+"$.    c #252525",
+"%.    c #BB0606",
+"&.    c #BB0303",
+"*.    c #AF0303",
+"=.    c #AF0B0B",
+"-.    c #303030",
+";.    c #2B2B2B",
+">.    c #323232",
+",.    c #CD0202",
+"'.    c #A60A0A",
+").    c #9E0909",
+"!.    c #CF0000",
+"~.    c #CE0404",
+"{.    c #292929",
+"].    c #B10808",
+"^.    c #A70303",
+"/.    c #B60A0A",
+"(.    c #961010",
+"_.    c #B90000",
+":.    c #9C1212",
+"<.    c #1A1A1A",
+"[.    c #222222",
+"}.    c #1C1C1C",
+"|.    c #C20202",
+"1.    c #A30606",
+"2.    c #C60000",
+"3.    c #2A2A2A",
+"4.    c #3B3B3B",
+"5.    c #444444",
+"6.    c #434343",
+"7.    c #3A3A3A",
+"8.    c #1E1E1E",
+"9.    c #131313",
+"0.    c #BB0A0A",
+"a.    c #AD0707",
+"b.    c #9A1515",
+"c.    c #D30000",
+"d.    c #353535",
+"e.    c #484848",
+"f.    c #5F5F5F",
+"g.    c #6C6C6C",
+"h.    c #646464",
+"i.    c #565656",
+"j.    c #343434",
+"k.    c #212121",
+"l.    c #121212",
+"m.    c #B30505",
+"n.    c #B10404",
+"o.    c #9A1111",
+"p.    c #424242",
+"q.    c #555555",
+"r.    c #6B6B6B",
+"s.    c #757575",
+"t.    c #6E6E6E",
+"u.    c #606060",
+"v.    c #4E4E4E",
+"w.    c #3F3F3F",
+"x.    c #2C2C2C",
+"y.    c #B10909",
+"z.    c #B60707",
+"A.    c #9B1515",
+"B.    c #D00000",
+"C.    c #494949",
+"D.    c #595959",
+"E.    c #676767",
+"F.    c #696969",
+"G.    c #616161",
+"H.    c #525252",
+"I.    c #454545",
+"J.    c #B20707",
+"K.    c #363636",
+"L.    c #626262",
+"M.    c #5B5B5B",
+"N.    c #505050",
+"O.    c #282828",
+"P.    c #B80B0B",
+"Q.    c #AC0707",
+"R.    c #AA1111",
+"S.    c #0D0D0D",
+"T.    c #585858",
+"U.    c #545454",
+"V.    c #4B4B4B",
+"W.    c #BF0303",
+"X.    c #9F0B0B",
+"Y.    c #B90707",
+"Z.    c #242424",
+"`.    c #313131",
+" +    c #3E3E3E",
+".+    c #474747",
+"++    c #4D4D4D",
+"@+    c #4F4F4F",
+"#+    c #4C4C4C",
+"$+    c #3D3D3D",
+"%+    c #D90000",
+"&+    c #8E1010",
+"*+    c #A00808",
+"=+    c #D00303",
+"-+    c #3C3C3C",
+";+    c #0B0B0B",
+">+    c #AE0808",
+",+    c #C10101",
+"'+    c #BB0202",
+")+    c #BA0A0A",
+"!+    c #1B1B1B",
+"~+    c #2F2F2F",
+"{+    c #C10303",
+"]+    c #A10A0A",
+"^+    c #9F0707",
+"/+    c #D80000",
+"(+    c #BE0303",
+"_+    c #821C1C",
+":+    c #C20404",
+"<+    c #232323",
+"[+    c #A90C0C",
+"}+    c #970C0C",
+"|+    c #960E0E",
+"1+    c #BE0101",
+"2+    c #C60505",
+"3+    c #131212",
+"4+    c #B00B0B",
+"5+    c #CE0101",
+"6+    c #A80707",
+"7+    c #990B0B",
+"8+    c #C40404",
+"9+    c #AD0909",
+"0+    c #D00101",
+"a+    c #B00505",
+"b+    c #7B1C1C",
+"c+    c #960C0C",
+"d+    c #BC0202",
+"e+    c #BC0808",
+"f+    c #962525",
+"g+    c #482E2E",
+"h+    c #1E1616",
+"i+    c #141010",
+"j+    c #2F2020",
+"k+    c #703636",
+"l+    c #A81212",
+"m+    c #A90707",
+"n+    c #8E1313",
+"o+    c #D30606",
+"p+    c #B91E1E",
+"q+    c #901919",
+"r+    c #661010",
+"s+    c #540F0F",
+"t+    c #4F0D0D",
+"u+    c #5A0F0F",
+"v+    c #7A1515",
+"w+    c #A21E1E",
+"x+    c #C51212",
+"y+    c #D60101",
+"z+    c #980D0D",
+"A+    c #930C0C",
+"B+    c #B30404",
+"C+    c #C60202",
+"D+    c #7B1919",
+"E+    c #8C1515",
+"F+    c #9F0909",
+"G+    c #B20303",
+"H+    c #C30000",
+"I+    c #CA0000",
+"J+    c #C90000",
+"K+    c #BC0101",
+"L+    c #AA0505",
+"M+    c #8F1111",
+"N+    c #7F1E1E",
+"O+    c #732626",
+"P+    c #762A2A",
+"Q+    c #6E2828",
+"                                                                ",
+"                        . + @ # $ % & * =                       ",
+"                  - ; > , ' ) ) ! ) ! ~ { ] ^                   ",
+"                / ( ' _ : < [ } | 1 2 3 4 ) , 5 6               ",
+"            7 8 9 ' 0 a b c d e e f g h i j k ) l m             ",
+"          n o p q r     s t u v v w t x       y z A B           ",
+"        C D ) E F         G H I G J K           L M N O         ",
+"        P Q R S             T U U T V             W ' X Y       ",
+"      Z `  ...              +.@.#.$.                %.! &.      ",
+"      *.) =.                  -.;.>.                  ,.4 '.    ",
+"    ).!.~.                      {.                    ].) (     ",
+"    ^.z /.                      $.                      A ` (.  ",
+"    _.! :.              K K <.V [.}.K K                 |.z 1.  ",
+"    2.9               v <.3.4.5.6.7.;.8.9.J             0.) a.  ",
+"  b.!.c.            w }.d.e.f.g.h.i.5.j.k.l.            m._ n.  ",
+"  o.` !.          u J 3.p.q.r.s.t.u.v.w.x.T w           y._ z.  ",
+"  A.B.`           u k.j.C.D.E.g.F.G.H.I.j.$.9.l.        m._ J.  ",
+"    : 4         s v #.K.C.q.u.h.L.M.N.I.K.O.J x         P.) Q.  ",
+"    > z R.      S.9.#.d.5.v.i.D.T.U.V.p.j.{.G t         W._ X.  ",
+"    % ) Y.      l.9.Z.`. +.+++N.@+#+I.$+>.@.I t         { %+&+  ",
+"    *+, =+      x w V ;.K.$+6.I.I.p.-+K.;.[.H ;+      >+z ,+    ",
+"      '+_ )+    x S.!+Z.~+d.7.-+-+7.d.~+#.8.9.;+      {+_ ]+    ",
+"      ^+/+,       e s }.$.;.~+`.`.-.;.#.U J S.w     z.' (+_+    ",
+"        ] ) :+    t S.K T [.@.O.O.@.<+U I v ;+    [+` ~ }+      ",
+"        |+1+) 2+    e t 9.I }.T 8.}.G K u e 3+  4+5+' 6+        ",
+"          7+l ) 8+    e ;+u 9.K K 9.v S.f w   9+0+) a+b+        ",
+"            c+d+) N e+f+g+h+;+f e f i+j+k+l+|.~ /+m+            ",
+"              n+D N ! o+p+q+r+s+t+u+v+w+x+y+! X z+              ",
+"                  A+B+X _ ! ~ /+N %+' ) ~ C+Y D+                ",
+"                      E+F+G+H+I+l J+K+L+M+N+                    ",
+"                              O+P+Q+                            ",
+"                                                                "};
diff --git a/applications/osmo4_wx/playlist.xpm b/applications/osmo4_wx/playlist.xpm
new file mode 100644 (file)
index 0000000..cfad2dc
--- /dev/null
@@ -0,0 +1,158 @@
+/* XPM */
+static const char* pl_open[] = {
+"16 16 5 1",
+"  c #000000",
+"! c #808000",
+"# c #C0C0C0",
+"$ c #FFFF00",
+"% c #FFFFFF",
+"################",
+"################",
+"#########   ####",
+"######## ### # #",
+"#############  #",
+"#   ########   #",
+" %$%       #####",
+" $%$%$%$%$ #####",
+" %$%$%$%$% #####",
+" $%$%          #",
+" %$% !!!!!!!!! #",
+" $% !!!!!!!!! ##",
+" % !!!!!!!!! ###",
+"  !!!!!!!!! ####",
+"           #####",
+"################"};
+
+/* XPM */
+static const char* pl_save[] = {
+"16 16 3 1",
+"  c #000000",
+"! c #808000",
+"# c #C0C0C0",
+"################",
+"#              #",
+"# ! ######## # #",
+"# ! ########   #",
+"# ! ######## ! #",
+"# ! ######## ! #",
+"# ! ######## ! #",
+"# ! ######## ! #",
+"# !!        !! #",
+"# !!!!!!!!!!!! #",
+"# !!         ! #",
+"# !!      ## ! #",
+"# !!      ## ! #",
+"# !!      ## ! #",
+"##             #",
+"################"};
+
+/* XPM */
+static const char* pl_add[] = {
+"16 16 2 1",
+"  c #000000",
+"! c #C0C0C0",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!           !!!",
+"!!           !!!",
+"!!           !!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* pl_rem[] = {
+"16 16 2 1",
+"  c #000000",
+"! c #C0C0C0",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!           !!!",
+"!!           !!!",
+"!!           !!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* pl_up[] = {
+"16 16 2 1",
+"  c #000000",
+"! c #C0C0C0",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!! !!!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!     !!!!!!",
+"!!!!       !!!!!",
+"!!!         !!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* pl_down[] = {
+"16 16 2 1",
+"  c #000000",
+"! c #C0C0C0",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!         !!!!",
+"!!!!       !!!!!",
+"!!!!!     !!!!!!",
+"!!!!!!   !!!!!!!",
+"!!!!!!! !!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* pl_sort[] = {
+"16 16 2 1",
+"  c #000000",
+"! c #C0C0C0",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!! !!!!! !!!!!",
+"!!!! !!!!   !!!!",
+"!!!! !!!     !!!",
+"!!!! !!!!! !!!!!",
+"!!!! !!!!! !!!!!",
+"!!!! !!!!! !!!!!",
+"!!!! !!!!! !!!!!",
+"!!     !!! !!!!!",
+"!!!   !!!! !!!!!",
+"!!!! !!!!! !!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
diff --git a/applications/osmo4_wx/resource.h b/applications/osmo4_wx/resource.h
new file mode 100644 (file)
index 0000000..ace6dd4
--- /dev/null
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by wxOsmo4.rc
+//
+#define IDI_OSMO_ICON                       101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        104
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/applications/osmo4_wx/toolbar.xpm b/applications/osmo4_wx/toolbar.xpm
new file mode 100644 (file)
index 0000000..887d59e
--- /dev/null
@@ -0,0 +1,254 @@
+/* XPM */
+static const char* tool_open_file[] = {
+"16 16 2 1",
+"  c #000000",
+"! c none",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!  !!!!!!!",
+"!!!!!!    !!!!!!",
+"!!!!!      !!!!!",
+"!!!!        !!!!",
+"!!!          !!!",
+"!!            !!",
+"!!            !!",
+"!!!!!!!!!!!!!!!!",
+"!!            !!",
+"!!            !!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* tool_prev[] = {
+"16 16 3 1",
+"  c #000000",
+"! c none",
+"# c #FF0000",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!  !!",
+"!!!!!!!!!!    !!",
+"!!!!!!!!   ## !!",
+"!!!!!!   #### !!",
+"!!!!   ###### !!",
+"!!!  ######## !!",
+"!!!!    ##### !!",
+"!!!!!!    ### !!",
+"!!!!!!!!    # !!",
+"!!!!!!!!!!    !!",
+"!!!!!!!!!!!!  !!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* tool_next[] = {
+"16 16 3 1",
+"  c #000000",
+"! c none",
+"# c #FF0000",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!  !!!!!!!!!!!!",
+"!!    !!!!!!!!!!",
+"!! ##   !!!!!!!!",
+"!! ####   !!!!!!",
+"!! ######   !!!!",
+"!! ########  !!!",
+"!! ######   !!!!",
+"!! ####   !!!!!!",
+"!! ##   !!!!!!!!",
+"!!    !!!!!!!!!!",
+"!!  !!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* tool_play[] = {
+"16 16 2 1",
+"  c #000000",
+"! c none",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!  !!!!!!!!!!!!",
+"!!    !!!!!!!!!!",
+"!!      !!!!!!!!",
+"!!        !!!!!!",
+"!!          !!!!",
+"!!            !!",
+"!!          !!!!",
+"!!        !!!!!!",
+"!!      !!!!!!!!",
+"!!    !!!!!!!!!!",
+"!!  !!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* tool_pause[] = {
+"16 16 3 1",
+"  c #000000",
+"! c #808080",
+"# c none",
+"################",
+"################",
+"################",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"###   !##!   ###",
+"################",
+"################"};
+
+
+/* XPM */
+static const char* tool_step[] = {
+"16 16 2 1",
+"  c #000000",
+"! c none",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!   !!!!!!!!!!!",
+"!!     !!!!!!!!!",
+"!!       !!!!!!!",
+"!!!!       !!!!!",
+"!!!!!!       !!!",
+"!!!!!!!!      !!",
+"!!!!!!       !!!",
+"!!!!       !!!!!",
+"!!       !!!!!!!",
+"!!     !!!!!!!!!",
+"!!   !!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+
+/* XPM */
+static const char* tool_stop[] = {
+"16 16 2 1",
+"  c #000000",
+"! c none",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!            !!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"};
+
+/* XPM */
+static const char* tool_info[] = {
+"16 16 3 1",
+"  c #000000",
+"! c none",
+"# c #0000FF",
+"!!!!!!!!!!!!!!!!",
+"!!!!!      !!!!!",
+"!!!          !!!",
+"!!   ######   !!",
+"!  ####!!####  !",
+"!  ####!!####  !",
+"  ############  ",
+"  #####!!#####  ",
+" ######!!#####  ",
+"  #####!!#####  ",
+"  #####!!#####  ",
+"!  ####!!####  !",
+"!  #####!!###  !",
+"!!   ######   !!",
+"!!!          !!!",
+"!!!!!      !!!!!"};
+
+
+/* XPM */
+static const char* tool_config[] = {
+"16 16 3 1",
+"  c #000000",
+"! c #808080",
+"# c none",
+"################",
+"################",
+"##   ##   ######",
+"## ## # ## #  ##",
+"## ##          #",
+"## #!# ####### #",
+"## # #!# ## ## #",
+"## #!# #!# ! # #",
+"## # #!# ## ## #",
+"## #!# #!##### #",
+"## # #!# ## ## #",
+"## #!# #!# ! # #",
+"## # #!# ## ## #",
+"##             #",
+"################",
+"################"};
+
+/* XPM */
+static const char* tool_sw_2d[] = {
+"16 16 4 1",
+"      c #FF0000",
+".     c #C0C0C0",
+"+     c #0000FF",
+"@     c #000000",
+" .............. ",
+". ..++..++++.. .",
+".. +..+..+..+ ..",
+"... ..+..+.. ...",
+".... +...+. +...",
+"...+. +..+ .+...",
+"...+++ .+ ++....",
+".......  .......",
+"....@@ @@ @.....",
+"...@. .@.@ .....",
+"...@ ....@. ....",
+"... ..@@.@.. ...",
+".. @...@.@.@. ..",
+". ..@@@@@@@@.. .",
+" .............. ",
+"................"};
+
+/* XPM */
+static const char* tool_sw_3d[] = {
+"16 16 4 1",
+"      c #FFFFFF",
+".     c #C0C0C0",
+"+     c #0000FF",
+"@     c #000000",
+"                ",
+"................",
+"....++..++++....",
+"...+..+..+..+...",
+"......+..+..+...",
+"....++...+..+...",
+"...+..+..+..+...",
+"...++++.++++....",
+"................",
+"....@@@@@@@.....",
+"...@...@.@......",
+"...@.....@......",
+"...@..@@.@......",
+"...@...@.@.@....",
+"....@@@@@@@@....",
+"................"};
+
diff --git a/applications/osmo4_wx/wxGPACControl.cpp b/applications/osmo4_wx/wxGPACControl.cpp
new file mode 100644 (file)
index 0000000..7d16802
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#include "wxOsmo4.h"
+#include <gpac/options.h>
+#include <gpac/modules/codec.h>
+#include <gpac/modules/raster2d.h>
+#include <gpac/modules/font.h>
+#include <gpac/modules/audio_out.h>
+#include <gpac/modules/video_out.h>
+
+#include <gpac/iso639.h>
+
+#include "wxGPACControl.h"
+
+
+#define NUM_RATES 11
+static const char *BIFSRates[11] = 
+{
+       "5.0",
+       "7.5",
+       "10.0",
+       "12.5",
+       "15.0",
+       "24.0",
+       "25.0",
+       "30.0",
+       "50.0",
+       "60.0",
+       "100.0"
+};
+
+void wxGPACControl::SetYUVLabel()
+{
+       u32 yuv_format = gf_term_get_option(m_pApp->m_term, GF_OPT_YUV_FORMAT);
+       if (!yuv_format) {
+               m_yuvtxt->SetLabel(wxT("(No YUV used)"));
+       } else {
+               char str[100];
+               sprintf(str, "(%s used)", gf_4cc_to_str(yuv_format));
+               m_yuvtxt->SetLabel(wxString(str, wxConvUTF8) );
+       }
+}
+
+wxGPACControl::wxGPACControl(wxWindow *parent)
+             : wxDialog(parent, -1, wxString(wxT("GPAC Control Panel")))
+{
+       const char *sOpt;
+       SetSize(320, 240);
+       u32 i;
+       wxBoxSizer *bs;
+       Centre();
+
+       m_pApp = (wxOsmo4Frame *)parent;
+
+       s_main = new wxBoxSizer(wxVERTICAL);
+
+       s_header = new wxBoxSizer(wxHORIZONTAL);
+       //s_header->Add(new wxStaticText(this, 0, wxT("Category"), wxDefaultPosition, wxSize(60, 20)), wxALIGN_CENTER);
+       m_select = new wxComboBox(this, ID_SELECT, wxT(""), wxDefaultPosition, wxSize(120, 30), 0, NULL, wxCB_READONLY);
+       s_header->Add(m_select, 2, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_header->Add( new wxButton(this, ID_APPLY, wxT("Apply"), wxDefaultPosition, 
+#ifdef WIN32
+               wxSize(40, 20)
+#else
+               wxSize(40, 30)
+#endif
+               ),
+               1, wxALIGN_TOP|wxALIGN_RIGHT|wxADJUST_MINSIZE);
+       s_main->Add(s_header, 0, wxEXPAND, 0);
+               
+       /*general section*/
+       s_general = new wxBoxSizer(wxVERTICAL);
+       m_loop = new wxCheckBox(this, 0, wxT("Loop at End"), wxPoint(10, 40), wxSize(140, 20));
+       s_general->Add(m_loop);
+       m_lookforsubs = new wxCheckBox(this, 0, wxT("Look for Subtitles"), wxPoint(180, 40), wxSize(140, 20));
+       s_general->Add(m_lookforsubs);
+       m_noconsole = new wxCheckBox(this, 0, wxT("Disable console messages"), wxPoint(10, 80), wxSize(180, 20));
+       s_general->Add(m_noconsole);
+       m_viewxmt = new wxCheckBox(this, 0, wxT("View graph in XMT-A format"), wxPoint(10, 120), wxSize(180, 20));
+       s_general->Add(m_viewxmt);
+       s_main->Add(s_general, 0, wxEXPAND, 0);
+
+       /*MPEG-4 systems*/
+       s_mpeg4 = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Prefered Stream Language")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_lang = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_lang, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_mpeg4->Add(bs, 0, wxALL|wxEXPAND, 2);
+
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Decoder Threading Mode")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_thread = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_thread, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_mpeg4->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_bifsalwaysdrawn = new wxCheckBox(this, 0, wxT("Always draw late BIFS frames"));
+       s_mpeg4->Add(m_bifsalwaysdrawn);
+       m_singletime = new wxCheckBox(this, 0, wxT("Force Single Timeline"));
+       s_mpeg4->Add(m_singletime);
+       s_main->Add(s_mpeg4, 0, wxEXPAND, 0);
+
+       /*media decoders*/
+       s_mdec = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Prefered Audio Output")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_decaudio = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_decaudio, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_mdec->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Prefered Video Output")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_decvideo = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_decvideo, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_mdec->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_mdec, 0, wxEXPAND, 0);
+
+       /*Rendering*/
+       s_rend = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Target Frame Rate")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_fps = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_fps, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Anti-Aliasing")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_aa = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_aa, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Graphics Driver")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_graph = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_graph, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_draw_bounds = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(new wxStaticText(this, 0, wxT("Bounds")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       bs->Add(m_draw_bounds, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_fast = new wxCheckBox(this, 0, wxT("Fast Rendering"));
+       m_force_size = new wxCheckBox(this, 0, wxT("Force Scene Size"));
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(m_fast, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       bs->Add(m_force_size, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_use3D = new wxCheckBox(this, 0, wxT("Use 3D Renderer"));
+       s_rend->Add(m_use3D, 0, wxALL|wxEXPAND, 2);
+       m_bWas3D = m_use3D->GetValue();
+       s_main->Add(s_rend, 0, wxEXPAND, 0);
+       
+       /*Render 2D*/
+       s_rend2d = new wxBoxSizer(wxVERTICAL);
+       m_direct = new wxCheckBox(this, 0, wxT("Direct Rendering"));
+       s_rend2d->Add(m_direct, 0, wxALL|wxEXPAND, 2);
+       m_scalable = new wxCheckBox(this, 0, wxT("Scalable Zoom"));
+       s_rend2d->Add(m_scalable, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_noyuv = new wxCheckBox(this, 0, wxT("Disable YUV hardware"));
+       bs->Add(m_noyuv, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_yuvtxt = new wxStaticText(this, 0, wxT("(No YUV used)"), wxDefaultPosition, wxSize(60, 20), wxALIGN_LEFT);
+       bs->Add(m_yuvtxt, wxALIGN_CENTER|wxADJUST_MINSIZE);
+       s_rend2d->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_rend2d, 0, wxEXPAND, 0);
+
+       /*Render 3D*/
+       s_rend3d = new wxBoxSizer(wxVERTICAL);
+       m_raster_outlines = new wxCheckBox(this, 0, wxT("Use OpenGL Raster outlines"));
+       s_rend3d->Add(m_raster_outlines, 0, wxALL|wxEXPAND, 2);
+       m_polyaa = new wxCheckBox(this, 0, wxT("Enable polygon anti-aliasing"));
+       s_rend3d->Add(m_polyaa, 0, wxALL|wxEXPAND, 2);
+       m_nobackcull = new wxCheckBox(this, 0, wxT("Disable backface culling"));
+       s_rend3d->Add(m_nobackcull, 0, wxALL|wxEXPAND, 2);
+       
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Wireframe mode")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_wire = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_wire, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend3d->Add(bs, 0, wxALL|wxEXPAND, 2);
+       
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Draw Normals")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_normals = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_normals, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rend3d->Add(bs, 0, wxALL|wxEXPAND, 2);
+
+       m_emulpow2 = new wxCheckBox(this, 0, wxT("Emulate power-of-two textures for video"));
+       s_rend3d->Add(m_emulpow2, 0, wxALL|wxEXPAND, 2);
+       m_norectext = new wxCheckBox(this, 0, wxT("Disable rectangular texture extensions"));
+       s_rend3d->Add(m_norectext, 0, wxALL|wxEXPAND, 2);
+       m_copypixels = new wxCheckBox(this, 0, wxT("Bitmap node uses direct pixel copy"));
+       s_rend3d->Add(m_copypixels, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_rend3d, 0, wxEXPAND, 0);
+
+       /*video*/
+       s_video = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Video Driver")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_video = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_video , wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_video->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_switchres = new wxCheckBox(this, 0, wxT("Change video resolution in fullscreen"));
+       s_video->Add(m_switchres, 0, wxALL|wxEXPAND, 2);
+       m_usehwmem = new wxCheckBox(this, 0, wxT("Use hardware memory in 2D mode"));
+       s_video->Add(m_usehwmem, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_video, 0, wxEXPAND, 0);
+       
+
+       /*audio*/
+       s_audio = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Audio Driver")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_audio = new wxComboBox(this, ID_AUDIO_DRIVER, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_audio, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_audio->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_forcecfg = new wxCheckBox(this, ID_FORCE_AUDIO, wxT("Force Audio Config"));
+       m_forcecfg->SetValue(1);
+       s_audio->Add(m_forcecfg, 0, wxALL|wxEXPAND, 2);
+
+
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Number of buffers")), wxALIGN_CENTER|wxADJUST_MINSIZE);
+       m_nbbuf = new wxSpinCtrl(this, -1, wxT(""), wxDefaultPosition, wxSize(20, 20), wxSP_WRAP | wxSP_ARROW_KEYS, 1, 30, 15);
+       m_nbbuf->SetValue(8);
+       bs->Add(m_nbbuf, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_audio->Add(bs, 0, wxALL|wxEXPAND, 2);
+
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Total length in ms")), wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_buflen = new wxSpinCtrl(this, -1, wxT(""), wxDefaultPosition, wxSize(20, 20), wxSP_WRAP | wxSP_ARROW_KEYS, 1, 1000);
+       m_buflen->SetValue(400);
+       bs->Add(m_buflen, wxALIGN_CENTER | wxADJUST_MINSIZE|wxLEFT,10);
+       s_audio->Add(bs, 0, wxALL|wxEXPAND, 2);
+
+       m_noresync = new wxCheckBox(this, -1, wxT("Disable Resynchronization"));
+       s_audio->Add(m_noresync);
+       m_nomulitch = new wxCheckBox(this, -1, wxT("Disable Multichannel"));
+       s_audio->Add(m_nomulitch);
+#ifdef WIN32
+       m_notifs = new wxCheckBox(this, -1, wxT("Disable DirectSound Notifications"));
+       s_audio->Add(m_notifs);
+#endif
+       s_main->Add(s_audio, 0, wxEXPAND, 0);
+       
+       /*font*/
+       s_font = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Font Engine")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_font = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_font, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_font->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("System Font Directory")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_fontdir = new wxButton(this, ID_FONT_DIR, wxT("..."), wxDefaultPosition, wxDefaultSize);
+       bs->Add(m_fontdir, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_font->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Text Texturing Mode")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_texturemode = new wxComboBox(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
+       bs->Add(m_texturemode, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_font->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_font, 0, wxEXPAND, 0);
+
+       /*download*/
+       s_dnld = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Cache Directory")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_cachedir = new wxButton(this, ID_CACHE_DIR, wxT("..."));
+       bs->Add(m_cachedir, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_dnld->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_cleancache = new wxCheckBox(this, -1, wxT("Remove temp files on exit"));
+       s_dnld->Add(m_cleancache);
+       m_restartcache = new wxCheckBox(this, -1, wxT("Always redownload incomplete cached files"));
+       s_dnld->Add(m_restartcache);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_progressive = new wxCheckBox(this, ID_PROGRESSIVE, wxT("XML progressive load"));
+       bs->Add(m_progressive, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_sax_duration = new wxTextCtrl(this, 0, wxT(""), wxPoint(10, 120), wxSize(60, 20));
+       bs->Add(m_sax_duration, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       bs->Add(new wxStaticText(this, 0, wxT("max load slice (ms)")), wxADJUST_MINSIZE | wxALIGN_CENTER);
+       s_dnld->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_use_proxy = new wxCheckBox(this, ID_USE_PROXY, wxT("Use proxy"));
+       bs->Add(m_use_proxy, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_proxy_name = new wxTextCtrl(this, 0, wxT(""), wxPoint(10, 120), wxSize(60, 20));
+       bs->Add(m_proxy_name, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_dnld->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_dnld, 0, wxEXPAND, 0);
+
+       /*streaming*/
+       s_stream = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Default RTSP port")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_port = new wxComboBox(this, ID_RTSP_PORT, wxT(""), wxPoint(160, 40), wxSize(140, 30), 0, NULL, wxCB_READONLY);
+       bs->Add(m_port, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_stream->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_rtsp = new wxCheckBox(this, ID_RTP_OVER_RTSP, wxT("RTP over RTSP"), wxPoint(10, 80), wxSize(140, 20));
+       m_reorder = new wxCheckBox(this, -1, wxT("use RTP reordering"), wxPoint(160, 80), wxSize(130, 20));
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(m_rtsp, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       bs->Add(m_reorder, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_stream->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_timeout = new wxTextCtrl(this, 0, wxT(""), wxPoint(10, 120), wxSize(60, 20));
+       bs->Add(new wxStaticText(this, 0, wxT("Control Timeout (ms): ")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       bs->Add(m_timeout, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_stream->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_buffer = new wxTextCtrl(this, 0, wxT(""), wxPoint(10, 150), wxSize(60, 20));
+       bs->Add(new wxStaticText(this, 0, wxT("Media Buffering (ms): ")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       bs->Add(m_buffer, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_stream->Add(bs, 0, wxALL|wxEXPAND, 2);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_dorebuffer = new wxCheckBox(this, ID_RTSP_REBUFFER, wxT("Rebuffer if below"));
+       bs->Add(m_dorebuffer, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_rebuffer = new wxTextCtrl(this, 0, wxT(""), wxPoint(200, 180), wxSize(60, 20));
+       bs->Add(m_rebuffer, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       m_rebuffer->Disable();
+       s_stream->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_stream, 0, wxEXPAND, 0);
+
+       /*streaming cache*/
+       s_rec = new wxBoxSizer(wxVERTICAL);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       bs->Add(new wxStaticText(this, 0, wxT("Record To: ")), wxALIGN_CENTER | wxADJUST_MINSIZE | wxALIGN_RIGHT);
+       m_recdir = new wxButton(this, ID_RECORD_DIR, wxT("..."));
+       bs->Add(m_recdir, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rec->Add(bs, 0, wxALL|wxEXPAND, 2);
+       m_overwrite = new wxCheckBox(this, -1, wxT("Overwrite existing files"));
+       s_rec->Add(m_overwrite);
+       bs = new wxBoxSizer(wxHORIZONTAL);
+       m_usename = new wxCheckBox(this, ID_USE_FILENAME, wxT("Use filename"));
+       m_recfile = new wxTextCtrl(this, 0, wxT(""));
+       bs->Add(m_usename, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       bs->Add(m_recfile, wxALIGN_CENTER | wxADJUST_MINSIZE);
+       s_rec->Add(bs, 0, wxALL|wxEXPAND, 2);
+       s_main->Add(s_rec, 0, wxEXPAND, 0);
+
+       /*load options*/
+       GF_Config *cfg = m_pApp->m_user.config;
+       /*general*/
+       sOpt = gf_cfg_get_key(cfg, "General", "Loop");
+       m_loop->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "General", "LookForSubtitles");
+       m_lookforsubs->SetValue((sOpt && !stricmp(sOpt, "no")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "General", "ConsoleOff");
+       m_noconsole->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "General", "ViewXMT");
+       m_viewxmt->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+
+       /*systems config*/
+       sOpt = gf_cfg_get_key(cfg, "Systems", "Language3CC");
+       if (!sOpt) sOpt = "eng";
+       u32 select = 0;
+       i=0;
+       while (GF_ISO639_Lang[i]) {
+               /*only use common languages (having both 2- and 3-char code names)*/
+               if (GF_ISO639_Lang[i+2][0]) {
+                       m_lang->Append(wxString(GF_ISO639_Lang[i], wxConvUTF8) );
+                       if (sOpt && !stricmp(sOpt, GF_ISO639_Lang[i+1])) select = m_lang->GetCount() - 1;
+               }
+               i+=3;
+       }
+       m_lang->SetSelection(select);
+       sOpt = gf_cfg_get_key(cfg, "Systems", "ThreadingPolicy");
+       select = 0;
+       m_thread->Append(wxT("Single Thread"));
+       m_thread->Append(wxT("Mutli Thread"));
+       if (sOpt && !stricmp(sOpt, "Multi")) select = 1;
+       m_thread->Append(wxT("Free"));
+       if (sOpt && !stricmp(sOpt, "Free")) select = 2;
+       m_thread->SetSelection(select);
+       sOpt = gf_cfg_get_key(cfg, "Systems", "ForceSingleClock");
+       m_singletime->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Systems", "AlwaysDrawBIFS");
+       m_bifsalwaysdrawn->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+
+
+       /*audio dec enum*/
+       sOpt = gf_cfg_get_key(cfg, "Systems", "DefAudioDec");
+       u32 count = gf_modules_get_count(m_pApp->m_user.modules);
+       GF_BaseDecoder *ifc_d;
+       select = 0;
+       s32 to_sel = 0;
+       for (i=0; i<count; i++) {
+               ifc_d = (GF_BaseDecoder *) gf_modules_load_interface(m_pApp->m_user.modules, i, GF_MEDIA_DECODER_INTERFACE);
+               if (!ifc_d) continue;
+               if (ifc_d->CanHandleStream(ifc_d, GF_STREAM_AUDIO, NULL, 0)) {
+                       if (sOpt && !stricmp(ifc_d->module_name, sOpt)) select = to_sel;
+                       m_decaudio->Append(wxString(ifc_d->module_name, wxConvUTF8) );
+                       to_sel++;
+               }
+               gf_modules_close_interface((GF_BaseInterface *) ifc_d);
+       }
+       m_decaudio->SetSelection(select);
+
+       /*video dec enum*/
+       sOpt = gf_cfg_get_key(cfg, "Systems", "DefVideoDec");
+       select = to_sel = 0;
+       for (i=0; i<count; i++) {
+               ifc_d = (GF_BaseDecoder *) gf_modules_load_interface(m_pApp->m_user.modules, i, GF_MEDIA_DECODER_INTERFACE);
+               if (!ifc_d) continue;
+               if (ifc_d->CanHandleStream(ifc_d, GF_STREAM_VISUAL, NULL, 0)) {
+                       if (sOpt && !stricmp(ifc_d->module_name, sOpt)) select = to_sel;
+                       m_decvideo->Append(wxString(ifc_d->module_name, wxConvUTF8) );
+                       to_sel++;
+               }
+               gf_modules_close_interface((GF_BaseInterface *) ifc_d);
+       }
+       m_decvideo->SetSelection(select);
+
+       /*rendering FIXME*/
+       m_bWas3D = 0;
+       m_use3D->SetValue(m_bWas3D ? 1 : 0);
+
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "ForceSceneSize");
+       m_force_size->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "FrameRate");
+       if (!sOpt) sOpt = "30.0";
+       select = 0;
+       for (i = 0; i<NUM_RATES; i++) {
+               m_fps->Append(wxString(BIFSRates[i], wxConvUTF8) );
+               if (sOpt && !stricmp(sOpt, BIFSRates[i]) ) select = i;
+       }
+       m_fps->SetSelection(select);
+       
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "HighSpeed");
+       m_fast->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "AntiAlias");
+       m_aa->Append(wxT("None"));
+       m_aa->Append(wxT("Text only"));
+       m_aa->Append(wxT("Complete"));
+       select = 2;
+       if (sOpt && !stricmp(sOpt, "Text")) select = 1;
+       else if (sOpt && !stricmp(sOpt, "None")) select = 0;
+       m_aa->SetSelection(select);
+
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "BoundingVolume");
+       m_draw_bounds->Append(wxT("None"));
+       m_draw_bounds->Append(wxT("Box/Rect"));
+       m_draw_bounds->Append(wxT("AABB Tree"));
+       select = 0;
+       if (sOpt && !stricmp(sOpt, "Box")) select = 1;
+       else if (sOpt && !stricmp(sOpt, "AABB")) select = 2;
+       m_draw_bounds->SetSelection(select);
+
+       /*render2d*/
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "DirectDraw");
+       m_direct->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "ScalableZoom");
+       m_scalable->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "DisableYUV");
+       m_noyuv->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       SetYUVLabel();
+
+       /*graphics driver enum*/
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "Raster2D");
+       GF_BaseInterface *ifce;
+       select = to_sel = 0;
+       for (i=0; i<count; i++) {
+               ifce = gf_modules_load_interface(m_pApp->m_user.modules, i, GF_RASTER_2D_INTERFACE);
+               if (!ifce) continue;
+               if (sOpt && !stricmp(((GF_BaseInterface *)ifce)->module_name, sOpt)) select = to_sel;
+               m_graph->Append(wxString(((GF_BaseInterface *)ifce)->module_name, wxConvUTF8) );
+               gf_modules_close_interface(ifce);
+               to_sel++;
+       }
+       m_graph->SetSelection(select);
+
+       /*render3d*/
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "RasterOutlines");
+       m_raster_outlines->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "EmulatePOW2");
+       m_emulpow2->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "PolygonAA");
+       m_polyaa->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "BackFaceCulling");
+       m_nobackcull->SetValue((sOpt && !stricmp(sOpt, "Off")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "Wireframe");
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "BitmapCopyPixels");
+       m_copypixels->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "DisableRectExt");
+       m_norectext->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       m_wire->Append(wxT("No Wireframe"));
+       m_wire->Append(wxT("Wireframe Only"));
+       m_wire->Append(wxT("Solid and Wireframe"));
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "Wireframe");
+       if (sOpt && !stricmp(sOpt, "WireOnly")) m_wire->SetSelection(1);
+       else if (sOpt && !stricmp(sOpt, "WireOnSolid")) m_wire->SetSelection(2);
+       else m_wire->SetSelection(0);
+       m_normals->Append(wxT("Never"));
+       m_normals->Append(wxT("Per Face"));
+       m_normals->Append(wxT("Per Vertex"));
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "DrawNormals");
+       if (sOpt && !stricmp(sOpt, "PerFace")) m_normals->SetSelection(1);
+       else if (sOpt && !stricmp(sOpt, "PerVertex")) m_normals->SetSelection(2);
+       else m_normals->SetSelection(0);
+
+       /*video*/
+       sOpt = gf_cfg_get_key(cfg, "Video", "SwitchResolution");
+       m_switchres->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Video", "UseHardwareMemory");
+       m_usehwmem->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Video", "DriverName");
+       select = to_sel = 0;
+       for (i=0; i<count; i++) {
+               ifce = gf_modules_load_interface(m_pApp->m_user.modules, i, GF_VIDEO_OUTPUT_INTERFACE);
+               if (!ifce) continue;
+               if (sOpt && !stricmp(((GF_BaseInterface *)ifce)->module_name, sOpt)) select = to_sel;
+               m_video->Append(wxString(((GF_BaseInterface *)ifce)->module_name, wxConvUTF8) );
+               gf_modules_close_interface(ifce);
+               to_sel++;
+       }
+       m_video->SetSelection(select);
+
+       /*audio*/
+       sOpt = gf_cfg_get_key(cfg, "Audio", "ForceConfig");
+       m_forcecfg->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Audio", "NumBuffers");
+       m_nbbuf->SetValue( sOpt ? wxString(sOpt, wxConvUTF8) : wxT("2"));
+       sOpt = gf_cfg_get_key(cfg, "Audio", "TotalDuration");
+       m_buflen->SetValue( sOpt ? wxString(sOpt, wxConvUTF8) : wxT("120"));
+       wxCommandEvent event;
+       ForceAudio(event);
+       sOpt = gf_cfg_get_key(cfg, "Audio", "NoResync");
+       m_noresync->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Audio", "DisableMultiChannel");
+       m_nomulitch->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+
+       /*driver enum*/
+       sOpt = gf_cfg_get_key(cfg, "Audio", "DriverName");
+       select = to_sel = 0;
+       for (i=0; i<count; i++) {
+               ifce = gf_modules_load_interface(m_pApp->m_user.modules, i, GF_AUDIO_OUTPUT_INTERFACE);
+               if (!ifce) continue;
+               if (sOpt && !stricmp(((GF_BaseInterface *)ifce)->module_name, sOpt)) select = to_sel;
+               m_audio->Append(wxString(((GF_BaseInterface *)ifce)->module_name, wxConvUTF8) );
+               gf_modules_close_interface(ifce);
+               to_sel++;
+       }
+       m_audio->SetSelection(select);
+#ifdef WIN32
+       sOpt = gf_cfg_get_key(cfg, "Audio", "DisableNotification");
+       m_notifs->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       wxCommandEvent audevt;
+       OnSetAudioDriver(audevt);
+#endif
+
+       /*font*/
+       sOpt = gf_cfg_get_key(cfg, "FontEngine", "FontReader");
+       to_sel = select = 0;
+       for (i=0; i<count; i++) {
+               ifce = gf_modules_load_interface(m_pApp->m_user.modules, i, GF_FONT_READER_INTERFACE);
+               if (!ifce) continue;
+               if (sOpt && !stricmp(((GF_BaseInterface *)ifce)->module_name, sOpt)) select = to_sel;
+               m_font->Append(wxString(((GF_BaseInterface *)ifce)->module_name, wxConvUTF8) );
+               gf_modules_close_interface(ifce);
+               to_sel++;
+       }
+       m_font->SetSelection(select);
+       sOpt = gf_cfg_get_key(cfg, "FontEngine", "FontDirectory");
+       if (sOpt) m_fontdir->SetLabel(wxString(sOpt, wxConvUTF8) );
+       sOpt = gf_cfg_get_key(cfg, "Compositor", "TextureTextMode");
+       m_texturemode->Append(wxT("Default"));
+       m_texturemode->Append(wxT("Never"));
+       m_texturemode->Append(wxT("Always"));
+       if (sOpt && !stricmp(sOpt, "Always")) m_texturemode->SetSelection(2);
+       else if (sOpt && !stricmp(sOpt, "3D")) m_texturemode->SetSelection(1);
+       else m_texturemode->SetSelection(0);
+
+       /*downloader*/
+       sOpt = gf_cfg_get_key(cfg, "General", "CacheDirectory");
+       if (sOpt) m_cachedir->SetLabel(wxString(sOpt, wxConvUTF8) );
+       sOpt = gf_cfg_get_key(cfg, "Downloader", "CleanCache");
+       m_cleancache->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "Downloader", "RestartFiles");
+       m_restartcache->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "SAXLoader", "Progressive");
+       m_progressive->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       sOpt = gf_cfg_get_key(cfg, "SAXLoader", "MaxDuration");
+       m_sax_duration->SetValue(sOpt ? wxString(sOpt, wxConvUTF8) : wxT("30"));
+       if (! m_progressive->GetValue()) m_sax_duration->Enable(0);
+
+       sOpt = gf_cfg_get_key(cfg, "HTTPProxy", "Enabled");
+       m_use_proxy->SetValue( (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0);
+       char szProxy[GF_MAX_PATH];
+       strcpy(szProxy, "");
+       sOpt = gf_cfg_get_key(cfg, "HTTPProxy", "Name");
+       if (sOpt) {
+               strcat(szProxy, sOpt);
+               sOpt = gf_cfg_get_key(cfg, "HTTPProxy", "Port");
+               if (sOpt) {
+                       strcat(szProxy, ":");
+                       strcat(szProxy, sOpt);
+               }
+       } else {
+               m_use_proxy->SetValue(0);
+       }
+       m_proxy_name->SetValue( wxString((char *)szProxy, wxConvUTF8) );
+       if (! m_use_proxy->GetValue()) m_proxy_name->Enable(0);
+
+       /*streaming*/   
+       m_port->Append(wxT("554 (RTSP standard)"));
+       m_port->Append(wxT("7070 (RTSP ext)"));
+       m_port->Append(wxT("80 (RTSP / HTTP tunnel)"));
+       m_port->Append(wxT("8080 (RTSP / HTTP tunnel)"));
+       sOpt = gf_cfg_get_key(cfg, "Streaming", "DefaultPort");
+       u32 port = 554;
+       Bool force_rtsp = 0;
+       if (sOpt) port = atoi(sOpt);
+       switch (port) {
+       case 8080:
+               m_port->SetSelection(3);
+               force_rtsp = 1;
+               break;
+       case 80:
+               m_port->SetSelection(2);
+               force_rtsp = 1;
+               break;
+       case 7070:
+               m_port->SetSelection(1);
+               break;
+       default:
+               m_port->SetSelection(0);
+               break;
+       }
+
+       Bool use_rtsp = 0;
+       sOpt = gf_cfg_get_key(cfg, "Streaming", "RTPoverRTSP");
+       if (sOpt && !stricmp(sOpt, "yes")) use_rtsp = 1;
+
+       if (force_rtsp) {
+               m_rtsp->SetValue(1);
+               m_rtsp->Enable(0);
+               m_reorder->SetValue(0);
+               m_reorder->Enable(0);
+       } else {
+               m_rtsp->SetValue(use_rtsp ? 1 : 0);
+               m_rtsp->Enable(1);
+               m_reorder->Enable(1);
+               sOpt = gf_cfg_get_key(cfg, "Streaming", "ReorderSize");
+               m_reorder->SetValue( (sOpt && !stricmp(sOpt, "0")) ? 1 : 0);
+       }
+       sOpt = gf_cfg_get_key(cfg, "Streaming", "RTSPTimeout");
+       m_timeout->SetValue(sOpt ? wxString(sOpt, wxConvUTF8) : wxT("30000"));
+       sOpt = gf_cfg_get_key(cfg, "Network", "BufferLength");
+       m_buffer->SetValue(sOpt ? wxString(sOpt, wxConvUTF8) : wxT("3000"));
+       sOpt = gf_cfg_get_key(cfg, "Network", "RebufferLength");
+       u32 buf_len = 0;
+       if (sOpt) buf_len = atoi(sOpt);
+       if (buf_len) {
+               m_dorebuffer->SetValue(1);
+               m_rebuffer->SetValue(wxString(sOpt, wxConvUTF8));
+               m_rebuffer->Enable(1);
+       } else {
+               m_dorebuffer->SetValue(0);
+               m_rebuffer->SetValue(wxT("0"));
+               m_rebuffer->Enable(0);
+       }
+
+       RTPoverRTSP(event);
+
+       sOpt = gf_cfg_get_key(cfg, "StreamingCache", "RecordDirectory");
+       if (!sOpt) sOpt = gf_cfg_get_key(cfg, "General", "CacheDirectory");
+       if (sOpt) m_recdir->SetLabel(wxString(sOpt, wxConvUTF8));
+       sOpt = gf_cfg_get_key(cfg, "StreamingCache", "KeepExistingFiles");
+       m_overwrite->SetValue((sOpt && !stricmp(sOpt, "yes")) ? 0 : 1);
+
+       sOpt = gf_cfg_get_key(cfg, "StreamingCache", "BaseFileName");
+       if (sOpt) {
+               m_usename->SetValue(1);
+               m_recfile->Enable(1);
+               m_recfile->SetValue(wxString(sOpt, wxConvUTF8));
+       } else {
+               m_usename->SetValue(0);
+               m_recfile->Enable(0);
+               m_recfile->SetValue(wxT("uses service URL"));
+       }
+
+       m_select->Append(wxT("General"));
+       m_select->Append(wxT("MPEG-4 Systems"));
+       m_select->Append(wxT("Media Decoders"));
+       m_select->Append(wxT("Compositor"));
+       m_select->Append(wxT("Renderer 2D"));
+       m_select->Append(wxT("Renderer 3D"));
+       m_select->Append(wxT("Video Output"));
+       m_select->Append(wxT("Audio Output"));
+       m_select->Append(wxT("Text Engine"));
+       m_select->Append(wxT("File Download"));
+       m_select->Append(wxT("Real-Time Streaming"));
+       m_select->Append(wxT("Streaming Cache"));
+
+       sOpt = gf_cfg_get_key(cfg, "General", "ConfigPanel");
+       m_sel = sOpt ? atoi(sOpt) : 0;
+       if (m_sel>11) m_sel=11;
+       m_select->SetSelection(m_sel);
+
+       DoSelect();
+}
+
+BEGIN_EVENT_TABLE(wxGPACControl, wxDialog)
+       EVT_BUTTON(ID_APPLY, wxGPACControl::Apply)
+       EVT_COMBOBOX(ID_SELECT, wxGPACControl::OnSetSelection)
+       EVT_CHECKBOX(ID_FORCE_AUDIO, wxGPACControl::ForceAudio)
+       EVT_COMBOBOX(ID_AUDIO_DRIVER, wxGPACControl::OnSetAudioDriver)
+       EVT_BUTTON(ID_FONT_DIR, wxGPACControl::FontDir)
+       EVT_BUTTON(ID_CACHE_DIR, wxGPACControl::CacheDir)
+       EVT_CHECKBOX(ID_PROGRESSIVE, wxGPACControl::OnProgressive)
+       EVT_CHECKBOX(ID_USE_PROXY, wxGPACControl::OnUseProxy)
+       EVT_CHECKBOX(ID_RTP_OVER_RTSP, wxGPACControl::RTPoverRTSP)
+       EVT_CHECKBOX(ID_RTSP_REBUFFER, wxGPACControl::Rebuffer)
+       EVT_COMBOBOX(ID_RTSP_PORT, wxGPACControl::OnSetRTSPPort)
+       EVT_CHECKBOX(ID_USE_FILENAME, wxGPACControl::OnUseFileName)
+       EVT_BUTTON(ID_RECORD_DIR, wxGPACControl::OnRecDir)
+END_EVENT_TABLE()
+
+
+wxGPACControl::~wxGPACControl()
+{
+       char str[20];
+       sprintf(str, "%d", m_sel);
+       gf_cfg_set_key(m_pApp->m_user.config, "General", "ConfigPanel", str);
+}
+
+
+void wxGPACControl::DoSelect()
+{
+
+       /*hide everything*/
+       s_main->Show(s_general, false);
+       s_main->Show(s_mpeg4, false);
+       s_main->Show(s_mdec, false);
+       s_main->Show(s_rend, false);
+       s_main->Show(s_rend2d, false);
+       s_main->Show(s_rend3d, false);
+       s_main->Show(s_video, false);
+       s_main->Show(s_audio, false);
+       s_main->Show(s_font, false);
+       s_main->Show(s_dnld, false);
+       s_main->Show(s_stream, false);
+       s_main->Show(s_rec, false);
+       switch (m_sel) {
+       case 0: s_main->Show(s_general, true); break;
+       case 1: s_main->Show(s_mpeg4, true); break;
+       case 2: s_main->Show(s_mdec, true); break;
+       case 3: s_main->Show(s_rend, true); break;
+       case 4: s_main->Show(s_rend2d, true); break;
+       case 5: s_main->Show(s_rend3d, true); break;
+       case 6: s_main->Show(s_video, true); break;
+       case 7: s_main->Show(s_audio, true); break;
+       case 8: s_main->Show(s_font, true); break;
+       case 9: s_main->Show(s_dnld, true); break;
+       case 10: s_main->Show(s_stream, true); break;
+       case 11: s_main->Show(s_rec, true); break;
+       }
+    SetSizer(s_main);
+       s_main->Fit(this);
+       //s_main->Layout();
+       return;
+
+}
+
+void wxGPACControl::OnSetSelection(wxCommandEvent &WXUNUSED(event))
+{
+       m_sel = m_select->GetSelection();
+       DoSelect();
+}
+
+void wxGPACControl::FontDir(wxCommandEvent &WXUNUSED(event))
+{
+       wxDirDialog dlg(this);
+       dlg.SetPath(m_fontdir->GetLabel());
+       if (dlg.ShowModal() == wxID_OK) {
+               m_fontdir->SetLabel(dlg.GetPath());
+       }
+}
+void wxGPACControl::CacheDir(wxCommandEvent &WXUNUSED(event))
+{
+       wxDirDialog dlg(this);
+       dlg.SetPath(m_cachedir->GetLabel());
+       if (dlg.ShowModal() == wxID_OK) {
+               m_cachedir->SetLabel(dlg.GetPath());
+       }
+}
+
+void wxGPACControl::OnProgressive(wxCommandEvent &WXUNUSED(event))
+{
+       m_sax_duration->Enable(m_progressive->GetValue() ? 1 : 0);
+}
+
+void wxGPACControl::OnUseProxy(wxCommandEvent &WXUNUSED(event))
+{
+       m_proxy_name->Enable(m_use_proxy->GetValue() ? 1 : 0);
+}
+
+void wxGPACControl::RTPoverRTSP(wxCommandEvent &WXUNUSED(event))
+{
+       m_reorder->Enable(m_rtsp->GetValue() ? 0 : 1);
+}
+
+void wxGPACControl::Rebuffer(wxCommandEvent &WXUNUSED(event))
+{
+       if (m_dorebuffer->GetValue()) {
+               m_rebuffer->Enable();
+       } else {
+               m_rebuffer->Disable();
+       }
+}
+
+void wxGPACControl::OnSetRTSPPort(wxCommandEvent &WXUNUSED(event))
+{
+       if (m_port->GetSelection() > 1) {
+               m_rtsp->Enable(0);
+               m_reorder->Enable(0);
+       } else {
+               m_rtsp->Enable(1);
+               m_reorder->Enable(1);
+       }
+}
+
+void wxGPACControl::OnRecDir(wxCommandEvent &WXUNUSED(event))
+{
+       wxDirDialog dlg(this);
+       dlg.SetPath(m_recdir->GetLabel());
+       if (dlg.ShowModal() == wxID_OK) {
+               m_recdir->SetLabel(dlg.GetPath());
+       }
+}
+
+void wxGPACControl::OnUseFileName(wxCommandEvent &WXUNUSED(event))
+{
+       if (m_usename->GetValue()) {
+               m_recfile->Enable();
+               m_recfile->SetValue(wxT("record"));
+       } else {
+               m_recfile->Disable();
+               m_recfile->SetValue(wxT("uses service URL"));
+       }
+}
+
+void wxGPACControl::ForceAudio(wxCommandEvent &WXUNUSED(event))
+{
+       if (m_forcecfg->GetValue()) {
+               m_nbbuf->Enable();
+               m_buflen->Enable();
+       } else {
+               m_nbbuf->Disable();
+               m_buflen->Disable();
+       }
+}
+
+void wxGPACControl::OnSetAudioDriver(wxCommandEvent &WXUNUSED(event))
+{
+#ifdef WIN32
+       if (strstr(m_audio->GetStringSelection().mb_str(wxConvUTF8), "DirectSound")) {
+               m_notifs->Enable(1);
+       } else {
+               m_notifs->Enable(0);
+       }
+#endif
+}
+
+
+
+void wxGPACControl::Apply(wxCommandEvent &WXUNUSED(event))
+{
+       /*save options*/
+       GF_Config *cfg = m_pApp->m_user.config;
+
+       m_pApp->m_loop = m_loop->GetValue() ? 1 : 0;
+       gf_cfg_set_key(cfg, "General", "Loop", m_loop->GetValue() ? "yes" : "no");
+       m_pApp->m_lookforsubs = m_lookforsubs->GetValue() ? 1 : 0;
+       gf_cfg_set_key(cfg, "General", "LookForSubtitles",  m_lookforsubs->GetValue() ? "yes" : "no");
+       m_pApp->m_console_off = m_noconsole->GetValue() ? 1 : 0;
+       gf_cfg_set_key(cfg, "General", "ConsoleOff", m_noconsole->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "General", "ViewXMT", m_viewxmt->GetValue() ? "yes" : "no");
+
+       s32 sel = m_lang->GetSelection();
+       u32 i=0;
+       while (GF_ISO639_Lang[i]) {
+               /*only use common languages (having both 2- and 3-char code names)*/
+               if (GF_ISO639_Lang[i+2][0]) {
+                       if (!sel) break;
+                       sel--;
+               }
+               i+=3;
+       }
+       gf_cfg_set_key(cfg, "Systems", "LanguageName", GF_ISO639_Lang[i]);
+       gf_cfg_set_key(cfg, "Systems", "Language3CC", GF_ISO639_Lang[i+1]);
+       gf_cfg_set_key(cfg, "Systems", "Language2CC", GF_ISO639_Lang[i+2]);
+
+
+       sel = m_thread->GetSelection();
+       gf_cfg_set_key(cfg, "Systems", "ThreadingPolicy", (sel==0) ? "Single" : ( (sel==1) ? "Multi" : "Free"));
+       gf_cfg_set_key(cfg, "Systems", "ForceSingleClock", m_singletime->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Systems", "AlwaysDrawBIFS", m_bifsalwaysdrawn->GetValue() ? "yes" : "no");
+
+       gf_cfg_set_key(cfg, "Systems", "DefAudioDec", m_decaudio->GetStringSelection().mb_str(wxConvUTF8));
+       gf_cfg_set_key(cfg, "Systems", "DefVideoDec", m_decvideo->GetStringSelection().mb_str(wxConvUTF8));
+       
+
+       gf_cfg_set_key(cfg, "Compositor", "HighSpeed", m_fast->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "ForceSceneSize", m_force_size->GetValue() ? "yes" : "no");
+
+       gf_cfg_set_key(cfg, "Compositor", "FrameRate", BIFSRates[m_fps->GetSelection()]);
+       sel = m_aa->GetSelection();
+       gf_cfg_set_key(cfg, "Compositor", "AntiAlias", (sel==0) ? "None" : ( (sel==1) ? "Text" : "All"));
+       sel = m_draw_bounds->GetSelection();
+       gf_cfg_set_key(cfg, "Compositor", "BoundingVolume", (sel==2) ? "AABB" : (sel==1) ? "Box" : "None");
+
+       Bool is_3D = m_use3D->GetValue() ? 1 : 0;
+       if (m_bWas3D != is_3D) {
+               /*FIXME*/
+       }
+       gf_cfg_set_key(cfg, "Compositor", "Raster2D", m_graph->GetStringSelection().mb_str(wxConvUTF8));
+
+       gf_cfg_set_key(cfg, "Compositor", "DirectDraw", m_direct->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "ScalableZoom", m_scalable->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "DisableYUV", m_noyuv->GetValue() ? "yes" : "no");
+
+       gf_cfg_set_key(cfg, "Compositor", "RasterOutlines", m_raster_outlines->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "EmulatePOW2", m_emulpow2->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "PolygonAA", m_polyaa->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "DisableRectExt", m_norectext->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "BitmapCopyPixels", m_copypixels->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Compositor", "BackFaceCulling", m_nobackcull->GetValue() ? "Off" : "On");
+
+       sel = m_wire->GetSelection();
+       gf_cfg_set_key(cfg, "Compositor", "Wireframe", (sel==2) ? "WireOnSolid" : ( (sel==1) ? "WireOnly" : "WireNone" ) );
+       sel = m_normals->GetSelection();
+       gf_cfg_set_key(cfg, "Compositor", "DrawNormals", (sel==2) ? "PerVertex" : ( (sel==1) ? "PerFace" : "Never" ) );
+
+       gf_cfg_set_key(cfg, "Video", "SwitchResolution", m_switchres->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Video", "UseHardwareMemory", m_usehwmem->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Video", "DriverName", m_video->GetStringSelection().mb_str(wxConvUTF8));
+
+
+       gf_cfg_set_key(cfg, "Audio", "ForceConfig", m_forcecfg->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Audio", "NoResync", m_noresync->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Audio", "DisableMultiChannel", m_nomulitch->GetValue() ? "yes" : "no");
+       
+       gf_cfg_set_key(cfg, "Audio", "NumBuffers", wxString::Format(wxT("%d"), m_nbbuf->GetValue()).mb_str(wxConvUTF8) );
+       gf_cfg_set_key(cfg, "Audio", "TotalDuration", wxString::Format(wxT("%d"), m_buflen->GetValue()).mb_str(wxConvUTF8) );
+       gf_cfg_set_key(cfg, "Audio", "DriverName", m_audio->GetStringSelection().mb_str(wxConvUTF8));
+#ifdef WIN32
+       if (m_notifs->IsEnabled()) 
+               gf_cfg_set_key(cfg, "Audio", "DisableNotification", m_notifs->GetValue() ? "yes" : "no");
+#endif
+       
+       gf_cfg_set_key(cfg, "FontEngine", "FontReader", m_font->GetStringSelection().mb_str(wxConvUTF8));
+       gf_cfg_set_key(cfg, "FontEngine", "FontDirectory", m_fontdir->GetLabel().mb_str(wxConvUTF8));
+       switch (m_texturemode->GetSelection()) {
+       case 2: gf_cfg_set_key(cfg, "Compositor", "TextureTextMode", "Always"); break;
+       case 1: gf_cfg_set_key(cfg, "Compositor", "TextureTextMode", "Never"); break;
+       default: gf_cfg_set_key(cfg, "Compositor", "TextureTextMode", "Default"); break;
+       }
+
+       gf_cfg_set_key(cfg, "Downloader", "CleanCache", m_cleancache->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "Downloader", "RestartFiles", m_restartcache->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "SAXLoader", "Progressive", m_progressive->GetValue() ? "yes" : "no");
+       gf_cfg_set_key(cfg, "SAXLoader", "MaxDuration", m_sax_duration->GetLabel().mb_str(wxConvUTF8));
+       gf_cfg_set_key(cfg, "General", "CacheDirectory", m_cachedir->GetLabel().mb_str(wxConvUTF8));
+
+
+       Bool force_rtsp = 0;
+       switch (m_port->GetSelection()) {
+       case 3:
+               gf_cfg_set_key(cfg, "Streaming", "DefaultPort", "8080");
+               force_rtsp = 1;
+               break;
+       case 2:
+               gf_cfg_set_key(cfg, "Streaming", "DefaultPort", "80");
+               force_rtsp = 1;
+               break;
+       case 1:
+               gf_cfg_set_key(cfg, "Streaming", "DefaultPort", "7070");
+               break;
+       default:
+               gf_cfg_set_key(cfg, "Streaming", "DefaultPort", "554");
+               break;
+       }
+
+       if (force_rtsp) {
+               gf_cfg_set_key(cfg, "Streaming", "RTPoverRTSP", "yes");
+       } else {
+               gf_cfg_set_key(cfg, "Streaming", "RTPoverRTSP", m_rtsp->GetValue() ? "yes" : "no");
+               if (!m_rtsp->GetValue()) gf_cfg_set_key(cfg, "Streaming", "ReorderSize", m_dorebuffer->GetValue() ? "30" : "0");
+       }
+
+       gf_cfg_set_key(cfg, "Streaming", "RTSPTimeout", m_timeout->GetValue().mb_str(wxConvUTF8));
+       gf_cfg_set_key(cfg, "Network", "BufferLength", m_buffer->GetValue().mb_str(wxConvUTF8));
+       if (m_dorebuffer->GetValue()) {
+               gf_cfg_set_key(cfg, "Network", "RebufferLength", m_rebuffer->GetValue().mb_str(wxConvUTF8));
+       } else {
+               gf_cfg_set_key(cfg, "Network", "RebufferLength", "0");
+       }
+
+       gf_cfg_set_key(cfg, "StreamingCache", "KeepExistingFiles", m_overwrite->GetValue() ? "no" : "yes");
+       if (m_usename->GetValue()) {
+               gf_cfg_set_key(cfg, "StreamingCache", "BaseFileName", m_recfile->GetValue().mb_str(wxConvUTF8));
+       } else {
+               gf_cfg_set_key(cfg, "StreamingCache", "BaseFileName", NULL);
+       }
+       gf_cfg_set_key(cfg, "StreamingCache", "RecordDirectory", m_recdir->GetLabel().mb_str(wxConvUTF8));
+
+
+       gf_term_set_option(m_pApp->m_term, GF_OPT_RELOAD_CONFIG, 1);
+}
+
diff --git a/applications/osmo4_wx/wxGPACControl.h b/applications/osmo4_wx/wxGPACControl.h
new file mode 100644 (file)
index 0000000..043d902
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *             
+ */
+
+#ifndef _OPTIONS_H
+#define _OPTIONS_H
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+  #include "wx/wx.h"
+#endif
+
+#include <wx/spinbutt.h>
+#include <wx/spinctrl.h>
+
+enum
+{
+       ID_SELECT = 1000,
+       ID_APPLY,
+
+       ID_MAKE_DEF,
+       ID_FORCE_AUDIO,
+       ID_AUDIO_DRIVER,
+       ID_FONT_DIR,
+       ID_CACHE_DIR,
+       ID_PROGRESSIVE,
+       ID_RTSP_PORT,
+       ID_RTP_OVER_RTSP,
+       ID_RTSP_REBUFFER,
+       ID_RECORD_DIR,
+       ID_USE_FILENAME,
+       ID_USE_PROXY,
+};
+
+class wxOsmo4Frame;
+class wxGPACControl : public wxDialog 
+{
+public:
+    wxGPACControl(wxWindow *parent);
+       virtual ~wxGPACControl();
+
+private:
+       DECLARE_EVENT_TABLE()
+
+       wxOsmo4Frame *m_pApp;
+
+       wxComboBox *m_select;
+       Bool m_bWas3D;
+
+       void Apply(wxCommandEvent &event);
+       void OnSetSelection(wxCommandEvent &event);
+       void ForceAudio(wxCommandEvent &event);
+       void OnSetAudioDriver(wxCommandEvent &event);
+       void FontDir(wxCommandEvent &event);
+       void CacheDir(wxCommandEvent &event);
+       void OnProgressive(wxCommandEvent &event);
+       void OnUseProxy(wxCommandEvent &event);
+       void RTPoverRTSP(wxCommandEvent &event);
+       void Rebuffer(wxCommandEvent &event);
+       void OnSetRTSPPort(wxCommandEvent &event);
+       void OnUseFileName(wxCommandEvent &event);
+       void OnRecDir(wxCommandEvent &event);
+       void DoSelect();
+       s32 m_sel;
+       void SetYUVLabel();
+
+       wxBoxSizer *s_header, *s_main, *s_general, *s_mpeg4, *s_mdec, *s_rend, *s_rend2d, *s_rend3d, *s_audio, *s_video, *s_font, *s_dnld, *s_stream, *s_rec;
+
+       /*general section*/
+       wxCheckBox *m_loop, *m_lookforsubs, *m_noconsole, *m_viewxmt;
+       /*MPEG-4 systems*/
+       wxCheckBox *m_bifsalwaysdrawn, *m_singletime;
+       wxComboBox *m_lang, *m_thread;
+       /*media decoders*/
+       wxComboBox *m_decaudio, *m_decvideo;
+       /*Rendering*/
+       wxComboBox *m_fps, *m_aa, *m_draw_bounds;
+       wxCheckBox *m_use3D, *m_fast, *m_force_size;
+       /*Renderer 2D*/
+       wxComboBox *m_graph;
+       wxCheckBox *m_noyuv, *m_direct, *m_scalable;
+       wxStaticText *m_yuvtxt;
+       /*Renderer 3D*/
+       wxCheckBox *m_raster_outlines, *m_polyaa, *m_nobackcull, *m_emulpow2, *m_norectext, *m_copypixels;
+       wxComboBox *m_wire, *m_normals;
+       /*video*/
+       wxComboBox *m_video;
+       wxCheckBox *m_switchres, *m_usehwmem;
+       /*audio*/
+       wxSpinCtrl *m_nbbuf, *m_buflen;
+       wxComboBox *m_audio;
+       wxCheckBox *m_forcecfg, *m_noresync, *m_nomulitch;
+#ifdef WIN32
+       wxCheckBox *m_notifs;
+#endif
+       /*font*/
+       wxComboBox *m_font;
+       wxButton *m_fontdir;
+       wxComboBox *m_texturemode;
+       /*file download*/
+       wxButton *m_cachedir;
+       wxCheckBox *m_cleancache, *m_restartcache, *m_progressive, *m_use_proxy;
+       wxTextCtrl *m_sax_duration, *m_proxy_name;
+       /*streaming*/
+       wxComboBox *m_port;
+       wxCheckBox *m_rtsp, *m_reorder, *m_dorebuffer;
+       wxTextCtrl *m_timeout, *m_buffer, *m_rebuffer;
+       /*file recorder*/
+       wxButton *m_recdir;
+       wxCheckBox *m_overwrite, *m_usename;
+       wxTextCtrl *m_recfile;
+};
+
+#endif
+
diff --git a/applications/osmo4_wx/wxOsmo4.cpp b/applications/osmo4_wx/wxOsmo4.cpp
new file mode 100644 (file)
index 0000000..b25b199
--- /dev/null
@@ -0,0 +1,2347 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is gf_free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  GPAC 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+
+#include "wxOsmo4.h"
+#include "wxGPACControl.h"
+#include "fileprops.h"
+#include <wx/image.h>
+#include <gpac/modules/service.h>
+#include <gpac/network.h>
+#include <gpac/constants.h>
+#include <gpac/options.h>
+
+
+IMPLEMENT_APP(wxOsmo4App)
+
+#include "osmo4.xpm"
+
+#include <wx/dnd.h>
+
+
+
+
+
+#include <wx/filename.h>
+#include <wx/clipbrd.h>
+
+#include "toolbar.xpm"
+
+#include "Playlist.h"
+
+#ifdef WIN32
+#define        FRAME_H 140
+#else
+#define        FRAME_H 110
+#endif
+
+
+wxString get_pref_browser(GF_Config *cfg)
+{
+       const char *sOpt = gf_cfg_get_key(cfg, "General", "Browser");
+       if (sOpt) return wxString(sOpt, wxConvUTF8);
+       return wxEmptyString;
+/*
+#ifdef __WXMAC__
+       return wxT("safari");
+#else
+#ifdef WIN32
+       return wxT("explorer.exe");
+#else
+       return wxT("mozilla");
+#endif
+#endif*/
+}
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxGPACEvent, wxEvent )
+
+wxGPACEvent::wxGPACEvent(wxWindow* win)
+{
+    SetEventType(GPAC_EVENT);
+    SetEventObject(win);
+       gpac_evt.type = 0;
+       to_url = wxT("");
+}
+wxEvent *wxGPACEvent::Clone() const
+{
+       wxGPACEvent *evt = new wxGPACEvent((wxWindow *) m_eventObject);
+       evt->to_url = to_url;
+       evt->gpac_evt = gpac_evt;
+       return evt;
+}
+
+#include <wx/wx.h>
+
+/*open file dlg*/
+BEGIN_EVENT_TABLE(OpenURLDlg, wxDialog)
+    EVT_BUTTON(ID_URL_GO, OpenURLDlg::OnGo)
+END_EVENT_TABLE()
+
+OpenURLDlg::OpenURLDlg(wxWindow *parent, GF_Config *cfg)
+             : wxDialog(parent, -1, wxString(wxT("Enter remote presentation location")))
+{
+#ifndef WIN32
+       SetSize(430, 35);
+#else
+       SetSize(430, 55);
+#endif
+       Centre();
+    m_url = new wxComboBox(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
+       m_url->SetSize(0, 2, 340, 18, wxSIZE_AUTO);
+    m_go = new wxButton(this, ID_URL_GO, wxT("Go !"));
+#ifndef WIN32
+       m_go->SetSize(344, 2, 20, 18, wxSIZE_AUTO);
+#else
+       m_go->SetSize(364, 2, 30, 18, wxSIZE_AUTO);
+#endif
+       m_urlVal = wxT("");
+
+       m_cfg = cfg;
+
+       const char *sOpt;
+       u32 i=0;
+
+       while (1) {
+               sOpt = gf_cfg_get_key_name(m_cfg, "RecentFiles", i);
+               if (!sOpt) break;
+               m_url->Append(wxString(sOpt, wxConvUTF8) );
+               i++;
+       }
+}
+
+#define MAX_LAST_FILES         20
+void UpdateLastFiles(GF_Config *cfg, const char *URL)
+{
+       u32 nb_entries;
+       gf_cfg_set_key(cfg, "RecentFiles", URL, NULL);
+       gf_cfg_insert_key(cfg, "RecentFiles", URL, "", 0);
+       /*remove last entry if needed*/
+       nb_entries = gf_cfg_get_key_count(cfg, "RecentFiles");
+       if (nb_entries>MAX_LAST_FILES) {
+               gf_cfg_set_key(cfg, "RecentFiles", gf_cfg_get_key_name(cfg, "RecentFiles", nb_entries-1), NULL);
+       }
+}
+
+void OpenURLDlg::OnGo(wxCommandEvent& event)
+{
+       m_urlVal = m_url->GetValue();
+       UpdateLastFiles(m_cfg, m_urlVal.mb_str(wxConvUTF8));
+       EndModal(wxID_OK);
+}
+/*end open file dlg*/
+
+#ifdef WIN32
+u32 get_sys_col(int idx)
+{
+       u32 res;
+       DWORD val = GetSysColor(idx);
+       res = (val)&0xFF; res<<=8;
+       res |= (val>>8)&0xFF; res<<=8;
+       res |= (val>>16)&0xFF;
+       return res;
+}
+#endif
+
+static void wxOsmo4_progress_cbk(const void *usr, const char *title, u64 done, u64 total)
+{
+       if (!total) return;
+       wxOsmo4Frame *app = (wxOsmo4Frame *)usr;
+       s32 prog = (s32) ( (100 * (u64)done) / total);
+       if (app->m_last_prog < prog) {
+               app->m_last_prog = prog;
+
+               if (prog<100) {
+                       /*appears to crash wxWidgets / X11 when refreshing the text too often*/
+                       if (app->m_LastStatusTime + 200 > gf_sys_clock()) return;
+                       char msg[1024];
+                       sprintf(msg, "%s %02d %%)", title, prog);
+                       //app->SetStatus(wxString(msg, wxConvUTF8));
+               } else {
+                       app->SetStatus(wxT("Ready"));
+                       app->m_last_prog = -1;
+               }
+       }
+}
+
+Bool GPAC_EventProc(void *ptr, GF_Event *evt)
+{
+       wxCommandEvent event;
+       wxOsmo4Frame *app = (wxOsmo4Frame *)ptr;
+
+       switch (evt->type) {
+       case GF_EVENT_DURATION:
+               app->m_duration = (u32) (evt->duration.duration*1000);
+               app->m_can_seek = evt->duration.can_seek;
+               if (app->m_duration<1100) app->m_can_seek = 0;
+               app->m_pProg->Enable(app->m_can_seek ? 1 : 0);
+               app->m_pPlayList->SetDuration((u32) evt->duration.duration);
+               break;
+       case GF_EVENT_MESSAGE:
+       {
+               const char *servName;
+               if (!evt->message.service || !strcmp(evt->message.service, app->m_pPlayList->GetURL().mb_str(wxConvUTF8))) {
+                       servName = "main service";
+               } else {
+                       servName = evt->message.service;
+               }
+               if (!evt->message.message) return 0;
+
+               if (evt->message.error) {
+                       app->SetStatus(wxString(evt->message.message, wxConvUTF8) + wxT(" (") + wxString(servName, wxConvUTF8) + wxT(")") );
+                       if (!app->m_connected) app->m_pPlayList->SetDead();
+               }
+               else if (!app->m_console_off) {
+                       if (strstr(evt->message.message, "100 %")) {
+                               app->SetStatus(wxT(""));
+                       } else {
+                               app->SetStatus(wxString(evt->message.message, wxConvUTF8) );
+                       }
+               }
+
+#if 0
+               /*log*/
+               if (evt->message.error)
+                       ::wxLogMessage(wxString(evt->message.message, wxConvUTF8) + wxT(" (") + wxString(servName, wxConvUTF8) + wxT(") ") + wxString(gf_error_to_string(evt->message.error), wxConvUTF8) );
+               else
+                       ::wxLogMessage(wxString(evt->message.message, wxConvUTF8) + wxT(" (") + wxString(servName, wxConvUTF8) + wxT(")"));
+#endif
+       }
+               break;
+       case GF_EVENT_PROGRESS:
+       {
+               const char *sTitle;
+               if (evt->progress.progress_type==0) sTitle = (char *)"Buffer";
+               else if (evt->progress.progress_type==1) sTitle = (char *)"Download";
+               else if (evt->progress.progress_type==2) sTitle = (char *)"Import";
+               gf_set_progress(sTitle, evt->progress.done, evt->progress.total);
+       }
+               break;
+       case GF_EVENT_KEYDOWN:
+               if (app->m_can_seek && (evt->key.flags & GF_KEY_MOD_ALT)) {
+                       s32 res;
+                       switch (evt->key.key_code) {
+                       case GF_KEY_LEFT:
+                               res = gf_term_get_time_in_ms(app->m_term) - 5*app->m_duration/100;
+                               if (res<0) res=0;
+                               gf_term_play_from_time(app->m_term, res, 0);
+                               break;
+                       case GF_KEY_RIGHT:
+                               res = gf_term_get_time_in_ms(app->m_term) + 5*app->m_duration/100;
+                               if ((u32) res>=app->m_duration) res = 0;
+                               gf_term_play_from_time(app->m_term, res, 0);
+                               break;
+                       case GF_KEY_DOWN:
+                               res = gf_term_get_time_in_ms(app->m_term) - 60000;
+                               if (res<0) res=0;
+                               gf_term_play_from_time(app->m_term, res, 0);
+                               break;
+                       case GF_KEY_UP:
+                               res = gf_term_get_time_in_ms(app->m_term) + 60000;
+                               if ((u32) res>=app->m_duration) res = 0;
+                               gf_term_play_from_time(app->m_term, res, 0);
+                               break;
+                       }
+               } else if (evt->key.flags & GF_KEY_MOD_CTRL) {
+                       switch (evt->key.key_code) {
+                       case GF_KEY_LEFT:
+                               app->m_pPlayList->PlayPrev();
+                               break;
+                       case GF_KEY_RIGHT:
+                               app->m_pPlayList->PlayNext();
+                               break;
+                       }
+               } else {
+                       switch (evt->key.key_code) {
+                       case GF_KEY_HOME:
+                               gf_term_set_option(app->m_term, GF_OPT_NAVIGATION_TYPE, 1);
+                               break;
+                       case GF_KEY_ESCAPE:
+                               if (gf_term_get_option(app->m_term, GF_OPT_FULLSCREEN))
+                                       gf_term_set_option(app->m_term, GF_OPT_FULLSCREEN, 0);
+                               break;
+                       default:
+                       {
+                               wxGPACEvent wxevt(app);
+                               wxevt.gpac_evt = *evt;
+                               app->AddPendingEvent(wxevt);
+                       }
+                               break;
+                       }
+               }
+               break;
+
+       case GF_EVENT_CONNECT:
+       {
+               wxGPACEvent wxevt(app);
+               wxevt.gpac_evt.type = GF_EVENT_CONNECT;
+               wxevt.gpac_evt.connect.is_connected = evt->connect.is_connected;
+               if (!evt->connect.is_connected) app->m_duration = 0;
+               app->AddPendingEvent(wxevt);
+       }
+               break;
+       case GF_EVENT_NAVIGATE:
+       {
+               wxGPACEvent wxevt(app);
+               wxevt.to_url = wxString(evt->navigate.to_url, wxConvUTF8);
+               wxevt.gpac_evt.type = evt->type;
+               app->AddPendingEvent(wxevt);
+       }
+               return 1;
+       case GF_EVENT_SET_CAPTION:
+       {
+               wxGPACEvent wxevt(app);
+               wxevt.to_url = wxString(evt->caption.caption, wxConvUTF8);
+               wxevt.gpac_evt.type = evt->type;
+               app->AddPendingEvent(wxevt);
+       }
+               return 1;
+
+       case GF_EVENT_QUIT:
+       case GF_EVENT_VIEWPOINTS:
+       case GF_EVENT_STREAMLIST:
+       case GF_EVENT_SCENE_SIZE:
+//     case GF_EVENT_SIZE:
+       {
+               wxGPACEvent wxevt(app);
+               wxevt.gpac_evt = *evt;
+               app->AddPendingEvent(wxevt);
+       }
+               break;
+       case GF_EVENT_DBLCLICK:
+               gf_term_set_option(app->m_term, GF_OPT_FULLSCREEN, !gf_term_get_option(app->m_term, GF_OPT_FULLSCREEN));
+               return 0;
+       case GF_EVENT_MOUSEDOWN:
+               if (!gf_term_get_option(app->m_term, GF_OPT_FULLSCREEN)) {
+#ifdef __WXGTK__
+                 app->m_pVisual->SetFocus();
+#else
+                 app->m_pView->SetFocus();
+#endif
+               }
+               break;
+       case GF_EVENT_AUTHORIZATION:
+       {
+         wxGPACEvent wxevt(app);
+         wxTextEntryDialog user_d (0, 
+                  wxT("Please set the user name for connection"), 
+                 wxString(evt->auth.site_url, wxConvUTF8), 
+                  wxString(evt->auth.user, wxConvUTF8));
+         if (user_d.ShowModal() != wxID_OK)
+           return 0;
+         strncpy(evt->auth.user, user_d.GetValue().mb_str(wxConvUTF8), 50);
+         wxPasswordEntryDialog passwd_d(0, 
+                      wxT("Please enter password"), 
+                      wxString(evt->auth.site_url, wxConvUTF8), 
+                      wxString(evt->auth.password, wxConvUTF8));
+         if (passwd_d.ShowModal() != wxID_OK)
+           return 0;
+         strncpy(evt->auth.password, passwd_d.GetValue().mb_str(wxConvUTF8), 50);
+         return 1;
+       }
+       case GF_EVENT_SYS_COLORS:
+#ifdef WIN32
+               evt->sys_cols.sys_colors[0] = get_sys_col(COLOR_ACTIVEBORDER);
+               evt->sys_cols.sys_colors[1] = get_sys_col(COLOR_ACTIVECAPTION);
+               evt->sys_cols.sys_colors[2] = get_sys_col(COLOR_APPWORKSPACE);
+               evt->sys_cols.sys_colors[3] = get_sys_col(COLOR_BACKGROUND);
+               evt->sys_cols.sys_colors[4] = get_sys_col(COLOR_BTNFACE);
+               evt->sys_cols.sys_colors[5] = get_sys_col(COLOR_BTNHIGHLIGHT);
+               evt->sys_cols.sys_colors[6] = get_sys_col(COLOR_BTNSHADOW);
+               evt->sys_cols.sys_colors[7] = get_sys_col(COLOR_BTNTEXT);
+               evt->sys_cols.sys_colors[8] = get_sys_col(COLOR_CAPTIONTEXT);
+               evt->sys_cols.sys_colors[9] = get_sys_col(COLOR_GRAYTEXT);
+               evt->sys_cols.sys_colors[10] = get_sys_col(COLOR_HIGHLIGHT);
+               evt->sys_cols.sys_colors[11] = get_sys_col(COLOR_HIGHLIGHTTEXT);
+               evt->sys_cols.sys_colors[12] = get_sys_col(COLOR_INACTIVEBORDER);
+               evt->sys_cols.sys_colors[13] = get_sys_col(COLOR_INACTIVECAPTION);
+               evt->sys_cols.sys_colors[14] = get_sys_col(COLOR_INACTIVECAPTIONTEXT);
+               evt->sys_cols.sys_colors[15] = get_sys_col(COLOR_INFOBK);
+               evt->sys_cols.sys_colors[16] = get_sys_col(COLOR_INFOTEXT);
+               evt->sys_cols.sys_colors[17] = get_sys_col(COLOR_MENU);
+               evt->sys_cols.sys_colors[18] = get_sys_col(COLOR_MENUTEXT);
+               evt->sys_cols.sys_colors[19] = get_sys_col(COLOR_SCROLLBAR);
+               evt->sys_cols.sys_colors[20] = get_sys_col(COLOR_3DDKSHADOW);
+               evt->sys_cols.sys_colors[21] = get_sys_col(COLOR_3DFACE);
+               evt->sys_cols.sys_colors[22] = get_sys_col(COLOR_3DHIGHLIGHT);
+               evt->sys_cols.sys_colors[23] = get_sys_col(COLOR_3DLIGHT);
+               evt->sys_cols.sys_colors[24] = get_sys_col(COLOR_3DSHADOW);
+               evt->sys_cols.sys_colors[25] = get_sys_col(COLOR_WINDOW);
+               evt->sys_cols.sys_colors[26] = get_sys_col(COLOR_WINDOWFRAME);
+               evt->sys_cols.sys_colors[27] = get_sys_col(COLOR_WINDOWTEXT);
+               return 1;
+#else
+               memset(evt->sys_cols.sys_colors, 0, sizeof(u32)*28);
+               return 1;
+#endif
+       }
+       return 0;
+}
+
+
+
+bool wxOsmo4App::OnInit()
+{
+#ifdef __WXGTK__
+       XSynchronize((Display *) wxGetDisplay(), 1);
+#endif
+       wxFrame *frame = new wxOsmo4Frame();
+       frame->Show(TRUE);
+       SetTopWindow(frame);
+       return true;
+}
+
+
+class myDropfiles : public wxFileDropTarget
+{
+public:
+       myDropfiles() : wxFileDropTarget() {}
+       virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames);
+       wxOsmo4Frame *m_pMain;
+};
+
+bool myDropfiles::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
+{
+       u32 count = filenames.GetCount();
+
+       if (count==1) {
+               const char *ext = strrchr(filenames.Item(0).mb_str(wxConvUTF8) , '.');
+               /*if playing and sub d&d, open sub in current presentation*/
+               if (m_pMain->m_connected && ext && ( !stricmp(ext, ".srt") || !stricmp(ext, ".sub") || !stricmp(ext, ".ttxt") || !stricmp(ext, ".xml") ) ) {
+                       m_pMain->AddSubtitle(filenames.Item(0).mb_str(wxConvUTF8) , 1);
+                       return TRUE;
+               }
+       }
+
+       for (u32 i=0; i<count; i++)
+               m_pMain->m_pPlayList->QueueURL(filenames.Item(i));
+
+       m_pMain->m_pPlayList->RefreshList();
+       m_pMain->m_pPlayList->PlayNext();
+       return TRUE;
+}
+
+bool GPACLogs::OnFrameClose(wxFrame *frame)
+{
+       Show(FALSE);
+       return 0;
+}
+
+void wxOsmo4Frame::ShowViewWindow(Bool do_show)
+{
+       m_pView->Show(do_show ? 1 : 0);
+#ifdef __WXGTK__
+       //m_pView->Show(0);
+#endif
+}
+
+#ifdef __WXGTK__
+extern "C" {
+#ifdef __WXGTK20__
+    int gdk_x11_drawable_get_xid( void * );
+    void *gdk_x11_drawable_get_xdisplay( void * );
+#endif
+    void *gtk_widget_get_parent_window( void * );
+}
+#endif
+
+
+void wxOsmo4Frame::CheckVideoOut()
+{
+       const char *sOpt = gf_cfg_get_key(m_user.config, "Video", "DriverName");
+       void *os_handle = NULL;
+       void *os_display = NULL;
+       /*build a child window for embed display*/
+       if (sOpt && stricmp(sOpt, "SDL Video Output")) {
+               if (m_user.os_window_handler) return;
+               m_bExternalView = 0;
+
+#ifdef __WXGTK__
+               GtkWidget* widget = m_pVisual->GetHandle();
+
+#ifdef __WXGTK20__
+               os_handle = (void *) gdk_x11_drawable_get_xid(gtk_widget_get_parent_window(widget));
+#else
+               os_handle = (void *)*(int *)( (char *)gtk_widget_get_parent_window(widget) + 2 * sizeof(void *) );
+#endif
+
+#elif defined (WIN32)
+               os_handle = m_pView->GetHandle();
+#endif
+               if (os_handle) {
+                       m_user.os_window_handler = os_handle;
+                       m_user.os_display = os_display;
+                       ShowViewWindow(1);
+                       m_pView->SetSize(320, 240);
+                       SetSize(wxSize(320, 240+FRAME_H));
+                       SetWindowStyle(wxDEFAULT_FRAME_STYLE);
+                       DoLayout(320, 240);
+                       return;
+               }
+       }
+       /*we're using SDL, don't use SDL hack*/
+       m_bExternalView = 1;
+       m_user.os_window_handler = 0;
+       m_user.os_display = NULL;
+       SetSize(wxSize(320,FRAME_H));
+       m_pView->SetSize(0, 0);
+       ShowViewWindow(0);
+       DoLayout();
+       SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER));
+}
+
+static void wxOsmo4_do_log(void *cbk, u32 level, u32 tool, const char *fmt, va_list list)
+{
+       wxOsmo4Frame *osmo = (wxOsmo4Frame *)cbk;
+
+       if (osmo->m_logs) {
+               vfprintf(osmo->m_logs, fmt, list);
+               fflush(osmo->m_logs);
+       } else {
+               ::wxVLogMessage(wxString(fmt, wxConvUTF8), list);
+       }
+}
+
+
+Bool wxOsmo4Frame::LoadTerminal()
+{
+       m_term = NULL;
+       memset(&m_user, 0, sizeof(GF_User));
+
+       /*locate exec dir for cfg file*/
+    wxPathList pathList;
+       wxString currentDir(wxGetCwd());
+    wxString abs_gpac_path = wxT("");
+       char *gpac_cfg, *sep;
+
+       ::wxLogMessage(wxT("Looking for GPAC configuration file"));
+
+       /*load config*/
+       Bool first_launch = 0;
+       m_user.config = gf_cfg_init(NULL, &first_launch);
+
+       if (!m_user.config) {
+               wxMessageDialog(NULL, wxT("Cannot open GPAC configuration file"), wxT("Init error"), wxOK);
+               return 0;
+       }
+
+       gpac_cfg = gf_cfg_get_filename(m_user.config);
+       sep = strrchr(gpac_cfg, '/');
+       if (!sep) sep = strrchr(gpac_cfg, '\\');
+       if (sep) sep[0] = 0;
+       strcpy(szAppPath, gpac_cfg);
+       if (sep) sep[0] = '/';
+       gf_free(gpac_cfg);
+
+       /*check log file*/
+       const char *str = gf_cfg_get_key(m_user.config, "General", "LogFile");
+       if (str) m_logs = fopen(str, "wt");
+       gf_log_set_callback(this, wxOsmo4_do_log);
+
+       /*set log level*/
+       gf_log_set_tools_levels( gf_cfg_get_key(m_user.config, "General", "Logs") );
+
+       gf_sys_init(0);
+
+       ::wxLogMessage(wxT("GPAC configuration file opened - looking for modules"));
+
+       m_user.modules = gf_modules_new(str, m_user.config);
+       /*initial launch*/
+       if (!m_user.modules || !gf_modules_get_count(m_user.modules)) {
+               wxMessageDialog(NULL, wxT("No modules available - system cannot work"), wxT("Fatal Error"), wxOK).ShowModal();
+               if (m_user.modules) gf_modules_del(m_user.modules);
+               gf_cfg_del(m_user.config);
+               m_user.config = NULL;
+               return 0;
+       }
+
+       if (first_launch) {
+               u32 i;
+               for (i=0; i<gf_modules_get_count(m_user.modules); i++) {
+                       GF_InputService *ifce = (GF_InputService *) gf_modules_load_interface(m_user.modules, i, GF_NET_CLIENT_INTERFACE);
+                       if (!ifce) continue;
+                       if (ifce) {
+                               ifce->CanHandleURL(ifce, "test.test");
+                               gf_modules_close_interface((GF_BaseInterface *) ifce);
+                       }
+               }
+       }
+
+
+
+       ::wxLogMessage(wxT("%d modules found:"), gf_modules_get_count(m_user.modules));
+       for (u32 i=0; i<gf_modules_get_count(m_user.modules); i++) {
+               ::wxLogMessage(wxT("\t") + wxString(gf_modules_get_file_name(m_user.modules, i), wxConvUTF8) );
+       }
+
+       ::wxLogMessage(wxT("Starting GPAC Terminal"));
+       /*now load terminal*/
+       m_user.opaque = this;
+       m_user.EventProc = GPAC_EventProc;
+
+       CheckVideoOut();
+
+       m_term = gf_term_new(&m_user);
+       if (!m_term) {
+               wxMessageDialog(NULL, wxT("Fatal Error"), wxT("Cannot load GPAC Terminal"), wxOK).ShowModal();
+               return 0;
+       } else {
+               ::wxLogMessage(wxT("GPAC Terminal started") );
+       }
+       return 1;
+}
+
+
+
+wxOsmo4Frame::wxOsmo4Frame() :
+               wxFrame((wxFrame *) NULL, -1, wxT("Osmo4 - GPAC"), wxPoint(-1, -1), wxSize(320, FRAME_H), //wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER)
+wxDEFAULT_FRAME_STYLE
+               )
+
+{
+       int ws[3];
+       m_Address = NULL;
+       m_pView = NULL;
+       m_term = NULL;
+       SetIcon(wxIcon(osmo4));
+       m_bExternalView = 0;
+       m_last_prog = -1;
+       m_num_chapters = 0;
+       m_chapters_start = NULL;
+       m_bViewRTI = 0;
+       m_logs = NULL;
+       m_bStartupFile = 0;
+       gf_set_progress_callback(this, wxOsmo4_progress_cbk);
+
+       myDropfiles *droptarget = new myDropfiles();
+       droptarget->m_pMain = this;
+       SetDropTarget(droptarget);
+       m_pLogs = new GPACLogs(this);
+       m_bGrabbed = 0;
+
+       /*new menu bar*/
+       wxMenuBar *b = new wxMenuBar();
+       /*file*/
+       wxMenu *menu = new wxMenu();
+       menu->Append(GWX_FILE_OPEN, wxT("&Open File\tCtrl+O"), wxT("Open local presentation"));
+       menu->Append(GWX_FILE_OPEN_URL, wxT("&Open URL\tCtrl+U"), wxT("Open remote presentation"));
+       menu->AppendSeparator();
+       menu->Append(FILE_PROPERTIES, wxT("&Properties\tCtrl+I"), wxT("Show presentation properties"));
+       menu->Enable(FILE_PROPERTIES, 0);
+       wxMenu *smenu = new wxMenu();
+       smenu->Append(ID_MCACHE_ENABLE, wxT("&Enable"), wxT("Turns Recorder On/Off"));
+       smenu->Append(ID_MCACHE_STOP, wxT("&Stop"), wxT("Stops recording and saves"));
+       smenu->Append(ID_MCACHE_ABORT, wxT("&Abort"), wxT("Stops recording and discards"));
+       menu->Append(0, wxT("&Streaming Cache"), smenu);
+       menu->AppendSeparator();
+       menu->Append(FILE_COPY, wxT("&Copy\tCtrl+C"), wxT("Copy selected text"));
+       menu->Append(FILE_PASTE, wxT("&Paste\tCtrl+V"), wxT("Copy selected text"));
+       menu->AppendSeparator();
+       menu->Append(FILE_QUIT, wxT("E&xit"), wxT("Quit the application"));
+       b->Append(menu, wxT("&File"));
+       /*view*/
+       menu = new wxMenu();
+       vp_list = new wxMenu();
+       menu->Append(0, wxT("&Viewpoint"), vp_list);
+       smenu = new wxMenu();
+       smenu->Append(ID_HEADLIGHT, wxT("Headlight"), wxT("Turns headlight on/off"), wxITEM_CHECK);
+       smenu->AppendSeparator();
+       smenu->Append(ID_NAVIGATE_NONE, wxT("None"), wxT("Disables Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_WALK, wxT("Walk"), wxT("Walk Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_FLY, wxT("Fly"), wxT("Fly Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_EXAMINE, wxT("Examine"), wxT("Examine Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_PAN, wxT("Pan"), wxT("Pan Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_SLIDE, wxT("Slide"), wxT("Slide Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_ORBIT, wxT("Orbit"), wxT("Orbit Navigation"), wxITEM_CHECK);
+       smenu->Append(ID_NAVIGATE_GAME, wxT("Game"), wxT("Game Navigation"), wxITEM_CHECK);
+       smenu->AppendSeparator();
+       wxMenu *ssmenu = new wxMenu();
+       ssmenu->Append(ID_COLLIDE_NONE, wxT("None"), wxT("No Collision detection"), wxITEM_CHECK);
+       ssmenu->Append(ID_COLLIDE_REG, wxT("Regular"), wxT("Regular Collision detection"), wxITEM_CHECK);
+       ssmenu->Append(ID_COLLIDE_DISP, wxT("Displacement"), wxT("Collision detecion with camera displacement"), wxITEM_CHECK);
+       smenu->Append(0, wxT("&Collision"), ssmenu);
+       smenu->Append(ID_GRAVITY, wxT("Gravity"), wxT("Turns gravity on/off"), wxITEM_CHECK);
+       smenu->AppendSeparator();
+       smenu->Append(ID_NAVIGATE_RESET, wxT("Reset"), wxT("Reset Navigation"));
+
+       menu->Append(0, wxT("&Navigation"), smenu);
+       menu->AppendSeparator();
+       menu->Append(VIEW_FULLSCREEN, wxT("&Fullscreen"), wxT("Toggles Fullscreen"), wxITEM_CHECK);
+       menu->Append(VIEW_ORIGINAL, wxT("&Original Size"), wxT("Restore original size"));
+       smenu = new wxMenu();
+       smenu->Append(VIEW_AR_KEEP, wxT("Keep Original\tCtrl+1"), wxT("Keep original aspect ratio"), wxITEM_CHECK);
+       smenu->Append(VIEW_AR_FILL, wxT("Fill Screen\tCtrl+2"), wxT("Stretch presentation to fill screen"), wxITEM_CHECK);
+       smenu->Append(VIEW_AR_43, wxT("Ratio 4/3\tCtrl+3"), wxT("Force aspect ratio to 4/3"), wxITEM_CHECK);
+       smenu->Append(VIEW_AR_169, wxT("Ratio 16/9\tCtrl+4"), wxT("Force aspect ratio to 16/9"), wxITEM_CHECK);
+       menu->Append(0, wxT("&Aspect Ratio"), smenu);
+       smenu->Check(VIEW_AR_KEEP, 1);
+       menu->AppendSeparator();
+       menu->Append(VIEW_OPTIONS, wxT("&Options"), wxT("View Options"));
+       menu->AppendSeparator();
+       menu->Append(VIEW_RTI, wxT("&Resource Usage"), wxT("View Resource Usage"), wxITEM_CHECK);
+       menu->Append(VIEW_LOGS, wxT("&Logs"), wxT("View GPAC logs"));
+       b->Append(menu, wxT("&View"));
+
+       /*play*/
+       menu = new wxMenu();
+       sel_menu = new wxMenu();
+       sel_menu->Append(0, wxT("&Audio"), new wxMenu());
+       sel_menu->Append(0, wxT("&Video"), new wxMenu());
+       sel_menu->Append(0, wxT("&Subtitles"), new wxMenu());
+       sel_menu->AppendSeparator();
+       sel_menu->Append(ID_ADD_SUB, wxT("&Add Subtitle"), wxT("Adds subtitle"));
+       menu->Append(ID_STREAM_MENU, wxT("&Streams Selection"), sel_menu);
+       chap_menu = new wxMenu();
+       menu->Append(ID_CHAPTER_MENU, wxT("&Chapters"), chap_menu);
+
+       menu->AppendSeparator();
+       menu->Append(VIEW_PLAYLIST, wxT("&Playlist\tCtrl+L"), wxT("Show navigation history as playlist"), wxITEM_CHECK);
+       menu->Append(ID_CLEAR_NAV, wxT("&Clear History"), wxT("Clear navigation history"));
+       menu->AppendSeparator();
+       menu->Append(FILE_PLAY, wxT("&Play/Pause\tCtrl+P"), wxT("Play/Pause/Resume Presentation"));
+       menu->Append(FILE_STEP, wxT("&Step-by-Step\tCtrl+S"), wxT("Play/Pause/Resume Presentation"));
+       menu->Append(FILE_STOP, wxT("&Stop"), wxT("Stop Presentation"));
+       menu->AppendSeparator();
+       menu->Append(FILE_RELOAD_CONFIG, wxT("&Reload Config\tCtrl+R"), wxT("Reload Configuration File"));
+       menu->Append(FILE_RELOAD, wxT("&Reload File\tCtrl+R"), wxT("Reload Presentation"));
+       b->Append(menu, wxT("&Play"));
+
+       menu = new wxMenu();
+       menu->Append(APP_SHORTCUTS, wxT("&Shortcuts"), wxT("Show keyboard shortcuts"));
+       menu->Append(APP_NAV_KEYS, wxT("&Navigation Keys"), wxT("Show navigation keys"));
+       menu->AppendSeparator();
+       menu->Append(APP_ABOUT, wxT("&About"), wxT("Display information and copyright"));
+       b->Append(menu, wxT("&?"));
+
+       SetMenuBar(b);
+
+       m_pStatusbar = CreateStatusBar(1, 0, -1, wxT("statusBar"));
+       ws[0] = 60;
+       ws[1] = 70;
+       ws[2] = -1;
+       m_pStatusbar->SetFieldsCount(3, ws);
+
+       SetStatusBarPane(2);
+       wxColour foreCol = m_pStatusbar->GetBackgroundColour();
+       SetBackgroundColour(foreCol);
+
+
+       m_pTimer = new wxTimer();
+       m_pTimer->SetOwner(this, ID_CTRL_TIMER);
+       m_bGrabbed = 0;
+
+       /*create toolbar*/
+       m_pToolBar = CreateToolBar(wxTB_FLAT|wxTB_HORIZONTAL);
+       m_pOpenFile = new wxBitmap(tool_open_file);
+       m_pPrev = new wxBitmap(tool_prev);
+       m_pNext = new wxBitmap(tool_next);
+       m_pPlay = new wxBitmap(tool_play);
+       m_pPause = new wxBitmap(tool_pause);
+       m_pStep = new wxBitmap(tool_step);
+       m_pStop = new wxBitmap(tool_stop);
+       m_pInfo = new wxBitmap(tool_info);
+       m_pConfig = new wxBitmap(tool_config);
+       m_pSW2D = new wxBitmap(tool_sw_2d);
+       m_pSW3D = new wxBitmap(tool_sw_3d);
+
+       m_pToolBar->AddTool(GWX_FILE_OPEN, wxT(""), *m_pOpenFile, wxT("Open File"));
+       m_pToolBar->AddSeparator();
+       m_pPrevBut = new wxMenuButton(m_pToolBar, FILE_PREV, *m_pPrev);
+       m_pPrevBut->SetToolTip(wxT("Previous Location"));
+       m_pToolBar->AddControl(m_pPrevBut);
+       m_pNextBut = new wxMenuButton(m_pToolBar, FILE_NEXT, *m_pNext);
+       m_pNextBut->SetToolTip(wxT("Next Location"));
+       m_pToolBar->AddControl(m_pNextBut);
+
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddTool(FILE_PLAY, wxT(""), *m_pPlay, wxT("Play/Pause File"));
+       m_pToolBar->AddTool(FILE_STEP, wxT(""), *m_pStep, wxT("Step-by-Step Mode"));
+       m_pToolBar->AddTool(FILE_STOP, wxT(""), *m_pStop, wxT("Stop File"));
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddTool(FILE_PROPERTIES, wxT(""), *m_pInfo, wxT("Show File Information"));
+       m_pToolBar->AddSeparator();
+       m_pToolBar->AddTool(VIEW_OPTIONS, wxT(""), *m_pConfig, wxT("GPAC Configuration"));
+       m_pToolBar->AddTool(SWITCH_RENDER, wxT(""), *m_pSW3D, wxT("Switch 2D/3D Renderers"));
+
+       m_pToolBar->Realize();
+
+       m_Address = new wxMyComboBox(this, ID_ADDRESS, wxT(""), wxPoint(50, 0), wxSize(80, 20));
+       wxStaticText *add_text = new wxStaticText(this, -1, wxT("URL"), wxPoint(0, 0), wxSize(40, 20));
+       add_text->SetBackgroundColour(foreCol);
+
+       m_pAddBar = new wxBoxSizer(wxHORIZONTAL);
+       m_pAddBar->Add(add_text, 0, wxALIGN_TOP);
+       m_pAddBar->Add(m_Address, 2, wxALIGN_CENTER|wxEXPAND|wxADJUST_MINSIZE);
+       m_pAddBar->SetMinSize(80, 32);
+       m_pAddBar->Layout();
+
+       m_pProg = new wxSlider(this, ID_SLIDER, 0, 0, 1000, wxPoint(0, 22), wxSize(80, 22), wxSL_HORIZONTAL|wxSUNKEN_BORDER);
+       m_pProg->Enable(0);
+       m_pProg->Show();
+       m_pProg->SetBackgroundColour(foreCol);
+
+       m_pView = new wxWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
+       m_pView->SetBackgroundColour(wxColour(wxT("BLACK")));
+#ifdef __WXGTK__
+       m_pVisual = new wxWindow(m_pView, -1, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
+       m_pVisual->SetBackgroundColour(wxColour(wxT("BLACK")));
+#endif
+
+       m_pPlayList = new wxPlaylist(this);
+       m_pPlayList->SetIcon(wxIcon(osmo4));
+       m_pPlayList->Hide();
+       Raise();
+       Show();
+
+       m_connected = 0;
+       if (!LoadTerminal()) {
+               Close(TRUE);
+               return;
+       }
+
+
+
+       if (m_bExternalView) SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER));
+       DoLayout(320, 240);
+       UpdateRenderSwitch();
+
+       const char *sOpt = gf_cfg_get_key(m_user.config, "General", "ConsoleOff");
+       m_console_off = (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0;
+       sOpt = gf_cfg_get_key(m_user.config, "General", "Loop");
+       m_loop = (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0;
+       sOpt = gf_cfg_get_key(m_user.config, "General", "LookForSubtitles");
+       m_lookforsubs = (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0;
+       gf_term_set_option(m_term, GF_OPT_AUDIO_VOLUME, 100);
+
+       ReloadURLs();
+       Raise();
+       m_pStatusbar->SetStatusText(wxT("Ready"), 2);
+       m_LastStatusTime = 0;
+
+       m_pPrevBut->Refresh();
+       m_pNextBut->Refresh();
+
+       wxOsmo4App &app = wxGetApp();
+       if (app.argc>1) {
+               m_pPlayList->QueueURL(wxString(app.argv[1]));
+               m_pPlayList->RefreshList();
+               m_pPlayList->PlayNext();
+       } else {
+               char sPL[GF_MAX_PATH];
+               strcpy((char *) sPL, szAppPath);
+#ifdef WIN32
+               strcat(sPL, "gpac_pl.m3u");
+#else
+               strcat(sPL, ".gpac_pl.m3u");
+#endif
+               m_pPlayList->OpenPlaylist(wxString(sPL, wxConvUTF8) );
+               const char *sOpt = gf_cfg_get_key(m_user.config, "General", "PLEntry");
+               if (sOpt) {
+                       m_pPlayList->m_cur_entry = atoi(sOpt);
+                       if (m_pPlayList->m_cur_entry>=(s32)gf_list_count(m_pPlayList->m_entries))
+                               m_pPlayList->m_cur_entry = -1;
+               }
+
+               sOpt = gf_cfg_get_key(m_user.config, "General", "StartupFile");
+               if (sOpt) {
+                       gf_term_connect(m_term, sOpt);
+                       m_bStartupFile = 1;
+               }
+       }
+
+       sOpt = gf_cfg_get_key(m_user.config, "Audio", "DriverName");
+
+       if (!strcmp(sOpt, "No Audio Output Available")) {
+         ::wxLogMessage(wxT("WARNING: no audio output availble - make sure no other program is locking the sound card"));
+         SetStatus(wxT("No audio ouput available"));
+
+       } else {
+         SetStatus(wxT("Ready"));
+       }
+}
+
+wxOsmo4Frame::~wxOsmo4Frame()
+{
+       vp_list = NULL;
+       sel_menu = NULL;
+
+       if (m_user.modules) gf_modules_del(m_user.modules);
+       gf_sys_close();
+       if (m_user.config) gf_cfg_del(m_user.config);
+
+       if (m_chapters_start) gf_free(m_chapters_start);
+       if (m_pView) delete m_pView;
+
+       //m_pToolBar->RemoveTool(FILE_PREV);
+       //m_pToolBar->RemoveTool(FILE_NEXT);
+
+       delete m_pPrevBut;
+       delete m_pNextBut;
+       delete m_pPlayList;
+       delete m_pTimer;
+       delete m_pOpenFile;
+       delete m_pPrev;
+       delete m_pNext;
+       delete m_pPlay;
+       delete m_pPause;
+       delete m_pStep;
+       delete m_pStop;
+       delete m_pInfo;
+       delete m_pConfig;
+       delete m_pSW2D;
+       delete m_pSW3D;
+}
+
+
+BEGIN_EVENT_TABLE(wxOsmo4Frame, wxFrame)
+       EVT_CLOSE(wxOsmo4Frame::OnCloseApp)
+       EVT_MENU(GWX_FILE_OPEN, wxOsmo4Frame::OnFileOpen)
+       EVT_MENU(GWX_FILE_OPEN_URL, wxOsmo4Frame::OnFileOpenURL)
+       EVT_MENU(FILE_RELOAD_CONFIG, wxOsmo4Frame::OnFileReloadConfig)
+       EVT_MENU(FILE_RELOAD, wxOsmo4Frame::OnFileReload)
+       EVT_MENU(FILE_PROPERTIES, wxOsmo4Frame::OnFileProperties)
+       EVT_MENU(FILE_QUIT, wxOsmo4Frame::OnFileQuit)
+       EVT_MENU(VIEW_FULLSCREEN, wxOsmo4Frame::OnFullScreen)
+       EVT_MENU(VIEW_OPTIONS, wxOsmo4Frame::OnOptions)
+       EVT_MENU(VIEW_AR_KEEP, wxOsmo4Frame::OnViewARKeep)
+       EVT_MENU(VIEW_AR_FILL, wxOsmo4Frame::OnViewARFill)
+       EVT_MENU(VIEW_AR_169, wxOsmo4Frame::OnViewAR169)
+       EVT_MENU(VIEW_AR_43, wxOsmo4Frame::OnViewAR43)
+       EVT_MENU(VIEW_ORIGINAL, wxOsmo4Frame::OnViewOriginal)
+       EVT_MENU(VIEW_PLAYLIST, wxOsmo4Frame::OnPlaylist)
+       EVT_UPDATE_UI(VIEW_PLAYLIST, wxOsmo4Frame::OnUpdatePlayList)
+       EVT_MENU(FILE_COPY, wxOsmo4Frame::OnFileCopy)
+       EVT_UPDATE_UI(FILE_COPY, wxOsmo4Frame::OnUpdateFileCopy)
+       EVT_MENU(FILE_PASTE, wxOsmo4Frame::OnFilePaste)
+       EVT_UPDATE_UI(FILE_PASTE, wxOsmo4Frame::OnUpdateFilePaste)
+
+       EVT_MENU(ID_CLEAR_NAV, wxOsmo4Frame::OnClearNav)
+       EVT_UPDATE_UI(ID_STREAM_MENU, wxOsmo4Frame::OnUpdateStreamMenu)
+       EVT_UPDATE_UI(ID_CHAPTER_MENU, wxOsmo4Frame::OnUpdateChapterMenu)
+       EVT_MENU(ID_ADD_SUB, wxOsmo4Frame::OnAddSub)
+
+       EVT_MENU(ID_MCACHE_ENABLE, wxOsmo4Frame::OnCacheEnable)
+       EVT_UPDATE_UI(ID_MCACHE_ENABLE, wxOsmo4Frame::OnUpdateCacheEnable)
+       EVT_MENU(ID_MCACHE_STOP, wxOsmo4Frame::OnCacheStop)
+       EVT_MENU(ID_MCACHE_ABORT, wxOsmo4Frame::OnCacheAbort)
+       EVT_UPDATE_UI(ID_MCACHE_STOP, wxOsmo4Frame::OnUpdateCacheAbort)
+       EVT_UPDATE_UI(ID_MCACHE_ABORT, wxOsmo4Frame::OnUpdateCacheAbort)
+
+
+       EVT_MENU(APP_SHORTCUTS, wxOsmo4Frame::OnShortcuts)
+       EVT_MENU(APP_NAV_KEYS, wxOsmo4Frame::OnNavInfo)
+       EVT_MENU(APP_ABOUT, wxOsmo4Frame::OnAbout)
+       EVT_GPACEVENT(wxOsmo4Frame::OnGPACEvent)
+       EVT_TIMER(ID_CTRL_TIMER, wxOsmo4Frame::OnTimer)
+       EVT_COMMAND_SCROLL(ID_SLIDER, wxOsmo4Frame::OnSlide)
+       EVT_MENU(VIEW_LOGS, wxOsmo4Frame::OnLogs)
+       EVT_MENU(VIEW_RTI, wxOsmo4Frame::OnRTI)
+
+       EVT_MENUBUTTON_OPEN(FILE_PREV, wxOsmo4Frame::OnFilePrevOpen)
+       EVT_MENUBUTTON_OPEN(FILE_NEXT, wxOsmo4Frame::OnFileNextOpen)
+    EVT_MENU(FILE_PREV, wxOsmo4Frame::OnNavPrev)
+       EVT_UPDATE_UI(FILE_PREV, wxOsmo4Frame::OnUpdateNavPrev)
+    EVT_MENU_RANGE(ID_NAV_PREV_0, ID_NAV_PREV_9, wxOsmo4Frame::OnNavPrevMenu)
+    EVT_MENU(FILE_NEXT, wxOsmo4Frame::OnNavNext)
+       EVT_UPDATE_UI(FILE_NEXT, wxOsmo4Frame::OnUpdateNavNext)
+    EVT_MENU_RANGE(ID_NAV_NEXT_0, ID_NAV_NEXT_9, wxOsmo4Frame::OnNavNextMenu)
+
+       EVT_TOOL(FILE_PLAY, wxOsmo4Frame::OnFilePlay)
+       EVT_TOOL(FILE_STEP, wxOsmo4Frame::OnFileStep)
+    EVT_TOOL(FILE_STOP, wxOsmo4Frame::OnFileStop)
+    EVT_TOOL(SWITCH_RENDER, wxOsmo4Frame::OnRenderSwitch)
+
+       EVT_COMBOBOX(ID_ADDRESS, wxOsmo4Frame::OnURLSelect)
+
+    EVT_MENU_RANGE(ID_SELSTREAM_0, ID_SELSTREAM_9, wxOsmo4Frame::OnStreamSel)
+       EVT_UPDATE_UI_RANGE(ID_SELSTREAM_0, ID_SELSTREAM_9, wxOsmo4Frame::OnUpdateStreamSel)
+
+    EVT_MENU_RANGE(ID_SETCHAP_FIRST, ID_SETCHAP_LAST, wxOsmo4Frame::OnChapterSel)
+       EVT_UPDATE_UI_RANGE(ID_SETCHAP_FIRST, ID_SETCHAP_LAST, wxOsmo4Frame::OnUpdateChapterSel)
+
+    EVT_MENU_RANGE(ID_VIEWPOINT_FIRST, ID_VIEWPOINT_LAST, wxOsmo4Frame::OnViewport)
+       EVT_UPDATE_UI_RANGE(ID_VIEWPOINT_FIRST, ID_VIEWPOINT_LAST, wxOsmo4Frame::OnUpdateViewport)
+
+    EVT_MENU_RANGE(ID_NAVIGATE_NONE, ID_NAVIGATE_GAME, wxOsmo4Frame::OnNavigate)
+       EVT_UPDATE_UI_RANGE(ID_NAVIGATE_NONE, ID_NAVIGATE_GAME, wxOsmo4Frame::OnUpdateNavigation)
+       EVT_MENU(ID_NAVIGATE_RESET, wxOsmo4Frame::OnNavigateReset)
+
+    EVT_MENU_RANGE(ID_COLLIDE_NONE, ID_COLLIDE_DISP, wxOsmo4Frame::OnCollide)
+       EVT_UPDATE_UI_RANGE(ID_COLLIDE_NONE, ID_COLLIDE_DISP, wxOsmo4Frame::OnUpdateCollide)
+
+       EVT_MENU(ID_HEADLIGHT, wxOsmo4Frame::OnHeadlight)
+       EVT_UPDATE_UI(ID_HEADLIGHT, wxOsmo4Frame::OnUpdateHeadlight)
+       EVT_MENU(ID_GRAVITY, wxOsmo4Frame::OnGravity)
+       EVT_UPDATE_UI(ID_GRAVITY, wxOsmo4Frame::OnUpdateGravity)
+
+       EVT_UPDATE_UI(FILE_PROPERTIES, wxOsmo4Frame::OnUpdateNeedsConnect)
+       EVT_UPDATE_UI(FILE_RELOAD, wxOsmo4Frame::OnUpdateNeedsConnect)
+       EVT_UPDATE_UI(FILE_PLAY, wxOsmo4Frame::OnUpdatePlay)
+       EVT_UPDATE_UI(FILE_STOP, wxOsmo4Frame::OnUpdateNeedsConnect)
+       EVT_UPDATE_UI(FILE_STEP, wxOsmo4Frame::OnUpdateNeedsConnect)
+       EVT_UPDATE_UI(VIEW_ORIGINAL, wxOsmo4Frame::OnUpdateNeedsConnect)
+       EVT_UPDATE_UI(VIEW_FULLSCREEN, wxOsmo4Frame::OnUpdateFullScreen)
+       EVT_UPDATE_UI(VIEW_AR_KEEP, wxOsmo4Frame::OnUpdateAR)
+       EVT_UPDATE_UI(VIEW_AR_FILL, wxOsmo4Frame::OnUpdateAR)
+       EVT_UPDATE_UI(VIEW_AR_169, wxOsmo4Frame::OnUpdateAR)
+       EVT_UPDATE_UI(VIEW_AR_43, wxOsmo4Frame::OnUpdateAR)
+
+       EVT_SIZE(wxOsmo4Frame::OnSize)
+END_EVENT_TABLE()
+
+void wxOsmo4Frame::DoLayout(u32 v_width, u32 v_height)
+{
+       wxPoint pos;
+       if (!m_Address || !m_pProg) return;
+
+       int t_h = m_pToolBar->GetSize().y;
+       int a_h = m_pAddBar->GetSize().y;
+       int p_h = m_pProg->GetSize().y;
+
+       if (m_bExternalView) {
+         if (v_width && v_height) {
+               m_orig_width = v_width;
+               m_orig_height = v_height;
+         }
+         SetClientSize(320, a_h+p_h+t_h);
+         m_pAddBar->SetDimension(0,0, 320, a_h);
+         m_pProg->SetSize(0, t_h+a_h, 320, p_h, 0);
+         return;
+       }
+
+       if (v_width && v_height) {
+               m_orig_width = v_width;
+               m_orig_height = v_height;
+               v_height += a_h + p_h + t_h;
+               SetClientSize(v_width, v_height);
+               m_pView->SetSize(0, a_h+t_h, v_width, v_height, 0);
+               m_pAddBar->SetDimension(0, t_h, v_width, a_h);
+               m_pProg->SetSize(0, v_height - p_h, v_width, p_h, 0);
+       }
+       wxSize s = GetClientSize();
+       s.y -= a_h + p_h + t_h;
+       if (m_pView) {
+               m_pView->SetSize(0, a_h+t_h, s.x, s.y, 0);
+               m_pAddBar->SetDimension(0, 0, s.x, a_h);
+               m_pAddBar->SetDimension(0, 0, s.x, a_h);
+               m_pAddBar->Layout();
+               m_pProg->SetSize(0, s.y+t_h+a_h, s.x, p_h, 0);
+               if (m_term) gf_term_set_size(m_term, s.x, s.y);
+       }
+}
+
+void wxOsmo4Frame::OnSize(wxSizeEvent &event)
+{
+       DoLayout();
+}
+
+void wxOsmo4Frame::OnCloseApp(wxCloseEvent &WXUNUSED(event))
+{
+       if (m_term) gf_term_del(m_term);
+       m_term = NULL;
+       Destroy();
+}
+
+
+wxString wxOsmo4Frame::GetFileFilter()
+{
+       u32 keyCount, i;
+       wxString sFiles, sSupportedFiles, sExts;
+
+       /*force MP4 and 3GP files at beginning to make sure they are selected (Win32 bug with too large filters)*/
+       sSupportedFiles = wxT("All Known Files|*.m3u;*.pls;*.mp4;*.3gp;*.3g2");
+       sExts = wxT("");
+       sFiles = wxT("");
+       keyCount = gf_cfg_get_key_count(m_user.config, "MimeTypes");
+       for (i=0; i<keyCount; i++) {
+               Bool first = 1;
+               const char *sMime;
+               char *sKey;
+               const char *opt;
+               char szKeyList[1000], sDesc[1000];
+               sMime = gf_cfg_get_key_name(m_user.config, "MimeTypes", i);
+               if (!sMime) continue;
+               opt = gf_cfg_get_key(m_user.config, "MimeTypes", sMime);
+               /*remove module name*/
+               strcpy(szKeyList, opt+1);
+               sKey = strrchr(szKeyList, '\"');
+               if (!sKey) continue;
+               sKey[0] = 0;
+               /*get description*/
+               sKey = strrchr(szKeyList, '\"');
+               if (!sKey) continue;
+               strcpy(sDesc, sKey+1);
+               sKey[0] = 0;
+               sKey = strrchr(szKeyList, '\"');
+               if (!sKey) continue;
+               sKey[0] = 0;
+
+               /*if same description for # mime types skip (means an old mime syntax)*/
+               if (sFiles.Find(wxString(sDesc, wxConvUTF8) )>=0) continue;
+               /*if same extensions for # mime types skip (don't polluate the file list)*/
+               if (sExts.Find(wxString(szKeyList, wxConvUTF8) )>=0) continue;
+
+               sExts += wxString(szKeyList, wxConvUTF8);
+               sExts += wxT(" ");
+               sFiles += wxString(sDesc, wxConvUTF8);
+               sFiles += wxT("|");
+
+               wxString sOpt = wxString(szKeyList, wxConvUTF8);
+               while (1) {
+                       wxString ext = sOpt.BeforeFirst(' ');
+                       if (ext.Find('.')<0) {
+                               if (first) first = 0;
+                               else sFiles += wxT(";");
+                               sFiles += wxT("*.");
+                               sFiles += ext;
+                               wxString sext = ext;
+                               sext += wxT(";");
+                               if (sSupportedFiles.Find(sext)<0) {
+                                       sSupportedFiles  += wxT(";*.");
+                                       sSupportedFiles += ext;
+                               }
+                       }
+                       if (sOpt==ext) break;
+                       wxString rem = ext + wxT(" ");
+                       sOpt.Replace(rem, wxT(""), TRUE);
+               }
+               sFiles += wxT("|");
+       }
+       sSupportedFiles += wxT("|");
+       sSupportedFiles += sFiles;
+       sSupportedFiles += wxT("M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|All Files|*.*||");
+       return sSupportedFiles;
+}
+
+void wxOsmo4Frame::OnFileOpen(wxCommandEvent & WXUNUSED(event))
+{
+       wxFileDialog dlg(this, wxT("Select file(s)"), wxT(""), wxT(""), GetFileFilter(), wxOPEN | wxMULTIPLE | wxCHANGE_DIR /*| wxHIDE_READONLY*/);
+
+       if (dlg.ShowModal() != wxID_OK) return;
+
+       wxArrayString stra;
+       dlg.GetPaths(stra);
+       if (stra.GetCount() == 1) {
+               m_pPlayList->Truncate();
+       } else {
+               m_pPlayList->Clear();
+       }
+       for (u32 i=0; i<stra.GetCount(); i++)
+               m_pPlayList->QueueURL(stra[i]);
+
+       m_pPlayList->RefreshList();
+       m_pPlayList->PlayNext();
+}
+
+void wxOsmo4Frame::OnFileOpenURL(wxCommandEvent & WXUNUSED(event))
+{
+       OpenURLDlg dlg(this, m_user.config);
+       if (dlg.ShowModal()==wxID_OK) {
+               m_pPlayList->Truncate();
+               m_pPlayList->QueueURL(dlg.m_urlVal);
+               m_pPlayList->RefreshList();
+               m_pPlayList->PlayNext();
+       }
+}
+
+void wxOsmo4Frame::OnFileProperties(wxCommandEvent & WXUNUSED(event))
+{
+       wxFileProps dlg(this);
+       dlg.SetIcon(wxIcon(osmo4));
+       dlg.ShowModal();
+}
+
+void wxOsmo4Frame::OnFileReload(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_disconnect(m_term);
+       m_connected = 0;
+       DoConnect();
+}
+
+void wxOsmo4Frame::OnFileReloadConfig(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_RELOAD_CONFIG, 1);
+}
+
+void wxOsmo4Frame::OnFileQuit(wxCommandEvent & WXUNUSED(event))
+{
+       Close(FALSE);
+}
+
+void wxOsmo4Frame::OnViewOriginal(wxCommandEvent & WXUNUSED(event))
+{
+       if (!m_bExternalView) {
+               DoLayout(m_orig_width, m_orig_height);
+       } else {
+               gf_term_set_option(m_term, GF_OPT_ORIGINAL_VIEW, 1);
+       }
+}
+
+void wxOsmo4Frame::OnOptions(wxCommandEvent & WXUNUSED(event))
+{
+       wxGPACControl dlg(this);
+       dlg.SetIcon(wxIcon(osmo4));
+       dlg.ShowModal();
+}
+
+void wxOsmo4Frame::DoConnect()
+{
+       //if (m_connected) { gf_term_disconnect(m_term); m_connected = 0; }
+
+       wxString url = m_pPlayList->GetURL();
+       m_Address->SetValue(url);
+#ifdef __WXGTK__
+       m_pVisual->SetFocus();
+#else
+       m_pView->SetFocus();
+#endif
+       wxString txt = wxT("Osmo4 - ");
+       txt += m_pPlayList->GetDisplayName();
+       SetTitle(txt);
+       m_bStartupFile = 0;
+       gf_term_connect(m_term, url.mb_str(wxConvUTF8));
+}
+
+void wxOsmo4Frame::OnLogs(wxCommandEvent & WXUNUSED(event))
+{
+       m_pLogs->Show();
+}
+
+void wxOsmo4Frame::OnUpdateNeedsConnect(wxUpdateUIEvent &event)
+{
+       event.Enable(m_connected ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnUpdatePlay(wxUpdateUIEvent &event)
+{
+       event.Enable( (m_connected || m_pPlayList->HasValidEntries()) ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnUpdateFullScreen(wxUpdateUIEvent &event)
+{
+       if (m_connected) {
+               event.Enable(1);
+               event.Check(gf_term_get_option(m_term, GF_OPT_FULLSCREEN) ? 1 : 0);
+       } else {
+               event.Enable(0);
+       }
+}
+
+void wxOsmo4Frame::OnFullScreen(wxCommandEvent & WXUNUSED(event))
+{
+       Bool isFS = gf_term_get_option(m_term, GF_OPT_FULLSCREEN) ? 1 : 0;
+       gf_term_set_option(m_term, GF_OPT_FULLSCREEN, isFS ? 0 : 1);
+}
+
+void wxOsmo4Frame::OnViewARKeep(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_KEEP);
+}
+void wxOsmo4Frame::OnViewARFill(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_FILL_SCREEN);
+}
+void wxOsmo4Frame::OnViewAR169(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_16_9);
+}
+void wxOsmo4Frame::OnViewAR43(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_ASPECT_RATIO, GF_ASPECT_RATIO_4_3);
+}
+
+void wxOsmo4Frame::OnUpdateAR(wxUpdateUIEvent &event)
+{
+       if (!m_connected) {
+               event.Enable(0);
+               return;
+       }
+       event.Enable(1);
+       u32 val = gf_term_get_option(m_term, GF_OPT_ASPECT_RATIO);
+       if ((event.GetId() == VIEW_AR_FILL) && (val==GF_ASPECT_RATIO_FILL_SCREEN))
+               event.Check(1);
+       else if ((event.GetId() == VIEW_AR_KEEP) && (val==GF_ASPECT_RATIO_KEEP))
+               event.Check(1);
+       else if ((event.GetId() == VIEW_AR_169) && (val==GF_ASPECT_RATIO_16_9))
+               event.Check(1);
+       else if ((event.GetId() == VIEW_AR_43) && (val==GF_ASPECT_RATIO_4_3))
+               event.Check(1);
+       else event.Check(0);
+}
+
+void wxOsmo4Frame::OnShortcuts(wxCommandEvent & WXUNUSED(event))
+{
+       wxMessageDialog dlg(this,
+               wxT("Shortcuts with focus on main frame:\n")
+               wxT("Open File: Ctrl + O\n")
+               wxT("Show File Information: Ctrl + I\n")
+               wxT("Reload File: Ctrl + R\n")
+               wxT("Pause/Resume File: Ctrl + P\n")
+               wxT("Step by Step: Ctrl + S\n")
+               wxT("Fullscreen On/Off: Alt + Return\n")
+               wxT("View Playlist: Ctrl + L\n")
+               wxT("Aspect Ratio Normal: Ctrl + 1\n")
+               wxT("Aspect Ratio Fill: Ctrl + 2\n")
+               wxT("Aspect Ratio 4/3: Ctrl + 3\n")
+               wxT("Aspect Ratio 16/9: Ctrl + 4\n")
+               wxT("\n")
+               wxT("Shortcuts with focus on video frame:\n")
+               wxT("Seek +5% into presentation: Alt + right arrow\n")
+               wxT("Seek -5% into presentation: Alt + left arrow\n")
+               wxT("Seek +1min into presentation: Alt + up arrow\n")
+               wxT("Seek -1min into presentation: Alt + down arrow\n")
+               wxT("Next Playlist Entry: Ctrl + right arrow\n")
+               wxT("Prev Playlist Entry: Ctrl + left arrow\n")
+
+               , wxT("Shortcuts Available on Osmo4")
+               , wxOK);
+
+       dlg.ShowModal();
+}
+
+void wxOsmo4Frame::OnNavInfo(wxCommandEvent & WXUNUSED(event))
+{
+       wxMessageDialog dlg(this,
+               wxT("* Walk & Fly modes:\n")
+               wxT("\tH move: H pan - V move: Z-translate - V move+CTRL or Wheel: V pan - Right Click (Walk only): Jump\n")
+               wxT("\tleft/right: H pan - left/right+CTRL: H translate - up/down: Z-translate - up/down+CTRL: V pan\n")
+               wxT("* Pan mode:\n")
+               wxT("\tH move: H pan - V move: V pan - V move+CTRL or Wheel: Z-translate\n")
+               wxT("\tleft/right: H pan - left/right+CTRL: H translate - up/down: V pan - up/down+CTRL: Z-translate\n")
+               wxT("* Slide mode:\n")
+               wxT("\tH move: H translate - V move: V translate - V move+CTRL or Wheel: Z-translate\n")
+               wxT("\tleft/right: H translate - left/right+CTRL: H pan - up/down: V translate - up/down+CTRL: Z-translate\n")
+               wxT("* Examine & Orbit mode:\n")
+               wxT("\tH move: Y-Axis rotate - H move+CTRL: No move - V move: X-Axis rotate - V move+CTRL or Wheel: Z-translate\n")
+               wxT("\tleft/right: Y-Axis rotate - left/right+CTRL: H translate - up/down: X-Axis rotate - up/down+CTRL: Y-translate\n")
+               wxT("* VR mode:\n")
+               wxT("\tH move: H pan - V move: V pan - V move+CTRL or Wheel: Camera Zoom\n")
+               wxT("\tleft/right: H pan - up/down: V pan - up/down+CTRL: Camera Zoom\n")
+               wxT("* Game mode (press END to escape):\n")
+               wxT("\tH move: H pan - V move: V pan\n")
+               wxT("\tleft/right: H translate - up/down: Z-translate\n")
+               wxT("\n")
+               wxT("* All 3D modes: CTRL+PGUP/PGDOWN will zoom in/out camera (field of view) \n")
+               wxT("\n")
+               wxT("*Slide Mode in 2D:\n")
+               wxT("\tH move: H translate - V move: V translate - V move+CTRL: zoom\n")
+               wxT("\tleft/right: H translate - up/down: V translate - up/down+CTRL: zoom\n")
+               wxT("*Examine Mode in 2D (3D renderer only):\n")
+               wxT("\tH move: Y-Axis rotate - V move: X-Axis rotate\n")
+               wxT("\tleft/right: Y-Axis rotate - up/down: X-Axis rotate\n")
+               wxT("\n")
+               wxT("HOME: reset navigation to last viewpoint (2D or 3D navigation)\n")
+               wxT("SHIFT key in all modes: fast movement\n")
+
+               , wxT("3D navigation keys (\'H\'orizontal and \'V\'ertical) used in GPAC")
+               , wxOK );
+       dlg.ShowModal();
+}
+
+
+/*open file dlg*/
+class AboutDlg : public wxDialog {
+public:
+    AboutDlg(wxWindow *parent);
+
+private:
+    wxStaticText *m_info;
+    wxButton *m_close;
+       void OnClose(wxCommandEvent& event);
+    DECLARE_EVENT_TABLE()
+};
+
+BEGIN_EVENT_TABLE(AboutDlg, wxDialog)
+    EVT_BUTTON(ID_ABOUT_CLOSE, AboutDlg::OnClose)
+END_EVENT_TABLE()
+
+AboutDlg::AboutDlg(wxWindow *parent)
+             : wxDialog(parent, -1, wxString(wxT("GPAC/Osmo4 V ")wxT(GPAC_FULL_VERSION)))
+{
+       SetSize(220, 320);
+       Centre();
+       wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
+
+       m_info = new wxStaticText(this, -1, wxT("http://gpac.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
+       sizer->Add(m_info, 1, wxEXPAND|wxADJUST_MINSIZE, 0);
+    m_close = new wxButton(this, ID_ABOUT_CLOSE, wxT("Close"), wxDefaultPosition, wxSize(120, 20));
+       sizer->Add(m_close, 0, wxEXPAND, 0);
+
+       SetIcon(wxIcon(osmo4));
+       m_info->SetLabel(
+               wxT("Osmo4 Player\n")
+               wxT("GPAC Multimedia Framework\n")
+               wxT("\n")
+               wxT("This program is gf_free software and may\n")
+               wxT("be distributed according to the terms\n")
+               wxT("of the GNU Lesser General Public License\n")
+               wxT("\n")
+               wxT("Copyright (c) Jean Le Feuvre 2000-2005\n")
+               wxT("(c) ENST 2005-200X\n")
+               wxT("All Rights Reserved\n")
+               wxT("http://gpac.sourceforge.net\n")
+               wxT("\n")
+               wxT(" ** With Many Thanks To ** \n\n")
+               wxT("Mozilla SpiderMonkey (JavaScript)\n")
+               wxT("The FreeType Project\n")
+               wxT("The PNG Group, The I.J.G.\n")
+               wxT("FFMPEG, FAAD, XVID, MAD\n")
+               );
+
+       SetSizer(sizer);
+       sizer->Fit(this);
+}
+void AboutDlg::OnClose(wxCommandEvent& WXUNUSED(event))
+{
+       Close(FALSE);
+}
+
+void wxOsmo4Frame::OnAbout(wxCommandEvent & WXUNUSED(event))
+{
+       AboutDlg dlg(this);
+       dlg.ShowModal();
+}
+
+
+void wxOsmo4Frame::OnGPACEvent(wxGPACEvent &event)
+{
+       wxString cmd;
+       wxCommandEvent evt;
+       if (!m_term) return;
+
+       switch (event.gpac_evt.type) {
+       case GF_EVENT_NAVIGATE:
+               if (gf_term_is_supported_url(m_term, event.to_url.mb_str(wxConvUTF8), 1, 0)) {
+                       char *str = gf_url_concatenate(m_pPlayList->GetURL().mb_str(wxConvUTF8), event.to_url.mb_str(wxConvUTF8));
+                       if (str) {
+                               m_pPlayList->Truncate();
+                               m_pPlayList->QueueURL(wxString(str, wxConvUTF8));
+                               m_pPlayList->RefreshList();
+                               gf_free(str);
+                               m_pPlayList->PlayNext();
+                       }
+                       return;
+               }
+               cmd = get_pref_browser(m_user.config);
+               if (cmd.IsEmpty()){
+                 cmd += wxT(" ");
+                 cmd += event.to_url;
+                 wxExecute(cmd);
+               } else {
+#ifdef wxLaunchDefaultBrowser
+                       wxLaunchDefaultBrowser(event.to_url);
+#endif
+               }
+               break;
+       case GF_EVENT_QUIT:
+               Close(TRUE);
+               break;
+       case GF_EVENT_SET_CAPTION:
+               SetTitle(event.to_url);
+               break;
+       case GF_EVENT_CONNECT:
+               BuildStreamList(0);
+               ConnectAcknowledged(event.gpac_evt.connect.is_connected);
+               break;
+       case GF_EVENT_KEYDOWN:
+               if (!(event.gpac_evt.key.flags & GF_KEY_MOD_CTRL)) return;
+               switch (event.gpac_evt.key.key_code) {
+               case GF_KEY_R:
+                       gf_term_set_option(m_term, GF_OPT_REFRESH, 1);
+                       break;
+               case GF_KEY_P:
+                       OnFilePlay(evt);
+                       break;
+               case GF_KEY_S:
+                       OnFileStep(evt);
+                       break;
+               }
+               break;
+       case GF_EVENT_SCENE_SIZE:
+               m_orig_width = event.gpac_evt.size.width;
+               m_orig_height = event.gpac_evt.size.height;
+       case GF_EVENT_SIZE:
+               if (! gf_term_get_option(m_term, GF_OPT_FULLSCREEN)) {
+                       DoLayout(event.gpac_evt.size.width, event.gpac_evt.size.height);
+               }
+               break;
+       case GF_EVENT_VIEWPOINTS:
+               BuildViewList();
+               break;
+       case GF_EVENT_STREAMLIST:
+               BuildStreamList(0);
+               break;
+       }
+}
+
+
+static wxString format_time(u32 duration, u32 timescale)
+{
+       u32 h, m, s;
+       Float time = duration;
+       time /= timescale;
+       time *= 1000;
+       h = (u32) (time / 1000 / 3600);
+       m = (u32) (time / 1000 / 60 - h*60);
+       s = (u32) (time / 1000 - h*3600 - m*60);
+       return wxString::Format(wxT("%02d:%02d:%02d"), h, m, s);
+}
+
+void wxOsmo4Frame::SetStatus(wxString str)
+{
+       //m_pStatusbar->SetStatusText(str, 2);
+       m_LastStatusTime = gf_sys_clock();
+}
+
+#define RTI_REFRESH_MS         500
+void wxOsmo4Frame::OnRTI(wxCommandEvent & event)
+{
+       m_bViewRTI = event.IsChecked();
+       if (m_bViewRTI) {
+               if (!m_pTimer->IsRunning()) m_pTimer->Start(RTI_REFRESH_MS, 0);
+       } else if (!m_connected && m_pTimer->IsRunning()) {
+               m_LastStatusTime = 0;
+               m_pStatusbar->SetStatusText(wxT("Ready"), 2);
+               m_pTimer->Stop();
+       }
+}
+
+void wxOsmo4Frame::OnTimer(wxTimerEvent& WXUNUSED(event))
+{
+       wxString str;
+       u32 now;
+       if (m_LastStatusTime) {
+               now = gf_sys_clock();
+               if (now > 1000+m_LastStatusTime) {
+                       m_LastStatusTime = 0;
+                       m_pStatusbar->SetStatusText(wxT("Ready"), 2);
+               }
+       }
+
+       if (m_bViewRTI) {
+               GF_SystemRTInfo rti;
+               if (!gf_sys_get_rti(RTI_REFRESH_MS, &rti, 0)) return;
+               if (rti.gpac_memory) rti.process_memory = rti.gpac_memory;
+
+               str = wxString::Format(wxT("CPU %02d (%02d) - Mem %d kB" ),
+                                               rti.total_cpu_usage, rti.process_cpu_usage, rti.gpac_memory/1024);
+
+               m_pStatusbar->SetStatusText(str, 2);
+       }
+       if (!m_connected) return;
+
+       now = gf_term_get_time_in_ms(m_term);
+       if (!now) return;
+
+       if (!m_duration) {
+               str = format_time(now, 1000);
+               m_pStatusbar->SetStatusText(str);
+               str = wxString::Format(wxT("FPS %.2f"), gf_term_get_framerate(m_term, 0));
+               m_pStatusbar->SetStatusText(str, 1);
+               return;
+       }
+#ifdef __WXGTK__
+       if (m_bGrabbed) {
+         u32 now = gf_sys_clock() - m_last_grab_time;
+         if (now>200) {
+           m_bGrabbed = 0;
+           Double res = (Double) m_last_grab_pos;
+           res /= 1000;
+           res *= m_duration;
+           if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED) {
+                       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
+                       m_bToReset = 0;
+           }
+           gf_term_play_from_time(m_term, (u32) res, 0);
+           return;
+         }
+       }
+#endif
+
+       if (!m_bGrabbed) {
+               if ((now >= m_duration + 500) && gf_term_get_option(m_term, GF_OPT_IS_FINISHED)) {
+                       m_pPlayList->PlayNext();
+               } else {
+                       Double val = now * 1000;
+                       val /= m_duration;
+                       m_pProg->SetValue((val<=1000) ? (u32) val : 1000);
+
+                       if (0) {
+                               str = format_time(m_duration-now, 1000);
+                       } else {
+                               str = format_time(now, 1000);
+                       }
+                       m_pStatusbar->SetStatusText(str);
+                       str = wxString::Format(wxT("FPS %.2f"), gf_term_get_framerate(m_term, 0));
+                       m_pStatusbar->SetStatusText(str, 1);
+               }
+       }
+}
+
+void wxOsmo4Frame::ConnectAcknowledged(Bool bOk)
+{
+       if (bOk) {
+               m_pTimer->Start(RTI_REFRESH_MS, 0);
+               m_connected = 1;
+               m_bToReset = 0;
+               UpdatePlay();
+               BuildChapterList(0);
+       } else {
+               BuildChapterList(1);
+               if (!m_connected) {
+                       UpdatePlay();
+                       m_pTimer->Stop();
+                       //m_pProg->Enable(0);
+               }
+       }
+}
+
+void wxOsmo4Frame::OnFilePlay(wxCommandEvent & WXUNUSED(event))
+{
+       wxCommandEvent evt;
+       if (m_connected) {
+               if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED) {
+                       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
+                       if (m_bToReset) {
+                               m_pTimer->Start(100, 0);
+                               gf_term_play_from_time(m_term, 0, 0);
+                       }
+                       m_bToReset = 0;
+                       UpdatePlay();
+               } else {
+                       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);
+                       UpdatePlay();
+               }
+       } else {
+               m_pPlayList->Play();
+       }
+}
+
+void wxOsmo4Frame::OnFileStep(wxCommandEvent & WXUNUSED(event))
+{
+       wxCommandEvent evt;
+       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE);
+       UpdatePlay();
+}
+
+void wxOsmo4Frame::OnFileStop(wxCommandEvent &WXUNUSED(event))
+{
+       Stop();
+}
+
+void wxOsmo4Frame::Stop()
+{
+       if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PLAYING) {
+               gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);
+       }
+       m_bToReset = 1;
+       m_pTimer->Stop();
+       m_pProg->SetValue(0);
+       UpdatePlay();
+}
+
+void wxOsmo4Frame::OnSlide(wxScrollEvent &event)
+{
+       if (!m_duration) return;
+
+       /*wxSlider on GTK is buggy, so track a release timeout*/
+#ifdef __WXGTK__
+       m_last_grab_time = gf_sys_clock();
+       m_bGrabbed = 1;
+       m_last_grab_pos = event.GetPosition();
+       Double now = (Double) m_last_grab_pos;
+       now /= 1000;
+       now *= m_duration;
+       wxString str = format_time((u32) (now), 1000);
+       m_pStatusbar->SetStatusText(str);
+       if (!m_pTimer->IsRunning()) m_pTimer->Start(100, 0);
+#else
+       s32 type = event.GetEventType();
+       if (type == wxEVT_SCROLL_THUMBTRACK) {
+         m_bGrabbed = 1;
+         Double now = (Double) event.GetPosition();
+         now /= 1000;
+         now *= m_duration;
+         wxString str = format_time((u32) (now), 1000);
+         m_pStatusbar->SetStatusText(str);
+       }
+       else if (m_bGrabbed){
+           m_bGrabbed = 0;
+           Double res = (Double) m_pProg->GetValue();
+           res /= 1000;
+           res *= m_duration;
+           if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED) {
+                       gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
+                       m_bToReset = 0;
+                       if (!m_pTimer->IsRunning()) m_pTimer->Start(100, 0);
+           }
+           gf_term_play_from_time(m_term, (u32) res, 0);
+       }
+#endif
+}
+
+
+void wxOsmo4Frame::BuildViewList()
+{
+       if (!vp_list || !m_connected) return;
+
+       while (vp_list->GetMenuItemCount()) {
+               wxMenuItem* it = vp_list->FindItemByPosition(0);
+               vp_list->Delete(it);
+       }
+
+       s32 id = ID_VIEWPOINT_FIRST;
+       nb_viewpoints = 0;
+       while (1) {
+               const char *szName;
+               Bool bound;
+               GF_Err e = gf_term_get_viewpoint(m_term, nb_viewpoints+1, &szName, &bound);
+               if (e) break;
+               if (szName) {
+                       vp_list->AppendCheckItem(id+nb_viewpoints, wxString(szName, wxConvUTF8) );
+               } else {
+                       vp_list->AppendCheckItem(id+nb_viewpoints, wxString::Format(wxT("Viewpoint #%d"), nb_viewpoints+1) );
+               }
+               nb_viewpoints++;
+       }
+}
+
+void wxOsmo4Frame::OnViewport(wxCommandEvent & event)
+{
+       u32 ID = event.GetId() - ID_VIEWPOINT_FIRST;
+       gf_term_set_viewpoint(m_term, ID+1, NULL);
+}
+
+void wxOsmo4Frame::OnUpdateViewport(wxUpdateUIEvent & event)
+{
+       u32 ID = event.GetId() - ID_VIEWPOINT_FIRST;
+       const char *szName;
+       Bool bound;
+       gf_term_get_viewpoint(m_term, ID+1, &szName, &bound);
+       event.Enable(1);
+       if (bound) event.Check(1);
+}
+
+void wxOsmo4Frame::OnNavigate(wxCommandEvent & event)
+{
+       switch (event.GetId()) {
+       case ID_NAVIGATE_NONE: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_NONE); break;
+       case ID_NAVIGATE_WALK: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_WALK); break;
+       case ID_NAVIGATE_FLY: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_FLY); break;
+       case ID_NAVIGATE_EXAMINE: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_EXAMINE); break;
+       case ID_NAVIGATE_PAN: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_PAN); break;
+       case ID_NAVIGATE_SLIDE: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_SLIDE); break;
+       case ID_NAVIGATE_ORBIT: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_ORBIT); break;
+       case ID_NAVIGATE_GAME: gf_term_set_option(m_term, GF_OPT_NAVIGATION, GF_NAVIGATE_GAME); break;
+       }
+}
+void wxOsmo4Frame::OnNavigateReset(wxCommandEvent & WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_NAVIGATION_TYPE, 0);
+}
+void wxOsmo4Frame::OnUpdateNavigation(wxUpdateUIEvent & event)
+{
+       u32 ID = event.GetId();
+       event.Enable(0);
+       if (!m_connected) return;
+       u32 type = gf_term_get_option(m_term, GF_OPT_NAVIGATION_TYPE);
+       bool enable = type ? 1 : 0;
+
+       u32 mode = gf_term_get_option(m_term, GF_OPT_NAVIGATION);
+       /*common 2D/3D modes*/
+       if (ID==ID_NAVIGATE_NONE) { event.Enable(enable); event.Check(mode ? 0 : 1); }
+       else if (ID==ID_NAVIGATE_EXAMINE) { event.Enable(enable); event.Check((mode==GF_NAVIGATE_EXAMINE) ? 1 : 0); }
+       else if (ID==ID_NAVIGATE_SLIDE) { event.Enable(enable); event.Check((mode==GF_NAVIGATE_SLIDE) ? 1 : 0); }
+
+       if (type==GF_NAVIGATE_TYPE_2D) return;
+       event.Enable(enable);
+       if (ID==ID_NAVIGATE_WALK) event.Check((mode==GF_NAVIGATE_WALK) ? 1 : 0);
+       else if (ID==ID_NAVIGATE_FLY) event.Check((mode==GF_NAVIGATE_FLY) ? 1 : 0);
+       else if (ID==ID_NAVIGATE_PAN) event.Check((mode==GF_NAVIGATE_PAN) ? 1 : 0);
+       else if (ID==ID_NAVIGATE_ORBIT) event.Check((mode==GF_NAVIGATE_ORBIT) ? 1 : 0);
+       else if (ID==ID_NAVIGATE_GAME) event.Check((mode==GF_NAVIGATE_GAME) ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnRenderSwitch(wxCommandEvent &WXUNUSED(event))
+{
+       const char *opt = gf_cfg_get_key(m_user.config, "Compositor", "ForceOpenGL");
+       Bool use_gl = (opt && !stricmp(opt, "yes")) ? 1 : 0;
+       gf_cfg_set_key(m_user.config, "Compositor", "ForceOpenGL", use_gl ? "no" : "yes");
+
+       gf_term_set_option(m_term, GF_OPT_USE_OPENGL, !use_gl);
+
+       UpdateRenderSwitch();
+}
+
+void wxOsmo4Frame::UpdateRenderSwitch()
+{
+       const char *opt = gf_cfg_get_key(m_user.config, "Compositor", "ForceOpenGL");
+       m_pToolBar->RemoveTool(SWITCH_RENDER);
+       if (opt && !stricmp(opt, "yes"))
+               m_pToolBar->InsertTool(12, SWITCH_RENDER, *m_pSW2D, wxNullBitmap, FALSE, NULL, wxT("2D Rasterizer"));
+       else
+               m_pToolBar->InsertTool(12, SWITCH_RENDER, *m_pSW3D, wxNullBitmap, FALSE, NULL, wxT("OpenGL Rendering"));
+
+#ifdef WIN32
+       /*there's a display bug with the menubtn, remove and reinsert*/
+       m_pToolBar->RemoveTool(FILE_PREV);
+       m_pToolBar->RemoveTool(FILE_NEXT);
+       m_pToolBar->InsertControl(2, m_pPrevBut);
+       m_pToolBar->InsertControl(3, m_pNextBut);
+#endif
+       m_pToolBar->Realize();
+}
+
+void wxOsmo4Frame::UpdatePlay()
+{
+       m_pToolBar->RemoveTool(FILE_PLAY);
+       if (m_connected) {
+               if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED)
+                       m_pToolBar->InsertTool(5, FILE_PLAY, *m_pPlay, wxNullBitmap, FALSE, NULL, wxT("Pause File"));
+               else
+                       m_pToolBar->InsertTool(5, FILE_PLAY, *m_pPause, wxNullBitmap, FALSE, NULL, wxT("Play File"));
+       } else {
+               m_pToolBar->InsertTool(5, FILE_PLAY, *m_pPlay, wxNullBitmap, FALSE, NULL, wxT("Pause File"));
+       }
+
+#ifdef WIN32
+       /*there's a display bug with the menubtn, remove and reinsert*/
+       m_pToolBar->RemoveTool(FILE_PREV);
+       m_pToolBar->RemoveTool(FILE_NEXT);
+       m_pToolBar->InsertControl(2, m_pPrevBut);
+       m_pToolBar->InsertControl(3, m_pNextBut);
+#endif
+       m_pToolBar->Realize();
+}
+
+void wxOsmo4Frame::OnCollide(wxCommandEvent & event)
+{
+       u32 ID = event.GetId();
+       if (ID==ID_COLLIDE_NONE) gf_term_set_option(m_term, GF_OPT_COLLISION, GF_COLLISION_NONE);
+       else if (ID==ID_COLLIDE_REG) gf_term_set_option(m_term, GF_OPT_COLLISION, GF_COLLISION_NORMAL);
+       else if (ID==ID_COLLIDE_DISP) gf_term_set_option(m_term, GF_OPT_COLLISION, GF_COLLISION_DISPLACEMENT);
+}
+void wxOsmo4Frame::OnUpdateCollide(wxUpdateUIEvent & event)
+{
+       u32 ID = event.GetId();
+       event.Enable(0);
+       if (!m_connected) return;
+       event.Enable(1);
+       u32 mode = gf_term_get_option(m_term, GF_OPT_COLLISION);
+       if (ID==ID_COLLIDE_NONE) { event.Check((mode==GF_COLLISION_NONE) ? 1 : 0); }
+       else if (ID==ID_COLLIDE_REG) { event.Check((mode==GF_COLLISION_NORMAL) ? 1 : 0); }
+       else if (ID==ID_COLLIDE_DISP) { event.Check((mode==GF_COLLISION_DISPLACEMENT) ? 1 : 0); }
+}
+
+void wxOsmo4Frame::OnHeadlight(wxCommandEvent &WXUNUSED(event))
+{
+       Bool val = !gf_term_get_option(m_term, GF_OPT_HEADLIGHT);
+       gf_term_set_option(m_term, GF_OPT_HEADLIGHT, val);
+}
+void wxOsmo4Frame::OnUpdateHeadlight(wxUpdateUIEvent & event)
+{
+       event.Enable(0);
+       if (!m_connected) return;
+       u32 type = gf_term_get_option(m_term, GF_OPT_NAVIGATION_TYPE);
+       if (type!=GF_NAVIGATE_TYPE_3D) return;
+
+       event.Enable(1);
+       event.Check(gf_term_get_option(m_term, GF_OPT_HEADLIGHT) ? 1 : 0);
+}
+void wxOsmo4Frame::OnGravity(wxCommandEvent & WXUNUSED(event))
+{
+       Bool val = gf_term_get_option(m_term, GF_OPT_GRAVITY) ? 0 : 1;
+       gf_term_set_option(m_term, GF_OPT_GRAVITY, val);
+}
+void wxOsmo4Frame::OnUpdateGravity(wxUpdateUIEvent & event)
+{
+       event.Enable(0);
+       if (!m_connected) return;
+       u32 type = gf_term_get_option(m_term, GF_OPT_NAVIGATION_TYPE);
+       if (type!=GF_NAVIGATE_TYPE_3D) return;
+       type = gf_term_get_option(m_term, GF_OPT_NAVIGATION);
+       if (type != GF_NAVIGATE_WALK) return;
+       event.Enable(1);
+       event.Check(gf_term_get_option(m_term, GF_OPT_GRAVITY) ? 1 : 0);
+}
+
+
+BEGIN_EVENT_TABLE(wxMyComboBox, wxComboBox)
+       EVT_KEY_UP(wxMyComboBox::OnKeyUp)
+END_EVENT_TABLE()
+
+void wxMyComboBox::OnKeyUp(wxKeyEvent &event)
+{
+       if (event.GetKeyCode()==WXK_RETURN) {
+               event.Skip();
+               wxCommandEvent evt;
+               evt.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED);
+               evt.SetEventObject(this);
+               evt.SetId(GetId());
+               GetParent()->AddPendingEvent(evt);
+       }
+}
+
+
+void wxOsmo4Frame::ReloadURLs()
+{
+       const char *sOpt;
+       u32 i=0;
+
+       m_Address->Clear();
+       while (1) {
+               sOpt = gf_cfg_get_key_name(m_user.config, "RecentFiles", i);
+               if (!sOpt) break;
+               m_Address->Append(wxString(sOpt, wxConvUTF8) );
+               i++;
+       }
+}
+
+void wxOsmo4Frame::SelectionReady()
+{
+       wxString urlVal = m_Address->GetValue();
+       if (urlVal.Find(wxT("://"))>0) {
+               UpdateLastFiles(m_user.config, urlVal.mb_str(wxConvUTF8));
+               ReloadURLs();
+       }
+       m_pPlayList->Truncate();
+       m_pPlayList->QueueURL(urlVal);
+       m_pPlayList->RefreshList();
+       m_pPlayList->PlayNext();
+}
+
+void wxOsmo4Frame::OnURLSelect(wxCommandEvent &WXUNUSED(event))
+{
+       SelectionReady();
+}
+
+void wxOsmo4Frame::OnPlaylist(wxCommandEvent &WXUNUSED(event))
+{
+       assert(m_pPlayList);
+       m_pPlayList->Show(m_pPlayList->IsShown() ? 0 : 1);
+}
+
+void wxOsmo4Frame::OnUpdatePlayList(wxUpdateUIEvent & event)
+{
+       event.Enable(1);
+       event.Check(m_pPlayList->IsShown() ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnFilePrevOpen(wxNotifyEvent & event)
+{
+       u32 count = gf_list_count(m_pPlayList->m_entries);
+       u32 start = m_pPlayList->m_cur_entry - 1;
+       wxMenu *popup = new wxMenu();
+
+       for (u32 i=0; i<10; i++) {
+               if (i > start) break;
+               if (start - i >= count) break;
+               PLEntry *ple = (PLEntry *) gf_list_get(m_pPlayList->m_entries, start - i);
+               popup->Append(ID_NAV_PREV_0 + i, wxString(ple->m_disp_name, wxConvUTF8) );
+       }
+       m_pPrevBut->AssignMenu(popup);
+}
+
+void wxOsmo4Frame::OnFileNextOpen(wxNotifyEvent & event)
+{
+       u32 count = gf_list_count(m_pPlayList->m_entries);
+       wxMenu *popup = new wxMenu();
+       u32 start = m_pPlayList->m_cur_entry + 1;
+       for (u32 i=0; i<10; i++) {
+               if (start + i >= count) break;
+               PLEntry *ple = (PLEntry *) gf_list_get(m_pPlayList->m_entries, start + i);
+               popup->Append(ID_NAV_NEXT_0 + i, wxString(ple->m_disp_name, wxConvUTF8) );
+       }
+       m_pNextBut->AssignMenu(popup);
+}
+
+void wxOsmo4Frame::OnNavPrev(wxCommandEvent &WXUNUSED(event))
+{
+       if (m_pPlayList->m_cur_entry<=0) return;
+       m_pPlayList->PlayPrev();
+}
+void wxOsmo4Frame::OnUpdateNavPrev(wxUpdateUIEvent & event)
+{
+       if (m_pPlayList->m_cur_entry<=0) event.Enable(0);
+       else event.Enable(TRUE);
+}
+void wxOsmo4Frame::OnNavPrevMenu(wxCommandEvent &event)
+{
+       u32 ID = event.GetId() - ID_NAV_PREV_0;
+       s32 prev = m_pPlayList->m_cur_entry - ID;
+       if (prev>=0) {
+               m_pPlayList->m_cur_entry = prev;
+               m_pPlayList->PlayPrev();
+       }
+}
+void wxOsmo4Frame::OnNavNext(wxCommandEvent &WXUNUSED(event))
+{
+       /*don't play if last could trigger playlist loop*/
+       if ((m_pPlayList->m_cur_entry<0) || (gf_list_count(m_pPlayList->m_entries) == 1 + (u32) m_pPlayList->m_cur_entry)) return;
+       m_pPlayList->PlayNext();
+}
+void wxOsmo4Frame::OnUpdateNavNext(wxUpdateUIEvent & event)
+{
+       if (m_pPlayList->m_cur_entry<0) event.Enable(0);
+       else if ((u32) m_pPlayList->m_cur_entry + 1 == gf_list_count(m_pPlayList->m_entries) ) event.Enable(0);
+       else event.Enable(1);
+}
+
+void wxOsmo4Frame::OnNavNextMenu(wxCommandEvent &event)
+{
+       u32 ID = event.GetId() - ID_NAV_NEXT_0;
+       s32 next = m_pPlayList->m_cur_entry + ID;
+       if (next < (s32) gf_list_count(m_pPlayList->m_entries) ) {
+               m_pPlayList->m_cur_entry = next;
+               m_pPlayList->PlayNext();
+       }
+}
+
+void wxOsmo4Frame::OnClearNav(wxCommandEvent &WXUNUSED(event))
+{
+       m_pPlayList->ClearButPlaying();
+}
+
+
+void wxOsmo4Frame::BuildStreamList(Bool reset_only)
+{
+       u32 nb_subs;
+       wxMenu *pMenu;
+
+       pMenu = sel_menu->FindItemByPosition(0)->GetSubMenu();
+       while (pMenu->GetMenuItemCount()) {
+               wxMenuItem* it = pMenu->FindItemByPosition(0);
+               pMenu->Delete(it);
+       }
+       pMenu = sel_menu->FindItemByPosition(1)->GetSubMenu();
+       while (pMenu->GetMenuItemCount()) {
+               wxMenuItem* it = pMenu->FindItemByPosition(0);
+               pMenu->Delete(it);
+       }
+       pMenu = sel_menu->FindItemByPosition(2)->GetSubMenu();
+       while (pMenu->GetMenuItemCount()) {
+               wxMenuItem* it = pMenu->FindItemByPosition(0);
+               pMenu->Delete(it);
+       }
+
+       if (reset_only) {
+               m_bFirstStreamListBuild = 1;
+               return;
+       }
+
+       if (!gf_term_get_option(m_term, GF_OPT_CAN_SELECT_STREAMS)) return;
+
+       nb_subs = 0;
+       GF_ObjectManager *root_od = gf_term_get_root_object(m_term);
+       if (!root_od) return;
+       u32 count = gf_term_get_object_count(m_term, root_od);
+
+       for (u32 i=0; i<count; i++) {
+               char szLabel[1024];
+               GF_MediaInfo info;
+               GF_ObjectManager *odm = gf_term_get_object(m_term, root_od, i);
+               if (!odm) return;
+
+               if (gf_term_get_object_info(m_term, odm, &info) != GF_OK) break;
+
+               if (info.owns_service) {
+                       char *szName = (char *) strrchr(info.service_url, '\\');
+                       if (!szName) szName = (char *) strrchr(info.service_url, '/');
+                       if (!szName) szName = (char *) info.service_url;
+                       else szName += 1;
+                       strcpy(szLabel, szName);
+                       szName = strrchr(szLabel, '.');
+                       if (szName) szName[0] = '\0';
+               }
+               switch (info.od_type) {
+               case GF_STREAM_AUDIO:
+                       pMenu = sel_menu->FindItemByPosition(0)->GetSubMenu();
+                       if (!info.owns_service) sprintf(szLabel, "Audio #"LLU, (u64)pMenu->GetMenuItemCount() + 1);
+                       pMenu->AppendCheckItem(ID_SELSTREAM_0 +i, wxString(szLabel, wxConvUTF8));
+                       break;
+               case GF_STREAM_VISUAL:
+                       pMenu = sel_menu->FindItemByPosition(1)->GetSubMenu();
+                       if (!info.owns_service) sprintf(szLabel, "Video #"LLU, (u64)pMenu->GetMenuItemCount() + 1);
+                       pMenu->AppendCheckItem(ID_SELSTREAM_0 +i, wxString(szLabel, wxConvUTF8));
+                       break;
+               case GF_STREAM_TEXT:
+                       nb_subs ++;
+                       pMenu = sel_menu->FindItemByPosition(2)->GetSubMenu();
+                       if (!info.owns_service) sprintf(szLabel, "Subtitle #"LLU, (u64)pMenu->GetMenuItemCount() + 1);
+                       pMenu->AppendCheckItem(ID_SELSTREAM_0 +i, wxString(szLabel, wxConvUTF8));
+                       break;
+               }
+       }
+       if (m_bFirstStreamListBuild) {
+               m_bFirstStreamListBuild = 0;
+               if (!nb_subs && m_lookforsubs) LookForSubtitles();
+       }
+}
+
+void wxOsmo4Frame::OnStreamSel(wxCommandEvent & event)
+{
+       GF_ObjectManager *root_od = gf_term_get_root_object(m_term);
+       if (!root_od) return;
+       u32 ID = event.GetId() - ID_SELSTREAM_0;
+       GF_ObjectManager *odm = gf_term_get_object(m_term, root_od, ID);
+       gf_term_select_object(m_term, odm);
+}
+
+void wxOsmo4Frame::OnUpdateStreamSel(wxUpdateUIEvent & event)
+{
+       GF_ObjectManager *root_od = gf_term_get_root_object(m_term);
+       if (!root_od) return;
+       u32 ID = event.GetId() - ID_SELSTREAM_0;
+
+       GF_ObjectManager *odm = gf_term_get_object(m_term, root_od, ID);
+       if (!odm) return;
+
+       GF_MediaInfo info;
+       gf_term_get_object_info(m_term, odm, &info);
+       event.Enable(1);
+       event.Check(info.status ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnUpdateStreamMenu(wxUpdateUIEvent & event)
+{
+       if (!m_connected || !gf_term_get_option(m_term, GF_OPT_CAN_SELECT_STREAMS)) {
+               event.Enable(0);
+       } else {
+               event.Enable(1);
+       }
+}
+
+void wxOsmo4Frame::OnAddSub(wxCommandEvent &WXUNUSED(event))
+{
+       wxFileDialog dlg(this, wxT("Add Subtitle"), wxT(""), wxT(""), wxT("All Subtitles|*.srt;*.ttxt|SRT Subtitles|*.srt|3GPP TimedText|*.ttxt|"), wxOPEN | wxCHANGE_DIR /* | wxHIDE_READONLY*/);
+
+       if (dlg.ShowModal() == wxID_OK) {
+               AddSubtitle(dlg.GetPath().mb_str(wxConvUTF8), 1);
+       }
+
+}
+
+void wxOsmo4Frame::AddSubtitle(const char *fileName, Bool auto_play)
+{
+       gf_term_add_object(m_term, fileName, auto_play);
+}
+
+static Bool subs_enum_dir_item(void *cbck, char *item_name, char *item_path)
+{
+       wxOsmo4Frame *_this = (wxOsmo4Frame*)cbck;
+       _this->AddSubtitle(item_path, 0);
+       return 0;
+}
+
+void wxOsmo4Frame::LookForSubtitles()
+{
+       char dir[GF_MAX_PATH];
+       const char *url = m_pPlayList->GetURL().mb_str(wxConvUTF8);
+       strcpy(dir, url);
+       char *sep = strrchr(dir, '\\');
+       if (!sep) strcpy(dir, ::wxGetCwd().mb_str(wxConvUTF8));
+       else sep[0] = 0;
+
+       gf_enum_directory(dir, 0, subs_enum_dir_item, this, "ttxt;srt");
+}
+
+void wxOsmo4Frame::OnCacheEnable(wxCommandEvent &WXUNUSED(event))
+{
+       u32 state = gf_term_get_option(m_term, GF_OPT_MEDIA_CACHE);
+       if (state==GF_MEDIA_CACHE_DISABLED) {
+               gf_term_set_option(m_term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_ENABLED);
+       } else if (state==GF_MEDIA_CACHE_DISABLED) {
+               gf_term_set_option(m_term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_DISABLED);
+       }
+}
+
+void wxOsmo4Frame::OnCacheStop(wxCommandEvent &WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_DISABLED);
+}
+
+void wxOsmo4Frame::OnCacheAbort(wxCommandEvent &WXUNUSED(event))
+{
+       gf_term_set_option(m_term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_DISCARD);
+}
+
+void wxOsmo4Frame::OnUpdateCacheEnable(wxUpdateUIEvent & event)
+{
+       u32 state = gf_term_get_option(m_term, GF_OPT_MEDIA_CACHE);
+       switch (state) {
+       case GF_MEDIA_CACHE_ENABLED:
+               event.Enable(1);
+               event.SetText(wxT("Enabled"));
+               break;
+       case GF_MEDIA_CACHE_RUNNING:
+               event.SetText(wxT("Running"));
+               event.Enable(0);
+               break;
+       case GF_MEDIA_CACHE_DISABLED:
+               event.SetText(wxT("Disabled"));
+               break;
+       }
+}
+
+void wxOsmo4Frame::OnUpdateCacheAbort(wxUpdateUIEvent & event)
+{
+       u32 state = gf_term_get_option(m_term, GF_OPT_MEDIA_CACHE);
+       event.Enable( (state==GF_MEDIA_CACHE_RUNNING) ? 1 : 0);
+}
+
+
+
+void wxOsmo4Frame::BuildChapterList(Bool reset_only)
+{
+       GF_MediaInfo odi;
+
+       while (chap_menu->GetMenuItemCount()) {
+               wxMenuItem* it = chap_menu->FindItemByPosition(0);
+               chap_menu->Delete(it);
+       }
+       if (m_chapters_start) gf_free(m_chapters_start);
+       m_chapters_start = NULL;
+       m_num_chapters = 0;
+       if (reset_only) return;
+
+       GF_ObjectManager *root_od = gf_term_get_root_object(m_term);
+       if (!root_od) return;
+       if (gf_term_get_object_info(m_term, root_od, &odi) != GF_OK) return;
+
+       u32 count = gf_list_count(odi.od->OCIDescriptors);
+       m_num_chapters = 0;
+       for (u32 i=0; i<count; i++) {
+               char szLabel[1024];
+               GF_Segment *seg = (GF_Segment *) gf_list_get(odi.od->OCIDescriptors, i);
+               if (seg->tag != GF_ODF_SEGMENT_TAG) continue;
+
+               if (seg->SegmentName && strlen((const char *)seg->SegmentName)) {
+                       strcpy(szLabel, (const char *) seg->SegmentName);
+               } else {
+                       sprintf(szLabel, "Chapter %02d", m_num_chapters+1);
+               }
+               chap_menu->AppendCheckItem(ID_SETCHAP_FIRST + m_num_chapters, wxString(szLabel, wxConvUTF8));
+
+               m_chapters_start = (Double *) gf_realloc(m_chapters_start, sizeof(Double)*(m_num_chapters+1));
+               m_chapters_start[m_num_chapters] = seg->startTime;
+               m_num_chapters++;
+       }
+
+       /*get any service info*/
+       NetInfoCommand com;
+       if (!m_bStartupFile && gf_term_get_service_info(m_term, root_od, &com) == GF_OK) {
+               wxString title = wxT("");
+               if (com.track_info) { title.Format(wxT("%02d "), (u32) (com.track_info>>16) ); }
+               if (com.artist) { title.Append(wxString(com.artist, wxConvUTF8)); title += wxT(" "); }
+               if (com.name) { title.Append(wxString(com.name, wxConvUTF8)); title += wxT(" "); }
+               if (com.album) { title += wxT("("); title.Append(wxString(com.album, wxConvUTF8)); title += wxT(")"); }
+
+               if (title.length()) SetTitle(title);
+       }
+
+}
+
+void wxOsmo4Frame::OnChapterSel(wxCommandEvent & event)
+{
+       GF_ObjectManager *root_od = gf_term_get_root_object(m_term);
+       if (!root_od) return;
+       u32 ID = event.GetId() - ID_SETCHAP_FIRST;
+       gf_term_play_from_time(m_term, (u32) (1000*m_chapters_start[ID]), 0);
+}
+
+void wxOsmo4Frame::OnUpdateChapterSel(wxUpdateUIEvent & event)
+{
+       Double now;
+       Bool is_current;
+       u32 ID = event.GetId() - ID_SETCHAP_FIRST;
+
+       now = gf_term_get_time_in_ms(m_term);
+       now /= 1000;
+
+       is_current = 0;
+       if (m_chapters_start[ID]<=now) {
+               if (ID+1<m_num_chapters) {
+                       if (m_chapters_start[ID+1]>now) is_current = 1;
+               } else {
+                       is_current = 1;
+               }
+       }
+       event.Enable(1);
+       event.Check(is_current ? 1 : 0);
+}
+
+void wxOsmo4Frame::OnUpdateChapterMenu(wxUpdateUIEvent & event)
+{
+       if (!m_connected || !m_num_chapters) {
+               event.Enable(0);
+       } else {
+               event.Enable(1);
+       }
+}
+
+void wxOsmo4Frame::OnFileCopy(wxCommandEvent &event)
+{
+       const char *text = gf_term_get_text_selection(m_term, 0);
+       if (!text) return;
+       if (!wxTheClipboard->Open()) return;
+
+       wxTheClipboard->SetData( new wxTextDataObject( wxString(text, wxConvUTF8)) );
+       wxTheClipboard->Close();
+}
+
+void wxOsmo4Frame::OnUpdateFileCopy(wxUpdateUIEvent &event)
+{
+       if (gf_term_get_text_selection(m_term, 1)!=NULL) {
+               event.Enable(1);
+       } else {
+               event.Enable(0);
+       }
+}
+
+void wxOsmo4Frame::OnFilePaste(wxCommandEvent &event)
+{
+       if (!wxTheClipboard->Open()) return;
+    if (wxTheClipboard->IsSupported( wxDF_TEXT )) {
+               wxTextDataObject data;
+               wxTheClipboard->GetData(data);
+               gf_term_paste_text(m_term, data.GetText().mb_str(wxConvUTF8), 0);
+       }
+       wxTheClipboard->Close();
+}
+
+void wxOsmo4Frame::OnUpdateFilePaste(wxUpdateUIEvent &event)
+{
+       Bool ok = 0;
+       if (wxTheClipboard->Open()) {
+           if (wxTheClipboard->IsSupported( wxDF_TEXT )) {
+                       if (gf_term_paste_text(m_term, NULL, 1)==GF_OK) {
+                               ok = 1;
+                       }
+               }
+               wxTheClipboard->Close();
+       }
+       event.Enable(ok ? 1 : 0);
+}
+
diff --git a/applications/osmo4_wx/wxOsmo4.h b/applications/osmo4_wx/wxOsmo4.h
new file mode 100644 (file)
index 0000000..6c2b463
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Osmo4 wxWidgets GUI
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  GPAC 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifndef _WXOSMO4_H
+#define _WXOSMO4_H
+
+/*
+we need to force X to work in sync mode when we use embedded view...
+include first to avoid Bool type redef between X11 and gpac
+*/
+#ifdef __WXGTK__
+#include <X11/Xlib.h>
+#endif
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <wx/image.h>
+#include <wx/listctrl.h>
+#include <wx/event.h>
+#include "menubtn.h"
+
+/*include gpac AFTER wx in case we override malloc/realloc/free for mem tracking*/
+#include <gpac/terminal.h>
+#include <gpac/term_info.h>
+
+class wxOsmo4App : public wxApp
+{
+public:
+       virtual bool OnInit();
+};
+
+DECLARE_APP(wxOsmo4App)
+
+class wxOsmo4Frame;
+class wxPlaylist;
+
+class GPACLogs : public wxLogWindow {
+public:
+    GPACLogs(wxFrame *parent) : wxLogWindow(parent, wxT("GPAC Logs"), FALSE, FALSE) {
+               m_pMain = (wxOsmo4Frame *) parent;
+       }
+       virtual bool OnFrameClose(wxFrame *frame);
+
+private:
+       wxOsmo4Frame *m_pMain;
+};
+
+#define MAX_VIEWPOINTS 50
+
+// Menu commands
+enum
+{
+       GWX_FILE_OPEN = wxID_HIGHEST,
+       GWX_FILE_OPEN_URL,
+       FILE_RELOAD,
+       FILE_RELOAD_CONFIG,
+       FILE_PLAY,
+       FILE_STEP,
+       FILE_STOP,
+       FILE_PREV,
+       FILE_NEXT,
+       FILE_PROPERTIES,
+       FILE_COPY,
+       FILE_PASTE,
+       TERM_RELOAD,
+       FILE_QUIT,
+       VIEW_FULLSCREEN,
+       VIEW_ORIGINAL,
+       VIEW_AR_KEEP,
+       VIEW_AR_FILL,
+       VIEW_AR_43,
+       VIEW_AR_169,
+       VIEW_OPTIONS,
+       VIEW_LOGS,
+       VIEW_RTI,
+       VIEW_PLAYLIST,
+       SWITCH_RENDER,
+       APP_SHORTCUTS,
+       APP_NAV_KEYS,
+       APP_ABOUT,
+       ID_ADDRESS,
+       ID_URL_GO,
+       ID_ABOUT_CLOSE,
+       ID_CLEAR_NAV,
+       ID_STREAM_MENU,
+       ID_CHAPTER_MENU,
+       ID_ADD_SUB,
+
+       ID_MCACHE_ENABLE,
+       ID_MCACHE_STOP,
+       ID_MCACHE_ABORT,
+
+       ID_CTRL_TIMER,
+       ID_SLIDER,
+
+       ID_TREE_VIEW,
+       ID_OD_TIMER,
+       ID_VIEW_SG,
+       ID_VIEW_WI,
+       ID_VIEW_SEL,
+
+
+       ID_HEADLIGHT,
+       ID_NAVIGATE_NONE,
+       ID_NAVIGATE_WALK,
+       ID_NAVIGATE_FLY,
+       ID_NAVIGATE_EXAMINE,
+       ID_NAVIGATE_SLIDE,
+       ID_NAVIGATE_PAN,
+       ID_NAVIGATE_ORBIT,
+       ID_NAVIGATE_GAME,
+       ID_NAVIGATE_RESET,
+
+       ID_COLLIDE_NONE,
+       ID_COLLIDE_REG,
+       ID_COLLIDE_DISP,
+       ID_GRAVITY,
+
+       ID_PL_OPEN,
+       ID_PL_SAVE,
+       ID_PL_ADD_FILE,
+       ID_PL_ADD_URL,
+       ID_PL_ADD_DIR,
+       ID_PL_ADD_DIR_REC,
+       ID_PL_REM_FILE,
+       ID_PL_REM_ALL,
+       ID_PL_REM_DEAD,
+       ID_PL_UP,
+       ID_PL_DOWN,
+       ID_PL_RANDOMIZE,
+       ID_PL_REVERSE,
+       ID_PL_SEL_REV,
+       ID_PL_SORT_TITLE,
+       ID_PL_SORT_FILE,
+       ID_PL_SORT_DUR,
+       ID_PL_PLAY,
+
+
+       /*reserve IDs for viewpoint menu*/
+       ID_VIEWPOINT_FIRST,
+       ID_VIEWPOINT_LAST = ID_VIEWPOINT_FIRST + MAX_VIEWPOINTS,
+
+       /*reserve IDs for navigation menus*/
+       ID_NAV_PREV_0,
+       ID_NAV_PREV_9 = ID_NAV_PREV_0 + 10,
+       ID_NAV_NEXT_0,
+       ID_NAV_NEXT_9 = ID_NAV_NEXT_0 + 10,
+       /*reserve IDs for stream selection menus*/
+       ID_SELSTREAM_0,
+       ID_SELSTREAM_9 = ID_SELSTREAM_0 + 10,
+
+       /*reserve IDs for chapter selection menus*/
+       ID_SETCHAP_FIRST,
+       ID_SETCHAP_LAST = ID_SELSTREAM_0 + 200,
+};
+
+wxString get_pref_browser(GF_Config *cfg);
+
+class wxGPACEvent : public wxEvent
+{
+public:
+       wxGPACEvent( wxWindow* win = (wxWindow*) NULL );
+       void CopyObject( wxObject& obj ) const;
+       virtual wxEvent *Clone() const;
+
+       wxString to_url;
+       GF_Event gpac_evt;
+
+       DECLARE_DYNAMIC_CLASS(wxGPACEvent)
+};
+typedef void (wxEvtHandler::*GPACEventFunction)(wxGPACEvent&);
+DEFINE_EVENT_TYPE(GPAC_EVENT)
+
+#define EVT_GPACEVENT(func) DECLARE_EVENT_TABLE_ENTRY(GPAC_EVENT, -1, -1, (wxObjectEventFunction) (wxEventFunction) (GPACEventFunction) & func, (wxObject*) NULL),
+
+class OpenURLDlg : public wxDialog {
+public:
+    OpenURLDlg(wxWindow *parent, GF_Config *cfg);
+       wxString m_urlVal;
+private:
+    wxButton *m_go;
+    wxComboBox *m_url;
+       GF_Config *m_cfg;
+       void OnGo(wxCommandEvent& event);
+    DECLARE_EVENT_TABLE()
+};
+
+class wxMyComboBox : public wxComboBox
+{
+public:
+       wxMyComboBox(wxWindow* parent, wxWindowID id, const wxString& value = wxT(""), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize)
+               : wxComboBox(parent, id, value, pos, size, 0, NULL, wxCB_DROPDOWN)
+       {}
+
+private:
+       DECLARE_EVENT_TABLE()
+
+       void OnKeyUp(wxKeyEvent &event);
+};
+
+class wxOsmo4Frame : public wxFrame {
+public:
+    wxOsmo4Frame();
+    virtual ~wxOsmo4Frame();
+
+       char szAppPath[GF_MAX_PATH];
+
+       u32 m_duration;
+       wxString the_next_url;
+       GF_Terminal *m_term;
+       GF_User m_user;
+       Bool m_connected, m_can_seek, m_console_off, m_loop, m_lookforsubs;
+
+       void DoConnect();
+
+       void ConnectAcknowledged(Bool bOk);
+       void SetStatus(wxString str);
+
+       void OnFilePlay(wxCommandEvent &event);
+       void OnFileStep(wxCommandEvent &event);
+       void OnFileStop(wxCommandEvent &event);
+       wxString GetFileFilter();
+
+       void BuildViewList();
+       void BuildStreamList(Bool reset_only);
+       void BuildChapterList(Bool reset_only);
+
+       void AddSubtitle(const char *fileName, Bool auto_play);
+
+       wxWindow *m_pView;
+
+#ifdef __WXGTK__
+       u32 m_last_grab_time, m_last_grab_pos;
+       wxWindow *m_pVisual;
+#endif
+       wxSlider *m_pProg;
+       wxPlaylist *m_pPlayList;
+
+       void DoLayout(u32 v_width = 0, u32 v_height = 0);
+       s32 m_last_prog;
+
+       FILE *m_logs;
+       u32 m_log_level, m_log_tools;
+       u32 m_LastStatusTime;
+
+protected:
+
+private:
+       DECLARE_EVENT_TABLE()
+
+       void OnCloseApp(wxCloseEvent &event);
+       void OnSize(wxSizeEvent &event);
+
+       void OnFileOpen(wxCommandEvent &event);
+       void OnFileOpenURL(wxCommandEvent &event);
+       void OnFileReload(wxCommandEvent &event);
+       void OnFileReloadConfig(wxCommandEvent & event);
+       void OnFileProperties(wxCommandEvent &event);
+       void OnFileQuit(wxCommandEvent &event);
+       void OnFullScreen(wxCommandEvent &event);
+       void OnOptions(wxCommandEvent &event);
+       void OnViewARKeep(wxCommandEvent &event);
+       void OnViewARFill(wxCommandEvent &event);
+       void OnViewAR169(wxCommandEvent &event);
+       void OnViewAR43(wxCommandEvent &event);
+       void OnViewOriginal(wxCommandEvent &event);
+       void OnPlaylist(wxCommandEvent &event);
+       void OnShortcuts(wxCommandEvent &event);
+       void OnNavInfo(wxCommandEvent &event);
+       void OnAddSub(wxCommandEvent &event);
+       void OnAbout(wxCommandEvent &event);
+       Bool LoadTerminal();
+       void OnGPACEvent(wxGPACEvent &event);
+       void OnTimer(wxTimerEvent& event);
+       void OnSlide(wxScrollEvent &event);
+       void OnRelease(wxScrollEvent &event);
+       void OnLogs(wxCommandEvent & event);
+       void OnRTI(wxCommandEvent & event);
+       void OnUpdatePlay(wxUpdateUIEvent &event);
+       void OnUpdateNeedsConnect(wxUpdateUIEvent &event);
+       void OnUpdateFullScreen(wxUpdateUIEvent &event);
+       void OnUpdateAR(wxUpdateUIEvent &event);
+       void OnViewport(wxCommandEvent & event);
+       void OnUpdateViewport(wxUpdateUIEvent & event);
+       void OnNavigate(wxCommandEvent & event);
+       void OnNavigateReset(wxCommandEvent & event);
+       void OnUpdateNavigation(wxUpdateUIEvent & event);
+       void OnRenderSwitch(wxCommandEvent &event);
+       void OnCollide(wxCommandEvent & event);
+       void OnUpdateCollide(wxUpdateUIEvent & event);
+       void OnHeadlight(wxCommandEvent & event);
+       void OnUpdateHeadlight(wxUpdateUIEvent & event);
+       void OnGravity(wxCommandEvent & event);
+       void OnUpdateGravity(wxUpdateUIEvent & event);
+       void OnURLSelect(wxCommandEvent &event);
+       void OnUpdatePlayList(wxUpdateUIEvent & event);
+       void OnFilePrevOpen(wxNotifyEvent & event);
+       void OnFileNextOpen(wxNotifyEvent & event);
+       void OnNavPrev(wxCommandEvent &event);
+       void OnUpdateNavPrev(wxUpdateUIEvent & event);
+       void OnNavPrevMenu(wxCommandEvent &event);
+       void OnNavNext(wxCommandEvent &event);
+       void OnUpdateNavNext(wxUpdateUIEvent & event);
+       void OnNavNextMenu(wxCommandEvent &event);
+       void OnClearNav(wxCommandEvent &event);
+       void OnStreamSel(wxCommandEvent &event);
+       void OnUpdateStreamSel(wxUpdateUIEvent & event);
+       void OnUpdateStreamMenu(wxUpdateUIEvent & event);
+       void OnChapterSel(wxCommandEvent &event);
+       void OnUpdateChapterSel(wxUpdateUIEvent & event);
+       void OnUpdateChapterMenu(wxUpdateUIEvent & event);
+
+       void SelectionReady();
+       void ReloadURLs();
+       void LookForSubtitles();
+
+       void OnCacheEnable(wxCommandEvent &event);
+       void OnCacheStop(wxCommandEvent &event);
+       void OnCacheAbort(wxCommandEvent &event);
+       void OnUpdateCacheEnable(wxUpdateUIEvent & event);
+       void OnUpdateCacheAbort(wxUpdateUIEvent & event);
+
+       void OnFileCopy(wxCommandEvent &event);
+       void OnUpdateFileCopy(wxUpdateUIEvent &event);
+       void OnFilePaste(wxCommandEvent &event);
+       void OnUpdateFilePaste(wxUpdateUIEvent &event);
+
+
+       void CheckVideoOut();
+
+    wxMenuBar* m_pMenubar;
+    wxStatusBar* m_pStatusbar;
+       wxTimer *m_pTimer;
+       GPACLogs *m_pLogs;
+       wxBoxSizer *m_pAddBar;
+
+       Bool m_bGrabbed, m_bToReset, m_bFirstStreamListBuild;
+       wxBitmap *m_pOpenFile, *m_pPrev, *m_pNext, *m_pPlay, *m_pPause, *m_pStep, *m_pStop, *m_pInfo, *m_pConfig, *m_pSW2D, *m_pSW3D;
+       wxMenuButton *m_pPrevBut, *m_pNextBut;
+       wxToolBar *m_pToolBar;
+       wxMyComboBox *m_Address;
+
+       wxMenu *vp_list;
+       wxMenu *sel_menu;
+       wxMenu *chap_menu;
+       void Stop();
+
+       s32 nb_viewpoints;
+
+       void UpdateRenderSwitch();
+       void UpdatePlay();
+
+       u32 m_orig_width, m_orig_height;
+
+       u32 m_num_chapters;
+       Double *m_chapters_start;
+       Bool m_bExternalView, m_bViewRTI, m_bStartupFile;
+
+       void ShowViewWindow(Bool do_show);
+};
+
+
+#endif  //_WXOSMO4_H
+
diff --git a/applications/osmo4_wx/wxOsmo4.rc b/applications/osmo4_wx/wxOsmo4.rc
new file mode 100644 (file)
index 0000000..3e839b8
--- /dev/null
@@ -0,0 +1,72 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_OSMO_ICON               ICON    DISCARDABLE     "../../doc/osmo4.ico"
+#endif    // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/applications/osmozilla/Makefile b/applications/osmozilla/Makefile
deleted file mode 100644 (file)
index 869f2be..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-include ../../config.mak
-
-vpath %.cpp $(SRC_PATH)/applications/osmozilla
-
-ifeq ($(CONFIG_WIN32),yes)
-USER_NAME=root
-else
-USER_NAME=$(shell whoami)
-ifeq ($(USER_NAME), root)
-else
-MOZILLA_DIR=local
-endif
-endif
-
-CFLAGS=$(CPPFLAGS) $(XUL_CFLAGS) -I"$(SRC_PATH)/include"
-
-ifeq ($(DEBUGBUILD), yes)
-CFLAGS+=-g
-LDFLAGS+=-g
-endif
-
-ifeq ($(GPROFBUILD), yes)
-CFLAGS+=-pg
-LDFLAGS+=-pg
-endif
-
-ifeq ($(CONFIG_WIN32),yes)
-CFLAGS+=-DXP_WIN
-else
-ifeq ($(CONFIG_DARWIN),yes)
-CFLAGS+=-DXP_MAC
-else
-CFLAGS+=-DXP_UNIX -DMOZ_X11
-endif
-endif
-
-CFLAGS+=-DNPBASIC_EXPORTS -DMOZILLA_STRICT_API -DXPCOM_GLUE
-
-
-LINKLIBS=-L../../bin/gcc -lgpac
-
-OBJS=osmozilla.o osmo_npapi.o
-
-SRCS := $(OBJS:.o=.cpp) 
-
-
-LIB=nposmozilla.$(DYN_LIB_SUFFIX)
-ifeq ($(CONFIG_WIN32),yes)
-LINKLIBS+=-lwinmm -lgdi32
-LDFLAGS+=--export-all-symbols
-endif
-
-all: $(LIB)
-
-$(LIB): $(OBJS)
-ifeq ($(CONFIG_WIN32),yes)
-       windres osmozilla.rc osmoz.o
-       $(CXX) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) osmoz.o $(LINKLIBS)
-       cp "$(SRC_PATH)/applications/osmozilla/nsIOsmozilla.xpt_w32" ../../bin/gcc/nposmozilla.xpt
-       chmod +w ../../bin/gcc/nposmozilla.xpt
-else
-       $(CXX) $(SHFLAGS) $(LDFLAGS) $(OBJS) $(LINKLIBS) -o ../../bin/gcc/$@ 
-       cp "$(SRC_PATH)/applications/osmozilla/nsIOsmozilla.xpt_linux" ../../bin/gcc/nposmozilla.xpt
-       chmod +w ../../bin/gcc/nposmozilla.xpt
-endif
-       @echo $(USER_ROOT)
-
-%.o: %.cpp
-       $(CXX) $(CFLAGS) -c -o $@ $< 
-
-clean:
-       rm -f $(OBJS) ../../bin/gcc/$(LIB) ../../bin/gcc/nposmozilla.xpt
-ifeq ($(CONFIG_WIN32),yes)
-       rm -f osmoz.o
-endif
-
-install: 
-ifeq ($(MOZILLA_DIR), local)
-ifeq ($(USER_NAME), root)
-       @echo "*** Root cannot install local mozilla plugins! ***"
-       @echo "*** Exit root mode and reinstall mozilla plugin! ***"
-else
-       $(MAKE) $(LIB)
-       install -D -m 755 ../../bin/gcc/$(LIB) "$(HOME)/.mozilla/plugins/$(LIB)"
-       install -D -m 755 ../../bin/gcc/nposmozilla.xpt "$(HOME)/.mozilla/components/nposmozilla.xpt"
-endif
-else
-       install -D -m 755 ../../bin/gcc/$(LIB) "$(MOZILLA_DIR)/components/$(LIB)"
-       install -D -m 755 ../../bin/gcc/nposmozilla.xpt "$(MOZILLA_DIR)/components/nposmozilla.xpt"
-endif
-
-uninstall:
-ifeq ($(MOZILLA_DIR), local)
-ifeq ($(USER_NAME), root)
-else
-       rm -rf "$(HOME)/.mozilla/plugins/$(LIB)"
-       rm -rf "$(HOME)/.mozilla/components/nposmozilla.xpt"
-endif
-else
-       rm -rf "$(MOZILLA_DIR)/components/$(LIB)"
-       rm -rf "$(MOZILLA_DIR)/components/nposmozilla.xpt"
-endif
-
-dep: depend
-
-depend:
-       rm -f .depend   
-       $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
-
-distclean: clean
-       rm -f Makefile.bak .depend
-
diff --git a/applications/osmozilla/nsIOsmozilla.h b/applications/osmozilla/nsIOsmozilla.h
deleted file mode 100644 (file)
index 15869d4..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-* DO NOT EDIT.  THIS FILE IS GENERATED FROM nsIOsmozilla.idl
-*/
-
-#ifndef __gen_nsIOsmozilla_h__
-#define __gen_nsIOsmozilla_h__
-
-#include "osmo_npapi.h"
-
-#ifdef GECKO_XPCOM
-
-#ifndef __gen_nsISupports_h__
-#include "nsISupports.h"
-#endif
-
-/* For IDL files that don't want to include root IDL files. */
-#ifndef NS_NO_VTABLE
-#define NS_NO_VTABLE
-#endif
-
-/* starting interface:    nsIOsmozilla */
-#define NS_IOSMOZILLA_IID_STR "d2d536a0-b6fc-11d5-9d10-0060b0fbd80b"
-
-#define NS_IOSMOZILLA_IID \
-  {0xd2d536a0, 0xb6fc, 0x11d5, \
-       { 0x9d, 0x10, 0x00, 0x60, 0xb0, 0xfb, 0xd8, 0x0b }}
-
-class NS_NO_VTABLE nsIOsmozilla : public nsISupports {
-public: 
-
-       NS_DEFINE_STATIC_IID_ACCESSOR(NS_IOSMOZILLA_IID)
-
-               /* void Pause (); */
-               NS_IMETHOD Pause(void) = 0;
-
-       /* void Play (); */
-       NS_IMETHOD Play(void) = 0;
-
-       /* void Stop (); */
-       NS_IMETHOD Stop(void) = 0;
-
-       /* void Update (in string type, in string commands); */
-       NS_IMETHOD Update(const char *type, const char *commands) = 0;
-
-};
-
-/* Use this macro when declaring classes that implement this interface. */
-#define NS_DECL_NSIOSMOZILLA \
-       NS_IMETHOD Pause(void); \
-       NS_IMETHOD Play(void); \
-       NS_IMETHOD Stop(void); \
-       NS_IMETHOD Update(const char *type, const char *commands); 
-
-/* Use this macro to declare functions that forward the behavior of this interface to another object. */
-#define NS_FORWARD_NSIOSMOZILLA(_to) \
-       NS_IMETHOD Pause(void) { return _to Pause(); } \
-       NS_IMETHOD Play(void) { return _to Play(); } \
-       NS_IMETHOD Stop(void) { return _to Stop(); } \
-       NS_IMETHOD Update(const char *type, const char *commands) { return _to Update(type, commands); } 
-
-/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
-#define NS_FORWARD_SAFE_NSIOSMOZILLA(_to) \
-       NS_IMETHOD Pause(void) { return !_to ? NS_ERROR_NULL_POINTER : _to->Pause(); } \
-       NS_IMETHOD Play(void) { return !_to ? NS_ERROR_NULL_POINTER : _to->Play(); } \
-       NS_IMETHOD Stop(void) { return !_to ? NS_ERROR_NULL_POINTER : _to->Stop(); } \
-       NS_IMETHOD Update(const char *type, const char *commands) { return !_to ? NS_ERROR_NULL_POINTER : _to->Update(type, commands); } 
-
-#if 0
-/* Use the code below as a template for the implementation class for this interface. */
-
-/* Header file */
-class nsOsmozilla : public nsIOsmozilla
-{
-public:
-       NS_DECL_ISUPPORTS
-               NS_DECL_NSIOSMOZILLA
-
-               nsOsmozilla();
-       virtual ~nsOsmozilla();
-       /* additional members */
-};
-
-/* Implementation file */
-NS_IMPL_ISUPPORTS1(nsOsmozilla, nsIOsmozilla)
-
-nsOsmozilla::nsOsmozilla()
-{
-       /* member initializers and constructor code */
-}
-
-nsOsmozilla::~nsOsmozilla()
-{
-       /* destructor code */
-}
-
-/* void Pause (); */
-NS_IMETHODIMP nsOsmozilla::Pause()
-{
-       return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* void Play (); */
-NS_IMETHODIMP nsOsmozilla::Play()
-{
-       return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* void Stop (); */
-NS_IMETHODIMP nsOsmozilla::Stop()
-{
-       return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* void Update (in string type, in string commands); */
-NS_IMETHODIMP nsOsmozilla::Update(const char *type, const char *commands)
-{
-       return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* End of implementation class template. */
-#endif
-
-#endif //GECKO_XPCOM
-
-#endif /* __gen_nsIOsmozilla_h__ */
diff --git a/applications/osmozilla/nsIOsmozilla.idl b/applications/osmozilla/nsIOsmozilla.idl
deleted file mode 100644 (file)
index 338fb96..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "nsISupports.idl"
-
-[scriptable, uuid(d2d536a0-b6fc-11d5-9d10-0060b0fbd8bn)]
-interface nsIOsmozilla : nsISupports {
-  void Pause();
-  void Play();
-  void Stop();
-  void Update(in string type, in string commands);
-};
diff --git a/applications/osmozilla/nsIOsmozilla.xpt_linux b/applications/osmozilla/nsIOsmozilla.xpt_linux
deleted file mode 100644 (file)
index 1c96fbb..0000000
Binary files a/applications/osmozilla/nsIOsmozilla.xpt_linux and /dev/null differ
diff --git a/applications/osmozilla/nsIOsmozilla.xpt_w32 b/applications/osmozilla/nsIOsmozilla.xpt_w32
deleted file mode 100644 (file)
index 1c96fbb..0000000
Binary files a/applications/osmozilla/nsIOsmozilla.xpt_w32 and /dev/null differ
diff --git a/applications/osmozilla/osmo_npapi.cpp b/applications/osmozilla/osmo_npapi.cpp
deleted file mode 100644 (file)
index 6e11664..0000000
+++ /dev/null
@@ -1,773 +0,0 @@
-/*\r
-*                      GPAC - Multimedia Framework C SDK\r
-*\r
-*                      Copyright (c) ENST 2000-200X\r
-*                                      All rights reserved\r
-*\r
-*  This file is part of GPAC / Osmozilla NPAPI plugin\r
-*\r
-*  GPAC is free software; you can redistribute it and/or modify\r
-*  it under the terms of the GNU Lesser General Public License as published by\r
-*  the Free Software Foundation; either version 2, or (at your option)\r
-*  any later version.\r
-*   \r
-*  GPAC is distributed in the hope that it will be useful,\r
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*  GNU Lesser General Public License for more details.\r
-*   \r
-*  You should have received a copy of the GNU Lesser General Public\r
-*  License along with this library; see the file COPYING.  If not, write to\r
-*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
-*\r
-*/\r
-\r
-\r
-////////////////////////////////////////////////////////////\r
-//\r
-// Implementation of Netscape entry points (NPN_*)\r
-//\r
-#include "osmo_npapi.h"\r
-#include "osmozilla.h"\r
-\r
-#if defined(XP_UNIX) && !defined(XP_MACOS) 
-#include <malloc.h>\r
-#include <string.h>\r
-#endif
-\r
-NPNetscapeFuncs *sBrowserFunctions = NULL;\r
-\r
-NPError Osmozilla_GetURL(NPP instance, const char *url, const char *target)\r
-{\r
-       if (!sBrowserFunctions) return NPERR_INVALID_FUNCTABLE_ERROR;\r
-       return sBrowserFunctions->geturl(instance, url, target);\r
-}\r
-\r
-void Osmozilla_SetStatus(NPP instance, const char *message)\r
-{\r
-       if (!sBrowserFunctions) return;\r
-       sBrowserFunctions->status(instance, message);\r
-}\r
-\r
-#ifndef GECKO_XPCOM\r
-void Osmozilla_InitScripting(Osmozilla *osmo);\r
-#endif\r
-\r
-NPError NPOsmozilla_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)\r
-{   \r
-       Osmozilla *osmo;\r
-       NPError rv = NPERR_NO_ERROR;\r
-       if(instance == NULL)\r
-               return NPERR_INVALID_INSTANCE_ERROR;\r
-\r
-\r
-       osmo = (Osmozilla *) malloc(sizeof(Osmozilla));\r
-       memset(osmo, 0, sizeof(Osmozilla));\r
-\r
-       osmo->np_instance = instance;\r
-       // associate the plugin instance object with NPP instance\r
-       instance->pdata = (void *)osmo;\r
-\r
-       Osmozilla_Initialize(osmo, argc, argn, argv);\r
-\r
-#ifndef GECKO_XPCOM\r
-       Osmozilla_InitScripting(osmo);\r
-#endif\r
-\r
-       return rv;\r
-}\r
-\r
-// here is the place to clean up and destroy the nsPluginInstance object\r
-NPError NPOsmozilla_Destroy (NPP instance, NPSavedData** save)\r
-{\r
-       NPError rv = NPERR_NO_ERROR;\r
-       Osmozilla *osmozilla;\r
-       if(instance == NULL)\r
-               return NPERR_INVALID_INSTANCE_ERROR;\r
-\r
-       osmozilla = (Osmozilla*)instance->pdata;\r
-       if (osmozilla != NULL) {\r
-               Osmozilla_Shutdown(osmozilla);\r
-#ifdef GECKO_XPCOM\r
-               NPOsmozilla_ShutdownScript(osmozilla);\r
-#else\r
-               if (osmozilla->script_obj) sBrowserFunctions->releaseobject(osmozilla->script_obj);\r
-               osmozilla->script_obj = NULL;\r
-#endif\r
-\r
-               free(osmozilla);\r
-       }\r
-       instance->pdata = NULL;\r
-       return rv;\r
-}\r
-\r
-// during this call we know when the plugin window is ready or\r
-// is about to be destroyed so we can do some gui specific\r
-// initialization and shutdown\r
-NPError NPOsmozilla_SetWindow (NPP instance, NPWindow* pNPWindow)\r
-{    \r
-       Osmozilla *osmozilla;\r
-       void *os_wnd_handle, *os_wnd_display;\r
-       NPError rv = NPERR_NO_ERROR;\r
-\r
-       if (!instance || !instance->pdata) return NPERR_INVALID_INSTANCE_ERROR;\r
-       if (pNPWindow == NULL) return NPERR_GENERIC_ERROR;\r
-       osmozilla = (Osmozilla *)instance->pdata;\r
-\r
-       // window just created\r
-       if (!osmozilla->window_set) {\r
-               if (pNPWindow->window == NULL) return NPERR_GENERIC_ERROR;\r
-\r
-#ifdef XP_WIN\r
-               os_wnd_handle = pNPWindow->window;\r
-               os_wnd_display = NULL;\r
-#elif defined(XP_MAXOS)\r
-               os_wnd_handle = pNPWindow->window;\r
-               os_wnd_display = NULL;\r
-#elif defined(XP_UNIX)\r
-               os_wnd_handle = pNPWindow->window;\r
-               /*HACK - although we don't use the display in the X11 plugin, this is used to signal that \r
-               the user is mozilla and prevent some X11 calls crashing the browser in file playing mode \r
-               (eg, "firefox myfile.mp4" )*/\r
-               os_wnd_display =((NPSetWindowCallbackStruct *)pNPWindow->ws_info)->display;\r
-#endif\r
-\r
-               if (! Osmozilla_SetWindow(osmozilla, os_wnd_handle, os_wnd_display, pNPWindow->width, pNPWindow->height) ) {\r
-                       return NPERR_MODULE_LOAD_FAILED_ERROR;\r
-               }\r
-\r
-       }\r
-\r
-#if 0\r
-       // window goes away\r
-       if((pNPWindow->window == NULL) && plugin->isInitialized())\r
-               return plugin->SetWindow(pNPWindow);\r
-\r
-       // window resized?\r
-       if(plugin->isInitialized() && (pNPWindow->window != NULL))\r
-               return plugin->SetWindow(pNPWindow);\r
-\r
-       // this should not happen, nothing to do\r
-       if((pNPWindow->window == NULL) && !plugin->isInitialized())\r
-               return plugin->SetWindow(pNPWindow);\r
-#endif\r
-\r
-       return rv;\r
-}\r
-\r
-NPError NPOsmozilla_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t *stype)\r
-{\r
-       Osmozilla *osmozilla;\r
-       if(instance == NULL)\r
-               return NPERR_INVALID_INSTANCE_ERROR;\r
-\r
-       osmozilla = (Osmozilla *)instance->pdata;\r
-       if(osmozilla== NULL) \r
-               return NPERR_GENERIC_ERROR;\r
-\r
-       Osmozilla_ConnectTo(osmozilla, stream->url);\r
-       *stype = NP_SEEK;\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-NPINT32 NPOsmozilla_WriteReady (NPP instance, NPStream *stream)\r
-{\r
-       return 0x0fffffff;\r
-}\r
-\r
-NPINT32 NPOsmozilla_Write (NPP instance, NPStream *stream, NPINT32 offset, NPINT32 len, void *buffer)\r
-{   \r
-       return len;\r
-}\r
-\r
-NPError NPOsmozilla_DestroyStream (NPP instance, NPStream *stream, NPError reason)\r
-{\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-void NPOsmozilla_StreamAsFile (NPP instance, NPStream* stream, const char* fname)\r
-{\r
-}\r
-\r
-void NPOsmozilla_Print (NPP instance, NPPrint* printInfo)\r
-{\r
-       Osmozilla *osmozilla;\r
-       if(instance == NULL)\r
-               return;\r
-\r
-       osmozilla = (Osmozilla *)instance->pdata;\r
-       if(osmozilla== NULL) \r
-               return;\r
-\r
-       Osmozilla_Print(osmozilla, (printInfo->mode == NP_EMBED) ? 1 : 0, printInfo->print.embedPrint.platformPrint, \r
-               printInfo->print.embedPrint.window.x, printInfo->print.embedPrint.window.y,\r
-               printInfo->print.embedPrint.window.width, printInfo->print.embedPrint.window.height);\r
-}\r
-\r
-void NPOsmozilla_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)\r
-{\r
-       return;\r
-}\r
-\r
-NPError        NPOsmozilla_GetValue(NPP instance, NPPVariable variable, void *value)\r
-{\r
-       NPError rv = NPERR_NO_ERROR;\r
-       Osmozilla *osmozilla;\r
-       if(instance == NULL)\r
-               return NPERR_INVALID_INSTANCE_ERROR;\r
-\r
-       osmozilla = (Osmozilla *)instance->pdata;\r
-       if(osmozilla== NULL) return NPERR_GENERIC_ERROR;\r
-\r
-       switch (variable) {\r
-#ifdef GECKO_XPCOM\r
-       case NPPVpluginScriptableInstance:\r
-               rv = NPOsmozilla_GetPeer(osmozilla, value);\r
-               break;  \r
-\r
-       case NPPVpluginScriptableIID:\r
-               rv = NPOsmozilla_GetPeerIID(osmozilla, value);\r
-               break;\r
-#else\r
-\r
-       case NPPVpluginScriptableNPObject:\r
-               sBrowserFunctions->retainobject(osmozilla->script_obj);\r
-               * (void **)value = osmozilla->script_obj;\r
-               break;\r
-\r
-#endif\r
-       case NPPVpluginNameString :\r
-               *(const char**)value = "Osmozilla/GPAC plugin for NPAPI";\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       return rv;\r
-}\r
-\r
-\r
-\r
-NPError NPOsmozilla_SetValue(NPP instance, NPNVariable variable, void *value)\r
-{\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-int16_t        NPOsmozilla_HandleEvent(NPP instance, void* event)\r
-{\r
-       /*we hacked the proc*/\r
-       return 0;\r
-}\r
-\r
-\r
-NPError OSCALL NP_Shutdown()\r
-{\r
-#ifdef GECKO_XPCOM\r
-       NPOsmozilla_ReleaseServiceManager();\r
-#endif\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-static NPError fillPluginFunctionTable(NPPluginFuncs* aNPPFuncs)\r
-{\r
-       if(aNPPFuncs == NULL)\r
-               return NPERR_INVALID_FUNCTABLE_ERROR;\r
-\r
-       // Set up the plugin function table that Netscape will use to\r
-       // call us. Netscape needs to know about our version and size   \r
-       // and have a UniversalProcPointer for every function we implement.\r
-\r
-       aNPPFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;\r
-       aNPPFuncs->newp          = NPOsmozilla_New;\r
-       aNPPFuncs->destroy       = NPOsmozilla_Destroy;\r
-       aNPPFuncs->setwindow     = NPOsmozilla_SetWindow;\r
-       aNPPFuncs->newstream     = NPOsmozilla_NewStream;\r
-       aNPPFuncs->destroystream = NPOsmozilla_DestroyStream;\r
-       aNPPFuncs->asfile        = NPOsmozilla_StreamAsFile;\r
-       aNPPFuncs->writeready    = NPOsmozilla_WriteReady;\r
-       aNPPFuncs->write         = NPOsmozilla_Write;\r
-       aNPPFuncs->print         = NPOsmozilla_Print;\r
-       aNPPFuncs->event         = NPOsmozilla_HandleEvent;\r
-       aNPPFuncs->urlnotify     = NPOsmozilla_URLNotify;\r
-       aNPPFuncs->getvalue      = NPOsmozilla_GetValue;\r
-       aNPPFuncs->setvalue      = NPOsmozilla_SetValue;\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-\r
-static NPError NS_PluginInitialize()\r
-{\r
-#ifdef GECKO_XPCOM\r
-       NPOsmozilla_GetServiceManager();\r
-#endif\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-// get values per plugin\r
-NPError NS_PluginGetValue(NPPVariable aVariable, void *aValue)\r
-{\r
-       NPError err = NPERR_NO_ERROR;\r
-       switch (aVariable) {\r
-       case NPPVpluginNameString:\r
-               *((char **)aValue) = (char *) "Osmozilla";\r
-               break;\r
-       case NPPVpluginDescriptionString:\r
-               *((char **)aValue) = Osmozilla_GetVersion();\r
-               break;\r
-       default:\r
-               err = NPERR_INVALID_PARAM;\r
-               break;\r
-       }\r
-       return err;\r
-}\r
-\r
-\r
-\r
-\r
-#define GPAC_PLUGIN_MIMETYPES \\r
-       "audio/mpeg:mp2,mp3,mpga,mpega:MP3 Music;" \\r
-       "audio/x-mpeg:mp2,mp3,mpga,mpega:MP3 Music;" \\r
-       "audio/amr:amr,awb:AMR Audio;" \\r
-       "audio/mp4:mp4,mpg4,mpeg4,m4a:MPEG-4 Audio;" \\r
-       "audio/aac:aac:MPEG-4 AAC Music;" \\r
-       "audio/aacp:aac:MPEG-4 AACPlus Music;" \\r
-       "audio/basic:snd,au:Basic Audio;"       \\r
-       "audio/x-wav:wav:WAV Audio;"    \\r
-       "audio/3gpp:3gp,3gpp:3GPP/MMS Music;"   \\r
-       "audio/3gpp2:3g2,3gp2:3GPP2/MMS Music;" \\r
-       "video/mpeg:mpg,mpeg,mpe,mpv2:MPEG Video;" \\r
-       "video/x-mpeg:mpg,mpeg,mpe,mpv2:MPEG Video;" \\r
-       "video/mpeg-system:mpg,mpeg,mpe,vob,mpv2:MPEG Video;" \\r
-       "video/x-mpeg-system:mpg,mpeg,mpe,vob,mpv2:MPEG Video;" \\r
-       "video/avi:avi:AVI Video;" \\r
-       "video/quicktime:mov,qt:QuickTime Movies;" \\r
-       "video/x-ms-asf:asf,asx:Windows Media Video;" \\r
-       "video/x-ms-wmv:wmv:Windows Media;" \\r
-       "video/mp4:mp4,mpg4:MPEG-4 Video;" \\r
-       "video/3gpp:3gp,3gpp:3GPP/MMS Video;" \\r
-       "video/3gpp2:3g2,3gp2:3GPP2/MMS Video;" \\r
-       "image/jpeg:jpeg,jpg:JPEG Images;"      \\r
-       "image/png:png:PNG Images;"     \\r
-       "image/bmp:bmp:MS Bitmap Images;"       \\r
-       "image/svg+xml:svg,svg.gz,svgz:SVG Document;"   \\r
-       "image/x-svgm:svgm:SVGM Document;"      \\r
-       "x-subtitle/srt:srt:SRT SubTitles;"     \\r
-       "x-subtitle/sub:sub:SUB SubTitles;"     \\r
-       "x-subtitle/ttxt:ttxt:GPAC 3GPP TimedText;"     \\r
-       "model/vrml:wrl,wrl.gz:VRML World;"     \\r
-       "model/x3d+vrml:x3dv,x3dv.gz,x3dvz:X3D/VRML World;"     \\r
-       "model/x3d+xml:x3d,x3d.gz,x3dz:X3D/XML World;" \\r
-       "application/ogg:ogg:Ogg Media;" \\r
-       "application/x-ogg:ogg:Ogg Media;" \\r
-       "application/x-bt:bt,bt.gz,btz:MPEG-4 Text (BT);"       \\r
-       "application/x-xmt:xmt,xmt.gz,xmtz:MPEG-4 Text (XMT);"  \\r
-       "application/mp4:mp4,mpg4:MPEG-4 Movies;" \\r
-       "application/sdp:sdp:Streaming Media Session;" \\r
-       /* explicit plugin call */ \\r
-       "application/x-gpac::GPAC plugin;" \\r
-\r
-char * NP_GetMIMEDescription(void)\r
-{\r
-       return (char *) GPAC_PLUGIN_MIMETYPES;\r
-}\r
-\r
-\r
-NPError NP_GetValue(void *future, NPPVariable aVariable, void *aValue)\r
-{\r
-       return NS_PluginGetValue(aVariable, aValue);\r
-}\r
-\r
-\r
-#if defined(XP_WIN) || defined(XP_MACOS) \r
-\r
-NPError OSCALL NP_Initialize(NPNetscapeFuncs* aNPNFuncs)\r
-{\r
-       sBrowserFunctions = aNPNFuncs;\r
-\r
-       return NS_PluginInitialize();\r
-}\r
-\r
-NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* aNPPFuncs)\r
-{\r
-       return fillPluginFunctionTable(aNPPFuncs);\r
-}\r
-\r
-\r
-#elif defined(XP_UNIX)\r
-\r
-NPError OSCALL NP_Initialize(NPNetscapeFuncs* aNPNFuncs, NPPluginFuncs* aNPPFuncs)\r
-{\r
-       NPError rv;\r
-       sBrowserFunctions = aNPNFuncs;\r
-       rv = fillPluginFunctionTable(aNPPFuncs);\r
-       if(rv != NPERR_NO_ERROR)\r
-               return rv;\r
-\r
-       return NS_PluginInitialize();\r
-}\r
-#endif\r
-\r
-\r
-#ifdef GECKO_XPCOM\r
-\r
-\r
-#include <nsIServiceManager.h>\r
-#include <nsIMemory.h>\r
-#include <nsISupportsUtils.h>\r
-#include <nsISupports.h>\r
-#include <nsMemory.h>\r
-\r
-#include "nsIOsmozilla.h"\r
-\r
-#include "osmozilla.h"\r
-\r
-\r
-nsIServiceManager *gServiceManager = NULL;\r
-\r
-\r
-// We must implement nsIClassInfo because it signals the\r
-// Mozilla Security Manager to allow calls from JavaScript.\r
-// helper class to implement all necessary nsIClassInfo method stubs\r
-// and to set flags used by the security system\r
-\r
-class nsClassInfoMixin : public nsIClassInfo\r
-{\r
-       // These flags are used by the DOM and security systems to signal that\r
-       // JavaScript callers are allowed to call this object's scritable methods.\r
-       NS_IMETHOD GetFlags(PRUint32 *aFlags)\r
-       {*aFlags = nsIClassInfo::PLUGIN_OBJECT | nsIClassInfo::DOM_OBJECT;\r
-       return NS_OK;}\r
-\r
-       NS_IMETHOD GetImplementationLanguage(PRUint32 *aImplementationLanguage)\r
-       {*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;\r
-       return NS_OK;}\r
-\r
-       // The rest of the methods can safely return error codes...\r
-       NS_IMETHOD GetInterfaces(PRUint32 *count, nsIID * **array)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-       NS_IMETHOD GetHelperForLanguage(PRUint32 language, nsISupports **_retval)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-       NS_IMETHOD GetContractID(char * *aContractID)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-       NS_IMETHOD GetClassDescription(char * *aClassDescription)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-       NS_IMETHOD GetClassID(nsCID * *aClassID)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-       NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)\r
-       {return NS_ERROR_NOT_IMPLEMENTED;}\r
-};\r
-\r
-\r
-class nsOsmozillaPeer : public nsIOsmozilla , public nsClassInfoMixin\r
-{\r
-public:\r
-       nsOsmozillaPeer(Osmozilla *osmo);\r
-       virtual ~nsOsmozillaPeer();\r
-\r
-       // methods from nsISupports\r
-       NS_IMETHOD QueryInterface(const nsIID & aIID, void **aInstancePtr);\r
-       NS_IMETHOD_(nsrefcnt) AddRef();\r
-       NS_IMETHOD_(nsrefcnt) Release();\r
-\r
-public:\r
-       NS_DECL_NSIOSMOZILLA\r
-               void SetInstance(Osmozilla *osmo);\r
-\r
-protected:\r
-       nsrefcnt mRefCnt; \r
-       Osmozilla *mPlugin;\r
-};\r
-\r
-\r
-static NS_DEFINE_IID(kIZillaPluginIID, NS_IOSMOZILLA_IID);\r
-static NS_DEFINE_IID(kIClassInfoIID, NS_ICLASSINFO_IID);\r
-static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);\r
-\r
-nsOsmozillaPeer::nsOsmozillaPeer(Osmozilla *osmo)\r
-{\r
-       mPlugin=osmo;\r
-       mRefCnt = 0;\r
-}\r
-\r
-nsOsmozillaPeer::~nsOsmozillaPeer()\r
-{\r
-}\r
-// Notice that we expose our claim to implement nsIClassInfo.\r
-//NS_IMPL_ISUPPORTS2(nsOsmozillaPeer, nsITestPlugin, nsIClassInfo)\r
-\r
-// the following method will be callable from JavaScript\r
-NS_IMETHODIMP nsOsmozillaPeer::Pause() { \r
-       Osmozilla_Pause(mPlugin); \r
-       return NS_OK; \r
-}\r
-NS_IMETHODIMP nsOsmozillaPeer::Play() { \r
-       Osmozilla_Play(mPlugin); \r
-       return NS_OK; \r
-}\r
-NS_IMETHODIMP nsOsmozillaPeer::Stop() { \r
-       Osmozilla_Stop(mPlugin); \r
-       return NS_OK; \r
-}\r
-\r
-NS_IMETHODIMP nsOsmozillaPeer::Update(const char *type, const char *commands) \r
-{\r
-       Osmozilla_Update(mPlugin, type, commands); \r
-       return NS_OK; \r
-}\r
-\r
-void nsOsmozillaPeer::SetInstance(Osmozilla *osmo)\r
-{\r
-       mPlugin = osmo;\r
-}\r
-\r
-NS_IMETHODIMP_(nsrefcnt) nsOsmozillaPeer::AddRef()\r
-{\r
-       ++mRefCnt;\r
-       return mRefCnt;\r
-}\r
-\r
-NS_IMETHODIMP_(nsrefcnt) nsOsmozillaPeer::Release()\r
-{\r
-       --mRefCnt;\r
-       if (mRefCnt == 0) {\r
-               delete this;\r
-               return 0;\r
-       }\r
-       return mRefCnt;\r
-}\r
-\r
-// here nsOsmozillaPeer should return three interfaces it can be asked for by their iid's\r
-// static casts are necessary to ensure that correct pointer is returned\r
-NS_IMETHODIMP nsOsmozillaPeer::QueryInterface(const nsIID & aIID,\r
-                                                                                         void **aInstancePtr)\r
-{\r
-       if (!aInstancePtr)\r
-               return NS_ERROR_NULL_POINTER;\r
-\r
-       if (aIID.Equals(kIZillaPluginIID)) {\r
-               *aInstancePtr = NS_STATIC_CAST(nsIOsmozilla *, this);\r
-               AddRef();\r
-               return NS_OK;\r
-       }\r
-\r
-       if (aIID.Equals(kIClassInfoIID)) {\r
-               *aInstancePtr = NS_STATIC_CAST(nsIClassInfo *, this);\r
-               AddRef();\r
-               return NS_OK;\r
-       }\r
-\r
-       if (aIID.Equals(kISupportsIID)) {\r
-               *aInstancePtr = NS_STATIC_CAST(nsISupports *, (NS_STATIC_CAST (nsIOsmozilla *, this)));\r
-               AddRef();\r
-               return NS_OK;\r
-       }\r
-       return NS_NOINTERFACE;\r
-}\r
-\r
-\r
-extern NPNetscapeFuncs *sBrowserFunctions;\r
-\r
-void NPOsmozilla_GetServiceManager()\r
-{\r
-       // this is probably a good place to get the service manager\r
-       // note that Mozilla will add reference, so do not forget to release\r
-       nsISupports *sm = NULL;\r
-\r
-       if (!sBrowserFunctions) return;\r
-       sBrowserFunctions->getvalue(NULL, NPNVserviceManager, &sm);\r
-\r
-       // Mozilla returns nsIServiceManager so we can use it directly; doing QI on\r
-       // nsISupports here can still be more appropriate in case something is changed\r
-       // in the future so we don't need to do casting of any sort.\r
-       if (sm) {\r
-               sm->QueryInterface(NS_GET_IID(nsIServiceManager), (void **) &gServiceManager);\r
-               NS_RELEASE(sm);\r
-       }\r
-}\r
-\r
-void NPOsmozilla_ReleaseServiceManager()\r
-{\r
-#ifdef GECKO_XPCOM\r
-       // we should release the service manager\r
-       NS_IF_RELEASE(gServiceManager);\r
-       gServiceManager = NULL;\r
-#endif\r
-}\r
-\r
-void NPOsmozilla_ShutdownScript(Osmozilla *osmo)\r
-{\r
-       nsOsmozillaPeer *peer = (nsOsmozillaPeer *) osmo->scriptable_peer;\r
-       if (peer != NULL) {\r
-               peer->SetInstance(NULL);\r
-               NS_IF_RELEASE(peer);\r
-       }\r
-}\r
-\r
-\r
-NPError        NPOsmozilla_GetPeer(Osmozilla *osmo, void *value)\r
-{\r
-       if (!osmo->scriptable_peer) {\r
-               osmo->scriptable_peer = new nsOsmozillaPeer(osmo);\r
-               if (!osmo->scriptable_peer) return NPERR_OUT_OF_MEMORY_ERROR;\r
-               NS_ADDREF( (nsOsmozillaPeer *) osmo->scriptable_peer);\r
-       }\r
-\r
-       NS_ADDREF( (nsOsmozillaPeer *)osmo->scriptable_peer);\r
-       *(nsISupports **) value = (nsISupports *) osmo->scriptable_peer;\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-NPError        NPOsmozilla_GetPeerIID(Osmozilla *osmo, void *value)\r
-{\r
-       static nsIID scriptableIID = NS_IOSMOZILLA_IID;\r
-       if (!sBrowserFunctions) return NPERR_OUT_OF_MEMORY_ERROR;\r
-\r
-       nsIID *ptr = (nsIID *) sBrowserFunctions->memalloc( sizeof(nsIID) );\r
-       if (! ptr) return NPERR_OUT_OF_MEMORY_ERROR;\r
-\r
-       *ptr = scriptableIID;\r
-       *(nsIID **) value = ptr;\r
-       return NPERR_NO_ERROR;\r
-}\r
-\r
-#else\r
-\r
-#define kOSMOZILLA_ID_METHOD_PLAY                      0\r
-#define kOSMOZILLA_ID_METHOD_PAUSE                             1\r
-#define kOSMOZILLA_ID_METHOD_STOP                              2\r
-#define kOSMOZILLA_ID_METHOD_UPDATE                            3\r
-\r
-#define kOSMOZILLA_NUM_METHODS                         4\r
-\r
-NPIdentifier    v_OSMOZILLA_MethodIdentifiers[kOSMOZILLA_NUM_METHODS];\r
-const NPUTF8 *  v_OSMOZILLA_MethodNames[kOSMOZILLA_NUM_METHODS] = {\r
-       "Play",\r
-       "Pause",\r
-       "Stop",\r
-       "Update"\r
-};\r
-\r
-NPClass osmozilla_script_class;\r
-\r
-typedef struct {\r
-       NPClass *_class;\r
-       uint32_t referenceCount;\r
-       Osmozilla *osmo;\r
-} OsmozillaObject;\r
-\r
-NPObject *OSMOZILLA_Allocate(NPP npp, NPClass *theClass)\r
-{\r
-       OsmozillaObject *obj = NULL;\r
-\r
-       sBrowserFunctions->getstringidentifiers(v_OSMOZILLA_MethodNames, kOSMOZILLA_NUM_METHODS, v_OSMOZILLA_MethodIdentifiers);\r
-       obj = (OsmozillaObject *)malloc(sizeof(OsmozillaObject));\r
-       obj->osmo = (Osmozilla *) npp->pdata;\r
-       return (NPObject *)obj;\r
-}\r
-\r
-void OSMOZILLA_Deallocate(NPObject* obj)\r
-{\r
-       free(obj);\r
-       return;\r
-}\r
-\r
-void OSMOZILLA_Invalidate(NPObject* obj)\r
-{\r
-       return;\r
-}\r
-\r
-bool OSMOZILLA_HasMethod(NPObject* obj, NPIdentifier name)\r
-{\r
-       int i = 0;\r
-       while (i < kOSMOZILLA_NUM_METHODS) {\r
-               if ( name == v_OSMOZILLA_MethodIdentifiers[i] ) {\r
-                       return 1;\r
-               }\r
-               i++;\r
-       }\r
-       return 0;\r
-}\r
-\r
-bool OSMOZILLA_Invoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)\r
-{\r
-       OsmozillaObject *npo = (OsmozillaObject *)obj;\r
-       if (!npo->osmo) return 0;\r
-       if (name == v_OSMOZILLA_MethodIdentifiers[kOSMOZILLA_ID_METHOD_PLAY]) {\r
-               Osmozilla_Play(npo->osmo);\r
-               return 1;\r
-       }\r
-       if (name == v_OSMOZILLA_MethodIdentifiers[kOSMOZILLA_ID_METHOD_PAUSE]) {\r
-               Osmozilla_Pause(npo->osmo);\r
-               return 1;\r
-       }\r
-       if (name == v_OSMOZILLA_MethodIdentifiers[kOSMOZILLA_ID_METHOD_STOP]) {\r
-               Osmozilla_Stop(npo->osmo);\r
-               return 1;\r
-       }\r
-       if (name == v_OSMOZILLA_MethodIdentifiers[kOSMOZILLA_ID_METHOD_UPDATE]) {\r
-               const char *mime = NULL;\r
-               const char *update = NULL;\r
-               if (argCount==2) {\r
-                       mime = (args[0].type==NPVariantType_String) ? args[0].value.stringValue.UTF8Characters : NULL; \r
-                       update = (args[1].type==NPVariantType_String) ? args[1].value.stringValue.UTF8Characters : NULL; \r
-               }\r
-               if (!update) return 0;\r
-               Osmozilla_Update(npo->osmo, mime, update);\r
-               return 1;\r
-       }\r
-       return 0;\r
-}\r
-\r
-bool OSMOZILLA_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)\r
-{\r
-       return 1;\r
-}\r
-\r
-bool OSMOZILLA_HasProperty(NPObject* obj, NPIdentifier name)\r
-{\r
-       bool result = 0;\r
-       /*nothing exposed yet*/\r
-       return result;\r
-}\r
-\r
-bool OSMOZILLA_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)\r
-{\r
-       return 1;\r
-}\r
-\r
-bool OSMOZILLA_SetProperty(NPObject *obj, NPIdentifier name, const NPVariant *value)\r
-{\r
-       return 1;\r
-}\r
-\r
-bool OSMOZILLA_RemoveProperty(NPObject *npobj, NPIdentifier name)\r
-{\r
-       return 1;\r
-}\r
-\r
-bool OSMOZILLA_Enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)\r
-{\r
-       return 1;\r
-}\r
-\r
-void Osmozilla_InitScripting(Osmozilla *osmo)\r
-{\r
-       osmozilla_script_class.allocate          = OSMOZILLA_Allocate;\r
-       osmozilla_script_class.deallocate        = OSMOZILLA_Deallocate;\r
-       osmozilla_script_class.invalidate        = OSMOZILLA_Invalidate;\r
-       osmozilla_script_class.hasMethod         = OSMOZILLA_HasMethod;\r
-       osmozilla_script_class.invoke            = OSMOZILLA_Invoke;\r
-       osmozilla_script_class.invokeDefault     = OSMOZILLA_InvokeDefault;\r
-       osmozilla_script_class.hasProperty       = OSMOZILLA_HasProperty;\r
-       osmozilla_script_class.getProperty       = OSMOZILLA_GetProperty;\r
-       osmozilla_script_class.setProperty       = OSMOZILLA_SetProperty;\r
-       osmozilla_script_class.removeProperty    = OSMOZILLA_RemoveProperty;\r
-       osmozilla_script_class.enumerate         = OSMOZILLA_Enumerate;\r
-\r
-       /*create script object*/\r
-       osmo->script_obj = sBrowserFunctions->createobject(osmo->np_instance, &osmozilla_script_class);\r
-\r
-}\r
-\r
-#endif //GECKO_XPCOM\r
-\r
diff --git a/applications/osmozilla/osmo_npapi.h b/applications/osmozilla/osmo_npapi.h
deleted file mode 100644 (file)
index cd2c3bf..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*\r
-*                      GPAC - Multimedia Framework C SDK\r
-*\r
-*                      Copyright (c) ENST 2000-200X\r
-*                                      All rights reserved\r
-*\r
-*  This file is part of GPAC / Osmozilla NPAPI plugin\r
-*\r
-*  GPAC is free software; you can redistribute it and/or modify\r
-*  it under the terms of the GNU Lesser General Public License as published by\r
-*  the Free Software Foundation; either version 2, or (at your option)\r
-*  any later version.\r
-*   \r
-*  GPAC is distributed in the hope that it will be useful,\r
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*  GNU Lesser General Public License for more details.\r
-*   \r
-*  You should have received a copy of the GNU Lesser General Public\r
-*  License along with this library; see the file COPYING.  If not, write to\r
-*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
-*\r
-*/\r
-\r
-#ifndef _OSMO_NPAPI_H_\r
-#define _OSMO_NPAPI_H_\r
-\r
-\r
-#ifdef WIN32\r
-#include <windows.h>\r
-#ifndef __cplusplus\r
-typedef BOOL bool;\r
-#endif //__cplusplus\r
-#endif\r
-\r
-#include "npapi.h"\r
-\r
-/*check this with gecko 1.9.2*/\r
-#if (NP_VERSION_MINOR < 20)\r
-#define GECKO_XPCOM\r
-#endif\r
-\r
-#ifdef GECKO_XPCOM\r
-#include "npupp.h"\r
-\r
-#ifndef uint16_t\r
-typedef uint16 uint16_t;\r
-#endif\r
-\r
-#ifndef int16_t\r
-typedef int16 int16_t;\r
-#endif\r
-\r
-#define NPINT32        int32\r
-\r
-#else\r
-\r
-#include "npfunctions.h"\r
-\r
-#define NPINT32        int32_t\r
-\r
-#endif\r
-\r
-#ifdef XP_UNIX\r
-#include <stdio.h>\r
-#endif //XP_UNIX\r
-\r
-\r
-#ifndef HIBYTE\r
-#define HIBYTE(i) (i >> 8)\r
-#endif\r
-\r
-#ifndef LOBYTE\r
-#define LOBYTE(i) (i & 0xff)\r
-#endif\r
-\r
-/*functions callbacks to browser*/\r
-NPError Osmozilla_GetURL(NPP instance, const char *url, const char *target);\r
-void Osmozilla_SetStatus(NPP instance, const char *message);\r
-\r
-\r
-/*\r
-Plugins functions exposed to browser\r
-*/\r
-NPError NPOsmozilla_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);\r
-NPError NPOsmozilla_Destroy(NPP instance, NPSavedData** save);\r
-NPError NPOsmozilla_SetWindow(NPP instance, NPWindow* window);\r
-NPError NPOsmozilla_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);\r
-NPError NPOsmozilla_DestroyStream(NPP instance, NPStream* stream, NPError reason);\r
-NPINT32 NPOsmozilla_WriteReady(NPP instance, NPStream* stream);\r
-NPINT32 NPOsmozilla_Write(NPP instance, NPStream* stream, NPINT32 offset, NPINT32 len, void* buffer);\r
-void    NPOsmozilla_StreamAsFile(NPP instance, NPStream* stream, const char* fname);\r
-void    NPOsmozilla_Print(NPP instance, NPPrint* platformPrint);\r
-int16_t NPOsmozilla_HandleEvent(NPP instance, void* event);\r
-void    NPOsmozilla_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData);\r
-NPError NPOsmozilla_GetValue(NPP instance, NPPVariable variable, void *result);\r
-NPError NPOsmozilla_SetValue(NPP instance, NPNVariable variable, void *value);\r
-\r
-\r
-/*\r
-Functions called by browser\r
-*/\r
-\r
-typedef struct __tag_osmozilla Osmozilla;\r
-\r
-/*base functions*/\r
-int Osmozilla_Initialize(Osmozilla *osmo, signed short argc, char* argn[], char* argv[]);\r
-void Osmozilla_Shutdown(Osmozilla *osmo);\r
-int Osmozilla_SetWindow(Osmozilla *osmozilla, void *os_wnd_handle, void *os_wnd_display, unsigned int width, unsigned int height);\r
-void Osmozilla_ConnectTo(Osmozilla *osmozilla, const char *url);\r
-void Osmozilla_Print(Osmozilla *osmozilla, unsigned int is_embed, void *os_print_dc, unsigned int target_x, unsigned int target_y, unsigned int target_width, unsigned int target_height);\r
-char *Osmozilla_GetVersion();\r
-\r
-\r
-/*scripting functions*/\r
-void Osmozilla_Play(Osmozilla *osmo);\r
-void Osmozilla_Pause(Osmozilla *osmo);\r
-void Osmozilla_Stop(Osmozilla *osmo);\r
-void Osmozilla_Update(Osmozilla *osmo, const char *type, const char *commands);\r
-\r
-\r
-\r
-#ifdef GECKO_XPCOM\r
-\r
-void NPOsmozilla_GetServiceManager();\r
-void NPOsmozilla_ReleaseServiceManager();\r
-void NPOsmozilla_ShutdownScript(Osmozilla *osmo);\r
-NPError        NPOsmozilla_GetPeer(Osmozilla *osmo, void *value);\r
-NPError        NPOsmozilla_GetPeerIID(Osmozilla *osmo, void *value);\r
-\r
-#endif //GECKO_XPCOM\r
-\r
-#endif //_NPPLAT_H_\r
diff --git a/applications/osmozilla/osmozilla.cpp b/applications/osmozilla/osmozilla.cpp
deleted file mode 100644 (file)
index 784fd6e..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
-*                      GPAC - Multimedia Framework C SDK
-*
-*                      Copyright (c) ENST 2000-200X
-*                                      All rights reserved
-*
-*  This file is part of GPAC / Osmozilla NPAPI plugin
-*
-*  GPAC is free software; you can redistribute it and/or modify
-*  it under the terms of the GNU Lesser General Public License as published by
-*  the Free Software Foundation; either version 2, or (at your option)
-*  any later version.
-*   
-*  GPAC 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 Lesser General Public License for more details.
-*   
-*  You should have received a copy of the GNU Lesser General Public
-*  License along with this library; see the file COPYING.  If not, write to
-*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
-*
-*/
-
-#include "osmozilla.h"
-
-#ifdef XP_WIN
-#include <windows.h>
-#endif
-
-#include <gpac/options.h>
-#include <gpac/terminal.h>
-#include <gpac/term_info.h>
-
-
-short Osmozilla_GetURL(NPP instance, const char *url, const char *target);
-void Osmozilla_SetStatus(NPP instance, const char *message);
-
-
-void Osmozilla_Shutdown(Osmozilla *osmo)
-{
-       if (osmo->url) gf_free(osmo->url);
-       osmo->url = NULL;
-       if (osmo->term) {
-               GF_Terminal *a_term = osmo->term;
-               osmo->term = NULL;
-               gf_term_del(a_term);
-       }
-       if (osmo->user->modules) gf_modules_del(osmo->user->modules);
-       if (osmo->user->config) gf_cfg_del(osmo->user->config);
-       gf_free(osmo->user);
-       osmo->user = NULL;
-}
-
-static void osmozilla_do_log(void *cbk, u32 level, u32 tool, const char *fmt, va_list list)
-{
-       FILE *logs = (FILE *) cbk;
-       vfprintf(logs, fmt, list);
-       fflush(logs);
-}
-
-
-Bool Osmozilla_EventProc(void *opaque, GF_Event *evt)
-{
-       char msg[1024];
-       Osmozilla *osmo = (Osmozilla *)opaque;
-       if (!osmo->term) return 0;
-
-       switch (evt->type) {
-       case GF_EVENT_MESSAGE:
-               if (!evt->message.message) return 0;
-               if (evt->message.error)
-                       sprintf((char *)msg, "GPAC: %s (%s)", evt->message.message, gf_error_to_string(evt->message.error));
-               else
-                       sprintf((char *)msg, "GPAC: %s", evt->message.message);
-
-               Osmozilla_SetStatus(osmo->np_instance, msg);
-               break;
-       case GF_EVENT_PROGRESS:
-               if (evt->progress.done == evt->progress.total) {
-                       Osmozilla_SetStatus(osmo->np_instance, "");
-               } else {
-                       char *szTitle = (char *)"";
-                       if (evt->progress.progress_type==0) szTitle = (char *)"Buffer ";
-                       else if (evt->progress.progress_type==1) szTitle = (char *)"Download ";
-                       else if (evt->progress.progress_type==2) szTitle = (char *)"Import ";
-                       sprintf(msg, "(GPAC) %s: %02.2f", szTitle, (100.0*evt->progress.done) / evt->progress.total);
-                       Osmozilla_SetStatus(osmo->np_instance, msg);
-               }
-               break;
-
-               /*IGNORE any scene size, just work with the size allocated in the parent doc*/
-       case GF_EVENT_SCENE_SIZE:       
-               gf_term_set_size(osmo->term, osmo->width, osmo->height);
-               break;
-               /*window has been resized (full-screen plugin), resize*/
-       case GF_EVENT_SIZE:     
-               osmo->width = evt->size.width;
-               osmo->height = evt->size.height;
-               gf_term_set_size(osmo->term, osmo->width, osmo->height);
-               break;
-       case GF_EVENT_CONNECT:  
-               osmo->is_connected = evt->connect.is_connected;
-               break;
-       case GF_EVENT_DURATION: 
-               osmo->can_seek = evt->duration.can_seek;
-               osmo->duration = evt->duration.duration;
-               break;
-       case GF_EVENT_DBLCLICK:
-               gf_term_set_option(osmo->term, GF_OPT_FULLSCREEN, !gf_term_get_option(osmo->term, GF_OPT_FULLSCREEN));
-               break;
-       case GF_EVENT_NAVIGATE_INFO:
-               strcpy(msg, evt->navigate.to_url);
-               Osmozilla_SetStatus(osmo->np_instance, msg);
-               break;
-       case GF_EVENT_NAVIGATE:
-               if (gf_term_is_supported_url(osmo->term, evt->navigate.to_url, 1, osmo->disable_mime)) {
-                       gf_term_navigate_to(osmo->term, evt->navigate.to_url);
-                       return 1;
-               } else {
-                       u32 i;
-                       char *target = (char *)"_self";
-
-                       for (i=0; i<evt->navigate.param_count; i++) {
-                               if (!strcmp(evt->navigate.parameters[i], "_parent")) target = (char *)"_parent";
-                               else if (!strcmp(evt->navigate.parameters[i], "_blank")) target = (char *)"_blank";
-                               else if (!strcmp(evt->navigate.parameters[i], "_top")) target = (char *)"_top";
-                               else if (!strcmp(evt->navigate.parameters[i], "_new")) target = (char *)"_new";
-                               else if (!strnicmp(evt->navigate.parameters[i], "_target=", 8)) target = (char *) evt->navigate.parameters[i]+8;
-                       }
-                       Osmozilla_GetURL(osmo->np_instance, evt->navigate.to_url, target);
-                       return 1;
-               }
-               break;
-       }
-       return 0;
-}
-
-int Osmozilla_Initialize(Osmozilla *osmo, signed short argc, char* argn[], char* argv[])
-{
-       const char *str;
-       int i;
-       u32 log_level, log_tools;
-
-       osmo->auto_start = 1;
-
-       /*options sent from plugin*/
-       for(i=0;i<argc;i++) {   
-               if (!argn[i] || !argv[i]) continue;
-               if (!stricmp(argn[i],"autostart") && (!stricmp(argv[i], "false") || !stricmp(argv[i], "no")) ) 
-                       osmo->auto_start = 0;
-
-               else if (!stricmp(argn[i],"src") ) {
-                       if (osmo->url) gf_free(osmo->url);
-                       osmo->url = gf_strdup(argv[i]);
-               }
-               else if (!stricmp(argn[i],"use3d") && (!stricmp(argv[i], "true") || !stricmp(argv[i], "yes") ) ) {
-                       osmo->use_3d = 1;
-               }
-               else if (!stricmp(argn[i],"loop") && (!stricmp(argv[i], "true") || !stricmp(argv[i], "yes") ) ) {
-                       osmo->loop = 1;
-               }
-               else if (!stricmp(argn[i],"aspectratio")) {
-                       osmo->aspect_ratio = GF_ASPECT_RATIO_KEEP;
-                       if (!stricmp(argv[i], "keep")) osmo->aspect_ratio = GF_ASPECT_RATIO_KEEP;
-                       else if (!stricmp(argv[i], "16:9")) osmo->aspect_ratio = GF_ASPECT_RATIO_16_9;
-                       else if (!stricmp(argv[i], "4:3")) osmo->aspect_ratio = GF_ASPECT_RATIO_4_3;
-                       else if (!stricmp(argv[i], "fill")) osmo->aspect_ratio = GF_ASPECT_RATIO_FILL_SCREEN;
-               }
-       }
-
-       /*URL is not absolute, request new stream to mozilla - we don't pass absolute URLs since some may not be 
-       handled by gecko */
-       if (osmo->url) {
-               Bool absolute_url = 0;
-               if (strstr(osmo->url, "://")) absolute_url = 1;
-               else if (osmo->url[0] == '/') {
-                       FILE *test = gf_f64_open(osmo->url, "rb");
-                       if (test) {     
-                               absolute_url = 1;
-                               fclose(test);
-                       }
-               }
-               else if ((osmo->url[1] == ':') && ((osmo->url[2] == '\\') || (osmo->url[2] == '/'))) absolute_url = 1;
-
-               if (!absolute_url) {
-                       char *url = osmo->url;
-                       osmo->url = NULL;
-                       Osmozilla_GetURL(osmo->np_instance, url, NULL);
-                       gf_free(url);
-               }
-       }
-
-       GF_SAFEALLOC(osmo->user, GF_User);
-       osmo->user->config = gf_cfg_init(NULL, NULL);
-       /*need to have a valid cfg file for now*/
-       if (!osmo->user->config) {
-               gf_free(osmo->user);
-               osmo->user = NULL;
-#ifdef WIN32
-               MessageBox(NULL, "GPAC CONFIGURATION FILE NOT FOUND OR INVALID", "OSMOZILLA FATAL ERROR", MB_OK);
-#else
-               fprintf(stdout, "OSMOZILLA FATAL ERROR\nGPAC CONFIGURATION FILE NOT FOUND OR INVALID\n");
-#endif
-               return 0;
-       }
-
-       str = gf_cfg_get_key(osmo->user->config, "General", "ModulesDirectory");
-       osmo->user->modules = gf_modules_new(str, osmo->user->config);
-       if (!gf_modules_get_count(osmo->user->modules)) {
-               if (osmo->user->modules) gf_modules_del(osmo->user->modules);
-               gf_free(osmo->user);
-               osmo->user = NULL;
-#ifdef WIN32
-               MessageBox(NULL, "GPAC MODULES NOT FOUND", "OSMOZILLA FATAL ERROR", MB_OK);
-#else
-               fprintf(stdout, "OSMOZILLA FATAL ERROR\nGPAC MODULES NOT FOUND\n");
-#endif
-               return 0;
-       }
-
-       osmo->user->opaque = osmo;
-       osmo->user->EventProc = Osmozilla_EventProc;
-
-       /*always fetch mime ? Check with anchor examples*/
-       osmo->disable_mime = 0;
-       str = gf_cfg_get_key(osmo->user->config, "General", "NoMIMETypeFetch");
-       if (str && !strcmp(str, "yes")) osmo->disable_mime = 0;
-       /*check log file*/
-       str = gf_cfg_get_key(osmo->user->config, "General", "LogFile");
-       if (str) {
-               osmo->logs = gf_f64_open(str, "wt");
-               if (osmo->logs) gf_log_set_callback(osmo->logs, osmozilla_do_log);
-       }
-
-       /*setup logs*/
-       log_level = gf_log_parse_level(gf_cfg_get_key(osmo->user->config, "General", "LogLevel"));
-       if (!log_level)
-               fprintf(stdout, "Osmozilla: invalid log level specified\n");
-       gf_log_set_level(log_level);
-       log_tools = gf_log_parse_tools(gf_cfg_get_key(osmo->user->config, "General", "LogTools"));
-       if (!log_tools)
-               fprintf(stdout, "Osmozilla: invalid log tools specified\n");
-       gf_log_set_tools(log_tools);
-
-       fprintf(stdout, "Osmozilla initialized\n");
-
-       return 1;
-}
-
-int Osmozilla_SetWindow(Osmozilla *osmo, void *os_wnd_handle, void *os_wnd_display, unsigned int width, unsigned int height)
-{
-       const char *gui;
-       if (osmo->window_set) {
-               osmo->width = width;
-               osmo->height = height;
-               if (osmo->is_connected) gf_term_set_size(osmo->term, osmo->width, osmo->height);
-               return 1;
-       }
-       if (!os_wnd_handle) return 0;
-
-       osmo->width = width;
-       osmo->height = height;
-
-       osmo->user->os_window_handler = os_wnd_handle;
-       osmo->user->os_display = os_wnd_display;
-
-       /*Everything is now setup, create the terminal*/
-       fprintf(stdout, "Creating Osmozilla terminal\n");
-       osmo->term = gf_term_new(osmo->user);
-       if (!osmo->term) return 0;
-       fprintf(stdout, "Osmozilla terminal created\n");
-
-       gf_term_set_option(osmo->term, GF_OPT_ASPECT_RATIO, osmo->aspect_ratio);
-       osmo->window_set = 1;
-
-#ifdef XP_WIN
-       SetFocus((HWND)os_wnd_handle);
-#endif
-
-       /*stream not ready*/
-       if (!osmo->url || !osmo->auto_start) {
-               fprintf(stdout, "Osmozilla ready - not connecting to %s yet\n", osmo->url);
-               return 1;
-       }
-
-       /*connect from 0 and pause if not autoplay*/
-       gui = gf_cfg_get_key(osmo->user->config, "General", "StartupFile");
-       if (gui) {
-               gf_cfg_set_key(osmo->user->config, "Temp", "BrowserMode", "yes");
-               gf_cfg_set_key(osmo->user->config, "Temp", "GUIStartupFile", osmo->url);
-               gf_term_connect(osmo->term, gui);
-       } else {
-               gf_term_connect(osmo->term, osmo->url);
-       }
-       fprintf(stdout, "Osmozilla connected to %s\n", osmo->url);
-       return 1;
-}
-
-char *Osmozilla_GetVersion()
-{
-       return (char *) "GPAC Plugin " GPAC_FULL_VERSION " for NPAPI compatible Web Browsers. For more information go to <a href=\"http://gpac.sourceforge.net\">GPAC website</a>";
-}
-
-void Osmozilla_ConnectTo(Osmozilla *osmo, const char *url)
-{
-       fprintf(stdout, "Osmozilla connecting to %s\n", url);
-       if (osmo->url) gf_free(osmo->url);      
-       osmo->url = gf_strdup(url);
-
-       /*connect from 0 and pause if not autoplay*/
-       if (osmo->auto_start) {
-               const char *gui = gf_cfg_get_key(osmo->user->config, "General", "StartupFile");
-               if (gui) {
-                       gf_cfg_set_key(osmo->user->config, "Temp", "BrowserMode", "yes");
-                       gf_cfg_set_key(osmo->user->config, "Temp", "GUIStartupFile", url);
-                       gf_term_connect(osmo->term, gui);
-               } else {
-                       gf_term_connect(osmo->term, url);
-               }
-       }
-       fprintf(stdout, "Osmozilla connected to %s\n", url);
-}
-
-void Osmozilla_Pause(Osmozilla *osmo)
-{
-       if (osmo->term) {
-               if (gf_term_get_option(osmo->term, GF_OPT_PLAY_STATE) == GF_STATE_PAUSED) {
-                       gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
-               } else {
-                       gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED);
-               }
-       }
-}
-
-void Osmozilla_Play(Osmozilla *osmo)
-{
-       if (!osmo->is_connected) {
-               if (osmo->url) gf_term_connect(osmo->term, (const char *) osmo->url);
-       } else {
-               gf_term_set_option(osmo->term, GF_OPT_PLAY_STATE, GF_STATE_PLAYING);
-       }
-}
-
-void Osmozilla_Stop(Osmozilla *osmo)
-{
-       if (osmo->term) gf_term_disconnect(osmo->term);
-}
-
-#ifdef XP_WIN
-PBITMAPINFO CreateBitmapInfoStruct(GF_VideoSurface *pfb)
-{ 
-       PBITMAPINFO pbmi; 
-       WORD    cClrBits; 
-
-       cClrBits = 32;
-
-       pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
-               sizeof(BITMAPINFOHEADER)); 
-
-       pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
-       pbmi->bmiHeader.biWidth = pfb->width;
-       pbmi->bmiHeader.biHeight = 1;
-       pbmi->bmiHeader.biPlanes = 1; 
-       pbmi->bmiHeader.biBitCount = cClrBits; 
-
-       pbmi->bmiHeader.biCompression = BI_RGB; 
-       pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
-               * pbmi->bmiHeader.biHeight; 
-       pbmi->bmiHeader.biClrImportant = 0; 
-       return pbmi; 
-}
-#endif
-
-void Osmozilla_Print(Osmozilla *osmo, unsigned int is_embed, void *os_print_dc, unsigned int target_x, unsigned int target_y, unsigned int target_width, unsigned int target_height)
-{
-       if (is_embed) {
-#ifdef XP_MACOS
-               /*
-               os_print_dc contains a THPrint reference on MacOS
-               */
-       }
-#endif  // XP_MACOS
-#ifdef XP_UNIX
-       /*
-       os_print_dc contains a NPPrintCallbackStruct on Unix and
-       the plug-in location and size in the NPWindow are in page coordinates (720/ inch), but the printer requires point coordinates (72/inch)
-       */
-#endif  // XP_UNIX
-#ifdef XP_WIN
-       /*
-       The coordinates for the window rectangle are in TWIPS format. 
-       This means that you need to convert the x-y coordinates using the Windows API call DPtoLP when you output text
-       */
-       GF_VideoSurface fb;
-       u32 xsrc, ysrc;
-       u16 src_16;
-       char *src;
-       float deltay;
-       int     ysuiv = 0;
-       char *ligne;
-       BITMAPINFO      *infoSrc;
-       HDC pDC = (HDC)os_print_dc;
-       /*lock the source buffer */
-       gf_term_get_screen_buffer(osmo->term, &fb);
-       infoSrc = CreateBitmapInfoStruct(&fb);
-       deltay = (float)target_height/(float)fb.height;
-       ligne = (char *) LocalAlloc(GMEM_FIXED, fb.width*4);
-       for (ysrc=0; ysrc<fb.height; ysrc++) {
-               int ycrt, delta;
-               char *dst = (char*)ligne;
-               src = fb.video_buffer + ysrc * fb.pitch_y;
-               for (xsrc=0; xsrc<fb.width; xsrc++)
-               {
-                       switch (fb.pixel_format) {
-                               case GF_PIXEL_RGB_32:
-                               case GF_PIXEL_ARGB:
-                                       dst[0] = src[0];
-                                       dst[1] = src[1];
-                                       dst[2] = src[2];
-                                       src+=4;
-                                       break;
-                               case GF_PIXEL_BGR_32:
-                               case GF_PIXEL_RGBA:
-                                       dst[0] = src[3];
-                                       dst[1] = src[2];
-                                       dst[2] = src[1];
-                                       src+=4;
-                                       break;
-                               case GF_PIXEL_RGB_24:
-                                       dst[0] = src[2];
-                                       dst[1] = src[1];
-                                       dst[2] = src[0];
-                                       src+=3;
-                                       break;
-                               case GF_PIXEL_BGR_24:
-                                       dst[0] = src[2];
-                                       dst[1] = src[1];
-                                       dst[2] = src[0];
-                                       src+=3;
-                                       break;
-                               case GF_PIXEL_RGB_565:
-                                       src_16 = * ( (u16 *)src );
-                                       dst[2] = (src_16 >> 8) & 0xf8;
-                                       dst[2] += dst[2]>>5;
-                                       dst[1] = (src_16 >> 3) & 0xfc;
-                                       dst[1] += dst[1]>>6;
-                                       dst[0] = (src_16 << 3) & 0xf8;
-                                       dst[0] += dst[0]>>5;
-                                       src+=2;
-                                       break;
-                               case GF_PIXEL_RGB_555:
-                                       src_16 = * (u16 *)src;
-                                       dst[2] = (src_16 >> 7) & 0xf8;
-                                       dst[2] += dst[2]>>5;
-                                       dst[1] = (src_16 >> 2) & 0xf8;
-                                       dst[1] += dst[1]>>5;
-                                       dst[0] = (src_16 << 3) & 0xf8;
-                                       dst[0] += dst[0]>>5;
-                                       src+=2;
-                                       break;
-                       }
-                       dst += 4;
-               }
-               ycrt = ysuiv;
-               ysuiv = (u32) ( ((float)ysrc+1.0)*deltay);
-               delta = ysuiv-ycrt;
-               StretchDIBits(
-                       pDC, target_x, target_y, target_width, 
-                       delta, 
-                       0, 0, fb.width, 1,
-                       ligne, infoSrc, DIB_RGB_COLORS, SRCCOPY);
-       }
-
-       /*unlock GPAC frame buffer */
-       gf_term_release_screen_buffer(osmo->term, &fb);
-       /* gf_free temporary  objects */
-       GlobalFree(ligne);
-       LocalFree(infoSrc);
-#endif   // XP_WIN
-
-       return;
-} 
-
-/*TODO - this is full print, present the print dialog and manage the print*/
-}
-
-void Osmozilla_Update(Osmozilla *osmo, const char *type, const char *commands)
-{
-       if (osmo->term) {
-               GF_Err e = gf_term_scene_update(osmo->term, (char *) type, (char *) commands);
-               if (e) {
-                       char szMsg[1024];
-                       sprintf((char *)szMsg, "GPAC: Error applying update (%s)", gf_error_to_string(e) );
-                       Osmozilla_SetStatus(osmo->np_instance, szMsg);
-               }
-       }
-}
-
diff --git a/applications/osmozilla/osmozilla.def b/applications/osmozilla/osmozilla.def
deleted file mode 100644 (file)
index 5d5bbb1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-LIBRARY   nposmozilla
-
-EXPORTS
-       NP_GetEntryPoints   @1
-       NP_Initialize       @2
-       NP_Shutdown         @3
diff --git a/applications/osmozilla/osmozilla.h b/applications/osmozilla/osmozilla.h
deleted file mode 100644 (file)
index 5929d97..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-*                      GPAC - Multimedia Framework C SDK
-*
-*                      Copyright (c) ENST 2000-200X
-*                                      All rights reserved
-*
-*  This file is part of GPAC / Osmozilla NPAPI plugin
-*
-*  GPAC is free software; you can redistribute it and/or modify
-*  it under the terms of the GNU Lesser General Public License as published by
-*  the Free Software Foundation; either version 2, or (at your option)
-*  any later version.
-*   
-*  GPAC 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 Lesser General Public License for more details.
-*   
-*  You should have received a copy of the GNU Lesser General Public
-*  License along with this library; see the file COPYING.  If not, write to
-*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
-*
-*/
-
-#ifndef __OSMOZILLA_H__
-#define __OSMOZILLA_H__
-
-
-/*DO NOT INCLUDE ANY GPAC FILE IN THIS HEADER, IT CAUSES TYPE REDEFINITION CONFLICT ON OSX*/
-typedef struct _tag_terminal GF_Terminal;
-typedef struct _tag_user GF_User;
-
-#include <stdio.h>
-
-
-typedef struct _NPP *NPP;
-
-typedef struct __tag_osmozilla
-{
-       /*plugiun & window info*/
-       NPP np_instance;
-       int window_set;
-       unsigned int height, width;
-
-       /*GPAC term*/
-       GF_User *user;
-       GF_Terminal *term;
-
-       /*general options*/
-       char loop, auto_start, is_connected, use_3d, disable_mime;
-       unsigned int aspect_ratio;
-
-       /*the URL we are connected to*/
-       char *url;
-       /*timing info of current url*/
-       double duration;
-       char can_seek;
-
-       /*log file if any*/
-       FILE *logs;
-
-#ifdef GECKO_XPCOM
-       void *scriptable_peer;
-#else
-       struct NPObject *script_obj;
-#endif
-
-} Osmozilla;
-
-
-#endif // __OSMOZILLA_H__
diff --git a/applications/osmozilla/osmozilla.png b/applications/osmozilla/osmozilla.png
deleted file mode 100644 (file)
index 6f66a17..0000000
Binary files a/applications/osmozilla/osmozilla.png and /dev/null differ
diff --git a/applications/osmozilla/osmozilla.rc b/applications/osmozilla/osmozilla.rc
deleted file mode 100644 (file)
index 9fc460b..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winresrc.h"
-
-/*do not include setup.h*/
-#define _GF_SETUP_H_
-#include <gpac/tools.h>
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Neutral resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
-#ifdef _WIN32
-LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,1,0
- PRODUCTVERSION 1,0,1,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904e4"
-        BEGIN
-            VALUE "Comments", "\0"
-            VALUE "CompanyName", " \0"
-            VALUE "FileDescription", "Osmozilla allows playback of many media and rich media files. For more information, visit <a href=""http://gpac.sourceforge.net"">gpac.sourceforge.net</a>\0"
-            VALUE "FileExtents", "*|aac|wrl,wrl.gz|x3dv,x3dv.gz,x3dvz|x3d,x3d.gz,x3dz|svg,svg.gz,svgz|mpg,mpeg,mp2,mpa,mpe,mpv2|asf,wma,wmv,asx,asr|avi|mp4,mpg4|mp4|m4a|3gp,3gpp|3gp,3gpp|3g2,3gp2|3g2,3gp2|mp2,mp3,mpga,mpega|ogg|sdp\0"
-            VALUE "FileOpenName", "GPAC Plugin|AAC Music|VRML World|X3D/VRML World|X3D/XML World|SVG Document|MPEG Video|WindowsMedia Movies|AVI Movies|MPEG-4 Videos|MPEG-4 Movies|MPEG-4 Music|3GPP Movies|3GPP Music|3GPP2 Movies|3GPP2 Music|MP3 Music|OGG Movies|SDP Session\0"
-            VALUE "FileVersion", GPAC_VERSION"-rev"GPAC_SVN_REVISION"\0"
-            VALUE "InternalName", "nposmozilla\0"
-            VALUE "LegalCopyright", "Copyright Â© GPAC 2005-2007\0"
-            VALUE "LegalTrademarks", "\0"
-            VALUE "MIMEType", "application/x-gpac|audio/aac|model/vrml|model/x3d+vrml|model/x3d+xml|image/svg+xml|video/mpeg|video/x-ms-asf|video/avi|video/mp4|application/mp4|audio/mp4|video/3gpp|audio/3gpp|video/3gpp2|audio/3gpp2|audio/mpeg|application/ogg|application/sdp\0"
-            VALUE "OriginalFilename", "nposmozilla.dll\0"
-            VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Osmozilla - GPAC Plugin for Mozilla\0"
-            VALUE "ProductVersion", GPAC_VERSION"-rev"GPAC_SVN_REVISION"\0"
-            VALUE "SpecialBuild", "\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1252
-    END
-END
-
-#endif    // !_MAC
-
-#endif    // Neutral resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""winresrc.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/applications/osmozilla/readme.txt b/applications/osmozilla/readme.txt
deleted file mode 100644 (file)
index 7a61b5c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-to regenerate plugin interface from IDL:
-
-xpidl -m header -I path_to\gecko-sdk\xpcom\idl nsIOsmozilla.idl
-xpidl -m typelib -I path_to\gecko-sdk\xpcom\idl nsIOsmozilla.idl
-xpt_link nposmozilla.xpt nsIOsmozilla.xpt 
-
-This MUST be done for win32 and linux OSs independently, an .xpt file generated on one OS is not compatible with another OS...
-Please keep the w32 file "nsIOsmozilla.xpt_w32" and the linux one "nsIOsmozilla.xpt_linux" to bear with makefiles...
\ No newline at end of file
diff --git a/applications/osmozilla/resource.h b/applications/osmozilla/resource.h
deleted file mode 100644 (file)
index 8d3b519..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by osmozilla.rc
-//
-#define IDD_MAIN                        101
-#define IDC_BUTTON_GO                   1002
-#define IDC_STATIC_UA                   1003
-#define IDC_BUTTON1                     1005
-#define IDC_BUTTON_DONT                 1005
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NO_MFC                     1
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1006
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
index 42d847b9ac5549ed0bdd789dd547ababe7baa588..2bc1e0ee8e0887838eb77838101f866900f22523 100644 (file)
@@ -21,13 +21,12 @@ endif
 #common obj
 OBJS=RTP_serv_generator.o RTP_serv_packetizer.o RTP_serv_sender.o broadcaster.o sdp_generator.o debug.o
 
-LDFLAGS += -L../../../bin/gcc
-LIBS=-lgpac
+LINKFLAGS=-L../../../bin/gcc -lgpac
 
 all: broadcaster
 
 broadcaster: $(OBJS) *.h
-       $(CC) -o $(APPNAME) $(OBJS) $(LIBS) $(LDFLAGS) 
+       $(CC) $(LDFLAGS) -o $(APPNAME) $(OBJS) $(LINKFLAG)
 
 .c.o:
        $(CC) -Wall -g -c $(CFLAGS) $*.c
index 3b8349caa1c47d533b664d2d4dc485baf3ad562d..e3a00f0f834f939d32b5284678c969cc2b725dd7 100644 (file)
@@ -213,7 +213,7 @@ u32 tcp_server(void *par)
                                fprintf(stderr, "Error opening temp file for the configuration\n");
                                exit(1);
                        }
-                       ret = fwrite(buffer, 1, byte_read, fp);
+                       ret = gf_fwrite(buffer, 1, byte_read, fp);
                        fclose(fp);
                        
                        /* parsing config info */
@@ -240,7 +240,7 @@ u32 tcp_server(void *par)
                                GF_Err e = gf_sk_receive(conn_socket, temp, sizeof(temp), 0, &byte_read);
 
                                if (e == GF_OK) {
-                                       fwrite(temp, 1, byte_read, fp);
+                                       gf_fwrite(temp, 1, byte_read, fp);
                                } else if (e==GF_IP_NETWORK_EMPTY) {
                                        num_retry--;
                                        if (!num_retry)
@@ -309,8 +309,6 @@ int main (const int argc, const char** argv)
        
        /* init gpac lib */
        gf_sys_init();
-       gf_log_set_level(GF_LOG_ERROR);
-       gf_log_set_tools(GF_LOG_NETWORK|GF_LOG_RTP|GF_LOG_SCENE|GF_LOG_PARSER|GF_LOG_AUTHOR|GF_LOG_CODING|GF_LOG_SCRIPT);
        
        GF_SAFEALLOC(conf, CONF_Data);
                
index 0cd7f8904c725fde58010c1861792c094d34dbcb..02a1b6bf56ae6fcc83921b008e54c4dcbe8b3714 100644 (file)
@@ -22,16 +22,16 @@ int sdp_generator(PNC_CallbackData *data, char *ip_dest, char *sdp_fmt)
                exit(1);
        }
 
-       ret = fwrite("v=0\n", 1, 4, fp);
+       ret = gf_fwrite("v=0\n", 1, 4, fp);
        sprintf(temp, "o=GpacBroadcaster 3326096807 1117107880000 IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest);
-       ret = fwrite(temp, 1, strlen(temp), fp);
+       ret = gf_fwrite(temp, 1, strlen(temp), fp);
 
-       ret = fwrite("s=MPEG4Broadcaster\n", 1, 19, fp);
+       ret = gf_fwrite("s=MPEG4Broadcaster\n", 1, 19, fp);
        
        sprintf(temp, "c=IN IP%d %s\n", gf_net_is_ipv6(ip_dest) ? 6 : 4, ip_dest);
-       ret = fwrite(temp, 1, strlen(temp), fp);
+       ret = gf_fwrite(temp, 1, strlen(temp), fp);
        
-       ret = fwrite("t=0 0\n", 1, 6, fp);
+       ret = gf_fwrite("t=0 0\n", 1, 6, fp);
        
        codec = (GF_SceneEngine *) data->codec;
        if (codec) {
@@ -45,21 +45,21 @@ int sdp_generator(PNC_CallbackData *data, char *ip_dest, char *sdp_fmt)
                free(buffer);
 
                sprintf(temp, "a=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\n", buf64);
-               ret = fwrite(temp, 1, strlen(temp), fp);
+               ret = gf_fwrite(temp, 1, strlen(temp), fp);
        }
        
        sprintf(temp, "m=application %d RTP/AVP 96\n", port);
-       ret = fwrite(temp, 1, strlen(temp), fp);
+       ret = gf_fwrite(temp, 1, strlen(temp), fp);
        
-       ret = fwrite("a=rtpmap:96 mpeg4-generic/1000\n", 1, 31, fp);
+       ret = gf_fwrite("a=rtpmap:96 mpeg4-generic/1000\n", 1, 31, fp);
 
        if (esd) {
                sprintf(temp, "a=mpeg4-esid:%d\n", esd->ESID);
-               ret = fwrite(temp, 1, strlen(temp), fp);
+               ret = gf_fwrite(temp, 1, strlen(temp), fp);
        }
        
        sprintf(temp, "%s\n", sdp_fmt);
-       ret = fwrite(temp, 1, strlen(temp), fp);
+       ret = gf_fwrite(temp, 1, strlen(temp), fp);
        fflush(fp);
        fclose(fp);
        dprintf(DEBUG_sdp_generator, "SDP file generated in broadcaster.sdp\n");
index 0755e4e1507ef66e46e742cab843ec5f6927bfa0..7650492bc712b80f0140b5382c753a0490d149f0 100644 (file)
 void save_ts(char *filename, unsigned char *data)
 {
        FILE *ts_out = fopen(filename,"a+b");
-       fwrite(data, 1, 188, ts_out);
+       gf_fwrite(data, 1, 188, ts_out);
        fclose(ts_out);
 }
 void save_rs_0(char *filename, unsigned char *data)
 {
        FILE *rs_out = fopen(filename,"a+b");
-       fwrite(data, 1, 204, rs_out);
+       gf_fwrite(data, 1, 204, rs_out);
        fclose(rs_out);
 }
 
@@ -219,7 +219,7 @@ void main(int argc, char **argv)
                        for (j = 1; j <188; j++) {
                                buffer[j] = rand();//j; 
                        }
-                       fwrite(buffer, 1, 188, in);
+                       gf_fwrite(buffer, 1, 188, in);
                }       
        }
        fclose(in);     
index f176754ed74a64558c099a42cd086593c7de2b45..c6bc6923f7502d9314c77792e1793fa9306143ea 100644 (file)
@@ -81,9 +81,6 @@ int main(int argc, char **argv)
                return GF_OK;
        }
 
-       gf_log_set_level(GF_LOG_ERROR);
-       gf_log_set_tools(GF_LOG_CONTAINER);
-
        GF_SAFEALLOC(mpedemux, MPEDemux);
        mpedemux->ts_demux = gf_m2ts_demux_new();
        mpedemux->ts_demux->on_event = mpedemux_on_event;
index ae79bfc786b7d1ccdb0f336e10e6ac6c4c8cc5c5..3e948a5fd63f51ee2427ad5b0a5f4855bdbb9c72 100644 (file)
@@ -32,7 +32,7 @@ void on_m2ts_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
        case GF_M2TS_EVT_PES_PCK:
                pck = par;
                if (dest && (dump_pid == pck->stream->pid)) {
-                       fwrite(pck->data, pck->data_len, 1, dest);
+                       gf_fwrite(pck->data, pck->data_len, 1, dest);
                }
 
                //fprintf(stdout, "PES(%d): DTS "LLD" PTS" LLD" RAP %d size %d\n", pck->stream->pid, pck->DTS, pck->PTS, pck->rap, pck->data_len);
index 33ede4f4d103db3aa9266eb1a002cb6d7fde8a6f..b372b65e3f7194160006053eacf8e59867cc8ed2 100644 (file)
@@ -131,8 +131,6 @@ int main(int argc, char **argv)
        /*   gpac init   */
        /*****************/
        gf_sys_init(0);
-       gf_log_set_level(GF_LOG_ERROR);
-       gf_log_set_tools(0xFFFFFFFF);
 
        /*****************/
        /*   parsing of the arguments */
@@ -256,7 +254,7 @@ int main(int argc, char **argv)
                        if (ts_output_file != NULL) {
                                u32 now = gf_sys_clock();
                                if (towrite) {
-                                       fwrite(input_buffer, 1, towrite, ts_output_file); 
+                                       gf_fwrite(input_buffer, 1, towrite, ts_output_file); 
                                        if (towrite < leftinbuffer) {
                                                fprintf(stderr, "Warning: wrote %d bytes, keeping %d bytes\n", towrite, (leftinbuffer-towrite));
                                                memmove(input_buffer, input_buffer+towrite, leftinbuffer-towrite);
diff --git a/bin/w32_rel/Osmo4.ico b/bin/w32_rel/Osmo4.ico
deleted file mode 100644 (file)
index 36ff667..0000000
Binary files a/bin/w32_rel/Osmo4.ico and /dev/null differ
diff --git a/bin/w32_rel/nsis_install/gpac_installer.nsi b/bin/w32_rel/nsis_install/gpac_installer.nsi
deleted file mode 100644 (file)
index 961e0c1..0000000
+++ /dev/null
@@ -1,738 +0,0 @@
-BGGradient 
-
-XPStyle on
-WindowIcon on
-Icon "..\..\..\..\doc\osmo4.ico"
-UninstallIcon "..\..\..\..\doc\osmo4.ico"
-
-!define GPAC_VERSION   0.4.6
-!define /date RELDATE "%Y%m%d_%H%M"
-
-!define GPAC_ROOT ..\..\..\..
-
-Name "GPAC Framework ${GPAC_VERSION}"
-OutFile "GPAC.Framework.Setup-${RELDATE}.exe"
-
-
-InstallDir "$PROGRAMFILES\GPAC"
-InstallDirRegKey HKCU "SOFTWARE\GPAC" "InstallDir"
-
-
-LicenseText "GPAC Licence"
-LicenseData "${GPAC_ROOT}\COPYING"
-
-DirText "This will install the GPAC Framework on your computer. Choose a directory"
-
-InstType Normal
-
-
-ComponentText "This will install the GPAC Framework on your computer. Select which optional things you want installed."
-
-
-Function FctWriteRegStrAuth
-   ;local var
-   Push $0
-   Push $R0
-   Push $R1
-   Push $R2
-   Push $R3
-   ;pop function arguments
-   Exch 5
-   Pop $R3
-   Exch 5
-   Pop $R2
-   Exch 5
-   Pop $R1
-   Exch 5
-   Pop $R0
-
-   ;test if calling HKCR
-   StrCmp $R0 "HKCR" +1 +3
-   WriteRegStr HKCR $R1 $R2 $R3
-   goto lbl_end
-   
-   #has current user admin privileges?
-   userInfo::getAccountType
-   Pop $0
-   StrCmp $0 "Admin" lbl_admin lbl_not_admin
-
-   lbl_admin:
-      WriteRegStr HKLM $R1 $R2 $R3
-      goto lbl_end
-
-   lbl_not_admin:
-      WriteRegStr HKCU $R1 $R2 $R3
-
-   lbl_end:
-      Pop $R3
-      Pop $R2
-      Pop $R1
-      Pop $R0
-      Pop $0
-FunctionEnd
-
-!macro WriteRegStrAuth HKREG SUBREG ENTRY VALUESTR
-    Push "${HKREG}"
-    Push "${SUBREG}"
-    Push "${ENTRY}"
-    Push "${VALUESTR}"
-    Call FctWriteRegStrAuth
-!macroend
-!define WriteRegStrAuth "!insertmacro WriteRegStrAuth"
-
-
-Function un.FctDeleteRegKeyAuth
-   ;local var
-   Push $0
-   Push $R0
-   Push $R1
-   ;pop function arguments
-   Exch 3
-   Pop $R1
-   Exch 3
-   Pop $R0
-
-   ;test if calling HKCR
-   StrCmp $R0 "HKCR" +1 +3
-   DeleteRegKey HKCR $R1
-   goto lbl_end
-   
-   #has current user admin privileges?
-   userInfo::getAccountType
-   Pop $0
-   StrCmp $0 "Admin" lbl_admin lbl_not_admin
-   
-   lbl_admin:
-      DeleteRegKey HKLM $R1
-      goto lbl_end
-   
-   lbl_not_admin:
-      DeleteRegKey HKCU $R1
-
-   lbl_end:
-      Pop $0
-      Pop $R1
-      Pop $R0
-FunctionEnd
-
-!macro DeleteRegKeyAuth HKREG SUBREG
-    Push "${HKREG}"
-    Push "${SUBREG}"
-    Call un.FctDeleteRegKeyAuth
-!macroend
-!define DeleteRegKeyAuth "!insertmacro DeleteRegKeyAuth"
-
-
-Function InsertGDIPLUS
-   Push $R0
-   Push $R1
-   ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-   StrCmp $R0 "" 0 lbl_winnt
-
-   ;NOT NT
-   ReadRegStr $R0 HKLM SOFTWARE\Microsoft\Windows\CurrentVersion VersionNumber
-
-   StrCpy $R1 $R0 1
-   ; win95, NOT SUPPORTED
-   StrCmp $R1 '4' 0 lbl_err_95
-   StrCpy $R1 $R0 3
-   StrCmp $R1 '4.0' lbl_err_95
-   ;winME or 98 otherwise
-   StrCmp $R1 '4.9' lbl_add lbl_add
-
-lbl_err_nt:
-   MessageBox MB_OK "Microsoft GDI+ cannot be installed on NT 3 Systems"
-   Goto lbl_done
-
-lbl_err_95:
-   MessageBox MB_OK "Microsoft GDI+ cannot be installed on Windows 95 and older Systems"
-   Goto lbl_done
-
-lbl_winnt:
-   StrCpy $R1 $R0 1
-   StrCmp $R1 '3' lbl_err_nt
-   StrCmp $R1 '4' lbl_add
-   StrCpy $R1 $R0 3
-   StrCmp $R1 '5.0' lbl_add    ;2000
-   StrCmp $R1 '5.1' lbl_xp     ;XP
-   StrCmp $R1 '5.2' lbl_done   ;.NET server
-
-lbl_add:
-   File ".\Gdiplus.dll"
-
-lbl_xp:
-   File "..\gm_gdip_raster.dll"
-
-lbl_done:
-FunctionEnd
-
-;osmo4 install
-Section "Osmo4/GPAC Player"
-  SectionIn RO
-  SetOutPath $INSTDIR
-
-  File /oname=ReadMe.txt "${GPAC_ROOT}\README"
-  File /oname=License.txt "${GPAC_ROOT}\COPYING"
-  File /oname=Changelog.txt "${GPAC_ROOT}\Changelog"
-  File "${GPAC_ROOT}\doc\configuration.html"
-  File "${GPAC_ROOT}\doc\gpac.mp4"
-
-  File "..\Osmo4.exe"
-  File "..\..\..\..\doc\osmo4.ico"
-  File "..\libgpac.dll"
-  File "..\gm_dummy_in.dll"
-  File "..\gm_dx_hw.dll"
-  File "..\js32.dll"
-  File "..\gm_gpac_js.dll"
-
-  ;create default cache
-  SetOutPath $INSTDIR\cache
-
-  SetOutPath $INSTDIR
-  
-  ${WriteRegStrAuth} HKCU "SOFTWARE\GPAC" "InstallDir" "$INSTDIR"
-  ${WriteRegStrAuth} HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Osmo4" "DisplayName" "Osmo4/GPAC (remove only)"
-  ${WriteRegStrAuth} HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Osmo4" "UninstallString" "$INSTDIR\uninstall.exe"
-  WriteUninstaller "uninstall.exe"
-
-SectionEnd
-
-SubSection "GPAC Plugins"
-
-
-;
-;      2 install modes, normal one and full one
-
-Section "MPEG-4 BIFS Decoder"
-  SectionIn 1
-  File "..\gm_bifs_dec.dll"
-SectionEnd
-
-Section "MPEG-4 ODF Decoder"
-  SectionIn 1
-  File "..\gm_odf_dec.dll"
-SectionEnd
-
-Section "MPEG-4 LASeR Decoder"
-  SectionIn 1
-  File "..\gm_laser_dec.dll"
-SectionEnd
-
-Section "MPEG-4 SAF Demultiplexer"
-  SectionIn 1
-  File "..\gm_saf_in.dll"
-SectionEnd
-
-Section "Generic Scene Description File Loader"
-  SectionIn 1
-  File "..\gm_ctx_load.dll"
-SectionEnd
-
-Section "Image Package (PNG, JPEG, BMP)"
-  SectionIn 1
-  File "..\gm_img_in.dll"
-SectionEnd
-
-Section "AAC Audio support (FAAD decoder, AAC files and Radios)"
-  SectionIn 1
-  File "..\gm_aac_in.dll"
-SectionEnd
-
-Section "MP3 Audio support (MAD decoder, MP3 files and Radios)"
-  SectionIn 1
-  File "..\gm_mp3_in.dll"
-SectionEnd
-
-Section "AC3 Audio support (A52 decoder, AC3 files and Radios)"
-  SectionIn 1
-  File "..\gm_ac3_in.dll"
-SectionEnd
-
-Section "FFMPEG Reader and Decoder"
-  SectionIn 1
-  File "..\gm_ffmpeg_in.dll"
-  File "..\avcodec-52.dll"
-  File "..\avformat-52.dll"
-  File "..\avutil-50.dll"
-  File "..\swscale-0.dll"
-SectionEnd
-
-Section "XviD Video Decoder"
-  SectionIn 1
-  File "..\gm_xvid_dec.dll"
-SectionEnd
-
-;Section "3GPP AMR NB & WB Speech Decoder"
-;  SectionIn 1
-;  File "..\gm_amr_float_dec.dll"
-;SectionEnd
-
-Section "Subtitle & TimedText Support"
-  SectionIn 1
-  File "..\gm_timedtext.dll"
-SectionEnd
-
-Section "MP4 and 3GPP File Reader"
-  SectionIn 1
-  File "..\gm_isom_in.dll"
-SectionEnd
-
-Section "MPEG-2 TS Reader"
-  SectionIn 1
-  File "..\gm_mpegts_in.dll"
-SectionEnd
-
-Section "Real-Time Streaming (RTP/RTSP/RTP) Support"
-  SectionIn 1
-  File "..\gm_rtp_in.dll"
-SectionEnd
-
-Section "Progressive SVG Support"
-  SectionIn 1
-  File "..\gm_svg_in.dll"
-SectionEnd
-
-
-Section "GDI+ Rasterizer"
-  SectionIn 1
-  call InsertGDIPLUS
-SectionEnd
-
-Section "GPAC 2D Rasterizer"
-  SectionIn 1
-  File "..\gm_soft_raster.dll"
-SectionEnd
-
-Section "FreeType Font Outliner"
-  SectionIn 1
-  File "..\gm_ft_font.dll"
-SectionEnd
-
-Section "Windows MME Audio Output"
-  SectionIn 1
-  File "..\gm_wav_out.dll"
-SectionEnd
-
-Section "Xiph Ogg Reader - Vorbis and Theora Decoders"
-  SectionIn 1
-  File "..\gm_ogg.dll"
-SectionEnd
-
-;Section "UPnP Support"
-;  SectionIn 1
-;  File "..\gm_platinum.dll"
-;SectionEnd
-
-;Section "Widget Manager"
-;  SectionIn 1
-;  File "..\gm_widgetman.dll"
-;SectionEnd
-
-SubSectionEnd
-
-SubSection "Osmo4 Shortcuts"
-
-Section "Add Start Menu Shortcuts"
-  SectionIn 1
-  #has current user admin privileges?
-  userInfo::getAccountType
-  Pop $0
-  StrCmp $0 "Admin" +1 +2
-  SetShellVarContext all
-  CreateDirectory "$SMPROGRAMS\Osmo4"
-  CreateShortCut "$SMPROGRAMS\Osmo4\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
-  CreateShortCut "$SMPROGRAMS\Osmo4\Osmo4.lnk" "$INSTDIR\Osmo4.exe" "" "$INSTDIR\Osmo4.exe" 0
-  CreateShortCut "$SMPROGRAMS\Osmo4\Readme.lnk" "$INSTDIR\ReadMe.txt"
-  CreateShortCut "$SMPROGRAMS\Osmo4\License.lnk" "$INSTDIR\License.txt"
-  CreateShortCut "$SMPROGRAMS\Osmo4\History.lnk" "$INSTDIR\changelog.txt"
-  CreateShortCut "$SMPROGRAMS\Osmo4\Configuration Info.lnk" "$INSTDIR\configuration.html"
-SectionEnd
-
-Section "Add shortcut to QuickLaunch"
-  SectionIn 1
-  CreateShortCut "$QUICKLAUNCH\Osmo4.lnk" "$INSTDIR\Osmo4.exe" "" "$INSTDIR\Osmo4.exe" 0
-SectionEnd
-
-Section "Add shortcut to Desktop"
-  SectionIn 1
-  CreateShortCut "$DESKTOP\Osmo4.lnk" "$INSTDIR\Osmo4.exe" "" "$INSTDIR\Osmo4.exe" 0
-SectionEnd
-
-!define SHCNE_ASSOCCHANGED 0x08000000
-!define SHCNF_IDLIST 0
-
-Section "Make Osmo4 the default MPEG-4 Player"
-  SectionIn 1
-  ;write file association
-  ${WriteRegStrAuth} HKCR GPAC\mp4\DefaultIcon "" "$INSTDIR\Osmo4.ico, 0"
-  ${WriteRegStrAuth} HKCR GPAC\mp4\Shell\open\command "" "$INSTDIR\Osmo4.exe %L"
-  ${WriteRegStrAuth} HKCR .mp4 "" "GPAC\mp4"
-  !system 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
-
-SectionEnd
-
-Section "Associate 3GPP files (3GP) with Osmo4"
-  SectionIn 1
-  ;write file association
-  ${WriteRegStrAuth} HKCR GPAC\3gp\DefaultIcon "" "$INSTDIR\Osmo4.ico, 0"
-  ${WriteRegStrAuth} HKCR GPAC\3gp\Shell\open\command "" "$INSTDIR\Osmo4.exe %L"
-  ${WriteRegStrAuth} HKCR .3gp "" "GPAC\3gp"
-  !system 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
-SectionEnd
-
-Section "Associate 3GPP2 files (3G2) with Osmo4"
-  SectionIn 1
-  ;write file association
-  ${WriteRegStrAuth} HKCR GPAC\3g2\DefaultIcon "" "$INSTDIR\Osmo4.ico, 0"
-  ${WriteRegStrAuth} HKCR GPAC\3g2\Shell\open\command "" "$INSTDIR\Osmo4.exe %L"
-  ${WriteRegStrAuth} HKCR .3g2 "" "GPAC\3g2"
-  !system 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
-SectionEnd
-
-SubSectionEnd
-
-
-Section "MP4Box (Command-line MPEG-4 tool)"
-  SectionIn 1
-  SetOutPath $INSTDIR
-  File "..\MP4Box.exe"
-
-  Push $INSTDIR
-  Call AddToPath
-SectionEnd
-
-
-!define HK_MOZ "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0"
-
-Section "Osmozilla (GPAC Plugin for Mozilla)"
-  SectionIn 1
-  SetOutPath $INSTDIR
-  File "..\nposmozilla.dll"
-  File "..\nposmozilla.xpt"
-
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "Path" "$INSTDIR\nposmozilla.dll"
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "XPTPath" "$INSTDIR\nposmozilla.xpt"
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "Version" "${GPAC_VERSION}"
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "Vendor" "GPAC"
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "Description" "GPAC plugin"
-  ${WriteRegStrAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0" "ProductName" "Osmozilla"
-SectionEnd
-
-
-Section "GPAX (GPAC ActiveX Control)"
-  SectionIn 1
-  SetOutPath $INSTDIR
-  File "..\GPAX.dll"
-  RegDLL "$INSTDIR\GPAX.dll"
-SectionEnd
-
-
-Section "MP4Client (GPAC Command-line client/grabber)"
-  SectionIn 1
-  SetOutPath $INSTDIR
-  File "..\MP4Client.exe"
-SectionEnd
-
-
-Function .onInstSuccess
-;  MessageBox MB_YESNO "GPAC Framework installation complete. Do you want to launch the Osmo4 player?" IDNO NoLaunch
-;  Exec $INSTDIR\Osmo4.exe
-;  NoLaunch:
-FunctionEnd
-
-
-
-
-
-; uninstall stuff
-
-UninstallText "This will uninstall OSMO4/GPAC from your computer. Hit next to continue."
-
-; special uninstall section.
-Section "Uninstall"
-  ; remove registry keys
-  ${DeleteRegKeyAuth} HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Osmo4"
-  ${DeleteRegKeyAuth} HKCU "SOFTWARE\GPAC"
-  ${DeleteRegKeyAuth} HKCU "SOFTWARE\MozillaPlugins\@gpac/osmozilla,version=1.0"
-  ${DeleteRegKeyAuth} HKCR GPAC\mp4\DefaultIcon
-  ${DeleteRegKeyAuth} HKCR GPAC\mp4\shell\open\command
-  ${DeleteRegKeyAuth} HKCR GPAC\mp4
-  ${DeleteRegKeyAuth} HKCR .mp4
-  ${DeleteRegKeyAuth} HKCR GPAC\3gp\DefaultIcon
-  ${DeleteRegKeyAuth} HKCR GPAC\3gp\shell\open\command
-  ${DeleteRegKeyAuth} HKCR GPAC\3gp
-  ${DeleteRegKeyAuth} HKCR .3gp
-  ${DeleteRegKeyAuth} HKCR GPAC\3g2\DefaultIcon
-  ${DeleteRegKeyAuth} HKCR GPAC\3g2\shell\open\command
-  ${DeleteRegKeyAuth} HKCR GPAC\3g2
-  ${DeleteRegKeyAuth} HKCR .3g2
-  ${DeleteRegKeyAuth} HKCR GPAC
-
-  Delete $INSTDIR\cache\*.*
-  RMDir "$INSTDIR\cache"
-  Delete $INSTDIR\*.*
-  RMDir "$INSTDIR"
-  UnRegDLL "$INSTDIR\GPAX.dll"
-  Push $INSTDIR
-  Call un.RemoveFromPath
-  #has current user admin privileges?
-  userInfo::getAccountType
-  Pop $0
-  StrCmp $0 "Admin" +1 +2
-  SetShellVarContext all
-  Delete "$SMPROGRAMS\Osmo4\*.*"
-  RMDir "$SMPROGRAMS\Osmo4"
-  Delete "$QUICKLAUNCH\Osmo4.lnk"
-  Delete "$DESKTOP\Osmo4.lnk"
-
-SectionEnd
-
-;path modif functions
-!verbose 3
-!include "WinMessages.NSH"
-!verbose 4
-
-; AddToPath - Adds the given dir to the search path.
-;        Input - head of the stack
-;        Note - Win9x systems requires reboot
-
-Function AddToPath
-  Exch $0
-  Push $1
-  Push $2
-  Push $3
-
-  # don't add if the path doesn't exist
-  IfFileExists $0 "" AddToPath_done
-
-  ReadEnvStr $1 PATH
-  Push "$1;"
-  Push "$0;"
-  Call StrStr
-  Pop $2
-  StrCmp $2 "" "" AddToPath_done
-  Push "$1;"
-  Push "$0\;"
-  Call StrStr
-  Pop $2
-  StrCmp $2 "" "" AddToPath_done
-  GetFullPathName /SHORT $3 $0
-  Push "$1;"
-  Push "$3;"
-  Call StrStr
-  Pop $2
-  StrCmp $2 "" "" AddToPath_done
-  Push "$1;"
-  Push "$3\;"
-  Call StrStr
-  Pop $2
-  StrCmp $2 "" "" AddToPath_done
-
-  Call IsNT
-  Pop $1
-  StrCmp $1 1 AddToPath_NT
-    ; Not on NT
-    StrCpy $1 $WINDIR 2
-    FileOpen $1 "$1\autoexec.bat" a
-    FileSeek $1 -1 END
-    FileReadByte $1 $2
-    IntCmp $2 26 0 +2 +2 # DOS EOF
-      FileSeek $1 -1 END # write over EOF
-    FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
-    FileClose $1
-    SetRebootFlag true
-    Goto AddToPath_done
-
-  AddToPath_NT:
-    ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-    StrCpy $2 $1 1 -1 # copy last char
-    StrCmp $2 ";" 0 +2 # if last char == ;
-      StrCpy $1 $1 -1 # remove last char
-    StrCmp $1 "" AddToPath_NTdoIt
-      StrCpy $0 "$1;$0"
-    AddToPath_NTdoIt:
-      WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0
-
-    ReadRegStr $1 HKCU "Environment" "PATH"
-    StrCpy $2 $1 1 -1 # copy last char
-    StrCmp $2 ";" 0 +2 # if last char == ;
-      StrCpy $1 $1 -1 # remove last char
-    StrCmp $1 "" AddToPath_NTdoIt2
-      StrCpy $0 "$1;$0"
-    AddToPath_NTdoIt2:
-      WriteRegExpandStr HKCU "Environment" "PATH" $0
-    SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-  AddToPath_done:
-    Pop $3
-    Pop $2
-    Pop $1
-    Pop $0
-FunctionEnd
-
-; RemoveFromPath - Remove a given dir from the path
-;     Input: head of the stack
-
-Function un.RemoveFromPath
-  Exch $0
-  Push $1
-  Push $2
-  Push $3
-  Push $4
-  Push $5
-  Push $6
-
-  IntFmt $6 "%c" 26 # DOS EOF
-
-  Call un.IsNT
-  Pop $1
-  StrCmp $1 1 unRemoveFromPath_NT
-    ; Not on NT
-    StrCpy $1 $WINDIR 2
-    FileOpen $1 "$1\autoexec.bat" r
-    GetTempFileName $4
-    FileOpen $2 $4 w
-    GetFullPathName /SHORT $0 $0
-    StrCpy $0 "SET PATH=%PATH%;$0"
-    Goto unRemoveFromPath_dosLoop
-
-    unRemoveFromPath_dosLoop:
-      FileRead $1 $3
-      StrCpy $5 $3 1 -1 # read last char
-      StrCmp $5 $6 0 +2 # if DOS EOF
-        StrCpy $3 $3 -1 # remove DOS EOF so we can compare
-      StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
-      StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
-      StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
-      StrCmp $3 "" unRemoveFromPath_dosLoopEnd
-      FileWrite $2 $3
-      Goto unRemoveFromPath_dosLoop
-      unRemoveFromPath_dosLoopRemoveLine:
-        SetRebootFlag true
-        Goto unRemoveFromPath_dosLoop
-
-    unRemoveFromPath_dosLoopEnd:
-      FileClose $2
-      FileClose $1
-      StrCpy $1 $WINDIR 2
-      Delete "$1\autoexec.bat"
-      CopyFiles /SILENT $4 "$1\autoexec.bat"
-      Delete $4
-      Goto unRemoveFromPath_done
-
-  unRemoveFromPath_NT:
-    ReadRegStr $1 HKCU "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-    StrCpy $5 $1 1 -1 # copy last char
-    StrCmp $5 ";" +2 # if last char != ;
-      StrCpy $1 "$1;" # append ;
-    Push $1
-    Push "$0;"
-    Call un.StrStr ; Find `$0;` in $1
-    Pop $2 ; pos of our dir
-    StrCmp $2 "" unRemoveFromPath_done
-      ; else, it is in path
-      # $0 - path to add
-      # $1 - path var
-      StrLen $3 "$0;"
-      StrLen $4 $2
-      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
-      StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
-      StrCpy $3 $5$6
-
-      StrCpy $5 $3 1 -1 # copy last char
-      StrCmp $5 ";" 0 +2 # if last char == ;
-        StrCpy $3 $3 -1 # remove last char
-
-      WriteRegExpandStr HKCU "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
-      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-  unRemoveFromPath_done:
-    Pop $6
-    Pop $5
-    Pop $4
-    Pop $3
-    Pop $2
-    Pop $1
-    Pop $0
-FunctionEnd
-
-###########################################
-#            Utility Functions            #
-###########################################
-
-; IsNT
-; no input
-; output, top of the stack = 1 if NT or 0 if not
-;
-; Usage:
-;   Call IsNT
-;   Pop $R0
-;  ($R0 at this point is 1 or 0)
-
-!macro IsNT un
-Function ${un}IsNT
-  Push $0
-  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-  StrCmp $0 "" 0 IsNT_yes
-  ; we are not NT.
-  Pop $0
-  Push 0
-  Return
-
-  IsNT_yes:
-    ; NT!!!
-    Pop $0
-    Push 1
-FunctionEnd
-!macroend
-!insertmacro IsNT ""
-!insertmacro IsNT "un."
-
-; StrStr
-; input, top of stack = string to search for
-;        top of stack-1 = string to search in
-; output, top of stack (replaces with the portion of the string remaining)
-; modifies no other variables.
-;
-; Usage:
-;   Push "this is a long ass string"
-;   Push "ass"
-;   Call StrStr
-;   Pop $R0
-;  ($R0 at this point is "ass string")
-
-!macro StrStr un
-Function ${un}StrStr
-Exch $R1 ; st=haystack,old$R1, $R1=needle
-  Exch    ; st=old$R1,haystack
-  Exch $R2 ; st=old$R1,old$R2, $R2=haystack
-  Push $R3
-  Push $R4
-  Push $R5
-  StrLen $R3 $R1
-  StrCpy $R4 0
-  ; $R1=needle
-  ; $R2=haystack
-  ; $R3=len(needle)
-  ; $R4=cnt
-  ; $R5=tmp
-  loop:
-    StrCpy $R5 $R2 $R3 $R4
-    StrCmp $R5 $R1 done
-    StrCmp $R5 "" done
-    IntOp $R4 $R4 + 1
-    Goto loop
-done:
-  StrCpy $R1 $R2 "" $R4
-  Pop $R5
-  Pop $R4
-  Pop $R3
-  Pop $R2
-  Exch $R1
-FunctionEnd
-!macroend
-!insertmacro StrStr ""
-!insertmacro StrStr "un."
-
index 128a87ca6c072b073f91f2e3aa5ffa5546e845d8..367006ecab509d6fc4807e9d2fb95205472494c5 100644 (file)
@@ -437,6 +437,7 @@ Section "MP4Box" SecMP4B
   SectionIn 1
   SetOutPath $INSTDIR
   File "..\MP4Box.exe"
+  File "..\MP42TS.exe"
 
   Push $INSTDIR
   Call AddToPath
index dbe7d8852d73ff25d9f2e13424558394c5882e56..feca36b45e316a3700eff465dedc5b48c234ad47 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,9 +1,11 @@
 #!/bin/sh
 #
-# GPAC MPEG-4 SDK configure script (c) 2003-2005 Jean Le Feuvre
-#              inspired from ffmpeg configure by Fabrice Bellard (c) 2000-2002
+# GPAC MPEG-4 SDK configure script (c) 2003-2005 Jean Le Feuvre (c) 2005-20XX Telecom ParisTech
+#      inspired from ffmpeg configure by Fabrice Bellard (c) 2000-2002
 #set -v
-# set temporary file name
+
+
+#set temporary file name
 if test ! -z "$TMPDIR" ; then
     TMPDIR1="${TMPDIR}"
 elif test ! -z "$TEMPDIR" ; then
@@ -12,6 +14,7 @@ else
     TMPDIR1="/tmp"
 fi
 
+
 #thanks to ffmpeg for this
 for v in "$@"; do
     r="${v#*=}"
@@ -28,7 +31,8 @@ TMPE="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}"
 TMPO="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}.o"
 TMPS="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}.S"
 
-# default parameters
+
+#default parameters
 DESTDIR=""
 prefix="/usr/local"
 mandir=""
@@ -43,6 +47,7 @@ ar="ar"
 ranlib="ranlib"
 make="make"
 strip="strip"
+pkg_config="pkg-config"
 readelf="readelf"
 install="${INSTALL:=install}"
 instflags="${INSTFLAGS:=-p}"
@@ -61,6 +66,7 @@ js_lib="-ljs"
 lm_lib=""
 has_mingw_directx="no"
 has_js="no"
+has_platinum="no"
 has_ft="no"
 has_jpeg="no"
 has_png="no"
@@ -138,6 +144,10 @@ disable_isoff_frag="no"
 disable_streaming="no"
 enable_depth_compositor="no"
 enable_renoir="no"
+has_avcap="no"
+avcap_cflags=""
+avcap_ldflags="-lavcap"
+has_opensvc="no"
 
 win32="no"
 mingw32="no"
@@ -162,7 +172,9 @@ OSS_LDFLAGS=""
 INSTFLAGS=""
 is_64="no"
 
-#Configure Usage
+
+
+#configure usage
 if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
     cat << EOF
 
@@ -199,11 +211,16 @@ GPAC configuration options:
   --disable-opt            disable GCC optimizations
   --disable-ipv6           disable IPV6 support
   --disable-wx             disable wxWidgets support
+  --disable-platinum       disable Platinum UPnP support
+  --disable-alsa           disable Alsa audio
   --disable-oss-audio      disable OSS audio
+  --enable-jack            enable  Jack audio
+  --disable-jack           disable Jack audio
+  --enable-pulseaudio      enable  Pulse audio
+  --disable-pulseaudio     disable Pulse audio
   --disable-x11-shm        disable X11 shared memory support
   --disable-x11-xv         disable X11 Xvideo support
   --enable-fixed-point     enable fixed-point math
-  --force-fixed-point      force fixed-point math without changing gpac math.h header
   --enable-tinygl          enable TinyGL support
   --enable-joystick        enable joystick support
   --disable-ssl            disable OpenSSL support
@@ -211,6 +228,7 @@ GPAC configuration options:
   --enable-amr-nb          enable AMR NB library
   --enable-amr-wb          enable AMR WB library
   --enable-amr             enable both AMR NB and WB libraries
+  --enable-static-bin      GPAC static build
   --static-mp4box          configure for static linking of MP4Box.
   --enable-depth           enables depth handling in the compositor
 
@@ -230,6 +248,7 @@ Configuration options for libgpac - all options can be enabled with --enable-opt
   --disable-m2ps           disable MPEG2 PS
   --disable-m2ts           disable MPEG2 TS
   --disable-m2ts-mux       disable MPEG2 TS Multiplexer
+  --disable-dvb4linux      disable dvb4linux support
   --disable-parsers        disable AV parsers
   --disable-import         disable media importers
   --disable-export         disable media exporters
@@ -251,6 +270,7 @@ Configuration options for libgpac - all options can be enabled with --enable-opt
 Extra libraries configuration. You can turn a libray off or force using the local version in gpac/extra_lib/
   --use-js=OPT             force SpiderMonkey ECMAScript OPT=[no,local]
   --use-ft=OPT             force FreeType OPT=[no,local]
+  --use-zlib=OPT           force ZLIB OPT=[no,local]
   --use-jpeg=OPT           force JPEG OPT=[no,local]
   --use-png=OPT            force PNG OPT=[no,local]
   --use-faad=OPT           force FAAD OPT=[no,local]
@@ -261,6 +281,7 @@ Extra libraries configuration. You can turn a libray off or force using the loca
   --use-vorbis=OPT         force vorbis OPT=[no,system,local]
   --use-theora=OPT         force theora OPT=[no,system,local]
   --use-openjpeg=OPT       force openjpeg OPT=[no,system,local]
+  --use-a52=OPT            force a52 (ac3) OPT=[no,system,local]
 
 NOTE: The object files are build at the place where configure is launched
 EOF
@@ -289,6 +310,12 @@ for opt do
             ;;
         --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
             ;;
+        --enable-debug) debuginfo="yes"; no_gcc_opt="yes"
+            ;;
+        --disable-opt) no_gcc_opt="yes"
+            ;;
+        --enable-pic) want_pic="yes";
+            ;;
     esac
 done
 
@@ -352,7 +379,7 @@ case "$cpu" in
         ;;
 esac
 
-# Checking for CFLAGS
+#checking for CFLAGS
 if test -z "$CFLAGS"; then
     CFLAGS=""
 fi
@@ -365,6 +392,7 @@ if test "$mingw32" = "yes" ; then
     cross_prefix=""
 fi
 
+
 cc="${cross_prefix}${cc}"
 #for ccache
 cc="${cc}"
@@ -372,9 +400,16 @@ cpp="${cross_prefix}${cpp}"
 ar="${cross_prefix}${ar}"
 ranlib="${cross_prefix}${ranlib}"
 strip="${cross_prefix}${strip}"
+pkg_config="${cross_prefix}${pkg_config}"
 
 
-# find source path
+#check pkg_config
+if ! $pkg_config --version >/dev/null 2>&1 ; then
+    echo "$pkg_config not found, configure may detect wrong libraries"
+fi
+
+
+#find source path
 source_path="`echo $0 | sed -e 's#/configure##'`"
 source_path_used="yes"
 if test -z "$source_path" -o "$source_path" = "." ; then
@@ -383,7 +418,9 @@ if test -z "$source_path" -o "$source_path" = "." ; then
 else
     source_path="`cd \"$source_path\"; pwd`"
 fi
-# OS specific
+
+
+#OS specific
 targetos=`uname -s`
 case $targetos in
     BeOS)
@@ -402,8 +439,8 @@ case $targetos in
         esac
 
         SHFLAGS=-nostart
-        # no need for libm, but the inet stuff
-        # Check for BONE
+        #no need for libm, but the inet stuff
+        #check for BONE
         if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
             extralibs="-lbind -lsocket"
         else
@@ -417,11 +454,12 @@ case $targetos in
         readelf="greadelf"
         LDFLAGS="${opt#--extra-ldflags=}"
         instflags=""
-        # check for 64-bit
-cat > $TMPC << EOF
+        #check for 64-bit
+        cat > $TMPC << EOF
 #include <stdio.h>
 int main( void ) { return 0; }
 EOF
+
         CFLAGS_NO_LTO=$(echo ${CFLAGS} | sed -e 's/\ -flto[-A-Za-z0-9=]*//g')
         $cc ${CFLAGS_NO_LTO} -o $TMPO $TMPC 2>/dev/null && $($readelf -h $TMPO | grep "Class:.*ELF64$" >/dev/null 2>&1)
         if test $? -eq 0; then
@@ -458,11 +496,11 @@ EOF
         xul_flags=-DXP_MAC
         if test -d /sw/bin ; then
             alt_macosx_dir="/sw"
-            CFLAGS="-I/sw/include $CFLAGS"
+            CFLAGS_DIR="-I/sw/include"
             LDFLAGS="-L/sw/lib $LDFLAGS"
         elif test -d /opt/local/bin ; then
             alt_macosx_dir="/opt/local"
-            CFLAGS="-I/opt/local/include $CFLAGS"
+            CFLAGS_DIR="-I/opt/local/include"
             LDFLAGS="-L/opt/local/lib $LDFLAGS"
         fi
         cc="cc"
@@ -519,7 +557,8 @@ EOF
     *) ;;
 esac
 
-# Defines directory for binaries and libs (ex. for TinyGL)
+
+#defines directory for binaries and libs (ex. for TinyGL)
 target_bin_dir="" 
 if test "$cross_prefix" = "" ; then
     target_bin_dir=`${cc} -v 2>&1 | sed -n '2p' | awk ' {print $2}'`-${cc_orig}
@@ -527,12 +566,14 @@ else
     target_bin_dir=${cross_prefix}${cc_orig}
 fi
 
+
 #if test "$source_path_used" = "yes" ; then
 mkdir -p extra_lib
 mkdir -p extra_lib/lib
 mkdir -p extra_lib/lib/gcc
 #fi
 
+
 #OK check for all local & systems lib
 local_inc=$source_path/extra_lib/include
 local_lib=extra_lib/lib/gcc
@@ -543,6 +584,7 @@ cat > $TMPC << EOF
 #include <stdio.h>
 int main( void ) { return 0; }
 EOF
+CFLAGS="$CFLAGS -Wall"
 if $cc -o $TMPO $TMPC -fno-strict-aliasing 2> /dev/null  ; then
     CFLAGS="$CFLAGS -fno-strict-aliasing"
 fi
@@ -551,22 +593,55 @@ if $cc -o $TMPO $TMPC -lz -Wno-pointer-sign 2> /dev/null  ; then
     CFLAGS="$CFLAGS -Wno-pointer-sign"
 fi
 
+
+#GCC opt
+if test "$no_gcc_opt" = "no"; then
+    if $cc --version | grep 'sbox-arm-linux-gcc (GCC) 3.4.4'
+    then
+        echo "Detected buggy arm GCC (diablo), using -O2"
+        CFLAGS="-O2 $CFLAGS"
+    else
+        CFLAGS="-O3 $CFLAGS"
+    fi
+fi
+
+
+#GCC PIC
+if test "$want_pic"  = "yes" ; then
+    CFLAGS="$CFLAGS -fPIC -DPIC"
+    CPPFLAGS="$CPPFLAGS -fPIC -DPIC"
+fi
+
+
+#force use of cflags with cc
+cc_naked=$cc
+cpp_naked=$cpp
+cc="$cc $CFLAGS"
+cpp="$cpp $CPPFLAGS"
+
+
 #look for zlib
 cat > $TMPC << EOF
 #include <zlib.h>
-int main( void ) { if (zlibVersion() != ZLIB_VERSION) { puts("zlib version differs !!!"); return 1; } return 0; }
+int main( void ) { if (strcmp(zlibVersion(), ZLIB_VERSION)) { puts("zlib version differs !!!"); return 1; } return 0; }
 EOF
 has_zlib="no"
-if $cc -o $TMPO $TMPC -lz 2> /dev/null  ; then
-    has_zlib="system"
-elif $cc -o $TMPO $TMPC -I"$local_inc/zlib" -L$local_lib -lz 2> /dev/null  ; then
+if test "$cross_prefix" = "" ; then
+  if $cc -o $TMPO $TMPC -lz $LDFLAGS 2> /dev/null  ; then
+      has_zlib="system"
+  fi
+fi
+if test "$has_zlib" = "no" ; then
+  if $cc -o $TMPO $TMPC -I"$local_inc/zlib" -L$local_lib -lz 2> /dev/null  ; then
     has_zlib="local"
-else
+  else
     echo "error: zlib not found on system or in local libs"
     exit 1
+  fi
 fi
 
 
+
 #check dlopen
 cat > $TMPC << EOF
 #include <dlfcn.h>
@@ -575,7 +650,7 @@ EOF
 
 if $cc -o $TMPE $TMPC > /dev/null 2>&1 ; then
     dlopen="yes"
-elif $cc -o $TMPE $TMPC -ldl > /dev/null 2>&1 ; then
+elif $cc -o $TMPE $TMPC $LDFLAGS -ldl > /dev/null 2>&1 ; then
     GPAC_SH_FLAGS="$GPAC_SH_FLAGS -ldl"
 else
     if test "$win32" = "no"; then
@@ -585,6 +660,7 @@ else
 fi
 
 
+
 #look for spidermonkey JS support
 
 #spidermonkey test for new API
@@ -602,14 +678,27 @@ EOF
         has_js="local"
         #dc added
     else
-
-        if pkg-config --exists mozilla-js 2> /dev/null  ; then
-            js_flags=`pkg-config --cflags mozilla-js`
-            js_lib_pkg=`pkg-config --libs mozilla-js`
-            if $cpp -o $TMPO $TMPCPP $js_flags $js_lib_pkg -lpthread 2> /dev/null  ; then
+        #try pkg-config
+        if $pkg_config --exists mozilla-js 2> /dev/null  ; then
+            js_flags=`$pkg_config --cflags mozilla-js`
+            js_lib_pkg=`$pkg_config --libs mozilla-js`
+            if $cpp -o $TMPO $TMPCPP $js_flags $js_lib_pkg $LDFLAGS -lpthread 2> /dev/null  ; then
                 has_js="system"
-                js_lib=`pkg-config --libs mozilla-js`
+                js_lib=`$pkg_config --libs mozilla-js`
             fi
+        #try firefox folders (starting at ubuntu 11.10, no pkg-config)
+        elif ls -d /usr/lib/firefox* > /dev/null 2>&1 ; then
+            firefox_version=`cd /usr/lib ; ls -d firefox* | grep -v addons | grep -v devel ; cd - > /dev/null`
+            for i in $firefox_version ; do
+                if test "$has_js" = "no" ; then
+                    js_inc="/usr/include/$i"
+                    js_flags="-DXP_UNIX -I$js_inc"
+                    js_lib="-L/usr/lib/$i/ -lxul -lmozsqlite3 -lmozalloc -lnss3"
+                    if $cpp -o $TMPO $TMPCPP $js_flags $js_lib 2> /dev/null  ; then
+                        has_js="$i"
+                    fi
+                fi
+            done
         fi
 
         if test "$has_js" = "no" ; then
@@ -620,10 +709,10 @@ EOF
                 has_js="prefix"
                 #dc added end
             else
-                if $cpp -o $TMPO $TMPCPP $js_flags -ljs -lpthread 2> /dev/null  ; then
+                if $cpp -o $TMPO $TMPCPP $js_flags $LDFLAGS -ljs -lpthread 2> /dev/null  ; then
                     js_inc="/usr/include"
                     has_js="system"
-                elif $cpp -o $TMPO $TMPCPP -DXP_UNIX -I$alt_macosx_dir/include/js -L$alt_macosx_dir/lib -ljs -lpthread 2> /dev/null ; then
+                elif $cpp -o $TMPO $TMPCPP -DXP_UNIX -I$alt_macosx_dir/include/js -L$alt_macosx_dir/lib $LDFLAGS -ljs -lpthread 2> /dev/null ; then
                     has_js="system"
                     js_flags="-DXP_UNIX -I$alt_macosx_dir/include/js"
                     js_lib="-L$alt_macosx_dir/lib -ljs"
@@ -632,14 +721,14 @@ EOF
                     #debian spidermonkey (smjs)
                     js_flags="-DXP_UNIX -I/usr/include/smjs"
                     js_inc="/usr/include/smjs"
-                    if $cpp -o $TMPO $TMPCPP $js_flags -lsmjs -lpthread 2> /dev/null  ; then
+                    if $cpp -o $TMPO $TMPCPP $js_flags $LDFLAGS -lsmjs -lpthread 2> /dev/null  ; then
                         has_js="system"
                         js_lib="-lsmjs"
                     else
                         #debian spidermonkey (mozjs)
                         js_flags="-DXP_UNIX -I/usr/include/mozjs"
                         js_inc="/usr/include/mozjs"
-                        if $cpp -o $TMPO $TMPCPP $js_flags -lmozjs -lpthread 2> /dev/null  ; then
+                        if $cpp -o $TMPO $TMPCPP $js_flags $LDFLAGS -lmozjs -lpthread 2> /dev/null  ; then
                             has_js="system"
                             js_lib="-lmozjs"
                         fi
@@ -680,19 +769,19 @@ EOF
             has_js="prefix"
             #dc added end
         else
-            if pkg-config --exists mozilla-js 2> /dev/null  ; then
-                js_flags=`pkg-config --cflags mozilla-js`
-                js_lib_pkg=`pkg-config --libs mozilla-js`
-                if $cc -o $TMPO $TMPC $js_flags $js_lib_pkg -lpthread 2> /dev/null  ; then
+            if $pkg_config --exists mozilla-js 2> /dev/null  ; then
+                js_flags=`$pkg_config --cflags mozilla-js`
+                js_lib_pkg=`$pkg_config --libs mozilla-js`
+                if $cc -o $TMPO $TMPC $js_flags $js_lib_pkg $LDFLAGS -lpthread 2> /dev/null  ; then
                     has_js="system"
-                    js_lib=`pkg-config --libs mozilla-js`
+                    js_lib=`$pkg_config --libs mozilla-js`
                 fi
             fi
             if test "$has_js" = "no" ; then
-                if $cc -o $TMPO $TMPC $js_flags -ljs 2> /dev/null  ; then
+                if $cc -o $TMPO $TMPC $js_flags $LDFLAGS -ljs 2> /dev/null  ; then
                     js_inc="/usr/include"
                     has_js="system"
-                elif $cc -o $TMPO $TMPC -DXP_UNIX -I$alt_macosx_dir/include/js -L$alt_macosx_dir/lib -ljs 2> /dev/null ; then
+                elif $cc -o $TMPO $TMPC -DXP_UNIX -I$alt_macosx_dir/include/js -L$alt_macosx_dir/lib $LDFLAGS -ljs 2> /dev/null ; then
                     has_js="system"
                     js_flags="-DXP_UNIX -I$alt_macosx_dir/include/js"
                     js_lib="-L$alt_macosx_dir/lib -ljs"
@@ -701,14 +790,14 @@ EOF
                     #debian spidermonkey (smjs)
                     js_flags="-DXP_UNIX -I/usr/include/smjs"
                     js_inc="/usr/include/smjs"
-                    if $cc -o $TMPO $TMPC $js_flags -lsmjs 2> /dev/null  ; then
+                    if $cc -o $TMPO $TMPC $js_flags $LDFLAGS -lsmjs 2> /dev/null  ; then
                         has_js="system"
                         js_lib="-lsmjs"
                     else
                         #debian spidermonkey (mozjs)
                         js_flags="-DXP_UNIX -I/usr/include/mozjs"
                         js_inc="/usr/include/mozjs"
-                        if $cc -o $TMPO $TMPC $js_flags -lmozjs 2> /dev/null  ; then
+                        if $cc -o $TMPO $TMPC $js_flags $LDFLAGS -lmozjs 2> /dev/null  ; then
                             has_js="system"
                             js_lib="-lmozjs"
                         fi
@@ -721,7 +810,6 @@ EOF
 fi
 
 
-
 if test "$has_js" != "no" ; then
     if test "$linux" = "yes" ; then
         if test "$cpu" != "sh4"; then
@@ -745,6 +833,79 @@ fi
 #end JS test
 
 
+
+#look for platinum support
+cat > $TMPC << EOF
+#include <Platinum.h>
+int main( void ) { return 0; }
+EOF
+if $cpp -o $TMPO $TMPC -I$local_inc/platinum $LDFLAGS -L$local_lib -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRenderer -lNeptune -lZlib 2> /dev/null  ; then
+  has_platinum="yes"
+fi
+
+
+#look for avcap support
+avcap_cflags=""
+avcap_ldflags="-lavcap"
+
+cat > $TMPC << EOF
+#include <avcap/avcap.h>
+using namespace avcap;
+int main( void ) { 
+  const DeviceCollector::DeviceList& dl = DEVICE_COLLECTOR::instance().getDeviceList();
+  DeviceDescriptor* dd = 0;
+  for (DeviceCollector::DeviceList::const_iterator i = dl.begin(); i != dl.end(); i++) {
+    dd = *i;
+       std::cout << dd->getName().c_str() << "\n";
+  }
+  return 0; 
+}
+EOF
+if $cpp -o $TMPO $TMPC $LDFLAGS $avcap_cflags $avcap_ldflags 2> /dev/null  ; then
+  has_avcap="yes"
+else
+    if test "$darwin" = "yes" ; then
+        avcap_cflags="-I$local_inc -I$local_inc/avcap/osx"
+        avcap_ldflags="${wl}-flat_namespace -lavcap -lpthread  -framework QuickTime -framework QuartzCore"
+    else
+        avcap_cflags="-I$local_inc -I$local_inc/avcap/linux"
+        avcap_ldflags="-lavcap -lpthread"
+    fi
+    if $cpp -o $TMPO $TMPC $avcap_cflags $LDFLAGS -L$local_lib $avcap_ldflags 2> /dev/null  ; then
+               has_avcap="yes"
+        avcap_ldflags="-L../../$local_lib $avcap_ldflags"
+    fi
+fi
+
+
+#look for opensvc support
+
+if test "$darwin" = "yes" ; then
+osvc_cflags="-I/usr/include -I/usr/local/include"
+osvc_ldflags="-L/usr/lib -L/usr/local/lib -lOpenSVCDec"
+else
+osvc_cflags=""
+osvc_ldflags="-lOpenSVCDec"
+fi
+
+cat > $TMPC << EOF
+#include <OpenSVCDecoder/SVCDecoder_ietr_api.h>
+int main( void ) { return 0; }
+EOF
+if $cpp -o $TMPO $TMPC $osvc_cflags $LDFLAGS $osvc_ldflags 2> /dev/null  ; then
+  has_opensvc="yes"
+else
+osvc_cflags="-I$local_inc"
+osvc_ldflags="-lOpenSVCDec"
+
+if $cpp -o $TMPO $TMPC $osvc_cflags $LDFLAGS -L$local_lib $osvc_ldflags 2> /dev/null  ; then
+  has_opensvc="yes"
+  osvc_ldflags="-L../../$local_lib $osvc_ldflags"
+fi
+
+fi
+
+
 #look for freetype support
 cat > $TMPC << EOF
 #include <ft2build.h>
@@ -753,30 +914,25 @@ cat > $TMPC << EOF
 #include FT_OUTLINE_H
 int main( void ) { return 0; }
 EOF
-if test "$cross_prefix"  != "" ; then
+if test "$cross_prefix" = "" ; then
     ft_cflags="-I$prefix/include "
     ft_lflags="-L$prefix/lib -lfreetype"
-    if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags 2> /dev/null  ; then
+    if $cc $CFLAGS_DIR -o $TMPO $TMPC $ft_cflags $ft_lflags $LDFLAGS 2> /dev/null  ; then
         has_ft="system"
     else
-        ft_cflags="-I$local_inc/freetype"
-        ft_lflags="-L$local_lib -lfreetype"
-        if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags 2> /dev/null  ; then
-            has_ft="local"
+        ft_cflags="`freetype-config --cflags`"
+        ft_lflags="`freetype-config --libs`"
+        if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags $LDFLAGS 2> /dev/null  ; then
+            has_ft="system"
         fi
     fi
-else
+fi
+if test "$has_ft" = "no" ; then
     if test "`which freetype-config`" != ""; then
-        ft_cflags="`freetype-config --cflags`"
-        ft_lflags="`freetype-config --libs`"
+        ft_cflags="-I$local_inc/freetype"
+        ft_lflags="-L$local_lib -lfreetype"
         if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags 2> /dev/null  ; then
-            has_ft="system"
-        else
-            ft_cflags="-I$local_inc/freetype"
-            ft_lflags="-L$local_lib -lfreetype"
-            if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags 2> /dev/null  ; then
-                has_ft="local"
-            fi
+            has_ft="local"
         fi
     fi
 fi
@@ -799,11 +955,12 @@ else
     LINK_SSL="-lssl -lcrypto"
 fi
 
-if $cc -o $TMPO $TMPC $LINK_SSL 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC $LINK_SSL $LDFLAGS 2> /dev/null  ; then
     has_ssl="yes"
 fi
 
 
+
 #look for JPEG support
 cat > $TMPC << EOF
 #include <stdio.h>
@@ -811,44 +968,37 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if test "$cross_prefix"  != "" ; then
-    if test "`which $prefix/bin/jpeg-config`" != ""; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -ljpeg 2> /dev/null  ; then
+        has_jpeg="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -ljpeg 2> /dev/null ; then
+            has_jpeg="system"
+        fi
+    elif test "`which $prefix/bin/jpeg-config`" != ""; then
         jpeg_cflags="`$prefix/bin/jpeg-config --cflags`"
         jpeg_lflags="`$prefix/bin/jpeg-config --libs`"
-        if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags 2> /dev/null  ; then
+        if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags $LDFLAGS 2> /dev/null  ; then
             has_jpeg="system"
-        else
-            jpeg_cflags="-I$local_inc/jpeg"
-            jpeg_lflags="-L$local_lib -ljpeg"
-            if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags 2> /dev/null  ; then
-                has_jpeg="local"
-            fi
         fi
     else
         jpeg_cflags="-I$prefix/include"
         jpeg_lflags="-L$prefix/lib -ljpeg"
-        if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags 2> /dev/null  ; then
+        if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags $LDFLAGS 2> /dev/null  ; then
             has_jpeg="system"
-        else
-            jpeg_cflags="-I$local_inc/jpeg"
-            jpeg_lflags="-L$local_lib -ljpeg"
-            if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags 2> /dev/null  ; then
-                has_jpeg="local"
-            fi
         fi
     fi
-else
-    if $cc -o $TMPO $TMPC -ljpeg 2> /dev/null  ; then
-        has_jpeg="system"
-    elif test "$alt_macosx_dir" != "" ; then
-        if cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -ljpeg 2> /dev/null ; then
-            has_jpeg="system"
-        fi
-    elif $cc -o $TMPO $TMPC -I$local_inc/jpeg -L$local_lib -ljpeg 2> /dev/null  ; then
+fi
+if test "$has_jpeg" = "no" ; then
+    jpeg_cflags="-I$local_inc/jpeg"
+    jpeg_lflags="-L$local_lib -ljpeg"
+    if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags 2> /dev/null  ; then
         has_jpeg="local"
     fi
 fi
 
+
+
 #look for OpenJPEG support
 cat > $TMPC << EOF
 #include <stdio.h>
@@ -856,64 +1006,76 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -lopenjpeg 2> /dev/null  ; then
-    has_openjpeg="system"
-elif test "$alt_macosx_dir" != "" ; then
-    if cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -ljpeg 2> /dev/null ; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -lopenjpeg 2> /dev/null  ; then
         has_openjpeg="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -ljpeg 2> /dev/null ; then
+            has_openjpeg="system"
+        fi
+    fi
+fi
+
+if test "$has_openjpeg" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/openjpeg -L$local_lib -lopenjpeg 2> /dev/null  ; then
+        has_openjpeg="local"
     fi
-elif $cc -o $TMPO $TMPC -I$local_inc/openjpeg -L$local_lib -lopenjpeg 2> /dev/null  ; then
-    has_openjpeg="local"
 fi
 
+
+
 #look for PNG support
 cat > $TMPC << EOF
 #include <png.h>
 int main( void ) { return 0; }
 EOF
 
-if test "$cross_prefix"  != "" ; then
+if test "$cross_prefix" = "" ; then
     png_cflags="-I$prefix/include"
     png_lflags="-L$prefix/lib -lpng -lz"
     #-nostdlib prevents from searching standard compiler libraries
     #if $cc -o $TMPO $TMPC -nostdlib $png_cflags $png_lflags 2> /dev/null  ; then
-    if $cc -o $TMPO $TMPC $png_cflags $png_lflags 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC $png_cflags $png_lflags $LDFLAGS 2> /dev/null  ; then
         has_png="system"
-    else
-        png_cflags="-I$local_inc/png"
-        png_lflags="-L$local_lib -lpng"
-        if $cc -o $TMPO $TMPC $png_cflags $png_lflags 2> /dev/null  ; then
-            has_png="local"
-        fi
-    fi
-else
-    if $cc -o $TMPO $TMPC -lpng -lz 2> /dev/null  ; then
+    elif $cc -o $TMPO $TMPC $LDFLAGS -lpng -lz 2> /dev/null  ; then
         has_png="system"
     elif test "$alt_macosx_dir" != "" ; then
-        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lpng 2> /dev/null ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lpng 2> /dev/null ; then
             has_png="system"
         fi
-    elif $cc -o $TMPO $TMPC -I$local_inc/png -L$local_lib -lpng 2> /dev/null  ; then
+    fi
+fi
+if test "$has_png" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/png -L$local_lib -lpng 2> /dev/null  ; then
         has_png="local"
     fi
 fi
 
+
+
 #look for MAD support
 cat > $TMPC << EOF
 #include <mad.h>
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -lmad 2> /dev/null  ; then
-    has_mad="system"
-elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lmad 2> /dev/null ; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -lmad 2> /dev/null  ; then
         has_mad="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lmad 2> /dev/null ; then
+            has_mad="system"
+        fi
+    fi
+fi
+if test "$has_mad" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/mad -L$local_lib -lmad 2> /dev/null  ; then
+        has_mad="local"
     fi
-elif $cc -o $TMPO $TMPC -I$local_inc/mad -L$local_lib -lmad 2> /dev/null  ; then
-    has_mad="local"
 fi
 
+
+
 #look for A52DEC support
 cat > $TMPC << EOF
 #define uint32_t unsigned int
@@ -923,15 +1085,22 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -la52 2> /dev/null  ; then
-    has_a52="system"
-elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -la52 2> /dev/null ; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -la52 2> /dev/null  ; then
         has_a52="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -la52 2> /dev/null ; then
+            has_a52="system"
+        fi
     fi
-elif $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -la52 2> /dev/null  ; then
-    has_a52="local"
 fi
+if test "$has_a52" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -la52 2> /dev/null  ; then
+        has_a52="local"
+    fi
+fi
+
+
 
 #look for XVID support
 cat > $TMPC << EOF
@@ -939,47 +1108,57 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if test "$cross_prefix"  != "" ; then
-    if $cc -o $TMPO $TMPC -I$prefix/include -L$prefix/lib -lxvidcore -lpthread 2> /dev/null  ; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC -I$prefix/include -L$prefix/lib $LDFLAGS -lxvidcore -lpthread 2> /dev/null  ; then
         has_xvid="system"
-    elif $cc -o $TMPO $TMPC -I$local_inc/xvid -L$local_lib -lxvidcore -lpthread 2> /dev/null  ; then
-        has_xvid="local"
-    fi
-else
-    if $cc -o $TMPO $TMPC -lxvidcore -lpthread 2> /dev/null  ; then
+    elif $cc -o $TMPO $TMPC $LDFLAGS -lxvidcore -lpthread 2> /dev/null  ; then
         has_xvid="system"
     elif test "$alt_macosx_dir" != "" ; then
-        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lxvidcore -lpthread 2> /dev/null ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lxvidcore -lpthread 2> /dev/null ; then
             has_xvid="system"
         fi
-    elif $cc -o $TMPO $TMPC -I$local_inc/xvid -L$local_lib -lxvidcore -lpthread 2> /dev/null  ; then
+    fi
+fi
+if test "$has_xvid" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/xvid -L$local_lib -lxvidcore -lpthread 2> /dev/null  ; then
         has_xvid="local"
     fi
 fi
 
+
+
 #look for FAAD support
 cat > $TMPC << EOF
 #include <faad.h>
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -lfaad -lm 2> /dev/null  ; then
-    has_faad="system"
-elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lfaad 2> /dev/null ; then
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -lfaad -lm 2> /dev/null  ; then
         has_faad="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lfaad 2> /dev/null ; then
+            has_faad="system"
+        fi
     fi
-elif $cc -o $TMPO $TMPC -I$local_inc/faad -L$local_lib -lfaad -lm 2> /dev/null  ; then
-    has_faad="local"
 fi
+if test "$has_faad" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/faad -L$local_lib -lfaad -lm 2> /dev/null  ; then
+        has_faad="local"
+    fi
+fi
+
 
 
 #look for FFMPEG support
 
-if pkg-config --exists libavcodec libavformat libswscale 2> /dev/null  ; then
-    ffmpeg_cflags=`pkg-config --cflags libavcodec libavformat libswscale libavutil`
-    ffmpeg_lflags=`pkg-config --libs libavcodec libavformat libswscale libavutil`
+if $pkg_config --exists libavcodec libavformat libswscale 2> /dev/null  ; then
+    ffmpeg_cflags=`$pkg_config --cflags libavcodec libavformat libswscale libavutil`
+    ffmpeg_lflags=`$pkg_config --libs libavcodec libavformat libswscale libavutil`
     has_ffmpeg="system"
+else
+    ffmpeg_cflags=""
+    ffmpeg_lflags="-lz -lavcodec -lavformat"
 fi
 
 cat > $TMPC << EOF
@@ -987,7 +1166,7 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC $ffmpeg_cflags $ffmpeg_lflags 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC $ffmpeg_cflags $ffmpeg_lflags $LDFLAGS 2> /dev/null  ; then
     old_ffmpeg_inc="no"
 else
     old_ffmpeg_inc="yes"
@@ -996,34 +1175,53 @@ else
 #include <ffmpeg/avcodec.h>
 int main( void ) { return 0; }
 EOF
+
 fi
 
-if test "$cross_prefix"  != "" ; then 
-    if $cc -o $TMPO $TMPC -I$prefix/include -L$prefix/lib -lz -lavcodec -lavformat -lavutil 2> /dev/null  ; then
+if test "$cross_prefix" = "" ; then 
+    if $cc -o $TMPO $TMPC -I$prefix/include -L$prefix/lib $ffmpeg_lflags $LDFLAGS 2> /dev/null  ; then
         has_ffmpeg="system"
         ffmpeg_cflags="-I$prefix/include"
-        ffmpeg_lflags="-L$prefix/lib -lz -lavcodec -lavformat -lavutil"
-    else
-        if $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -lz -lavcodec -lavformat 2> /dev/null  ; then
-            has_ffmpeg="local"
-            ffmpeg_cflags="-I$local_inc/include"
-            ffmpeg_lflags="-L$local_lib/lib -lz -lavcodec -lavformat -lavutil"
-            echo OK 
-        fi
-    fi
-else
-    if $cc -o $TMPO $TMPC -lz -lavcodec -lavformat 2> /dev/null  ; then
+        ffmpeg_lflags="-L$prefix/lib $ffmpeg_lflags"
+    elif $cc -o $TMPO $TMPC $ffmpeg_lflags $LDFLAGS 2> /dev/null  ; then
         has_ffmpeg="system"
     elif test "$alt_macosx_dir" != "" ; then
-        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lz -lavcodec -lavformat 2> /dev/null ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $ffmpeg_lflags $LDFLAGS 2> /dev/null ; then
             has_ffmpeg="system"
             ffmpeg_cflags="-I$alt_macosx_dir/include"
-            ffmpeg_lflags="-L$alt_macosx_dir/lib -lz -lavcodec -lavformat"
+            ffmpeg_lflags="-L$alt_macosx_dir/lib $ffmpeg_lflags"
         fi
-    elif $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -lz -lavcodec -lavformat 2> /dev/null  ; then
+    fi
+fi
+if test "$has_ffmpeg" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc -L$local_lib $ffmpeg_lflags 2> /dev/null  ; then
         has_ffmpeg="local"
         ffmpeg_cflags="-I$local_inc"
-        ffmpeg_lflags="-L$local_lib -lz -lavcodec -lavformat -lavutil"
+        ffmpeg_lflags="-L$local_lib $ffmpeg_lflags"
+    fi
+fi
+
+
+
+#look for MAD support
+has_freenect="no"
+cat > $TMPC << EOF
+#include <libfreenect/libfreenect.h>
+int main( void ) { return 0; }
+EOF
+
+if test "$cross_prefix" = "" ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -lfreenect 2> /dev/null  ; then
+        has_freenect="system"
+    elif test "$alt_macosx_dir" != "" ; then
+        if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lfreenect 2> /dev/null ; then
+            has_freenect="system"
+        fi
+    fi
+fi
+if test "$has_freenect" = "no" ; then
+    if $cc -o $TMPO $TMPC -I$local_inc/mad -L$local_lib -lfreenect 2> /dev/null  ; then
+        has_freenect="local"
     fi
 fi
 
@@ -1034,42 +1232,46 @@ cat > $TMPC << EOF
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -lvorbis 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC $LDFLAGS -lvorbis 2> /dev/null  ; then
     has_vorbis="system"
 elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -lvorbis 2> /dev/null ; then
+    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lvorbis 2> /dev/null ; then
         has_vorbis="system"
     fi
 elif $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -lvorbis -lm 2> /dev/null  ; then
     has_vorbis="local"
 fi
 
+
+
 #look for theora support
 cat > $TMPC << EOF
 #include <theora/theora.h>
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -ltheora 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC $LDFLAGS -ltheora 2> /dev/null  ; then
     has_theora="system"
 elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -ltheora -logg 2> /dev/null ; then
+    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -ltheora -logg 2> /dev/null ; then
         has_theora="system"
     fi
 elif $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -ltheora -logg -lm 2> /dev/null  ; then
     has_theora="local"
 fi
 
+
+
 #look for OGG support
 cat > $TMPC << EOF
 #include <ogg/ogg.h>
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPC -logg 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC $LDFLAGS -logg 2> /dev/null  ; then
     has_ogg="system"
 elif test "$alt_macosx_dir" != "" ; then
-    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib -logg 2> /dev/null ; then
+    if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -logg 2> /dev/null ; then
         has_ogg="system"
     fi
 elif $cc -o $TMPO $TMPC -I$local_inc -L$local_lib -logg -lm 2> /dev/null  ; then
@@ -1080,15 +1282,15 @@ else
 fi
 
 
-#look for OSS support
 
+#look for OSS support
 if test "$darwin" = "yes" ; then
-
     cat > $TMPC << EOF
 #include <soundcard.h>
 int main( void ) { return 0; }
 EOF
-    if $cc -o $TMPO $TMPC -DLIBOSS_INTERNAL -I$alt_macosx_dir/include/ -I$alt_macosx_dir/include/liboss -L$alt_macosx_dir/lib -loss 2> /dev/null ; then
+
+    if $cc -o $TMPO $TMPC -DLIBOSS_INTERNAL -I$alt_macosx_dir/include/ -I$alt_macosx_dir/include/liboss -L$alt_macosx_dir/lib -loss $LDFLAGS 2> /dev/null ; then
         has_oss_audio="SYS"
         OSS_CFLAGS="-DLIBOSS_INTERNAL -I$alt_macosx_dir/include/ -I$alt_macosx_dir/include/liboss"
         OSS_LDFLAGS="-L$alt_macosx_dir/lib -loss"
@@ -1114,7 +1316,8 @@ EOF
 #include <soundcard.h>
 int main( void ) { return 0; }
 EOF
-        if $cc -o $TMPO $TMPC 2> /dev/null  ; then
+
+        if $cc -o $TMPO $TMPC $LDFLAGS 2> /dev/null  ; then
             has_oss_audio="YES"
         fi
     fi
@@ -1122,6 +1325,7 @@ EOF
 fi
 
 
+
 #look for wxWidgets support
 has_wx="no"
 wx_too_old="no"
@@ -1167,18 +1371,19 @@ EOF
 fi
 #end wx test
 
-# If svg isn't disabled
+#if svg isn't disabled
 if test "$disable_svg" != "yes"; then
-    # Then we check libxm2 presence via pkg-config
-    if pkg-config libxml-2.0 --exists > /dev/null 2>&1  ; then
-        libxml2_cflags=`pkg-config libxml-2.0 --cflags`
-        libxml2_lib_flags=`pkg-config libxml-2.0 --libs`
+    #then check libxm2 presence via pkg-config
+    if $pkg_config libxml-2.0 --exists > /dev/null 2>&1  ; then
+        libxml2_cflags=`$pkg_config libxml-2.0 --cflags`
+        libxml2_lib_flags=`$pkg_config libxml-2.0 --libs`
         has_libxml2="yes"
     fi
 fi
 
 
-# look for IPv6
+
+#look for IPv6
 cat > $TMPC << EOF
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -1193,11 +1398,13 @@ IN6_IS_ADDR_MULTICAST( (struct in6_addr *) 0);
 }
 EOF
 
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_ipv6="yes"
 fi
 
-# look for DVB4linux
+
+
+#look for DVB4linux
 cat > $TMPC << EOF
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
@@ -1205,11 +1412,13 @@ int main( void ) {
 }
 EOF
 
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_dvb4linux="yes"
 fi
 
-# look for XMLRPC
+
+
+#look for XMLRPC
 cat > $TMPC << EOF
 #include <xmlrpc-c/base.h>
 #include <xmlrpc-c/server.h>
@@ -1218,58 +1427,70 @@ int main( void ) {
 }
 EOF
 
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_xmlrpc="yes"
 fi
 
-# look for alsa
+
+
+#look for alsa
 cat > $TMPC << EOF
-#include <alsa/asoundlib.h>          
+#include <alsa/asoundlib.h>
 int main( void ) {
 }
 EOF
 
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_alsa="yes"
 fi
 
-# look for pulseaudio
+
+
+#look for pulseaudio
 cat > $TMPC << EOF
 #include <pulse/pulseaudio.h>
 int main( void ) {
 }
 EOF
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_pulseaudio="yes"
 fi
 
+
+
 #look for jack
 cat > $TMPC << EOF
 #include <jack/jack.h>
 int main( void ) {
 }
 EOF
-if $cc -o $TMPE $TMPC > /dev/null 2>&1  ; then
+if $cc -o $TMPE $TMPC $LDFLAGS > /dev/null 2>&1  ; then
     has_jack="yes"
 fi
 
+
+
 #look for directfb support
 cat > $TMPC << EOF
-#include <directfb/directfb.h>
+#include <directfb.h>
 int main( void ) { return 0; }
 EOF
-directfb_inc="/opt/STM/STLinux-2.3/devkit/sh4/target/usr/include/directfb"
+directfb_inc="/usr/include/directfb"
 directfb_lib="-ldirectfb -lfusion -ldirect"
-if $cc -o $TMPO $TMPC -I$directfb_inc -L$directfb_lib 2> /dev/null  ; then
+if $cc -o $TMPO $TMPC -I$directfb_inc -L$directfb_lib $LDFLAGS 2> /dev/null  ; then
     has_directfb="yes"
 fi
 
+
+
 #look for X11 shared memory support
 cat > $TMPC << EOF
 #include <X11/Xlib.h>
 int main( void ) { return 0; }
 EOF
-if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib 2> /dev/null  ; then
+
+if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib $LDFLAGS 2> /dev/null  ; then
     has_x11="yes"
 
     #look for X11 shared memory support
@@ -1281,7 +1502,7 @@ if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib 2> /dev/null  ; then
 int main( void ) { return 0; }
 EOF
 
-    if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib $LDFLAGS 2> /dev/null  ; then
         has_x11_shm="yes"
     fi
 
@@ -1293,12 +1514,15 @@ EOF
 int main( void ) { return 0; }
 EOF
 
-    if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib $LDFLAGS 2> /dev/null  ; then
         has_x11_xv="yes"
     fi
 
 fi
 
+
+
+#overwrite detection with manual settings
 for opt do
     case "$opt" in
         --sdl-cfg=*) sdl_path=`echo $opt | cut -d '=' -f 2`; sdl_local="yes"
@@ -1329,22 +1553,18 @@ for opt do
             ;;
         --disable-jack=*) has_jack="no"
             ;;
-        --disable-alsa=*) has_alsa="no"
-            ;;
-        --enable-debug) debuginfo="yes"; no_gcc_opt="yes"
+        --disable-alsa) has_alsa="no"
             ;;
         --enable-gprof) gprof_build="yes";
             ;;
         --enable-static-bin) static_build="yes";
             ;;
-        --enable-pic) want_pic="yes";
-            ;;
-        --disable-opt) no_gcc_opt="yes"
-            ;;
         --disable-ipv6) has_ipv6="no"
             ;;
         --disable-wx) has_wx="no"
             ;;
+        --disable-platinum) has_platinum="no"
+            ;;
         --disable-oss-audio) has_oss_audio="no"
             ;;
         --disable-x11-shm) has_x11_shm="no"
@@ -1383,10 +1603,12 @@ for opt do
             ;;
         --use-ffmpeg=*) has_ffmpeg=${opt#--use-ffmpeg=}
             ;;
+        --use-freenect=*) has_freenect=${opt#--use-freenect=}
+            ;;
         --use-png=*) tmp_has_png=${opt#--use-png=}
             if test "$tmp_has_png" = "system" ; then
                 if test "$has_png"  != "system" ; then
-                    if test "$cross_prefix"  != "" ; then
+                    if test "$cross_prefix" != "" ; then
                         echo 
                         echo "WARNING: PNG has been forced to system, but we are cross-compiling, it will have to be on target"
                         echo 
@@ -1399,6 +1621,22 @@ for opt do
             fi
             has_png=$tmp_has_png
             ;;
+        --use-zlib=*) tmp_has_zlib=${opt#--use-zlib=}
+            if test "$tmp_has_zlib" = "system" ; then
+                if test "$has_zlib"  != "system" ; then
+                    if test "$cross_prefix" != "" ; then
+                        echo 
+                        echo "WARNING: ZLIB has been forced to system, but we are cross-compiling, it will have to be on target"
+                        echo 
+                    else
+                        echo 
+                        echo "WARNING!! : ZLIB has been forced to system even though it hasn't been found in this host"
+                        echo 
+                    fi
+                fi
+            fi
+            has_png=$tmp_has_png
+            ;;
         --use-ogg=*) has_ogg=${opt#--use-ogg=}
             ;;
         --use-vorbis=*) has_vorbis=${opt#--use-vorbis=}
@@ -1412,7 +1650,7 @@ for opt do
         --enable-pulseaudio=*) has_pulseaudio="yes"
             ;;
 
-        --disable-all) has_pulseaudio="no"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_beng="yes"; disable_qtvr="yes";  disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"
+        --disable-all) has_pulseaudio="no"; has_alsa="no"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_beng="yes"; disable_qtvr="yes";  disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"
             ;;
 
         --disable-3d) disable_3d="yes"
@@ -1475,6 +1713,8 @@ for opt do
             ;;
         --enable-m2ts-mux) disable_m2ts_mux="no"
             ;;
+        --disable-dvb4linux) has_dvb4linux="no"
+            ;;
         --disable-parsers) disable_parsers="yes"
             ;;
         --enable-parsers) disable_parsers="no"
@@ -1542,14 +1782,15 @@ for opt do
         --disable-streaming) disable_streaming="yes"
             ;;
         --enable-streaming) disable_streaming="no"
-            ;;
+            ;; 
 
 
     esac
 done
 
-#look for OpenGL support or for TinyGL support
 
+
+#look for OpenGL support or for TinyGL support
 LINK3D=""
 INCL3D=""
 DarwinGL="no"
@@ -1560,12 +1801,14 @@ if test "$darwin" = "yes" ; then
 #include <OpenGL/glu.h>
 int main( void ) { glEnable(GL_NORMALIZE); return 0; }
 EOF
+
 else
     cat > $TMPC << EOF
 #include <GL/gl.h>
 #include <GL/glu.h>
 int main( void ) { glEnable(GL_NORMALIZE); return 0; }
 EOF
+
 fi
 
 if test "$disable_3d" = "no" ; then
@@ -1581,9 +1824,9 @@ if test "$disable_3d" = "no" ; then
     else
         LINK3D="-lGL -lGLU -lX11"
     fi
-    if $cc -o $TMPO $TMPC $LINK3D 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC $LINK3D $LDFLAGS 2> /dev/null  ; then
         has_opengl="yes"
-    elif $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib 2> /dev/null  ; then
+    elif $cc -o $TMPO $TMPC -I$X11_PATH/include -L$X11_PATH/lib $LDFLAGS 2> /dev/null  ; then
         has_opengl="yes"
         INCL3D="-I$X11_PATH/include"
         LINK3D="-L$X11_PATH/lib $LINK3D"
@@ -1597,8 +1840,9 @@ cat > $TMPC << EOF
 #include <GL/gl.h>
 int main( void ) { int a ; a = TINYGL ; }
 EOF
+
 if test "$enable_tinygl" = "yes"  ;then
-    if $cc -o $TMPO $TMPC -lTinyGL 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS -lTinyGL 2> /dev/null  ; then
         has_tinygl="yes"
         has_opengl="yes"
         LINK3D="-lTinyGL"
@@ -1606,24 +1850,25 @@ if test "$enable_tinygl" = "yes"  ;then
 fi
 
 
+
 #look for GECKO support
 cat > $TMPCPP << EOF
 #include <npapi.h>
 int main( void ) { return 0; }
 EOF
 
-if $cc -o $TMPO $TMPCPP -I$xulsdk_path $CFLAGS $LDFLAGS 2> /dev/null  ; then
+if $cc -o $TMPO $TMPCPP -I$xulsdk_path $LDFLAGS 2> /dev/null  ; then
     has_xul="system"
     xul_flags="-I$xulsdk_path $xul_flags"
 else
-    if $cc -o $TMPO $TMPCPP $xul_flags -I$local_inc/gecko-sdk/include 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPCPP $xul_flags -I$local_inc/gecko-sdk/include $LDFLAGS 2> /dev/null  ; then
         has_xul="local"
         xul_flags="-I$local_inc/gecko-sdk/include $xul_flags"
     else
         #xulrunner directories are sometimes included through js packages
         if test "$has_js" = "system"  ;then
-            if $cpp -o $TMPO $TMPCPP $js_flags $js_lib_pkg 2> /dev/null  ; then
-                xul_flags=`pkg-config --cflags mozilla-js`
+            if $cpp -o $TMPO $TMPCPP $js_flags $js_lib_pkg $LDFLAGS 2> /dev/null  ; then
+                xul_flags=`$pkg_config --cflags mozilla-js`
                 has_xul="system"
             fi
         fi
@@ -1631,28 +1876,19 @@ else
 fi
 
 
+
 #look for joystick support
 cat > $TMPC << EOF
 #include <linux/joystick.h>
 int main( void ) { return 0; }
 EOF
 if test "$enable_joystick" = "yes"  ;then
-    if $cc -o $TMPO $TMPC  2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS  2> /dev/null  ; then
         has_joystick="yes"
     fi
 fi
 
 
-#GCC opt
-if test "$no_gcc_opt" = "no"; then
-    if $cc --version | grep 'sbox-arm-linux-gcc (GCC) 3.4.4'
-    then
-        echo "Detected buggy arm GCC (diablo), using -O2"
-        CFLAGS="-O2 $CFLAGS"
-    else
-        CFLAGS="-O3 $CFLAGS"
-    fi
-fi
 
 #look for DX support
 dx_path="system"
@@ -1664,7 +1900,7 @@ if test "$win32" = "yes" ; then
 int main( void ) { return 0; }
 EOF
 
-    if $cc -o $TMPO $TMPC 2> /dev/null  ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS 2> /dev/null  ; then
         has_mingw_directx="yes"
     else
         dx_path="$dxsdk_path"
@@ -1676,6 +1912,7 @@ EOF
 fi
 
 
+
 #look for SDL support
 sdl_too_old=no
 has_sdl=no
@@ -1700,7 +1937,7 @@ EOF
     fi
     sdl_cflags=`$sdl_config --cflags`
 
-    if $cc -o $TMPO $sdl_cflags $TMPC $sdl_lib_flags  > /dev/null 2>&1  ; then
+    if $cc -o $TMPO $sdl_cflags $TMPC $LDFLAGS $sdl_lib_flags  > /dev/null 2>&1  ; then
         _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
         if test "$_sdlversion" -lt 121 ; then
             sdl_too_old=yes
@@ -1713,6 +1950,8 @@ fi
 #end SDL check
 
 
+
+#look at endianess
 if test -z "$cross_prefix" ; then
 
     # big/little endian test
@@ -1724,7 +1963,7 @@ return (*((uint8_t*)(&i))) == 0x67;
 }
 EOF
 
-    if $cc -o $TMPO $TMPC 2>/dev/null ; then
+    if $cc -o $TMPO $TMPC $LDFLAGS 2>/dev/null ; then
         $TMPO && bigendian="yes"
     else
         echo big/little endian test failed
@@ -1740,6 +1979,8 @@ else
 fi
 
 
+
+#man dir
 if test x"$mandir" = x""; then
     mandir="${prefix}/man"
 fi
@@ -1760,6 +2001,8 @@ if test "$cpu" = "sh4"; then
     fi
 fi
 
+
+
 #prepare for config.h writing
 TMPH="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}.h"
 echo "/* Automatically generated by configure */" > $TMPH
@@ -1767,7 +2010,6 @@ echo "#ifndef GF_CONFIG_H" >> $TMPH
 echo "#define GF_CONFIG_H" >> $TMPH
 echo "#define GPAC_CONFIGURATION \"$GPAC_CONFIGURATION\"" >> $TMPH
 
-
 version="`grep '#define GPAC_VERSION ' \"$source_path/include/gpac/tools.h\" | cut -d '"' -f 2`"
 
 if which svnversion >/dev/null
@@ -1782,8 +2024,8 @@ echo ""
 echo "** System Configuration"
 echo "Install prefix: $prefix"
 echo "Source path: $source_path"
-echo "C   compiler: $cc"
-echo "C++ compiler: $cpp"
+echo "C   compiler: $cc_naked"
+echo "C++ compiler: $cpp_naked"
 echo "make: $make"
 echo "CPU: $cpu"
 echo "Big Endian: $bigendian"
@@ -1943,7 +2185,7 @@ if test "$win32" != "yes" ; then
     echo "PulseAudio Audio: $has_pulseaudio"
     echo "DirectFB support: $has_directfb"
     echo "X11 Shared Memory support: $has_x11_shm (path: $X11_PATH)"
-    echo "X11 XVideo support: $has_x11_xv"     
+    echo "X11 XVideo support: $has_x11_xv"
 fi
 
 echo "SDL Support: $has_sdl"
@@ -1988,6 +2230,8 @@ echo "FAAD: $has_faad"
 echo "XVID: $has_xvid"
 echo "FFMPEG: $has_ffmpeg"
 echo "Xiph OGG: $has_ogg"
+echo "Platinum UPnP: $has_platinum"
+echo "AVCap: $has_avcap"
 if test "$has_ogg" = "no"; then
     has_ogg="no"
 else
@@ -1995,6 +2239,8 @@ else
     echo "Xiph Theora: $has_theora"
 fi
 echo "A52 (AC3): $has_a52"
+echo "OpenSVCDecoder: $has_opensvc"
+echo "Freenect: $has_freenect"
 
 if test "$enable_renoir" = "yes" ; then
     echo "Renoir enabled - make sure the driver libraries are present in modules/viren_out directory"
@@ -2045,10 +2291,8 @@ if test "$gprof_build" = "yes"; then
     fi
 fi
 
-
-if test "$want_pic"  = "yes" ; then
-    CFLAGS="$CFLAGS -fPIC -DPIC"
-    CPPFLAGS="$CPPFLAGS -fPIC -DPIC"
+if test "$darwin" = "yes" ; then
+    CFLAGS="$CFLAGS_DIR $CFLAGS"
 fi
 
 ldir=`pwd`
@@ -2068,7 +2312,7 @@ echo "moddir_path=$prefix/$libdir/gpac" >> config.mak
 echo "mandir=$mandir" >> config.mak
 echo "tinygl_target_bin_dir=$target_bin_dir" >> config.mak
 echo "MAKE=$make" >> config.mak
-echo "CC=$cc" >> config.mak
+echo "CC=$cc_naked" >> config.mak
 echo "AR=$ar" >> config.mak
 echo "RANLIB=$ranlib" >> config.mak
 echo "STRIP=$strip" >> config.mak
@@ -2082,7 +2326,7 @@ echo "libdir=$libdir" >> config.mak
 
 
 #for cross-compilation
-if test "$cross_prefix"  != "" ; then
+if test "$cross_prefix" != "" ; then
     echo "CROSS_COMPILING=yes" >> config.mak
 fi
 
@@ -2162,6 +2406,10 @@ echo "CONFIG_JS=$has_js" >> config.mak
 if test "$has_js" = "no" ; then
     has_js="no"
 else
+    if test "$has_js" = "local" ; then
+        js_flags="-DXP_UNIX -I$local_inc/js"
+        js_lib="-ljs"
+    fi
     echo "JS_FLAGS=$js_flags" >> config.mak
     echo "JS_LIBS=$js_lib" >> config.mak
     echo "#define GPAC_HAS_SPIDERMONKEY" >> $TMPH
@@ -2199,6 +2447,7 @@ echo "CONFIG_ALSA=$has_alsa" >> config.mak
 echo "CONFIG_JACK=$has_jack" >> config.mak
 echo "CONFIG_A52=$has_a52" >> config.mak
 echo "CONFIG_PULSEAUDIO=$has_pulseaudio" >> config.mak
+echo "CONFIG_FREENECT=$has_freenect" >> config.mak
 
 echo "DISABLE_SVG=$disable_svg" >> config.mak
 echo "HAS_LIBXML2=$has_libxml2" >> config.mak
@@ -2269,6 +2518,20 @@ if test "$has_wx" = "yes"; then
     echo "WX_LFLAGS=$wx_lflags" >> config.mak
 fi
 
+echo "CONFIG_PLATINUM=$has_platinum" >> config.mak
+
+echo "CONFIG_AVCAP=$has_avcap" >> config.mak
+if test "$has_avcap" = "yes" ; then
+    echo "AVCAP_CFLAGS=$avcap_cflags" >> config.mak
+    echo "AVCAP_LDFLAGS=$avcap_ldflags" >> config.mak
+fi
+
+echo "CONFIG_OPENSVC=$has_opensvc" >> config.mak
+if test "$has_opensvc" = "yes" ; then
+    echo "OSVC_CFLAGS=$osvc_cflags" >> config.mak
+    echo "OSVC_LDFLAGS=$osvc_ldflags" >> config.mak
+fi
+
 echo "MOZILLA_DIR=$moz_path" >> config.mak
 
 echo "CONFIG_XUL=$has_xul" >> config.mak
@@ -2338,7 +2601,8 @@ echo "GPAC_ENST=$GPAC_ENST" >> config.mak
 echo "GPAC_ENST_INC=$GPAC_ENST" >> config.mak
 
 
-# build tree in object directory if source path is different from current one
+
+#build tree in object directory if source path is different from current one
 if test "$source_path_used" = "yes" ; then
 
     echo "Creating compilation tree image"
@@ -2394,27 +2658,43 @@ echo "LOCAL_INC_PATH=$local_inc" >> config.mak
 
 echo "#endif" >> $TMPH
 
-# Do not overwrite config.h if unchanged to avoid superfluous rebuilds.
-if ! cmp -s $TMPH config.h; then
+
+#do not overwrite config.h if unchanged to avoid superfluous rebuilds.
+if ! cmp -s $TMPH config.h ; then
     rm -f config.h
     mv -f $TMPH config.h
 else
     echo "config.h is unchanged"
 fi
 
+
 rm -f $TMPO $TMPC $TMPE $TMPS $TMPCPP $TMPH
 
-if [ ! -d "./bin" ]; then
+
+if [ ! -d "./bin" ] ; then
     mkdir ./bin
 fi
-if [ ! -d "./bin/gcc" ]; then
+if [ ! -d "./bin/gcc" ] ; then
     mkdir ./bin/gcc
 fi
-if [ ! -d "./bin/gcc/temp" ]; then
+if [ ! -d "./bin/gcc/temp" ] ; then
     mkdir ./bin/gcc/temp
 fi
 
 echo '%.opic : %.c' >> config.mak
 echo ' $(CC) $(CFLAGS) $(PIC_CFLAGS) -c $< -o $@' >> config.mak
 
+#pkg-config
+echo "prefix=$prefix"                           > gpac.pc
+echo "exec_prefix=\${prefix}"                  >> gpac.pc
+echo "libdir=\${exec_prefix}/lib"              >> gpac.pc
+echo "includedir=\${exec_prefix}/include"      >> gpac.pc
+echo ""                                                >> gpac.pc
+echo "Name: gpac"                              >> gpac.pc
+echo "Description: GPAC Multimedia Framework"  >> gpac.pc
+echo "URL: http://gpac.sourceforge.net"                >> gpac.pc
+echo "Version:$version"                                >> gpac.pc
+echo "Cflags: -I\${prefix}/include/gpac"       >> gpac.pc
+echo "Libs: -L\${libdir} -lgpac"               >> gpac.pc
+
 echo "Done - type 'make help' for make info, 'make' to build"
index 49025fe0f2093751bbb49f6d3cdef2bb31b2101b..b87b7e463754134ed6b07b356cf534abab7b2e96 100644 (file)
Binary files a/doc/configuration.html and b/doc/configuration.html differ
index 00b9854fc71ba877856d0e5d9ba87e5279da2900..8f927e662ec100d837a5fc5d982f7ab6c68b2b4a 100644 (file)
@@ -159,6 +159,9 @@ splits in files of desired maximum size. This will remove all MPEG-4 Systems med
 .B \-split-chunk start:end
 extracts a new file from specified start to end times (in seconds). This will remove all MPEG-4 Systems media. Alias: -splitx
 .TP
+.B \-splitz start:end
+same as -split-chunk option, but adjust end time to be juste before the last rap found in the chunk.
+.TP
 .B \-split-rap start:end
 splits in files begining at each RAP. This will remove all MPEG-4 Systems media. Alias: -splitr
 .TP
index c7e58e1cb207b41d75c0f626789e04f2a61ba9ab..8ede331f82797627dd1d8b1878ff27c4493a2e4d 100644 (file)
@@ -28,6 +28,61 @@ removes script message, buffering and downloading status.
 .TP
 .B \-strict-error
 exits after the first error is reported.
+.TP
+.B \-log-file FILE
+specifies where to write logs. Default is stdout. Same as -lf.
+.TP
+.B \-logs TOOLS
+sets log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@level. By default all errors are logged. level can be one of quiet, error, warning, info or debug. tool can be:
+.br
+core: libgpac core
+.br
+coding: bitstream formats (audio, video, scene)
+.br
+container: container formats (ISO File, MPEG-2 TS, AVI, ...)
+.br
+network: network data exept RTP trafic
+.br
+rtp: rtp trafic
+.br
+author: authoring tools (hint, import, export)
+.br
+sync: terminal sync layer
+.br
+codec: terminal codec messages
+.br
+parser: scene parsers (svg, xmt, bt) and other
+.br
+media: terminal media object management
+.br
+scene: scene graph and scene manager
+.br
+script: scripting engine messages
+.br
+interact: interaction engine (events, scripts, etc)
+.br
+smil: SMIL timing engine
+.br
+compose: composition engine (2D, 3D, etc)
+.br
+mmio: Audio/Video HW I/O management
+.br
+rti: various run-time stats
+.br
+cache: HTTP cache subsystem
+.br
+audio: Audio renderer and mixers
+.br
+mem: GPAC memory tracker
+.br
+module: GPAC modules debugging
+.br
+mutex: mutex
+.br
+none: no tool logged
+.br
+all: all tools logged - other tools can be specified afterwards.
+.br
 .
 .SH PLAYBACK OPTIONS
 A file can be controled during playback by typing one of the following key at prompt.
diff --git a/extra_lib/include/OpenSVCDecoder/ControlLayer.h b/extra_lib/include/OpenSVCDecoder/ControlLayer.h
new file mode 100644 (file)
index 0000000..789b2ec
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************\r
+   *\r
+   *  SVC4DSP developped in IETR image lab\r
+   *\r
+   *\r
+   *\r
+   *              Médéric BLESTEL <mblestel@insa-rennes.Fr>\r
+   *              Mickael RAULET <mraulet@insa-rennes.Fr>\r
+   *              http://www.ietr.org/\r
+   *\r
+   *\r
+   *\r
+   *\r
+   *\r
+   * This library is free software; you can redistribute it and/or\r
+   * modify it under the terms of the GNU Lesser General Public\r
+   * License as published by the Free Software Foundation; either\r
+   * version 2 of the License, or (at your option) any later version.\r
+   *\r
+   * This library is distributed in the hope that it will be useful,\r
+   * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+   * Lesser General Public License for more details.\r
+   *\r
+   * You should have received a copy of the GNU Lesser General Public\r
+   * License along with this library; if not, write to the Free Software\r
+   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
+   *\r
+   *\r
+   * $Id$\r
+   *\r
+   **************************************************************************/\r
+\r
+#define WINEXPORT\r
+\r
+#ifdef TCPMP\r
+#ifndef POCKET_PC\r
+#include "windows.h"\r
+#undef WINEXPORT\r
+#define WINEXPORT WINAPI\r
+#endif\r
+#endif\r
+\r
+\r
+void getLayer(int *num_layer);\r
diff --git a/extra_lib/include/OpenSVCDecoder/ParseAU.h b/extra_lib/include/OpenSVCDecoder/ParseAU.h
new file mode 100644 (file)
index 0000000..c9119ad
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************\r
+*\r
+*  SVC4DSP developped in IETR image lab\r
+*\r
+*\r
+*\r
+*              Médéric BLESTEL <mblestel@insa-rennes.Fr>\r
+*              Mickael RAULET <mraulet@insa-rennes.Fr>\r
+*              http://www.ietr.org/\r
+*\r
+*\r
+*\r
+*\r
+*\r
+* This library is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU Lesser General Public\r
+* License as published by the Free Software Foundation; either\r
+* version 2 of the License, or (at your option) any later version.\r
+*\r
+* This library is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+* Lesser General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU Lesser General Public\r
+* License along with this library; if not, write to the Free Software\r
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
+*\r
+*\r
+* $Id$\r
+*\r
+**************************************************************************/\r
+\r
+\r
+\r
+void ParseAuPlayers(void *PlayerStruct, const unsigned char *buf, int buf_size, int nal_length_size, int is_avc);\r
+int GetDqIdMax(const unsigned char *buf, int buf_size, int nal_length_size, int *DqidTable, int is_avc);\r
+int Geth264NalSize(const unsigned char *buf, int buf_size, int *bufindex);\r
+\r
diff --git a/extra_lib/include/OpenSVCDecoder/SVCDecoder_ietr_api.h b/extra_lib/include/OpenSVCDecoder/SVCDecoder_ietr_api.h
new file mode 100644 (file)
index 0000000..4f3c7d0
--- /dev/null
@@ -0,0 +1,128 @@
+/*****************************************************************************\r
+*\r
+*  SVC4DSP developped in IETR image lab\r
+*\r
+*\r
+*\r
+*              Médéric BLESTEL <mblestel@insa-rennes.Fr>\r
+*              Mickael RAULET <mraulet@insa-rennes.Fr>\r
+*              http://www.ietr.org/\r
+*\r
+*\r
+*\r
+*\r
+*\r
+* This library is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU Lesser General Public\r
+* License as published by the Free Software Foundation; either\r
+* version 2 of the License, or (at your option) any later version.\r
+*\r
+* This library is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+* Lesser General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU Lesser General Public\r
+* License along with this library; if not, write to the Free Software\r
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
+*\r
+*\r
+* $Id$\r
+*\r
+**************************************************************************/\r
+\r
+#ifndef _SVCDecoder_ietr_api_h\r
+#define _SVCDecoder_ietr_api_h\r
+\r
+#define WINEXPORT\r
+\r
+#include "SvcInterface.h"\r
+\r
+#ifndef POCKET_PC\r
+#ifdef TCPMP\r
+#include "windows.h"\r
+#undef WINEXPORT\r
+#define WINEXPORT WINAPI\r
+#endif\r
+#endif\r
+\r
+enum {\r
+       SVC_STATUS_ERROR        = -1,\r
+       SVC_STATUS_OK       = 0,        // no error and no frame ready\r
+       SVC_IMAGE_READY     = 1,        // no error and image ready\r
+       SVC_GHOST_IMAGE         = 2             // no image for chosen layer but image could be ready for other layers\r
+};\r
+\r
+\r
+/*======================================================================================================\r
+int SVCDecoder_init();\r
+This method initializes the internal resources of the decoder\r
+@return SVC_STATUS_OK if creation is successful\r
+======================================================================================================*/\r
+int WINEXPORT SVCDecoder_init(void **PlayerStruct);\r
+\r
+\r
+/*======================================================================================================\r
+void WINEXPORT UpdateLayer(int *DqIdTable, int *CurrDqId, int MaxDqId, int Command);\r
+Use this method to change of quality, spatial or temporal scalability during the \r
+decoding process.\r
+The DqIdTable specifies the DqId of each layer present into the stream.\r
+CurrDqId specifies the DqId of the current layer.\r
+MaxDqId specifies the maximal DqId present into the access unit.\r
+Command specifies the action to execute:\r
+0: To switch down of spatial or quality scalability\r
+1: To switch up of spatial or quality scalability \r
+2: To switch up to the layer with the higthest DqId\r
+3: To switch down of temporal scalability\r
+4: To switch up of temproal scalability\r
+@return nothing\r
+=======================================================================================================*/\r
+void WINEXPORT UpdateLayer(int *DqIdTable, int *CurrDqId, int *TemporalCom, int *TemporalId, int MaxDqId, int Command);\r
+\r
+\r
+\r
+/*======================================================================================================\r
+void WINEXPORT SetCommandLayer(int *Command, int DqIdMax, int CurrDqId, int *TemporalCom, int TemporalId);\r
+Use this method to generate the right command for the SVC decoder.\r
+The Command is a 4 size table given to the decoder.\r
+DqIdMax specifies the maximal DqId present into the access unit.\r
+CurrDqId specifies the DqId of the current layer.\r
+TemporalCom is the command to use concerning the temporal scalability.\r
+0 -> do nothing\r
+1 -> decode a lower temporal scalability.\r
+2 -> decode a highter temporal scalability.\r
+3 -> define a specific temporal scalability. (use TemporalId variable to set).\r
+@return nothing\r
+=======================================================================================================*/\r
+void WINEXPORT SetCommandLayer(int *Command, int DqIdMax, int CurrDqId, int *TemporalCom, int TemporalId);\r
+\r
+\r
+/*======================================================================================================\r
+int decodeNAL( unsigned char* nal, int nal_length, OPENSVCFRAME *Frame, int DqIdMax);\r
+Use this method to give a new NAL Unit to the decoder. The NAL content (no start code)\r
+is stored at the address given by the argument pNAL and the length of the NAL is provided \r
+by the argument nal_length. Memory of this nal buffer is managed by the application.\r
+If the function returns the code SVC_IMAGE_READY, this means that an image is ready and in this case, \r
+the arguments *Frame has been updated by the decoder and the image plans are contained at \r
+the addresses pY, PU, pV.\r
+The image stored at these location is an image centered in a rectangle of size (*pWidth + 32, *pHeight + 32)\r
+for Y and ((*pWidth + 32) / 2, (*pHeight + 32) / 2)) for U and V.\r
+Memory of these image buffers is managed by the decoder.\r
+In case of a SVC stream, the largest DqIq of the Access Unit should be given.\r
+\r
+@param nal is the address of the buffer that contains the NAL unit\r
+@param nal_length is the size of NAL Unit data\r
+@param Frame Contains all parameters from the displayed picture\r
+@param DQIdMax is the largest DQId of the current access unit\r
+@return SVC_STATUS_OK or SVC_STATUS_ERROR or SVC_IMAGE_READY or SVC_GHOST_IMAGE\r
+======================================================================================================*/\r
+int WINEXPORT decodeNAL(void *PlayerStruct, unsigned char* nal, int nal_length, OPENSVCFRAME *Frame, int *LayerCommand); \r
+\r
+\r
+/*======================================================================================================\r
+int SVCDecoder_close();\r
+This method releases the internal resources of the decoder\r
+@return SVC_STATUS_OK if creation is successfull\r
+=======================================================================================================*/\r
+int WINEXPORT SVCDecoder_close(void *PlayerStruct);\r
+#endif // SVCDecoder_ietr_api\r
diff --git a/extra_lib/include/OpenSVCDecoder/SvcInterface.h b/extra_lib/include/OpenSVCDecoder/SvcInterface.h
new file mode 100644 (file)
index 0000000..03f6664
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************\r
+*\r
+*  SVC4DSP developped in IETR image lab\r
+*\r
+*\r
+*\r
+*              Médéric BLESTEL <mblestel@insa-rennes.Fr>\r
+*              Mickael RAULET <mraulet@insa-rennes.Fr>\r
+*              http://www.ietr.org/\r
+*\r
+*\r
+*\r
+*\r
+*\r
+* This library is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU Lesser General Public\r
+* License as published by the Free Software Foundation; either\r
+* version 2 of the License, or (at your option) any later version.\r
+*\r
+* This library is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+* Lesser General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU Lesser General Public\r
+* License along with this library; if not, write to the Free Software\r
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
+*\r
+*\r
+* $Id$\r
+*\r
+**************************************************************************/\r
+\r
+#ifndef SVCINTERFACE_H\r
+#define SVCINTERFACE_H\r
+\r
+#define QoE_\r
+\r
+#ifdef QoE\r
+#include "SvcToQoE.h"\r
+#endif\r
+\r
+\r
+typedef struct{\r
+\r
+       int Width;                              //Output frame width\r
+       int Height;                             //Output frame height\r
+       unsigned char* pY[1];   //Output frame Y\r
+       unsigned char* pU[1];   //Output frame U\r
+       unsigned char* pV[1];   //Output frame V\r
+\r
+#ifdef QoE\r
+       SVCTOQOE *QoEData[1];   //QoE structure\r
+#endif\r
+\r
+} OPENSVCFRAME;\r
+\r
+\r
+#endif\r
diff --git a/extra_lib/include/avcap/CaptureDevice.h b/extra_lib/include/avcap/CaptureDevice.h
new file mode 100644 (file)
index 0000000..c0636b3
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef CAPTUREDEVICE_H_
+#define CAPTUREDEVICE_H_
+
+#include <string>
+#include <list>
+
+#include "avcap-export.h"
+#include "DeviceDescriptor.h"
+
+//! This is the namespace which contains all classes of the avcap-library.
+
+namespace avcap
+{
+       // forward declarations
+       class ConnectorManager;
+       class ControlManager;
+       class CaptureManager;
+       class DeviceDescriptor;
+       class FormatManager;
+
+       /*! \brief This class is an abstraction of a video capture device.
+        *
+        * It is the main entry point for an application to access the functionality of
+        * a capture device, i.e. to query capabilities and settings of the device, to
+        * manipulate them and to capture the video.
+        *
+        * The access to the functionality of a capture device is divided into different domains and is
+        * provided by so called managers. See the documentation of the various Manager-classes for
+        * the details of their usage. The managers and their responsibilities are:
+        *
+        * <ul>
+        * <li> CaptureManager: start/stop capture and register a capture-handler </li>
+        * <li> ConnectorManager: query available inputs/outputs of the device and get/set them</li>
+        * <li> ControlManager: query available controls of the device and get/set their values </li>
+        * <li> FormatManager: query and get/set available formats,
+        *      their properties and resolutions associated with them </li>
+        * </ul>
+        *
+        * CaptureDevice-classes implementing the back-end for a certain capture-API must derive from this class and
+        * implement the abstract methods to provide the API-specific manager-classes.
+        * However, if you want to use avcap only, you can use one of the following implementations,
+        * representing the supported, existing devices (depending on the operating system avcap has
+        * been build on, not all of them may be available and/or not all methods of their managers are implemented):
+        *
+        * <ul>
+        * <li> V4L2_Device (Linux): devices that are supported by a Video4Linux2-API driver
+        * (Requires read/write access to the /dev/video* -file of the device)</li>
+        * <li> V4L1_Device (Linux): devices that are supported by a Video4Linux-API driver
+        * (Requires read/write access to the /dev/video* -file of the device)</li>
+        * <li> AVC_Device (Linux): support for AV/C-Devices (e.g. DV-Cams).
+        * (Requires: libiec61883, libavc1394, librom1394, libraw1394 and read/write access to /dev/raw1394)</li>
+        * <li> QT_Device (MAC OS X): capture from a device using the QuickTime SampleGrabber </li>
+        * <li> DS_Device (Win32): capture from a device using a DirectShow filter-graph</li>
+        * </ul>
+        *
+        * A concrete CaptureDevice-object must not be created manually. A unique instance can be obtained by calling
+        * the method DeviceDescriptor::getDevice() between successive calls to DeviceDescriptor::open() and close().
+        * All available DeviceDescriptors representing the capture devices found on a system can be obtained by calling
+        * DeviceCollector::instance()->getDeviceList(). The CaptureDevice-object is owned by the DeviceDescriptor,
+        * so you must not delete the CaptureDevice instance.
+        *
+        */
+
+       class AVCAP_Export CaptureDevice
+       {
+       public:
+               //! Constructor
+               inline CaptureDevice()
+                       {}
+
+               //! Destructor
+               virtual inline ~CaptureDevice()
+                       {}
+
+               //! Return the descriptor of the device.
+               /*! \return The DeviceDescriptor-object.*/
+               virtual const DeviceDescriptor* getDescriptor() = 0;
+
+               //! Use this manager to start/stop capturing and to register a user defined CaptureHandler.
+               /*! \return The VidCapManager.*/
+               virtual CaptureManager* getVidCapMgr() = 0;
+
+               //! Use this manager to query available audio/video inputs/outputs and to select them.
+               /*! \return The ConnectorManager. */
+               virtual ConnectorManager* getConnectorMgr() = 0;
+
+               /*! Use this manager to query and to adjust the available controls of the device (e.g.
+                * brightness, contrast, saturation...).
+                * \return The ControlManager. */
+               virtual ControlManager* getControlMgr() = 0;
+
+               //! Use this manager to query the available formats, video standards and resolutions to select the desired ones.
+               /*! \return The FormatManager. */
+               virtual FormatManager* getFormatMgr() = 0;
+
+       private:
+               //! Open the device and do initialization. May fail, if already opened before.
+               /*! This method creates the managers. Don't use them before open() has been called.
+                * \return 0 if successful, -1 else
+                * */
+               virtual int open() = 0;
+
+               //! Close the device and do cleanup.
+               /*! All IOBuffers received by a capture-CallbackHandler should have called their
+                * release()-method, before close() is called to ensure propper cleanup. Usually this is guaranteed,
+                * if the buffer is released in the context of the capture-thread from within handleCapture().
+                * All managers are destroyed by this method and are thus not available anymore after calling close().
+                * \return 0 if successful, -1 else */
+               virtual int close() = 0;
+       };
+}
+
+#endif // CAPTUREDEVICE_H_
+
+/*! \mainpage avcap-library
+ *
+ * \section intro Introduction
+ *
+ * The avcap-library is a cross-API, cross-platform simple and easy to use C++
+ * video capture library. It's aim is to provide a unified API for
+ * Linux, Windows and Mac OS X to capture video from appropriate hardware. It hides the
+ * system specific quirks and issues of different API's used on different systems to access video
+ * capture hardware and hopefully helps to write portable capture-applications.
+ *
+ * \subsection linux Linux
+ * Under GNU/Linux the avcap-library supports Video4Linux-Devices, Video4Linux2-Devices and AV/C-Devices (e.g.
+ * DV-Cams) as capture sources. Note that you need read/write permission to the /dev/video* files
+ * to use V4L(2)-Devices. Usually it is sufficient, if the user is a member of the group that owns this files
+ * (usually group 'video'). To capture from AV/C-Devices the user needs read/write permission to /dev/raw1394. Membership
+ * in the group 'disk' should be sufficient here.
+ *
+ * \subsection windows Win32 (Implementation by Robin Luedtke, Nico Pranke)
+ * The Windows-version is basically a class wrapper for the DirectShow API and thus
+ * supports only devices with a WDM (Windows driver model) or an old VFW (Video for
+ * windows) compliant capture device driver. Understanding the avcap Win32 implementation
+ * may be a little difficult because of the following reasons:
+ * First, DirectShow is based on the Windows COM (component object model), second,
+ * in some cases, DirectShow is a little confusing (e.g. some DirectShow functions have a strange behavior -- workarounds
+ * are inevitable).
+ * In addition to this, VFW, WDM and even WDM devices itself are handled differently by DirectShow.
+ * Third, some important documentation is missing in the DirectShow documentation.\n \n
+ *
+ * \subsection mac Mac OS X
+ *
+ * The implementation for Darwin uses the QuickTime SequenceGrabber-Component and has been tested with the built-in
+ * iSight, various USB-cams and DV-Cams.
+ *
+ * \section install Building and Installation
+ *
+ * See the INSTALL file.
+ *
+ * \section Usage
+ *
+ * For an example on how to use the avcap-library take a look at the captest-program and read the documentation of
+ * class CaptureDevice to have a good starting point.
+ *
+ * \section licence Licence
+ *
+ * (c) 2005-2008 Nico Pranke <Nico.Pranke@googlemail.com>, Win32 implementation by Robin Luedtke <RobinLu@gmx.de> \n\n
+ *
+ * For non-commercial use, avcap is distributed under the GNU General Public License version 2. Refer to the file "COPYING" for details.
+ *
+ * For commercial use, please contact Nico Pranke <Nico.Pranke@googlemail.com> for licensing.
+*/
+
diff --git a/extra_lib/include/avcap/CaptureHandler.h b/extra_lib/include/avcap/CaptureHandler.h
new file mode 100644 (file)
index 0000000..29c1105
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef CAPTUREHANDLER_H_
+#define CAPTUREHANDLER_H_
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+       //! Abstract base class for capture handlers.
+
+       /*! If an application wants to capture data, it must implement a CaptureHandler and must register it
+        * with the VidCapManager of the CaptureDevice. The VidCapManager will call handleCaptureEvent() 
+        * always a new frame has been captured. If the buffer isn't used  
+        * anymore the IOBuffer::release() method must be called in order to enable the
+        * VidCapManager to reuse or release the buffer. */
+
+       class AVCAP_Export CaptureHandler
+       {
+       public:
+               //! Consturctor
+               inline CaptureHandler() 
+                       {}
+                       
+               //! Destructor
+               virtual inline ~CaptureHandler() 
+                       {}
+               
+               //! This method is called if a new frame has been captured by the VidCapManager.
+               /*! If the buffer isn't used anymore, then the method IOBuffer::release() must be
+                * called. 
+                * \param io_buf The buffer containing the captured frame. */
+               virtual void handleCaptureEvent(class IOBuffer* io_buf) = 0;
+       };
+}
+
+#endif // CAPTUREHANDLER_H_
diff --git a/extra_lib/include/avcap/CaptureManager.h b/extra_lib/include/avcap/CaptureManager.h
new file mode 100644 (file)
index 0000000..4a39ae6
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef CAPTUREMANAGER_H_
+#define CAPTUREMANAGER_H_
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include "avcap-config.h"
+#endif
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+       class CaptureHandler;
+       class IOBuffer;
+       
+       //! Abstract interface to access capture related tasks of a CaptureDevice.
+       
+       /*! An implementation of this class is provided by the API-specific CaptureDevice. 
+        * The CaptureManager can be used by applications to register a CaptureHandler and
+        * to start/stop the capture. There is only one CaptureHandler at the same time.
+        * To distribute the captured data to more than one interested sink is the responsibility 
+        * of the application. */
+       
+       class AVCAP_Export CaptureManager
+       {
+       public:
+               enum
+               {
+                       MAX_BUFFERS = 32,       //!< The maximum number of IOBuffers.
+                       DEFAULT_BUFFERS = 16    //!< The default number of used IOBuffers.
+               };
+               
+                       
+#ifdef AVCAP_LINUX
+               enum IOMethod
+               {
+                       IO_METHOD_NOCAP = 0,
+               IO_METHOD_READ,
+               IO_METHOD_MMAP,
+               IO_METHOD_USERPTR,
+               };
+#endif
+
+       private:
+               CaptureHandler* mCaptureHandler;
+               
+       public:
+               //! Constructor
+               inline CaptureManager() : mCaptureHandler(0)
+                       {}
+               
+               //! Destructor
+               virtual inline ~CaptureManager()
+                       {}
+               
+               //! Do basic initialization after startup.
+               virtual int init() = 0;
+               
+               //! Called before object destruction.
+               virtual int destroy() = 0;
+               
+               //! Start capturing data.
+               virtual int startCapture() = 0;
+               
+               //! Stop capturing data.
+               virtual int stopCapture() = 0;
+               
+               //! Register a capture handler.
+               /*! Only one capture handler can be registered at the same time.
+                * The handlers CaptureHandler::handleCaptureEvent() method will be called,
+                * if new data has been captured. The ownership of the handler remains at the caller.
+                * He is responsible for removing and deleting the handler. 
+                * \param handler The capture handler implementation.*/
+               virtual inline void registerCaptureHandler(CaptureHandler *handler) 
+                       { mCaptureHandler = handler; }
+
+               //! Remove the current capture handler.
+               /*! If a capture handler was registered before, then this handler will not be 
+                * notified anymore if data has been captured. */ 
+               virtual inline void removeCaptureHandler()
+                       { mCaptureHandler = 0; }
+               
+               //! Get the current CaptureHandler.
+               /*! Return the capture handler currently registered with registerCaptureHandler()
+                * or 0, if no handler was registered before.
+                * \return pointer to the capture handler */ 
+               virtual inline CaptureHandler* getCaptureHandler()
+                       { return mCaptureHandler; }
+               
+               //! Returns the number of IOBuffers currently available.
+               /*! The CaptureManager usually waits to capture the next frame until an IOBuffer is available.
+                * The application is reponsible to release the IOBuffers to make it available to the capture manager.
+                * \return the number of IOBuffers. */
+               virtual int getNumIOBuffers() = 0;
+               
+       private:
+               //! Dequeue the next buffer.
+               /*! \return the next buffer with captured data. */
+               virtual IOBuffer* dequeue() = 0;
+
+               //! Enqueue a buffer.
+               /*! \param buf the buffer that isn't used by the application anymore and that can be reused now. 
+                * \return 0 success, -1 on failure*/
+               virtual int enqueue(IOBuffer* buf) = 0;
+
+               friend class IOBuffer;
+       };
+};
+
+#endif // CAPTUREMANAGER_H_
diff --git a/extra_lib/include/avcap/Connector.h b/extra_lib/include/avcap/Connector.h
new file mode 100644 (file)
index 0000000..cc318a7
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef CONNECTOR_H_
+#define CONNECTOR_H_
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include "avcap-config.h"
+#endif
+
+#ifdef AVCAP_LINUX
+# include <linux/types.h>
+# include <linux/videodev.h>
+#endif
+
+#include <string>
+#include <list>
+
+#include "avcap-export.h"
+
+namespace avcap
+{      
+       // forward declaration
+       class DeviceDescriptor;
+       class Tuner;
+       
+       //! This class is the abstraction of a video/audio input or output.
+       
+       /*! It is used to describe available inputs and outputs of a device and 
+        * to select them by means of the API-dependent CaptureDevices implementation of the ConnectorManager. 
+        * The ConnectorManager queries all available connectors of a device and 
+        * provides methods to set and get the currently used ones.
+        */
+        
+       class AVCAP_Export Connector
+       {
+       public:
+#ifdef AVCAP_LINUX
+               enum
+               {
+                       INPUT_TYPE_TUNER = V4L2_INPUT_TYPE_TUNER
+               };
+#endif
+               
+       protected:
+               DeviceDescriptor*       mDeviceDescriptor;
+               int                                     mIndex;
+               int                                     mAudioset;
+               int                                     mType;
+               std::string                     mName;
+               
+       public:
+               //! The Constructor. Objects of this class are created by the ConnectorManager.
+               inline Connector(DeviceDescriptor *dd, int index, const std::string& name, int type=0, int audioset=0):
+                       mDeviceDescriptor(dd), mIndex(index), mAudioset(audioset), mType(type), mName(name)
+                       {}
+
+               //! The Destructor. 
+               virtual inline ~Connector() 
+                       {}
+
+               //! Returns the unique index of the connector.
+               /*! \return The index. */
+               inline int getIndex() const 
+                       { return mIndex; }
+               
+               //! Get mapping of audio inputs to video inputs.
+               /*! For devices which provide audio and video capturing, 
+                * video inputs can correspond to zero or more audio inputs. The audio inputs 
+                * are numbered from 0 to N-1, N <= 32. Each bit of the audioset corresponds
+                * to one input. For details, see the Video4Linux2 API Documentation.
+                * \n\n<b>Win32:</b> A video connector can correspond to only one audio connector
+                * (only one bit can be set at a time). */
+               inline int getAudioset() const 
+                       { return mAudioset; }
+               
+               //! Get the tuner associated with the Connector.
+               /*! If a tuner is associated whith the connector (e.g. for TV-Tuner cards), then this method returns
+                * an object of class Tuner to access the tuner specific functionality.
+                * \return object of class Tuner or 0 if there is no tuner. */
+               virtual inline Tuner* getTuner() 
+                       { return 0; }
+               
+               //! Provides a textual description of the connector. 
+               /*! \return connector name. */
+               inline const std::string& getName() const 
+                       { return mName; }
+               
+               //! Test, whether a tuner is associated with the connector or not.
+               /*! \return true, if tuner is associated, false otherwise. */
+               virtual inline bool hasTuner() const 
+                       { return false; }
+       };
+};
+
+#endif // CONNECTOR_H_
diff --git a/extra_lib/include/avcap/ConnectorManager.h b/extra_lib/include/avcap/ConnectorManager.h
new file mode 100644 (file)
index 0000000..417ef15
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef CONNECTORMANAGER_H_
+#define CONNECTORMANAGER_H_
+
+#include <list>
+
+#include "Connector.h"
+#include "Manager.h"
+#include "avcap-export.h"
+
+namespace avcap
+{      
+class DeviceCollector;
+
+       //! This class is the interface to query and select the available video/audio inputs/outputs.
+        
+       /*! This class manages STL-lists of objects of class Connector which describe 
+        * an input or output of a capture device. Applications can get these lists and get/set
+        * the currently used connector of a special type. The methods to deal
+        * with outputs are only of partial interest for capturing but have been added
+        * for completeness.
+        * Application must use the API-dependent CaptureDevice-object to get an ConnectorManager.
+        * The default implementations of the mehtods in this class are a noop.
+        */
+
+       class AVCAP_Export ConnectorManager: public Manager<Connector>
+       {       
+       protected:
+               // Connector Lists
+               ListType                mVideoInputs;
+               ListType                mAudioInputs;
+               ListType                mVideoOutputs;
+               ListType                mAudioOutputs;
+               
+       public:         
+               //! Construct the manager and query for available inputs and outputs for audio and video.
+               /*! The manager is usualy created by an CaptureDevice object.
+                * \param dd The DeviceDescriptor to acces the device. */
+               ConnectorManager(DeviceDescriptor *dd);
+
+               //! The destructor. */
+               virtual ~ConnectorManager() = 0;
+               
+               //! Returns the Connector describing the currently used video input.
+               /*! The default-implementation returns 0. 
+                * \return video input connector.*/
+               virtual inline Connector* getVideoInput()
+                       { return 0; }
+
+               //! Sets the currently used video input.
+               /*! The default-implementation is a noop and returns -1. 
+                * \param c The connector to use for the video input.
+                * \return 0, if succesful, -1 else*/
+               virtual inline int setVideoInput(Connector* c)
+                       { return -1; }
+                       
+               //! Returns the Connector describing the currently used audio input. 
+               /*! The default-implementation returns 0. 
+                * \return audio input connector.*/
+               virtual inline Connector* getAudioInput()
+                       { return 0; }
+
+               //! Sets the currently used audio input.
+               /*! The default-implementation is a noop and returns -1. 
+                * \param c The connector to use for the audio input.
+                * \return 0, if succesful, -1 else*/
+               virtual inline int setAudioInput(Connector* c)
+                       { return -1; }
+               
+               //! Returns the Connector describing the currently used video output.
+               /*! The default-implementation returns 0. 
+                * \return video output connector.*/
+               virtual inline Connector* getVideoOutput()
+                       { return 0; }
+               
+               //! Sets the currently used video output.
+               /*! The default-implementation is a noop and returns -1. 
+                * \param c The connector to use for the video input.
+                * \return 0, if succesful, -1 else*/
+               virtual inline int setVideoOutput(Connector* c)
+                       { return -1; }
+                       
+               //! Returns the Connector describing the currently used audio output. 
+               /*! The default-implementation returns 0. 
+                * \return audio output connector.*/            
+               virtual inline Connector* getAudioOutput()
+                       { return 0; }
+
+               //! Sets the currently used audio output.
+               /*! The default-implementation is a noop and returns -1. 
+                * \param c The connector to use for the audio output.
+                * \return 0, if succesful, -1 else*/
+               virtual inline int setAudioOutput(Connector* c)
+                       { return -1; }
+
+               //! Get the list of available video inputs of the device.
+               /*! \return STL-list of pointers to objects of type 
+                * Connector describing the available video inputs. */
+               inline const ListType& getVideoInputList() const 
+                       { return mVideoInputs; }
+               
+               //! Get the list of available audio inputs of the device.
+               /*! \return STL-list of pointers to objects of type 
+                * Connector describing the available audio inputs. */          
+               inline const ListType& getAudioInputList() const 
+                       { return mAudioInputs; }        
+
+               //! Get the list of available video outputs of the device.
+               /*! \return STL-list of pointers to objects of type 
+                * Connector describing the available video outputs. */
+               inline const ListType& getVideoOutputList() const 
+                       { return mVideoOutputs; }       
+
+               //! Get the list of available audio outputs of the device.
+               /*! \return STL-list of pointers to objects of type 
+                * Connector describing the available audio outputs. */
+               inline const ListType& getAudioOutputList() const 
+                       { return mAudioOutputs; }
+
+               //! This method is called after creation to query for video/audio in- and outputs.
+               virtual void query() = 0;
+
+       private:
+               void clearList(ConnectorManager::ListType& list);
+       };
+}
+
+#endif //CONNECTORMANAGER_H_
diff --git a/extra_lib/include/avcap/ControlManager.h b/extra_lib/include/avcap/ControlManager.h
new file mode 100644 (file)
index 0000000..ff4a253
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef CONTROLMANAGER_H_
+#define CONTROLMANAGER_H_
+
+#include <string>
+#include <list>
+
+#include "Control_avcap.h"
+#include "Manager.h"
+#include "avcap-export.h"
+
+namespace avcap
+{
+       //! Abstract base for classes that manage the controls of a capture device.
+       
+       /*! Devices have typically a number of user-setable controls (e.g. brightness, hue,...).
+        * The number of controls, the type and possible values will vary from device to device.
+        * The ControlManager queries for available controls, their type and valid values.
+        * It provides a STL-List of Control-derived objects which represents the functonality of a
+        * device control. The concrete ControlManager may not be instantiated
+        * by the application but can be obtained from the CaptureDevice object. */
+       
+       class AVCAP_Export ControlManager:public Manager<Control>
+       {
+       protected:
+               ListType mControls;
+       
+       public:
+               //! The constructor. 
+               /*! \param dd The device descriptor to access the device. */
+               ControlManager(DeviceDescriptor *dd);
+       
+               //! The destructor.
+               virtual ~ControlManager() = 0;
+       
+               //! Find a control by name.
+               /*! \param name The name of the control to find.
+                * \return Pointer to the control or 0, if no control was found. */
+               Control* getControl(const std::string& name);
+       
+               //! Find a control by id.
+               /*! \param id The id of the control to find.
+                * \return Pointer to the control or 0, if no control was found. */
+               Control* getControl(int id);
+       
+               //! Returns the STL-list of Control objects.
+               /*! \return The control list. */
+               inline const ListType& getControlList() 
+                       { return (const ListType&) mControls; }
+       
+               //! Reset all controls to their default values,i.e. calls the reset()-method of all managed controls.
+               /*! \return 0 if successful, -1 else */
+               virtual int resetAll();
+       
+               virtual void query() = 0;
+       };
+}
+
+
+#endif //CONTROLMANAGER_H_
diff --git a/extra_lib/include/avcap/Control_avcap.h b/extra_lib/include/avcap/Control_avcap.h
new file mode 100644 (file)
index 0000000..47e05cb
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef CONTROL_H_
+#define CONTROL_H_
+
+#include <string>
+#include <list>
+
+#include "avcap-export.h"
+#include "Interval.h"
+
+namespace avcap {
+// forward declaration
+class DeviceDescriptor;
+
+       //! Abstract Base class for all device controls.
+       
+       /*! Capture devices possess various controls (e.g. hue, saturation,...) of different type.
+        * This class provides the interface that all controls share. Objects 
+        * derived from this class are managed by a ControlManager which is 
+        * obtained by the concrete CaptureDevice object. 
+        * A concrete control may expose an extended interface to provide additional functionality. 
+        * Applications can use the getType()-method or RTTI to determine the type of the concrete control. */
+
+       class AVCAP_Export Control
+       {
+       public:
+               enum Type {
+                       INTEGER_CONTROL = 0,
+                       BOOL_CONTROL,
+                       BUTTON_CONTROL,
+                       MENU_CONTROL,
+                       CTRLCLASS_CONTROL,
+                       USERDEFINED_CONTROL
+               };
+               
+       private:
+               Type mType;
+               
+       public:
+               //! Constructor
+               Control(Type t): mType(t)
+                       {}
+       
+               //! Destructor
+               virtual ~Control() 
+                       {}
+               
+               //! Get the unique identifier of the control.
+               /*! \return id */
+               virtual int getId() const = 0;
+       
+               //! Get the default value of the control.
+               /*! \return default value */
+               virtual int getDefaultValue() const = 0;
+       
+               //! Get the name of the control.
+               /*! \return control name */
+               virtual const std::string& getName() const = 0;
+       
+               //! Set the new value of the control.
+               /*!  \param val : The new value.
+                * \return 0, if successful, -1 else */
+               virtual int setValue(int val) = 0;
+       
+               //! Get the current value of the control.
+               /*!  \return the value */
+               virtual int getValue() const = 0;
+       
+               //! Set the  value of the control to the default value.
+               /*!  \return 0, if successful, -1 else */
+               virtual int reset() = 0;
+               
+               //! Return the type of the control.
+               /* \return type */  
+               virtual inline Type getType() const 
+                       { return mType; }
+               
+       private:
+               Control() 
+                       {}
+       };
+       
+       //! Abstraction of an Integer-valued control.
+       /*! Such controls additionally provide information about the range and step of it's values. */
+       
+       class AVCAP_Export IntegerControl: public Control
+       {
+       public:
+               IntegerControl(): Control(Control::INTEGER_CONTROL)
+                       {}
+               
+               virtual ~IntegerControl() 
+                       {}
+               
+               //! Get the interval describing the range and step of valid values for this control.
+               /*! \return interval */
+               virtual const Interval& getInterval() const = 0; 
+       };
+       
+       //! Abstraction of a boolean-like control.
+       /*! Such controls provide no additional information. */
+       
+       class AVCAP_Export BoolControl: public Control
+       {
+       public:
+               BoolControl(): Control(Control::BOOL_CONTROL)
+                       {}
+               
+               virtual ~BoolControl() 
+                       {}      
+       };
+
+       //! Abstraction of a button-like control.
+       /*! Such controls provide a convinience-method to trigger the buttons action. */
+
+       class AVCAP_Export ButtonControl: public Control
+       {
+       public:
+               ButtonControl(): Control(Control::BUTTON_CONTROL)
+                       {}
+               
+               virtual ~ButtonControl() 
+                       {}
+               
+               //! Push the button. 
+               /*! \return 0, if successful, -1 else */
+               virtual int push() = 0;
+       };
+
+       //! Abstraction of a control describing the class of the successive controls.
+       /*! The sole purpose of such a control is to provide a name for the class of the controls
+        * following in the control-list. This name can be used for example to group the controls 
+        * in a 'tabbed' user-interface (See V4L2-API spec, Extended Controls).  */
+       
+       class AVCAP_Export CtrlClassControl: public Control
+       {
+       public:
+               CtrlClassControl(): Control(Control::CTRLCLASS_CONTROL)
+                       {}
+               
+               virtual ~CtrlClassControl() 
+                       {}
+       };
+
+       
+       //! A menu item.
+       struct MenuItem
+       {
+               //! The name of the item.
+               std::string name;
+               
+               //! The index to identify the item.
+               int index;
+
+       public:
+               //! The constructor.
+               inline MenuItem(const std::string& n, int i):
+                       name(n), index(i)
+                       {}
+       };
+
+       //! Abstraction of a menu-like control.
+       /*! These controls provide a list of items, the user can chose from. */
+       
+       class AVCAP_Export MenuControl: public Control
+       {
+       public:
+               //! Type of the item list.
+               typedef std::list<MenuItem*> ItemList;
+
+       public:
+               MenuControl(): Control(Control::MENU_CONTROL)
+                       {}
+               
+               virtual ~MenuControl() 
+                       {}
+               
+               //! Returns the STL-list of menu items associated with this control.
+               /*! \return the menu items. */
+               virtual const ItemList& getItemList () = 0;
+       };
+}
+
+#endif // CONTROL_H_
diff --git a/extra_lib/include/avcap/DeviceCollector.h b/extra_lib/include/avcap/DeviceCollector.h
new file mode 100644 (file)
index 0000000..0d02c66
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef DEVICECOLLECTOR_H_
+#define DEVICECOLLECTOR_H_
+
+#include <list>
+#include <string>
+
+#include "singleton.h"
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include "avcap-config.h"
+#endif
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+class DeviceDescriptor;
+class CaptureDevice;
+
+       //! This singleton queries the capture devices available on the system and provides a factory-method to create CaptureDevice-objects.
+       
+       /*! This class tests during instantiation (i.e. the first call to it's instance()-method), 
+        * which capture devices are available on the system
+        * and provides an STL-list of DeviceDescriptor objects describing these devices.  
+        * 
+        * The following strategy to find capture devices in the system is applied:
+        *  
+        * <b>Linux:</b>
+        * <UL> 
+        * <LI>All /dev/video* nodes are tested by default. </LI>
+        * <LI>If avcap has been compiled with HAS_AVC_SUPPORT defined, all IEEE 1394 AV/C-devices are tested. </LI>
+        * <LI>IEEE1394 digital camera support is planned but currently not implemented. 
+        * </UL>
+        * <b>Win32:</b>
+        * <UL> 
+        * <LI>All devices in the CLSID_VideoInputDeviceCategory category (see DirectShow documentation) are tested.</LI>
+        * </UL>
+        * <b>Darwin:</b>
+        * <UL> 
+        * <LI>All devices of the SequenceGrabber-Component device-list are tested.</LI>
+        * </UL>
+        * 
+        * Access the singleton instance via DEVICE_COLLECTOR::instance().
+        **/
+       
+       class AVCAP_Export DeviceCollector
+       {
+       public:
+               //! List type of the DeviceDescriptor object list.
+               typedef std::list<DeviceDescriptor*> DeviceList;
+       
+       private:
+               DeviceList mDeviceList;
+       
+       public:
+               //! Constructor
+               DeviceCollector();
+               
+               //! Destructor
+               virtual ~DeviceCollector();
+       
+               //! Returns the STL-list of DeviceDescriptor objects describing available capture devices.
+               /*! \return The descriptor list.*/
+               inline const DeviceList& getDeviceList() const 
+                       { return (const DeviceList&) mDeviceList; }
+       
+               //! Linux only! Test, if the device with the given name can be opened and is a V4L1 or V4L2 capture device or not. 
+               /*! If it is, a new DeviceDescriptor-object is created 
+                * and stored in the device list, managed by the collector. 
+                * \param name : the name of a device node (e.g. /dev/video0) 
+                * \return true, if it is a V4L1-device, false else*/
+               bool testDevice(const std::string& name);
+       
+       private:
+       
+#ifdef AVCAP_LINUX
+               void query_V4L1_Devices();
+               
+               void query_V4L2_Devices();
+               
+               void query_ieee1394_Devices();
+               
+               int test_V4L1_Device(const std::string& name);
+               
+               int test_V4L2_Device(const std::string& name);
+#endif
+
+#ifdef AVCAP_OSX
+               void query_QT_Devices();
+#endif
+
+#ifdef AVCAP_WINDOWS
+               void query_DS_Devices();
+               
+               int test_DS_Device(const std::string& name);
+               
+               bool getInstalledDeviceIDs(std::list<std::string> &UniqueDeviceIDList);
+
+#endif
+};
+
+//! The DeviceCollector singleton. Access the singleton instance via DEVICE_COLLECTOR::instance().
+typedef Singleton<DeviceCollector> DEVICE_COLLECTOR;
+}
+
+/* \todo Add Linux-support for IEEE 1394 digital cameras. */
+
+#endif // DEVICECOLLECTOR_H_
diff --git a/extra_lib/include/avcap/DeviceDescriptor.h b/extra_lib/include/avcap/DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..676831c
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef DEVICEDESCRIPTOR_H_
+#define DEVICEDESCRIPTOR_H_
+
+#include <iostream>
+#include <string>
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include "avcap-config.h"
+#endif
+
+#include "avcap-export.h"
+
+// IVTV driver name
+#define DRIVER_IVTV    "ivtv"
+
+namespace avcap
+{
+class CaptureDevice;
+
+       //! Objects of classes derived from this abstract base uniquely identify a capture device in a system.
+
+       /*! It is used as an system independent description of a capture device.
+        * It provides the interface to access information about a device and the device itself.
+        * Special devices must inherit this class, e.g. V4L2_DeviceDescriptor or AVC_DeviceDescriptor.
+        * A list of objects derived from this class (one for each device) is provided
+        * by the DeviceCollector-singleton, which tries
+        * to determine all capture devices available on the system, so applications
+        * don't have to instantiate objects of these class explicitly. Objects of this
+        * class can be used to create a concrete CaptureDevice object by calling DEVICE_COLLECTOR::instance()->createDevice().
+        * The class must be implemented for a concrete capture API/OS.
+        */
+
+       class AVCAP_Export DeviceDescriptor
+       {
+       public:
+#ifdef AVCAP_LINUX
+               typedef int DEV_HANDLE_T;
+#endif
+
+#ifdef AVCAP_OSX
+               typedef int DEV_HANDLE_T;
+#endif
+
+#ifdef _WIN32
+               //! <b>Win32:</b> Platform dependent device handle type for windows. (represents the DirectShow capture filter (always casted to a IBaseFilter COM-Interface).
+               /* To get the complete created filter graph call GetFilterGraphFromFilter()
+                declared in the "HelpFunc.h" header file. */
+               typedef void* DEV_HANDLE_T;
+#endif
+
+       private:
+               const static std::string mEmptyString;
+
+       public:
+               //! Constructor
+               DeviceDescriptor();
+
+               //! Destructor
+               virtual ~DeviceDescriptor() = 0;
+
+               //! Open the underlying device.
+               /*! The CaptureDevice-Object returned by getDevice(), which is actually used to perform
+                * capturing is not valid before open() is called.
+                * \return 0 success, -1 on failure, e.g. open() has been already called before
+                */
+               virtual int open() = 0;
+
+               //! Close the underlying device.
+               /*! The CaptureDevice-Object returned by getDevice(), which is actually used to perform
+                * capturing, is not valid after close() is called.
+                * \return 0 success, -1 failure
+                */
+               virtual int close() = 0;
+
+               //! Returns the unique identifier of the device.
+               /*! \return unique identifier of device */
+               virtual const std::string& getName() const = 0;
+
+               //! Returns the name of the driver.
+               /*! The default implementation returns an empty string.
+                * \return driver */
+               virtual inline const std::string& getDriver() const
+                       { return mEmptyString; }
+
+               //! Returns the name of the device
+               /*! The default implementation returns an empty string.
+                * \return name of the card */
+               virtual inline const std::string& getCard() const
+                       { return mEmptyString; }
+
+               //! Returns a textual description of the device.
+               /*! The default implementation returns an empty string.
+                * \return name */
+               virtual inline const std::string& getInfo() const
+                       { return mEmptyString; }
+
+               //! Returns the version number of the driver.
+               /*! The default implementation returns 0.
+                * \return version. */
+               virtual inline int getVersion() const
+                       { return 0; }
+
+               //! Returns the version number of the driver as string.
+               /*! The default implementation returns an empty string.
+                * \return version string. */
+               virtual inline const std::string& getVersionString() const
+                       { return mEmptyString; }
+
+               //! Returns the API-specific device handle used to reference the device.
+               /*! \return the device handle */
+               virtual const DEV_HANDLE_T getHandle() const = 0;
+
+               //! Device is an audio/video device. The default implementation returns false.
+               virtual inline bool isAVDev() const
+                       { return false; }
+
+               //! Device is capable to capture some data. The default implementation returns false.
+               virtual inline bool isVideoCaptureDev() const
+                       { return false; }
+
+               //! Device is a VBI device. The default implementation returns false.
+               virtual inline bool isVBIDev() const
+                       { return false; }
+
+               //! Device has a tuner. The default implementation returns false.
+               virtual inline bool isTuner() const
+                       { return false; }
+
+               //! Device is an audio device. The default implementation returns false.
+               virtual inline bool isAudioDev() const
+                       { return false; }
+
+               //! Device is a radio device. The default implementation returns false.
+               virtual inline bool isRadioDev() const
+                       { return false; }
+
+               //! Device supports video overlay. The default implementation returns false.
+               virtual inline bool isOverlayDev() const
+                       { return false; }
+
+               //! Device supports read/write IO-methods (linux specific, see V4L2 API Docu for further details).
+               /*!  The default implementation returns false. */
+               virtual inline bool isRWDev () const
+                       { return false; }
+
+               //! Device supports asynchroneous IO-methods (linux specific, see V4L2 API Docu for further details).
+               /*! The default implementation returns false. */
+               virtual inline bool isAsyncIODev() const
+                       { return false; }
+
+               //! Device supports memory mapping IO-methods (linux specific, see V4L2 API Docu for further details).
+               /*! The default implementation returns false. */
+               virtual inline bool isStreamingDev() const
+                       { return false; }
+
+               //! Factory-method to create a API-dependent CaptureDevice-object.
+               /*! Applications must not create their own
+                * instances of a CaptureDevice but use this method to access the proper
+                * API-dependent unique device-object. You can use this object anywhere between
+                * successive calls to open() and close(), i.e. it is not valid before open() and not after close().
+                * The ownership of the object remains at the descriptor, so the caller
+                * must not delete the object after usage.
+                * Only one CaptureDevice-object will be created for each DeviceDescriptor, so
+                * multiple calls to getDevice() will always return the same object instance.
+                *
+                * \return the CaptureDevice-instance or 0, if not available. */
+               virtual CaptureDevice* getDevice() = 0;
+       };
+}
+
+
+#endif //DEVICEDESCRIPTOR_H_
diff --git a/extra_lib/include/avcap/FormatManager.h b/extra_lib/include/avcap/FormatManager.h
new file mode 100644 (file)
index 0000000..b111c26
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef FORMATMANAGER_H_
+#define FORMATMANAGER_H_
+
+#include <list>
+#include <string>
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include <stdint.h>
+# include "avcap-config.h"
+#endif
+
+#include "Manager.h"
+#include "avcap-export.h"
+
+#ifdef AVCAP_LINUX
+# include <linux/types.h>
+# include <linux/videodev.h>
+#endif // AVCAP_LINUX
+
+#ifdef _WIN32
+typedef unsigned int uint32_t;
+#endif
+
+/* taken from linux/videodev2.h but all FormatManagers use these fourcc-codes*/
+
+#define FOURCC(a,b,c,d)\
+        (((uint32_t)(a)<<0)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24))
+
+#define PIX_FMT_RGB332  FOURCC('R','G','B','1') /*  8  RGB-3-3-2     */
+#define PIX_FMT_RGB555  FOURCC('R','G','B','O') /* 16  RGB-5-5-5     */
+#define PIX_FMT_RGB565  FOURCC('R','G','B','P') /* 16  RGB-5-6-5     */
+#define PIX_FMT_RGB555X FOURCC('R','G','B','Q') /* 16  RGB-5-5-5 BE  */
+#define PIX_FMT_RGB565X FOURCC('R','G','B','R') /* 16  RGB-5-6-5 BE  */
+#define PIX_FMT_BGR24   FOURCC('B','G','R','3') /* 24  BGR-8-8-8     */
+#define PIX_FMT_RGB24   FOURCC('R','G','B','3') /* 24  RGB-8-8-8     */
+#define PIX_FMT_BGR32   FOURCC('B','G','R','4') /* 32  BGR-8-8-8-8   */
+#define PIX_FMT_RGB32   FOURCC('R','G','B','4') /* 32  RGB-8-8-8-8   */
+#define PIX_FMT_GREY    FOURCC('G','R','E','Y') /*  8  Greyscale     */
+#define PIX_FMT_YVU410  FOURCC('Y','V','U','9') /*  9  YVU 4:1:0     */
+#define PIX_FMT_YVU420  FOURCC('Y','V','1','2') /* 12  YVU 4:2:0     */
+#define PIX_FMT_YUYV    FOURCC('Y','U','Y','V') /* 16  YUV 4:2:2     */
+#define PIX_FMT_UYVY    FOURCC('U','Y','V','Y') /* 16  YUV 4:2:2     */
+#define PIX_FMT_YUV422P FOURCC('4','2','2','P') /* 16  YVU422 planar */
+#define PIX_FMT_YUV411P FOURCC('4','1','1','P') /* 16  YVU411 planar */
+#define PIX_FMT_Y41P    FOURCC('Y','4','1','P') /* 12  YUV 4:1:1     */
+
+/* two planes -- one Y, one Cr + Cb interleaved  */
+#define PIX_FMT_NV12    FOURCC('N','V','1','2') /* 12  Y/CbCr 4:2:0  */
+#define PIX_FMT_NV21    FOURCC('N','V','2','1') /* 12  Y/CrCb 4:2:0  */
+
+/*  The following formats are not defined in the V4L2 specification */
+#define PIX_FMT_YUV410  FOURCC('Y','U','V','9') /*  9  YUV 4:1:0     */
+#define PIX_FMT_YUV420  FOURCC('Y','U','1','2') /* 12  YUV 4:2:0     */
+#define PIX_FMT_I420   FOURCC('I','4','2','0') /* 12  identical to YU12 */
+#define PIX_FMT_YYUV    FOURCC('Y','Y','U','V') /* 16  YUV 4:2:2     */
+#define PIX_FMT_HI240   FOURCC('H','I','2','4') /*  8  8-bit color   */
+#define PIX_FMT_HM12    FOURCC('H','M','1','2') /*  8  YUV 4:1:1 16x16 macroblocks */
+
+/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#define PIX_FMT_SBGGR8  FOURCC('B','A','8','1') /*  8  BGBG.. GRGR.. */
+
+/* compressed formats */
+#define PIX_FMT_MJPEG    FOURCC('M','J','P','G') /* Motion-JPEG   */
+#define PIX_FMT_JPEG     FOURCC('J','P','E','G') /* JFIF JPEG     */
+#define PIX_FMT_DV       FOURCC('d','v','s','d') /* 1394          */
+#define PIX_FMT_MPEG     FOURCC('M','P','E','G') /* MPEG-1/2/4    */
+
+/*  Vendor-specific formats   */
+#define PIX_FMT_WNVA     FOURCC('W','N','V','A') /* Winnov hw compress */
+#define PIX_FMT_SN9C10X  FOURCC('S','9','1','0') /* SN9C10x compression */
+#define PIX_FMT_PWC1     FOURCC('P','W','C','1') /* pwc older webcam */
+#define PIX_FMT_PWC2     FOURCC('P','W','C','2') /* pwc newer webcam */
+#define PIX_FMT_ET61X251 FOURCC('E','6','2','5') /* ET61X251 compression */
+
+namespace avcap
+{
+class DeviceDescriptor;
+
+       //! Description of the video standard.
+       struct AVCAP_Export VideoStandard
+       {
+#ifdef AVCAP_LINUX
+               typedef v4l2_std_id     STANDARD_ID_T;
+               enum {
+                       PAL = V4L2_STD_PAL_B,
+                       NTSC = V4L2_STD_NTSC_M,
+                       SECAM = V4L2_STD_SECAM_B
+               };
+#endif
+
+#if defined (_WIN32) || defined (AVCAP_OSX)
+               typedef unsigned int STANDARD_ID_T;
+#endif
+
+
+               std::string             name;   //!< The name of the standard.
+               STANDARD_ID_T   id;             //!< A unique identifier.
+
+               //! Constructor
+               VideoStandard(const std::string& n, STANDARD_ID_T i):
+                       name(n),
+                       id(i)
+                       {};
+       };
+
+       //! The Resolution consists of a width and a height.
+       struct AVCAP_Export Resolution {
+               int width, height;
+
+               Resolution(int w, int h):
+                       width(w),
+                       height(h)
+                       {}
+       };
+
+       //! Description of a video format.
+       class AVCAP_Export Format
+       {
+       public:
+               typedef std::list<Resolution*> ResolutionList_t;
+       private:
+               std::string mName;              // A textual description.
+               uint32_t mFourcc;               // The Four Character Code of the format.
+               ResolutionList_t        mResList;
+
+#ifdef _WIN32
+               void *mediatype;                /* stores DirectShow-specific format description (only used internaly).
+                                                                *< It is always casted to a AM_MEDIA_TYPE
+                                                                * DirectShow structure; see DirectShow documentation */
+#endif
+
+       public:
+               //! Constructor
+               inline Format(const std::string& n, uint32_t f):
+                       mName(n), mFourcc(f)
+                       {}
+
+               //! Destructor
+               virtual ~Format();
+
+               //! Get the name of the format.
+               /*! \return name */
+               inline const std::string& getName() const
+                       { return mName; }
+
+               //! Get the four character code of the format (see: www.fourcc.org).
+               /*! \return fourcc */
+               inline uint32_t getFourcc() const
+                       { return mFourcc; }
+
+               //! Return a list of resolutions that are supported for this format.
+               /*! \return the resolutions.*/
+               inline const ResolutionList_t& getResolutionList() const
+                       { return mResList; }
+
+               void addResolution(int w, int h);
+
+#ifdef _WIN32
+               void* getMediaType() { return mediatype; }
+
+               void setMediaType(void* mt) { mediatype = mt; }
+#endif
+       };
+
+       //! Abstract base for classes that query and manage available formats, video-standards and resolutions of a capture device.
+
+       /*! This class queries the formats, video-standards and resolutions provided by the device
+        * and allows applications to set them.
+        * The class provides a STL-list of Format-objects.
+        * Actualy changing the format may be deferred by the concrete implementation until it
+        * is really necessary, e.g. the capture begins, because advising the driver
+        * to change the format can be a quite time-consuming operation.
+        * Most of the methods in this class are implemented as a noop and are
+        * reimplemented by the derived class for a concrete capture API/OS, if the method is applicable.
+        */
+
+       class AVCAP_Export FormatManager: public Manager<Format>
+       {
+       public:
+               typedef std::list<VideoStandard*>       VideoStandardList;
+
+       protected:
+               ListType                mFormats;
+               int                             mWidth;
+               int                             mHeight;
+               int                     mBytesPerLine;
+#if defined(AVCAP_LINUX) || defined (AVCAP_OSX)
+               unsigned int    mCurrentFormat;
+#endif
+#ifdef _WIN32
+               void                    *mCurrentFormat;                // Always casted to a AM_MEDIA_TYPE DirectShow structure
+#endif
+               unsigned long   mImageSize;
+               bool                    mModified;
+               VideoStandardList       mStandards;
+
+       public:
+               //! The constructor. */
+               FormatManager(DeviceDescriptor *dd);
+
+               //! The destructor. */
+               virtual ~FormatManager();
+
+               //! Returns the STL-list of Format objects describing the available formats.
+               /*! \return The format list.*/
+               virtual inline const ListType& getFormatList() const
+                       { return (const ListType&) mFormats; }
+
+               //! Set the format to capture.
+               /*! \param fmt The new format.
+                * \return 0, if successful, -1 else */
+               virtual int setFormat(Format *fmt);
+
+               //! Set the format to capture.
+               /*! \param fourcc The four character code of the new format.
+                * \return 0, if successful, -1 else */
+               virtual int setFormat(uint32_t fourcc);
+
+               //! Get the current format.
+               /*! \return The format. */
+               virtual Format* getFormat();
+
+               //! Set the image with and height.
+               /*! \param w : width
+                * \param h : height
+                * \return 0, if successful, -1 else */
+               virtual int setResolution(int w, int h);
+
+               //! Set the number of used bytes per scanline, if possible.
+               /*! \param bpl
+                * \return 0, if successful, -1 else */
+               virtual int setBytesPerLine(int bpl);
+
+               //! Returns the image with.
+               /*! \return width*/
+               virtual int getWidth();
+
+               //! Returns the image height.
+               /*! \return height*/
+               virtual int getHeight();
+
+               //! Returns the bytes per line.
+               /*! \return bpl*/
+               virtual int getBytesPerLine();
+
+               //! Flushes the format, i.e. the driver is advised to apply the current format settings.
+               /*! \return  0, if successful, -1 else */
+               virtual int flush();
+
+               //! The number of bytes that an image of the current size requires to be stored in memory, including padding.
+               /*! \return size */
+               virtual size_t getImageSize();
+
+               //! Set the framerate.
+               /*! The default implementation returns -1
+                * \param fps : the number of frames per second.
+                * \return 0 if successful, -1 on failure */
+               virtual int setFramerate(int fps);
+
+               //! Get the current framerate.
+               /*! The default implementation returns -1
+                *! \return the frames per second */
+               virtual int getFramerate();
+
+               //! Get the STL-list of avaliable video standards described by VideoStandard objects.
+               /*! \return standards list*/
+               virtual inline const VideoStandardList& getVideoStandardList() const
+                       { return (const VideoStandardList&) mStandards; }
+
+               //! Get the currently used video standard.
+               /*! The default implementation returns 0
+                * \return the current standard or 0, if not applicable */
+               virtual const VideoStandard* getVideoStandard();
+
+               //! Set the video standard to use.
+               /*! Attention: not all video standards can be set in conjunction with each connector and format.
+                * The default implementation returns -1
+                * \param std The new video standard.
+                * \return 0, if successful, -1 else */
+               virtual int setVideoStandard(const VideoStandard* std);
+
+               virtual void query() = 0;
+       };
+};
+#endif //FORMATMANAGER_H_
+
+
diff --git a/extra_lib/include/avcap/IOBuffer.h b/extra_lib/include/avcap/IOBuffer.h
new file mode 100644 (file)
index 0000000..a8b379a
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef IOBUFFER_H_
+#define IOBUFFER_H_
+
+
+#include <sys/types.h>
+#include <time.h>
+#include <iostream>
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include <sys/time.h>
+# include "avcap-config.h"
+#endif
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#include "CaptureManager.h"
+#include "avcap-export.h"
+
+namespace avcap
+{
+       //! The buffer to store captured data.
+       
+       /*! The class contains the captured data and provides additional information,
+        * e.g. sequence number, valid bytes and a capture timestamp. The data in the buffer
+        * may not correspond exactly to one frame, e.g. if the captured data is part 
+        * of a stream (e.g. MPEG).
+        * */
+        
+       class AVCAP_Export IOBuffer
+       {
+       public:
+               
+               //! Use-state of the buffer
+               enum State
+               {
+                       STATE_USED = 0,         //!> currently used
+                       STATE_UNUSED,           //!> currently unused
+               };
+               
+       private:
+               CaptureManager *mMgr;
+               void*                   mPtr;
+               size_t                  mSize;
+               int                             mIndex;
+               int                             mState;
+               long                    mSequence;
+               size_t                  mValid;
+               struct timeval  mTimestamp;
+               
+       public:
+               
+               //! Constructor
+               IOBuffer(CaptureManager* mgr, void* ptr, size_t size, int index = 0);
+               virtual ~IOBuffer();
+
+               //! Get the pointer to the frame data.
+               /*! \return the captured data. */
+               inline void* getPtr() const
+                       { return mPtr; }
+               
+               //! Returns the maximum number of bytes the buffer can contain.
+               /*! \return Size of buffer in bytes. */
+               inline size_t getSize() const
+                       { return mSize; }
+               
+               //! Return the sequence number of the frame. 
+               /*! \return Sequence number */
+               inline long getSequence() const 
+                       { return mSequence; }
+               
+               //! Returns the number of valid bytes in the buffer.
+               /*! \return Number of valid bytes */
+               inline size_t getValidBytes() const 
+                       { return mValid; }
+               
+               //! Returns a timestamp in milliseconds. 
+               /*! \return timestamp */
+               unsigned long getTimestamp();
+
+               //! Must be called by the application after the buffer isn't used anymore to to enable its reutilization.
+               void release();
+               
+               //! Get the index of the buffer.
+               /*! \return the buffer index. */
+               inline int getIndex() const 
+                       { return mIndex; } 
+
+               //! Set the state of the buffer.
+               /*! This method should not be used by applications.
+                *! \param state : the new state */
+               inline void setState(State state) 
+                       { mState = state; }
+
+               //! Get the buffer usage state.
+               /*! \return the current buffer state. */
+               inline State getState() const 
+                       { return (State) mState; }
+               
+               //! Set buffer parameters.
+               /*! This method should not be used by applications. 
+                * \param valid : number of valid bytes in buffer
+                * \param state : the current buffer state
+                * \param ts : the timestamp the data was captured
+                * \param seq : the sequence number of the captured data */
+               void setParams(const size_t valid, State state, struct timeval &ts, int seq);
+       };
+}
+
+#endif // IOBUFFER_H_
diff --git a/extra_lib/include/avcap/Interval.h b/extra_lib/include/avcap/Interval.h
new file mode 100644 (file)
index 0000000..ac45118
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef INTERVAL_H_
+#define INTERVAL_H_
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+       //! An integer interval used by some Control-types.
+       class AVCAP_Export Interval
+       {
+       public:
+               //! The minimal value.
+               int min;
+
+               //! The maximal value.
+               int max;
+               
+               //! The increment.
+               int step;
+               
+               //! The Constructor.
+               Interval( int min_, int max_, int step_ )
+               {
+                       min = min_;
+                       max = max_;
+                       step = step_;
+               };
+       };
+};
+
+#endif // INTERVAL_H_
+
diff --git a/extra_lib/include/avcap/Manager.h b/extra_lib/include/avcap/Manager.h
new file mode 100644 (file)
index 0000000..b1b2d17
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef MANAGER_H_
+#define MANAGER_H_
+
+#include <list>
+#include <iostream>
+
+namespace avcap
+{
+       class DeviceDescriptor;
+       
+       //! Abstract base class for Managers. 
+       
+       /*! Classes that provide access to specific aspects of 
+        * a device derive from this class. Managers usualy manage a number of 
+        * objects of a specific type that abstract these aspects.
+        * The template parameter is used to define a STL list-type to 
+        * store these objects.*/
+        
+       template<class T>
+       class Manager
+       {
+       public:
+               //! The STL list-type to store the managed objects.
+               typedef std::list<T*>   ListType;
+               
+       protected:
+               DeviceDescriptor        *mDeviceDescriptor;
+               
+       public:
+               inline Manager(DeviceDescriptor* dd):
+                       mDeviceDescriptor(dd) 
+                       {}
+                       
+               virtual ~Manager() 
+                       {}
+               
+               /*! Called during initialisation by the CaptureDevice to query for 
+                * the objects that the implementation of this class manages. */
+               virtual void query() = 0;               
+       };
+}
+
+#endif // MANAGER_H_
diff --git a/extra_lib/include/avcap/ProbeValues.h b/extra_lib/include/avcap/ProbeValues.h
new file mode 100644 (file)
index 0000000..9a161bb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef PROBEVALUES_H
+#define PROBEVALUES_H
+namespace avcap {
+
+//! Standard resolutions to probe, if querying resolutions is not supported by the API/device
+static int NumResolutions = 13;
+static unsigned int Resolutions[][2] = 
+{
+       {640, 480},
+       {640, 360},
+       {352, 288}, 
+       {352, 240}, 
+       {320, 240}, 
+       {176, 144},
+       {160, 120},
+       {80, 60},
+       {720, 480},
+       {720, 576},
+       {800, 600},
+       {1280, 1024},
+       {1600, 1200}
+};
+
+}
+
+#endif
diff --git a/extra_lib/include/avcap/Tuner_avcap.h b/extra_lib/include/avcap/Tuner_avcap.h
new file mode 100644 (file)
index 0000000..197f644
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef TUNER_H_
+#define TUNER_H_
+
+#include <string>
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+       class DeviceDescriptor;
+       
+       //! Interface of a tuner.
+       
+       /*! This class provides access to the tuner functionality of TV or Radio-cards.
+        * Applications can adjust things like frequency, audio mode etc. 
+        * Applications don't create Tuner objects themselfes but get them from the Connector
+        * the tuner is associated with. The connector in turn can be obtained from the 
+        * ConnectorManager of the CaptureDevice.
+        **/
+        
+       class AVCAP_Export Tuner
+       {
+       private:
+       public:
+               virtual inline ~Tuner()
+                       {}
+               
+               //! Determine whether the tuner is able to receive radio frequencies. 
+               /*! The default implementation returns false.
+                * \return true if radio tuner, false else */
+               virtual inline bool isRadioTuner() const 
+                       { return false; }
+
+               //! Determine whether the tuner is able to receive TV frequencies.
+               /*! The default implementation returns false.
+                * \return true if TV tuner, false else */
+               virtual inline bool isTVTuner() const 
+                       { return false; };
+
+               //! Set the audio mode to stereo.
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int setStereo()  
+                       { return -1; }
+
+               //! Set the audio mode to mono.
+               /*! Default implementation is noop and return -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int setMono() 
+                       { return -1; }
+               
+               //! Set the audio mode to secondary audio program (SAP).
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int setSAP() 
+                       { return -1; }
+               
+               //! Set the audio mode to language 1.
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int setLang1() 
+                       { return -1; }
+
+               //! Set the audio mode to language 2.
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int setLang2() 
+                       { return -1; }
+
+               //! Returns the current frequency in MHz.
+               /*! The default implementation is noop and returns -1.
+                * \return tuner frequency */
+               virtual inline double getFreq() const 
+                       { return -1.0f; }
+
+               //! Returns the step with in which the frequency can be increased or decreased.
+               /*! The default implementation is noop and returns -1.
+                * \return frequency step width*/
+               virtual inline double getFreqStep() const
+                       { return -1.0f; }
+               
+               //! Returns the minimum possible frequency in MHz which can be applied to the tuner. 
+               /*! The default implementation is noop and returns -1.
+                * \return minimal tuner frequency */
+               virtual inline double getMinFreq() const
+                       { return -1.0f; }
+
+               //! Returns the maximum possible frequency in MHz which can be applied to the tuner. 
+               /*! The default implementation is noop and returns -1.
+                * \return maximal tuner frequency */
+               virtual inline double getMaxFreq() const
+                       { return -1.0f; }
+               
+               //! Returns the tuner name. 
+               /*! Default implementation returns an empty string.
+                * \return tuner name */
+               virtual inline const std::string getName() const
+                       { return ""; }
+               
+               //! This method tries to readjust and to fine-tune the frequency by means of the current AFC-value.
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */
+               virtual inline int finetune(int maxsteps) 
+                       { return -1; }
+               
+               //! Get the current automatic frequency control (AFC) value.  
+               /*! If the afc value is negative, the frequency is too low, if positive it is too high. 
+                *! The default implementation is noop and returns -1.
+                * \return afc */
+               virtual inline int getAFCValue() const
+                       { return -1; }
+               
+               //! Return the strength of the signal. 
+               /*! The default implementation is noop and returns -1.
+                * \return signal strength */
+               virtual inline int getSignalStrength() const
+                       { return -1; }
+               
+               //! Increase the frequency a step corresponding to getFreqStep(). 
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */
+               virtual inline int increaseFreq() 
+                       { return 0; }
+               
+               //! Decrease the frequency a step corresponding to getFreqStep(). 
+               /*! The default implementation is noop and returns -1.
+                * \return 0, if successful, -1 else. */                
+               virtual inline int decreaseFreq() 
+                       { return 0; }
+               
+               //! Set the new frequency. The frequency is given in MHz.
+               /*! The default implementation is noop and returns -1.
+                * \param f The new frequency.
+                * \return 0, if successful, -1 else. */
+               virtual inline int setFreq(double f) 
+                       { return -1; }
+       };
+       
+       /*! Known european terrestric analog TV channels. They must be multiplied by 10^6 
+        * to obtain the frequency in Hz. */
+       static const double TV_Channels[] = 
+       {
+               48.25, 55.25, 62.25, 175.25, 182.25, 189.25, 196.25, 203.25, 210.25, 217.25, 224.25, 471.25, 479.25, 487.25,
+        495.25, 503.25, 511.25, 519.25, 527.25, 535.25, 543.25, 551.25, 559.25, 567.25, 575.25, 583.25, 591.25,
+        599.25, 607.25, 615.25, 623.25, 631.25, 639.25, 647.25, 655.25, 663.25, 671.25, 679.25, 687.25, 695.25,
+        703.25, 711.25, 719.25, 727.25, 735.25, 743.25, 751.25, 759.25, 767.25, 775.25, 783.25, 791.25, 799.25,
+        807.25, 815.25, 823.25, 831.25, 839.25, 847.25, 855.25
+       };
+
+       /*! The number of TV channels */        
+       static const int TV_Num_Channels = 60;
+
+       /*! Some german analog radio channels. They must be multiplied by 10^6 
+        * to obtain the frequency in Hz. */
+       static const double Radio_Channels[] = 
+       {
+               102.4, 102.0
+       };
+
+       /*! The number of radio channels */     
+       static const int Radio_Num_Channels = 2;
+       
+}
+
+#endif // TUNER_H_
diff --git a/extra_lib/include/avcap/avcap-export.h b/extra_lib/include/avcap/avcap-export.h
new file mode 100644 (file)
index 0000000..58d0e22
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>\r
+ */\r
+\r
+\r
+#ifndef AVCAP_EXPORT_H\r
+#define AVCAP_EXPORT_H\r
+\r
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)\r
+#include "avcap-config.h"\r
+#endif\r
+\r
+#ifdef AVCAP_WINDOWS\r
+# if defined AVCAP_EXPORTS\r
+#   define AVCAP_Export __declspec(dllexport)\r
+# else /* AVCAP_BUILD_DLL */\r
+#   define AVCAP_Export /*__declspec(dllimport)*/\r
+# endif\r
+#else\r
+#define AVCAP_Export \r
+#endif\r
+\r
+#endif /* AVCAP_EXPORT_H */\r
+\r
diff --git a/extra_lib/include/avcap/avcap.h b/extra_lib/include/avcap/avcap.h
new file mode 100644 (file)
index 0000000..0e21a61
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef AVCAP_H
+#define AVCAP_H
+
+#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS)
+# include "avcap-config.h"
+#endif
+#include "avcap/DeviceCollector.h"
+#include "avcap/DeviceDescriptor.h"
+#include "avcap/CaptureDevice.h"
+#include "avcap/FormatManager.h"
+#include "avcap/CaptureHandler.h"
+#include "avcap/CaptureManager.h"
+#include "avcap/Control_avcap.h"
+#include "avcap/ControlManager.h"
+#include "avcap/Connector.h"
+#include "avcap/ConnectorManager.h"
+#include "avcap/IOBuffer.h"
+#include "avcap/Tuner_avcap.h"
+#include "avcap/log.h"
+
+#endif
diff --git a/extra_lib/include/avcap/linux/AVC_ConnectorManager.h b/extra_lib/include/avcap/linux/AVC_ConnectorManager.h
new file mode 100644 (file)
index 0000000..14c0847
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_CONNECTORMANAGER_H_
+#define AVC_CONNECTORMANAGER_H_
+
+#include <list>
+
+#include "ConnectorManager.h"
+
+namespace avcap
+{      
+       class AVC_DeviceDescriptor;
+       
+       //! \brief This class implements the ConnectorManager for AV/C-devices. 
+       
+       /*! Such devices don't have Connectors the user could chose. So the query()
+        * method is a noop. */
+       
+       class AVC_ConnectorManager: public ConnectorManager
+       {       
+       public:
+               
+               inline AVC_ConnectorManager(AVC_DeviceDescriptor *dd): 
+                       ConnectorManager((DeviceDescriptor*) dd)
+                       {}
+               
+               virtual inline ~AVC_ConnectorManager()
+                       {}
+               
+               inline void query()
+                       {}
+       };
+}
+
+#endif // AVC_CONNECTORMANAGER_H_
+
+#endif // HAS_AVC_SUPPORT
+
diff --git a/extra_lib/include/avcap/linux/AVC_ControlManager.h b/extra_lib/include/avcap/linux/AVC_ControlManager.h
new file mode 100644 (file)
index 0000000..9c2f698
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_CONTROLMANAGER_H_
+#define AVC_CONTROLMANAGER_H_
+
+#include <string>
+#include <list>
+
+#include "ControlManager.h"
+
+namespace avcap
+{
+       //! Implementation of the ControlManager for AV/C-devices. 
+       /*! These devices have usually no controls, so there the query method is a noop. */
+        
+       class AVC_ControlManager:public ControlManager
+       {
+       public:
+               //! The constructor. 
+               /*! \param dd The device descriptor to access the device. */
+               inline AVC_ControlManager(AVC_DeviceDescriptor *dd):
+                       ControlManager((DeviceDescriptor*) dd)
+                       {}
+               
+               //! The destructor.
+               virtual inline ~AVC_ControlManager() 
+                       {}
+               
+               virtual inline void query()
+                       {}
+       };
+};
+
+#endif // AVC_CONTROLMANAGER_H_
+#endif
diff --git a/extra_lib/include/avcap/linux/AVC_Device.h b/extra_lib/include/avcap/linux/AVC_Device.h
new file mode 100644 (file)
index 0000000..4d8d8b2
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_DEVICE_H_
+#define AVC_DEVICE_H_
+
+#include <string>
+#include <list>
+
+#include "DeviceDescriptor.h"
+#include "CaptureDevice.h"
+#include "AVC_FormatManager.h"
+
+namespace avcap
+{
+       // forward declarations
+       class AVC_DeviceDescriptor;
+       class AVC_VidCapManager;
+       class AVC_ConnectorManager;
+       class AVC_ControlManager;
+
+       //! Implementation of the CaptureDevice for IEEE 1394 AV/C-devices under linux.
+
+       /*! Such devices don't have controls, various resolutions, extensions, or connectors.
+        * So the implementation of the methods rely mostly on the default implementations or are
+        * implemented as noop.
+        *
+        * Note: If capturing from AV/C-devices is enabled, avcap depends on
+        * libiec61883, libavc1394, librom1394, libraw1394
+        * Furthermore the user requires read/write access to /dev/raw1394.
+        *
+        * AV/C-support is enabled by the configure-script, if the neccessary libs and developement-headers
+        * are found on the system.
+        *
+        * The AV/C-support is based on dvgrab (http://www.kinodv.org), which is released under the GPLv2.
+        */
+
+       class AVC_Device : public CaptureDevice
+       {
+       public:
+
+       private:
+               AVC_DeviceDescriptor*   mDeviceDescriptor;
+               AVC_FormatManager*              mFormatMgr;
+               AVC_VidCapManager*              mVidCapMgr;
+               AVC_ConnectorManager*   mConnectorMgr;
+               AVC_ControlManager*             mControlMgr;
+
+       public:
+               //! Constructor
+               AVC_Device(AVC_DeviceDescriptor* dd);
+
+               //! Destructor
+               virtual ~AVC_Device();
+
+               inline const DeviceDescriptor* getDescriptor()
+                       { return mDeviceDescriptor; }
+
+               inline CaptureManager* getVidCapMgr()
+                       { return (CaptureManager*) mVidCapMgr; }
+
+               inline ConnectorManager* getConnectorMgr()
+                       { return (ConnectorManager*) mConnectorMgr; }
+
+               inline ControlManager* getControlMgr()
+                       { return (ControlManager*) mControlMgr; }
+
+               inline FormatManager* getFormatMgr()
+                       { return (FormatManager*) mFormatMgr; }
+
+       private:
+               int open();
+
+               int close();
+       };
+}
+
+#endif // AVC_DEVICE_H_
+#endif // HAS_AVC_SUPPORT
+
diff --git a/extra_lib/include/avcap/linux/AVC_DeviceDescriptor.h b/extra_lib/include/avcap/linux/AVC_DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..e6a78fd
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef AVC_DEVICEDESCRIPTOR_H_
+#define AVC_DEVICEDESCRIPTOR_H_
+
+#ifdef HAS_AVC_SUPPORT
+
+#include <iostream>
+#include <libavc1394/rom1394.h>
+
+#include "DeviceDescriptor.h"
+
+namespace avcap
+{
+class CaptureDevice;
+class AVC_Device;
+
+       //! This class implements a descriptor for a IEEE 1394 AV/C capture device under linux (e.g. a DV-Camera).
+
+       class AVC_DeviceDescriptor : public DeviceDescriptor
+       {
+       private:
+               std::string mName;
+               std::string mGUIDString;
+               std::string mInfo;
+               std::string     mDriver;
+
+               octlet_t        mGUID;
+               static int      mDevCount;
+               AVC_Device*     mDevice;
+
+       public:
+               //! This constructor uses a numerical global unique identifier to represent a IEEE 1394 capture device (e.g. a firewire DV-Cam).
+               /*! \param guid The unique identifier of device.*/
+               AVC_DeviceDescriptor(const octlet_t guid);
+
+               //! The destructor */
+               virtual ~AVC_DeviceDescriptor();
+
+               int open();
+
+               int close();
+
+               //! Returns the unique identifier of the device. AV/C-devices get the name
+               /*! "AV/C_n", where n is the number of the device in the system starting with 1.
+                * So the 3rd device found has the name AV/C_3.
+                * \return unique identifier of device */
+               inline const std::string& getName() const
+                       { return mName; }
+
+               virtual inline const std::string& getInfo() const
+                       { return mInfo; }
+
+               virtual inline const std::string& getDriver() const
+                       { return mDriver; }
+
+               virtual inline const std::string& getCard() const
+                       { return mGUIDString; }
+
+               //! There is no handle associated with a AV/C-device. So this method always returns -1.
+               inline const DEV_HANDLE_T getHandle() const
+                       { return -1; }
+
+               //! Device is an audio/video device. Always returns true.
+               inline bool isAVDev() const
+                       { return true; }
+
+               //! Device is capable to capture some data. Always returns true.
+               inline bool isVideoCaptureDev() const
+                       { return true; }
+
+               inline octlet_t& getGUID()
+                       { return mGUID; }
+
+               virtual CaptureDevice* getDevice();
+       };
+}
+
+#endif // AVC_DEVICEDESCRIPTOR_H_
+#endif // HAS_DVLIBS
+
diff --git a/extra_lib/include/avcap/linux/AVC_FormatManager.h b/extra_lib/include/avcap/linux/AVC_FormatManager.h
new file mode 100644 (file)
index 0000000..dfd420c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_FORMATMANAGER_H_
+#define AVC_FORMATMANAGER_H_
+
+#include "FormatManager.h"
+
+namespace avcap
+{
+       class AVC_DeviceDescriptor;
+       
+       //! Implementation of the FormatManager for AV/C devices. 
+         
+       /*! DV-Cams usually provide only a fixed resolution (PAL: 720x576, NTSC: 720x480)
+        * YUV-format and no choice of video standards.
+        * Additionally, this manager provides RGB.*/
+        
+       class AVC_FormatManager: public FormatManager
+       {
+       private:
+               bool mIsPal;
+               
+       public:
+               AVC_FormatManager(AVC_DeviceDescriptor *dd);
+               
+               virtual ~AVC_FormatManager();
+               
+               //! Set the image with. 
+               /*! For AV/C -devices the reolution is fixed and thus can't be realy modified.
+                * \param w: width
+                * \param h: height
+                * \return 0, if the desired resolution matches the native resolution, -1 else*/
+               int setResolution(int w, int h);
+
+               //! Get the current framerate. Setting the framerate is not possible.
+               /*! \return 25 for PAL, 30 for NTSC(this is a little bit inaccurate, since the proper NTSC-frame rate is 29.97 fps)*/
+               inline int getFramerate() { return mIsPal ? 25 : 30; }
+               
+               void query();
+       };
+};
+#endif // AVC_FORMATMANAGER_H_
+
+#endif // HAS_AVC_SUPPORT
+
diff --git a/extra_lib/include/avcap/linux/AVC_Reader.h b/extra_lib/include/avcap/linux/AVC_Reader.h
new file mode 100644 (file)
index 0000000..2c214b0
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_READER_H_
+#define AVC_READER_H_
+
+#include <list>
+
+#include "ieee1394io.h"
+
+namespace avcap
+{
+class AVC_VidCapManager;
+class AVC_FormatManager;
+class IOBuffer;
+
+       //! AVC_Reader, used by the AVC_VidCapManager.
+       
+       class AVC_Reader : public iec61883Reader
+       {
+               typedef std::list<IOBuffer*>    BufferList_t;
+               
+               
+               AVC_VidCapManager* mVidCapMgr;
+               AVC_FormatManager*      mFormatMgr;
+               CaptureHandler*         mCaptureHandler;
+       
+               BufferList_t    mBuffers;
+               long                    mSequence;
+               int                             mAvailableBuffers;
+               
+       public:
+               AVC_Reader(AVC_VidCapManager* cap_mgr, AVC_FormatManager* fmt_mgr, int port, int channel, int num_bufs);
+               
+               virtual ~AVC_Reader();
+       
+               void registerCaptureHandler(CaptureHandler *handler);
+       
+               void removeCaptureHandler();
+               
+               virtual void TriggerAction();
+               
+               void enqueue(IOBuffer* io_buf);
+               
+               inline int getNumIOBuffers() 
+                       { return mAvailableBuffers; }
+       
+       };      
+}
+
+#endif // AVC_READER_H_
+#endif
diff --git a/extra_lib/include/avcap/linux/AVC_VidCapManager.h b/extra_lib/include/avcap/linux/AVC_VidCapManager.h
new file mode 100644 (file)
index 0000000..8f33572
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef AVC_VIDCAPMANAGER_H_
+#define AVC_VIDCAPMANAGER_H_
+
+#include "avcap-config.h"
+
+#include <sys/types.h>
+#include <list>
+#include <time.h>
+
+#include "CaptureManager.h"
+
+namespace avcap
+{
+       class AVC_DeviceDescriptor;
+       class AVC_FormatManager;
+       class IOBuffer;
+       class CaptureHandler;
+       class AVC_Reader;
+       class iec61883Connection;
+       
+       //! The IEEE 1394 AV/C video capture manager.
+       
+       /*! This class is used to capture video data from a AV/C-Device (e.g. DV-Cams) connected 
+        * to the computer via IEEE 1394 (aka Firewire or iLink) under Linux. 
+       */
+       class AVC_VidCapManager: public CaptureManager
+       {
+       public:
+               enum
+               {
+                       MAX_BUFFERS = 32,       //!< The maximum number of IOBuffers.
+                       DEFAULT_BUFFERS = 8     //!< The default number of used IOBuffers.
+               };
+               
+       private:
+               typedef std::list<IOBuffer*> IOBufList;
+               
+               AVC_DeviceDescriptor    *mDeviceDescriptor;
+               AVC_FormatManager               *mFormatMgr;
+               AVC_Reader                              *mReader;
+               iec61883Connection              *mConnection;
+               
+               IOBufList                       mBuffers;
+               int                                     mNumBufs;
+               int                             mSequence;
+
+       public:
+       
+               AVC_VidCapManager(AVC_DeviceDescriptor* dd, AVC_FormatManager* fmt_mgr, int nbufs = DEFAULT_BUFFERS);
+               
+               virtual ~AVC_VidCapManager();
+               
+               int init();
+               
+               int destroy();
+               
+               int startCapture();
+
+               int stopCapture();
+               
+               void registerCaptureHandler(CaptureHandler *handler); 
+
+               void removeCaptureHandler(); 
+               
+               virtual int getNumIOBuffers();
+
+       private:
+               virtual IOBuffer* dequeue();
+
+               virtual int enqueue(IOBuffer* buf);
+       };
+}
+#endif // AVC_VIDCAPMANAGER_H_
+
+#endif // HAS_AVC_SUPPORT
+
diff --git a/extra_lib/include/avcap/linux/V4L1_Connector.h b/extra_lib/include/avcap/linux/V4L1_Connector.h
new file mode 100644 (file)
index 0000000..827b5eb
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef V4L1_CONNECTOR_H_
+#define V4L1_CONNECTOR_H_
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#include <string>
+#include <list>
+
+#include "Connector.h"
+
+namespace avcap
+{      
+       // forward declaration
+       class V4L1_DeviceDescriptor;
+       class Tuner;
+       
+       //! Implementation of the Connector for a Video4Linux1 device. 
+
+       class V4L1_Connector : public Connector
+       {
+       public:
+               //! The Constructor. Objects should be instantiated only by the ConnectorManager.
+               inline V4L1_Connector(V4L1_DeviceDescriptor *dd, int index, const std::string& name, int type=0):
+                       Connector(dd, index, name, type)
+                       {}
+               
+               virtual inline ~V4L1_Connector()
+                       {}                      
+       };
+}
+
+#endif // V4L1_CONNECTOR_H_
diff --git a/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h b/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h
new file mode 100644 (file)
index 0000000..f771b67
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+
+#ifndef V4L1_CONNECTORMANAGER_H_
+#define V4L1_CONNECTORMANAGER_H_
+
+#include <linux/videodev.h>
+#include <list>
+
+#include "ConnectorManager.h"
+
+namespace avcap
+{      
+       class V4L1_DeviceDescriptor;
+       
+       //! Implementation of the ConnectorManager for Video4Linux2-devices. */
+       
+       class V4L1_ConnectorManager: public ConnectorManager
+       {       
+       private:
+               Connector*      mCurrentVideoInput;
+               
+       public:
+               V4L1_ConnectorManager(V4L1_DeviceDescriptor *dd);
+               
+               virtual ~V4L1_ConnectorManager();
+               
+               Connector* getVideoInput();
+
+               int setVideoInput(Connector* c);
+               
+               void query();
+       
+       private:
+               Connector* findByIndex(const ListType& l, int index);
+       };
+}
+
+#endif // V4L1_CONNECTORMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L1_Control.h b/extra_lib/include/avcap/linux/V4L1_Control.h
new file mode 100644 (file)
index 0000000..f0cfd55
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef V4L1_CONTROL_H_
+#define V4L1_CONTROL_H_
+
+#include <string>
+#include <list>
+
+#include "Control_avcap.h"
+
+namespace avcap
+{
+       // forward declaration
+       class V4L1_DeviceDescriptor;
+       
+       //! Implementation of a V4L1-Control.
+
+       /*! The V4L1 API supprots only controls for brightness, hue, colour, contrast, depth and whiteness.
+        * They are all integer values between 0 and 65535.*/
+        
+       class V4L1_Control: public IntegerControl
+       {
+       public:
+               enum Ctrl {
+                       BRIGHTNESS = 0,
+                       HUE,
+                       COLOUR,
+                       CONTRAST,
+                       WHITENESS,
+                       DEPTH
+               };
+       
+       private:        
+               static std::string mNames[6];
+               
+               V4L1_DeviceDescriptor*  mDescriptor;
+               Ctrl    mType;
+               int             mDefaultValue;
+               Interval mInterval;
+               
+       public:
+               V4L1_Control(V4L1_DeviceDescriptor* dd, Ctrl type,  __u16 def);
+
+               virtual inline ~V4L1_Control()
+                       {}
+               
+               virtual inline int getId() const
+                       { return mType; }
+               
+               virtual inline int getDefaultValue() const
+                       { return mDefaultValue; }
+               
+               virtual const std::string& getName() const;
+               
+               virtual int setValue(int val);
+
+               virtual int getValue() const;
+               
+               virtual int reset();
+
+               virtual inline const Interval& getInterval() const 
+                       { return mInterval; }
+       };
+}
+
+#endif // V4L1_CONTROL_H_
+
diff --git a/extra_lib/include/avcap/linux/V4L1_ControlManager.h b/extra_lib/include/avcap/linux/V4L1_ControlManager.h
new file mode 100644 (file)
index 0000000..2f08164
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef V4L1_CONTROLMANAGER_H_
+#define V4L1_CONTROLMANAGER_H_
+
+#include <string>
+#include <list>
+
+#include "ControlManager.h"
+
+namespace avcap
+{
+       class V4L1_DeviceDescriptor;
+       
+       //! Implementation of the ControlManager for Video4Linux2 devices.
+       
+       class V4L1_ControlManager:public ControlManager
+       {
+       public:
+               V4L1_ControlManager(V4L1_DeviceDescriptor *dd);
+               
+               virtual ~V4L1_ControlManager();
+       
+               void query();
+       };
+}
+
+#endif // V4L1_CONTROLMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L1_Device.h b/extra_lib/include/avcap/linux/V4L1_Device.h
new file mode 100644 (file)
index 0000000..cd7db28
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef V4L1_DEVICE_H_
+#define V4L1_DEVICE_H_
+
+#include <string>
+#include <list>
+
+#include "V4L1_DeviceDescriptor.h"
+#include "CaptureDevice.h"
+
+namespace avcap
+{
+       // forward declarations
+       class V4L1_ConnectorManager;
+       class V4L1_ControlManager;
+       class V4L1_VidCapManager;
+       class V4L1_DeviceDescriptor;
+       class V4L1_FormatManager;
+
+       //! Implementation of the CaptureDevice interface for Video4Linux2 devices. */
+
+       class V4L1_Device : public CaptureDevice
+       {
+       public:
+
+       private:
+               V4L1_VidCapManager              *mVidCapMgr;
+               V4L1_ConnectorManager   *mConnectorMgr;
+               V4L1_ControlManager             *mControlMgr;
+               V4L1_FormatManager              *mFormatMgr;
+               V4L1_DeviceDescriptor   *mDeviceDescriptor;
+
+       public:
+               V4L1_Device(V4L1_DeviceDescriptor* dd);
+
+               virtual ~V4L1_Device();
+
+               inline const DeviceDescriptor* getDescriptor()
+                       { return mDeviceDescriptor; }
+
+               inline CaptureManager* getVidCapMgr()
+                       { return (CaptureManager*) mVidCapMgr; }
+
+               inline ConnectorManager* getConnectorMgr()
+                       { return (ConnectorManager*) mConnectorMgr; }
+
+               inline ControlManager*  getControlMgr()
+                       { return (ControlManager*) mControlMgr; }
+
+               inline FormatManager* getFormatMgr()
+                       { return (FormatManager*) mFormatMgr; }
+
+       private:
+               int open();
+
+               int close();
+       };
+}
+
+#endif //V4L1_DEVICE_H_
+
diff --git a/extra_lib/include/avcap/linux/V4L1_DeviceDescriptor.h b/extra_lib/include/avcap/linux/V4L1_DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..f555312
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L1_DEVICEDESCRIPTOR_H_
+#define V4L1_DEVICEDESCRIPTOR_H_
+
+#include <iostream>
+
+#include "DeviceDescriptor.h"
+
+namespace avcap
+{
+class CaptureDevice;
+class V4L1_Device;
+
+       //! This class uniquely identifies a Video4Linux1 capture device.
+
+       class V4L1_DeviceDescriptor : public DeviceDescriptor
+       {
+       public:
+               struct bounds {
+                       unsigned int minwidth, minheight, maxwidth, maxheight;
+               };
+
+       private:
+               std::string     mName;
+               std::string mDriver;
+               std::string mCard;
+               std::string mInfo;
+               std::string mVersionString;
+
+               int mVersion;
+
+               DEV_HANDLE_T mHandle;
+               bool mValid;
+
+               // Video4Linux1 specific data
+               int             mType;
+               bounds  mBounds;
+               int     mAudios;
+               int             mChannels;
+               bool    mIsStreamingDev;
+
+               V4L1_Device*    mDevice;
+
+       public:
+               V4L1_DeviceDescriptor(const std::string &name);
+
+               virtual ~V4L1_DeviceDescriptor();
+
+               virtual CaptureDevice* getDevice();
+
+               virtual int open();
+
+               virtual int close();
+
+               virtual const std::string& getName() const;
+
+               inline const std::string& getDriver() const
+                       { return mDriver; }
+
+               inline const std::string& getCard() const
+                       { return mCard; }
+
+               inline const std::string& getInfo() const
+                       { return mInfo; }
+
+               inline int getVersion() const
+                       { return mVersion; }
+
+               const std::string& getVersionString() const;
+
+               inline const DEV_HANDLE_T getHandle() const
+                       { return mHandle; }
+
+               bool isAVDev() const;
+
+               bool isVideoCaptureDev() const;
+
+               bool isVBIDev() const;
+
+               bool isTuner() const;
+
+               bool isAudioDev() const;
+
+               bool isRadioDev() const;
+
+               bool isOverlayDev() const;
+
+               bool isRWDev () const;
+
+               bool isAsyncIODev() const;
+
+               bool isStreamingDev() const;
+
+               inline int getChannels() const
+                       { return mChannels; }
+
+               inline int getAudios() const
+                       { return mAudios; }
+
+               //! Returns a reference to the bounds of the video size.
+               inline bounds& getBounds()
+                       { return mBounds; }
+
+       private:
+               bool queryCapabilities();
+       };
+};
+
+#endif // V4L1_DEVICEDESCRIPTOR_H_
diff --git a/extra_lib/include/avcap/linux/V4L1_FormatManager.h b/extra_lib/include/avcap/linux/V4L1_FormatManager.h
new file mode 100644 (file)
index 0000000..2fe7068
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L1_FORMATMANAGER_H_
+#define V4L1_FORMATMANAGER_H_
+
+#include <linux/videodev.h>
+
+#include "FormatManager.h"
+
+namespace avcap
+{
+       class V4L1_DeviceDescriptor;
+       
+       //! This class implements the FormatManager for Video4Linux2 devices. */
+       /*! This CaptureManager starts an own thread to capture data. 
+        * The access to the internal buffer-list is synchronized, so \c release() can be called
+        * from any thread at any time.
+        */
+                
+       class V4L1_FormatManager: public FormatManager
+       {
+       private:
+               struct fmtdesc {
+                       char    description[32];
+                       __u16   palette;
+                       __u32   fourcc;
+                       float   sizefactor;
+               };
+               
+               static const int mNumDescriptors = 18; 
+
+               static const fmtdesc mDescriptors[mNumDescriptors];
+               
+               bool mIsOVFX2;
+               
+       public:
+               V4L1_FormatManager(V4L1_DeviceDescriptor *dd);
+               
+               virtual ~V4L1_FormatManager();
+               
+               int setFormat(Format *fmt);
+               
+               int setFormat(unsigned int fourcc);
+
+               Format* getFormat();
+               
+               int setResolution(int w, int h);
+               
+               int setBytesPerLine(int bpl);
+
+               int getWidth();
+
+               int getHeight();
+               
+               int getBytesPerLine();
+
+               int flush();
+
+               size_t getImageSize();
+
+               const VideoStandard* getVideoStandard();
+
+               int setVideoStandard(const VideoStandard* std);
+               
+               //! Setting the frame-rate is currently only possible for some philips-cams
+               int setFramerate(int fps);
+               
+               int getFramerate();
+
+               __u16 getPalette();
+               
+               void query();
+
+       private:
+               int getParams();
+
+               void queryResolutions();
+               
+               __u16 getPalette(__u32 fourcc);
+               
+               int updateDimensions();
+       };
+}
+
+#endif //V4L1_FORMATMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L1_VidCapManager.h b/extra_lib/include/avcap/linux/V4L1_VidCapManager.h
new file mode 100644 (file)
index 0000000..f1e83ce
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L1_VIDCAPMANAGER_H_
+#define V4L1_VIDCAPMANAGER_H_
+
+#include <sys/types.h>
+#include <list>
+#include <time.h>
+
+#include "CaptureManager.h"
+
+namespace avcap
+{
+       class V4L1_DeviceDescriptor;
+       class V4L1_FormatManager;
+       class IOBuffer;
+       class CaptureHandler;
+
+       //! The Video4Linux2-API video capture manager.
+
+       class V4L1_VidCapManager: public CaptureManager
+       {
+       private:
+               typedef std::list<IOBuffer*> IOBufList_t;
+               typedef std::list<int>           IndexList_t;
+                               
+               V4L1_DeviceDescriptor   *mDeviceDescriptor;
+               V4L1_FormatManager              *mFormatMgr;
+               
+               IOBufList_t                     mBuffers;
+               IndexList_t                     mCaptureIndices;
+               
+               int                                     mNumBufs;
+               int                                     mMethod;
+               int                                     mState;
+
+               pthread_t*                      mThread;
+               int                                     mFinish;
+               pthread_mutex_t         mLock;
+               timeval                         mStartTime;
+
+               long                            mSequence;
+
+               unsigned char*          mVideobuf;
+               size_t                          mVideobufSize;
+               int                                     mWidth;
+               int                                     mHeight;
+               unsigned int            mPalette;
+               int                                     mAvailableBuffers;
+               
+       public:
+       
+               V4L1_VidCapManager(V4L1_DeviceDescriptor* dd, V4L1_FormatManager* fmt_mgr, int nbufs = DEFAULT_BUFFERS);
+               
+               virtual ~V4L1_VidCapManager();
+               
+               int init();
+               
+               int destroy();
+               
+               int startCapture();
+
+               int stopCapture();
+               
+               int getNumIOBuffers();
+               
+       private:
+               int start_read();
+
+               int start_mmap();
+
+               int stop_read();
+               
+               int stop_mmap();
+
+               IOBuffer* dequeue();
+               
+               int enqueue(IOBuffer* buf);
+               
+               IOBuffer* findBuffer(int index);
+               
+               static void run(void* mgr);
+               
+               void clearBuffers();
+               
+               int getUsedBufferCount();
+       };
+};
+#endif // V4L1_VIDCAPMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_BoolControl.h b/extra_lib/include/avcap/linux/V4L2_BoolControl.h
new file mode 100644 (file)
index 0000000..b713019
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_BOOLCONTROL_H_
+#define V4L2_BOOLCONTROL_H_
+
+#include "V4L2_ControlBase.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+
+       //! A control for a Video4Linux2 device with one of the two values true (1) or false (0).
+       
+       class V4L2_BoolControl: public BoolControl
+       {
+       private:
+               V4L2_ControlBase        mControlBase;
+               
+       public:
+               inline V4L2_BoolControl(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query):
+                       mControlBase(dd, query)
+                       {}
+
+               virtual inline ~V4L2_BoolControl()
+                       {}
+               
+               virtual inline int getId() const
+                       { return mControlBase.getId(); }
+       
+               virtual inline int getDefaultValue() const
+                       { return mControlBase.getDefaultValue(); }
+       
+               virtual inline const std::string& getName() const
+                       { return mControlBase.getName(); }
+       
+               virtual inline int setValue(int val)
+                       { return mControlBase.setValue(val); }
+       
+               virtual inline int getValue() const
+                       { return mControlBase.getValue(); }
+               
+               virtual inline int reset()
+                       { return mControlBase.reset(); }
+       };
+}
+
+#endif // V4L2_BOOLCONTROL_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_ButtonControl.h b/extra_lib/include/avcap/linux/V4L2_ButtonControl.h
new file mode 100644 (file)
index 0000000..ea589a5
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_BUTTONCONTROL_H_
+#define V4L2_BUTTONCONTROL_H_
+
+#include "V4L2_ControlBase.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       
+       //! A control for a Video4Linux2 device that performs an action when set, independently from the value.
+       
+       class V4L2_ButtonControl: public ButtonControl
+       {
+       private:
+               V4L2_ControlBase        mControlBase;
+
+       public:
+               inline V4L2_ButtonControl(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query): 
+                       mControlBase(dd, query)
+                       {}
+
+               virtual inline ~V4L2_ButtonControl()
+                       {}
+               
+               virtual inline int push()
+                       { return setValue(0); }
+               
+               virtual inline int getId() const
+                       { return mControlBase.getId(); }
+       
+               virtual inline int getDefaultValue() const
+                       { return mControlBase.getDefaultValue(); }
+       
+               virtual inline const std::string& getName() const
+                       { return mControlBase.getName(); }
+       
+               virtual inline int setValue(int val)
+                       { return mControlBase.setValue(val); }
+       
+               virtual inline int getValue() const
+                       { return mControlBase.getValue(); }
+               
+               virtual inline int reset() 
+                       { return mControlBase.reset(); }
+       };
+}
+
+#endif // V4L2_BUTTONCONTROL_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_Connector.h b/extra_lib/include/avcap/linux/V4L2_Connector.h
new file mode 100644 (file)
index 0000000..3927bf2
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_CONNECTOR_H_
+#define V4L2_CONNECTOR_H_
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#include <string>
+#include <list>
+
+#include "Connector.h"
+
+namespace avcap
+{      
+       // forward declaration
+       class V4L2_DeviceDescriptor;
+       class Tuner;
+       
+       //! This class implements Connector (a video/audio input or output) for a Video4Linux2 device.
+        
+       class V4L2_Connector : public Connector
+       {
+       private:
+               Tuner*                          mTuner;
+               
+       public:
+               V4L2_Connector(V4L2_DeviceDescriptor *dd, int index, const std::string& name, int type=0, int audioset=0, int tuner=0);                 
+
+               virtual ~V4L2_Connector();
+
+               inline Tuner* getTuner()
+                       { return mTuner; }
+                               
+               inline bool hasTuner() const
+                       { return mType & INPUT_TYPE_TUNER; }
+       };
+}
+
+#endif // V4L2_CONNECTOR_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_ConnectorManager.h b/extra_lib/include/avcap/linux/V4L2_ConnectorManager.h
new file mode 100644 (file)
index 0000000..7be974c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_CONNECTORMANAGER_H_
+#define V4L2_CONNECTORMANAGER_H_
+
+#include <list>
+
+#include "ConnectorManager.h"
+
+namespace avcap
+{      
+       class V4L2_DeviceDescriptor;
+       
+       //! This class implements the ConnectorManager for Video4Linux2-devices.
+       
+       class V4L2_ConnectorManager: public ConnectorManager
+       {       
+       public:
+       
+               V4L2_ConnectorManager(V4L2_DeviceDescriptor *dd);
+
+               virtual ~V4L2_ConnectorManager();
+               
+               Connector* getVideoInput();
+
+               int setVideoInput(Connector* c);
+               
+               Connector* getAudioInput();
+
+               int setAudioInput(Connector* c);
+               
+               Connector* getVideoOutput();
+               
+               int setVideoOutput(Connector* c);
+               
+               Connector* getAudioOutput();
+               
+               int setAudioOutput(Connector* c);
+
+               void query();
+       
+       private:
+               Connector* findByIndex(const ListType& l, int index);
+       };
+}
+
+#endif // V4L2_CONNECTORMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_ControlBase.h b/extra_lib/include/avcap/linux/V4L2_ControlBase.h
new file mode 100644 (file)
index 0000000..806574c
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_CONTROLBASE_H_
+#define V4L2_CONTROLBASE_H_
+
+#include <string>
+#include <list>
+#include <linux/videodev.h>
+
+namespace avcap
+{
+       // forward declaration
+       class V4L2_DeviceDescriptor;
+       
+       //! Basic implementation of a device control for a Video4Linux2 device.
+       
+       /*! Implements common methods of V4L2-controls. */
+       
+       class V4L2_ControlBase
+       {
+       protected:
+               V4L2_DeviceDescriptor   *mDeviceDescriptor;
+               int     mId;
+               int mValue;
+       
+       private:
+               std::string     mName;
+               int mDefaultValue;
+               int mFlags;
+
+       public:
+               V4L2_ControlBase(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query);
+
+               virtual ~V4L2_ControlBase();
+
+               inline int getId() const
+                       { return mId; }
+
+               inline int getDefaultValue() const
+                       { return mDefaultValue; }
+               
+               inline const std::string& getName() const 
+                       { return mName; }
+               
+               virtual int setValue(int val);
+
+               virtual int getValue() const;
+               
+               virtual int reset();
+               
+               //! Return the flags of the v4l2_queryctrl structure associated with the control.
+               __u32 getFlags() const { return mFlags; }
+               
+       protected:
+               // updates the value of the control
+               int update();
+       };
+}
+
+#endif // V4L2_CONTROLBASE_H_
+
diff --git a/extra_lib/include/avcap/linux/V4L2_ControlManager.h b/extra_lib/include/avcap/linux/V4L2_ControlManager.h
new file mode 100644 (file)
index 0000000..2b3e5ed
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_CONTROLMANAGER_H_
+#define V4L2_CONTROLMANAGER_H_
+
+#include <string>
+#include <list>
+
+#include "ControlManager.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       
+       //! Implementation of the ControlManager for Video4Linux2 devices.
+       
+       class V4L2_ControlManager:public ControlManager
+       {
+       public:
+               V4L2_ControlManager(V4L2_DeviceDescriptor *dd);
+               
+               virtual ~V4L2_ControlManager();
+       
+               void query();
+               
+       private:
+               void query(int start_id, int end_id);
+               
+               bool queryExtended();
+       };
+}
+
+#endif // V4L2_CONTROLMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_CtrlClassControl.h b/extra_lib/include/avcap/linux/V4L2_CtrlClassControl.h
new file mode 100644 (file)
index 0000000..c4a37f1
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_CTRLCLASS_CONTROL_H_
+#define V4L2_CTRLCLASS_CONTROL_H_
+
+#include "V4L2_ControlBase.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+
+       //! A control for a Video4Linux2 device naming the control-class of the subsequent enumerated controls.
+       
+       class V4L2_CtrlClassControl: public CtrlClassControl
+       {
+       private:
+               V4L2_ControlBase        mControlBase;
+               
+       public:
+               inline V4L2_CtrlClassControl(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query):
+                       mControlBase(dd, query)
+                       {}
+
+               virtual inline ~V4L2_CtrlClassControl()
+                       {}
+               
+               virtual inline int getId() const
+                       { return mControlBase.getId(); }
+       
+               virtual inline int getDefaultValue() const
+                       { return 0; }
+       
+               virtual inline const std::string& getName() const
+                       { return mControlBase.getName(); }
+       
+               virtual inline int setValue(int val)
+                       { return 0; }
+       
+               virtual inline int getValue() const
+                       { return 0; }
+               
+               virtual inline int reset()
+                       { return 0; }
+       };
+}
+
+#endif // V4L2_CTRLCLASS_CONTROL_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_Device.h b/extra_lib/include/avcap/linux/V4L2_Device.h
new file mode 100644 (file)
index 0000000..ddd0b90
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_DEVICE_H_
+#define V4L2_DEVICE_H_
+
+#include <string>
+#include <list>
+
+#include "V4L2_DeviceDescriptor.h"
+#include "CaptureDevice.h"
+
+namespace avcap
+{
+       // forward declarations
+       class V4L2_ConnectorManager;
+       class V4L2_ControlManager;
+       class V4L2_VidCapManager;
+       class V4L2_DeviceDescriptor;
+       class V4L2_FormatManager;
+
+       //! Implementation of the CaptureDevice for Video4Linux2 devices. */
+
+       class V4L2_Device : public CaptureDevice
+       {
+       public:
+
+       private:
+               V4L2_VidCapManager              *mVidCapMgr;
+               V4L2_ConnectorManager   *mConnectorMgr;
+               V4L2_ControlManager             *mControlMgr;
+               V4L2_FormatManager              *mFormatMgr;
+               V4L2_DeviceDescriptor   *mDeviceDescriptor;
+
+       public:
+               V4L2_Device(V4L2_DeviceDescriptor* dd);
+
+               virtual ~V4L2_Device();
+
+               inline const DeviceDescriptor* getDescriptor()
+                       { return mDeviceDescriptor; }
+
+               inline CaptureManager* getVidCapMgr()
+                       { return (CaptureManager*) mVidCapMgr; }
+
+               inline ConnectorManager* getConnectorMgr()
+                       { return (ConnectorManager*) mConnectorMgr; }
+
+               inline ControlManager*  getControlMgr()
+                       { return (ControlManager*) mControlMgr; }
+
+               inline FormatManager* getFormatMgr()
+                       { return (FormatManager*) mFormatMgr; }
+
+       private:
+               int open();
+
+               int close();
+       };
+}
+
+#endif // V4L2_DEVICE_H_
+
diff --git a/extra_lib/include/avcap/linux/V4L2_DeviceDescriptor.h b/extra_lib/include/avcap/linux/V4L2_DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..99f66f8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_DEVICEDESCRIPTOR_H_
+#define V4L2_DEVICEDESCRIPTOR_H_
+
+#include <string>
+
+#include "DeviceDescriptor.h"
+
+// IVTV driver name
+#define DRIVER_IVTV    "ivtv"
+
+namespace avcap
+{
+class CaptureDevice;
+class V4L2_Device;
+
+       //! This class uniquely identifies a Video4Linux2 capture device.
+
+       class V4L2_DeviceDescriptor : public DeviceDescriptor
+       {
+       private:
+               std::string     mName;
+               std::string mDriver;
+               std::string mCard;
+               std::string mInfo;
+               std::string mVersionString;
+
+               int mVersion;
+               int mCapabilities;
+
+               DEV_HANDLE_T    mHandle;
+               bool                    mValid;
+               V4L2_Device*    mDevice;
+
+       public:
+               V4L2_DeviceDescriptor(const std::string &name);
+
+               virtual ~V4L2_DeviceDescriptor();
+
+               virtual CaptureDevice* getDevice();
+
+               int open();
+
+               int close();
+
+               virtual const std::string& getName() const;
+
+               inline const std::string& getDriver() const
+                       { return mDriver; }
+
+               inline const std::string& getCard() const
+                       { return mCard; }
+
+               inline const std::string& getInfo() const
+                       { return mInfo; }
+
+               inline int getVersion() const
+                       { return mVersion; }
+
+               const std::string& getVersionString() const;
+
+               inline const DEV_HANDLE_T getHandle() const
+                       { return mHandle; }
+
+               bool isAVDev() const;
+
+               bool isVideoCaptureDev() const;
+
+               bool isVBIDev() const;
+
+               bool isTuner() const;
+
+               bool isAudioDev() const;
+
+               bool isRadioDev() const;
+
+               bool isOverlayDev() const;
+
+               bool isRWDev () const;
+
+               bool isAsyncIODev() const;
+
+               bool isStreamingDev() const;
+
+       private:
+               bool queryCapabilities();
+       };
+}
+
+#endif // V4L2_DEVICEDESCRIPTOR_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_FormatManager.h b/extra_lib/include/avcap/linux/V4L2_FormatManager.h
new file mode 100644 (file)
index 0000000..d729c42
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_FORMATMANAGER_H_
+#define V4L2_FORMATMANAGER_H_
+
+#include "FormatManager.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       
+       //! This class implements the FormatManager for Video4Linux2 devices. */
+       
+       class V4L2_FormatManager: public FormatManager
+       {
+       
+       public:
+               V4L2_FormatManager(V4L2_DeviceDescriptor *dd);
+               
+               virtual ~V4L2_FormatManager();
+               
+               int setFormat(Format *fmt);
+               
+               int setFormat(unsigned int fourcc);
+
+               Format* getFormat();
+               
+               int setResolution(int w, int h);
+
+               int setBytesPerLine(int bpl);
+
+               int getWidth();
+
+               int getHeight();
+               
+               int getBytesPerLine();
+               
+               int flush();
+
+               size_t getImageSize();
+               
+               const VideoStandard* getVideoStandard();
+
+               int setVideoStandard(const VideoStandard* std);
+               
+               int setFramerate(int fps);
+               
+               int getFramerate();
+               
+               void query();
+
+       private:
+               int tryFormat();
+               
+               int getParams();
+               
+               void queryVideoStandards();
+               
+               void queryResolutions(Format* f);
+       
+       };
+}
+
+#endif // V4L2_FORMATMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_IntControl.h b/extra_lib/include/avcap/linux/V4L2_IntControl.h
new file mode 100644 (file)
index 0000000..da07a18
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_INTCONTROL_H_
+#define V4L2_INTCONTROL_H_
+
+#include "V4L2_ControlBase.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       
+       //! Implementation of an integer valued control for Video4Linux2 devices.
+        
+       class V4L2_IntControl: public IntegerControl
+       {
+       private:
+               V4L2_ControlBase        mControlBase;
+               Interval                        mInterval;
+               
+       public:
+               inline V4L2_IntControl(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query):
+                       mControlBase(dd, query),
+                       mInterval(query->minimum, query->maximum, query->step)
+                       {}
+
+               virtual inline ~V4L2_IntControl()
+                       {}
+               
+               inline const Interval& getInterval() const 
+                       { return mInterval; }
+
+               virtual inline int getId() const
+                       { return mControlBase.getId(); }
+       
+               virtual inline int getDefaultValue() const
+                       { return mControlBase.getDefaultValue(); }
+       
+               virtual inline const std::string& getName() const
+                       { return mControlBase.getName(); }
+       
+               virtual inline int setValue(int val)
+                       { return mControlBase.setValue(val); }
+       
+               virtual inline int getValue() const
+                       { return mControlBase.getValue(); }
+               
+               virtual inline int reset() 
+                       { return mControlBase.reset(); }
+
+       };
+}
+
+#endif // V4L2_INTCONTROL_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_MenuControl.h b/extra_lib/include/avcap/linux/V4L2_MenuControl.h
new file mode 100644 (file)
index 0000000..c1182fb
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef V4L2_MENUCONTROL_H_
+#define V4L2_MENUCONTROL_H_
+
+#include "V4L2_ControlBase.h"
+#include "Control_avcap.h"
+
+namespace avcap
+{
+       // forward declaration
+       class V4L2_DeviceDescriptor;
+       
+       //! A Control for a Video4Linux2 device which has various menu-like items to choose from.
+       
+       class V4L2_MenuControl: public MenuControl
+       {
+       private:
+               V4L2_ControlBase        mControlBase;
+               ItemList                        mMenuItems;
+               V4L2_DeviceDescriptor*  mDeviceDescriptor;
+               
+       public:
+               //! The constructor.
+               V4L2_MenuControl(V4L2_DeviceDescriptor *dd, struct v4l2_queryctrl* query);
+
+               //! The destructor.
+               virtual ~V4L2_MenuControl();
+       
+               virtual inline int getId() const
+                       { return mControlBase.getId(); }
+       
+               virtual inline int getDefaultValue() const
+                       { return mControlBase.getDefaultValue(); }
+       
+               virtual inline const std::string& getName() const
+                       { return mControlBase.getName(); }
+       
+               virtual inline int setValue(int val)
+                       { return mControlBase.setValue(val); }
+       
+               virtual inline int getValue() const
+                       { return mControlBase.getValue(); }
+               
+               virtual inline int reset() 
+                       { return mControlBase.reset(); }
+
+               virtual inline const ItemList& getItemList () 
+                       { return mMenuItems; }
+
+       private:
+               void queryMenuItems();
+       };
+}
+
+#endif //V4L2_MENUCONTROL_H_
diff --git a/extra_lib/include/avcap/linux/V4L2_Tuner.h b/extra_lib/include/avcap/linux/V4L2_Tuner.h
new file mode 100644 (file)
index 0000000..043acb4
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_TUNER_H_
+#define V4L2_TUNER_H_
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <sys/types.h>
+#include <string>
+
+#include "Tuner_avcap.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       
+       //! Implementation of the Tuner class for Video4Linux2 -devices.
+       
+       class V4L2_Tuner: public Tuner
+       {
+       private:
+
+               enum {
+                       TUNER_RADIO = V4L2_TUNER_RADIO,
+                       TUNER_ANALOG_TV = V4L2_TUNER_ANALOG_TV,
+               };
+               
+               enum {
+                       TUNER_CAP_LOW = V4L2_TUNER_CAP_LOW
+               };
+
+               typedef __u32        uint;
+
+       private:
+               V4L2_DeviceDescriptor*  mDeviceDescriptor;
+               int                     mIndex;
+               std::string     mName;
+               int                     mType;
+               int                     mCapabilities;
+               uint            mRangeHigh;
+               uint            mRangeLow;
+               double          mStep;
+               
+       public:
+               V4L2_Tuner(V4L2_DeviceDescriptor *dd, int index, const std::string &name, int type, int caps, uint high, uint low);
+               virtual ~V4L2_Tuner();
+               
+               inline bool isRadioTuner() const 
+                       { return mType & TUNER_RADIO; }
+
+               inline bool isTVTuner() const 
+                       { return mType & TUNER_ANALOG_TV; };
+
+               int setStereo();
+
+               int setMono();
+               
+               int setSAP();
+               
+               int setLang1();
+
+               int setLang2();
+
+               double getFreq() const;
+
+               inline double getFreqStep() const 
+                       { return mStep; }
+               
+               inline double getMinFreq() const 
+                       { return mRangeLow*mStep; }
+
+               inline double getMaxFreq() const 
+                       { return mRangeHigh*mStep; }
+               
+               inline const std::string getName() const
+                       { return mName; }
+               
+               int finetune(int maxsteps);
+               
+               int getAFCValue() const;
+               
+               int getSignalStrength() const;
+               
+               int increaseFreq();
+               
+               int decreaseFreq();             
+               
+               int setFreq(double f);
+               
+       private:
+               int setAudioMode(int mode);
+
+               int getAudioMode();
+       };
+}
+
+#endif // V4L2_TUNER_H_
+
diff --git a/extra_lib/include/avcap/linux/V4L2_VidCapManager.h b/extra_lib/include/avcap/linux/V4L2_VidCapManager.h
new file mode 100644 (file)
index 0000000..63d004a
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef V4L2_VIDCAPMANAGER_H_
+#define V4L2_VIDCAPMANAGER_H_
+
+#include <sys/types.h>
+#include <list>
+#include <time.h>
+
+#include "CaptureManager.h"
+
+namespace avcap
+{
+       class V4L2_DeviceDescriptor;
+       class FormatManager;
+       class IOBuffer;
+       class CaptureHandler;
+
+       //! The Video4Linux2-API video capture manager.
+       
+       /*! This class can be used to capture video data from a V4L2 video device. 
+        * The manager creates a defined number 
+        * of IOBuffers and permanently reuses them to store the captured data. 
+        * Since the number of these buffers is finite, it is important that applications 
+        * call IOBuffer::release() as soon as they don't need the data anymore. The
+        * access to the internal buffer-list is synchronized, so \c release() can be called
+        * from any thread at any time.
+        * Typical applications don't create objects of this class directly. They obtain
+        * an instance from CaptureDevice. */
+        
+       class V4L2_VidCapManager: public CaptureManager
+       {
+       public:
+               enum
+               {
+                       MAX_BUFFERS = 32,       //!< The maximum number of IOBuffers.
+                       DEFAULT_BUFFERS = 16    //!< The default number of used IOBuffers.
+               };
+               
+               enum IOMethod
+               {
+                       IO_METHOD_NOCAP = 0,
+               IO_METHOD_READ,
+               IO_METHOD_MMAP,
+               IO_METHOD_USERPTR,
+               };
+
+       private:
+               typedef std::list<IOBuffer*> IOBufList;
+               
+               V4L2_DeviceDescriptor   *mDeviceDescriptor;
+               FormatManager           *mFormatMgr;
+
+               IOBufList                       mBuffers;
+               int                                     mNumBufs;
+               int                                     mMethod;
+               int                                     mState;
+               pthread_t*                      mThread;
+               int                             mFinish;
+               pthread_mutex_t         mLock;
+               timeval                         mStartTime;
+
+               int                             mSequence;
+               int                                     mDTNumerator;
+               int                                     mDTDenominator;
+               int                                     mAvailableBuffers;
+       
+       public:
+               V4L2_VidCapManager(V4L2_DeviceDescriptor* dd, FormatManager* fmt_mgr, int nbufs = DEFAULT_BUFFERS);
+               
+               virtual ~V4L2_VidCapManager();
+               
+               int init();
+               
+               int destroy();
+               
+               int startCapture();
+
+               int stopCapture();
+               
+               int getNumIOBuffers();
+
+       private:
+               int start_read();
+               int start_mmap();
+               int start_userptr();
+
+               int stop_read();
+               int stop_mmap();
+               int stop_userptr();
+
+               IOBuffer* dequeue();
+               int enqueue(IOBuffer* buf);
+               
+               IOBuffer* findBuffer(int index);
+               static void run(void* mgr);
+               
+               void clearBuffers();
+               int getUsedBufferCount();
+       };
+}
+
+#endif // V4L2_VIDCAPMANAGER_H_
diff --git a/extra_lib/include/avcap/linux/error.h b/extra_lib/include/avcap/linux/error.h
new file mode 100644 (file)
index 0000000..217a25a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+* error.h Error handling
+* Copyright (C) 2000 - 2002 Arne Schirmacher <arne@schirmacher.de>
+*
+* This program 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.
+*
+* This program 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 this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define fail_neg(eval)  real_fail_neg  (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
+#define fail_null(eval) real_fail_null (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
+#define fail_if(eval)   real_fail_if   (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
+
+       void real_fail_neg ( int eval, const char * eval_str, const char * func, const char * file, int line );
+       void real_fail_null ( const void * eval, const char * eval_str, const char * func, const char * file, int line );
+       void real_fail_if ( bool eval, const char * eval_str, const char * func, const char * file, int line );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+#endif
+
diff --git a/extra_lib/include/avcap/linux/frame.h b/extra_lib/include/avcap/linux/frame.h
new file mode 100644 (file)
index 0000000..1a4cd0b
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+* frame.h -- utilities for process digital video frames
+* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
+*
+* This program 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.
+*
+* This program 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 this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAS_AVC_SUPPORT
+#define HAVE_LIBDV
+
+#ifndef _FRAME_H
+#define _FRAME_H 1
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+#include <string>
+using std::string;
+
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+#define DV_AUDIO_MAX_SAMPLES 1944
+
+#define FRAME_MAX_WIDTH 720
+#define FRAME_MAX_HEIGHT 576
+
+namespace avcap
+{
+       
+typedef struct Pack
+{
+       /// the five bytes of a packet
+       unsigned char data[ 5 ];
+}
+Pack;
+
+typedef struct TimeCode
+{
+       int hour;
+       int min;
+       int sec;
+       int frame;
+}
+TimeCode;
+
+
+typedef struct AudioInfo
+{
+       int frames;
+       int frequency;
+       int samples;
+       int channels;
+       int quantization;
+}
+AudioInfo;
+
+
+class VideoInfo
+{
+public:
+       int width;
+       int height;
+       bool isPAL;
+       TimeCode timeCode;
+       struct tm       recDate;
+
+       VideoInfo();
+
+       //    string GetTimeCodeString();
+       //    string GetRecDateString();
+}
+;
+
+
+class Frame
+{
+public:
+       /// enough space to hold a PAL frame
+       unsigned char data[ 144000 ];
+       /// the number of bytes written to the frame
+       int bytesInFrame;
+#ifdef HAVE_LIBDV
+
+       dv_decoder_t *decoder;
+#endif
+
+       int16_t *audio_buffers[ 4 ];
+
+public:
+       Frame();
+       ~Frame();
+
+       bool GetSSYBPack( int packNum, Pack &pack ) const;
+       bool GetVAUXPack( int packNum, Pack &pack ) const;
+       bool GetAAUXPack( int packNum, Pack &pack ) const;
+       bool GetTimeCode( TimeCode &timeCode ) const;
+       bool GetRecordingDate( struct tm &recDate ) const;
+       string GetRecordingDate( void ) const;
+       bool GetAudioInfo( AudioInfo &info ) const;
+       bool GetVideoInfo( VideoInfo &info ) const;
+       int GetFrameSize( void ) const;
+       float GetFrameRate() const;
+       bool IsPAL( void ) const;
+       bool IsNewRecording( void ) const;
+       bool IsNormalSpeed() const;
+       bool IsComplete( void ) const;
+       int ExtractAudio( void *sound ) const;
+       void ExtractHeader( void );
+
+#ifdef HAVE_LIBDV
+
+       void SetPreferredQuality( );
+       int ExtractAudio( int16_t **channels ) const;
+       int ExtractRGB( void *rgb );
+       int ExtractPreviewRGB( void *rgb );
+       int ExtractYUV( void *yuv );
+       int ExtractPreviewYUV( void *yuv );
+       bool IsWide( void ) const;
+       int GetWidth();
+       int GetHeight();
+       void SetRecordingDate( time_t *datetime, int frame );
+       void SetTimeCode( int frame );
+#endif
+
+       void Deinterlace( void *image, int bpp );
+
+private:
+#ifndef HAVE_LIBDV
+       /// flag for initializing the lookup maps once at startup
+       static bool maps_initialized;
+       /// lookup tables for collecting the shuffled audio data
+       static int palmap_ch1[ 2000 ];
+       static int palmap_ch2[ 2000 ];
+       static int palmap_2ch1[ 2000 ];
+       static int palmap_2ch2[ 2000 ];
+       static int ntscmap_ch1[ 2000 ];
+       static int ntscmap_ch2[ 2000 ];
+       static int ntscmap_2ch1[ 2000 ];
+       static int ntscmap_2ch2[ 2000 ];
+       static short compmap[ 4096 ];
+#endif
+};
+
+}
+
+#endif
+#endif
diff --git a/extra_lib/include/avcap/linux/ieee1394io.h b/extra_lib/include/avcap/linux/ieee1394io.h
new file mode 100644 (file)
index 0000000..7b2792f
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+* ieee1394io.cc -- asynchronously grabbing DV data
+* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
+*
+* This program 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.
+*
+* This program 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 this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef _IEEE1394IO_H
+#define _IEEE1394IO_H 1
+
+#include <libraw1394/raw1394.h>
+#include <libraw1394/csr.h>
+#include <libiec61883/iec61883.h>
+
+
+#include <string>
+using std::string;
+#include <deque>
+using std::deque;
+
+namespace avcap
+{
+       
+class Frame;
+
+class IEEE1394Reader
+{
+protected:
+       /// the number of frames that had to be thrown away because
+       /// our inFrames queue did not contain available frames
+       int droppedFrames;
+
+       /// the number of frames that are tainted because they are incomplete -
+       /// a packet was dropped
+       int incompleteFrames;
+
+       /// a pointer to the frame which is currently been transmitted
+       Frame   *currentFrame;
+
+       /// a list of empty frames
+       deque < Frame* > inFrames;
+
+       /// a list of already received frames
+       deque < Frame* > outFrames;
+
+public:
+
+       IEEE1394Reader( int channel = 63, int frames = 5 );
+       virtual ~IEEE1394Reader();
+
+       // Mutex protected public methods
+       virtual bool StartThread( void ) = 0;
+       virtual void StopThread( void ) = 0;
+       Frame* GetFrame( void );
+       
+       void DoneWithFrame( Frame* );
+       int GetDroppedFrames( void );
+       int GetIncompleteFrames( void );
+       int GetOutQueueSize( void )
+       {
+               return outFrames.size();
+       }
+       int GetInQueueSize( void )
+       {
+               return inFrames.size();
+       }
+
+       // These two public methods are not mutex protected
+       virtual bool Open( void ) = 0;
+       virtual void Close( void ) = 0;
+
+       bool WaitForAction( int seconds = 0 );
+       virtual void TriggerAction( );
+
+       virtual bool StartReceive( void ) = 0;
+       virtual void StopReceive( void ) = 0;
+
+protected:
+       /// the iso channel we listen to (typically == 63)
+       int     channel;
+
+       /// contains information about our thread after calling StartThread
+       pthread_t thread;
+
+       /// this mutex protects capture related variables that could possibly
+       /// accessed from two threads at the same time
+       pthread_mutex_t mutex;
+
+       // This condition and mutex are used to indicate when new frames are
+       // received
+       pthread_mutex_t condition_mutex;
+       pthread_cond_t condition;
+
+       /// A state variable for starting and stopping thread
+       bool isRunning;
+
+       void Flush( void );
+};
+
+
+typedef void (*BusResetHandler)( void* );
+typedef void* BusResetHandlerData;
+
+class CaptureHandler;
+
+class iec61883Reader: public IEEE1394Reader
+{
+private:
+
+       /// the interface card to use (typically == 0)
+       int     m_port;
+
+       /// the handle to libraw1394
+       raw1394handle_t m_handle;
+
+       /// the handle to libiec61883
+       iec61883_dv_fb_t m_iec61883dv;
+
+       BusResetHandler m_resetHandler;
+       const void* m_resetHandlerData;
+
+       CaptureHandler* m_captureHandler;
+       
+public:
+       iec61883Reader( int port = 0, int channel = 63, int buffers = 5, 
+               BusResetHandler = 0, BusResetHandlerData = 0 );
+       ~iec61883Reader();
+
+       bool Open( void );
+       void Close( void );
+       bool StartReceive( void );
+       void StopReceive( void );
+       bool StartThread( void );
+       void StopThread( void );
+       int Handler( int length, int complete, unsigned char *data );
+       void *Thread();
+       void ResetHandler( void );
+               
+
+private:
+       static int ResetHandlerProxy( raw1394handle_t handle, unsigned int generation );
+       static int HandlerProxy( unsigned char *data, int length, int complete, 
+               void *callback_data );
+       static void* ThreadProxy( void *arg );
+};
+
+
+class iec61883Connection
+{
+private:
+       raw1394handle_t m_handle;
+       nodeid_t m_node;
+       int m_channel;
+       int m_bandwidth;
+       int m_outputPort;
+       int m_inputPort;
+
+public:
+
+       iec61883Connection( int port, int node );
+       ~iec61883Connection();
+
+       static void CheckConsistency( int port, int node );
+       int GetChannel( void ) const
+       {
+               return m_channel;
+       }
+       int Reconnect( void );
+};
+
+}
+
+#endif
+#endif
diff --git a/extra_lib/include/avcap/linux/ivtv.h b/extra_lib/include/avcap/linux/ivtv.h
new file mode 100644 (file)
index 0000000..55bb9de
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+    Public ivtv API header
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+
+    VBI portions:
+    Copyright (C) 2004  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LINUX_IVTV_H
+#define LINUX_IVTV_H
+
+// 00 = Program stream
+// 01 = Transport stream
+// 02 = MPEG1 stream
+// 10 or 0a = DVD stream
+// 11 or 0b = VCD stream
+// 12 or 0c = SVCD stream
+// 13 or 0d = DVD-Special 1
+// 14 or 0e = DVD-Special 2
+
+/* Stream types */
+#define IVTV_STREAM_PS         0
+#define IVTV_STREAM_TS         1
+#define IVTV_STREAM_MPEG1      2
+#define IVTV_STREAM_PES_AV     3
+#define IVTV_STREAM_PES_V      5
+#define IVTV_STREAM_PES_A      7
+#define IVTV_STREAM_DVD                10
+#define IVTV_STREAM_VCD                11
+#define IVTV_STREAM_SVCD       12
+#define IVTV_STREAM_DVD_S1     13
+#define IVTV_STREAM_DVD_S2     14
+
+#define IVTV_SLICED_TELETEXT_B         (1 << 0)
+#define IVTV_SLICED_CAPTION_625        (1 << 1)
+#define IVTV_SLICED_CAPTION_525        (1 << 2)
+#define IVTV_SLICED_WSS_625    (1 << 3)
+#define IVTV_SLICED_VPS                (1 << 4)
+
+struct ivtv_sliced_vbi_format {
+       unsigned long service_set;      /* one or more of the IVTV_SLICED_ defines */
+       unsigned long packet_size;      /* the size in bytes of the ivtv_sliced_data packet */
+       unsigned long io_size;          /* maximum number of bytes passed by one read() call */
+       unsigned long reserved;
+};
+
+/* This structure is the same as the proposed v4l2_sliced_data structure */
+/* id is one of the VBI_SLICED_ flags. */
+struct ivtv_sliced_data {
+       unsigned long id;
+       unsigned long line;
+       unsigned char data[];
+};
+
+/* The four bit VBI data type found in the embedded VBI data of an
+   MPEG stream has one of the following values: */
+#define VBI_TYPE_TELETEXT      0x1     // Teletext (uses lines 6-22 for PAL, 10-21 for NTSC)
+#define VBI_TYPE_CC            0x4     // Closed Captions (line 21 NTSC, line 22 PAL)
+#define VBI_TYPE_WSS           0x5     // Wide Screen Signal (line 20 NTSC, line 23 PAL)
+#define VBI_TYPE_VPS           0x7     // Video Programming System (PAL) (line 16)
+
+/* These data types are not (yet?) used but are already reserved
+   for future use. */
+#ifdef IVTV_INTERNAL
+#define VBI_TYPE_NABST                 0x2     // NABST (NTSC)
+#define VBI_TYPE_MOJI          0x3     // MOJI (NTSC)
+#define VBI_TYPE_VITC          0x6     // Vertical Interval Time Code
+#define VBI_TYPE_GEMSTAR2X     0x7     // Gemstar TV Guide (NTSC)
+#define VBI_TYPE_GEMSTAR1X     0x8     // Gemstar TV Guide (NTSC)
+#endif
+
+/* device ioctls should use the range 29-199 */
+#define IVTV_IOC_START_DECODE      _IOW ('@', 29, struct ivtv_cfg_start_decode)
+#define IVTV_IOC_STOP_DECODE       _IOW ('@', 30, struct ivtv_cfg_stop_decode)
+#define IVTV_IOC_G_SPEED           _IOR ('@', 31, struct ivtv_speed)
+#define IVTV_IOC_S_SPEED           _IOW ('@', 32, struct ivtv_speed)
+#define IVTV_IOC_DEC_STEP          _IOW ('@', 33, int)
+#define IVTV_IOC_DEC_FLUSH         _IOW ('@', 34, int)
+#define IVTV_IOC_S_VBI_MODE               _IOWR('@', 35, struct ivtv_sliced_vbi_format)
+#define IVTV_IOC_G_VBI_MODE               _IOR ('@', 36, struct ivtv_sliced_vbi_format)
+#define IVTV_IOC_PLAY             _IO  ('@', 37)
+#define IVTV_IOC_PAUSE            _IO  ('@', 38)
+#define IVTV_IOC_FRAMESYNC        _IOR ('@', 39, struct ivtv_ioctl_framesync)
+#define IVTV_IOC_GET_TIMING       _IOR ('@', 40, struct ivtv_ioctl_framesync)
+#define IVTV_IOC_S_SLOW_FAST       _IOW ('@', 41, struct ivtv_slow_fast)
+#define IVTV_IOC_S_START_DECODE    _IOW ('@', 42, struct ivtv_cfg_start_decode)
+#define IVTV_IOC_S_STOP_DECODE     _IOW ('@', 43, struct ivtv_cfg_stop_decode)
+#define IVTV_IOC_GET_FB            _IOR ('@', 44, int)
+#define IVTV_IOC_G_CODEC           _IOR ('@', 48, struct ivtv_ioctl_codec)
+#define IVTV_IOC_S_CODEC           _IOW ('@', 49, struct ivtv_ioctl_codec)
+#define IVTV_IOC_S_GOP_END         _IOWR('@', 50, int)
+#define IVTV_IOC_S_VBI_PASSTHROUGH _IOW ('@', 51, int)
+#define IVTV_IOC_G_VBI_PASSTHROUGH _IOR ('@', 52, int)
+#define IVTV_IOC_PASSTHROUGH       _IOW ('@', 53, int)
+#define IVTV_IOC_S_VBI_EMBED       _IOW ('@', 54, int)
+#define IVTV_IOC_G_VBI_EMBED       _IOR ('@', 55, int)
+#define IVTV_IOC_PAUSE_ENCODE      _IO  ('@', 56)
+#define IVTV_IOC_RESUME_ENCODE     _IO  ('@', 57)
+
+#define PACK_ME __attribute__((packed))
+// Note: You only append to this structure, you never reorder the members,
+// you never play tricks with its alignment, you never change the size of
+// anything.
+#define IVTV_DRIVER_INFO_MAX_COMMENT_LENGTH 100
+struct ivtv_driver_info {
+       uint32_t size;    // size of this structure
+       uint32_t version; // version bits 31-16 = major, 15-8 = minor,
+                                         // 7-0 = patchlevel
+       char comment[IVTV_DRIVER_INFO_MAX_COMMENT_LENGTH];
+} PACK_ME;
+
+#define IVTV_DRIVER_INFO_V1_SIZE 108
+
+#define IVTV_IOC_G_DRIVER_INFO _IOWR('@', 100, struct ivtv_driver_info *)
+
+// Version info
+// Note: never use the _INTERNAL versions of these macros
+
+// Internal version macros, don't use these
+#define IVTV_VERSION_NUMBER_INTERNAL(name) name##_version_int
+#define IVTV_VERSION_STRING_INTERNAL(name) name##_version_string
+#define IVTV_VERSION_COMMENT_INTERNAL(name) name##_comment_string
+
+#define IVTV_VERSION_EXTERN_NUMBER_INTERNAL(name) \
+       extern uint32_t IVTV_VERSION_NUMBER_INTERNAL(name)
+#define IVTV_VERSION_EXTERN_STRING_INTERNAL(name) \
+       extern const char * const IVTV_VERSION_STRING_INTERNAL(name)
+#define IVTV_VERSION_EXTERN_COMMENT_INTERNAL(name) \
+       extern const char * const IVTV_VERSION_COMMENT_INTERNAL(name)
+
+#define IVTV_VERSION_MAJOR_INTERNAL(name) \
+       (0xFF & (IVTV_VERSION_NUMBER_INTERNAL(name) >> 16))
+#define IVTV_VERSION_MINOR_INTERNAL(name) \
+       (0xFF & (IVTV_VERSION_NUMBER_INTERNAL(name) >> 8))
+#define IVTV_VERSION_PATCHLEVEL_INTERNAL(name) \
+       (0xFF & (IVTV_VERSION_NUMBER_INTERNAL(name)))
+
+// External version macros
+#define IVTV_VERSION_NUMBER(name) IVTV_VERSION_NUMBER_INTERNAL(name)
+#define IVTV_VERSION_STRING(name) IVTV_VERSION_STRING_INTERNAL(name)
+#define IVTV_VERSION_COMMENT(name) IVTV_VERSION_COMMENT_INTERNAL(name)
+#define IVTV_VERSION_EXTERN_NUMBER(name) \
+       IVTV_VERSION_EXTERN_NUMBER_INTERNAL(name)
+#define IVTV_VERSION_EXTERN_STRING(name) \
+       IVTV_VERSION_EXTERN_STRING_INTERNAL(name)
+#define IVTV_VERSION_EXTERN_COMMENT(name) \
+       IVTV_VERSION_EXTERN_COMMENT_INTERNAL(name)
+
+#define IVTV_VERSION_INFO_NAME ivtv_rev
+
+IVTV_VERSION_EXTERN_NUMBER(IVTV_VERSION_INFO_NAME);
+IVTV_VERSION_EXTERN_STRING(IVTV_VERSION_INFO_NAME);
+IVTV_VERSION_EXTERN_COMMENT(IVTV_VERSION_INFO_NAME);
+
+/* Custom v4l controls */
+#ifndef V4L2_CID_PRIVATE_BASE
+#define V4L2_CID_PRIVATE_BASE                  0x08000000
+#endif
+
+#define V4L2_CID_IVTV_FREQ             (V4L2_CID_PRIVATE_BASE)
+#define V4L2_CID_IVTV_ENC              (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_IVTV_BITRATE          (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_IVTV_MONO             (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_IVTV_JOINT            (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_IVTV_EMPHASIS         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_IVTV_CRC              (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_IVTV_COPYRIGHT        (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_IVTV_GEN              (V4L2_CID_PRIVATE_BASE + 8)
+
+#define V4L2_CID_IVTV_DEC_SMOOTH_FF    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_IVTV_DEC_FR_MASK      (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_IVTV_DEC_SP_MUTE      (V4L2_CID_PRIVATE_BASE + 11)
+#define V4L2_CID_IVTV_DEC_FR_FIELD     (V4L2_CID_PRIVATE_BASE + 12)
+#define V4L2_CID_IVTV_DEC_AUD_SKIP     (V4L2_CID_PRIVATE_BASE + 13)
+#define V4L2_CID_IVTV_DEC_NUM_BUFFERS  (V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_IVTV_DEC_PREBUFFER    (V4L2_CID_PRIVATE_BASE + 15)
+
+struct ivtv_ioctl_framesync {
+       uint32_t frame;
+       uint64_t pts;
+       uint64_t scr;
+};
+
+struct ivtv_speed {
+       int scale;      /* 1-?? (50 for now) */
+       int smooth;     /* Smooth mode when in slow/fast mode */
+       int speed;      /* 0 = slow, 1 = fast */
+       int direction;  /* 0 = forward, 1 = reverse (not supportd */
+       int fr_mask;    /* 0 = I, 1 = I,P, 2 = I,P,B    2 = default!*/
+       int b_per_gop;  /* frames per GOP (reverse only) */
+       int aud_mute;   /* Mute audio while in slow/fast mode */
+       int fr_field;   /* 1 = show every field, 0 = show every frame */
+       int mute;       /* # of audio frames to mute on playback resume */
+};
+
+struct ivtv_slow_fast {
+       int speed; /* 0 = slow, 1 = fast */
+       int scale; /* 1-?? (50 for now) */
+};      
+
+struct ivtv_cfg_start_decode {
+       uint32_t     gop_offset;        /*Frames in GOP to skip before starting */
+       uint32_t     muted_audio_frames;/* #of audio frames to mute */
+};
+
+struct ivtv_cfg_stop_decode {
+       int             hide_last; /* 1 = show black after stop,
+                                     0 = show last frame */
+       uint64_t        pts_stop; /* PTS to stop at */
+};
+
+
+/* For use with IVTV_IOC_G_CODEC and IVTV_IOC_S_CODEC */
+struct ivtv_ioctl_codec {
+        uint32_t aspect;
+        uint32_t audio_bitmask;
+        uint32_t bframes;
+        uint32_t bitrate_mode;
+        uint32_t bitrate;
+        uint32_t bitrate_peak;
+        uint32_t dnr_mode;
+        uint32_t dnr_spatial;
+        uint32_t dnr_temporal;
+        uint32_t dnr_type;
+        uint32_t framerate;    /* read only, ignored on write */
+        uint32_t framespergop; /* read only, ignored on write */
+        uint32_t gop_closure;
+        uint32_t pulldown;
+        uint32_t stream_type;
+};
+
+
+/* Framebuffer external API */
+
+struct ivtvfb_ioctl_state_info {
+  unsigned long status;
+  unsigned long alpha;
+};
+
+struct ivtvfb_ioctl_blt_copy_args {
+  int x, y, width, height, source_offset, source_stride;
+};
+
+struct ivtvfb_ioctl_blt_fill_args {
+    int rasterop, alpha_mode, alpha_mask, width, height, x, y;
+    unsigned int destPixelMask, colour;
+
+};
+
+struct ivtvfb_ioctl_dma_host_to_ivtv_args {
+  void* source;
+  unsigned long dest_offset;
+  int count;
+};
+
+struct ivtvfb_ioctl_get_frame_buffer {
+  void* mem;
+  int   size;
+  int   sizex;
+  int   sizey;
+};
+
+struct ivtv_osd_coords {
+  unsigned long offset;
+  unsigned long max_offset;
+  int pixel_stride;
+  int lines;
+  int x;
+  int y;
+};
+
+struct rectangle {
+  int x0;
+  int y0;
+  int x1;
+  int y1;
+};
+
+/* Framebuffer ioctls should use the range 1 - 28 */
+#define IVTVFB_IOCTL_GET_STATE          _IOR('@', 1, struct ivtvfb_ioctl_state_info)
+#define IVTVFB_IOCTL_SET_STATE          _IOW('@', 2, struct ivtvfb_ioctl_state_info)
+#define IVTVFB_IOCTL_PREP_FRAME         _IOW('@', 3, struct ivtvfb_ioctl_dma_host_to_ivtv_args)
+#define IVTVFB_IOCTL_BLT_COPY           _IOW('@', 4, struct ivtvfb_ioctl_blt_copy_args)
+#define IVTVFB_IOCTL_GET_ACTIVE_BUFFER  _IOR('@', 5, struct ivtv_osd_coords)
+#define IVTVFB_IOCTL_SET_ACTIVE_BUFFER  _IOW('@', 6, struct ivtv_osd_coords)
+#define IVTVFB_IOCTL_GET_FRAME_BUFFER   _IOR('@', 7, struct ivtvfb_ioctl_get_frame_buffer)
+#define IVTVFB_IOCTL_BLT_FILL           _IOW('@', 8, struct ivtvfb_ioctl_blt_fill_args)
+#define IVTVFB_IOCTL_PREP_FRAME_BUF     _IOW('@', 9, struct ivtvfb_ioctl_dma_host_to_ivtv_args)
+#define IVTVFB_IOCTL_PREP_FRAME_YUV     _IOW('@', 10, struct ivtvfb_ioctl_dma_host_to_ivtv_args)
+
+#define IVTVFB_STATUS_ENABLED           (1 << 0)
+#define IVTVFB_STATUS_GLOBAL_ALPHA      (1 << 1)
+#define IVTVFB_STATUS_LOCAL_ALPHA       (1 << 2)
+#define IVTVFB_STATUS_FLICKER_REDUCTION (1 << 3)
+
+#ifdef IVTV_INTERNAL
+/* Do not use these structures and ioctls in code that you want to release.
+   Only to be used for testing and by the utilities ivtvctl, ivtvfbctl and fwapi. */
+
+#define IVTV_MBOX_MAX_DATA 16
+
+struct ivtv_ioctl_fwapi {
+       uint32_t cmd;
+       uint32_t result;
+       int32_t args;
+       uint32_t data[IVTV_MBOX_MAX_DATA];
+};
+
+struct ivtv_ioctl_event {
+        uint32_t type;
+        uint32_t mbox;
+       struct ivtv_ioctl_fwapi api;
+};
+
+struct ivtv_saa71xx_reg {
+       unsigned char reg;
+       unsigned char val;
+};
+
+struct ivtv_itvc_reg {
+       uint32_t reg;
+       uint32_t val;
+};
+
+struct ivtv_msp_matrix {
+       int input;
+       int output;
+};
+
+/* Debug flags */
+#define IVTV_DEBUG_ERR   (1 << 0)
+#define IVTV_DEBUG_INFO  (1 << 1)
+#define IVTV_DEBUG_API   (1 << 2)
+#define IVTV_DEBUG_DMA   (1 << 3)
+#define IVTV_DEBUG_IOCTL (1 << 4)
+#define IVTV_DEBUG_I2C   (1 << 5)
+#define IVTV_DEBUG_IRQ   (1 << 6)
+#define IVTV_DEBUG_DEC   (1 << 7)
+
+/* BLT RasterOps */
+#define IVTV_BLT_RASTER_ZERO           0
+#define IVTV_BLT_RASTER_NOTDEST_AND_NOTSRC     1
+#define IVTV_BLT_RASTER_NOTDEST_AND_SRC        2
+#define IVTV_BLT_RASTER_NOTDEST                3
+#define IVTV_BLT_RASTER_DEST_AND_NOTSRC        4
+#define IVTV_BLT_RASTER_NOTSRC         5
+#define IVTV_BLT_RASTER_DEST_XOR_SRC   6
+#define IVTV_BLT_RASTER_NOTDEST_OR_NOTSRC      7
+/* #define IVTV_BLT_RASTER_NOTDEST_AND_NOTSRC  8 */ /* Same as 1 */
+#define IVTV_BLT_RASTER_DEST_XNOR_SRC  9
+#define IVTV_BLT_RASTER_SRC                    10
+#define IVTV_BLT_RASTER_NOTDEST_OR_SRC 11
+#define IVTV_BLT_RASTER_DEST           12
+#define IVTV_BLT_RASTER_DEST_OR_NOTSRC 13
+#define IVTV_BLT_RASTER_DEST_OR_SRC            14
+#define IVTV_BLT_RASTER_ONE                    15
+
+/* BLT Alpha blending */
+
+#define IVTV_BLT_ALPHABLEND_SRC                0x01
+#define IVTV_BLT_ALPHABLEND_DEST       0x10
+#define IVTV_BLT_ALPHABLEND_DEST_X_SRC 0x11 /* dest x src +1 , = zero if both zero */
+
+
+/* Internal ioctls should use the range 200-255 */
+#define IVTV_IOC_S_DEBUG_LEVEL     _IOWR('@', 200, int)
+#define IVTV_IOC_G_DEBUG_LEVEL     _IOR ('@', 201, int)
+#define IVTV_IOC_RELOAD_FW         _IO  ('@', 202)
+#define IVTV_IOC_ZCOUNT            _IO  ('@', 203) 
+#define IVTV_IOC_FWAPI             _IOWR('@', 204, struct ivtv_ioctl_fwapi)
+#define IVTV_IOC_EVENT_SETUP       _IOWR('@', 205, struct ivtv_ioctl_event)
+#define IVTV_IOC_G_SAA7115_REG     _IOWR('@', 206, struct ivtv_saa71xx_reg)
+#define IVTV_IOC_S_SAA7115_REG     _IOW ('@', 207, struct ivtv_saa71xx_reg)
+#define IVTV_IOC_G_SAA7127_REG     _IOWR('@', 208, struct ivtv_saa71xx_reg)
+#define IVTV_IOC_S_SAA7127_REG     _IOW ('@', 209, struct ivtv_saa71xx_reg)
+#define IVTV_IOC_S_MSP_MATRIX      _IOW ('@', 210, struct ivtv_msp_matrix)
+#define IVTV_IOC_G_ITVC_REG        _IOWR('@', 211, struct ivtv_itvc_reg)
+#define IVTV_IOC_S_ITVC_REG        _IOW ('@', 212, struct ivtv_itvc_reg)
+
+#endif
+
+#endif
+
diff --git a/extra_lib/include/avcap/linux/pwc-ioctl.h b/extra_lib/include/avcap/linux/pwc-ioctl.h
new file mode 100644 (file)
index 0000000..63754ab
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program 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.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+                          changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+               PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC              VIDeo IOCtl prefix
+         PWC           Philps WebCam
+            G           optional: Get
+            S           optional: Set
+             ...       the function
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 10)
+/* Compatibility for older kernel */
+typedef __u16 __le16;
+#endif
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF      0x00
+#define PSZ_QSIF       0x01
+#define PSZ_QCIF       0x02
+#define PSZ_SIF                0x03
+#define PSZ_CIF                0x04
+#define PSZ_VGA                0x05
+#define PSZ_MAX                6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT          16
+#define PWC_FPS_MASK           0x00FF0000
+#define PWC_FPS_FRMASK         0x003F0000
+#define PWC_FPS_SNAPSHOT       0x00400000
+#define PWC_QLT_MASK           0x03000000
+#define PWC_QLT_SHIFT          24
+
+
+/* structure for transferring x & y coordinates */
+struct pwc_coord
+{
+       int x, y;               /* guess what */
+       int size;               /* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+       char name[32];
+       int type;
+};
+
+struct pwc_serial
+{
+       char serial[30];        /* String with serial number. Contains terminating 0 */
+};
+       
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR          0
+#define PWC_WB_OUTDOOR         1
+#define PWC_WB_FL              2
+#define PWC_WB_MANUAL          3
+#define PWC_WB_AUTO            4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). 
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside 
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; 
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/   
+struct pwc_whitebalance
+{
+       int mode;
+       int manual_red, manual_blue;    /* R/W */
+       int read_red, read_blue;        /* R/O */
+};
+
+/* 
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and 
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+       int control_speed;
+       int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+       int led_on;                     /* Led on-time; range = 0..25000 */
+       int led_off;                    /* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+       int width;
+       int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN            0x01
+#define PWC_MPT_TILT           0x02
+#define PWC_MPT_TIMEOUT                0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the 
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */   
+struct pwc_mpt_angles
+{
+       int absolute;           /* write-only */
+       int pan;                /* degrees * 100 */
+       int tilt;               /* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+       int pan_min, pan_max;           /* degrees * 100 */
+       int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+       int status;
+       int time_pan;
+       int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */   
+struct pwc_video_command
+{
+       int type;               /* camera type (645, 675, 730, etc.) */
+       int release;            /* release number */
+
+        int size;              /* one of PSZ_* */
+        int alternate;
+       int command_len;        /* length of USB video command */
+       unsigned char command_buf[13];  /* Actual USB video command */
+       int bandlength;         /* >0 = compressed */
+       int frame_size;         /* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR       0x0001
+#define PWCX_FLAG_BAYER                0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER         _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER         _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY       _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL                _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL                _IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL       _IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE         _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC          _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC          _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER      _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED     _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED     _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR      _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR      _IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT    _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT    _IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER      _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER      _IOR('v', 208, int)  
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE     _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE     _IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE     _IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */ 
+#define VIDIOCPWCMPTRESET      _IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE     _IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE     _IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE     _IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS     _IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD       _IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE     _IOR('v', 216, struct pwc_table_init_buffer)
+
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to 
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;                /* type of the webcam */
+   __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];      /* the four byte of the command (in case of nala,
+                          only the first 3 bytes is filled) */
+   __u8   rawframe[0]; /* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
+#endif
diff --git a/extra_lib/include/avcap/linux/raw1394util.h b/extra_lib/include/avcap/linux/raw1394util.h
new file mode 100644 (file)
index 0000000..5a5c433
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef HAS_AVC_SUPPORT
+
+#ifndef RAW1394UTIL_H
+#define RAW1394UTIL_H 1
+
+#include <libraw1394/raw1394.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+       int raw1394_get_num_ports( void );
+       raw1394handle_t raw1394_open( int port );
+       void raw1394_close( raw1394handle_t handle );
+       int discoverAVC( int * port, octlet_t* guid );
+       void reset_bus( int port );
+
+#ifdef __cplusplus
+}
+
+#endif
+#endif
+
+#endif // HAS_AVC_SUPPORT
diff --git a/extra_lib/include/avcap/linux/uvc_compat.h b/extra_lib/include/avcap/linux/uvc_compat.h
new file mode 100644 (file)
index 0000000..e400499
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _UVC_COMPAT_H
+#define _UVC_COMPAT_H
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+/*
+ * Extended control API
+ */
+struct v4l2_ext_control
+{
+       __u32 id;
+       __u32 reserved2[2];
+       union {
+               __s32 value;
+               __s64 value64;
+               void *reserved;
+       };
+} __attribute__ ((packed));
+
+struct v4l2_ext_controls
+{
+       __u32 ctrl_class;
+       __u32 count;
+       __u32 error_idx;
+       __u32 reserved[2];
+       struct v4l2_ext_control *controls;
+};
+
+/* Values for ctrl_class field */
+#define V4L2_CTRL_CLASS_USER           0x00980000      /* Old-style 'user' controls */
+#define V4L2_CTRL_CLASS_MPEG           0x00990000      /* MPEG-compression controls */
+
+#define V4L2_CTRL_ID_MASK              (0x0fffffff)
+#define V4L2_CTRL_ID2CLASS(id)         ((id) & 0x0fff0000UL)
+#define V4L2_CTRL_DRIVER_PRIV(id)      (((id) & 0xffff) >= 0x1000)
+
+/* User-class control IDs defined by V4L2 */
+#undef V4L2_CID_BASE
+#define V4L2_CID_BASE                  (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_USER_BASE             V4L2_CID_BASE
+#define V4L2_CID_USER_CLASS            (V4L2_CTRL_CLASS_USER | 1)
+       
+#define VIDIOC_G_EXT_CTRLS             _IOWR ('V', 71, struct v4l2_ext_controls)
+#define VIDIOC_S_EXT_CTRLS             _IOWR ('V', 72, struct v4l2_ext_controls)
+#define VIDIOC_TRY_EXT_CTRLS           _IOWR ('V', 73, struct v4l2_ext_controls)
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+/*
+ * Frame size and frame rate enumeration
+ *
+ * Included in Linux 2.6.19
+ */
+enum v4l2_frmsizetypes
+{
+       V4L2_FRMSIZE_TYPE_DISCRETE      = 1,
+       V4L2_FRMSIZE_TYPE_CONTINUOUS    = 2,
+       V4L2_FRMSIZE_TYPE_STEPWISE      = 3,
+};
+
+struct v4l2_frmsize_discrete
+{
+       __u32                   width;          /* Frame width [pixel] */
+       __u32                   height;         /* Frame height [pixel] */
+};
+
+struct v4l2_frmsize_stepwise
+{
+       __u32                   min_width;      /* Minimum frame width [pixel] */
+       __u32                   max_width;      /* Maximum frame width [pixel] */
+       __u32                   step_width;     /* Frame width step size [pixel] */
+       __u32                   min_height;     /* Minimum frame height [pixel] */
+       __u32                   max_height;     /* Maximum frame height [pixel] */
+       __u32                   step_height;    /* Frame height step size [pixel] */
+};
+
+struct v4l2_frmsizeenum
+{
+       __u32                   index;          /* Frame size number */
+       __u32                   pixel_format;   /* Pixel format */
+       __u32                   type;           /* Frame size type the device supports. */
+
+        union {                                        /* Frame size */
+               struct v4l2_frmsize_discrete    discrete;
+               struct v4l2_frmsize_stepwise    stepwise;
+       };
+
+       __u32   reserved[2];                    /* Reserved space for future use */
+};
+
+enum v4l2_frmivaltypes
+{
+       V4L2_FRMIVAL_TYPE_DISCRETE      = 1,
+       V4L2_FRMIVAL_TYPE_CONTINUOUS    = 2,
+       V4L2_FRMIVAL_TYPE_STEPWISE      = 3,
+};
+
+struct v4l2_frmival_stepwise
+{
+       struct v4l2_fract       min;            /* Minimum frame interval [s] */
+       struct v4l2_fract       max;            /* Maximum frame interval [s] */
+       struct v4l2_fract       step;           /* Frame interval step size [s] */
+};
+
+struct v4l2_frmivalenum
+{
+       __u32                   index;          /* Frame format index */
+       __u32                   pixel_format;   /* Pixel format */
+       __u32                   width;          /* Frame width */
+       __u32                   height;         /* Frame height */
+       __u32                   type;           /* Frame interval type the device supports. */
+
+       union {                                 /* Frame interval */
+               struct v4l2_fract               discrete;
+               struct v4l2_frmival_stepwise    stepwise;
+       };
+
+       __u32   reserved[2];                    /* Reserved space for future use */
+};
+
+#define VIDIOC_ENUM_FRAMESIZES         _IOWR ('V', 74, struct v4l2_frmsizeenum)
+#define VIDIOC_ENUM_FRAMEINTERVALS     _IOWR ('V', 75, struct v4l2_frmivalenum)
+#endif
+
+
+#endif /* _UVC_COMPAT_H */
+
diff --git a/extra_lib/include/avcap/log.h b/extra_lib/include/avcap/log.h
new file mode 100644 (file)
index 0000000..aff6824
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef AVCAP_LOG_H
+#define AVCAP_LOG_H
+
+#include <sstream>
+#include <iostream>
+
+static inline void logDebug(const std::string& msg)
+{
+#ifdef DEBUG
+       std::cerr<<msg<<std::endl;
+#endif 
+}
+
+static inline void logDebug(const std::string& msg, int err)
+{
+#ifdef DEBUG
+       std::cerr<<msg<<" "<<err<<std::endl;
+#endif 
+}
+
+#endif
diff --git a/extra_lib/include/avcap/osx/QT_ConnectorManager.h b/extra_lib/include/avcap/osx/QT_ConnectorManager.h
new file mode 100644 (file)
index 0000000..bd71a3d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef QT_CONNECTORMANAGER_H
+#define QT_CONNECTORMANAGER_H
+
+#include <list>
+
+#include "ConnectorManager.h"
+
+namespace avcap
+{      
+       class QT_DeviceDescriptor;
+       
+       //! This class implements the ConnectorManager for QuickTime-devices. 
+       
+       /*! Such devices don't have Connectors the user could chose. So the abstract
+        * methods are implemented as noops. */
+       
+       class QT_ConnectorManager: public ConnectorManager
+       {       
+       public:
+       
+               QT_ConnectorManager(QT_DeviceDescriptor *dd);
+               
+               virtual ~QT_ConnectorManager();
+               void query();
+       };
+}
+
+#endif // QT_CONNECTORMANAGER_H
+
diff --git a/extra_lib/include/avcap/osx/QT_Control.h b/extra_lib/include/avcap/osx/QT_Control.h
new file mode 100644 (file)
index 0000000..40837ce
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef QT_CONTROL_H_
+#define QT_CONTROL_H_
+
+#include <string>
+#include <list>
+
+#include "Control_avcap.h"
+
+namespace avcap
+{
+       // forward declaration
+       class QT_DeviceDescriptor;
+       
+       //! Implementation of a Control for the QuickTime-implementation of CaptureDevice.
+
+       /*! The QT API supports only controls for brightness, hue, colour, contrast, depth and whiteness.
+        * They are all integer values between 0 and 65535.*/
+        
+       class QT_Control: public IntegerControl
+       {
+       public:
+               enum Ctrl {
+                       BRIGHTNESS = 0,
+                       BLACKLEVEL,
+                       WHITELEVEL,
+                       HUE,
+                       CONTRAST,
+                       SATURATION,
+                       SHARPNESS
+               };
+       
+       private:        
+               static std::string mNames[7];
+               
+               QT_DeviceDescriptor*    mDescriptor;
+               Ctrl                                    mType;
+               unsigned short                  mDefaultValue;
+               Interval                                mInterval;
+               
+       public:
+               QT_Control(QT_DeviceDescriptor* dd, Ctrl type);
+
+               virtual inline ~QT_Control()
+                       {}
+               
+               virtual inline int getId() const 
+                       { return mType; }
+
+               virtual inline int getDefaultValue() const
+                       { return mDefaultValue; }
+
+               virtual const std::string& getName() const;
+               
+               virtual int setValue(int val);
+
+               virtual int getValue() const;
+               
+               virtual int reset();
+               
+               virtual inline const Interval& getInterval() const 
+                       { return mInterval; }
+       };
+}
+
+#endif // QT_CONTROL_H_
+
diff --git a/extra_lib/include/avcap/osx/QT_ControlManager.h b/extra_lib/include/avcap/osx/QT_ControlManager.h
new file mode 100644 (file)
index 0000000..5c33d25
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef QT_CONTROLMANAGER_H
+#define QT_CONTROLMANAGER_H
+
+#include <string>
+#include <list>
+
+#include "ControlManager.h"
+
+namespace avcap
+{
+
+class QT_DeviceDescriptor;
+
+       //! Implementation of the ControlManager for the QuickTime-implementation of CaptureDevice.
+        
+       class QT_ControlManager: public ControlManager
+       {
+       public:
+
+               QT_ControlManager(QT_DeviceDescriptor *dd);
+               
+               virtual ~QT_ControlManager();
+               
+               virtual void query();
+       };
+}
+
+#endif // QT_CONTROLMANAGER_H
+
diff --git a/extra_lib/include/avcap/osx/QT_Device.h b/extra_lib/include/avcap/osx/QT_Device.h
new file mode 100644 (file)
index 0000000..4e10a0c
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef QT_DEVICE_H
+#define QT_DEVICE_H
+
+#include <string>
+#include <list>
+
+#include "DeviceDescriptor.h"
+#include "CaptureDevice.h"
+#include "QT_FormatManager.h"
+
+namespace avcap
+{
+       // forward declarations
+       class QT_DeviceDescriptor;
+       class QT_VidCapManager;
+       class QT_ConnectorManager;
+       class QT_ControlManager;
+
+       //! Implementation of the CaptureDevice for QuickTime.
+
+       class QT_Device : public CaptureDevice
+       {
+       public:
+
+       private:
+               QT_DeviceDescriptor*    mDeviceDescriptor;
+               QT_FormatManager*               mFormatMgr;
+               QT_VidCapManager*               mVidCapMgr;
+               QT_ConnectorManager*    mConnectorMgr;
+               QT_ControlManager*              mControlMgr;
+
+       public:
+               QT_Device(QT_DeviceDescriptor* dd);
+
+               virtual ~QT_Device();
+
+               inline const DeviceDescriptor* getDescriptor()
+                       { return (const DeviceDescriptor*) mDeviceDescriptor; }
+
+               inline CaptureManager* getVidCapMgr()
+                       { return (CaptureManager*) mVidCapMgr; }
+
+               inline ConnectorManager* getConnectorMgr()
+                       { return (ConnectorManager*) mConnectorMgr; }
+
+               inline ControlManager*  getControlMgr()
+                       { return (ControlManager*) mControlMgr; }
+
+               inline FormatManager* getFormatMgr()
+                       { return (FormatManager*) mFormatMgr; }
+
+       private:
+               int open();
+
+               int close();
+       };
+}
+
+#endif // QT_DEVICE_H
+
diff --git a/extra_lib/include/avcap/osx/QT_DeviceDescriptor.h b/extra_lib/include/avcap/osx/QT_DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..bc5c156
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef QT_DEVICEDESCRIPTOR_H_
+#define QT_DEVICEDESCRIPTOR_H_
+
+#include <iostream>
+#include <string>
+
+#include "DeviceDescriptor.h"
+#include <QuickTime/QuickTime.h>
+
+namespace avcap
+{
+class CaptureDevice;
+class QT_Device;
+
+       //! Implementation of the DeviceDescriptor for QuickTime.
+
+       class QT_DeviceDescriptor : public DeviceDescriptor
+       {
+       public:
+
+       private:
+               SeqGrabComponent mGrabber;
+               SGChannel                mChannel;
+               VideoDigitizerComponent mDigitizer;
+               DigitizerInfo                   mDigiInfo;
+
+               int                              mDeviceID;
+               int                              mInputID;
+               bool                     mValid;
+
+               std::string              mName;
+               std::string              mDriver;
+               QT_Device*               mDevice;
+
+       public:
+               QT_DeviceDescriptor(int device, int input, const std::string& dev_name, const std::string& driver_name,
+                       SeqGrabComponent current_grabber, SGChannel current_channel);
+
+               QT_DeviceDescriptor();
+
+               virtual ~QT_DeviceDescriptor();
+
+               virtual CaptureDevice* getDevice();
+
+               virtual int open();
+
+               virtual int close();
+
+               virtual const std::string& getName() const;
+
+               virtual const std::string& getDriver() const;
+
+               bool isVideoCaptureDev() const;
+
+               virtual inline const DEV_HANDLE_T getHandle() const
+                       { return 0; }
+
+               //! Get the SequenceGrabber-Component.
+               /*! \return the SequenceGrabber-Component. */
+               inline SeqGrabComponent getGrabber(void)
+                       { return mGrabber; }
+
+               //! Get the SequenceGrabber-Channel associated with the device.
+               /*! \return the SequenceGrabber-Channel. */
+               inline SGChannel getChannel(void)
+                       { return mChannel; }
+
+               //! Get the VideoDigitizer associated with the device.
+               /*! \return the VideoDigitizer. */
+               inline VideoDigitizerComponent getDigitizer(void)
+                       { return mDigitizer; }
+
+       private:
+               bool queryCapabilities(SeqGrabComponent current_grabber, SGChannel current_channel);
+
+       };
+}
+
+#endif // QT_DEVICEDESCRIPTOR_H_
diff --git a/extra_lib/include/avcap/osx/QT_DeviceEnumerator.h b/extra_lib/include/avcap/osx/QT_DeviceEnumerator.h
new file mode 100644 (file)
index 0000000..9e1e375
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef QT_DEVICEENUMERATOR_H_
+#define QT_DEVICEENUMERATOR_H_
+
+#include <QuickTime/QuickTime.h>
+
+#include "DeviceCollector.h"
+#include "QT_DeviceDescriptor.h"
+
+namespace avcap
+{
+       //! This special DeviceDescriptor is used by the DeviceCollector to enumerate QuickTime capture-devices.
+
+       class QT_DeviceEnumerator: public QT_DeviceDescriptor
+       {
+       private:
+               SGDeviceList    mDeviceList;
+               
+       public:
+               QT_DeviceEnumerator();
+               virtual ~QT_DeviceEnumerator();
+               
+               //! Use this method to populate a DeviceList with the descriptors of the Devices found on the system.
+               /*! \param dev_list : the list that is filled with DeviceDescriptor-objects.
+                * \return 0 on success, -1 else */ 
+               int findDevices(DeviceCollector::DeviceList& dev_list);
+               
+               virtual int open();
+               
+               virtual int close();
+       };      
+}
+
+#endif // QT_DEVICEENUMERATOR_H_
+
diff --git a/extra_lib/include/avcap/osx/QT_FormatManager.h b/extra_lib/include/avcap/osx/QT_FormatManager.h
new file mode 100644 (file)
index 0000000..a819d14
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef QT_FORMATMANAGER_H
+#define QT_FORMATMANAGER_H
+
+#include <stdint.h>
+#include <QuickTime/QuickTime.h>
+
+#include "FormatManager.h"
+
+namespace avcap
+{
+       class QT_DeviceDescriptor;
+       
+       //! Implementation of the FormatManager for the QuickTime-implementation of CaptureDevice.
+       
+       /*! This FormatManager supports at most one format, so setting the format is not realy neccessary. */
+       
+       class QT_FormatManager: public FormatManager
+       {
+       private:
+               QT_DeviceDescriptor*    mQTDeviceDescriptor;
+               GWorldPtr                               mGWorld;
+               Rect                                    mCurrentBounds;
+               bool                                    mNeedsDecompression;
+               
+       public:
+               QT_FormatManager(QT_DeviceDescriptor *dd);
+               
+               virtual ~QT_FormatManager();
+               
+               int setFormat(Format *fmt);
+               
+               int setFormat(uint32_t fourcc);
+
+               Format* getFormat();
+               
+               int setResolution(int w, int h);
+
+               int getWidth();
+
+               int getHeight();
+               
+               size_t getImageSize();
+                               
+               int setFramerate(int fps);
+               
+               int getFramerate();
+               
+               void query();
+               
+       private:
+               
+               int probeResolutions(Format* fmt);
+
+               int checkResolution(int w, int h);
+
+               int updateGWorld(const Rect* bounds);
+
+               static uint32_t OSType2Fourcc(OSType pixel_format);
+               
+               static OSType Fourcc2OSType(uint32_t fourcc);
+
+               inline bool needsDecompression() const 
+                       { return mNeedsDecompression; }
+
+               friend class QT_VidCapManager;
+       };
+}
+
+#endif // QT_FORMATMANAGER_H
diff --git a/extra_lib/include/avcap/osx/QT_VidCapManager.h b/extra_lib/include/avcap/osx/QT_VidCapManager.h
new file mode 100644 (file)
index 0000000..ff34c3c
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef QT_VIDCAPMANAGER_H_
+#define QT_VIDCAPMANAGER_H_
+
+#include <sys/types.h>
+#include <list>
+#include <time.h>
+#include <pthread.h>
+
+#include <QuickTime/QuickTime.h>
+
+#include "CaptureManager.h"
+
+namespace avcap
+{
+       class QT_DeviceDescriptor;
+       class QT_FormatManager;
+       class IOBuffer;
+       class CaptureHandler;
+       
+       //! Implementation of the CaptureManager for the QuickTime-implementation of a CaptureDevice.
+
+       /*! This CaptureManager captures the data in an ow thread. 
+        * Decompression is performed, if neccessary (e.g. for DV-Cams). */
+       
+       class QT_VidCapManager: public CaptureManager
+       {
+       public:
+
+       private:                
+               typedef std::list<IOBuffer*> IOBufList_t;
+
+               QT_DeviceDescriptor     *mQTDeviceDescriptor;
+               QT_FormatManager        *mFormatMgr;
+               IOBufList_t                     mBuffers;
+               TimeScale                       mTimeScale;
+               TimeScale                       mLastTime;
+               pthread_t*                      mThread;
+               pthread_mutex_t         mLock;
+               int                                     mFinish;
+               long                            mSequence;
+               int                                     mNumBufs;
+               int                                     mAvailableBuffers;
+               ICMDecompressionSessionRef      mDecompSession;
+
+       public:
+               QT_VidCapManager(QT_DeviceDescriptor* dd, QT_FormatManager* fmt_mgr, int nbufs);
+               
+               virtual ~QT_VidCapManager();
+               
+               int init();
+               
+               int destroy();
+               
+               int startCapture();
+
+               int stopCapture();
+               
+               virtual IOBuffer* dequeue();
+
+               virtual int enqueue(IOBuffer* buf);
+               
+               virtual int getNumIOBuffers();
+               
+       private:
+               int startCaptureImpl();
+               
+               int stopCaptureImpl();
+
+               void notifyCaptureHandler(void* data, size_t length, size_t bytes_per_row, TimeValue time);
+
+               int poll();
+
+               struct timespec getPollTimespec(double fps);
+
+               int decompressData(void* data, long length, TimeValue timeValue);
+
+               static OSErr captureCallback(SGChannel ch, Ptr data, long data_len, long * offset, 
+                       long ch_ref_con, TimeValue time_value, short write_type, long priv);
+
+               OSErr captureCallbackImpl(SGChannel ch, Ptr data, long data_len, long * offset, 
+                       long ch_ref_con, TimeValue time_value, short write_type);
+
+               int createDecompSession();
+               
+               static void* threadFunc(void* arg);
+       
+               static void decompTrackingCallback(void *decompressionTrackingRefCon, OSStatus result,
+                       ICMDecompressionTrackingFlags decompressionTrackingFlags, CVPixelBufferRef pixelBuffer,
+                       TimeValue64 displayTime, TimeValue64 displayDuration, ICMValidTimeFlags validTimeFlags,
+                       void *reserved, void *sourceFrameRefCon );
+
+               void threadFuncImpl();
+               
+               void clearBuffers();
+       };
+}
+
+#endif // QT_VIDCAPMANAGER_H
+
diff --git a/extra_lib/include/avcap/osx/avcap-config.h b/extra_lib/include/avcap/osx/avcap-config.h
new file mode 100644 (file)
index 0000000..9639389
--- /dev/null
@@ -0,0 +1,264 @@
+#ifndef _AVCAP_CONFIG_H
+#define _AVCAP_CONFIG_H 1
+/* avcap-config.h. Generated automatically at end of configure. */
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the `alarm' function. */
+#ifndef AVCAP_HAVE_ALARM 
+#define AVCAP_HAVE_ALARM  1 
+#endif
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifndef AVCAP_HAVE_DLFCN_H 
+#define AVCAP_HAVE_DLFCN_H  1 
+#endif
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#ifndef AVCAP_HAVE_FCNTL_H 
+#define AVCAP_HAVE_FCNTL_H  1 
+#endif
+
+/* Define to 1 if you have the <float.h> header file. */
+#ifndef AVCAP_HAVE_FLOAT_H 
+#define AVCAP_HAVE_FLOAT_H  1 
+#endif
+
+/* Define to 1 if you have the `getpagesize' function. */
+#ifndef AVCAP_HAVE_GETPAGESIZE 
+#define AVCAP_HAVE_GETPAGESIZE  1 
+#endif
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#ifndef AVCAP_HAVE_GETTIMEOFDAY 
+#define AVCAP_HAVE_GETTIMEOFDAY  1 
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef AVCAP_HAVE_INTTYPES_H 
+#define AVCAP_HAVE_INTTYPES_H  1 
+#endif
+
+/* Define to 1 if you have the <limits.h> header file. */
+#ifndef AVCAP_HAVE_LIMITS_H 
+#define AVCAP_HAVE_LIMITS_H  1 
+#endif
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#ifndef AVCAP_HAVE_MALLOC 
+#define AVCAP_HAVE_MALLOC  1 
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef AVCAP_HAVE_MEMORY_H 
+#define AVCAP_HAVE_MEMORY_H  1 
+#endif
+
+/* Define to 1 if you have the `memset' function. */
+#ifndef AVCAP_HAVE_MEMSET 
+#define AVCAP_HAVE_MEMSET  1 
+#endif
+
+/* Define to 1 if you have a working `mmap' system call. */
+#ifndef AVCAP_HAVE_MMAP 
+#define AVCAP_HAVE_MMAP  1 
+#endif
+
+/* Define to 1 if you have the `munmap' function. */
+#ifndef AVCAP_HAVE_MUNMAP 
+#define AVCAP_HAVE_MUNMAP  1 
+#endif
+
+/* Define to 1 if you have the `pow' function. */
+#ifndef AVCAP_HAVE_POW 
+#define AVCAP_HAVE_POW  1 
+#endif
+
+/* Define to 1 if you have the `select' function. */
+#ifndef AVCAP_HAVE_SELECT 
+#define AVCAP_HAVE_SELECT  1 
+#endif
+
+/* Define to 1 if you have the `sqrt' function. */
+#ifndef AVCAP_HAVE_SQRT 
+#define AVCAP_HAVE_SQRT  1 
+#endif
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#ifndef AVCAP_HAVE_STDBOOL_H 
+#define AVCAP_HAVE_STDBOOL_H  1 
+#endif
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#ifndef AVCAP_HAVE_STDDEF_H 
+#define AVCAP_HAVE_STDDEF_H  1 
+#endif
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#ifndef AVCAP_HAVE_STDINT_H 
+#define AVCAP_HAVE_STDINT_H  1 
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef AVCAP_HAVE_STDLIB_H 
+#define AVCAP_HAVE_STDLIB_H  1 
+#endif
+
+/* Define to 1 if you have the `strerror' function. */
+#ifndef AVCAP_HAVE_STRERROR 
+#define AVCAP_HAVE_STRERROR  1 
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef AVCAP_HAVE_STRINGS_H 
+#define AVCAP_HAVE_STRINGS_H  1 
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef AVCAP_HAVE_STRING_H 
+#define AVCAP_HAVE_STRING_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#ifndef AVCAP_HAVE_SYS_IOCTL_H 
+#define AVCAP_HAVE_SYS_IOCTL_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#ifndef AVCAP_HAVE_SYS_SELECT_H 
+#define AVCAP_HAVE_SYS_SELECT_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#ifndef AVCAP_HAVE_SYS_SOCKET_H 
+#define AVCAP_HAVE_SYS_SOCKET_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef AVCAP_HAVE_SYS_STAT_H 
+#define AVCAP_HAVE_SYS_STAT_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#ifndef AVCAP_HAVE_SYS_TIME_H 
+#define AVCAP_HAVE_SYS_TIME_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef AVCAP_HAVE_SYS_TYPES_H 
+#define AVCAP_HAVE_SYS_TYPES_H  1 
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef AVCAP_HAVE_UNISTD_H 
+#define AVCAP_HAVE_UNISTD_H  1 
+#endif
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef HAVE__BOOL */
+
+/* Compile avcap for Linux */
+/* #undef LINUX */
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
+
+/* Compile avcap for Mac OS X */
+#ifndef AVCAP_OSX 
+#define AVCAP_OSX  1 
+#endif
+
+/* Name of package */
+#ifndef AVCAP_PACKAGE 
+#define AVCAP_PACKAGE  "avcap" 
+#endif
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef AVCAP_PACKAGE_BUGREPORT 
+#define AVCAP_PACKAGE_BUGREPORT  "Nico.Pranke@googlemail.com" 
+#endif
+
+/* Define to the full name of this package. */
+#ifndef AVCAP_PACKAGE_NAME 
+#define AVCAP_PACKAGE_NAME  "A video capture library" 
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef AVCAP_PACKAGE_STRING 
+#define AVCAP_PACKAGE_STRING  "A video capture library 0.1.9" 
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef AVCAP_PACKAGE_TARNAME 
+#define AVCAP_PACKAGE_TARNAME  "avcap" 
+#endif
+
+/* Define to the version of this package. */
+#ifndef AVCAP_PACKAGE_VERSION 
+#define AVCAP_PACKAGE_VERSION  "0.1.9" 
+#endif
+
+/* Define to the type of arg 1 for `select'. */
+#ifndef AVCAP_SELECT_TYPE_ARG1 
+#define AVCAP_SELECT_TYPE_ARG1  int 
+#endif
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#ifndef AVCAP_SELECT_TYPE_ARG234 
+#define AVCAP_SELECT_TYPE_ARG234  (fd_set *) 
+#endif
+
+/* Define to the type of arg 5 for `select'. */
+#ifndef AVCAP_SELECT_TYPE_ARG5 
+#define AVCAP_SELECT_TYPE_ARG5  (struct timeval *) 
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef AVCAP_STDC_HEADERS 
+#define AVCAP_STDC_HEADERS  1 
+#endif
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#ifndef AVCAP_TIME_WITH_SYS_TIME 
+#define AVCAP_TIME_WITH_SYS_TIME  1 
+#endif
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#ifndef AVCAP_VERSION 
+#define AVCAP_VERSION  "0.1.9" 
+#endif
+
+/* Compile avcap for Windows */
+/* #undef WINDOWS */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
+/* once: _AVCAP_CONFIG_H */
+#endif
diff --git a/extra_lib/include/avcap/singleton.h b/extra_lib/include/avcap/singleton.h
new file mode 100644 (file)
index 0000000..97b4375
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>
+ */
+
+#ifndef SINGLETON_H_
+#define SINGLETON_H_
+
+
+
+namespace avcap 
+{
+       //! Base for classes that implement the singleton pattern. 
+       
+       /*! There are lots of more spohisticated approaches to implement 
+        * a singleton but this simple approach is sufficient here.  */
+       template <class T>
+       class Singleton
+       {
+       public:
+         
+               //! Get the global instance of the singleton.
+               static T& instance() 
+               {
+                       static T _instance;
+                       return _instance;
+               }
+         
+       private:
+       
+               Singleton();    // ctor hidden
+               ~Singleton();   // dtor hidden
+               Singleton(Singleton const&);    // copy ctor hidden
+               Singleton& operator=(Singleton const&); // assign op hidden
+       };
+}
+
+#endif // SINGLETON_H_
+
diff --git a/extra_lib/include/avcap/windows/Crossbar.h b/extra_lib/include/avcap/windows/Crossbar.h
new file mode 100644 (file)
index 0000000..698f3ff
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef CROSSBAR_H_
+#define CROSSBAR_H_
+
+#include <DShow.h>
+
+#include "avcap-export.h"
+
+namespace avcap
+{
+       struct AVCAP_Export STConnector
+       {
+               std::string NameOfConnector;
+               LONG PhysicalType;
+               bool IsAudioConnector;
+               bool IsVideoConnector;
+               bool IsRouted;
+       
+               IAMCrossbar *Crossbar;
+               long PinIndexOfCrossbar;
+               int AudioSet; 
+               
+               /* Video inputs correspond to zero or max. one audio input. 
+                The pins are numbered from 0 to N-1, N <= 32.
+                Each bit set is the index of a audio pin on the 
+                same crossbar corresponding to the selected video pin.
+                AudioSet only used for video input pins. */
+       
+               int PinIndex; // Independent PinIndex
+       };
+       
+       struct AVCAP_Export STRouting
+       {
+               long OutputPinIndex;
+               IPin *OutputPin;
+               long RelatedInPinIndex;
+               IPin *RelatedInputPin;
+               IAMCrossbar *Crossbar;
+               int CrossbarIndex; // Zero based index
+               bool HasConnector;
+       };
+       
+       //! A class for controlling DirectShow video crossbars.
+       
+       /*! This class creates a single object which encapsulates all connected
+        *      crossbars, enumerates all unique inputs which can be reached from
+        *  a given starting downstream filter.
+        *  
+        *  The class supports an arbitrarily complex graph of crossbars, 
+        *  which can be cascaded and disjoint, that is not all inputs need 
+        *  to traverse the same set of crossbars.
+        *  
+        *  Given a starting filter (typically the capture filter), the class 
+        *  recursively traces upstream searching for all viable inputs.  
+        *  An input is considered viable if it is either: 
+        * 
+        *  - unconnected
+        *  - connects to a DirectShow filter which does not support IAMCrossbar 
+        * COM-Interface.       
+        * */
+       
+       class AVCAP_Export CCrossbar
+       {
+       public:
+               CCrossbar(ICaptureGraphBuilder2 *CaptureGraphBuilder);
+               ~CCrossbar(void);
+       
+               /*! Searches upstrean for all available crossbars in the filter graph, 
+                * starting from a given filter.
+                * \param StartFilter Filter to start search from.
+                * \return The number of crossbars found in the filter graph, -1 else. */
+               int FindAllCrossbarsAndConnectors(IBaseFilter *StartFilter);
+               std::list<STConnector*>& GetInputConnectorList();
+       
+               /*! Gets the currently selected video input connector.
+                * \param Connector Connector data */
+               bool GetCurrentVideoInput(STConnector *Connector);
+       
+               /*! Gets the currently selected audio input connector.
+                * \param Connector Connector data */
+               bool GetCurrentAudioInput(STConnector *Connector);
+       
+               /*! Sets the input connector.
+                * \param PinIndex Pin index */
+               bool SetInput(int PinIndex);
+       
+       private:
+               QzCComPtr<ICaptureGraphBuilder2> m_CaptureBuilder;
+               std::list<IAMCrossbar*> m_CrossbarList;
+               std::list<STRouting*> m_RoutingList;
+               std::list<STConnector*> m_InputConnectorList;
+       
+               HRESULT GetCrossbarIPinAtIndex(IAMCrossbar *pXbar, LONG PinIndex,
+                               BOOL IsInputPin, IPin ** ppPin);
+               void StringFromPinType(std::string &PinName, long lType);
+               void DeleteAllLists();
+       };
+}
+
+#endif // CROSSBAR_H_
diff --git a/extra_lib/include/avcap/windows/DS_Connector.h b/extra_lib/include/avcap/windows/DS_Connector.h
new file mode 100644 (file)
index 0000000..ada6fc7
--- /dev/null
@@ -0,0 +1,74 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSCONNECTOR_H_\r
+#define DSCONNECTOR_H_\r
+\r
+#include <string>\r
+#include <list>\r
+\r
+#include "Connector.h"\r
+#include "DeviceDescriptor.h"\r
+#include "avcap-export.h"\r
+\r
+namespace avcap\r
+{\r
+// forward declaration\r
+class DS_DeviceDescriptor;\r
+class DS_Tuner;\r
+\r
+       //! Implementation of the Connector for DirectShow.\r
+\r
+\r
+       class AVCAP_Export DS_Connector : public Connector\r
+       {\r
+       public:\r
+       \r
+#pragma warning( disable : 4800 )\r
+               enum {\r
+                       INPUT_TYPE_TUNER = 0x00010000 // CAP_TUNERDEVICE --> see "HelpFunc.h" file\r
+               };\r
+       \r
+       protected:\r
+               DS_DeviceDescriptor*    mDSDeviceDescriptor;\r
+               int                                     mIndex;\r
+               int                                     mAudioset;\r
+               int                                             mType;\r
+               std::string                     mName;\r
+               DS_Tuner*                               mTuner;\r
+       \r
+       public:\r
+               /*! The Constructor.  */\r
+               DS_Connector(DS_DeviceDescriptor *dd, int index, const std::string& name,\r
+                               int type=0, int audioset=0, int tuner=0);\r
+       \r
+               /*! The Destructor. */\r
+               virtual ~DS_Connector();\r
+       \r
+               bool hasTuner() const\r
+                       { return mType & INPUT_TYPE_TUNER; }\r
+       };\r
+}\r
+\r
+#endif // DSConnector_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_ConnectorManager.h b/extra_lib/include/avcap/windows/DS_ConnectorManager.h
new file mode 100644 (file)
index 0000000..5dce4fa
--- /dev/null
@@ -0,0 +1,91 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSCONNECTORMANAGER_H_\r
+#define DSCONNECTORMANAGER_H_\r
+\r
+#include <list>\r
+\r
+#include "Connector.h"\r
+#include "ConnectorManager.h"\r
+#include "avcap-export.h"\r
+\r
+class IPin;\r
+class IBaseFilter;\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+class DS_Connector;\r
+\r
+       //! DirectShow implementation of the ConnectorManager.\r
+\r
+       class AVCAP_Export DS_ConnectorManager : public ConnectorManager\r
+       {\r
+       private:\r
+               void*                                   mCrossbar;\r
+               DS_DeviceDescriptor*    mDSDeviceDescriptor;\r
+       \r
+       public:\r
+       \r
+               /*! Construct the manager and query for available inputs and outputs for audio and video.\r
+                * The manager is usualy created by an CaptureDevice object.\r
+                * \param dd The DeviceDescriptor to acces the device. */\r
+               DS_ConnectorManager(DS_DeviceDescriptor *dd);\r
+       \r
+               /*! The destructor. */\r
+               virtual ~DS_ConnectorManager();\r
+       \r
+               Connector* getVideoInput();\r
+               int setVideoInput(Connector* c);\r
+       \r
+               Connector* getAudioInput();\r
+               int setAudioInput(Connector* c);\r
+       \r
+               Connector* getVideoOutput();\r
+               int setVideoOutput(Connector* c);\r
+       \r
+               Connector* getAudioOutput();\r
+               int setAudioOutput(Connector* c);\r
+       \r
+               void query();\r
+       \r
+       private:\r
+       \r
+               int setConnector(bool IsVideoConnector, Connector* c);\r
+               \r
+               Connector* getConnector(bool IsVideoConnector);\r
+               \r
+               Connector* findByIndex(const ListType& l, int index);\r
+       \r
+               void getIPinFromConnector(Connector *con, IPin **ConnectorPin,\r
+                               IBaseFilter *CaptureFilter);\r
+               \r
+               bool removeAllFilters(IPin *OutputPinToStart);\r
+               \r
+               bool getPinCategory(IPin *Pin, GUID *PinCategory);\r
+       };\r
+}\r
+\r
+#endif // DSCONNECTORMANAGER_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_Control.h b/extra_lib/include/avcap/windows/DS_Control.h
new file mode 100644 (file)
index 0000000..d968bbe
--- /dev/null
@@ -0,0 +1,185 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSCONTROL_H_\r
+#define DSCONTROL_H_\r
+\r
+#include <string>\r
+\r
+#include "Control_avcap.h"\r
+#include "Interval.h"\r
+#include "avcap-export.h"\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+\r
+       //! Implementation of the Control-class for DirectShow.\r
+\r
+       class AVCAP_Export DS_Control\r
+       {\r
+       public:\r
+               enum Ctrl_Type\r
+               {\r
+                       CTRL_TYPE_INTEGER = 1,\r
+                       CTRL_TYPE_BOOLEAN = 2,\r
+               };\r
+       \r
+               enum DShowInterface\r
+               {\r
+                       IAM_VIDEOPROCAMP = 1,\r
+                       IAM_CAMERACONTROL = 2,\r
+               };\r
+       \r
+               //! Helper-class to query control-properties\r
+               \r
+               struct Query_Ctrl\r
+               {\r
+                       unsigned int    id;\r
+                       Ctrl_Type               type;\r
+                       std::string     name;\r
+                       \r
+                       long minimum;\r
+                       long maximum;\r
+                       long step;\r
+                       long default_value;\r
+                       long flags;\r
+                       long property;\r
+       \r
+                       DS_Control::DShowInterface DShowInterfaceType;\r
+               };\r
+       \r
+       private:\r
+               DShowInterface  mDShowInterfaceType;\r
+               long                    mProperty;\r
+               int                     mId;\r
+               int                     mValue;\r
+               std::string     mName;\r
+               int                     mDefaultValue;\r
+               int                     mFlags;\r
+               bool                    mInitialized;\r
+       \r
+       protected:\r
+               DS_DeviceDescriptor* mDSDeviceDescriptor;\r
+       \r
+       public:\r
+               DS_Control(DS_DeviceDescriptor *dd, Query_Ctrl* query);\r
+               virtual ~DS_Control();\r
+       \r
+               inline int getId() const\r
+                       { return mId; }\r
+       \r
+               inline int getDefaultValue() const\r
+                       { return mDefaultValue; }\r
+       \r
+               inline const std::string& getName() const\r
+                       { return mName; }\r
+       \r
+               int setValue(int val);\r
+       \r
+               int getValue() const;\r
+       \r
+               int reset();\r
+               \r
+       private:\r
+               int update();\r
+\r
+               int retrieveValue();\r
+       };\r
+       \r
+       //! DirectShow integer valued control.\r
+       \r
+       class DS_IntControl : public IntegerControl\r
+       {\r
+       private:\r
+               Interval        mInterval;\r
+               DS_Control      mControlBase;\r
+               \r
+       public:\r
+               inline DS_IntControl(DS_DeviceDescriptor *dd, struct DS_Control::Query_Ctrl* query) :\r
+                       mInterval(query->minimum, query->maximum, query->step),\r
+                       mControlBase(dd, query)\r
+                       {}\r
+       \r
+               virtual inline ~DS_IntControl()\r
+                       {}\r
+       \r
+               inline const Interval& getInterval() const \r
+                       { return mInterval; }\r
+\r
+               virtual inline int getId() const\r
+                       { return mControlBase.getId(); }\r
+       \r
+               virtual inline int getDefaultValue() const\r
+                       { return mControlBase.getDefaultValue(); }\r
+       \r
+               virtual inline const std::string& getName() const\r
+                       { return mControlBase.getName(); }\r
+       \r
+               virtual inline int setValue(int val)\r
+                       { return mControlBase.setValue(val); }\r
+       \r
+               virtual inline int getValue() const\r
+                       { return mControlBase.getValue(); }\r
+               \r
+               virtual inline int reset() \r
+                       { return mControlBase.reset(); }\r
+       };\r
+       \r
+       //! DirectShow boolean control.\r
+\r
+       class DS_BoolControl : public BoolControl\r
+       {\r
+       private:\r
+               DS_Control      mControlBase;\r
+\r
+       public:\r
+               inline DS_BoolControl(DS_DeviceDescriptor *dd, struct DS_Control::Query_Ctrl* query) :\r
+                       mControlBase(dd, query)\r
+                       {}\r
+       \r
+               virtual inline ~DS_BoolControl()\r
+                       {}\r
+               \r
+               virtual inline int getId() const\r
+                       { return mControlBase.getId(); }\r
+       \r
+               virtual inline int getDefaultValue() const\r
+                       { return mControlBase.getDefaultValue(); }\r
+       \r
+               virtual inline const std::string& getName() const\r
+                       { return mControlBase.getName(); }\r
+       \r
+               virtual inline int setValue(int val)\r
+                       { return mControlBase.setValue(val); }\r
+       \r
+               virtual inline int getValue() const\r
+                       { return mControlBase.getValue(); }\r
+               \r
+               virtual inline int reset() \r
+                       { return mControlBase.reset(); }\r
+       };\r
+}\r
+\r
+#endif // DSCONTROL_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_ControlManager.h b/extra_lib/include/avcap/windows/DS_ControlManager.h
new file mode 100644 (file)
index 0000000..278ea84
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSCONTROLMANAGER_H_\r
+#define DSCONTROLMANAGER_H_\r
+\r
+#include <string>\r
+#include <list>\r
+\r
+#include "ControlManager.h"\r
+#include "DS_Control.h"\r
+#include "avcap-export.h"\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+       \r
+       //! DirectShow ControlManager implementation.\r
+\r
+       /*! DirectShow doesn't provide any methods to enumerate driver- \r
+       * specific controls like V4L2 does. \r
+       * There are only few DirectShow COM-Interfaces (e.g. IAMExtTransport (for \r
+       * Firewire or other external devices), IAMVideoControl, IAMVideoCompression, IAMVideoProcAmp, \r
+       * IAMCameraControl --> see DirectShow documentation), the capture device DirectShow filter\r
+       * (only WDM capture devices) can expose to support the setting of global properties. The most \r
+       * important settings are covered by these DirectShow COM-Interfaces. \r
+       * In the future, DirectShow will provide more COM-Interfaces.\r
+       * \r
+       * The DirectShow COM-Interfaces IAMVideoProcAmp and IAMCameraControl have been already \r
+       * implemented in the avcap-library.\r
+       * \r
+       * Most WDM capture devices and \b all VFW capture devices have their own driver-supplied dialog \r
+       * boxes with user-setable controls on it, that can't be set programmatically. */\r
+       \r
+       class AVCAP_Export DS_ControlManager : public ControlManager\r
+       {\r
+       private:\r
+               DS_DeviceDescriptor* mDSDeviceDescriptor;\r
+       \r
+       public:\r
+               DS_ControlManager(DS_DeviceDescriptor *dd);\r
+       \r
+               virtual ~DS_ControlManager();\r
+       \r
+               Control* getControl(const std::string& name);\r
+       \r
+               Control* getControl(int id);\r
+       \r
+               const ListType& getControlList()\r
+                       { return (const ListType&) mControls; }\r
+               \r
+               void query();\r
+       \r
+       private:\r
+               void query(int start_id, int end_id);\r
+       };\r
+}\r
+\r
+#endif \r
diff --git a/extra_lib/include/avcap/windows/DS_Device.h b/extra_lib/include/avcap/windows/DS_Device.h
new file mode 100644 (file)
index 0000000..1575a6f
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>\r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSDEVICE_H_\r
+#define DSDEVICE_H_\r
+\r
+#include <string>\r
+#include <list>\r
+\r
+#include "DS_DeviceDescriptor.h"\r
+#include "CaptureDevice.h"\r
+#include "avcap-export.h"\r
+\r
+namespace avcap\r
+{\r
+// forward declarations\r
+class DS_ConnectorManager;\r
+class DS_ControlManager;\r
+class DS_VidCapManager;\r
+class DS_DeviceDescriptor;\r
+class DS_FormatManager;\r
+\r
+       //! Implementation of the CaptureDevice for DirectShow.\r
+\r
+       class AVCAP_Export DS_Device : public CaptureDevice\r
+       {\r
+       private:\r
+               DS_VidCapManager*               mVidCapMgr;\r
+               DS_ConnectorManager*    mConnectorMgr;\r
+               DS_ControlManager*              mControlMgr;\r
+               DS_FormatManager*               mFormatMgr;\r
+               DS_DeviceDescriptor*    mDSDeviceDescriptor;\r
+\r
+       public:\r
+               DS_Device(DS_DeviceDescriptor* dd);\r
+\r
+               virtual ~DS_Device();\r
+\r
+               inline const DeviceDescriptor* getDescriptor()\r
+                       { return (const DeviceDescriptor*) mDSDeviceDescriptor; }\r
+\r
+               inline CaptureManager* getVidCapMgr()\r
+                       { return (CaptureManager*) mVidCapMgr; }\r
+\r
+               inline ConnectorManager* getConnectorMgr()\r
+                       { return (ConnectorManager*) mConnectorMgr;     }\r
+\r
+               inline ControlManager* getControlMgr()\r
+                       { return (ControlManager*) mControlMgr; }\r
+\r
+               inline FormatManager* getFormatMgr()\r
+                       { return (FormatManager*)mFormatMgr; }\r
+\r
+       private:\r
+               int open();\r
+\r
+               int close();\r
+       };\r
+}\r
+\r
+#endif // DSDEVICE_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_DeviceDescriptor.h b/extra_lib/include/avcap/windows/DS_DeviceDescriptor.h
new file mode 100644 (file)
index 0000000..6f96b3c
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de>\r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSDEVICEDESCRIPTOR_H_\r
+#define DSDEVICEDESCRIPTOR_H_\r
+\r
+#include <iostream>\r
+#include <string>\r
+#include <DShow.h>\r
+\r
+#include "DeviceDescriptor.h"\r
+#include "avcap-export.h"\r
+\r
+class IBaseFilter;\r
+\r
+namespace avcap\r
+{\r
+class CaptureDevice;\r
+class DS_Device;\r
+\r
+       //! Implementation of the DeviceDescriptor for DirectShow.\r
+\r
+       class AVCAP_Export DS_DeviceDescriptor : public DeviceDescriptor\r
+       {\r
+       public:\r
+               // Used by AddToRot() and RemoveFromRot() for spying on\r
+               // filter graph with GraphEdit software\r
+               unsigned long mRegister; // For debugging purpose\r
+\r
+       private:\r
+               std::string mName;\r
+               std::string mCard;\r
+               std::string mInfo;\r
+\r
+               int                     mCapabilities;\r
+               DEV_HANDLE_T    mHandle;\r
+               bool                    mValid;\r
+               bool                    mIsOpen;\r
+               DS_Device*              mDevice;\r
+\r
+       public:\r
+               DS_DeviceDescriptor(const std::string &card);\r
+\r
+               virtual ~DS_DeviceDescriptor();\r
+\r
+               virtual CaptureDevice* getDevice();\r
+\r
+               int open();\r
+\r
+               int close();\r
+\r
+               virtual inline const std::string& getName() const\r
+                       { return mName; }\r
+\r
+               // implementation of pure virtual method\r
+               inline const DEV_HANDLE_T getHandle() const\r
+                       { return mHandle; }\r
+\r
+               // but non-const access is needed by the device-class\r
+               inline DEV_HANDLE_T getHandle()\r
+                       { return mHandle; }\r
+\r
+               bool isAVDev() const;\r
+\r
+               bool isVideoCaptureDev() const;\r
+\r
+               bool isVBIDev() const;\r
+\r
+               bool isTuner() const;\r
+\r
+               bool isAudioDev() const;\r
+\r
+               bool isRadioDev() const;\r
+\r
+               bool isOverlayDev() const;\r
+\r
+               //! Device is a VFW (Video for Windows) device.\r
+               /*! \return true VFW device, else false */\r
+               bool isVfWDevice() const;\r
+\r
+       private:\r
+               bool queryCapabilities();\r
+\r
+               void findDevice(std::string &UniqueDeviceID, IBaseFilter **CaptureFilter,\r
+                               std::string &DeviceName, std::string &DeviceInfo,\r
+                               bool *IsVideoDevice=NULL, bool *IsAudioDevice=NULL);\r
+\r
+               bool createCaptureFilterGraph(std::string &UniqueDeviceID,\r
+                               IBaseFilter *CaptureFilter);\r
+\r
+               bool getInfosFromDevice(IBaseFilter *CaptureFilter, int *Capabilities,\r
+                               std::string &Card, std::string &Info);\r
+\r
+               bool findOverlaySupport(IBaseFilter *CaptureFilter, int *Capabilities);\r
+\r
+               bool findVBISupport(IBaseFilter *CaptureFilter, int *Capabilities);\r
+\r
+               bool findTunerRadioSupport(IBaseFilter *CaptureFilter, int *Capabilities);\r
+\r
+               bool isAudioOrVideoDevice(IBaseFilter *CaptureFilter, int *Capabilities);\r
+\r
+               HRESULT addToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);\r
+\r
+               void removeFromRot(DWORD pdwRegister);\r
+\r
+               friend class DS_Device;\r
+       };\r
+}\r
+\r
+#endif // DSEVICEDESCRIPTOR_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_FormatManager.h b/extra_lib/include/avcap/windows/DS_FormatManager.h
new file mode 100644 (file)
index 0000000..2d773b1
--- /dev/null
@@ -0,0 +1,101 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+#ifndef DSFORMATMANAGER_H_\r
+#define DSFORMATMANAGER_H_\r
+\r
+#include <list>\r
+#include <string>\r
+#include <Dshow.h>\r
+\r
+#ifndef _MSC_VER\r
+# include <stdint.h>\r
+#endif\r
+\r
+#include "FormatManager.h"\r
+#include "avcap-export.h"\r
+\r
+class IBaseFilter;\r
+class IPin;\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+\r
+       //! Implementation of the FormatManager for DirectShow.\r
+       \r
+       /*! A capture device that still uses a VFW (Video for Windows)\r
+       * driver can select the available formats only by using the VFW driver-supplied dialog box.\r
+       * But GUI-related stuff is out of the scope of this library. */\r
+       \r
+       class AVCAP_Export DS_FormatManager : public FormatManager\r
+       {\r
+       private:\r
+               DS_DeviceDescriptor* mDSDeviceDescriptor;\r
+               int                        mFrameRate;\r
+\r
+       public:\r
+               DS_FormatManager(DS_DeviceDescriptor *dd);\r
+\r
+               virtual ~DS_FormatManager();\r
+       \r
+               virtual int setFormat(Format *fmt);\r
+       \r
+               virtual Format* getFormat();\r
+       \r
+               virtual int setResolution(int w, int h);\r
+       \r
+               virtual int getWidth();\r
+       \r
+               virtual int getHeight();\r
+       \r
+               virtual int getBytesPerLine();\r
+       \r
+               virtual int setFramerate(int fps);\r
+\r
+               virtual int getFramerate();\r
+\r
+               virtual int flush();\r
+       \r
+               virtual size_t getImageSize();\r
+       \r
+               virtual const VideoStandard* getVideoStandard();\r
+       \r
+               virtual int setVideoStandard(const VideoStandard* std);\r
+       \r
+               virtual void query();\r
+       \r
+       private:\r
+               int getParams();\r
+               \r
+               void queryVideoStandards();\r
+       \r
+               bool getVideoInfoHeader(AM_MEDIA_TYPE *MediaType,\r
+                               VIDEOINFOHEADER *VideoInfoHeader);\r
+               \r
+               bool getCurrentConnectedVideoPin(IBaseFilter *CaptureFilter,\r
+                               IPin **VideoPin);\r
+       };\r
+}\r
+\r
+#endif // DSFORMATMANAGER_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_Tuner.h b/extra_lib/include/avcap/windows/DS_Tuner.h
new file mode 100644 (file)
index 0000000..187d2a8
--- /dev/null
@@ -0,0 +1,134 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSTUNER_H_\r
+#define DSTUNER_H_\r
+\r
+#include <string>\r
+\r
+#include "Tuner_avcap.h"\r
+#include "avcap-export.h"\r
+\r
+class IAMTVAudio;\r
+class IAMTVTuner;\r
+class IBaseFilter;\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+\r
+       //! Implementation of the Tuner-class for DirectShow.\r
+         \r
+       /*! This implementation uses the PROPSETID_TUNER property-set which is defined in \r
+        * the library kstvtuner.ax which can not be linked with gcc. \r
+        * It thus can not be used under mingw, but only if build with Visual-C++.\r
+        * So the mingw-build library misses this tuner-implentation.\r
+        * \r
+        * There are only three states of signal strength:\r
+        * signal present, signal not present, signal not determined. Because of this limitation\r
+        * the method getAFCValue() is not implemented.\r
+        */\r
+       \r
+       class AVCAP_Export DS_Tuner : public Tuner\r
+       {\r
+       private:\r
+       \r
+#pragma warning( disable : 4800 )\r
+\r
+               enum\r
+               {\r
+                       TUNER_RADIO = 0x00080000, // CAP_RADIO --> see "HelpFunc.h" file\r
+                       TUNER_ANALOG_TV = 0x00020000 // CAP_TUNER --> see "HelpFunc.h" file\r
+               };\r
+       \r
+               int                     mIndex;\r
+               std::string     mName;\r
+               int                     mType;\r
+               int                     mCapabilities;\r
+               unsigned int    mRangeHigh;\r
+               unsigned int    mRangeLow;\r
+               double                  mStep;\r
+               double                  mFreq;\r
+       \r
+       private:\r
+               DS_DeviceDescriptor* mDSDeviceDescriptor;\r
+       \r
+       public:\r
+               DS_Tuner(DS_DeviceDescriptor *dd, int index, const std::string &name,\r
+                               int type, int caps, unsigned int high, unsigned int low);\r
+               \r
+               virtual ~DS_Tuner();\r
+       \r
+               inline bool isRadioTuner() const\r
+                       { return mType & TUNER_RADIO; }\r
+       \r
+               inline bool isTVTuner() const\r
+                       { return mType & TUNER_ANALOG_TV; }\r
+       \r
+               int setStereo();\r
+       \r
+               int setMono();\r
+       \r
+               int setSAP();\r
+       \r
+               int setLang1();\r
+       \r
+               int setLang2();\r
+       \r
+               double getFreq() const;\r
+       \r
+               inline double getFreqStep() const\r
+                       { return mStep; }\r
+       \r
+               inline double getMinFreq() const\r
+                       { return mRangeLow*mStep; }\r
+       \r
+               inline double getMaxFreq() const\r
+                       { return mRangeHigh*mStep; }\r
+       \r
+               const std::string getName() const\r
+                       { return mName; }\r
+       \r
+               int getSignalStrength() const;\r
+       \r
+               int increaseFreq();\r
+       \r
+               int decreaseFreq();\r
+       \r
+               int setFreq(double f);\r
+       \r
+       private:\r
+               int setAudioMode(int mode);\r
+               \r
+               int getAudioMode();\r
+       \r
+               bool getIAMTVTunerInterfaceFromFilter(IBaseFilter *Filter,\r
+                       IAMTVTuner **Tuner) const;\r
+\r
+               bool getIAMTVAudioInterfaceFromFilter(IBaseFilter *Filter,\r
+                       IAMTVAudio **Audio);\r
+       };\r
+}\r
+\r
+#endif // DSTUNER_H_\r
diff --git a/extra_lib/include/avcap/windows/DS_VidCapManager.h b/extra_lib/include/avcap/windows/DS_VidCapManager.h
new file mode 100644 (file)
index 0000000..d606e88
--- /dev/null
@@ -0,0 +1,98 @@
+/*\r
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> \r
+ *\r
+ * This file is part of avcap.\r
+ *\r
+ * avcap is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * avcap is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with avcap.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+\r
+/* avcap is free for non-commercial use.\r
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.\r
+ */\r
+\r
+\r
+#ifndef DSVIDCAPMANAGER_H_\r
+#define DSVIDCAPMANAGER_H_\r
+\r
+#include <list>\r
+\r
+#include "CaptureManager.h"\r
+#include "SampleGrabberCallback.h"\r
+#include "avcap-export.h"\r
+\r
+namespace avcap\r
+{\r
+class DS_DeviceDescriptor;\r
+class DS_FormatManager;\r
+class IOBuffer;\r
+class CaptureHandler;\r
+class SampleGrabberCallback;\r
+\r
+       //! Implementation of the CaptureManager for DirectShow.\r
+\r
+       class AVCAP_Export DS_VidCapManager : public CaptureManager\r
+       {\r
+       private:\r
+               typedef std::list<IOBuffer*> IOBufList;\r
+               \r
+               DS_DeviceDescriptor*    mDSDeviceDescriptor;\r
+               SampleGrabberCallback*  mGrabberCallback;\r
+               HANDLE                                  mLock;\r
+               int                                     mSequence;\r
+               int                                     mNumBuffers;\r
+\r
+       public:\r
+               DS_VidCapManager(DS_DeviceDescriptor* dd, DS_FormatManager* fmt_mgr,\r
+                               int nbufs = DEFAULT_BUFFERS);\r
+       \r
+               virtual ~DS_VidCapManager();\r
+       \r
+               int init();\r
+       \r
+               int destroy();\r
+       \r
+               int startCapture();\r
+       \r
+               int stopCapture();\r
+               \r
+               int getNumIOBuffers();\r
+       \r
+       private:\r
+               IOBuffer* dequeue();\r
+\r
+               int enqueue(IOBuffer* buf);\r
+       \r
+               friend class IOBuffer;\r
+               friend class SampleGrabberCallback;\r
+       };\r
+\r
+       class MutexGuard\r
+       {\r
+       private:\r
+               HANDLE  mLock;\r
+               \r
+       public:\r
+               inline MutexGuard(HANDLE lock) : \r
+                       mLock(lock)\r
+                       { WaitForSingleObject(mLock, INFINITE); }\r
+                       \r
+               inline virtual ~MutexGuard()\r
+                       { ReleaseMutex(mLock); }\r
+       private:\r
+               inline MutexGuard()\r
+                       {}\r
+       };\r
+}\r
+\r
+#endif // DSVIDCAPMANAGER_H_\r
diff --git a/extra_lib/include/avcap/windows/FormatNames.h b/extra_lib/include/avcap/windows/FormatNames.h
new file mode 100644 (file)
index 0000000..e85b449
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef FORMATNAMES_H_
+#define FORMATNAMES_H_
+
+#include <string>
+#include <uuids.h>
+
+void GetVideoFormatName(const GUID* guid, std::string& FormatName)
+{
+       // list creation date:05/27/2005 - taken from DirectShow documentation
+
+       // Uncompressed RGB video subtypes
+       if (*guid==MEDIASUBTYPE_ARGB1555) {
+               FormatName="RGB 555 with alpha channel";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_ARGB4444) {
+               FormatName="16-bit RGB with alpha channel; 4 bits per channel";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_ARGB32) {
+               FormatName="RGB 32 with alpha channel";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_A2R10G10B10) {
+               FormatName
+                               ="32-bit RGB with alpha channel; 10 bits per RGB channel plus 2 bits for alpha";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_A2B10G10R10) {
+               FormatName
+                               ="32-bit RGB with alpha channel; 10 bits per RGB channel plus 2 bits for alpha";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB1) {
+               FormatName="RGB, 1 bit per pixel (bpp), palettized";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB4) {
+               FormatName="RGB, 4 bpp, palettized";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB8) {
+               FormatName="RGB, 8 bpp";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB555) {
+               FormatName="RGB 555, 16 bpp";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB565) {
+               FormatName="RGB 565, 16 bpp";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB24) {
+               FormatName="RGB, 24 bpp";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_RGB32) {
+               FormatName="RGB, 32 bpp";
+               return;
+       }
+
+       // DV video subtypes
+       if (*guid==MEDIASUBTYPE_dvsl) {
+               FormatName="DV, 12.5 Mbps SD-DVCR 525-60 or SD-DVCR 625-50";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_dvsd) {
+               FormatName="DV, 25 Mbps SDL-DVCR 525-60 or SDL-DVCR 625-50";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_dvhd) {
+               FormatName="DV, 50 Mbps HD-DVCR 1125-60 or HD-DVCR 1250-50";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_dv25) {
+               FormatName="DV, 25 Mbps DVCPRO 25 (525-60 or 625-50)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_dv50) {
+               FormatName="DV, 50 Mbps DVCPRO 50 (525-60 or 625-50)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_dvh1) {
+               FormatName="DV, 100 Mbps DVCPRO 100 (1080/60i, 1080/50i, or 720/60P)";
+               return;
+       }
+
+       // YUV video subtypes
+       if (*guid==MEDIASUBTYPE_AYUV) {
+               FormatName="4:4:4 YUV formats";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_UYVY) {
+               FormatName="UYVY (packed 4:2:2)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_Y411) {
+               FormatName="Y411 (packed 4:1:1)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_Y41P) {
+               FormatName="Y41P (packed 4:1:1)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_Y211) {
+               FormatName="Y211";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_YUY2) {
+               FormatName="YUYV (packed 4:2:2)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_YVYU) {
+               FormatName="YVYU (packed 4:2:2)";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_YUYV) {
+               FormatName="YUYV (packed 4:2:2)(Used by Canopus; FOURCC 'YUYV')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_IF09) {
+               FormatName="Indeo YVU9";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_IYUV) {
+               FormatName="IYUV";
+               return;
+       }
+       /*
+       if (*guid==MEDIASUBTYPE_I420) {
+               FormatName="I420";
+               return;
+       }
+       */
+       if (*guid==MEDIASUBTYPE_YV12) {
+               FormatName="YV12";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_YVU9) {
+               FormatName="YVU9";
+               return;
+       }
+
+       // Miscellaneous video subtypes
+       if (*guid==MEDIASUBTYPE_CFCC) {
+               FormatName="MJPG format produced by some cards. (FOURCC 'CFCC')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_CLJR) {
+               FormatName="Cirrus Logic CLJR format. (FOURCC 'CLJR')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_CPLA) {
+               FormatName="Cinepak UYVY format. (FOURCC 'CPLA')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_CLPL) {
+               FormatName
+                               ="A YUV format supported by some Cirrus Logic drivers. (FOURCC 'CLPL')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_IJPG) {
+               FormatName="Intergraph JPEG format. (FOURCC 'IJPG')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_MDVF) {
+               FormatName="A DV encoding format. (FOURCC 'MDVF')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_MJPG) {
+               FormatName="Motion JPEG (MJPG) compressed video. (FOURCC 'MJPG')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_MPEG1Packet) {
+               FormatName="MPEG1 Video Packet";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_MPEG1Payload) {
+               FormatName="MPEG1 Video Payload";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_Overlay) {
+               FormatName="Video delivered using hardware overlay";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_Plum) {
+               FormatName="Plum MJPG format. (FOURCC 'Plum')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_QTJpeg) {
+               FormatName="QuickTime JPEG compressed data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_QTMovie) {
+               FormatName="Apple® QuickTime® compression";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_QTRle) {
+               FormatName="QuickTime RLE compressed data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_QTRpza) {
+               FormatName="QuickTime RPZA compressed data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_QTSmc) {
+               FormatName="QuickTime SMC compressed data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_TVMJ) {
+               FormatName="TrueVision MJPG format. (FOURCC 'TVMJ')";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_VPVBI) {
+               FormatName="Video port vertical blanking interval (VBI) data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_VPVideo) {
+               FormatName="Video port video data";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_WAKE) {
+               FormatName="MJPG format produced by some cards. (FOURCC 'WAKE')";
+               return;
+       }
+
+       if (*guid==MEDIASUBTYPE_MPEG1Video) {
+               FormatName="MPEG1 Video";
+               return;
+       }
+       if (*guid==MEDIASUBTYPE_MPEG2_VIDEO) {
+               FormatName="MPEG2 Video";
+               return;
+       }
+
+       FormatName="Unknown format type!";
+       return;
+}
+
+void GetVideoStandardName(ULONG VideoStandard,
+               std::list<avcap::VideoStandard*>& VidStandard)
+{
+       // list creation date:05/27/2005 - taken from DirectShow documentation
+
+       if (VideoStandard & AnalogVideo_None) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("Digital sensor", 0);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_NTSC_M) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("NTSC (M) standard, 7.5 IRE black", 0x1);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_NTSC_M_J) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("NTSC (M) standard, 0 IRE black (Japan)", 0x2);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_NTSC_433) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("NTSC-433", 0x4);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_B) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL-B standard", 0x10);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_D) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (D) standard", 0x20);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_G) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (G) standard", 0x40);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_H) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (H) standard", 0x80);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_I) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (I) standard", 0x100);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_M) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (M) standard", 0x200);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_N) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL (N) standard", 0x400);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_60) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("PAL-60 standard", 0x800);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_B) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (B) standard", 0x1000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_D) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (D) standard", 0x2000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_G) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (G) standard", 0x4000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_H) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (H) standard", 0x8000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_K) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (K) standard", 0x10000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_K1) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (K1) standard", 0x20000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_L) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (L) standard", 0x40000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_SECAM_L1) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("SECAM (L1) standard", 0x80000);
+               VidStandard.push_back(vidSt);
+       }
+       if (VideoStandard & AnalogVideo_PAL_N_COMBO) {
+               avcap::VideoStandard *vidSt=new avcap::VideoStandard("Combination (N) PAL standard (Argentina)", 0x100000);
+               VidStandard.push_back(vidSt);
+       }
+}
+
+#endif // FORMATNAMES_H_
diff --git a/extra_lib/include/avcap/windows/HelpFunc.h b/extra_lib/include/avcap/windows/HelpFunc.h
new file mode 100644 (file)
index 0000000..cf56b11
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+
+#ifndef HELPFUNC_H_
+#define HELPFUNC_H_
+
+#include <list>
+#include <math.h>
+#include <string>
+
+#include <DShow.h> // DirectShow
+#include <mtype.h> // DeleteMediaType() function
+#include <qedit.h> // CLSID_NullRenderer/CLSID_ISampleGrabber definitions
+#include <winnls.h>
+
+#ifndef __STREAMS__
+# include <streams.h>
+#endif
+
+// Some definitions
+#define VIDEO_SAMPLEGRABBER_FILTER_NAME L"SampleGrabber Video"
+#define AUDIO_SAMPLEGRABBER_FILTER_NAME L"SampleGrabber Audio"
+
+#define CAP_VIDEO_CAPTURE  0x00000001  /* Is a video capture device */
+#define CAP_VIDEO_OUTPUT   0x00000002  /* Is a video output device */
+#define CAP_VIDEO_OVERLAY  0x00000004  /* Can do video overlay */
+#define CAP_VBI_CAPTURE    0x00000010  /* Is a VBI capture device */
+
+#define CAP_TUNERDEVICE           0x00010000  /* Has radio tuner or tv tuner */
+#define CAP_TUNER          0x00020000  /* Has a tuner */
+#define CAP_AUDIO_CAPTURE  0x00040000  /* Has audio support */
+#define CAP_RADIO                 0x00080000  /* Is a radio device */
+
+// Helper Functions -> see end of file
+static inline void DeleteList(std::list<IPin*> &PinList);
+
+static inline void DeleteList(std::list<IBaseFilter*> &AudioCaptureFilterList);
+
+static inline void DeleteList(std::list<AM_MEDIA_TYPE*> &MediaTypeList);
+
+static inline void EnumMediaTypesOnPin(IPin *Pin,
+               std::list<AM_MEDIA_TYPE*> &MediaTypeList);
+
+static inline void EnumPinsOnFilter(IBaseFilter *Filter,
+               std::list<IPin*> &PinList);
+
+static inline bool GetFilterGraphFromFilter(IBaseFilter *Filter,
+               IGraphBuilder **FilterGraph,
+               ICaptureGraphBuilder2 **CaptureGraphBuilder=NULL);
+
+static inline char* WChar2Char(const wchar_t* szWChar);
+
+static inline bool FindTunerRadioSupport(IBaseFilter *CaptureFilter,
+               int *Capabilities);
+
+static inline bool RenderStream(IUnknown *FilterOrPinToRender,
+               bool RenderVideo, bool RenderAudio);
+
+static inline bool GetInstalledDeviceIDs(
+               std::list<std::string> &UniqueDeviceIDList);
+
+static inline std::string bstr2string(BSTR bstr);
+
+static inline std::string bstr2string(BSTR bstr)
+{
+
+       int length = ((DWORD*) bstr)[0];
+       wchar_t* wchar_data = (wchar_t*) (((DWORD*) bstr) );
+
+       int converted_length = WideCharToMultiByte(CP_ACP, 0, wchar_data, -1, 0, 0,
+                       0, 0);
+       char* char_data = new char[converted_length];
+       WideCharToMultiByte(CP_ACP, 0, wchar_data, -1, char_data, converted_length,
+                       0, 0);
+       std::string res = char_data;
+       delete[] char_data;
+       return res;
+}
+
+//######################### DEBUG FUNCTIONS - MAKE THE FILTERGRAPH VISIBLE IN GRPAHEDIT ###################
+
+static inline void EnumMediaTypesOnPin(IPin *Pin,
+               std::list<AM_MEDIA_TYPE*> &MediaTypeList)
+{
+       QzCComPtr<IEnumMediaTypes> EnumMediaTypes;
+       if (Pin->EnumMediaTypes(&EnumMediaTypes)==S_OK) {
+               AM_MEDIA_TYPE *MediaType=NULL;
+               while (EnumMediaTypes->Next(1, &MediaType, NULL) == S_OK) {
+                       MediaTypeList.push_back(MediaType);
+               }
+       }
+}
+
+static inline void EnumPinsOnFilter(IBaseFilter *Filter,
+               std::list<IPin*> &PinList)
+{
+       QzCComPtr<IEnumPins> EnumPins;
+       IPin *Pin=NULL;
+       if (Filter->EnumPins(&EnumPins)==S_OK) {
+               while (EnumPins->Next(1, &Pin, 0) == S_OK) {
+                       PinList.push_back(Pin);
+               }
+       }
+}
+
+static inline bool GetFilterGraphFromFilter(IBaseFilter *Filter,
+               IGraphBuilder **FilterGraph,
+               ICaptureGraphBuilder2 **CaptureGraphBuilder)
+{
+       if (Filter==NULL) {
+               return false;
+       }
+       // Get the FilterGraph from the Filter
+       FILTER_INFO FilterInfo;
+       if (FAILED(Filter->QueryFilterInfo(&FilterInfo))) {
+               return false;
+       }
+       if (FilterInfo.pGraph==NULL) {
+               return false;
+       }
+       if (FAILED(FilterInfo.pGraph->QueryInterface(IID_IGraphBuilder,
+                       (void**) &*FilterGraph))) {
+               return false;
+       }
+       // Get the CaptureGraphBuilder2
+       // CaptureGraphBuilder is useful for building many kinds of custom filter graphs, not only capture graphs
+       if (CaptureGraphBuilder!=NULL) {
+               if (FAILED(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
+                               CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
+                               (void**)&*CaptureGraphBuilder))) {
+                       return false;
+               }
+               if (FAILED((*CaptureGraphBuilder)->SetFiltergraph(*FilterGraph))) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static inline char* WChar2Char(const wchar_t* szWChar)
+{
+       if (szWChar == NULL) {
+               return NULL;
+       }
+       char* szChar = NULL;
+       size_t size = 0;
+       if ((size = wcstombs(0, szWChar, 0)) == -1) {
+               return NULL;
+       }
+       szChar = new char[size + 1];
+       szChar[size] = 0;
+       wcstombs(szChar, szWChar, size);
+       return szChar;
+}
+
+static inline bool FindTunerRadioSupport(IBaseFilter *CaptureFilter,
+               int *Capabilities)
+{
+       if (CaptureFilter==NULL) {
+               return false;
+       }
+
+       // Get the CaptureBuilderGraph COM-Interface from CaptureFilter
+       QzCComPtr<ICaptureGraphBuilder2> CaptureGraphBuilder;
+       QzCComPtr<IGraphBuilder> FilterGraph;
+       if (!GetFilterGraphFromFilter(CaptureFilter, &FilterGraph,
+                       &CaptureGraphBuilder)) {
+               return false;
+       }
+
+       // Look for the tuner, radio
+       QzCComPtr<IAMTVTuner> Tuner;
+       if (SUCCEEDED(CaptureGraphBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL,
+                       CaptureFilter, IID_IAMTVTuner, (void**)&Tuner))) {
+               long lModes = 0;
+               HRESULT hr = Tuner->GetAvailableModes(&lModes);
+               if (SUCCEEDED(hr) && (lModes & AMTUNER_MODE_FM_RADIO)) {
+                       *Capabilities |= CAP_RADIO;
+               }
+               if (SUCCEEDED(hr) && (lModes & AMTUNER_MODE_TV)) {
+                       *Capabilities |= CAP_TUNER;
+               }
+       }
+
+       return true;
+}
+
+static inline void GetInstalledAudioDevices(
+               std::list<IBaseFilter*> &AudioCaptureFilterList)
+{
+       // Enumerate the audio category
+       std::list<CLSID> EnumCategoriesList;
+       EnumCategoriesList.push_back(CLSID_AudioInputDeviceCategory);
+
+       for (std::list<CLSID>::iterator EnumCategoriesListIter=
+                       EnumCategoriesList.begin(); EnumCategoriesListIter
+                       !=EnumCategoriesList.end(); EnumCategoriesListIter++) {
+               // Create the System Device Enumerator.
+               HRESULT hr;
+               ICreateDevEnum *SysDevEnum = NULL;
+               if (FAILED(CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
+                               CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&SysDevEnum))) {
+                       return;
+               }
+
+               // Obtain a class enumerator for the device capture category.
+               IEnumMoniker *EnumCat = NULL;
+               hr = SysDevEnum->CreateClassEnumerator(*EnumCategoriesListIter,
+                               &EnumCat, 0);
+
+               if (hr == S_OK) {
+                       // Enumerate the monikers.
+                       IMoniker *Moniker = NULL;
+                       ULONG Fetched;
+                       while (EnumCat->Next(1, &Moniker, &Fetched) == S_OK) {
+                               IBaseFilter *AudioCaptureFilter=NULL;
+                               if (SUCCEEDED(Moniker->BindToObject(0, 0, IID_IBaseFilter,
+                                               (void**)&AudioCaptureFilter))) {
+                                       AudioCaptureFilterList.push_back(AudioCaptureFilter);
+                               }
+                               else {
+                                       if (AudioCaptureFilter!=NULL) {
+                                               AudioCaptureFilter->Release();
+                                       }
+                               }
+                               Moniker->Release();
+                       }
+                       EnumCat->Release();
+               }
+               SysDevEnum->Release();
+       }
+}
+
+static inline bool RenderStream(IUnknown *FilterOrPinToRender,
+               bool RenderVideo, bool RenderAudio)
+{
+       QzCComPtr<IGraphBuilder> FilterGraph;
+       QzCComPtr<ICaptureGraphBuilder2> CaptureGraphBuilder;
+
+       // Get the IGraphBuilder and CaptureGraphBuilder2 interfaces from pin or filter
+       QzCComPtr<IPin> Pin;
+       bool IsPin=false;
+       if (SUCCEEDED(FilterOrPinToRender->QueryInterface(IID_IPin, (void**)&Pin))) // It's a pin
+       {
+               PIN_INFO PinInfo;
+               Pin->QueryPinInfo(&PinInfo);
+               IsPin=true;
+
+               if (!GetFilterGraphFromFilter(PinInfo.pFilter, &FilterGraph,
+                               &CaptureGraphBuilder)) {
+                       return false;
+               }
+       }
+       else // It's a filter
+       {
+               if (!GetFilterGraphFromFilter((IBaseFilter*)FilterOrPinToRender,
+                               &FilterGraph, &CaptureGraphBuilder)) {
+                       return false;
+               }
+       }
+
+       //if(SUCCEEDED(CaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, CaptureFilter, NULL, NullRendererVideo))){return true;}
+
+       // Build complete filter graph
+       if (RenderVideo) {
+               // Add NullRenderer filters because we want to set formats with IAMStreamConfig COM-Interface while the complete
+               // filtergraph is connected. NullRenderer filters and the samplegrabber filter accept all formats.
+               QzCComPtr<IBaseFilter> RendererVideo;
+               if (FAILED(CoCreateInstance(CLSID_NullRenderer, 0,
+                               CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&RendererVideo))) {
+                       return false;
+               }
+               if (FAILED(FilterGraph->AddFilter(RendererVideo,L"Video Null Renderer" ))) {return false;}
+               QzCComPtr<IBaseFilter> SampleGrabberVideo;
+               if(FAILED(CoCreateInstance(CLSID_SampleGrabber, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&SampleGrabberVideo))) {return false;}
+               if(FAILED(FilterGraph->AddFilter(SampleGrabberVideo, VIDEO_SAMPLEGRABBER_FILTER_NAME))) {return false;}
+               // Set the video samplegrabber
+               QzCComPtr<ISampleGrabber> SampleGrabber;
+               if(FAILED(SampleGrabberVideo->QueryInterface(IID_ISampleGrabber, (void**)&SampleGrabber))) {return false;}
+               AM_MEDIA_TYPE mt;
+               mt.majortype=MEDIATYPE_Video;
+               mt.subtype=GUID_NULL;
+               mt.pUnk=NULL;
+               mt.cbFormat=0;
+               if(FAILED(SampleGrabber->SetMediaType(&mt))) {return false;}
+               //render the pin or filter
+               if(FAILED(CaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, FilterOrPinToRender, SampleGrabberVideo, RendererVideo))) {return false;}
+       }
+
+       if(RenderAudio)
+       {
+               // Add NullRenderer filters because we want to set formats with IAMStreamConfig COM-Interface while the complete
+               // filtergraph is connected. NullRenderer filters and the SampleGrabber filter accept all formats.
+               QzCComPtr<IBaseFilter> RendererAudio;
+               CoCreateInstance(CLSID_NullRenderer, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&RendererAudio); //CLSID_DSoundRender for DirectSound Filter
+               FilterGraph->AddFilter(RendererAudio, L"Audio Null Renderer");
+               QzCComPtr<IBaseFilter> SampleGrabberAudio;
+               CoCreateInstance(CLSID_SampleGrabber, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&SampleGrabberAudio);
+               FilterGraph->AddFilter(SampleGrabberAudio, AUDIO_SAMPLEGRABBER_FILTER_NAME);
+               // Set the audio samplegrabber filter
+               QzCComPtr<ISampleGrabber> SampleGrabber;
+               SampleGrabberAudio->QueryInterface(IID_ISampleGrabber, (void**)&SampleGrabber);
+               AM_MEDIA_TYPE mt;
+               mt.majortype=MEDIATYPE_Audio;
+               mt.subtype=GUID_NULL;
+               mt.pUnk=NULL;
+               mt.cbFormat=0;
+               SampleGrabber->SetMediaType(&mt);
+
+               //Render Audio
+               if(IsPin) //if we should render a pin
+               {
+                       HRESULT hr=CaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FilterOrPinToRender, SampleGrabberAudio, RendererAudio);
+                       if(hr!=S_OK) {return false;}
+               }
+               // If we should render a filter
+
+               else if(FAILED(CaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FilterOrPinToRender, SampleGrabberAudio, RendererAudio)))
+               {
+                       /* The avcap library doesn't provide full audio support at this time. There are only some basic audio
+                        functions implemented (not implemented: audio capture functions, ...)*/
+
+                       /* Some notes about DirectShow and audio capture
+                        - Old VFW driver based capture devices don't support audio.
+                        - New WDM driver based capture devices can support audio:
+                        1. The capture filter has audio output pins which have to be connected to a sound rendering DirectShow filter
+                        2. The capture filter has crossbar support and the audio output pins are on the crossbar and have to
+                        be connected to a sound rendering DirectShow filter.
+                        3. Many capture devices (e.g. tv tuner cards) don't provide direct audio support. They have audio
+                        connectors which have to be connected to a soundcard by cable. The soundcard takes up the
+                        capture process of the audio data. In this case, a soundcard capture DirectShow filter is needed.
+                        What we do if the function above fails?? We insert a audio capture DirectShow filter in the filtergraph
+                        and connect it to the sound rendering DirectShow filter. What can we do if multiple soundcards
+                        are installed - which audio capture DirectShow filter should we use?? Normally the user has to choose the
+                        audio capture DirectShow filter. But because of the uncomplete audio implementation of the avcap library 
+                        we use the first audio capture DirectShow Filter we'll find in the system. */
+
+                       /* TODO: Complete the audio functionality */
+
+                       std::list<IBaseFilter*> AudioCaptureFilterList;
+                       GetInstalledAudioDevices(AudioCaptureFilterList);
+                       for(std::list<IBaseFilter*>::iterator Iter=AudioCaptureFilterList.begin(); Iter!=AudioCaptureFilterList.end(); Iter++)
+                       {
+                               FilterGraph->AddFilter((*Iter), L"AudioCaptureFilter");
+                               if(SUCCEEDED(CaptureGraphBuilder->RenderStream(NULL, &MEDIATYPE_Audio, (*Iter), SampleGrabberAudio, RendererAudio)))
+                               {
+                                       break;
+                               }
+                               FilterGraph->RemoveFilter((*Iter));
+                       }
+                       DeleteList(AudioCaptureFilterList);
+               }
+       }
+
+       return true;
+}
+
+static inline void DeleteList(std::list<IPin*> &PinList)
+{
+       for (std::list<IPin*>::iterator Iter=PinList.begin(); Iter!=PinList.end(); Iter++) {
+               if ((*Iter)!=NULL) {
+                       (*Iter)->Release();
+               }
+       }
+       PinList.clear();
+}
+
+static inline void DeleteList(std::list<IBaseFilter*> &AudioCaptureFilterList)
+{
+       for (std::list<IBaseFilter*>::iterator Iter=AudioCaptureFilterList.begin(); Iter
+                       !=AudioCaptureFilterList.end(); Iter++) {
+               if ((*Iter)!=NULL) {
+                       (*Iter)->Release();
+               }
+       }
+       AudioCaptureFilterList.clear();
+}
+
+static inline void DeleteList(std::list<AM_MEDIA_TYPE*> &MediaTypeList)
+{
+       for (std::list<AM_MEDIA_TYPE*>::iterator Iter=MediaTypeList.begin(); Iter
+                       !=MediaTypeList.end(); Iter++) {
+               DeleteMediaType(*Iter);
+       }
+       MediaTypeList.clear();
+}
+
+#endif
diff --git a/extra_lib/include/avcap/windows/SampleGrabberCallback.h b/extra_lib/include/avcap/windows/SampleGrabberCallback.h
new file mode 100644 (file)
index 0000000..195615d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * (c) 2005, 2008 Nico Pranke <Nico.Pranke@googlemail.com>, Robin Luedtke <RobinLu@gmx.de> 
+ *
+ * This file is part of avcap.
+ *
+ * avcap 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * avcap 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 avcap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* avcap is free for non-commercial use.
+ * To use it in commercial endeavors, please contact Nico Pranke <Nico.Pranke@googlemail.com>.
+ */
+
+#ifndef SAMPLEGRABBER_H_
+#define SAMPLEGRABBER_H_
+
+#include "QEdit.h"
+
+#include "IOBuffer.h"
+#include "avcap-export.h"
+
+namespace avcap
+{
+class DS_VidCapManager;
+
+       //! Data capture handler for DirectShow devices.
+       
+       /*! Each time new data arrives, the method
+        * SampleCB() is called and delivers the data to the video capture 
+        * manager set by the SetVideoCaptureManager() method.*/
+
+       class AVCAP_Export SampleGrabberCallback : public ISampleGrabberCB
+       {
+       private:
+               DS_VidCapManager*       mVidCapMngr;
+               ISampleGrabber*         mSampleGrabberFilter;
+               HANDLE&                         mLock;
+
+       public:
+               SampleGrabberCallback(HANDLE& lock);
+               
+               ~SampleGrabberCallback();
+       
+               /*! Sets the video capture manager. 
+                * New data will be delivered to the video capture manager.
+                * \param vidCapManager The video capture manager. */
+               void SetVideoCaptureManager(DS_VidCapManager *vidCapManager);
+       
+               /*! Sets the samplegrabber filter. 
+                * Needed to get some information (e.g. currently used format).
+                * \param SampleGrabberFilter The samplegrabber filter. */
+               void SetSampleGrabberFilter(ISampleGrabber *SampleGrabberFilter);
+       
+               /* Fake referance counting - This is safe because the application 
+                * creates the object on the stack, and the object remains in scope 
+                * throughout the lifetime of the filter graph.*/
+               STDMETHODIMP_(ULONG) AddRef() 
+                       { return 1; }
+               
+               STDMETHODIMP_(ULONG) Release() 
+                       { return 2; }
+
+               STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
+       
+               /*! New data (captured data) arrives here and will be
+                * delivered to the video capture manager set 
+                * by the SetVideoCaptureManager() method. */
+               STDMETHODIMP SampleCB(double Time, IMediaSample *pSample);
+
+               STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen);
+       
+               friend class IOBuffer;
+       };
+}
+
+#endif // SAMPLEGRABBER_H_
index e8e8b79360d1a2aa9abcb1ec58bd320d065b11d0..f83921200b69de73e714ea90ffaaf07b0a0560e7 100644 (file)
@@ -80,12 +80,12 @@ function open_widget_manager(extension)
                  WidgetManager.last_widget_dir = directory;\r
                  widget_insert_icon(new_wid);\r
                  dock.layout(dock.width, dock.height);\r
-                 open_dock(true);\r
+                 show_dock(true);\r
     }\r
     filebrowse.on_directory = function(directory) {\r
                WidgetManager.last_widget_dir = directory;\r
                scan_directory(directory);\r
-                 open_dock(true);\r
+                 show_dock(true);\r
     }\r
     filebrowse.set_size(320 , 240);\r
     gpacui_show_window(filebrowse);\r
@@ -100,7 +100,7 @@ function open_widget_manager(extension)
     widman_cfg_dlg.close();\r
     widman_cfg_dlg = null;\r
          dock.layout(dock.width, dock.height);\r
-         open_dock(true);\r
+         show_dock(true);\r
   }\r
   widman_cfg_dlg.on_close = function() {\r
    widman_cfg_dlg = null;\r
@@ -332,6 +332,49 @@ function on_widget_load()
 }\r
 \r
 \r
+mpegu_targets = null;\r
+\r
+function select_mpegu_target(callback)\r
+{ \r
+  if (mpegu_targets) return;\r
+  mpegu_targets = gw_new_file_open();\r
+  mpegu_targets.set_label('Select Remote Display');\r
+  mpegu_targets.callback = callback;\r
+\r
+  mpegu_targets.on_close = function() {\r
+   mpegu_targets = null;\r
+  }\r
+  /*override browse function*/\r
+  mpegu_targets._on_mpegu_click = function() {\r
+       var target = (this.render_idx<0) ? null : WidgetManager.get_mpegu_service_providers(this.render_idx);\r
+\r
+               mpegu_targets.callback(target);\r
+               mpegu_targets.callback = null;\r
+    mpegu_targets.close();\r
+    mpegu_targets = null;\r
+  }\r
+  mpegu_targets._browse = function(dir, up) {\r
+   var w, h, i, y;\r
+   this.area.reset_children();\r
\r
+   for (i=0; ; i++) {\r
+               var target = WidgetManager.get_mpegu_service_providers(i);\r
+               if (!target) break;\r
+               var     icon = 'icons/applications-internet.svg';\r
+    var item = gw_new_icon_button(this.area, icon, target.Name, 'button');\r
+    item.set_size(item.width, item.height);\r
+    item.render_idx = i;\r
+    item.on_click = this._on_mpegu_click;\r
+   }  \r
+   this.layout(this.width, this.height);\r
+ }\r
+ mpegu_targets.browse('');  \r
+ mpegu_targets.go_up.hide();\r
+ mpegu_targets.set_size(display_width, display_height);\r
+ gpacui_show_window(mpegu_targets);\r
+}\r
+\r
+\r
 function new_widget_control(widget)\r
 {\r
   var ctrl;\r
@@ -447,7 +490,7 @@ function new_widget_control(widget)
   if (UPnP_Enabled) {\r
     ctrl.remote = ctrl.add_tool(gwskin.images.remote_display, gwskin.labels.remote_display);\r
     ctrl.remote.on_click = function() { \r
-      var dlg = select_remote_display('callback', new_migrate_callback(this.dlg.widget) );    \r
+      var dlg = select_mpegu_target(new_migrate_callback(this.dlg.widget) );    \r
     };  \r
        \r
     ctrl.show_remote = function(show) {\r
@@ -575,7 +618,7 @@ function on_widget_launch() {
        } else {\r
                widget_launch(this.widget);\r
        }\r
-  open_dock(false);\r
+  show_dock(false);\r
 }\r
 \r
 \r
@@ -721,9 +764,10 @@ function widget_request_install(wid, args)
                        break;\r
                }\r
        }\r
+       alert('opening widget '+wid_url);\r
        /*not found, install new widget*/\r
        if (j == count) {\r
-               var new_wid = WidgetManager.open(wid_url, null);\r
+               var new_wid = WidgetManager.open(wid_url, null, wid);\r
                if (new_wid==null) return;\r
                widget_insert_icon(new_wid);\r
        }\r
@@ -751,7 +795,7 @@ function widget_migrate_component(wid, args)
                WidgetManager.migrate_widget(UPnP.GetMediaRenderer(parseInt(args[1])), comp);\r
                widget_close(comp);\r
        } else {\r
-    var dlg = select_remote_display('callback', new_migrate_callback(comp) );    \r
+    var dlg = select_mpegu_target(new_migrate_callback(comp) );    \r
        }\r
        if (ifce != null) {\r
                wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 1); // send return code 1 = success\r
index 6767db7e0a95fc21c2843cdb6b6bce400b4a6687..d09946bf7b003acc167bf85272e488249043d351 100644 (file)
@@ -28,6 +28,7 @@ UPnP_Enabled = false;
 browser_mode = false;
 upnp_renderers = null;
 current_url = '';
+current_duration = 0.0;
 current_time = 0.0;
 player_control = null;
 
@@ -45,6 +46,7 @@ function new_extension()
 function on_movie_duration(value)
 {
   if (value<0) value=0;
+  current_duration = value;
   player_control.set_duration(value);
   if (UPnP_Enabled) UPnP.MovieDuration = value;
 }
@@ -102,11 +104,11 @@ function filter_event(evt)
   if ((start_drag_x == evt.mouse_x) && (start_drag_y == evt.mouse_y)) {
 /*
    if (dock.visible) {
-    open_dock(false);
+    show_dock(false);
    } else 
 */   
    {
-    open_dock(false);
+    show_dock(false);
     if (player_control.visible) {
       //player_control.hide();
       top_wnd = null;
@@ -123,7 +125,7 @@ function filter_event(evt)
   //commented out as HOME is used for viewpoint reset
 /*
   if (evt.keycode=='Home') {
-    open_dock(!dock.visible);
+    show_dock(!dock.visible);
     return true;
   }
 */
@@ -162,16 +164,27 @@ function filter_event(evt)
 }
 
 
-function open_dock(show)
+function show_dock(show)
 {
  if (show) {
   dock.show();
+  if (movie_connected) {
+   dock.set_size(display_width, display_height/2);
+   dock.move(0, -display_height/4);
+   movie.scale.x = movie.scale.y = 0.5;
+   movie.translation.y = display_height/4;
+  } else {
+   dock.set_size(display_width, display_height);
+   dock.move(0, 0);
+  }
   dock.layout();
   player_control.hide();
-  set_movie_url('');
+//  set_movie_url('');
   top_wnd = dock;
 //  uidisplay.hide();
  } else {
+  movie.scale.x = movie.scale.y = 1;
+  movie.translation.y = 0;
   dock.hide();
   player_control.hide();
   top_wnd = null;
@@ -212,6 +225,21 @@ function gpacui_show_window(obj)
  layout();
 }
  
+function compute_movie_size(width, height)
+{
+   var w, h, r_w, r_h;
+   if (!width || !height) return;
+   
+   w = width;
+   h = height;
+   r_w = r_h = 1;
+   if (w < min_width) r_w = Math.ceil(min_width/w);
+   if (h < min_height) r_h = Math.ceil(min_height/h);
+   if (r_w < r_h) r_w = r_h;
+   w = r_w * w;
+   h = r_w * h;
+   gpac.set_size(w, h);
+}
 
 //Initialize the main UI script
 function initialize() {
@@ -222,8 +250,8 @@ function initialize() {
     gpac.caption = 'Osmo4';
     current_time = 0;
 
-    min_width = 320;
-    min_height = 240;
+    min_width = 160;
+    min_height = 80;
     
     /*load the UI lib*/
     Browser.loadScript('gwlib.js', false);
@@ -239,10 +267,42 @@ function initialize() {
 //    gwskin.tooltip_callback = function(over, label) { alert('' + over ? label : ''); };
 
     root.children[0].backColor = gwskin.back_color;
+    movie.children[0].on_size = function(evt) {
+      if (!gpac.fullscreen) {
+       compute_movie_size(evt.width, evt.height);
+      }
+    }
+    movie.children[0].addEventListener('gpac_scene_attached', movie.children[0].on_size, 0);
+
+    movie.children[0].on_media_progress = function(evt) {
+     if (!current_duration) return;
+     /*this is not conform to HTML5, we're using the old MediaAccessEvent syntax ...*/
+     var percent_dload = 100.0 * evt.loaded / evt.total;
+     var percent_playback = 100.0 * current_time / current_duration;
+     //alert('URL data ' + percent_dload + ' - ' + percent_playback + ' playback');     
+    }
+    movie.children[0].addEventListener('progress', movie.children[0].on_media_progress, 0);
+
+    movie.children[0].on_media_playing = function(evt) {
+     alert('URL is now paying');     
+    }
+    movie.children[0].addEventListener('playing', movie.children[0].on_media_playing, 0);
+    movie.children[0].addEventListener('canplay', movie.children[0].on_media_playing, 0);
+
+    movie.children[0].on_media_waiting = function(evt) {
+     alert('URL is now buffering');     
+    }
+    movie.children[0].addEventListener('waiting', movie.children[0].on_media_waiting, 0);
+
     
     display_width = parseInt( gpac.getOption('General', 'LastWidth') );
     display_height = parseInt( gpac.getOption('General', 'LastHeight') );
     
+    if (!gpac.fullscreen && (!display_width || !display_height)) {
+     display_width = 320;
+     display_height = 240;
+    }
+    
     if (!gpac.fullscreen && display_width && display_height) {
      gpac.set_size(display_width, display_height);
     } else {
@@ -309,14 +369,14 @@ function initialize() {
 
     /*init our internal extensions*/
     var icon = gpacui_insert_dock_icon('Player', 'icons/applications-multimedia.svg');
-    icon.on_click = function () { dock.hide(); player_control.show(); };
+    icon.on_click = function () { show_dock(false); player_control.show(); };
     
     if (UPnP_Enabled) {
       icon = gpacui_insert_dock_icon('Control', 'icons/video-display.svg');
-      icon.on_click = function () { select_remote_display('select'); };
+      icon.on_click = function () { show_dock(false); select_remote_display('select'); };
 
       icon = gpacui_insert_dock_icon('Remote', 'icons/applications-internet.svg');
-      icon.on_click = function () { browse_remote_servers('select'); };
+      icon.on_click = function () { set_movie_url(''); show_dock(false); browse_remote_servers('select'); };
     }
 
     /*init all extensions*/
@@ -339,7 +399,7 @@ function initialize() {
       if (extension.icon && extension.launch) {
        var icon = gpacui_insert_dock_icon(extension.label, extension.path+extension.icon);
        icon.extension = extension;
-       icon.on_click = function () { dock.hide(); this.extension.launch(this.extension); }
+       icon.on_click = function () { show_dock(false); this.extension.launch(this.extension); }
       }
       if (extension.initialize) extension.initialize(extension);
     }
@@ -354,7 +414,7 @@ function initialize() {
       if (url.indexOf('://')<0) set_movie_url('gpac://'+url);
       else set_movie_url(url);
     } else {
-//     open_dock(true);
+//     show_dock(true);
         player_control.show();
   }
 }
@@ -377,12 +437,13 @@ function set_movie_url(url)
     test_resource.on_attached = function(evt) {
 
       this.callback_done = true;
+      var current_url = this.url[0];
+      
+      /*process the error or connect service*/
       if (evt.error) {
         var notif = gw_new_message(null, 'Error!', 'Failed to open\n'+this.url[0]+ '\nReason: '+gpac.error_string(evt.error) );
         gpacui_show_window(notif);
       } else {
-        current_url = this.url[0];
-
         movie.children[0].url[0] = current_url;
         movie_ctrl.url[0] = current_url;
         movie_sensor.url[0] = current_url;
@@ -390,22 +451,18 @@ function set_movie_url(url)
 
         if (!movie_connected) {
           if (!gpac.fullscreen) {
-           var w, h;
-           w = evt.width;
-           if (w < min_width) w = min_width;
-           h = evt.height;
-           if (h < min_height) h = min_height;
-           gpac.set_size(w, h);
+           compute_movie_size(evt.width, evt.height);
           }
           movie_connected = true;
           gpac.set_3d(evt.type3d ? 1 : 0);
         }
       }
-      /*and destroy the resource node*/
+      /*destroy the resource node*/
       this.url.length = 0;
       gw_detach_child(this);
       test_resource.removeEventListener('gpac_scene_attached', test_resource.on_attached, 0);
       this.on_attached = null;
+      
     }
     /*get notified when service loads or fails*/
     test_resource.addEventListener('gpac_scene_attached', test_resource.on_attached, 0);
@@ -441,7 +498,9 @@ function layout()
   var i, list, start_x;
   player_control.set_size(display_width, player_control.height);
 
+  
   dock.set_size(display_width, display_height);
+//  dock.set_size(display_width, display_height);
 //  if (uidisplay.children.length) uidisplay.children[0].set_size(display_width, display_height);
 }
 
@@ -667,7 +726,7 @@ function new_player_control(container)
   
   if (!browser_mode) {
     wnd.home = gw_new_icon_button(wnd.infobar, 'icons/go-home.svg', 'Home', 'icon');
-    wnd.home.on_click = function() { open_dock(true); }
+    wnd.home.on_click = function() { show_dock(true); }
     wnd.home.set_size(small_control_icon_size, small_control_icon_size);
   } else {
     wnd.home = null;
@@ -866,7 +925,7 @@ function open_local_file()
   filebrowse.on_browse = function(value, directory) {
     if (directory) gpac.last_working_directory = directory;
     set_movie_url(value);
-    open_dock(false);
+    show_dock(false);
  }
 
  filebrowse.set_size(display_width, display_height);
index 705dbc092246a324f01bfcbc2b578b45a2474451..9c7ab05b19a996feadf4b8171a318e9073513115 100644 (file)
@@ -259,24 +259,26 @@ function gw_window_show_hide()
    this.timer = gw_new_timer(1);
    this.timer.set_timeout(0.25, false);
    this.timer.on_fraction = function(val) {
+    if (!this.wnd) return;
     if (this.wnd.visible) {
       this.wnd.scale.x = 1-val;
       this.wnd.scale.y = 1-val;
-      this.wnd.set_alpha(1-val);
+      this.wnd.set_alpha( (1-val) * this.wnd.alpha);
     } else {
       this.wnd.scale.x = val;
       this.wnd.scale.y = val;
-      this.wnd.set_alpha(val);
+      this.wnd.set_alpha(val * this.wnd.alpha);
     }
    }
    this.timer.on_active = function(val) {
     var fun;
-    if (val) return;
+    if (val || !this.wnd) return;
     var wnd = this.wnd;
     this.wnd = null;
     wnd.visible = !wnd.visible;
     wnd.scale.x = wnd.visible ? 1 : 0;
     wnd.scale.y = wnd.visible ? 1 : 0;
+    wnd.set_alpha(wnd.alpha);
     fun = this.call_on_end;
     this.call_on_end = null;
     if (fun) {
@@ -284,6 +286,10 @@ function gw_window_show_hide()
     }
    }
  }
+ /*not done yet! This can happen when the function is called faster than the animation duration*/
+ if (this.timer.wnd) return;
+ this.alpha = this.get_alpha();
  this.set_alpha(1.0);
  this.timer.wnd = this;
  this.timer.start(0);
@@ -616,6 +622,9 @@ function gw_new_rectangle(class_name, style)
    obj.set_alpha = function(alpha) {
     this.children[0].appearance.material.transparency = 1-alpha;
    }
+   obj.get_alpha = function() {
+    return 1 - this.children[0].appearance.material.transparency;
+   } 
    obj.set_fill_color = function(r, g, b) {
     this.children[0].appearance.material.emissiveColor.r = r;
     this.children[0].appearance.material.emissiveColor.g = g;
@@ -636,6 +645,7 @@ function gw_new_rectangle(class_name, style)
    obj.set_fill_color = function(r, g, b) {}
    obj.set_strike_color = function(r, g, b) {}
    obj.set_line_width = function(width) {}
+   obj.get_alpha = function() { return 1; }
   }
   
   obj.set_style = function(classname, style) {
@@ -839,6 +849,10 @@ function gw_new_window(parent, offscreen, class_name)
     obj.set_alpha = function(alpha) {
      this.children[0].appearance.material.transparency = 1 - alpha;
     } 
+    obj.get_alpha = function() {
+     return 1 - this.children[0].appearance.material.transparency;
+    } 
+
     obj.add_child = function(child) {
      this.children[0].appearance.texture.children[this.children[0].appearance.texture.children.length] = child;
     }
@@ -1618,6 +1632,8 @@ function gw_new_slider(parent, vertical, class_name)
   }
   obj.min = 0;
   obj.max = 100;
+  obj.frac = 0;
+  obj.set_trackpoint(0);
   
   obj.move = function(x,y) {
    this.translation.x = x;
index e10827e12fd87e58ed54edcfd9e89d10037fcf54..d9cb1a9acbf8a7c7405455b4d7f8e6a50db291ab 100644 (file)
-// to make sure the initialization is done only once
-init = true;
-
-// constant
-xlinkns = 'http://www.w3.org/1999/xlink';
-evns = 'http://www.w3.org/2001/xml-events';
-
-// state of the widget manager: displays homepage (value=home) or executes widget (value="exec")
-state = 'home';
-
-// convenience variables for SVG elements
-homepage = null, arrows = null, icons = null, widgetContainer = null, homebar = null, execbar = null;
-
-// where is the index into pages of icons on the home page
-where = 0, maxwhere = 0, whereW = 0;
-
-// array of activated widgets
-activatedWidgets = new Array();
-numActivatedWidgets = 0;
-
-// variables for flexible layout
-// variables for flexible layout
-totalWidth = 0, totalHeight = 0, iconNbHoriz = 0, iconNbVert = 0, iconsPerPage = 0;
-
-//previous size
-previousWidth = 0, previousHeight = 0;
-
-// to differentiate between install icon and scan dir for icons
-isThisAScan = null;
-
-// preferred icon type
-preferredIconType = '.svg';
-
-// adapt layout to the size of the screen
-function adaptLayoutToSize() {
-    if (l_deb < log_level) alert("[UI] adaptLayoutToSize");
-    var tmpObject, tmpObj2;
-    // get size to adapt to
-    totalWidth = document.documentElement.viewport.width;
-    totalHeight = document.documentElement.viewport.height;
-    if (totalWidth == 0) totalWidth = 160;
-    if (totalHeight == 0) totalHeight = 280;
-    while (totalWidth < 160 || totalHeight < 280) {
-        totalWidth *= 4;
-        totalHeight *= 4;
-    }
-    // min size is 160 by 280
-    if (totalWidth < 160) totalWidth = 160;
-    if (totalHeight < 280) totalHeight = 280;
-    // round to lower multiple of 80
-    totalWidth -= totalWidth % 80;
-    var iconHeight = totalHeight - 120;
-    iconHeight -= iconHeight % 80;
-    // how many lines and columns of icons
-    iconNbHoriz = totalWidth / 80;
-    iconNbVert = iconHeight / 80;
-    totalHeight = iconHeight + 120;
-    // 120 is upper bar (60) + lower bar (60)
-    iconsPerPage = iconNbHoriz * iconNbVert;
-    // fix svg viewbox
-    document.getElementById("svg").setAttribute("viewBox", "0 0 " + totalWidth + " " + totalHeight);
-    // fix odd line
-    tmpObj2 = document.getElementById("odd");
-    var i, already = tmpObj2.getElementsByTagName("use").length;
-    //alert("odd line "+already+" "+iconNbHoriz);
-    for (i = already; i < iconNbHoriz; i++) {
-        tmpObject = document.createElement("use");
-        tmpObject.setAttribute("x", i * 80);
-        tmpObject.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#lightRect" : "#darkRect" ));
-        tmpObj2.appendChild(tmpObject);
-    }
-    // fix even line
-    tmpObj2 = document.getElementById("even");
-    already = tmpObj2.getElementsByTagName("use").length;
-    //alert("even line "+already+" "+iconNbHoriz);
-    for (i = already; i < iconNbHoriz; i++) {
-        tmpObject = document.createElement("use");
-        tmpObject.setAttribute("x", i * 80);
-        tmpObject.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#darkRect" : "#lightRect" ));
-        tmpObj2.appendChild(tmpObject);
-    }
-    // fix frame (black with rounded corners)
-    tmpObject = document.getElementById("frame");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight);
-    tmpObject = document.getElementById("frame2");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight);
-    // fix screen (white)
-    tmpObject = document.getElementById("screen");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight - 120);
-    // fix grid back (gray)
-    tmpObject = document.getElementById("gridback");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight - 120);
-    // fix icon background grid
-    tmpObject = document.getElementById("grid");
-    already = tmpObject.getElementsByTagName("use").length;
-    for (i = already; i < iconNbVert; i++) {
-        tmpObj2 = document.createElement("use");
-        tmpObj2.setAttribute("y", i * 80);
-        tmpObj2.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#odd" : "#even" ));
-        tmpObject.appendChild(tmpObj2);
-    }
-    // if there are already too many lines, remove the extra ones otherwise they are rendered on top of the lower
-    // part of the decoration
-    if (already > iconNbVert) {
-        while (already-- > iconNbVert) tmpObject.removeChild(tmpObject.lastChild);
-    }
-    // fix commands (lower bar)
-    document.getElementById("commands").setAttribute("transform", "translate(0, " + (totalHeight - 60) + ")");
-    document.getElementById("homeButton").setAttribute("transform", "translate(" + (totalWidth / 2) + ", 30)");
-    document.getElementById("right").setAttribute("transform", "translate(" + (totalWidth - 50) + ", 10)");
-    document.getElementById("rightW").setAttribute("transform", "translate(" + (totalWidth - 50) + ", 10)");
-    // fix the cuts (white rects left and right because we have no clipping)
-    tmpObject = document.getElementById("leftCut");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight);
-    tmpObject.setAttribute("x", -1 - totalWidth);
-    tmpObject = document.getElementById("rightCut");
-    tmpObject.setAttribute("width", totalWidth);
-    tmpObject.setAttribute("height", totalHeight);
-    tmpObject.setAttribute("x", 1 + totalWidth);
-    // respace executing widgets if any
-    tmpObject = widgetContainer.getElementsByTagName("g");
-    for (i = 0; i < tmpObject.length; i++) {
-        var gg = tmpObject.item(i);
-        gg.setAttribute("transform", "translate(" + (totalWidth * (i - 1)) + ", 0)");
-        if (gg.firstElementChild != null) {
-            gg.firstElementChild.setAttribute("width", totalWidth);
-            gg.firstElementChild.setAttribute("height", totalHeight - 120);
+// 01122011 AMD1 startWidget listWidgets getWidget implemented
+
+var iphone_wm_gui = (function () {
+
+    // to make sure the initialization is done only once
+    var init = true;
+
+    // constant
+    var xlinkns = 'http://www.w3.org/1999/xlink';
+    //var evns = 'http://www.w3.org/2001/xml-events';
+
+    // state of the widget manager: displays homepage (value=home) or executes widget (value="exec")
+    var state = 'home';
+
+    // convenience variables for SVG elements
+    var homepage = null, arrows = null, icons = null, widgetContainer = null, homebar = null, execbar = null;
+
+    // where is the index into pages of icons on the home page
+    var where = 0,maxwhere = 0,whereW = 0;
+
+    // array of activated widgets
+    var activatedWidgets = new Array();
+    var numActivatedWidgets = 0;
+
+    // variables for flexible layout
+    // variables for flexible layout
+    var totalWidth = 0,totalHeight = 0,iconNbHoriz = 0,iconNbVert = 0,iconsPerPage = 0;
+
+    //previous size
+    var previousWidth = 0,previousHeight = 0;
+
+    // to differentiate between install icon and scan dir for icons
+    var isThisAScan = null;
+
+    // preferred icon type
+    var preferredIconType = '.svg';
+
+    // adapt layout to the size of the screen
+    function adaptLayoutToSize() {
+        if (l_deb < log_level) {
+            alert("[UI] adaptLayoutToSize");
+        }
+        var tmpObject, tmpObj2;
+        // get size to adapt to
+        totalWidth = document.documentElement.viewport.width;
+        totalHeight = document.documentElement.viewport.height;
+        if (totalWidth == 0) {
+            totalWidth = 160;
+        }
+        if (totalHeight == 0) {
+            totalHeight = 280;
+        }
+        while (totalWidth < 160 || totalHeight < 280) {
+            totalWidth *= 4;
+            totalHeight *= 4;
+        }
+        // min size is 160 by 280
+        if (totalWidth < 160) {
+            totalWidth = 160;
+        }
+        if (totalHeight < 280) {
+            totalHeight = 280;
+        }
+        // round to lower multiple of 80
+        totalWidth -= totalWidth % 80;
+        var iconHeight = totalHeight - 120;
+        iconHeight -= iconHeight % 80;
+        // how many lines and columns of icons
+        iconNbHoriz = totalWidth / 80;
+        iconNbVert = iconHeight / 80;
+        totalHeight = iconHeight + 120;
+        // 120 is upper bar (60) + lower bar (60)
+        iconsPerPage = iconNbHoriz * iconNbVert;
+        // fix svg viewbox
+        document.getElementById("svg").setAttribute("viewBox", "0 0 " + totalWidth + " " + totalHeight);
+        // fix odd line
+        tmpObj2 = document.getElementById("odd");
+        var i, already = tmpObj2.getElementsByTagName("use").length;
+        //alert("odd line "+already+" "+iconNbHoriz);
+        for (i = already; i < iconNbHoriz; i++) {
+            tmpObject = document.createElement("use");
+            tmpObject.setAttribute("x", i * 80);
+            tmpObject.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#lightRect" : "#darkRect" ));
+            tmpObj2.appendChild(tmpObject);
+        }
+        // fix even line
+        tmpObj2 = document.getElementById("even");
+        already = tmpObj2.getElementsByTagName("use").length;
+        //alert("even line "+already+" "+iconNbHoriz);
+        for (i = already; i < iconNbHoriz; i++) {
+            tmpObject = document.createElement("use");
+            tmpObject.setAttribute("x", i * 80);
+            tmpObject.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#darkRect" : "#lightRect" ));
+            tmpObj2.appendChild(tmpObject);
+        }
+        // fix frame (black with rounded corners)
+        tmpObject = document.getElementById("frame");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight);
+        tmpObject = document.getElementById("frame2");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight);
+        // fix screen (white)
+        tmpObject = document.getElementById("screen");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight - 120);
+        // fix grid back (gray)
+        tmpObject = document.getElementById("gridback");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight - 120);
+        // fix icon background grid
+        tmpObject = document.getElementById("grid");
+        already = tmpObject.getElementsByTagName("use").length;
+        for (i = already; i < iconNbVert; i++) {
+            tmpObj2 = document.createElement("use");
+            tmpObj2.setAttribute("y", i * 80);
+            tmpObj2.setAttributeNS(xlinkns, "href", (((i % 2) == 0) ? "#odd" : "#even" ));
+            tmpObject.appendChild(tmpObj2);
+        }
+        // if there are already too many lines, remove the extra ones otherwise they are rendered on top of the lower
+        // part of the decoration
+        if (already > iconNbVert) {
+            while (already-- > iconNbVert) {
+                tmpObject.removeChild(tmpObject.lastChild);
+            }
+        }
+        // fix commands (lower bar)
+        document.getElementById("commands").setAttribute("transform", "translate(0, " + (totalHeight - 60) + ")");
+        document.getElementById("homeButton").setAttribute("transform", "translate(" + (totalWidth / 2) + ", 30)");
+        document.getElementById("right").setAttribute("transform", "translate(" + (totalWidth - 50) + ", 10)");
+        document.getElementById("rightW").setAttribute("transform", "translate(" + (totalWidth - 50) + ", 10)");
+        // fix the cuts (white rects left and right because we have no clipping)
+        tmpObject = document.getElementById("leftCut");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight);
+        tmpObject.setAttribute("x", -1 - totalWidth);
+        tmpObject = document.getElementById("rightCut");
+        tmpObject.setAttribute("width", totalWidth);
+        tmpObject.setAttribute("height", totalHeight);
+        tmpObject.setAttribute("x", 1 + totalWidth);
+        // respace executing widgets if any
+        tmpObject = widgetContainer.getElementsByTagName("g");
+        for (i = 0; i < tmpObject.length; i++) {
+            var gg = tmpObject.item(i);
+            gg.setAttribute("transform", "translate(" + (totalWidth * (i - 1)) + ", 0)");
+            if (gg.firstElementChild != null) {
+                gg.firstElementChild.setAttribute("width", totalWidth);
+                gg.firstElementChild.setAttribute("height", totalHeight - 120);
+            }
         }
     }
-}
 
-//
-// widget close on click at "Kill" button
-//
-function on_kill_widget() {
-    if (state == 'exec') {
-        widget_close(activatedWidgets[whereW]);
+    //
+    // widget close on click at "Kill" button
+    //
+    function on_kill_widget() {
+        if (state == 'exec') {
+            widget_close(activatedWidgets[whereW]);
+        }
     }
-}
 
-//
-// when deleting an executing widgets, all executing widgets to its right are moved to the left
-//
-function recurseMoveAfterDelete(target) {
-    if (target != null && target.nextElementSibling != null) {
-        var v = target.nextElementSibling;
-        recurseMoveAfterDelete(v);
-        v.setAttribute("transform", target.getAttribute("transform"));
+    //
+    // widget get on click at "GetW" button
+    //
+    function on_get_widget() {
+        alert("on_get_widget "+WidgetManager.MPEGUStandardServiceProviders.length);
+        if (WidgetManager.MPEGUStandardServiceProviders.length != 0) {
+            upnp_renders = selector_window1();
+            upnp_renders.on_select = function(item) {
+                upnp_renders.unregister(root);
+                upnp_renders = null;
+                if (item == -1) {
+                    return;
+                }
+                alert("upnp_renders.on_select(" + item + ")");
+                var device = WidgetManager.MPEGUStandardServiceProviders[item];
+                device.standardService.SetActionListener("listWidgets", get_widget_callback(device), true);
+                device.standardService.CallAction("listWidgets", new Array());
+            }
+            upnp_renders.register(root);
+        }
     }
-}
 
-//
-// click on home button to switch from icons to executing widgets
-//
-function home_button(evt) {
-    if (l_deb < log_level) alert("[UI] home_button");
-    if (state != 'home') {
-        state = 'home';
-        widgetContainer.setAttribute('display', 'none');
-        homepage.setAttribute('display', 'inline');
-        homebar.setAttribute('display', 'inline');
-        execbar.setAttribute('display', 'none');
-        arrows.setAttribute('display', 'inline');
-        arrowsW.setAttribute('display', 'none');
-        widgetAddList.setAttribute('display', 'none');
-    } else {
-        state = 'exec';
-        widgetContainer.setAttribute('display', 'inline');
-        homepage.setAttribute('display', 'none');
-        homebar.setAttribute('display', 'none');
-        execbar.setAttribute('display', 'inline');
-        arrows.setAttribute('display', 'none');
-        arrowsW.setAttribute('display', 'inline');
-        widgetAddList.setAttribute('display', 'none');
+    function get_widget_callback(device) {
+        return function() {
+            //alert("get_widget_callback");
+            // msgHandler is the first argument, the next arguments are from the reply to listWidgets
+            var act = arguments[0];
+            var act1 = act.GetArgumentValue("widgetCodes");
+            var act2 = act.GetArgumentValue("widgetNames");
+            //alert(act1+" "+act2);
+            target_widgets = selector_window2(act1.split(" "), act2.split(" "));
+            target_widgets.on_select = function(item) {
+                alert("target_widgets.on_select");
+                target_widgets.unregister(root);
+                target_widgets = null;
+                if (item == -1) {
+                    return;
+                }
+                alert("target_widgets.on_select(" + item + ")");
+                var args = new Array();
+                args[0] = "widgetCode";
+                args[1] = item;
+                device.standardService.CallAction("getWidget", args);
+            }
+            target_widgets.register(root);
+        }
     }
-}
 
-// constants
-adjustFrom = "0,0";
-animDue = true;
-
-//
-// after each change of icon page, this function adjusts the visibility of arrows in the lower bar
-//
-function adjustwhere(animDue) {
-    if (l_deb < log_level) alert("[UI] adjust " + where + " 0 " + maxwhere);
-    document.getElementById("left").setAttribute("display", ((where > 0) ? "inline" : "none"));
-    document.getElementById("right").setAttribute("display", ((where < maxwhere) ? "inline" : "none"));
-    if (!animDue) {
-        icons.setAttribute("transform", 'translate(' + (-80 * iconNbHoriz * where) + ',0)');
-    } else {
-        var aw = document.createElement("animateTransform");
-        aw.setAttribute("attributeName", "transform");
-        aw.setAttribute("type", "translate");
-        //alert('time '+document.documentElement.getCurrentTime());
-        aw.setAttribute("begin", document.documentElement.getCurrentTime());
-        aw.setAttribute("dur", "1s");
-        aw.setAttribute("fill", "freeze");
-        aw.setAttributeNS(xlinkns, "href", "#icons");
-        aw.setAttribute("from", adjustFrom);
-        aw.setAttribute("to", (-80 * iconNbHoriz * where) + ",0");
-        document.documentElement.appendChild(aw);
-    }
-    adjustFrom = (-80 * iconNbHoriz * where) + ",0";
-}
+    //
+    // creates the menu of available targets for pushing a widget elsewhere
+    //
+    function selector_window1() {
+        var i, count, render;
+        var selector = document.createElement('g'), obj, child;
+        selector.setAttribute('transform', 'translate(10,10)');
+        count = WidgetManager.MPEGUStandardServiceProviders.length;
+        selector.appendChild(rect(0, 0, 300, 20 * (count + 1), 'white', 'black'));
+        for (i = 0; i < count; i++) {
+            render = WidgetManager.MPEGUStandardServiceProviders[i];
+            obj = createtext(render.Name, 'black', 5, 17 + (20 * i), 15, 'sans-serif');
+            obj.setAttribute('id', "select" + i);
+            selector.appendChild(obj);
+            obj.addEventListener('mouseover', sw1("select" + i), false);
+            obj.addEventListener('mouseout', sw2("select" + i), false);
+            obj.addEventListener('click', sw4(i), false);
+        }
+        obj = createtext('Cancel', 'rgb(0,0,120)', 55, 17 + (20 * i), 15, 'sans-serif');
+        obj.setAttribute('id', "canc");
+        selector.appendChild(obj);
+        obj.addEventListener('mouseover', function(evt) { document.getElementById("canc").setAttribute("fill", "red"); }, false);
+        obj.addEventListener('mouseout', function(evt) { document.getElementById("canc").setAttribute("fill", "black"); }, false);
+        obj.addEventListener('click', function(evt) { upnp_renders.on_select(-1); }, false);
+        selector.register = function(disp) {
+            disp.appendChild(this);
+        };
+        selector.unregister = function(disp) {
+            disp.removeChild(this);
+        };
+        return selector;
+    }
 
-//
-// action of the left button on the lower bar
-//
-function left_button() {
-    if (l_deb < log_level) alert("[UI] left button " + where + " 0");
-    if (where > 0) {
-        where--;
-        adjustwhere(true);
+    //
+    // creates the menu of available targets for pushing a widget elsewhere
+    //
+    function selector_window2(codes, names) {
+        alert("selector_window2");
+        var i, count, render;
+        var selector = document.createElement('g'), obj, child;
+        selector.setAttribute('transform', 'translate(10,10)');
+        count = codes.length;
+        selector.appendChild(rect(0, 0, 300, 20 * (count + 1), 'white', 'black'));
+        for (i = 0; i < count; i++) {
+            render = names[i];
+            obj = createtext(render, 'black', 5, 17 + (20 * i), 15, 'sans-serif');
+            obj.setAttribute('id', "selecto" + i);
+            selector.appendChild(obj);
+            obj.addEventListener('mouseover', sw1("selecto" + i), false);
+            obj.addEventListener('mouseout', sw2("selecto" + i), false);
+            obj.addEventListener('click', sw5(i), false);
+        }
+        obj = createtext('Cancel', 'rgb(0,0,120)', 55, 17 + (20 * i), 15, 'sans-serif');
+        obj.setAttribute('id', "cance");
+        selector.appendChild(obj);
+        obj.addEventListener('mouseover', function(evt) { document.getElementById("cance").setAttribute("fill", "red"); }, false);
+        obj.addEventListener('mouseout', function(evt) { document.getElementById("cance").setAttribute("fill", "black"); }, false);
+        obj.addEventListener('click', function(evt) { target_widgets.on_select(-1); }, false);
+        selector.register = function(disp) {
+            disp.appendChild(this);
+        };
+        selector.unregister = function(disp) {
+            disp.removeChild(this);
+        };
+        return selector;
     }
-}
 
-//
-// action of the right button of the lower bar
-//
-function right_button() {
-    if (l_deb < log_level) alert("[UI] right button " + where + " " + maxwhere);
-    if (where < maxwhere) {
-        where++;
-        adjustwhere(true);
+    function sw4(si) {
+        return function(evt) { upnp_renders.on_select(si); };
     }
-}
 
-adjustFromW = "0,0";
-oldwhereW = -1;
-
-//
-// after each change of icon page, this function adjusts the visibility of arrows in the lower bar
-//
-function adjustWhereWidgets(animDue) {
-    if (oldwhereW != whereW) {
-        // hide oldwhereW
-        if (oldwhereW >= 0 && activatedWidgets[oldwhereW] != null) WidgetManager.corein_message(activatedWidgets[oldwhereW], "hide");
-    }
-    if (l_deb < log_level) alert("[UI] adjustW " + whereW + " 0 " + (numActivatedWidgets - 1));
-    document.getElementById("leftW").setAttribute("display", ((whereW > 0) ? "inline" : "none"));
-    document.getElementById("rightW").setAttribute("display", ((whereW < (numActivatedWidgets - 1)) ? "inline" : "none"));
-    if (!animDue) {
-        widgetContainer.setAttribute("transform", "translate(" + (-totalWidth * whereW) + ",0)");
-    } else {
-        var aw = document.createElement("animateTransform");
-        aw.setAttribute("attributeName", "transform");
-        aw.setAttribute("type", "translate");
-        aw.setAttribute("begin", document.documentElement.getCurrentTime());
-        aw.setAttribute("dur", "1s");
-        aw.setAttribute("fill", "freeze");
-        aw.setAttributeNS(xlinkns, "href", "#widget");
-        aw.setAttribute("from", adjustFromW);
-        aw.setAttribute("to", (-totalWidth * whereW) + ",0");
-        document.documentElement.appendChild(aw);
-    }
-    adjustFromW = (-totalWidth * whereW) + ",0";
-    document.getElementById("widgetName").textContent =
-            (whereW >= 0 && activatedWidgets[whereW] != null ? activatedWidgets[whereW].shortName : '-');
-    if (oldwhereW != whereW) {
-        // show whereW
-        if (whereW >= 0 && activatedWidgets[whereW] != null) WidgetManager.corein_message(activatedWidgets[whereW], "show");
-        oldwhereW = whereW;
+    function sw5(si) {
+        return function(evt) { target_widgets.on_select(si); };
     }
-}
 
-//
-// action of the left button on the lower bar
-//
-function left_buttonW() {
-    if (l_deb < log_level) alert("[UI] left button " + whereW);
-    if (whereW > 0) {
-        whereW--;
-        adjustWhereWidgets(animDue);
+    //
+    // when deleting an executing widgets, all executing widgets to its right are moved to the left
+    //
+    function recurseMoveAfterDelete(target) {
+        if (target != null && target.nextElementSibling != null) {
+            var v = target.nextElementSibling;
+            recurseMoveAfterDelete(v);
+            v.setAttribute("transform", target.getAttribute("transform"));
+        }
     }
-}
 
-//
-// action of the right button of the lower bar
-//
-function right_buttonW() {
-    if (l_deb < log_level) alert("[UI] right button " + whereW + " " + (numActivatedWidgets - 1));
-    if (whereW < (numActivatedWidgets - 1)) {
-        whereW++;
-        adjustWhereWidgets(animDue);
+    //
+    // click on home button to switch from icons to executing widgets
+    //
+    function home_button(evt) {
+        if (l_deb < log_level) {
+            alert("[UI] home_button");
+        }
+        if (state != 'home') {
+            state = 'home';
+            widgetContainer.setAttribute('display', 'none');
+            homepage.setAttribute('display', 'inline');
+            homebar.setAttribute('display', 'inline');
+            execbar.setAttribute('display', 'none');
+            arrows.setAttribute('display', 'inline');
+            arrowsW.setAttribute('display', 'none');
+            widgetAddList.setAttribute('display', 'none');
+        } else {
+            state = 'exec';
+            widgetContainer.setAttribute('display', 'inline');
+            homepage.setAttribute('display', 'none');
+            homebar.setAttribute('display', 'none');
+            execbar.setAttribute('display', 'inline');
+            arrows.setAttribute('display', 'none');
+            arrowsW.setAttribute('display', 'inline');
+            widgetAddList.setAttribute('display', 'none');
+        }
+    }
+
+    // constants
+    var adjustFrom = "0,0";
+    var animDue = true;
+
+    //
+    // after each change of icon page, this function adjusts the visibility of arrows in the lower bar
+    //
+    function adjustwhere(animDue) {
+        if (l_deb < log_level) {
+            alert("[UI] adjust " + where + " 0 " + maxwhere);
+        }
+        document.getElementById("left").setAttribute("display", ((where > 0) ? "inline" : "none"));
+        document.getElementById("right").setAttribute("display", ((where < maxwhere) ? "inline" : "none"));
+        if (!animDue) {
+            icons.setAttribute("transform", 'translate(' + (-80 * iconNbHoriz * where) + ',0)');
+        } else {
+            var aw = document.createElement("animateTransform");
+            aw.setAttribute("attributeName", "transform");
+            aw.setAttribute("type", "translate");
+            //alert('time '+document.documentElement.getCurrentTime());
+            aw.setAttribute("begin", document.documentElement.getCurrentTime());
+            aw.setAttribute("dur", "1s");
+            aw.setAttribute("fill", "freeze");
+            aw.setAttributeNS(xlinkns, "href", "#icons");
+            aw.setAttribute("from", adjustFrom);
+            aw.setAttribute("to", (-80 * iconNbHoriz * where) + ",0");
+            document.documentElement.appendChild(aw);
+        }
+        adjustFrom = (-80 * iconNbHoriz * where) + ",0";
+    }
+
+    //
+    // action of the left button on the lower bar
+    //
+    function left_button() {
+        if (l_deb < log_level) {
+            alert("[UI] left button " + where + " 0");
+        }
+        if (where > 0) {
+            where--;
+            adjustwhere(true);
+        }
+    }
+
+    //
+    // action of the right button of the lower bar
+    //
+    function right_button() {
+        if (l_deb < log_level) {
+            alert("[UI] right button " + where + " " + maxwhere);
+        }
+        if (where < maxwhere) {
+            where++;
+            adjustwhere(true);
+        }
+    }
+
+    var adjustFromW = "0,0";
+    var oldwhereW = -1;
+
+    //
+    // after each change of icon page, this function adjusts the visibility of arrows in the lower bar
+    //
+    function adjustWhereWidgets(animDue) {
+        if (oldwhereW != whereW) {
+            // hide oldwhereW
+            if (oldwhereW >= 0 && activatedWidgets[oldwhereW] != null) {
+                WidgetManager.corein_message(activatedWidgets[oldwhereW], "hide");
+            }
+        }
+        if (l_deb < log_level) {
+            alert("[UI] adjustW " + whereW + " 0 " + (numActivatedWidgets - 1));
+        }
+        document.getElementById("leftW").setAttribute("display", ((whereW > 0) ? "inline" : "none"));
+        document.getElementById("rightW").setAttribute("display", ((whereW < (numActivatedWidgets - 1)) ? "inline" : "none"));
+        if (!animDue) {
+            widgetContainer.setAttribute("transform", "translate(" + (-totalWidth * whereW) + ",0)");
+        } else {
+            var aw = document.createElement("animateTransform");
+            aw.setAttribute("attributeName", "transform");
+            aw.setAttribute("type", "translate");
+            aw.setAttribute("begin", document.documentElement.getCurrentTime());
+            aw.setAttribute("dur", "1s");
+            aw.setAttribute("fill", "freeze");
+            aw.setAttributeNS(xlinkns, "href", "#widget");
+            aw.setAttribute("from", adjustFromW);
+            aw.setAttribute("to", (-totalWidth * whereW) + ",0");
+            document.documentElement.appendChild(aw);
+        }
+        adjustFromW = (-totalWidth * whereW) + ",0";
+        document.getElementById("widgetName").textContent =
+                (whereW >= 0 && activatedWidgets[whereW] != null ? activatedWidgets[whereW].shortName : '-');
+        if (oldwhereW != whereW) {
+            // show whereW
+            if (whereW >= 0 && activatedWidgets[whereW] != null) {
+                WidgetManager.corein_message(activatedWidgets[whereW], "show");
+            }
+            oldwhereW = whereW;
+        }
+    }
+
+    //
+    // action of the left button on the lower bar
+    //
+    function left_buttonW() {
+        if (l_deb < log_level) {
+            alert("[UI] left button " + whereW);
+        }
+        if (whereW > 0) {
+            whereW--;
+            adjustWhereWidgets(animDue);
+        }
+    }
+
+    //
+    // action of the right button of the lower bar
+    //
+    function right_buttonW() {
+        if (l_deb < log_level) {
+            alert("[UI] right button " + whereW + " " + (numActivatedWidgets - 1));
+        }
+        if (whereW < (numActivatedWidgets - 1)) {
+            whereW++;
+            adjustWhereWidgets(animDue);
+        }
+    }
+
+    //
+    // action of each icon, starting the matching widget
+    //
+    function activating_widget(w) {
+        if (l_deb < log_level) {
+            alert("[UI] activating widget: " + w.name);
+        }
+        widget_add(w);
+    }
+
+    //
+    // main initialization function
+    // init variables, then init the widget manager C code, then inits UPnP
+    //
+    function initialize() {
+        if (l_deb < log_level) {
+            alert("[UI] initialize");
+        }
+        init = false;
+        var display_width = parseInt(gpac.getOption('Widgets', 'LastWMWidth'));
+        var display_height = parseInt(gpac.getOption('Widgets', 'LastWMHeight'));
+        if (display_width && display_height) {
+            gpac.set_size(display_width, display_height);
+        }
+        root = document.documentElement;
+        homepage = document.getElementById('homepage');
+        homebar = document.getElementById('homebar');
+        execbar = document.getElementById('execbar');
+        arrows = document.getElementById('arrows');
+        arrowsW = document.getElementById('arrowsW');
+        icons = document.getElementById('icons');
+        widgetContainer = document.getElementById('widget');
+        widgetAddList = document.getElementById('widgetAddList');
+        /* Setup the GPAC Widget Manager - this will also scan the available widgets */
+        log_level = l_inf;
+        widget_manager_init();
+        WidgetManager.on_widget_remove = widget_remove;
+        WidgetManager.on_widget_add = widget_add;
+        /* register the callback to be notified of incoming widgets */
+        has_upnp = (typeof UPnP != 'undefined');
+        if (has_upnp) {
+            /* setting the callback to allow other devices to push their widgets */
+            UPnP.onMediaConnect = onMediaConnect;
+            /* Tell GPAC that the calls to the main Renderer (like open, ...) must be forwared to this scene */
+            UPnP.BindRenderer();
+        }
+        WidgetManager.coreOutShow = coreOutShowImplementation;
+        WidgetManager.coreOutGetAttention = coreOutGetAttentionImplementation;
+        WidgetManager.coreOutHide = coreOutHideImplementation;
+        WidgetManager.coreOutRequestDeactivate = coreOutRequestDeactivateImplementation;
+        WidgetManager.coreOutInstallWidget = coreOutInstallWidgetImplementation;
+        WidgetManager.coreOutActivateTemporaryWidget = coreOutActivateTemporaryWidgetImplementation;
+        WidgetManager.coreOutMigrateComponent = coreOutMigrateComponentImplementation;
+        WidgetManager.coreOutRequestMigrationTargets = coreOutRequestMigrationTargetsImplementation;
+    }
+
+    //
+    // implementation of core:out install widget
+    //
+    function coreOutInstallWidgetImplementation(wid, args) {
+        var w = widgetInstall(args[0], true, false, wid);
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.installWidgetMessage, ifce.get_message("installWidget"),
+                    wid, (w != null ? 1 : 0)); // send return code 1 = success
+        }
+    }
+
+    //
+    // implementation of core:out activate temporary widget
+    //
+    function coreOutActivateTemporaryWidgetImplementation(wid, args) {
+        var w = widgetInstall(args[0], true, true, null);
+        if (w != null) {
+            activating_widget(w);
+        }
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.activateTemporaryWidgetMessage, ifce.get_message("activateTemporaryWidget"),
+                    wid, (w != null ? 1 : 0)); // send return code 1 = success
+        }
+    }
+
+    //
+    // implementation of core:out migrate component
+    //
+    function coreOutMigrateComponentImplementation(wid, args) {
+        //alert("coreOutMigrateComponent "+wid.name+" "+args.length);
+        var comp = wid.get_component(args[0], true);
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (comp == null) {
+            log(l_err, 'Component ' + args[0] + ' cannot be found in widget ' + wid.name);
+            if (ifce != null) {
+                wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 0);
+            }
+            return;
+        }
+        if (args.length > 1 && args[1] != null) {
+            //WidgetManager.migrate_widget(UPnP.GetMediaRenderer(parseInt(args[1])), comp);
+            WidgetManager.migrate_widget(WidgetManager.get_mpegu_service_providers(parseInt(args[1])), comp);
+            widget_close(comp);
+        } else {
+            upnp_renders = selector_window(comp);
+            upnp_renders.on_select = function(item, wid) {
+                upnp_renders.unregister(root);
+                upnp_renders = null;
+                if (item == -1) {
+                    return;
+                }
+                if (comp != null) {
+                    alert("upnp_renders.on_select(" + item + "," + comp.name + ")");
+                    //WidgetManager.migrate_widget(UPnP.GetMediaRenderer(item), comp);
+                    WidgetManager.migrate_widget(WidgetManager.get_mpegu_service_providers(item), comp);
+                    widget_close(comp);
+                }
+            };
+            upnp_renders.register(root);
+        }
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 1); // send return code 1 = success
+        }
+    }
+
+    //
+    // implementation of core:out request migration targets
+    //
+    function coreOutRequestMigrationTargetsImplementation(wid, args) {
+        var count = UPnP.MediaRenderersCount, codes = new Array(), names = new Array(), descriptions = new Array(), i;
+        for (i = 0; i < count; i++) {
+            var render = UPnP.GetMediaRenderer(i);
+            codes.push("" + i);
+            names.push(render.Name);
+            descriptions.push(render.HostName + " " + render.UUID);
+        }
+        i = null;
+        var ifce_count = wid.num_interfaces, j;
+        for (j = 0; j < ifce_count; j++) {
+            var ifce = wid.get_interface(j);
+            if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:out:2010") {
+                i = ifce;
+                break;
+            }
+        }
+        if (i != null) {
+            wmjs_core_out_invoke_reply(coreOut.requestMigrationTargetsMessage, i.get_message("requestMigrationTargets"),
+                    wid, codes, names, descriptions);
+        }
+    }
+
+    //
+    // implementation of core:out Show message
+    // this is a request by the widget to be shown
+    //
+    function coreOutShowImplementation(wid, args) {
+        //alert("core:out show "+wid.name);
+        var target = widgetContainer.firstElementChild;
+        var i;
+        for (i = 0; i < numActivatedWidgets; i++) {
+            //alert("is it "+activatedWidgets[i].name);
+            if (activatedWidgets[i] == wid) {
+                break;
+            }
+            target = target.nextElementSibling;
+        }
+        // here, i is the index of the current widget
+        //alert(" "+i+" "+numActivatedWidgets);
+        if (i < numActivatedWidgets) {
+            whereW = i;
+            adjustWhereWidgets(false);
+        }
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.showMessage, ifce.get_message("show"), wid, 1); // send return code 1 = success
+        }
+    }
+
+    //
+    // implementation of core:out GetAttention message
+    // this is a request by the widget to be shown and some special signal is given
+    //
+    function coreOutGetAttentionImplementation(wid, args) {
+        //alert("core:out getAttention "+wid.name);
+        var target = widgetContainer.firstElementChild;
+        var i;
+        for (i = 0; i < numActivatedWidgets; i++) {
+            //alert("is it "+activatedWidgets[i].name);
+            if (activatedWidgets[i] == wid) {
+                break;
+            }
+            target = target.nextElementSibling;
+        }
+        // here, i is the index of the current widget
+        //alert(" "+i+" "+numActivatedWidgets);
+        if (i < numActivatedWidgets) {
+            whereW = i;
+            adjustWhereWidgets(false);
+        }
+        document.getElementById("getAttention").beginElement();
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.getAttentionMessage, ifce.get_message("getAttention"), wid, 1); // send return code 1 = success
+        }
     }
-}
 
-//
-// action of each icon, starting the matching widget
-//
-function activating_widget(w) {
-    if (l_deb < log_level) alert("[UI] activating widget: " + w.name);
-    if (widget_add(w)) {
+    //
+    // implementation of core:out hide message
+    // this is a request by the widget to be hidden (some other widget (if any) is shown)
+    //
+    function coreOutHideImplementation(wid, args) {
+        //alert("core:out hide "+wid.name);
+        var target = widgetContainer.firstElementChild;
+        var i;
+        for (i = 0; i < numActivatedWidgets; i++) {
+            //alert("is it "+activatedWidgets[i].name);
+            if (activatedWidgets[i] == wid) {
+                break;
+            }
+            target = target.nextElementSibling;
+        }
+        // here, i is the index of the current widget
+        //alert("hide "+i+" "+numActivatedWidgets);
+        if (i < numActivatedWidgets) {
+            if (whereW > 0) {
+                whereW--;
+            }
+            else if (whereW < numActivatedWidgets - 1) {
+                whereW++;
+            }
+            else {
+                return;
+            }
+            adjustWhereWidgets(false);
+        }
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.hideMessage, ifce.get_message("hide"), wid, 1); // send return code 1 = success
+        }
+    }
+
+    //
+    // implementation of core:out requestDeactivate message
+    // this is a request by the widget to be stopped
+    //
+    function coreOutRequestDeactivateImplementation(wid, args) {
+        //alert("core:out hide "+wid.name);
+        var target = widgetContainer.firstElementChild;
+        var i;
+        for (i = 0; i < numActivatedWidgets; i++) {
+            //alert("is it "+activatedWidgets[i].name);
+            if (activatedWidgets[i] == wid) {
+                break;
+            }
+            target = target.nextElementSibling;
+        }
+        // here, i is the index of the current widget
+        //alert("hide "+i+" "+numActivatedWidgets);
+        if (i < numActivatedWidgets) {
+            widget_close(activatedWidgets[i]);
+        }
+        var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
+        if (ifce != null) {
+            wmjs_core_out_invoke_reply(coreOut.requestDeactivateMessage, ifce.get_message("requestDeactivate"), wid, 1); // send return code 1 = success
+        }
+    }
+
+    //
+    // WM callback for when a component is activated by its parent
+    //
+    function widget_add(w) {
+        log(l_inf, "widget add " + w.name);
+        if (!w.activated) {
+            if (sameFileIgnoringSVGView(w.icon, w.main)) {
+                // same file in icon and main
+            } else {
+                widget_launch(w, document.createElement("animation"));
+            }
+        } else if (w.multipleInstances) {
+            var newwid = WidgetManager.open(w.manifest, null);
+            widget_launch(newwid, document.createElement("animation"));
+        } else return false;
         state = 'exec';
         widgetContainer.setAttribute('display', 'inline');
         homepage.setAttribute('display', 'none');
@@ -305,485 +736,549 @@ function activating_widget(w) {
         arrows.setAttribute('display', 'none');
         arrowsW.setAttribute('display', 'inline');
         widgetAddList.setAttribute('display', 'none');
+        return true;
     }
-}
 
-function widget_activated_and_bound(wid) {
-    WidgetManager.corein_message(wid, "activate");
-}
+    function sameFileIgnoringSVGView(name1, name2) {
+        if (name1 == name2) {
+            return true;
+        }
+        if (name1 == null) {
+            return false;
+        }
+        var i1 = name1.indexOf("#");
+        var i2 = name2.indexOf("#");
+        if (i1 < 0) {
+            i1 = name1.length;
+        }
+        else {
+            i1--;
+        }
+        if (i2 < 0) {
+            i2 = name2.length;
+        }
+        else {
+            i2--;
+        }
+        return name1.substring(0, i1) == name2.substring(0, i2);
+    }
 
-//
-// main initialization function
-// init variables, then init the widget manager C code, then inits UPnP
-//
-function initialize() {
-    if (l_deb < log_level) alert("[UI] initialize");
-    init = false;
-    var display_width = parseInt(gpac.getOption('Widgets', 'LastWMWidth'));
-    var display_height = parseInt(gpac.getOption('Widgets', 'LastWMHeight'));
-    if (display_width && display_height) {
-        gpac.set_size(display_width, display_height);
-    }
-    root = document.documentElement;
-    homepage = document.getElementById('homepage');
-    homebar = document.getElementById('homebar');
-    execbar = document.getElementById('execbar');
-    arrows = document.getElementById('arrows');
-    arrowsW = document.getElementById('arrowsW');
-    icons = document.getElementById('icons');
-    widgetContainer = document.getElementById('widget');
-    widgetAddList = document.getElementById('widgetAddList');
-    /* Setup the GPAC Widget Manager - this will also scan the available widgets */
-    log_level = l_inf;
-    widget_manager_init();
-    WidgetManager.on_widget_remove = widget_remove;
-    WidgetManager.on_widget_add = widget_add;
-    /* register the callback to be notified of incoming widgets */
-    has_upnp = (typeof UPnP != 'undefined');
-    if (has_upnp) {
-        /* setting the callback to allow other devices to push their widgets */
-        UPnP.onMediaConnect = onMediaConnect;
-        /* Tell GPAC that the calls to the main Renderer (like open, ...) must be forwared to this scene */
-        UPnP.BindRenderer();
-    }
-    WidgetManager.coreOutShow = coreOutShowImplementation;
-    WidgetManager.coreOutGetAttention = coreOutGetAttentionImplementation;
-    WidgetManager.coreOutHide = coreOutHideImplementation;
-    WidgetManager.coreOutRequestDeactivate = coreOutRequestDeactivateImplementation;
-    WidgetManager.coreOutInstallWidget = coreOutInstallWidgetImplementation;
-    WidgetManager.coreOutActivateTemporaryWidget = coreOutActivateTemporaryWidgetImplementation;
-    WidgetManager.coreOutMigrateComponent = coreOutMigrateComponentImplementation;
-    WidgetManager.coreOutRequestMigrationTargets = coreOutRequestMigrationTargetsImplementation;
-}
+    //
+    // recompute the number of widgets loaded currently
+    //
+    function getNbWidgets() {
+        var i, nbWidgets = 0;
+        for (i = 0; i < WidgetManager.num_widgets; i++) {
+            var w = WidgetManager.get(i);
+            if (w != null && w.loaded) {
+                nbWidgets++;
+            }
+        }
+        return nbWidgets;
+    }
 
-//
-// implementation of core:out install widget
-//
-function coreOutInstallWidgetImplementation(wid, args) {
-    var w = widgetInstall(args[0], true, false);
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.installWidgetMessage, ifce.get_message("installWidget"),
-                wid, (w != null ? 1 : 0)); // send return code 1 = success
+    //
+    // just resize the window and viewport, and initialize the first time this is called
+    //
+    function resize() {
+        if (init) {
+            initialize();
+        }
+        if (document.documentElement.viewport.width == previousWidth && document.documentElement.viewport.height == previousHeight) {
+            return;
+        }
+        if (l_deb < log_level) {
+            alert("[UI] start initialize() w:" + document.documentElement.viewport.width + " h:" + document.documentElement.viewport.height);
+        }
+        adaptLayoutToSize();
+        // start by filling the "home page" with known icons
+        where = 0;
+        var nbWidgets = getNbWidgets();
+        maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
+        var wid;
+        var iconIterator = document.getElementById("icons").firstElementChild;
+        var position = 0;
+        for (i = 1; i <= WidgetManager.num_widgets; i++) {
+            wid = WidgetManager.get(i - 1);
+            // alert("build:"+wid.main+" "+wid.loaded);
+            if (wid.loaded) {
+                insert_icon(wid, position, i - 1, iconIterator);
+                WidgetManager.corein_message(wid, 'setSize', 'width', totalWidth, 'height', totalHeight - 120, 'dpi', 96);
+                position++;
+                if (iconIterator != null) {
+                    iconIterator = iconIterator.nextElementSibling;
+                }
+            }
+        }
+        adjustwhere(false);
+        adjustWhereWidgets(false);
+        previousWidth = document.documentElement.viewport.width;
+        previousHeight = document.documentElement.viewport.height;
+        gpac.setOption("Widgets", "LastWMWidth", '' + previousWidth);
+        gpac.setOption("Widgets", "LastWMHeight", '' + previousHeight);
     }
-}
 
-//
-// implementation of core:out activate temporary widget
-//
-function coreOutActivateTemporaryWidgetImplementation(wid, args) {
-    var w = widgetInstall(args[0], true, true);
-    if (w != null) activating_widget(w);
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.activateTemporaryWidgetMessage, ifce.get_message("activateTemporaryWidget"),
-                wid, (w != null ? 1 : 0)); // send return code 1 = success
+    //
+    // function inserting an icon on the home page
+    //
+    function insert_icon(widget, position, widgetIndex, previousIcon) {
+        if (l_deb < log_level) {
+            alert("[UI] insert_icon: " + widget.shortName + " " + position + " " + widgetIndex + " WMnw:" + WidgetManager.num_widgets);
+        }
+        widget.loaded = true;
+        if (l_deb < log_level) {
+            alert("[UI] widget name: " + widget.name);
+        }
+        var icon = null, original = null;
+        for (var i = 0; i < widget.icons.length; i++) {
+            // default to the first icon even if not of the preferred type
+            if (i == 0) {
+                icon = widget.icons[0].relocated_src;
+                //original = widget.icons[0].original;
+                // alert("choosing default icon " + icon);
+            }
+            // check for preferred type
+            if (widget.icons[i].relocated_src.indexOf(preferredIconType) > 0) {
+                icon = widget.icons[i].relocated_src;
+                //original = widget.icons[i].original;
+                break;
+            }
+        }
+        var shortName = widget.shortName;
+        if (typeof shortName == 'undefined') {
+            shortName = widget.name.substring(0, 9);
+        }
+        createIconSVGdecoration(previousIcon, widget, (((position % iconNbHoriz) * 80) + ((80 * (position - (position % iconsPerPage))) / iconNbVert)),
+                ((((position % iconsPerPage) - (position % iconNbHoriz)) / iconNbHoriz) * 80), "icons", icon,
+                shortName, widgetIndex);
     }
-}
 
-//
-// implementation of core:out migrate component
-//
-function coreOutMigrateComponentImplementation(wid, args) {
-    //alert("coreOutMigrateComponent "+wid.name+" "+args.length);
-    var comp = wid.get_component(args[0], true);
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (comp==null) {
-       log(l_err, 'Component '+args[0]+' cannot be found in widget '+wid.name);
-        if (ifce != null) {
-            wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 0);
-        }
-       return;
-    }
-    if (args.length > 1 && args[1] != null) {
-        WidgetManager.migrate_widget(UPnP.GetMediaRenderer(parseInt(args[1])), comp);
-        widget_close(comp);
-    } else {
-        upnp_renders = selector_window(comp);
-        upnp_renders.on_select = function(item, wid) {
-            upnp_renders.unregister(root);
-            upnp_renders = null;
-            if (item == -1) return;
-            if (comp != null) {
-                alert("upnp_renders.on_select("+item+","+comp.name+")");
-                WidgetManager.migrate_widget(UPnP.GetMediaRenderer(item), comp);
-                widget_close(comp);
+    /*function restoreFragmentOnURL(iconUrl, original) {
+        var l = original.indexOf('#');
+        if (l >= 0) {
+            return iconUrl + original.substring(l);
+        }
+        return iconUrl;
+    }*/
+
+    // constant
+    // const corein = "urn:mpeg:mpegu:schema:widgets:core:in:2010";
+
+    //
+    // commodity method to empty a list of children
+    //
+    function removeAllChildren(o) {
+        if (o != null && o.hasChildNodes()) {
+            while (o.childNodes.length >= 1) {
+                o.removeChild(o.firstChild);
             }
-        };
-        upnp_renders.register(root);
+        }
+    }
+
+    //
+    // create the home page icon with all its behaviours
+    //
+    function createIconSVGdecoration(previousIcon, widget, x, y, fatherId, iconUrl, name, widIndex) {
+        var g, g2;
+        if (l_inf < log_level) {
+            alert("[UI] createIconSVGdecoration " + iconUrl + " " + x + " " + y);
+        }
+        if (previousIcon != null) {
+            g = previousIcon;
+        } else {
+            g = document.createElement("g");
+            document.getElementById(fatherId).appendChild(g);
+        }
+        g.setAttribute("transform", 'translate(' + x + ',' + y + ')');
+        if (previousIcon != null) {
+            g2 = g.firstElementChild;
+        } else {
+            g2 = document.createElement("g");
+            g2.setAttribute("transform", 'translate(15,10)');
+            g.appendChild(g2);
+        }
+        if (iconUrl == null || iconUrl == "") {
+            iconUrl = "icons/face-surprise.svg";
+        }
+        //
+        // process differently cases where widget.icon == widget.main
+        //
+        var container;
+        if (sameFileIgnoringSVGView(iconUrl, widget.main) && widget.main.indexOf('.svg') >= 0) {
+            // see if the animation already exists
+            container = document.getElementById(name);
+            if (container == null) {
+                // if the animation does not exist yet, create it
+                container = media('animation', iconUrl, 50, 50);
+                // store the animation in the main defs
+                document.getElementById("mainDefs").appendChild(container);
+                container.setAttribute('id', name);
+            }
+            if (previousIcon == null) {
+                // put the container in a use
+                var use = document.createElement("use");
+                use.setAttribute('id', 'iconContainer' + name);
+                use.setAttributeNS(xlinkns, 'href', '#' + name);
+                g2.appendChild(use);
+            }
+        } else {
+            if (previousIcon == null) {
+                container = appropriateElementForMedia(iconUrl, 50, 50);
+                container.setAttribute('id', name);
+                g2.appendChild(container);
+            }
+        }
+        if (previousIcon == null) {
+            g2 = document.createElement("g");
+            g2.setAttribute("transform", 'translate(40,70)');
+            g.appendChild(g2);
+            var anim = createtext(name, 'white', 0, 0, 14, 'Arial Unicode MS');
+            anim.setAttribute("text-anchor", "middle");
+            anim.setAttribute("display-align", "center");
+            g2.appendChild(anim);
+            var rect = invisible_rect(80, 80);
+            g.appendChild(rect);
+            rect.addEventListener("click", csi(widget), false);
+        }
     }
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 1); // send return code 1 = success
+
+    function csi(widget) {
+        return function(evt) { activating_widget(widget);};
     }
-}
 
-//
-// implementation of core:out request migration targets
-//
-function coreOutRequestMigrationTargetsImplementation(wid, args) {
-    var count = UPnP.MediaRenderersCount, codes = new Array(), names = new Array(), descriptions = new Array(), i;
-    for (i = 0; i < count; i++) {
-        var render = UPnP.GetMediaRenderer(i);
-        codes.push(""+i);
-        names.push(render.Name);
-        descriptions.push(render.HostName +" "+ render.UUID);
-    }
-    i = null;
-    var ifce_count = wid.num_interfaces, j;
-    for (j = 0; j < ifce_count; j++) {
-        var ifce = wid.get_interface(j);
-        if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:out:2010") {
-            i = ifce;
-            break;
-        }
-    }
-    if (i != null) {
-        wmjs_core_out_invoke_reply(coreOut.requestMigrationTargetsMessage, i.get_message("requestMigrationTargets"), 
-                wid, codes, names, descriptions);
+    //
+    // widget closing action (WM callback)
+    //
+    function widget_close(wid) {
+        if (wid == null) {
+            return;
+        }
+        if (l_inf <= log_level) {
+            alert('[UI] widget_close:' + wid.name);
+        }
+        // maybe inform the widget that it is going to be deactivated
+        WidgetManager.corein_message(wid, "deactivate");
+        var target = widgetContainer.firstElementChild;
+        var i;
+        for (i = 0; i < numActivatedWidgets; i++) {
+            if (activatedWidgets[i] == wid) {
+                break;
+            }
+            target = target.nextElementSibling;
+        }
+        if (target != null) {
+            // move next widgets back one slot
+            recurseMoveAfterDelete(target);
+            // stop the subscene
+            if (target.firstElementChild != null) {
+                target.firstElementChild.setAttributeNS(xlinkns, "href", "");
+            }
+            // end trying
+            widgetContainer.removeChild(target);
+        }
+        wid.deactivate();
+        wid.activated = false;
+        activatedWidgets.splice(i, 1);
+        numActivatedWidgets--;
+        whereW = (whereW >= i ? (whereW > 0 ? whereW - 1 : 0) : whereW);
+        adjustWhereWidgets(false);
+        // if no more widgets, go back to the icons
+        if (numActivatedWidgets == 0) {
+            state = 'home';
+            widgetContainer.setAttribute('display', 'none');
+            homepage.setAttribute('display', 'inline');
+            homebar.setAttribute('display', 'inline');
+            execbar.setAttribute('display', 'none');
+            arrows.setAttribute('display', 'inline');
+            arrowsW.setAttribute('display', 'none');
+            widgetAddList.setAttribute('display', 'none');
+        }
+        if (!wid.permanent) {
+            WidgetManager.unload(wid, false);
+        }
+    }
+
+    //
+    // widget unloading action (WM callback)
+    //
+    function widget_remove(wid) {
+        if (l_deb <= log_level) {
+            alert('[UI] widget_remove:' + wid.name);
+        }
+        widget_close(wid);
+        WidgetManager.unload(wid, false);
+    }
+
+    //
+    // widget launcher action
+    //
+    function widget_launch(wid, scene_container) {
+        if (l_inf <= log_level) {
+            alert('[UI] widget_launch:' + wid.name);
+        }
+        var tmp = document.createElement("g");
+        tmp.setAttribute("transform", "translate(" + (totalWidth * numActivatedWidgets) + ", 0)");
+        widgetContainer.appendChild(tmp);
+        var icon = null;
+        alert("wid: " + wid.name + "|" + wid.shortName);
+        if (typeof wid.shortName != 'undefined') {
+            var container = document.getElementById(wid.shortName);
+            if (container != null) {
+                icon = container.getAttributeNS(xlinkns, 'href');
+            }
+        }
+        if (icon != null &&
+                sameFileIgnoringSVGView(icon, wid.main) &&
+                endsWith(wid.main, '.svg')) {
+            // get the animation with id=shortName stored in mainDefs
+            scene_container = document.getElementById(wid.shortName);
+            // get the original use on it, used in the icon
+            var iconContainer = document.getElementById('iconContainer' + wid.shortName);
+            // create a new use
+            var use = document.createElement('use');
+            // point to the animation
+            use.setAttributeNS(xlinkns, 'href', '#' + wid.shortName);
+            // resize the animation
+            scene_container.setAttribute("width", totalWidth);
+            scene_container.setAttribute("height", totalHeight - 120);
+            // resize the original use //TODO fix the aspect ratio conservation
+            var m, t = Math.abs(totalHeight - 120 - totalWidth) / 2;
+            if (totalWidth > totalHeight - 120) {
+                m = 50 / (totalHeight - 120);
+                iconContainer.setAttribute('transform', 'scale(' + m + ',' + m + ') translate(' + (-t) + ',0)');
+            } else {
+                m = 50 / totalWidth;
+                iconContainer.setAttribute('transform', 'scale(' + m + ',' + m + ') translate(0,' + (-t) + ') ');
+            }
+            // add the new use as widget execution container
+            tmp.appendChild(use);
+            wid.activate(scene_container);
+        } else {
+            scene_container.setAttribute("width", totalWidth);
+            scene_container.setAttribute("height", totalHeight - 120);
+            tmp.appendChild(scene_container);
+            scene_container.setAttributeNS(xlinkns, 'href', wid.main);
+            wid.activate(scene_container);
+        }
+        wid.activated = true;
+        activatedWidgets.splice(numActivatedWidgets, 0, wid);
+        whereW = numActivatedWidgets;
+        numActivatedWidgets++;
+        adjustWhereWidgets(false);
+        wid.load_component = widget_load_component;
+        wid.permanent = true;
+        wid.on_load = function () {
+            WidgetManager.corein_message(this, 'setSize', 'width', totalWidth, 'height', totalHeight - 120, 'dpi', 96);
+        };
+        //
+        if (log_level > l_inf) {
+            var i = 0;
+            alert(">>>>>>>>>>>>> " + wid.name + " interfaces:");
+            for (; i < wid.num_interfaces; i++) {
+                alert("" + wid.get_interface(i).type);
+            }
+        }
+        //
     }
-}
 
-//
-// implementation of core:out Show message
-// this is a request by the widget to be shown
-//
-function coreOutShowImplementation(wid, args) {
-    //alert("core:out show "+wid.name);
-    var target = widgetContainer.firstElementChild;
-    var i;
-    for (i = 0; i < numActivatedWidgets; i++) {
-        //alert("is it "+activatedWidgets[i].name);
-        if (activatedWidgets[i] == wid) break;
-        target = target.nextElementSibling;
-    }
-    // here, i is the index of the current widget
-    //alert(" "+i+" "+numActivatedWidgets);
-    if (i < numActivatedWidgets) {
-        whereW = i;
-        adjustWhereWidgets(false);
-    }
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.showMessage, ifce.get_message("show"), wid, 1); // send return code 1 = success
+    //
+    // widget load component (WM callback)
+    //
+    function widget_load_component(comp, is_unload) {
+        if (l_deb <= log_level) {
+            alert('[UI] widget_load_component:' + comp.name);
+        }
+        if (is_unload) {
+            widget_close(comp);
+            comp.parent = null;
+        } else {
+            widget_add(comp);
+            comp.permanent = false;
+            comp.parent = this;
+        }
     }
-}
 
-//
-// implementation of core:out GetAttention message
-// this is a request by the widget to be shown and some special signal is given
-//
-function coreOutGetAttentionImplementation(wid, args) {
-    //alert("core:out getAttention "+wid.name);
-    var target = widgetContainer.firstElementChild;
-    var i;
-    for (i = 0; i < numActivatedWidgets; i++) {
-        //alert("is it "+activatedWidgets[i].name);
-        if (activatedWidgets[i] == wid) break;
-        target = target.nextElementSibling;
-    }
-    // here, i is the index of the current widget
-    //alert(" "+i+" "+numActivatedWidgets);
-    if (i < numActivatedWidgets) {
-        whereW = i;
-        adjustWhereWidgets(false);
+    var upnp_renders = null, target_widgets = null;
+
+    //
+    // widget remoting function
+    //
+    function on_widget_remote() {
+        if (WidgetManager.MPEGUStandardServiceProviders.length != 0 && numActivatedWidgets > 0) {
+            upnp_renders = selector_window(activatedWidgets[whereW]);
+            upnp_renders.on_select = function(item, wid) {
+                upnp_renders.unregister(root);
+                upnp_renders = null;
+                if (item == -1) {
+                    return;
+                }
+                if (wid != null) {
+                    alert("upnp_renders.on_select(" + item + "," + wid.name + ")");
+                    //WidgetManager.migrate_widget(UPnP.GetMediaRenderer(item), wid);
+                    WidgetManager.migrate_widget(WidgetManager.get_mpegu_service_providers(item), wid);
+                    widget_close(wid);
+                }
+            };
+            upnp_renders.register(root);
+        }
     }
-    document.getElementById("getAttention").beginElement();
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.getAttentionMessage, ifce.get_message("getAttention"), wid, 1); // send return code 1 = success
+
+    //
+    // creates the menu of available targets for pushing a widget elsewhere
+    //
+    function selector_window(widget) {
+        var i, count, render;
+        var selector = document.createElement('g'), obj, child;
+        selector.setAttribute('transform', 'translate(10,10)');
+        count = WidgetManager.MPEGUStandardServiceProviders.length;
+        selector.appendChild(rect(0, 0, 300, 20 * (count + 1), 'white', 'black'));
+        for (i = 0; i < count; i++) {
+            render = WidgetManager.MPEGUStandardServiceProviders[i];
+            obj = createtext(render.Name, 'black', 5, 17 + (20 * i), 15, 'sans-serif');
+            obj.setAttribute('id', "selector" + i);
+            selector.appendChild(obj);
+            obj.addEventListener('mouseover', sw1("selector" + i), false);
+            obj.addEventListener('mouseout', sw2("selector" + i), false);
+            obj.addEventListener('click', sw3(i, widget), false);
+        }
+        obj = createtext('Cancel', 'rgb(0,0,120)', 55, 17 + (20 * i), 15, 'sans-serif');
+        obj.setAttribute('id', "cancel");
+        selector.appendChild(obj);
+        obj.addEventListener('mouseover', function(evt) { document.getElementById("cancel").setAttribute("fill", "red"); }, false);
+        obj.addEventListener('mouseout', function(evt) { document.getElementById("cancel").setAttribute("fill", "black"); }, false);
+        obj.addEventListener('click', function(evt) { upnp_renders.on_select(-1, null); }, false);
+        selector.register = function(disp) {
+            disp.appendChild(this);
+        };
+        selector.unregister = function(disp) {
+            disp.removeChild(this);
+        };
+        return selector;
     }
-}
 
-//
-// implementation of core:out hide message
-// this is a request by the widget to be hidden (some other widget (if any) is shown)
-//
-function coreOutHideImplementation(wid, args) {
-    //alert("core:out hide "+wid.name);
-    var target = widgetContainer.firstElementChild;
-    var i;
-    for (i = 0; i < numActivatedWidgets; i++) {
-        //alert("is it "+activatedWidgets[i].name);
-        if (activatedWidgets[i] == wid) break;
-        target = target.nextElementSibling;
-    }
-    // here, i is the index of the current widget
-    //alert("hide "+i+" "+numActivatedWidgets);
-    if (i < numActivatedWidgets) {
-        if (whereW > 0) whereW--;
-        else if (whereW < numActivatedWidgets - 1) whereW++;
-        else return;
-        adjustWhereWidgets(false);
+    function sw1(s) {
+        return function(evt) { document.getElementById(s).setAttribute("fill", "blue"); };
     }
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.hideMessage, ifce.get_message("hide"), wid, 1); // send return code 1 = success
+
+    function sw2(s) {
+        return function(evt) { document.getElementById(s).setAttribute("fill", "black"); };
     }
-}
 
-//
-// implementation of core:out requestDeactivate message
-// this is a request by the widget to be stopped
-//
-function coreOutRequestDeactivateImplementation(wid, args) {
-    //alert("core:out hide "+wid.name);
-    var target = widgetContainer.firstElementChild;
-    var i;
-    for (i = 0; i < numActivatedWidgets; i++) {
-        //alert("is it "+activatedWidgets[i].name);
-        if (activatedWidgets[i] == wid) break;
-        target = target.nextElementSibling;
-    }
-    // here, i is the index of the current widget
-    //alert("hide "+i+" "+numActivatedWidgets);
-    if (i < numActivatedWidgets) {
-        widget_close(activatedWidgets[i]);
-    }
-    var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
-    if (ifce != null) {
-        wmjs_core_out_invoke_reply(coreOut.requestDeactivateMessage, ifce.get_message("requestDeactivate"), wid, 1); // send return code 1 = success
+    function sw3(si, widget) {
+        return function(evt) { upnp_renders.on_select(si, widget); };
     }
-}
 
-//
-// WM callback for when a component is activated by its parent
-//
-function widget_add(w) {
-    if (!w.activated) {
-/*
-        if (testCyrilsExtension) {
-            var anima = document.createElement("animation");
-            anima.setAttributeNS('http://gpac.sourceforge.net/svg-extensions', 'use-as-primary', 'false');
-            widget_launch(w, anima);
-        } else {
-*/
-            if (sameFileIgnoringSVGView(w.icon, w.main)) {
-                // same file in icon and main
-            } else {
-                widget_launch(w, document.createElement("animation"));
+    //
+    // when a widget is pushed to here, install the widget and execute it
+    //
+    function onMediaConnect(url, src_ip) {
+        if (l_inf <= log_level) {
+            alert('[UI] onMediaConnect :\"' + url + '\"');
+        }
+        if (WidgetManager.probe(url)) {
+            var w = WidgetManager.open(url, src_ip);
+            if (w == null) {
+                return;
             }
-//        }
-        return true;
-    } else if (w.multipleInstances) {
-        var newwid = WidgetManager.open(w.manifest, null);
-        widget_launch(newwid, document.createElement("animation"));
-        return true;
+            widget_add(w);
+            adjustWhereWidgets(false);
+            w.permanent = false;
+        }
     }
-    return false;
-}
 
-function sameFileIgnoringSVGView(name1, name2) {
-    if (name1 == name2) return true;
-    if (name1 == null) return false;
-    var i1 = name1.indexOf("#");
-    var i2 = name2.indexOf("#");
-    if (i1 < 0) i1 = name1.length;
-    else i1--;
-    if (i2 < 0) i2 = name2.length;
-    else i2--;
-    return name1.substring(0, i1) == name2.substring(0, i2);
-}
+    //
+    // file list vars
+    //
+    var flstart = 0,fllist = null,maxFileNames = 14;
 
-//
-// recompute the number of widgets loaded currently
-//
-function getNbWidgets() {
-    var i, nbWidgets = 0;
-    for (i = 0; i < WidgetManager.num_widgets; i++) {
-        var w = WidgetManager.get(i);
-        if (w != null && w.loaded) nbWidgets++;
+    //
+    // create a file menu in the main screen, allowing to navigate directories and choose widget config files
+    //
+    function on_widget_add_menu() {
+        state = 'list';
+        widgetContainer.setAttribute('display', 'none');
+        homepage.setAttribute('display', 'none');
+        homebar.setAttribute('display', 'none');
+        execbar.setAttribute('display', 'inline');
+        arrows.setAttribute('display', 'none');
+        arrowsW.setAttribute('display', 'none');
+        widgetAddList.setAttribute('display', 'inline');
+        maxFileNames = Math.round(((iconNbVert * 80) / 25) - 1.4);
+        isThisAScan = false;
+        refillWidgetAddList(false);
     }
-    return nbWidgets;
-}
-
-//
-// just resize the window and viewport, and initialize the first time this is called
-//
-function resize() {
-    if (init) initialize();
-    if (document.documentElement.viewport.width == previousWidth && document.documentElement.viewport.height == previousHeight) return;
-    if (l_deb < log_level) alert("[UI] start initialize() w:" + document.documentElement.viewport.width + " h:" + document.documentElement.viewport.height);
-    adaptLayoutToSize();
-    // start by filling the "home page" with known icons
-    where = 0;
-    var nbWidgets = getNbWidgets();
-    maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
-    var wid;
-    var iconIterator = document.getElementById("icons").firstElementChild;
-    var position = 0;
-    for (i = 1; i <= WidgetManager.num_widgets; i++) {
-        wid = WidgetManager.get(i - 1);
-        // alert("build:"+wid.main+" "+wid.loaded);
-        if (wid.loaded) {
-            insert_icon(wid, position, i - 1, iconIterator);
-            WidgetManager.corein_message(wid, 'setSize', 'width', totalWidth, 'height', totalHeight-120, 'dpi', 96);
-            position++;
-            if (iconIterator != null) iconIterator = iconIterator.nextElementSibling;
-        }
-    }
-    adjustwhere(false);
-    adjustWhereWidgets(false);
-    previousWidth = document.documentElement.viewport.width;
-    previousHeight = document.documentElement.viewport.height;
-    gpac.setOption("Widgets", "LastWMWidth", '' + previousWidth);
-    gpac.setOption("Widgets", "LastWMHeight", '' + previousHeight);
-}
-
-//
-// function inserting an icon on the home page
-//
-function insert_icon(widget, position, widgetIndex, previousIcon) {
-    if (l_deb < log_level) alert("[UI] insert_icon: " + widget.shortName + " " + position + " " + widgetIndex + " WMnw:" + WidgetManager.num_widgets);
-    widget.loaded = true;
-    if (l_deb < log_level) alert("[UI] widget name: " + widget.name);
-    var icon = null, original = null;
-    for (var i = 0; i < widget.icons.length; i++) {
-        // default to the first icon even if not of the preferred type
-        if (i == 0) {
-            icon = widget.icons[0].relocated_src;
-            //original = widget.icons[0].original;
-            // alert("choosing default icon " + icon);
-        }
-        // check for preferred type
-        if (widget.icons[i].relocated_src.indexOf(preferredIconType) > 0) {
-            icon = widget.icons[i].relocated_src;
-            //original = widget.icons[i].original;
-            break;
-        }
-    }
-    //alert("");
-    //alert("content of widget:");
-    //alert("main " + widget.main);
-    //alert("icon " + icon);
-    //alert("original " + original);
-    //alert("");
-    //icon = restoreFragmentOnURL(icon, original);
-    var shortName = widget.shortName;
-    if (typeof shortName == 'undefined') shortName = widget.name.substring(0, 9);
-    createIconSVGdecoration(previousIcon, widget, (((position % iconNbHoriz) * 80) + ((80 * (position - (position % iconsPerPage))) / iconNbVert)),
-            ((((position % iconsPerPage) - (position % iconNbHoriz)) / iconNbHoriz) * 80), "icons", icon,
-            shortName, widgetIndex);
-}
 
-function restoreFragmentOnURL(iconUrl, original) {
-    var l = original.indexOf('#');
-    if (l >= 0) {
-        return iconUrl + original.substring(l);
+    //
+    // create a file menu in the main screen, allowing to navigate directories and choose a directory to scan for widgets
+    // and load all their icons
+    //
+    function on_dir_scan() {
+        state = 'list';
+        widgetContainer.setAttribute('display', 'none');
+        homepage.setAttribute('display', 'none');
+        homebar.setAttribute('display', 'none');
+        execbar.setAttribute('display', 'inline');
+        arrows.setAttribute('display', 'none');
+        arrowsW.setAttribute('display', 'none');
+        widgetAddList.setAttribute('display', 'inline');
+        maxFileNames = Math.round(((iconNbVert * 80) / 25) - 1.4);
+        isThisAScan = true;
+        refillWidgetAddList(true);
     }
-    return iconUrl;
-}
-
-// constant
-const corein = "urn:mpeg:mpegu:schema:widgets:core:in:2010";
 
-//
-// commodity method to empty a list of children
-//
-function removeAllChildren(o) {
-    if (o != null && o.hasChildNodes()) {
-        while (o.childNodes.length >= 1) {
-            o.removeChild(o.firstChild);
+    //
+    // remove all installed icons
+    //
+    function on_clean_up() {
+        var i;
+        //if (l_inf <= log_level) alert('[UI] unloading ' + WidgetManager.num_widgets + ' widgets');
+        for (i = WidgetManager.num_widgets - 1; i >= 0; i--) {
+            var w = WidgetManager.get(i);
+            if (w.loaded) {
+                alert("unloading " + w.name);
+                w.loaded = false;
+                WidgetManager.unload(w, false);
+            }
         }
+        where = 0;
+        maxwhere = 0;
+        removeAllChildren(document.getElementById("icons"));
+        adjustwhere(false);
     }
-}
 
-//
-// create the home page icon with all its behaviours
-//
-function createIconSVGdecoration(previousIcon, widget, x, y, fatherId, iconUrl, name, widIndex) {
-    var g, g2;
-    if (l_inf < log_level) alert("[UI] createIconSVGdecoration " + iconUrl + " " + x + " " + y);
-    if (previousIcon != null) {
-        g = previousIcon;
-    } else {
-        g = document.createElement("g");
-        document.getElementById(fatherId).appendChild(g);
-    }
-    g.setAttribute("transform", 'translate(' + x + ',' + y + ')');
-    if (previousIcon != null) {
-        g2 = g.firstElementChild;
-    } else {
-        g2 = document.createElement("g");
-        g2.setAttribute("transform", 'translate(15,10)');
-        g.appendChild(g2);
-    }
-    if (iconUrl == null || iconUrl == "") iconUrl = "icons/face-surprise.svg";
-    //
-    // process differently cases where widget.icon == widget.main
-    //
-    var container;
-    if (sameFileIgnoringSVGView(iconUrl, widget.main) && widget.main.indexOf('.svg') >= 0) {
-        // see if the animation already exists
-        container = document.getElementById(name);
-        if (container == null) {
-            // if the animation does not exist yet, create it
-            container = media('animation', iconUrl, 50, 50);
-            // store the animation in the main defs
-            document.getElementById("mainDefs").appendChild(container);
-            container.setAttribute('id', name);
+    //
+    // install, but do not launch, the widget whose config.xml has been chosen, and return to the home page
+    //
+    function widgetInstall(uri, manual, temporary, parent_wid) {
+        var wid, j, count = WidgetManager.num_widgets, nbWidgets = getNbWidgets();
+        for (j = 0; j < count; j++) {
+            wid = WidgetManager.get(j);
+            if (wid.url == uri) {
+                if (wid.loaded) {
+                    break;
+                }
+                if (temporary) {
+                    wid.permanent = false;
+                }
+                else {
+                    insert_icon(wid, nbWidgets, nbWidgets);
+                }
+            }
         }
-        if (previousIcon == null) {
-            // put the container in a use
-            var use = document.createElement("use");
-            use.setAttribute('id', 'iconContainer' + name);
-            use.setAttributeNS(xlinkns, 'href', '#' + name);
-            g2.appendChild(use);
+        if (j == count) {
+            wid = WidgetManager.open(uri, null, parent_wid);
+            if (wid != null) {
+                if (temporary) {
+                    wid.permanent = false;
+                }
+                else {
+                    insert_icon(wid, nbWidgets, nbWidgets);
+                }
+            }
+        }
+        if (manual) {
+            return wid;
         }
-    } else {
-        if (previousIcon == null) {
-            container = appropriateElementForMedia(iconUrl, 50, 50);
-            container.setAttribute('id', name);
-            g2.appendChild(container);
-        }
-    }
-    if (previousIcon == null) {
-        g2 = document.createElement("g");
-        g2.setAttribute("transform", 'translate(40,70)');
-        g.appendChild(g2);
-        var anim = createtext(name, 'white', 0, 0, 14, 'Arial Unicode MS');
-        anim.setAttribute("text-anchor", "middle");
-        anim.setAttribute("display-align", "center");
-        g2.appendChild(anim);
-        var rect = invisible_rect(80, 80);
-        g.appendChild(rect);
-        rect.addEventListener("click", csi(widget), false);
-    }
-}
-
-function csi(widget) {
-    return function(evt) { activating_widget(widget);};
-}
-
-//
-// widget closing action (WM callback)
-//
-function widget_close(wid) {
-    if (wid == null) return;
-    if (l_inf <= log_level) alert('[UI] widget_close:' + wid.name);
-    // maybe inform the widget that it is going to be deactivated
-    WidgetManager.corein_message(wid, "deactivate");
-    var target = widgetContainer.firstElementChild;
-    var i;
-    for (i = 0; i < numActivatedWidgets; i++) {
-        if (activatedWidgets[i] == wid) break;
-        target = target.nextElementSibling;
-    }
-    if (target != null) {
-        // move next widgets back one slot
-        recurseMoveAfterDelete(target);
-        // stop the subscene
-        if (target.firstElementChild != null) target.firstElementChild.setAttributeNS(xlinkns, "href", "");
-        // end trying
-        widgetContainer.removeChild(target);
-    }
-    wid.deactivate();
-    wid.activated = false;
-    activatedWidgets.splice(i, 1);
-    numActivatedWidgets--;
-    whereW = (whereW >= i ? (whereW > 0 ? whereW - 1 : 0) : whereW);
-    adjustWhereWidgets(false);
-    // if no more widgets, go back to the icons
-    if (numActivatedWidgets == 0) {
         state = 'home';
         widgetContainer.setAttribute('display', 'none');
         homepage.setAttribute('display', 'inline');
@@ -791,569 +1286,351 @@ function widget_close(wid) {
         execbar.setAttribute('display', 'none');
         arrows.setAttribute('display', 'inline');
         arrowsW.setAttribute('display', 'none');
-        widgetAddList.setAttribute('display', 'none');
+        removeAllChildren(widgetAddList);
+        maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
+        where = maxwhere;
+        adjustwhere(false);
+        return wid;
     }
-    if (!wid.permanent) WidgetManager.unload(wid, false);
-}
 
-//
-// widget unloading action (WM callback)
-//
-function widget_remove(wid) {
-    if (l_deb <= log_level) alert('[UI] widget_remove:' + wid.name);
-    widget_close(wid);
-    WidgetManager.unload(wid, false);
-}
-
-//
-// widget launcher action
-//
-function widget_launch(wid, scene_container) {
-    if (l_inf <= log_level) alert('[UI] widget_launch:' + wid.name);
-    var tmp = document.createElement("g");
-    tmp.setAttribute("transform", "translate(" + (totalWidth * numActivatedWidgets) + ", 0)");
-    widgetContainer.appendChild(tmp);
-    var icon = null;
-    alert("wid: "+wid.name+"|"+wid.shortName);
-    if (typeof wid.shortName != 'undefined') {
-        var container = document.getElementById(wid.shortName);
-        if (container != null) icon = container.getAttributeNS(xlinkns, 'href');
-    }
-    if (icon != null &&
-            sameFileIgnoringSVGView(icon, wid.main) &&
-            endsWith(wid.main, '.svg')) {
-        // get the animation with id=shortName stored in mainDefs
-        scene_container = document.getElementById(wid.shortName);
-        // get the original use on it, used in the icon
-        var iconContainer = document.getElementById('iconContainer' + wid.shortName);
-        // create a new use
-        var use = document.createElement('use');
-        // point to the animation
-        use.setAttributeNS(xlinkns, 'href', '#' + wid.shortName);
-        // resize the animation
-        scene_container.setAttribute("width", totalWidth);
-        scene_container.setAttribute("height", totalHeight - 120);
-        // resize the original use //TODO fix the aspect ratio conservation
-        var m, t = Math.abs(totalHeight - 120 - totalWidth) / 2;
-        if (totalWidth > totalHeight - 120) {
-            m = 50 / (totalHeight - 120);
-            iconContainer.setAttribute('transform', 'scale(' + m + ',' + m + ') translate(' + (-t) + ',0)');
-        } else {
-            m = 50 / totalWidth;
-            iconContainer.setAttribute('transform', 'scale(' + m + ',' + m + ') translate(0,' + (-t) + ') ');
-        }
-        // add the new use as widget execution container
-        tmp.appendChild(use);
-        wid.activate(scene_container);
-    } else {
-        scene_container.setAttribute("width", totalWidth);
-        scene_container.setAttribute("height", totalHeight - 120);
-        tmp.appendChild(scene_container);
-        scene_container.setAttributeNS(xlinkns, 'href', wid.main);
-        wid.activate(scene_container);
-    }
-    wid.activated = true;
-    activatedWidgets.splice(numActivatedWidgets, 0, wid);
-    whereW = numActivatedWidgets;
-    numActivatedWidgets++;
-    adjustWhereWidgets(false);
-    wid.load_component = widget_load_component;
-    wid.permanent = true;
-    wid.on_load = function () {
-        WidgetManager.corein_message(this, 'setSize', 'width', totalWidth, 'height', totalHeight-120, 'dpi', 96);
-    };
-    //
-    if (log_level > l_inf) {
-        var i = 0;
-        alert(">>>>>>>>>>>>> "+wid.name+" interfaces:");
-        for (;i < wid.num_interfaces; i++) {
-            alert(""+wid.get_interface(i).type);
-        }
-    }
     //
-}
-
-//
-// widget load component (WM callback)
-//
-function widget_load_component(comp, is_unload) {
-    if (l_deb <= log_level) alert('[UI] widget_load_component:' + comp.name);
-    if (is_unload) {
-        widget_close(comp);
-        comp.parent = null;
-    } else {
-        widget_add(comp);
-        comp.permanent = false;
-        comp.parent = this;
-    }
-}
-
-upnp_renders = null;
-
-//
-// widget remoting function
-//
-function on_widget_remote() {
-    if (UPnP.MediaRenderersCount && numActivatedWidgets > 0) {
-        upnp_renders = selector_window(activatedWidgets[whereW]);
-        upnp_renders.on_select = function(item, wid) {
-            upnp_renders.unregister(root);
-            upnp_renders = null;
-            if (item == -1) return;
-            if (wid != null) {
-                alert("upnp_renders.on_select("+item+","+wid.name+")");
-                WidgetManager.migrate_widget(UPnP.GetMediaRenderer(item), wid);
-                widget_close(wid);
-            }
-        };
-        upnp_renders.register(root);
-    }
-}
-
-//
-// creates the menu of available targets for pushing a widget elsewhere
-//
-function selector_window(widget) {
-    var i, count, render;
-    var selector = document.createElement('g'), obj, child;
-    selector.setAttribute('transform', 'translate(10,10)');
-    count = UPnP.MediaRenderersCount;
-    selector.appendChild(rect(0, 0, 300, 20 * (count + 1), 'white', 'black'));
-    for (i = 0; i < count; i++) {
-        render = UPnP.GetMediaRenderer(i);
-        obj = createtext(render.Name, 'black', 5, 17 + (20 * i), 15, 'sans-serif');
-        obj.setAttribute('id', "selector" + i);
-        selector.appendChild(obj);
-        obj.addEventListener('mouseover', sw1("selector"+i), false);
-        obj.addEventListener('mouseout', sw2("selector"+i), false);
-        obj.addEventListener('click', sw3(i, widget), false);
-    }
-    obj = createtext('Cancel', 'rgb(0,0,120)', 55, 17 + (20 * i), 15, 'sans-serif');
-    obj.setAttribute('id', "cancel");
-    selector.appendChild(obj);
-    obj.addEventListener('mouseover', function(evt) { document.getElementById("cancel").setAttribute("fill", "red"); }, false);
-    obj.addEventListener('mouseout', function(evt) { document.getElementById("cancel").setAttribute("fill", "black"); }, false);
-    obj.addEventListener('click', function(evt) { upnp_renders.on_select(-1, null); }, false);
-    selector.register = function(disp) {
-        disp.appendChild(this);
-    };
-    selector.unregister = function(disp) {
-        disp.removeChild(this);
-    };
-    return selector;
-}
-
-function sw1(s) {
-    return function(evt) { document.getElementById(s).setAttribute("fill", "blue"); };
-}
-
-function sw2(s) {
-    return function(evt) { document.getElementById(s).setAttribute("fill", "black"); };
-}
-
-function sw3(si, widget) {
-    return function(evt) { upnp_renders.on_select(si, widget); };
-}
-
-//
-// when a widget is pushed to here, install the widget and execute it
-//
-function onMediaConnect(url, src_ip) {
-    if (l_inf <= log_level) alert('[UI] onMediaConnect :\"' + url + '\"');
-    if (WidgetManager.probe(url)) {
-        var w = WidgetManager.open(url, src_ip);
-        if (w == null) return;
-        state = 'exec';
-        widgetContainer.setAttribute('display', 'inline');
-        homepage.setAttribute('display', 'none');
-        homebar.setAttribute('display', 'none');
-        execbar.setAttribute('display', 'inline');
-        arrows.setAttribute('display', 'none');
-        arrowsW.setAttribute('display', 'inline');
-        widgetAddList.setAttribute('display', 'none');
-        var nbWidgets = getNbWidgets();
-        widget_add(w);
-        adjustWhereWidgets(false);
-        w.permanent = false;
+    // clean up file list space and refill it
+    //
+    function refillWidgetAddList(flag) {
+        removeAllChildren(widgetAddList);
+        fllist = null;
+        flstart = 0;
+        fllist = gpac.enum_directory(gpac.last_working_directory, "", false);
+        fillWidgetAddList(flag);
     }
-}
-
-//
-// file list vars
-//
-flstart = 0, fllist = null, maxFileNames = 14;
-
-//
-// create a file menu in the main screen, allowing to navigate directories and choose widget config files
-//
-function on_widget_add_menu() {
-    state = 'list';
-    widgetContainer.setAttribute('display', 'none');
-    homepage.setAttribute('display', 'none');
-    homebar.setAttribute('display', 'none');
-    execbar.setAttribute('display', 'inline');
-    arrows.setAttribute('display', 'none');
-    arrowsW.setAttribute('display', 'none');
-    widgetAddList.setAttribute('display', 'inline');
-    maxFileNames = Math.round(((iconNbVert * 80) / 25) - 1.4);
-    isThisAScan = false;
-    refillWidgetAddList(false);
-}
-
-//
-// create a file menu in the main screen, allowing to navigate directories and choose a directory to scan for widgets
-// and load all their icons
-//
-function on_dir_scan() {
-    state = 'list';
-    widgetContainer.setAttribute('display', 'none');
-    homepage.setAttribute('display', 'none');
-    homebar.setAttribute('display', 'none');
-    execbar.setAttribute('display', 'inline');
-    arrows.setAttribute('display', 'none');
-    arrowsW.setAttribute('display', 'none');
-    widgetAddList.setAttribute('display', 'inline');
-    maxFileNames = Math.round(((iconNbVert * 80) / 25) - 1.4);
-    isThisAScan = true;
-    refillWidgetAddList(true);
-}
-
-//
-// remove all installed icons
-//
-function on_clean_up() {
-    var i;
-    //if (l_inf <= log_level) alert('[UI] unloading ' + WidgetManager.num_widgets + ' widgets');
-    for (i = WidgetManager.num_widgets - 1; i >= 0; i--) {
-        var w = WidgetManager.get(i);
-        if (w.loaded) {
-            alert("unloading " + w.name);
-            w.loaded = false;
-            WidgetManager.unload(w, false);
-        }
-    }
-    where = 0;
-    maxwhere = 0;
-    removeAllChildren(document.getElementById("icons"));
-    adjustwhere(false);
-}
-
-//
-// install, but do not launch, the widget whose config.xml has been chosen, and return to the home page
-//
-function widgetInstall(uri, manual, temporary) {
-    var wid, j, count = WidgetManager.num_widgets, nbWidgets = getNbWidgets();
-    for (j = 0; j < count; j++) {
-        wid = WidgetManager.get(j);
-        if (wid.url == uri) {
-            if (wid.loaded) break;
-            if (temporary) wid.permanent = false;
-            else insert_icon(wid, nbWidgets, nbWidgets);
-        }
-    }
-    if (j == count) {
-        wid = WidgetManager.open(uri, null);
-        if (wid != null) {
-            if (temporary) wid.permanent = false;
-            else insert_icon(wid, nbWidgets, nbWidgets);
-        }
-    }
-    if (manual) return wid;
-    state = 'home';
-    widgetContainer.setAttribute('display', 'none');
-    homepage.setAttribute('display', 'inline');
-    homebar.setAttribute('display', 'inline');
-    execbar.setAttribute('display', 'none');
-    arrows.setAttribute('display', 'inline');
-    arrowsW.setAttribute('display', 'none');
-    removeAllChildren(widgetAddList);
-    maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
-    where = maxwhere;
-    adjustwhere(false);
-    return wid;
-}
-
-//
-// clean up file list space and refill it
-//
-function refillWidgetAddList(flag) {
-    removeAllChildren(widgetAddList);
-    fllist = null;
-    flstart = 0;
-    fllist = gpac.enum_directory(gpac.last_working_directory, "", false);
-    fillWidgetAddList(flag);
-}
 
-//
-// go to parent directory
-//
-function flUpDir(evt) {
-    var s = gpac.last_working_directory;
-    if (l_inf <= log_level) alert("[UI] lwd:" + gpac.last_working_directory);
-    var index = s.lastIndexOf("\\");
-    if (index != -1) {
-        gpac.last_working_directory = s.substring(0, index);
-        refillWidgetAddList(isThisAScan);
-    } else {
-        index = s.lastIndexOf("/");
+    //
+    // go to parent directory
+    //
+    function flUpDir(evt) {
+        var s = gpac.last_working_directory;
+        if (l_inf <= log_level) {
+            alert("[UI] lwd:" + gpac.last_working_directory);
+        }
+        var index = s.lastIndexOf("\\");
         if (index != -1) {
             gpac.last_working_directory = s.substring(0, index);
             refillWidgetAddList(isThisAScan);
         } else {
-            gpac.last_working_directory = "/";
-            refillWidgetAddList(isThisAScan);
+            index = s.lastIndexOf("/");
+            if (index != -1) {
+                gpac.last_working_directory = s.substring(0, index);
+                refillWidgetAddList(isThisAScan);
+            } else {
+                gpac.last_working_directory = "/";
+                refillWidgetAddList(isThisAScan);
+            }
         }
     }
-}
-
-//
-// go to a named directory
-//
-function flGoTo(newDir) {
-    //alert("goto "+newDir);
-    var s = gpac.last_working_directory;
-    if (s == "/") {
-        gpac.last_working_directory = newDir;
-    } else {
-        var c = s.charAt(s.length - 1);
-        if (c != '\\' && c != '/') s += "/";
-        gpac.last_working_directory = s + newDir;
-    }
-    //alert(gpac.last_working_directory);
-    refillWidgetAddList(isThisAScan);
-}
 
-//
-// if the directory contains more files that can be shown, show previous page of file names
-//
-function flPrevFiles(evt) {
-    if (flstart == 0) return;
-    flstart -= maxFileNames;
-    if (flstart < 0) flstart = 0;
-    removeAllChildren(widgetAddList);
-    fillWidgetAddList(isThisAScan);
-}
+    //
+    // go to a named directory
+    //
+    function flGoTo(newDir) {
+        //alert("goto "+newDir);
+        var s = gpac.last_working_directory;
+        if (s == "/") {
+            gpac.last_working_directory = newDir;
+        } else {
+            var c = s.charAt(s.length - 1);
+            if (c != '\\' && c != '/') {
+                s += "/";
+            }
+            gpac.last_working_directory = s + newDir;
+        }
+        //alert(gpac.last_working_directory);
+        refillWidgetAddList(isThisAScan);
+    }
 
-//
-// if the directory contains more files that can be shown, show next page of file names
-//
-function flNextFiles(evt) {
-    if (flstart + maxFileNames < fllist.length) {
-        flstart += maxFileNames;
+    //
+    // if the directory contains more files that can be shown, show previous page of file names
+    //
+    function flPrevFiles(evt) {
+        if (flstart == 0) {
+            return;
+        }
+        flstart -= maxFileNames;
+        if (flstart < 0) {
+            flstart = 0;
+        }
         removeAllChildren(widgetAddList);
         fillWidgetAddList(isThisAScan);
     }
-}
 
-//
-// scan the current directory recursively for widgets, clean up and return to home page
-//
-function flScanDir(evt) {
-    scan_directory(gpac.last_working_directory);
-    state = 'home';
-    var nbWidgets = getNbWidgets();
-    widgetContainer.setAttribute('display', 'none');
-    homepage.setAttribute('display', 'inline');
-    homebar.setAttribute('display', 'inline');
-    execbar.setAttribute('display', 'none');
-    arrows.setAttribute('display', 'inline');
-    arrowsW.setAttribute('display', 'none');
-    removeAllChildren(widgetAddList);
-    maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
-    where = maxwhere;
-    adjustwhere(false);
-}
+    //
+    // if the directory contains more files that can be shown, show next page of file names
+    //
+    function flNextFiles(evt) {
+        if (flstart + maxFileNames < fllist.length) {
+            flstart += maxFileNames;
+            removeAllChildren(widgetAddList);
+            fillWidgetAddList(isThisAScan);
+        }
+    }
 
-//
-// scanning
-//
-function scan_directory(dir) {
-    var ii, j, count, list, w, uri, loadedWidgets = 0;
-    list = gpac.enum_directory(dir, '.xml;.wgt', 0);
-    for (ii = 0; ii < list.length; ii++) {
-        uri = list[ii].path + list[ii].name;
-        if (list[ii].directory) {
-            scan_directory(uri);
-        } else {
-            count = WidgetManager.num_widgets;
-            for (j = 0; j < count; j++) {
-                var wid = WidgetManager.get(j);
-                if (wid.loaded) loadedWidgets++;
-                if (wid.url == uri) {
-                    if (wid.loaded) break;
-                    insert_icon(wid, getNbWidgets(), j);
-                    break;
+    //
+    // scan the current directory recursively for widgets, clean up and return to home page
+    //
+    function flScanDir(evt) {
+        scan_directory(gpac.last_working_directory);
+        state = 'home';
+        var nbWidgets = getNbWidgets();
+        widgetContainer.setAttribute('display', 'none');
+        homepage.setAttribute('display', 'inline');
+        homebar.setAttribute('display', 'inline');
+        execbar.setAttribute('display', 'none');
+        arrows.setAttribute('display', 'inline');
+        arrowsW.setAttribute('display', 'none');
+        removeAllChildren(widgetAddList);
+        maxwhere = ((nbWidgets - 1) - ((nbWidgets - 1) % iconsPerPage)) / iconsPerPage;
+        where = maxwhere;
+        adjustwhere(false);
+    }
+
+    //
+    // scanning
+    //
+    function scan_directory(dir) {
+        var ii, j, count, list, w, uri, loadedWidgets = 0;
+        list = gpac.enum_directory(dir, '.xml;.wgt', 0);
+        for (ii = 0; ii < list.length; ii++) {
+            uri = list[ii].path + list[ii].name;
+            if (list[ii].directory) {
+                scan_directory(uri);
+            } else {
+                count = WidgetManager.num_widgets;
+                for (j = 0; j < count; j++) {
+                    var wid = WidgetManager.get(j);
+                    if (wid.loaded) {
+                        loadedWidgets++;
+                    }
+                    if (wid.url == uri) {
+                        if (wid.loaded) {
+                            break;
+                        }
+                        insert_icon(wid, getNbWidgets(), j);
+                        break;
+                    }
                 }
-            }
-            if (j == count) {
-                w = WidgetManager.open(uri, null);
-                if (w != null) {
-                    insert_icon(w, loadedWidgets, WidgetManager.num_widgets - 1);
+                if (j == count) {
+                    w = WidgetManager.open(uri, null);
+                    if (w != null) {
+                        insert_icon(w, loadedWidgets, WidgetManager.num_widgets - 1);
+                    }
                 }
             }
         }
     }
-}
 
-//
-// create the up, prev, next button, show current directory and as many file names as possible
-// the file names are active: clicking on a directory name goes to that directory
-// clicking on a file tries to load that file as a widget
-//
-function fillWidgetAddList(flag) {
-    if (flag) {
-        widgetAddList.appendChild(use("cartoucheflag"));
-        document.getElementById("dirflag").textContent = gpac.last_working_directory;
-    } else {
-        widgetAddList.appendChild(use("cartouche"));
-        document.getElementById("dir").textContent = gpac.last_working_directory;
-    }
-    // next lines are file names
-    var obj;
-    for (i = 0; i < (fllist.length - flstart) && i < maxFileNames; i++) {
-        obj = use("fileMenuElement" + i);
-        obj.setAttribute('transform', 'translate(0,' + (25 * (i + 1)) + ')');
-        widgetAddList.appendChild(obj);
-        document.getElementById("fileMenuElement" + i + "u").setAttributeNS(xlinkns, 'href', "#" + (fllist[i + flstart].directory ? 'folder' : 'new'));
-        document.getElementById("fileMenuElement" + i + "t").textContent = fllist[i + flstart].name;
-        if (obj.listener != null) obj.removeEventListener("click", obj.listener);
-        if (fllist[i + flstart].directory) {
-            obj.listener = createGoto(escaping(fllist[i + flstart].name));
-            obj.addEventListener("click", obj.listener, false);
-        } else if (isWidgetFileName(fllist[i + flstart].name)) {
-            obj.listener = createWidgetInstall(escaping(gpac.last_working_directory + '/' + fllist[i + flstart].name));
-            obj.addEventListener("click", obj.listener, false);
+    //
+    // create the up, prev, next button, show current directory and as many file names as possible
+    // the file names are active: clicking on a directory name goes to that directory
+    // clicking on a file tries to load that file as a widget
+    //
+    function fillWidgetAddList(flag) {
+        if (flag) {
+            widgetAddList.appendChild(use("cartoucheflag"));
+            document.getElementById("dirflag").textContent = gpac.last_working_directory;
+        } else {
+            widgetAddList.appendChild(use("cartouche"));
+            document.getElementById("dir").textContent = gpac.last_working_directory;
+        }
+        // next lines are file names
+        var obj;
+        for (i = 0; i < (fllist.length - flstart) && i < maxFileNames; i++) {
+            obj = use("fileMenuElement" + i);
+            obj.setAttribute('transform', 'translate(0,' + (25 * (i + 1)) + ')');
+            widgetAddList.appendChild(obj);
+            document.getElementById("fileMenuElement" + i + "u").setAttributeNS(xlinkns, 'href', "#" + (fllist[i + flstart].directory ? 'folder' : 'new'));
+            document.getElementById("fileMenuElement" + i + "t").textContent = fllist[i + flstart].name;
+            if (obj.listener != null) {
+                obj.removeEventListener("click", obj.listener);
+            }
+            if (fllist[i + flstart].directory) {
+                obj.listener = createGoto(escaping(fllist[i + flstart].name));
+                obj.addEventListener("click", obj.listener, false);
+            } else if (isWidgetFileName(fllist[i + flstart].name)) {
+                obj.listener = createWidgetInstall(escaping(gpac.last_working_directory + '/' + fllist[i + flstart].name));
+                obj.addEventListener("click", obj.listener, false);
+            }
         }
     }
-}
-
-function createGoto(s) {
-    return function () {
-        flGoTo(s);
-    };
-}
-
-function createWidgetInstall(s) {
-    return function () {
-        widgetInstall(s, false, false);
-    };
-}
 
-// // // // // // // // // // // // // // //
-// function library
-// // // // // // // // // // // // // // //
-
-function isWidgetFileName(s) {
-    if (endsWith(s, 'config.xml')) return true;
-    if (endsWith(s, '.wgt')) return true;
-    return false;
-}
-
-//
-// replace globally \ with / in a string
-//
-function escaping(s) {
-    s = s.replace(/\\/g, '/');
-    return s;
-}
-
-//
-// create rect
-//
-function rect(x, y, w, h, fill, stroke, id) {
-    var child = document.createElement('rect');
-    if (id != null) {
-        child.setAttribute('id', id);
-    }
-    child.setAttribute('x', x);
-    child.setAttribute('y', y);
-    child.setAttribute('width', w);
-    child.setAttribute('height', h);
-    child.setAttribute('fill', fill);
-    child.setAttribute('stroke', stroke);
-    return child;
-}
+    function createGoto(s) {
+        return function () {
+            flGoTo(s);
+        };
+    }
 
-//
-// create text
-//
-function createtext(content, fill, x, y, size, family) {
-    var child = document.createElement('text');
-    child.setAttribute('fill', fill);
-    child.textContent = content;
-    child.setAttribute('x', x);
-    child.setAttribute('y', y);
-    child.setAttribute('font-size', size);
-    child.setAttribute('font-family', family);
-    return child;
-}
+    function createWidgetInstall(s) {
+        return function () {
+            widgetInstall(s, false, false, null);
+        };
+    }
 
-//
-// create invisible rect getting all events
-//
-function invisible_rect(w, h) {
-    var child = document.createElement('rect');
-    child.setAttribute('width', w);
-    child.setAttribute('height', h);
-    child.setAttribute('fill', 'none');
-    child.setAttribute('stroke', 'none');
-    child.setAttribute('pointer-events', 'all');
-    return child;
-}
+    // // // // // // // // // // // // // // //
+    // function library
+    // // // // // // // // // // // // // // //
 
-//
-// create animation
-//
-function media(etype, uri, w, h) {
-    var child = document.createElement(etype);
-    child.setAttributeNS(xlinkns, 'href', uri);
-    child.setAttribute('width', w);
-    child.setAttribute('height', h);
-    if (etype == 'animation') {
-        child.setAttributeNS('http://gpac.sourceforge.net/svg-extensions', 'use-as-primary', 'false');
-    }
-    return child;
-}
+    function isWidgetFileName(s) {
+        if (endsWith(s, 'config.xml')) {
+            return true;
+        }
+        if (endsWith(s, '.wgt')) {
+            return true;
+        }
+        return false;
+    }
 
-//
-// create use
-//
-function use(uri) {
-    var child = document.createElement('use');
-    child.setAttributeNS(xlinkns, 'href', '#' + uri);
-    return child;
-}
+    //
+    // replace globally \ with / in a string
+    //
+    function escaping(s) {
+        s = s.replace(/\\/g, '/');
+        return s;
+    }
 
-//
-// create appropriate element for media reference by the given uri
-//
-function appropriateElementForMedia(uri, w, h) {
-    if (uri.indexOf('#') != -1) {
-        return media('animation', uri, w, h);
+    //
+    // create rect
+    //
+    function rect(x, y, w, h, fill, stroke, id) {
+        var child = document.createElement('rect');
+        if (id != null) {
+            child.setAttribute('id', id);
+        }
+        child.setAttribute('x', x);
+        child.setAttribute('y', y);
+        child.setAttribute('width', w);
+        child.setAttribute('height', h);
+        child.setAttribute('fill', fill);
+        child.setAttribute('stroke', stroke);
+        return child;
     }
-    if (endsWith(uri, '.svg')) {
-        return media('animation', uri, w, h);
+
+    //
+    // create text
+    //
+    function createtext(content, fill, x, y, size, family) {
+        var child = document.createElement('text');
+        child.setAttribute('fill', fill);
+        child.textContent = content;
+        child.setAttribute('x', x);
+        child.setAttribute('y', y);
+        child.setAttribute('font-size', size);
+        child.setAttribute('font-family', family);
+        return child;
     }
-    if (endsWith(uri, '.bt')) {
-        return media('animation', uri, w, h);
+
+    //
+    // create invisible rect getting all events
+    //
+    function invisible_rect(w, h) {
+        var child = document.createElement('rect');
+        child.setAttribute('width', w);
+        child.setAttribute('height', h);
+        child.setAttribute('fill', 'none');
+        child.setAttribute('stroke', 'none');
+        child.setAttribute('pointer-events', 'all');
+        return child;
     }
-    if (endsWith(uri, '.png')) {
-        return media('image', uri, w, h);
+
+    //
+    // create animation
+    //
+    function media(etype, uri, w, h) {
+        var child = document.createElement(etype);
+        child.setAttributeNS(xlinkns, 'href', uri);
+        child.setAttribute('width', w);
+        child.setAttribute('height', h);
+        if (etype == 'animation') {
+            child.setAttributeNS('http://gpac.sourceforge.net/svg-extensions', 'use-as-primary', 'false');
+        }
+        return child;
     }
-    if (endsWith(uri, '.jpg')) {
-        return media('image', uri, w, h);
+
+    //
+    // create use
+    //
+    function use(uri) {
+        var child = document.createElement('use');
+        child.setAttributeNS(xlinkns, 'href', '#' + uri);
+        return child;
     }
-    if (endsWith(uri, '.gif')) {
+
+    //
+    // create appropriate element for media reference by the given uri
+    //
+    function appropriateElementForMedia(uri, w, h) {
+        if (uri.indexOf('#') != -1) {
+            return media('animation', uri, w, h);
+        }
+        if (endsWith(uri, '.svg')) {
+            return media('animation', uri, w, h);
+        }
+        if (endsWith(uri, '.bt')) {
+            return media('animation', uri, w, h);
+        }
+        if (endsWith(uri, '.png')) {
+            return media('image', uri, w, h);
+        }
+        if (endsWith(uri, '.jpg')) {
+            return media('image', uri, w, h);
+        }
+        if (endsWith(uri, '.gif')) {
+            return media('image', uri, w, h);
+        }
+        if (l_war <= log_level) {
+            alert("[UI] WARNING: bad suffix for an icon URI: " + uri);
+        }
         return media('image', uri, w, h);
     }
-    if (l_war <= log_level) alert("[UI] WARNING: bad suffix for an icon URI: " + uri);
-    return media('image', uri, w, h);
-}
 
-//
-// substitute for the useful predefined function endsWith
-//
-function endsWith(s1, s2) {
-    return s1.toLowerCase().substring(s1.length - s2.length) == s2;
+    //
+    // substitute for the useful predefined function endsWith
+    //
+    function endsWith(s1, s2) {
+        return s1.toLowerCase().substring(s1.length - s2.length) == s2;
+    }
+
+    // export the resize function as the resize member of iphone_wm_gui, as well as other functions
+    return {
+        resize: resize,
+        left_button: left_button,
+        right_button: right_button,
+        left_buttonW: left_buttonW,
+        right_buttonW: right_buttonW,
+        home_button: home_button,
+        on_dir_scan: on_dir_scan,
+        on_clean_up: on_clean_up,
+        on_widget_add_menu: on_widget_add_menu,
+        on_kill_widget: on_kill_widget,
+        on_get_widget: on_get_widget,
+        on_widget_remote: on_widget_remote,
+        flUpDir: flUpDir,
+        flPrevFiles: flPrevFiles,
+        flNextFiles: flNextFiles,
+        flScanDir: flScanDir
+    }
+
+}());
+
+function widget_activated_and_bound(wid) {
+    WidgetManager.corein_message(wid, "activate");
 }
 
+function printAllFieldsOf(obj, printableName) {
+    var details = "fields of "+printableName+":\n";
+    for (var field in obj) {
+      fieldContents = obj[field];
+      if (typeof(fieldContents) == "function") {
+        fieldContents = "(function)";
+      }
+      details += "  " + field + ": " + fieldContents + "\n";
+    }
+    alert(details);
+}
diff --git a/include/gpac/ait.h b/include/gpac/ait.h
new file mode 100644 (file)
index 0000000..f393fa3
--- /dev/null
@@ -0,0 +1,240 @@
+/* \r
+ * Copyright (c) TELECOM ParisTech 2011\r
+ */\r
+\r
+#ifndef _GF_AIT_H_\r
+#define _GF_AIT_H_\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <gpac/mpegts.h>\r
+#include <gpac/dsmcc.h>\r
+#include <string.h>\r
+#include <gpac/bitstream.h>\r
+\r
+\r
+#define AIT_SECTION_LENGTH_MAX 1021\r
+#define APPLICATION_TYPE_HTTP_APPLICATION 16\r
+#define DSMCC_SECTION_LENGTH_MAX 4093\r
+\r
+typedef enum {\r
+       APPLICATION_DESCRIPTOR = 0x00,\r
+       APPLICATION_NAME_DESCRIPTOR = 0x01,\r
+       TRANSPORT_PROTOCOL_DESCRIPTOR = 0x02,\r
+       SIMPLE_APPLICATION_LOCATION_DESCRIPTOR = 0x15,\r
+       APPLICATION_USAGE_DESCRIPTOR = 0x16,\r
+       APPLICATION_BOUNDARY_DESCRIPTOR = 0x17,\r
+} DESCRIPTOR_TAG;\r
+\r
+enum ApplicationControlCode {\r
+       AUTOSTART =                             0x01, \r
+       PRESENT =                               0x02, \r
+       DESTROY =                               0x03, \r
+       KILL =                                  0x04,\r
+       PREFETCH =                              0x05,\r
+       REMOTE =                                0x06,\r
+       DISABLED =                              0x07,\r
+       PLAYBACK_AUTOSTART =    0x08\r
+};\r
+\r
+enum TransportType {\r
+       BROADCAST =             0x01,\r
+       BROADBAND =     0x03\r
+};\r
+\r
+typedef struct\r
+{\r
+       u32 pid;\r
+       u32 service_id;\r
+       u8 table_id;\r
+       Bool section_syntax_indicator;\r
+       u16 section_length;\r
+       Bool test_application_flag;\r
+       u16 application_type;\r
+       u8 version_number;\r
+       Bool current_next_indicator;\r
+       u8 section_number;\r
+       u8 last_section_number;\r
+       u16 common_descriptors_length;\r
+       GF_List * common_descriptors;\r
+       u16 application_loop_length;\r
+       GF_List * application_decoded;\r
+       u32 CRC_32;\r
+\r
+} GF_M2TS_AIT;\r
+\r
+\r
+typedef struct\r
+{\r
+       ABSTRACT_ES\r
+       GF_M2TS_SectionFilter *sec;     \r
+\r
+} GF_M2TS_AIT_CARRY;\r
+\r
+\r
+typedef struct\r
+{\r
+       u32 organisation_id;\r
+       u16 application_id;\r
+       u8 application_control_code;\r
+       u16 application_descriptors_loop_length;\r
+       GF_List * application_descriptors;\r
+       u8 application_descriptors_id[50];\r
+       u8 index_app_desc_id;\r
+\r
+}GF_M2TS_AIT_APPLICATION_DECODE;\r
+\r
+\r
+typedef enum {\r
+       FUTURE_USE = 0x00,\r
+       CAROUSEL = 0x01,\r
+       RESERVED = 0x02,\r
+       TRANSPORT_HTTP = 0x03,\r
+       DVB_USE = 0x04,\r
+       TO_REGISTER = 0x100,\r
+} PROTOCOL_ID;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u8 application_profiles_length;\r
+       u16 application_profile;\r
+       u8 version_major;\r
+       u8 version_minor;\r
+       u8 version_micro;\r
+       Bool service_bound_flag;\r
+       u8 visibility;\r
+       u8 application_priority;\r
+       u8 transport_protocol_label[5];\r
+\r
+} GF_M2TS_APPLICATION_DESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u8 usage_type;\r
+\r
+} GF_M2TS_APPLICATION_USAGE;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       char* initial_path_bytes;\r
+\r
+}GF_M2TS_SIMPLE_APPLICATION_LOCATION;\r
+\r
+typedef struct\r
+{\r
+       Bool remote_connection;\r
+       u16 original_network_id;\r
+       u16 transport_stream_id;\r
+       u16 service_id;\r
+       u8 component_tag;\r
+\r
+} GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE;\r
+\r
+typedef struct{\r
+\r
+       u8 URL_extension_length;\r
+       char* URL_extension_byte;\r
+\r
+}GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION;\r
+\r
+typedef struct\r
+{\r
+       u8 URL_base_length;\r
+       char* URL_base_byte;\r
+       u8 URL_extension_count;\r
+       GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION* URL_extentions;   \r
+\r
+} GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u16 protocol_id;\r
+       u8 transport_protocol_label;\r
+       void* selector_byte;\r
+\r
+} GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u32 ISO_639_language_code;\r
+       u8 application_name_length;\r
+       char* application_name_char;\r
+\r
+} GF_M2TS_APPLICATION_NAME_DESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u8 boundary_extension_length;\r
+       char* boundary_extension_byte;\r
+\r
+} GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u8 boundary_extension_count;\r
+       GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO* boundary_extension_info;\r
+\r
+} GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR;\r
+\r
+typedef struct\r
+{      \r
+       u32 application_id;\r
+       u8 application_control_code;\r
+\r
+       u8 priority;\r
+       u16 application_profile;\r
+\r
+       /* Transport mode - 1 Broadcast - 3 Broadband */\r
+       Bool broadcast;\r
+       Bool broadband;\r
+       char* http_url;\r
+       char* carousel_url;\r
+       Bool url_received;\r
+\r
+       /* Carousel */\r
+       u32 carousel_pid;\r
+       u32 component_tag;\r
+       \r
+\r
+       char* appli_name;\r
+\r
+} GF_M2TS_AIT_APPLICATION;\r
+\r
+typedef struct\r
+{\r
+       u32 service_id;\r
+       u32 version_number;\r
+       u32 ait_pid;\r
+       u32 nb_application;\r
+       GF_List *Application;   \r
+\r
+} GF_M2TS_CHANNEL_APPLICATION_INFO;\r
+\r
+void on_ait_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par);\r
+GF_M2TS_ES *gf_ait_section_new(u32 service_id);\r
+GF_M2TS_CHANNEL_APPLICATION_INFO* gf_m2ts_get_channel_application_info(GF_List* ChannelAppList, u32 ait_service_id);\r
+void  gf_m2ts_delete_channel_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO* ChannelApp);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif\r
+\r
+#endif //_GF_CAROUSSEL_H_\r
+\r
index b4e748662226f964a0bba876a157f11182cc443f..eeb1afa033d2ed7cc01f66cffdbc40766ae08261 100644 (file)
@@ -91,7 +91,7 @@ s32 gf_mv12_next_slice_start(unsigned char *pbuffer, u32 startoffset, u32 buflen
 u8 gf_mp3_num_channels(u32 hdr);
 u16 gf_mp3_sampling_rate(u32 hdr);
 u16 gf_mp3_window_size(u32 hdr);
-u16 gf_mp3_bit_rate(u32 hdr);
+u32 gf_mp3_bit_rate(u32 hdr);
 u8 gf_mp3_object_type_indication(u32 hdr);
 u8 gf_mp3_layer(u32 hdr);
 u16 gf_mp3_frame_size(u32 hdr);
@@ -233,7 +233,7 @@ void gf_img_parse(GF_BitStream *bs, u8 *OTI, u32 *mtype, u32 *width, u32 *height
 GF_Err gf_img_jpeg_dec(char *jpg, u32 jpg_size, u32 *width, u32 *height, u32 *pixel_format, char *dst, u32 *dst_size, u32 dst_nb_comp);
 
 GF_Err gf_img_png_dec(char *png, u32 png_size, u32 *width, u32 *height, u32 *pixel_format, char *dst, u32 *dst_size);
-GF_Err gf_img_png_file_dec(char *png_file, u32 *width, u32 *height, u32 *pixel_format, char **dst, u32 *dst_size);
+GF_Err gf_img_file_dec(char *png_file, u32 *oti, u32 *width, u32 *height, u32 *pixel_format, char **dst, u32 *dst_size);
 GF_Err gf_img_png_enc(char *data, u32 width, u32 height, s32 stride, u32 pixel_format, char *dst, u32 *dst_size);
 
 #ifdef __cplusplus
diff --git a/include/gpac/carousel.h b/include/gpac/carousel.h
deleted file mode 100644 (file)
index 2cbadc9..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- *                     GPAC - Multimedia Framework C SDK
- *
- *                     Authors: Telecom Paristech
- *    Copyright (c)2006-200X ENST - All rights reserved
- *
- *  This file is part of GPAC / MPEG2-TS sub-project
- *
- *  GPAC is gf_free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the gf_free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  GPAC 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 Lesser General Public License for more details.
- *   
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; see the file COPYING.  If not, write to
- *  the gf_free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- */
-
-
-#ifndef _GF_CAROUSSEL_H_
-#define _GF_CAROUSSEL_H_
-
-#include <gpac/mpegts.h>
-#include <string.h>
-#include <gpac/bitstream.h>
-
-#define AIT_SECTION_LENGTH_MAX 1021
-#define APPLICATION_TYPE_HTTP_APPLICATION 16
-
-typedef enum {
-       APPLICATION_DESCRIPTOR = 0x00,
-       APPLICATION_NAME_DESCRIPTOR = 0x01,
-       TRANSPORT_PROTOCOL_DESCRIPTOR = 0x02,
-       SIMPLE_APPLICATION_LOCATION_DESCRIPTOR = 0x15,
-       APPLICATION_USAGE_DESCRIPTOR = 0x16,
-} DESCRIPTOR_TAG;
-
-
-typedef struct
-{
-       
-       ABSTRACT_ES
-       GF_M2TS_SectionFilter *sec;
-
-       u32 service_id;
-       u8 table_id;
-       Bool section_syntax_indicator;
-       u16 section_length;
-       Bool test_application_flag;
-       u16 application_type;
-       u8 version_number;
-       Bool current_next_indicator;
-       u8 section_number;
-       u8 last_section_number;
-       u16 common_descriptors_length;
-       GF_List * common_descriptors;
-       u16 application_loop_length;
-       GF_List * application;
-       u32 CRC_32;
-
-} GF_M2TS_AIT;
-
-
-typedef struct
-{
-       u32 organisation_id;
-       u16 application_id;
-       u8 application_control_code;
-       u16 application_descriptors_loop_length;
-       GF_List * application_descriptors;
-       u8 application_descriptors_id[50];
-       u8 index_app_desc_id;
-
-}
-GF_M2TS_AIT_APPLICATION;
-
-
-typedef enum {
-       FUTURE_USE = 0x00,
-       CAROUSEL = 0x01,
-       RESERVED = 0x02,
-       TRANSPORT_HTTP = 0x03,
-       DVB_USE = 0x04,
-       TO_REGISTER = 0x100,
-} PROTOCOL_ID;
-
-typedef struct
-{
-       u8 descriptor_tag;
-       u8 descriptor_length;
-       u8 application_profiles_length;
-       u16 application_profile;
-       u8 version_major;
-       u8 version_minor;
-       u8 version_micro;
-       Bool service_bound_flag;
-       u8 visibility;
-       u8 application_priority;
-       u8 transport_protocol_label;
-
-} GF_M2TS_APPLICATION_DESCRIPTOR;
-
-typedef struct
-{
-       u8 descriptor_tag;
-       u8 descriptor_length;
-       u8 usage_type;
-
-} GF_M2TS_APPLICATION_USAGE;
-
-typedef struct
-{
-       u8 descriptor_tag;
-       u8 descriptor_length;
-       char* initial_path_bytes;
-
-}GF_M2TS_SIMPLE_APPLICATION_LOCATION;
-
-typedef struct
-{
-       Bool remote_connection;
-       u16 original_network_id;
-       u16 transport_stream_id;
-       u16 service_id;
-       u8 component_tag;
-
-} GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE;
-
-typedef struct{
-
-       u8 URL_extension_length;
-       char* URL_extension_byte;
-
-}GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION;
-
-typedef struct
-{
-       u8 URL_base_length;
-       char* URL_base_byte;
-       u8 URL_extension_count;
-       GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION* URL_extentions;   
-
-} GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE;
-
-typedef struct
-{
-       u8 descriptor_tag;
-       u8 descriptor_length;
-       u16 protocol_id;
-       u8 transport_protocol_label;
-       void* selector_byte;
-
-} GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR;
-
-typedef struct
-{
-       u8 descriptor_tag;
-       u8 descriptor_length;
-       u32 ISO_639_language_code;
-       u8 application_name_length;
-       char* application_name_char;
-
-} GF_M2TS_APPLICATION_NAME_DESCRIPTOR;
-
-GF_Err gf_m2ts_process_ait(GF_M2TS_AIT *es, char  *data, u32 data_size, u32 table_id);
-void on_ait_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par);
-GF_M2TS_ES *gf_ait_section_new(u32 service_id);
-void gf_ait_destroy(GF_M2TS_AIT* ait);
-
-
-#endif //_GF_CAROUSSEL_H_
-
index d08a4f6c78995f4d3825055ade51ae3db574bb4e..e1384a2f788193d614356bced42b3ba318c544b5 100644 (file)
@@ -111,6 +111,16 @@ GF_Err gf_cfg_save(GF_Config *iniFile);
  *\return the desired key value if found, NULL otherwise.
  */
 const char *gf_cfg_get_key(GF_Config *cfgFile, const char *secName, const char *keyName);
+/*!
+ *     \brief key value query ignoring case
+ *
+ *Gets a key value from its section and name. Comparison is performed while ignoring case.
+ *\param cfgFile the target configuration file
+ *\param secName the desired key parent section name (case ignored)
+ *\param keyName the desired key name (case ignored)
+ *\return the desired key value if found, NULL otherwise.
+ */
+const char *gf_cfg_get_ikey(GF_Config *cfgFile, const char *secName, const char *keyName);
 /*!
  *     \brief key value update
  *
index 8220aa49650035af55bf53b65293e6cd927fb26a..601fe9351b98c25755dd3feb885aa1c8266e751c 100644 (file)
@@ -29,7 +29,6 @@
 extern "C" {
 #endif
 
-#include <gpac/tools.h>
 
 /*! \addtogroup cst_grp constants
  *     \brief Constants used within GPAC
@@ -154,6 +153,9 @@ enum
  *
  *     Supported pixel formats for everything using video
 */
+#ifndef GF_4CC
+#define GF_4CC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
+#endif
 typedef enum
 {
        /*!8 bit GREY */
@@ -214,6 +216,8 @@ typedef enum
        GF_PIXEL_IYUV           =       GF_4CC('I','Y','U','V'),
        /*!YUV planar format*/
        GF_PIXEL_I420           =       GF_4CC('I','4','2','0'),
+       /*!YUV planar format*/
+       GF_PIXEL_NV21           =       GF_4CC('N','V','2','1'),
 
        /*!YV12 + Alpha plane*/
        GF_PIXEL_YUVA           =       GF_4CC('Y', 'U', 'V', 'A'),
@@ -558,12 +562,12 @@ enum
 
 
 /*rate sizes - note that these sizes INCLUDE the rate_type header byte*/
-static const u32 GF_QCELP_RATE_TO_SIZE [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
-static const u32 GF_QCELP_RATE_TO_SIZE_NB = 7;
-static const u32 GF_SMV_EVRC_RATE_TO_SIZE [] = {0, 1, 1, 3, 2, 6, 3, 11, 4, 23, 5, 1};
-static const u32 GF_SMV_EVRC_RATE_TO_SIZE_NB = 6;
-static const u32 GF_AMR_FRAME_SIZE[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
-static const u32 GF_AMR_WB_FRAME_SIZE[16] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0 };
+static const unsigned int GF_QCELP_RATE_TO_SIZE [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
+static const unsigned int GF_QCELP_RATE_TO_SIZE_NB = 7;
+static const unsigned int GF_SMV_EVRC_RATE_TO_SIZE [] = {0, 1, 1, 3, 2, 6, 3, 11, 4, 23, 5, 1};
+static const unsigned int GF_SMV_EVRC_RATE_TO_SIZE_NB = 6;
+static const unsigned int GF_AMR_FRAME_SIZE[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
+static const unsigned int GF_AMR_WB_FRAME_SIZE[16] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0 };
 
 
 /*out-of-band sample desc (128 and 255 reserved in RFC)*/
index a96194fb648398f839883107122382059fa4843e..5d5380f14362bc462411dd3b3b3b5a9c85f1a4bf 100644 (file)
@@ -160,7 +160,8 @@ extern "C" {
     /*!session download flags*/
     enum
     {
-        /*!session is not threaded, the user must explicitely fetch the data */
+        /*!session is not threaded, the user must explicitely fetch the data , either with the function gf_dm_sess_fetch_data 
+               or the function gf_dm_sess_process- if the session is threaded, the user must call gf_dm_sess_process to start the session*/
         GF_NETIO_SESSION_NOT_THREADED  =       1,
         /*! session data is live, e.g. data will be sent to the user if threaded mode (live streams like radios & co)
                                Whether the data is cached or not to disk cannot be controlled by the user at the current time.
@@ -242,14 +243,16 @@ extern "C" {
      *\param sess the download session
     */
     void gf_dm_sess_del(GF_DownloadSession * sess);
-    /*!
+
+       /*!
      *\brief aborts downloading
      *
      *Aborts all operations in the session, regardless of its state. The session cannot be reused once this is called.
      *\param sess the download session
      */
     void gf_dm_sess_abort(GF_DownloadSession * sess);
-    /*!
+
+       /*!
      *\brief sets private data
      *
      *associate private data with the session.
@@ -299,9 +302,9 @@ extern "C" {
     GF_Err gf_dm_sess_fetch_data(GF_DownloadSession * sess, char *buffer, u32 buffer_size, u32 *read_size);
 
     /*!
-     *\brief get mime type
+     *\brief get mime type as lower case
      *
-     *Fetches the mime type of the URL this session is fetching
+     *Fetches the mime type of the URL this session is fetching, value will be returned lower case, so application/x-mpegURL will be returned as application/x-mpegurl
      *\param sess the download session
      *\return the mime type of the URL, or NULL if error. You should get the error with \ref gf_dm_sess_last_error
      */
diff --git a/include/gpac/dsmcc.h b/include/gpac/dsmcc.h
new file mode 100644 (file)
index 0000000..4fd2add
--- /dev/null
@@ -0,0 +1,643 @@
+/* \r
+ * Copyright (c) TELECOM ParisTech 2011\r
+ */\r
+\r
+\r
+\r
+#ifndef _GF_DSMCC_H_\r
+#define _GF_DSMCC_H_\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <gpac/mpegts.h>\r
+#include <string.h>\r
+#include <gpac/bitstream.h>\r
+\r
+#define DSMCC_SECTION_LENGTH_MAX 4093\r
+\r
+typedef enum{\r
+       DOWNLOAD_INFO_REQUEST =                                 0x1001,\r
+       DOWNLOAD_INFO_REPONSE_INDICATION =              0x1002,\r
+       DOWNLOAD_DATA_BLOCK =                                   0x1003,\r
+       DOWNLOAD_DATA_REQUEST =                                 0x1004,\r
+       DOWNLOAD_DATA_CANCEL =                                  0x1005,\r
+       DOWNLOAD_SERVER_INITIATE =                              0x1006\r
+}DSMCC_DOWNLOAD_MESSAGE_ID;\r
+\r
+typedef enum{\r
+       TAG_BIOP =                              0x49534F06,\r
+       TAG_LITE_OPTIONS =              0x49534F05\r
+}DSMCC_DOWNLOAD_PROFILE_ID_TAG;\r
+\r
+typedef enum{\r
+       CACHING_PRIORITY_DESCRIPTOR             =               0x71,\r
+       CONTENT_TYPE_DESCRIPTOR                 =               0x72,\r
+       COMPRESSED_MODULE_DESCRIPTOR    =               0x09\r
+}DSMCC_BIOP_DESCRIPTOR;\r
+\r
+typedef struct{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u32 carousel_id;\r
+       u8 FormatID;\r
+       char *private_data_byte;\r
+       u8 ModuleVersion;\r
+       u8 ModuleId;\r
+       u16 BlockSize;\r
+       u32 ModuleSize;\r
+       u8 CompressionMethod;\r
+       u32 OriginalSize;\r
+       u8 TimeOut;\r
+       u8 ObjectKeyLength;\r
+       char* ObjectKeyData;\r
+}GF_M2TS_CAROUSEL_INDENTIFIER_DESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u32 moduleId;\r
+       u32 downloadId;\r
+       u32 version_number;\r
+       Bool done;\r
+}GF_M2TS_DSMCC_PROCESSED;\r
+\r
+typedef struct\r
+{\r
+       /* Module identifier */\r
+       u32 moduleId;\r
+       /* Version number of the module */\r
+       u32 version_number;\r
+       /* size in byte of the module */\r
+       u32 size;\r
+       /* Download identifier */\r
+       u32 downloadId;\r
+       /* buffer of data */\r
+       char* buffer;\r
+       /* byte shifting in the buffer of data */\r
+       u32 byte_sift;\r
+       /* last section number processed */\r
+       u16 section_number;\r
+       /* the last section number of the module */\r
+       u16 last_section_number;\r
+       /* size in byte of each block in the module */\r
+       u32 block_size;\r
+       /* Checks if the module has been processed */\r
+       /* 1 if yes */\r
+       /* 0 otherwise */\r
+       Bool processed;\r
+       /* Checks if the module's data are zipped */\r
+       /* 1 if yes */\r
+       /* 0 otherwise */\r
+       Bool Gzip;\r
+       /* Size of the module's data after uncompression */\r
+       u32 original_size;\r
+}GF_M2TS_DSMCC_MODULE;\r
+\r
+typedef struct\r
+{\r
+       /* table id : identifier for dsmcc message type */\r
+       u8 table_id;\r
+       /* indicates the presence of CRC 32 */\r
+       u8 section_syntax_indicator;\r
+       u8 private_indicator;\r
+       /* length in byte of the dsmcc section */\r
+       u16 dsmcc_section_length;\r
+       /* linked with the moduleId if carried by the section */\r
+       u16 table_id_extension;\r
+       /* version number linked with the Data block if carried by the section */\r
+       u8 version_number;\r
+       u8 current_next_indicator;\r
+       /* section number of the data block if carried by the section */\r
+       u8 section_number;\r
+       /* last section number of the data block if carried by the section */\r
+       u8 last_section_number; \r
+       void* DSMCC_Extension;\r
+       u32 checksum;\r
+       u32 CRC_32;\r
+}GF_M2TS_DSMCC_SECTION;\r
+\r
+typedef struct\r
+{\r
+       u8 adaptationType;\r
+       char* adaptationDataByte;\r
+}\r
+GF_M2TS_DSMCC_ADAPTATION_HEADER;\r
+\r
+typedef struct\r
+{\r
+       u8 protocolDiscriminator;\r
+       u8 dsmccType;\r
+       u16 messageId;\r
+       /* dsmccMessageHeader mode */\r
+       u32 transactionId;\r
+       /* dsmccDownloadDataHeader */\r
+       u32 downloadId;\r
+       u8 reserved;\r
+       u8 adaptationLength;\r
+       u16 messageLength;\r
+       /* added not in the spec */\r
+       u8 header_length;\r
+       GF_M2TS_DSMCC_ADAPTATION_HEADER* DsmccAdaptationHeader;\r
+\r
+}GF_M2TS_DSMCC_MESSAGE_DATA_HEADER;\r
+\r
+/* DOWNLOAD_DATA_MESSAGE */\r
+typedef struct\r
+{\r
+       u8 protocolDiscriminator;\r
+       u8 dsmccType;\r
+       u16 messageId;\r
+       u32 downloadId;\r
+       u8 reserved;\r
+       u8 adaptationLength;\r
+       u16 messageLength;\r
+       GF_M2TS_DSMCC_ADAPTATION_HEADER* DsmccAdaptationHeader;\r
+\r
+}GF_M2TS_DSMCC_DOWNLOAD_DATA_HEADER;\r
+\r
+typedef struct\r
+{      \r
+       u8 subDescriptorType;\r
+       u8 subDescriptorLength; \r
+       char *additionalInformation;\r
+\r
+}GF_M2TS_DSMCC_SUBDESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u8 descriptorType;\r
+       u8 descriptorLength;\r
+       u8 specifierType;\r
+       u32 specifierData;\r
+       u16 model;\r
+       u16 version;\r
+       u8 subDescriptorCount;\r
+       GF_M2TS_DSMCC_SUBDESCRIPTOR* SubDescriptor;\r
+\r
+}GF_M2TS_DSMCC_DESCRIPTOR;\r
+\r
+typedef struct\r
+{\r
+       u16 compatibilityDescriptorLength;\r
+       u16 descriptorCount;\r
+       GF_M2TS_DSMCC_DESCRIPTOR* Descriptor;\r
+}GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR;\r
+\r
+typedef struct\r
+{      \r
+       u32 bufferSize;\r
+       u16 maximumBlockSize;\r
+       GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR CompatibilityDescr;\r
+       u16 privateDataLength;\r
+       char* privateDataByte;\r
+}GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST;\r
+\r
+typedef struct\r
+{\r
+       u16 moduleId;\r
+       u32 moduleSize;\r
+       u8 moduleVersion;\r
+       u8 moduleInfoLength;\r
+       char* moduleInfoByte;\r
+}GF_M2TS_DSMCC_INFO_MODULES;\r
+\r
+typedef struct\r
+{  \r
+       u32 downloadId;\r
+       u16 blockSize;\r
+       u8 windowSize;\r
+       u8 ackPeriod;\r
+       u32 tCDownloadWindow;\r
+       u32 tCDownloadScenario;\r
+       GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR CompatibilityDescr;\r
+       u16 numberOfModules;\r
+       GF_M2TS_DSMCC_INFO_MODULES Modules;\r
+       u16 privateDataLength;     \r
+       char* privateDataByte;\r
+}GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC;\r
+\r
+typedef struct\r
+{  \r
+       u8 moduleId;\r
+       u8 moduleVersion;\r
+       u8 reserved;\r
+       u8 blockNumber;\r
+       char* blockDataByte;\r
+       /*added not in the spec */\r
+       u32 dataBlocksize;\r
+}GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK;\r
+\r
+typedef struct\r
+{ \r
+       u16 moduleId;\r
+       u16 blockNumber;\r
+       u8 downloadReason;\r
+}GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE;\r
+\r
+typedef struct\r
+{  \r
+       u32 downloadId;\r
+       u16 moduleId;\r
+       u16 blockNumber;\r
+       u8 downloadCancelReason;\r
+       u8 reserved;\r
+       u16 privateDataLength;\r
+       char* privateDataByte;\r
+}GF_M2TS_DSMCC_DOWNLOAD_CANCEL;\r
+\r
+typedef struct\r
+{      \r
+       u32 GroupId;\r
+       u32 GroupSize;\r
+       GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR CompatibilityDescr;\r
+       u16 GroupInfoLength;\r
+       char* groupInfoByte;\r
+}GF_M2TS_DSMCC_INFO_GROUP;\r
+\r
+typedef struct\r
+{\r
+       u16 NumberOfGroups;\r
+       GF_M2TS_DSMCC_INFO_GROUP* InfoGroup; \r
+       u16 PrivateDataLength;\r
+       char* privateDataByte;\r
+\r
+}GF_M2TS_DSMCC_GROUP_INFO_INDICATION;\r
+\r
+typedef struct\r
+{ \r
+       u8 serverId[20];\r
+       GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR CompatibilityDescr;\r
+       u16 privateDataLength;\r
+       char* privateDataByte;\r
+       GF_M2TS_DSMCC_GROUP_INFO_INDICATION* GroupInfoIndic;\r
+}GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT;\r
+\r
+typedef struct\r
+{\r
+       GF_M2TS_DSMCC_MESSAGE_DATA_HEADER DownloadDataHeader;\r
+       void* dataMessagePayload;\r
+}GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE;\r
+\r
+/* DESCRIPTOR LIST */\r
+\r
+typedef struct\r
+{\r
+       u8 descriptorTag;\r
+       u8 descriptorLength;\r
+       u8 postDiscontinuityIndicator;\r
+       u8 contentId;\r
+       u8 STC_Reference[5];\r
+       u8 NPT_Reference[5];\r
+       u16 scaleNumerator;\r
+       u16 scaleDenominator;\r
+}GF_M2TS_DSMCC_NPT_REFERENCE_DESCRIPTOR;\r
+\r
+\r
+typedef struct\r
+{\r
+       u8 descriptorTag;\r
+       u8 descriptorLength;\r
+       void* descriptor;\r
+}GF_M2TS_DSMCC_STREAM_DESCRIPTOR;\r
+\r
+/* OBJECT CAROUSEL */\r
+typedef struct{\r
+       u16 id;\r
+       u16 use;\r
+       u16 assocTag;\r
+       u8 selector_length;\r
+       char* selector_data;\r
+       u16 selector_type;\r
+       u32 transactionId;\r
+       u32 timeout;\r
+}GF_M2TS_DSMCC_BIOP_TAPS;\r
+\r
+typedef struct{\r
+       u8 AFI;\r
+       u8 type;\r
+       u32 carouselId;\r
+       u8 specifierType;\r
+       u32 specifierData;\r
+       u16 transport_stream_id; \r
+       u16 original_network_id;\r
+       u16 service_id;\r
+       u32 reserved;\r
+}GF_M2TS_DSMCC_SERVICE_DOMAIN;\r
+\r
+typedef struct{\r
+       u32 componentId_tag;\r
+       u8 component_data_length;\r
+       u32 carouselId;\r
+       u16 moduleId;\r
+       u8 version_major;\r
+       u8 version_minor;\r
+       u8 objectKey_length;\r
+       u32 objectKey_data;\r
+}GF_M2TS_DSMCC_BIOP_OBJECT_LOCATION;\r
+\r
+typedef struct{\r
+       u32 componentId_tag;\r
+       u8 component_data_length;\r
+       u8 taps_count;\r
+       GF_M2TS_DSMCC_BIOP_TAPS* Taps;\r
+       char* additional_tap_byte;\r
+}GF_M2TS_DSMCC_BIOP_CONN_BINDER;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_BIOP_OBJECT_LOCATION ObjectLocation;\r
+       GF_M2TS_DSMCC_BIOP_CONN_BINDER ConnBinder;\r
+}GF_M2TS_DSMCC_BIOP_PROFILE_BODY;\r
+\r
+typedef struct{\r
+       u32 id_length;\r
+       char* id_data;\r
+       u32 kind_length;\r
+       char* kind_data;\r
+}GF_M2TS_DSMCC_BIOP_NAME_COMPONENT;\r
+\r
+typedef struct{\r
+       u32 componentId_tag;\r
+       u8 component_data_length;\r
+       u8 serviceDomain_length;\r
+       GF_M2TS_DSMCC_SERVICE_DOMAIN serviceDomain_data;\r
+       u32 nameComponents_count;\r
+       GF_M2TS_DSMCC_BIOP_NAME_COMPONENT* NameComponent;\r
+       u32 initialContext_length;\r
+       char* InitialContext_data_byte;\r
+}GF_M2TS_DSMCC_BIOP_SERVICE_LOCATION;\r
+\r
+typedef struct{\r
+       u32 componentId_tag;\r
+       u8 component_data_length;\r
+       char* component_data_byte;\r
+}GF_M2TS_DSMCC_BIOP_LITE_COMPONENT;\r
+\r
+typedef struct{\r
+       u32 profileId_tag;\r
+       u32 profile_data_length;\r
+       u8 profile_data_byte_order;\r
+       u8 lite_component_count;\r
+\r
+       GF_M2TS_DSMCC_BIOP_PROFILE_BODY* BIOPProfileBody;\r
+       GF_M2TS_DSMCC_BIOP_SERVICE_LOCATION* ServiceLocation;\r
+       GF_M2TS_DSMCC_BIOP_LITE_COMPONENT* LiteComponent;\r
+\r
+}GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE;\r
+\r
+typedef struct{\r
+       u32 type_id_length;\r
+       char* type_id_byte;\r
+       u32 taggedProfiles_count;\r
+       GF_List* taggedProfile;\r
+}GF_M2TS_DSMCC_IOR;\r
+\r
+typedef struct{\r
+       u32 moduleTimeOut;\r
+       u32 blockTimeOut;\r
+       u32 minBlockTime;\r
+       u8 taps_count;\r
+       GF_M2TS_DSMCC_BIOP_TAPS* Taps;\r
+       u8 userInfoLength;\r
+       u8* userInfo_data;\r
+       GF_List* descriptor;\r
+\r
+       u8 compression_method;  \r
+       u8 transparency_level; \r
+}GF_M2TS_DSMCC_BIOP_MODULE_INFO;\r
+\r
+typedef struct{\r
+       u32 context_id;\r
+       u16 context_data_length;\r
+       char* context_data_byte;\r
+}GF_M2TS_DSMCC_SERVICE_CONTEXT;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_IOR IOR;\r
+       u8 downloadTaps_count;\r
+       GF_M2TS_DSMCC_BIOP_TAPS* Taps;\r
+       u8 serviceContextList_count;\r
+       GF_M2TS_DSMCC_SERVICE_CONTEXT* ServiceContext;\r
+       u16 userInfoLength;\r
+       char* userInfo_data;\r
+}GF_M2TS_DSMCC_SERVICE_GATEWAY_INFO;\r
+\r
+\r
+/* DESCRIPTORS */\r
+typedef struct{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u8 priority_value;\r
+       u8 transparency_level;\r
+}GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR;\r
+\r
+typedef struct{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;\r
+       u8 compression_method;\r
+       u32 original_size;\r
+}GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR;\r
+\r
+typedef struct{\r
+       u8 descriptor_tag;\r
+       u8 descriptor_length;                                                   \r
+       char* content_type_data_byte;\r
+}GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR;\r
+\r
+\r
+typedef struct{\r
+       /* "BIOP" */\r
+       u32 magic;\r
+       u8 biop_version_major;\r
+       u8 biop_version_minor;\r
+       u8 byte_order;\r
+       u8 message_type;\r
+       /* size in byte of the whole object carousel */\r
+       u32 message_size;\r
+       u8 objectKey_length;\r
+       /* witness the kind of object carousel the item is */\r
+       /* fil for a file */\r
+       /* dir for a directory */\r
+       /* srg for the ServiceGateway */\r
+       /* str for Stream Message */\r
+       /* ste for Stream Event Message */\r
+       u32 objectKey_data;\r
+       u32 objectKind_length;\r
+       /* The number that identifies the object in the module */\r
+       char* objectKind_data;\r
+       u16 objectInfo_length;\r
+}GF_M2TS_DSMCC_BIOP_HEADER;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_BIOP_HEADER* Header;\r
+       u64 ContentSize;\r
+       GF_List* descriptor;\r
+       u8 serviceContextList_count;\r
+       GF_M2TS_DSMCC_SERVICE_CONTEXT* ServiceContext;\r
+       u32 messageBody_length;\r
+       /* size in byte of the data of the file */\r
+       u32 content_length;\r
+       /* data a the file */\r
+       char* content_byte;\r
+}GF_M2TS_DSMCC_BIOP_FILE;\r
+\r
+typedef struct{\r
+       /* Name */\r
+       u8 nameComponents_count;\r
+       /* There is must be only one nameComponent */\r
+       u8 id_length;\r
+       /* the name of the item */\r
+       char * id_data;\r
+       u8 kind_length;\r
+       /* the kind of the item */\r
+       /* fil for a file */\r
+       /* dir for a directory */\r
+       /* srg for the ServiceGateway */\r
+       /* str for Stream Message */\r
+       /* ste for Stream Event Message */\r
+       char* kind_data;\r
+       /* 1 if the item a file or a stream */\r
+       /* 0 if the item si a directory */\r
+       u8 BindingType;\r
+       GF_M2TS_DSMCC_IOR IOR;\r
+       u16 objectInfo_length;\r
+       u64 ContentSize;\r
+       GF_List* descriptor;\r
+}GF_M2TS_DSMCC_BIOP_NAME;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_BIOP_HEADER* Header;\r
+       char* objectInfo_data;\r
+       u8 serviceContextList_count;\r
+       GF_M2TS_DSMCC_SERVICE_CONTEXT* ServiceContext;\r
+       /* Length is byte of the message */\r
+       u32 messageBody_length;\r
+       /* Number of the item */\r
+       u16 bindings_count;\r
+       /* List of the item in the directory */\r
+       GF_M2TS_DSMCC_BIOP_NAME* Name;          \r
+}GF_M2TS_DSMCC_BIOP_DIRECTORY;\r
+\r
+typedef struct{\r
+       u8 aDescription_length;                                 \r
+       char* aDescription_bytes;\r
+       u32 duration_aSeconds;\r
+       u32 duration_aMicroseconds;\r
+       u8 audio;        \r
+       u8 video;        \r
+       u8 data;\r
+}GF_M2TS_DSMCC_STREAM_INFO;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_BIOP_HEADER* Header;                      \r
+       GF_M2TS_DSMCC_STREAM_INFO Info;\r
+       char* objectInfo_byte;\r
+       u8 serviceContextList_count;                            \r
+       GF_M2TS_DSMCC_SERVICE_CONTEXT* ServiceContext;\r
+       u32 messageBody_length; \r
+       u8 taps_count;\r
+       GF_M2TS_DSMCC_BIOP_TAPS* Taps;                          \r
+}GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE;\r
+\r
+typedef struct{                                        \r
+       u8 eventName_length;                            \r
+       char* eventName_data_byte;\r
+}GF_M2TS_DSMCC_BIOP_EVENT_LIST;\r
+\r
+typedef struct{\r
+       GF_M2TS_DSMCC_BIOP_HEADER* Header; \r
+       GF_M2TS_DSMCC_STREAM_INFO Info;                         \r
+       u16 eventNames_count;\r
+       GF_M2TS_DSMCC_BIOP_EVENT_LIST* EventList;\r
+       char* objectInfo_byte;\r
+       u8 serviceContextList_count;                            \r
+       GF_M2TS_DSMCC_SERVICE_CONTEXT* ServiceContext;\r
+       u32 messageBody_length;          \r
+       u8 taps_count;\r
+       GF_M2TS_DSMCC_BIOP_TAPS* Taps;          \r
+       u8 eventIds_count;                              \r
+       u16* eventId;\r
+}GF_M2TS_DSMCC_BIOP_STREAM_EVENT;\r
+\r
+/*Define the base element for extracted dsmcc element*/\r
+#define GF_M2TS_DSMCC_ELEMENT          \\r
+                       u32 moduleId; \\r
+                       u32 downloadId; \\r
+                       u32 version_number; \\r
+                       u32 objectKey_data; \\r
+                       char* name; \\r
+                       void* parent;\r
+\r
+typedef struct\r
+{      \r
+       GF_M2TS_DSMCC_ELEMENT\r
+       /*Path to the file */\r
+       char* Path;\r
+}GF_M2TS_DSMCC_FILE;\r
+\r
+typedef struct\r
+{      GF_M2TS_DSMCC_ELEMENT\r
+       /* List of files in the directory*/\r
+       GF_List* File;\r
+       /* List of directories of the directory*/\r
+       GF_List* Dir;\r
+       /*Path to the directory */\r
+       char* Path;\r
+}GF_M2TS_DSMCC_DIR;\r
+\r
+typedef struct\r
+{      GF_M2TS_DSMCC_ELEMENT\r
+       /* Number of process directories */\r
+       u8 nb_processed_dir;\r
+       /* Service Id of the data carousel*/\r
+       u32 service_id;\r
+       /* List of files of the root of the file system*/\r
+       GF_List* File;\r
+       /* List of directories of the root of the file system*/\r
+       GF_List* Dir;\r
+}GF_M2TS_DSMCC_SERVICE_GATEWAY;\r
+\r
+typedef struct\r
+{      \r
+       /* List that carries the modules to process */\r
+       GF_List* dsmcc_modules;\r
+       /* List of processed module */\r
+       GF_M2TS_DSMCC_PROCESSED processed[512]; \r
+       /*Check if the ServiceGateway has been recovered*/\r
+       /* 1 ServiceGateway received */\r
+       /* 0 otherwise */\r
+       Bool Got_ServiceGateway;\r
+       /* ServiceGateway Structure */\r
+       GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway;\r
+       /* u32 transactionId for DownloadInfoIndicator versioning */\r
+       u32 transactionId;\r
+       /* List that carries modules that have been received before inti - TO DO */\r
+       GF_List* Unprocessed_module;\r
+       /* Service ID that carries this carousel */\r
+       u32 service_id;\r
+       /* Path of the root directory of the file system */\r
+       char* root_dir;\r
+       /*Check if the index.html (root of the application) has been recovered*/\r
+       /* 1 index.html received received */\r
+       /* 0 otherwise */\r
+       Bool get_index;\r
+       /* Number of the application that uses the carousel*/\r
+       u32 application_id;\r
+}GF_M2TS_DSMCC_OVERLORD;\r
+\r
+void on_dsmcc_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par);\r
+GF_Err gf_m2ts_process_dsmcc(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char  *data, u32 data_size, u32 table_id);\r
+GF_M2TS_DSMCC_OVERLORD* gf_m2ts_init_dsmcc_overlord(u32 service_id);\r
+GF_M2TS_DSMCC_OVERLORD* gf_m2ts_get_dmscc_overlord(GF_List* Dsmcc_controller,u32 service_id);\r
+void gf_m2ts_delete_dsmcc_overlord(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif\r
+\r
+#endif //_GF_CAROUSSEL_H_\r
+\r
index 6a6305c4a03c91fc61d3d3732ed6b7c83c558599..f96664eed5ce1252171d3780c3fda2f0f7d64078 100644 (file)
@@ -29,6 +29,8 @@
 #include <gpac/mpegts.h>
 #include <string.h>
 
+#ifndef GPAC_DISABLE_MPEG2TS
+
 typedef struct tag_m2ts_section_mpe GF_M2TS_SECTION_MPE;
 typedef struct _sock_entry GF_SOCK_ENTRY;
 
@@ -38,4 +40,6 @@ GF_M2TS_ES *gf_dvb_mpe_section_new();
 void gf_dvb_mpe_section_del(GF_M2TS_ES *es);
 void gf_m2ts_print_mpe_info(GF_M2TS_Demuxer *ts);
 
+#endif //GPAC_DISABLE_MPEG2TS
+
 #endif //_GF_DVB_MPE_H_
index f5f06d89d7237ddf2aa897d0c8a992fc1d96f669..2fbe8edb4cf560f17f2fabacdbc445d3a463f5f7 100644 (file)
 extern "C" {
 #endif
 
+
 #include <gpac/math.h>
 #include <gpac/tools.h>
+#include <gpac/events_constants.h>
 
-/*
-               minimal event system
-
-       DO NOT CHANGE THEIR POSITION IN THE LIST, USED TO SPEED UP FILTERING OF USER INPUT EVENTS
-*/
-
-/*events*/
-enum {
-
-       /******************************************************
-
-               Events used for both GPAC internals and DOM Events
-
-       *******************************************************/
-       /*MouseEvents*/
-       GF_EVENT_CLICK,
-       GF_EVENT_MOUSEUP,
-       GF_EVENT_MOUSEDOWN,
-       GF_EVENT_MOUSEOVER,
-       GF_EVENT_MOUSEOUT,
-       /*!! ALL MOUSE EVENTS SHALL BE DECLARED BEFORE MOUSEMOVE !! */
-       GF_EVENT_MOUSEMOVE,
-       /*mouse wheel event*/
-       GF_EVENT_MOUSEWHEEL,
-
-       /*Key Events*/
-       GF_EVENT_KEYUP,
-       GF_EVENT_KEYDOWN, /* covers KeyDown, KeyPress and AccessKey */
-       GF_EVENT_LONGKEYPRESS,
-       /*character input*/
-       GF_EVENT_TEXTINPUT,
-
-
-       /******************************************************
-
-               Events used for DOM Events only
-
-       *******************************************************/
-       GF_EVENT_TEXTSELECT,
-
-       /*DOM UIEvents*/
-       GF_EVENT_FOCUSIN,
-       GF_EVENT_FOCUSOUT,
-       GF_EVENT_ACTIVATE,
-       GF_EVENT_CHANGE,
-       GF_EVENT_FOCUS,
-       GF_EVENT_BLUR,
-       /*SVG (HTML) Events*/
-       GF_EVENT_LOAD,
-       GF_EVENT_UNLOAD,
-       GF_EVENT_ABORT,
-       GF_EVENT_ERROR,
-       GF_EVENT_RESIZE,
-       GF_EVENT_SCROLL,
-       GF_EVENT_ZOOM,
-       GF_EVENT_BEGIN, /*this is a fake event, it is NEVER fired, only used in SMIL begin*/
-       GF_EVENT_BEGIN_EVENT,
-       GF_EVENT_END, /*this is a fake event, it is NEVER fired, only used in SMIL end*/
-       GF_EVENT_END_EVENT,
-       GF_EVENT_REPEAT, /*this is a fake event, it is NEVER fired, only used in SMIL repeat*/
-       GF_EVENT_REPEAT_EVENT,
-
-       /*DOM MutationEvents - NOT SUPPORTED YET*/
-       GF_EVENT_TREE_MODIFIED,
-       GF_EVENT_NODE_INSERTED,
-       GF_EVENT_NODE_REMOVED,
-       GF_EVENT_NODE_INSERTED_DOC,
-       GF_EVENT_NODE_REMOVED_DOC,
-       GF_EVENT_ATTR_MODIFIED,
-       GF_EVENT_CHAR_DATA_MODIFIED,
-       GF_EVENT_NODE_NAME_CHANGED,
-       GF_EVENT_ATTR_NAME_CHANGED,
-
-       GF_EVENT_DCCI_PROP_CHANGE,
-
-       /*LASeR events*/
-       GF_EVENT_ACTIVATED,
-       GF_EVENT_DEACTIVATED,
-       GF_EVENT_PAUSE,
-       GF_EVENT_PAUSED_EVENT,
-       GF_EVENT_PLAY,
-       GF_EVENT_REPEAT_KEY,
-       GF_EVENT_RESUME_EVENT,
-       GF_EVENT_SHORT_ACCESSKEY,
-       /*pseudo-event, only used in LASeR coding*/
-       GF_EVENT_EXECUTION_TIME,
-
-       /*MediaAccess events - cf http://www.w3.org/TR/MediaAccessEvents*/
-       GF_EVENT_MEDIA_BEGIN_SESSION_SETUP,
-       GF_EVENT_MEDIA_END_SESSION_SETUP,
-       GF_EVENT_MEDIA_DATA_REQUEST,
-       GF_EVENT_MEDIA_PLAYABLE,
-       GF_EVENT_MEDIA_NOT_PLAYABLE,
-       GF_EVENT_MEDIA_DATA_PROGRESS,
-       GF_EVENT_MEDIA_END_OF_DATA,
-       GF_EVENT_MEDIA_STOP,
-       GF_EVENT_MEDIA_ERROR,
-
-       GF_EVENT_BATTERY,
-       GF_EVENT_CPU,
-       GF_EVENT_UNKNOWN,
-
-
-       /******************************************************
-
-               Events used for GPAC internals only
-
-       *******************************************************/
-
-       /*same as mousedown, generated internally by GPAC*/
-       GF_EVENT_DBLCLICK,
-
-       /*scene attached event, dispatched when the root node of a scene is loaded and
-       attached to the window or parent object (animation, inline, ...)*/
-       GF_EVENT_SCENE_ATTACHED,
-
-       /*VP resize attached event, dispatched when viewport of a scene is being modified
-       attached to the window or parent object (animation, inline, ...)*/
-       GF_EVENT_VP_RESIZE,
-
-       /*window events*/
-       /*size has changed - indicate new w & h in .x end .y fields of event.
-       When sent from gpac to a video plugin, indicates the output size should be changed. This is only sent when the plugin
-       manages the output video himself
-       When sent from a video plugin to gpac, indicates the output size has been changed. This is only sent when the plugin
-       manages the output video himself
-       */
-       GF_EVENT_SIZE,
-       /*signals the scene size (if indicated in scene) upon connection (sent to the user event proc only)
-               if scene size hasn't changed (seeking or other) this event is not sent
-       */
-       GF_EVENT_SCENE_SIZE,
-       GF_EVENT_SHOWHIDE,      /*window show/hide (minimized or other). This is also sent to the user to signal focus switch in fullscreen*/
-       GF_EVENT_SET_CURSOR,    /*set mouse cursor*/
-       GF_EVENT_SET_CAPTION,   /*set window caption*/
-       GF_EVENT_MOVE,          /*move window*/
-       GF_EVENT_REFRESH, /*window needs repaint (whenever needed, eg restore, hide->show, background refresh, paint)*/
-       GF_EVENT_QUIT,  /*window is being closed*/
-       /*video hw setup message:
-               - when sent from gpac to plugin, indicates that the plugin should re-setup hardware context due to a window resize:
-                       * for 2D output, this means resizing the backbuffer if needed (depending on HW constraints)
-                       * for 3D output, this means re-setup of OpenGL context (depending on HW constraints). Depending on windowing systems
-                       and implementations, it could be possible to resize a window without destroying the GL context.
-
-               - when sent from plugin to gpac, indicates that hardware resources must be resetup before next render step (this is mainly
-               due to discard all openGL textures and cached objects)
-       */
-       GF_EVENT_VIDEO_SETUP,
-       /*queries the list of system colors - only exchanged between compositor and video output*/
-       GF_EVENT_SYS_COLORS,
-
-       /*indicates some text has been pasted - from video output to compositor only*/
-       GF_EVENT_PASTE_TEXT,
-       /*queries for text to be copied - from video output to compositor only*/
-       GF_EVENT_COPY_TEXT,
-
-       /*terminal events*/
-       GF_EVENT_CONNECT,       /*signal URL is connected*/
-       GF_EVENT_DURATION,      /*signal duration of presentation*/
-       GF_EVENT_EOS,   /*signal End of scene playback*/
-       GF_EVENT_AUTHORIZATION, /*indicates a user and pass is queried*/
-       GF_EVENT_NAVIGATE, /*indicates the user app should load or jump to the given URL.*/
-       GF_EVENT_NAVIGATE_INFO, /*indicates the link or its description under the mouse pointer*/
-       GF_EVENT_MESSAGE, /*message from the MPEG-4 terminal*/
-       GF_EVENT_PROGRESS, /*progress message from the MPEG-4 terminal*/
-       GF_EVENT_FORWARDED, /*event forwarded by service (MPEG-2, RTP, ...)*/
-       GF_EVENT_VIEWPOINTS,    /*indicates viewpoint list has changed - no struct associated*/
-       GF_EVENT_STREAMLIST,    /*indicates stream list has changed - no struct associated - only used when no scene info is present*/
-       GF_EVENT_METADATA, /*indicates a change in associated metadata*/
-       GF_EVENT_MIGRATE, /*indicates a session migration request*/
-       GF_EVENT_DISCONNECT, /*indicates the current url should be disconnected*/
-       GF_EVENT_RESOLUTION, /*indicates the screen resolution has changed*/
-       GF_EVENT_OPENFILE,
-    /* Events for Keyboad */
-    GF_EVENT_TEXT_EDITING_START,
-    GF_EVENT_TEXT_EDITING_END
-};
-
-/*GPAC/DOM3 key codes*/
-enum {
-       GF_KEY_UNIDENTIFIED = 0,
-       GF_KEY_ACCEPT = 1, /* "Accept"    The Accept (Commit) key.*/
-       GF_KEY_AGAIN, /* "Again"  The Again key.*/
-       GF_KEY_ALLCANDIDATES, /* "AllCandidates"    The All Candidates key.*/
-       GF_KEY_ALPHANUM, /*"Alphanumeric"    The Alphanumeric key.*/
-       GF_KEY_ALT, /*"Alt"    The Alt (Menu) key.*/
-       GF_KEY_ALTGRAPH, /*"AltGraph"    The Alt-Graph key.*/
-       GF_KEY_APPS, /*"Apps"    The Application key.*/
-       GF_KEY_ATTN, /*"Attn"    The ATTN key.*/
-       GF_KEY_BROWSERBACK, /*"BrowserBack"    The Browser Back key.*/
-       GF_KEY_BROWSERFAVORITES, /*"BrowserFavorites"    The Browser Favorites key.*/
-       GF_KEY_BROWSERFORWARD, /*"BrowserForward"    The Browser Forward key.*/
-       GF_KEY_BROWSERHOME, /*"BrowserHome"    The Browser Home key.*/
-       GF_KEY_BROWSERREFRESH, /*"BrowserRefresh"    The Browser Refresh key.*/
-       GF_KEY_BROWSERSEARCH, /*"BrowserSearch"    The Browser Search key.*/
-       GF_KEY_BROWSERSTOP, /*"BrowserStop"    The Browser Stop key.*/
-       GF_KEY_CAPSLOCK, /*"CapsLock"    The Caps Lock (Capital) key.*/
-       GF_KEY_CLEAR, /*"Clear"    The Clear key.*/
-       GF_KEY_CODEINPUT, /*"CodeInput"    The Code Input key.*/
-       GF_KEY_COMPOSE, /*"Compose"    The Compose key.*/
-       GF_KEY_CONTROL, /*"Control"    The Control (Ctrl) key.*/
-       GF_KEY_CRSEL, /*"Crsel"    The Crsel key.*/
-       GF_KEY_CONVERT, /*"Convert"    The Convert key.*/
-       GF_KEY_COPY, /*"Copy"    The Copy key.*/
-       GF_KEY_CUT, /*"Cut"    The Cut key.*/
-       GF_KEY_DOWN, /*"Down"    The Down Arrow key.*/
-       GF_KEY_END, /*"End"    The End key.*/
-       GF_KEY_ENTER, /*"Enter"    The Enter key.
-                   Note: This key identifier is also used for the Return (Macintosh numpad) key.*/
-       GF_KEY_ERASEEOF, /*"EraseEof"    The Erase EOF key.*/
-       GF_KEY_EXECUTE, /*"Execute"    The Execute key.*/
-       GF_KEY_EXSEL, /*"Exsel"    The Exsel key.*/
-       GF_KEY_F1, /*"F1"    The F1 key.*/
-       GF_KEY_F2, /*"F2"    The F2 key.*/
-       GF_KEY_F3, /*"F3"    The F3 key.*/
-       GF_KEY_F4, /*"F4"    The F4 key.*/
-       GF_KEY_F5, /*"F5"    The F5 key.*/
-       GF_KEY_F6, /*"F6"    The F6 key.*/
-       GF_KEY_F7, /*"F7"    The F7 key.*/
-       GF_KEY_F8, /*"F8"    The F8 key.*/
-       GF_KEY_F9, /*"F9"    The F9 key.*/
-       GF_KEY_F10, /*"F10"    The F10 key.*/
-       GF_KEY_F11, /*"F11"    The F11 key.*/
-       GF_KEY_F12, /*"F12"    The F12 key.*/
-       GF_KEY_F13, /*"F13"    The F13 key.*/
-       GF_KEY_F14, /*"F14"    The F14 key.*/
-       GF_KEY_F15, /*"F15"    The F15 key.*/
-       GF_KEY_F16, /*"F16"    The F16 key.*/
-       GF_KEY_F17, /*"F17"    The F17 key.*/
-       GF_KEY_F18, /*"F18"    The F18 key.*/
-       GF_KEY_F19, /*"F19"    The F19 key.*/
-       GF_KEY_F20, /*"F20"    The F20 key.*/
-       GF_KEY_F21, /*"F21"    The F21 key.*/
-       GF_KEY_F22, /*"F22"    The F22 key.*/
-       GF_KEY_F23, /*"F23"    The F23 key.*/
-       GF_KEY_F24, /*"F24"    The F24 key.*/
-       GF_KEY_FINALMODE, /*"FinalMode"    The Final Mode (Final) key used on some asian keyboards.*/
-       GF_KEY_FIND, /*"Find"    The Find key.*/
-       GF_KEY_FULLWIDTH, /*"FullWidth"    The Full-Width Characters key.*/
-       GF_KEY_HALFWIDTH, /*"HalfWidth"    The Half-Width Characters key.*/
-       GF_KEY_HANGULMODE, /*"HangulMode"    The Hangul (Korean characters) Mode key.*/
-       GF_KEY_HANJAMODE, /*"HanjaMode"    The Hanja (Korean characters) Mode key.*/
-       GF_KEY_HELP, /*"Help"    The Help key.*/
-       GF_KEY_HIRAGANA, /*"Hiragana"    The Hiragana (Japanese Kana characters) key.*/
-       GF_KEY_HOME, /*"Home"    The Home key.*/
-       GF_KEY_INSERT, /*"Insert"    The Insert (Ins) key.*/
-       GF_KEY_JAPANESEHIRAGANA, /*"JapaneseHiragana"    The Japanese-Hiragana key.*/
-       GF_KEY_JAPANESEKATAKANA, /*"JapaneseKatakana"    The Japanese-Katakana key.*/
-       GF_KEY_JAPANESEROMAJI, /*"JapaneseRomaji"    The Japanese-Romaji key.*/
-       GF_KEY_JUNJAMODE, /*"JunjaMode"    The Junja Mode key.*/
-       GF_KEY_KANAMODE, /*"KanaMode"    The Kana Mode (Kana Lock) key.*/
-       GF_KEY_KANJIMODE, /*"KanjiMode"    The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key.*/
-       GF_KEY_KATAKANA, /*"Katakana"    The Katakana (Japanese Kana characters) key.*/
-       GF_KEY_LAUNCHAPPLICATION1, /*"LaunchApplication1"    The Start Application One key.*/
-       GF_KEY_LAUNCHAPPLICATION2, /*"LaunchApplication2"    The Start Application Two key.*/
-       GF_KEY_LAUNCHMAIL, /*"LaunchMail"    The Start Mail key.*/
-       GF_KEY_LEFT, /*"Left"    The Left Arrow key.*/
-       GF_KEY_META, /*"Meta"    The Meta key.*/
-       GF_KEY_MEDIANEXTTRACK, /*"MediaNextTrack"    The Media Next Track key.*/
-       GF_KEY_MEDIAPLAYPAUSE, /*"MediaPlayPause"    The Media Play Pause key.*/
-       GF_KEY_MEDIAPREVIOUSTRACK, /*"MediaPreviousTrack"    The Media Previous Track key.*/
-       GF_KEY_MEDIASTOP, /*"MediaStop"    The Media Stok key.*/
-       GF_KEY_MODECHANGE, /*"ModeChange"    The Mode Change key.*/
-       GF_KEY_NONCONVERT, /*"Nonconvert"    The Nonconvert (Don't Convert) key.*/
-       GF_KEY_NUMLOCK, /*"NumLock"    The Num Lock key.*/
-       GF_KEY_PAGEDOWN, /*"PageDown"    The Page Down (Next) key.*/
-       GF_KEY_PAGEUP, /*"PageUp"    The Page Up key.*/
-       GF_KEY_PASTE, /*"Paste"    The Paste key.*/
-       GF_KEY_PAUSE, /*"Pause"    The Pause key.*/
-       GF_KEY_PLAY, /*"Play"    The Play key.*/
-       GF_KEY_PREVIOUSCANDIDATE, /*"PreviousCandidate"    The Previous Candidate function key.*/
-       GF_KEY_PRINTSCREEN, /*"PrintScreen"    The Print Screen (PrintScrn, SnapShot) key.*/
-       GF_KEY_PROCESS, /*"Process"    The Process key.*/
-       GF_KEY_PROPS, /*"Props"    The Props key.*/
-       GF_KEY_RIGHT, /*"Right"    The Right Arrow key.*/
-       GF_KEY_ROMANCHARACTERS, /*"RomanCharacters"    The Roman Characters function key.*/
-       GF_KEY_SCROLL, /*"Scroll"    The Scroll Lock key.*/
-       GF_KEY_SELECT, /*"Select"    The Select key.*/
-       GF_KEY_SELECTMEDIA, /*"SelectMedia"    The Select Media key.*/
-       GF_KEY_SHIFT, /*"Shift"    The Shift key.*/
-       GF_KEY_STOP, /*"Stop"    The Stop key.*/
-       GF_KEY_UP, /*"Up"    The Up Arrow key.*/
-       GF_KEY_UNDO, /*"Undo"    The Undo key.*/
-       GF_KEY_VOLUMEDOWN, /*"VolumeDown"    The Volume Down key.*/
-       GF_KEY_VOLUMEMUTE, /*"VolumeMute"    The Volume Mute key.*/
-       GF_KEY_VOLUMEUP, /*"VolumeUp"    The Volume Up key.*/
-       GF_KEY_WIN, /*"Win"    The Windows Logo key.*/
-       GF_KEY_ZOOM, /*"Zoom"    The Zoom key.*/
-       GF_KEY_BACKSPACE, /*"U+0008"    The Backspace (Back) key.*/
-       GF_KEY_TAB, /*"U+0009"    The Horizontal Tabulation (Tab) key.*/
-       GF_KEY_CANCEL, /*"U+0018"    The Cancel key.*/
-       GF_KEY_ESCAPE, /*"U+001B"    The Escape (Esc) key.*/
-       GF_KEY_SPACE, /*"U+0020"    The Space (Spacebar) key.*/
-       GF_KEY_EXCLAMATION, /*"U+0021"    The Exclamation Mark (Factorial, Bang) key (!).*/
-       GF_KEY_QUOTATION, /*"U+0022"    The Quotation Mark (Quote Double) key (").*/
-       GF_KEY_NUMBER, /*"U+0023"    The Number Sign (Pound Sign, Hash, Crosshatch, Octothorpe) key (#).*/
-       GF_KEY_DOLLAR, /*"U+0024"    The Dollar Sign (milreis, escudo) key ($).*/
-       GF_KEY_AMPERSAND, /*"U+0026"    The Ampersand key (&).*/
-       GF_KEY_APOSTROPHE, /*"U+0027"    The Apostrophe (Apostrophe-Quote, APL Quote) key (').*/
-       GF_KEY_LEFTPARENTHESIS, /*"U+0028"    The Left Parenthesis (Opening Parenthesis) key (().*/
-       GF_KEY_RIGHTPARENTHESIS, /*"U+0029"    The Right Parenthesis (Closing Parenthesis) key ()).*/
-       GF_KEY_STAR, /*"U+002A"    The Asterix (Star) key (*).*/
-       GF_KEY_PLUS, /*"U+002B"    The Plus Sign (Plus) key (+).*/
-       GF_KEY_COMMA, /*"U+002C"    The Comma (decimal separator) sign key (,).*/
-       GF_KEY_HYPHEN, /*"U+002D"    The Hyphen-minus (hyphen or minus sign) key (-).*/
-       GF_KEY_FULLSTOP, /*"U+002E"    The Full Stop (period, dot, decimal point) key (.).*/
-       GF_KEY_SLASH, /*"U+002F"    The Solidus (slash, virgule, shilling) key (/).*/
-       GF_KEY_0, /*"U+0030"    The Digit Zero key (0).*/
-       GF_KEY_1, /*"U+0031"    The Digit One key (1).*/
-       GF_KEY_2, /*"U+0032"    The Digit Two key (2).*/
-       GF_KEY_3, /*"U+0033"    The Digit Three key (3).*/
-       GF_KEY_4, /*"U+0034"    The Digit Four key (4).*/
-       GF_KEY_5, /*"U+0035"    The Digit Five key (5).*/
-       GF_KEY_6, /*"U+0036"    The Digit Six key (6).*/
-       GF_KEY_7, /*"U+0037"    The Digit Seven key (7).*/
-       GF_KEY_8, /*"U+0038"    The Digit Eight key (8).*/
-       GF_KEY_9, /*"U+0039"    The Digit Nine key (9).*/
-       GF_KEY_COLON, /*"U+003A"    The Colon key (:).*/
-       GF_KEY_SEMICOLON, /*"U+003B"    The Semicolon key (;).*/
-       GF_KEY_LESSTHAN, /*"U+003C"    The Less-Than Sign key (<).*/
-       GF_KEY_EQUALS, /*"U+003D"    The Equals Sign key (=).*/
-       GF_KEY_GREATERTHAN, /*"U+003E"    The Greater-Than Sign key (>).*/
-       GF_KEY_QUESTION, /*"U+003F"    The Question Mark key (?).*/
-       GF_KEY_AT, /*"U+0040"    The Commercial At (@) key.*/
-       GF_KEY_A, /*"U+0041"    The Latin Capital Letter A key (A).*/
-       GF_KEY_B, /*"U+0042"    The Latin Capital Letter B key (B).*/
-       GF_KEY_C, /*"U+0043"    The Latin Capital Letter C key (C).*/
-       GF_KEY_D, /*"U+0044"    The Latin Capital Letter D key (D).*/
-       GF_KEY_E, /*"U+0045"    The Latin Capital Letter E key (E).*/
-       GF_KEY_F, /*"U+0046"    The Latin Capital Letter F key (F).*/
-       GF_KEY_G, /*"U+0047"    The Latin Capital Letter G key (G).*/
-       GF_KEY_H, /*"U+0048"    The Latin Capital Letter H key (H).*/
-       GF_KEY_I, /*"U+0049"    The Latin Capital Letter I key (I).*/
-       GF_KEY_J, /*"U+004A"    The Latin Capital Letter J key (J).*/
-       GF_KEY_K, /*"U+004B"    The Latin Capital Letter K key (K).*/
-       GF_KEY_L, /*"U+004C"    The Latin Capital Letter L key (L).*/
-       GF_KEY_M, /*"U+004D"    The Latin Capital Letter M key (M).*/
-       GF_KEY_N, /*"U+004E"    The Latin Capital Letter N key (N).*/
-       GF_KEY_O, /*"U+004F"    The Latin Capital Letter O key (O).*/
-       GF_KEY_P, /*"U+0050"    The Latin Capital Letter P key (P).*/
-       GF_KEY_Q, /*"U+0051"    The Latin Capital Letter Q key (Q).*/
-       GF_KEY_R, /*"U+0052"    The Latin Capital Letter R key (R).*/
-       GF_KEY_S, /*"U+0053"    The Latin Capital Letter S key (S).*/
-       GF_KEY_T, /*"U+0054"    The Latin Capital Letter T key (T).*/
-       GF_KEY_U, /*"U+0055"    The Latin Capital Letter U key (U).*/
-       GF_KEY_V, /*"U+0056"    The Latin Capital Letter V key (V).*/
-       GF_KEY_W, /*"U+0057"    The Latin Capital Letter W key (W).*/
-       GF_KEY_X, /*"U+0058"    The Latin Capital Letter X key (X).*/
-       GF_KEY_Y, /*"U+0059"    The Latin Capital Letter Y key (Y).*/
-       GF_KEY_Z, /*"U+005A"    The Latin Capital Letter Z key (Z).*/
-       GF_KEY_LEFTSQUAREBRACKET, /*"U+005B"    The Left Square Bracket (Opening Square Bracket) key ([).*/
-       GF_KEY_BACKSLASH, /*"U+005C"    The Reverse Solidus (Backslash) key (\).*/
-       GF_KEY_RIGHTSQUAREBRACKET, /*"U+005D"    The Right Square Bracket (Closing Square Bracket) key (]).*/
-       GF_KEY_CIRCUM, /*"U+005E"    The Circumflex Accent key (^).*/
-       GF_KEY_UNDERSCORE, /*"U+005F"    The Low Sign (Spacing Underscore, Underscore) key (_).*/
-       GF_KEY_GRAVEACCENT, /*"U+0060"    The Grave Accent (Back Quote) key (`).*/
-       GF_KEY_LEFTCURLYBRACKET, /*"U+007B"    The Left Curly Bracket (Opening Curly Bracket, Opening Brace, Brace Left) key ({).*/
-       GF_KEY_PIPE, /*"U+007C"    The Vertical Line (Vertical Bar, Pipe) key (|).*/
-       GF_KEY_RIGHTCURLYBRACKET, /*"U+007D"    The Right Curly Bracket (Closing Curly Bracket, Closing Brace, Brace Right) key (}).*/
-       GF_KEY_DEL, /*"U+007F"    The Delete (Del) Key.*/
-       GF_KEY_INVERTEXCLAMATION, /*"U+00A1"    The Inverted Exclamation Mark key (�).*/
-       GF_KEY_DEADGRAVE, /*"U+0300"    The Combining Grave Accent (Greek Varia, Dead Grave) key.*/
-       GF_KEY_DEADEACUTE, /*"U+0301"    The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute) key.*/
-       GF_KEY_DEADCIRCUM, /*"U+0302"    The Combining Circumflex Accent (Hat, Dead Circumflex) key.*/
-       GF_KEY_DEADTILDE, /*"U+0303"    The Combining Tilde (Dead Tilde) key.*/
-       GF_KEY_DEADMACRON, /*"U+0304"    The Combining Macron (Long, Dead Macron) key.*/
-       GF_KEY_DEADBREVE, /*"U+0306"    The Combining Breve (Short, Dead Breve) key.*/
-       GF_KEY_DEADABOVEDOT, /*"U+0307"    The Combining Dot Above (Derivative, Dead Above Dot) key.*/
-       GF_KEY_DEADDIARESIS, /*"U+0308"    The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika, Double Derivative, Dead Diaeresis) key.*/
-       GF_KEY_DEADRINGABOVE, /*"U+030A"    The Combining Ring Above (Dead Above Ring) key.*/
-       GF_KEY_DEADDOUBLEACUTE, /*"U+030B"    The Combining Double Acute Accent (Dead Doubleacute) key.*/
-       GF_KEY_DEADCARON, /*"U+030C"    The Combining Caron (Hacek, V Above, Dead Caron) key.*/
-       GF_KEY_DEADCEDILLA, /*"U+0327"    The Combining Cedilla (Dead Cedilla) key.*/
-       GF_KEY_DEADOGONEK, /*"U+0328"    The Combining Ogonek (Nasal Hook, Dead Ogonek) key.*/
-       GF_KEY_DEADIOTA, /*"U+0345"    The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota Subscript, Dead Iota) key.*/
-       GF_KEY_EURO, /*"U+20AC"    The Euro Currency Sign key (�).*/
-       GF_KEY_DEADVOICESOUND, /*"U+3099"    The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key.*/
-       GF_KEY_DEADSEMIVOICESOUND, /*"U+309A"    The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced Sound) key. */
-       /* STB */
-       GF_KEY_CHANNELUP, /*ChannelUp*/
-       GF_KEY_CHANNELDOWN, /*ChannelDown*/
-       GF_KEY_TEXT, /*Text*/
-       GF_KEY_INFO, /*Info*/
-       GF_KEY_EPG, /*EPG*/
-       GF_KEY_RECORD, /*Record*/
-       GF_KEY_BEGINPAGE, /*BeginPage*/
-    /* end STB */
-
-       /*non-dom keys, used in LASeR*/
-       GF_KEY_CELL_SOFT1,      /*soft1 key of cell phones*/
-       GF_KEY_CELL_SOFT2,      /*soft2 key of cell phones*/
-
-       /*for joystick handling*/
-       GF_KEY_JOYSTICK
-};
-
-
-/*key modifiers state - set by terminal (not set by video driver)*/
-enum
-{
-       GF_KEY_MOD_SHIFT = (1),
-       GF_KEY_MOD_CTRL = (1<<2),
-       GF_KEY_MOD_ALT = (1<<3),
-
-       GF_KEY_EXT_NUMPAD = (1<<4),
-       GF_KEY_EXT_LEFT = (1<<5),
-       GF_KEY_EXT_RIGHT = (1<<6)
-};
 
 /*mouse button modifiers*/
 enum
@@ -504,7 +98,7 @@ typedef struct
        u8 type;
        /*width and height of visual surface to allocate*/
        u16 width, height;
-       /*indicates whether double buffering is desired*/
+       /*indicates whether double buffering is desired - when sent from plugin to player, indicates the backbuffer has been destroyed*/
        Bool back_buffer;
        /*indicates whether system memory for the backbuffer is desired (no video blitting)*/
        Bool system_memory;
@@ -527,24 +121,6 @@ typedef struct
        u32 show_type;
 } GF_EventShow;
 
-
-/*sensor signaling*/
-enum
-{
-       GF_CURSOR_NORMAL = 0x00,
-       GF_CURSOR_ANCHOR,
-       GF_CURSOR_TOUCH,
-       /*discSensor, cylinderSensor, sphereSensor*/
-       GF_CURSOR_ROTATE,
-       /*proximitySensor & proximitySensor2D*/
-       GF_CURSOR_PROXIMITY,
-       /*planeSensor & planeSensor2D*/
-       GF_CURSOR_PLANE,
-       /*collision*/
-       GF_CURSOR_COLLIDE,
-       GF_CURSOR_HIDE,
-};
-
 /*event proc return value: ignored*/
 typedef struct
 {
@@ -672,13 +248,6 @@ typedef struct
        u32 sys_colors[28];
 } GF_EventSysColors;
 
-/*Mutation AttrChangeType Signaling*/
-enum
-{
-       GF_MUTATION_ATTRCHANGE_MODIFICATION = 0x01,
-       GF_MUTATION_ATTRCHANGE_ADDITION = 0x02,
-       GF_MUTATION_ATTRCHANGE_REMOVAL = 0x03,
-};
 
 typedef struct {
        /* GF_EVENT_TREE_MODIFIED, GF_EVENT_NODE_INSERTED, GF_EVENT_NODE_REMOVED, GF_EVENT_NODE_INSERTED_DOC, GF_EVENT_NODE_REMOVED_DOC, GF_EVENT_ATTR_MODIFIED, GF_EVENT_CHAR_DATA_MODIFIED */
@@ -690,13 +259,6 @@ typedef struct {
        u8 attrChange;
 } GF_EventMutation;
 
-enum
-{
-       /*events forwarded from MPEG-2 stack*/
-       GF_EVT_FORWARDED_MPEG2 = 0,
-       /*events forwarded from RTP/RTSP/IP stack (not used yet)*/
-       GF_EVT_FORWARDED_RTP_RTSP
-};
 
 typedef struct {
        /* GF_EVENT_OPENFILE*/
diff --git a/include/gpac/events_constants.h b/include/gpac/events_constants.h
new file mode 100644 (file)
index 0000000..f1693fd
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Copyright (c) Jean Le Feuvre 2000-2005
+ *                     Copyright (c) Telecom-Paristech 2005-20xx
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Events management
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  GPAC 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef _GF_EVENTS_CONSTANTS_H_
+#define _GF_EVENTS_CONSTANTS_H_
+
+
+
+/*
+               minimal event system
+
+       DO NOT CHANGE THEIR POSITION IN THE LIST, USED TO SPEED UP FILTERING OF USER INPUT EVENTS
+*/
+
+/*events*/
+enum {
+
+       /******************************************************
+
+               Events used for both GPAC internals and DOM Events
+
+       *******************************************************/
+       /*MouseEvents*/
+       GF_EVENT_CLICK,
+       GF_EVENT_MOUSEUP,
+       GF_EVENT_MOUSEDOWN,
+       GF_EVENT_MOUSEOVER,
+       GF_EVENT_MOUSEOUT,
+       /*!! ALL MOUSE EVENTS SHALL BE DECLARED BEFORE MOUSEMOVE !! */
+       GF_EVENT_MOUSEMOVE,
+       /*mouse wheel event*/
+       GF_EVENT_MOUSEWHEEL,
+
+       /*Key Events*/
+       GF_EVENT_KEYUP,
+       GF_EVENT_KEYDOWN, /* covers KeyDown, KeyPress and AccessKey */
+       GF_EVENT_LONGKEYPRESS,
+       /*character input*/
+       GF_EVENT_TEXTINPUT,
+
+
+       /******************************************************
+
+               Events used for DOM Events only
+
+       *******************************************************/
+       GF_EVENT_TEXTSELECT,
+
+       /*DOM UIEvents*/
+       GF_EVENT_FOCUSIN,
+       GF_EVENT_FOCUSOUT,
+       GF_EVENT_ACTIVATE,
+       GF_EVENT_CHANGE,
+       GF_EVENT_FOCUS,
+       GF_EVENT_BLUR,
+       /*SVG (HTML) Events*/
+       GF_EVENT_LOAD,
+       GF_EVENT_UNLOAD,
+       GF_EVENT_ABORT,
+       GF_EVENT_ERROR,
+       GF_EVENT_RESIZE,
+       GF_EVENT_SCROLL,
+       GF_EVENT_ZOOM,
+       GF_EVENT_BEGIN, /*this is a fake event, it is NEVER fired, only used in SMIL begin*/
+       GF_EVENT_BEGIN_EVENT,
+       GF_EVENT_END, /*this is a fake event, it is NEVER fired, only used in SMIL end*/
+       GF_EVENT_END_EVENT,
+       GF_EVENT_REPEAT, /*this is a fake event, it is NEVER fired, only used in SMIL repeat*/
+       GF_EVENT_REPEAT_EVENT,
+
+       /*DOM MutationEvents - NOT SUPPORTED YET*/
+       GF_EVENT_TREE_MODIFIED,
+       GF_EVENT_NODE_INSERTED,
+       GF_EVENT_NODE_REMOVED,
+       GF_EVENT_NODE_INSERTED_DOC,
+       GF_EVENT_NODE_REMOVED_DOC,
+       GF_EVENT_ATTR_MODIFIED,
+       GF_EVENT_CHAR_DATA_MODIFIED,
+       GF_EVENT_NODE_NAME_CHANGED,
+       GF_EVENT_ATTR_NAME_CHANGED,
+
+       GF_EVENT_DCCI_PROP_CHANGE,
+
+       /*LASeR events*/
+       GF_EVENT_ACTIVATED,
+       GF_EVENT_DEACTIVATED,
+       GF_EVENT_PAUSE,
+       GF_EVENT_PAUSED_EVENT,
+       GF_EVENT_PLAY,
+       GF_EVENT_REPEAT_KEY,
+       GF_EVENT_RESUME_EVENT,
+       GF_EVENT_SHORT_ACCESSKEY,
+       /*pseudo-event, only used in LASeR coding*/
+       GF_EVENT_EXECUTION_TIME,
+
+       /*MediaAccess events - cf http://www.w3.org/TR/MediaAccessEvents*/
+#if 0
+       GF_EVENT_MEDIA_BEGIN_SESSION_SETUP,
+       GF_EVENT_MEDIA_END_SESSION_SETUP,
+       GF_EVENT_MEDIA_DATA_REQUEST,
+       GF_EVENT_MEDIA_PLAYABLE,
+       GF_EVENT_MEDIA_NOT_PLAYABLE,
+       GF_EVENT_MEDIA_DATA_PROGRESS,
+       GF_EVENT_MEDIA_END_OF_DATA,
+       GF_EVENT_MEDIA_STOP,
+       GF_EVENT_MEDIA_ERROR,
+#endif
+
+       /*HTML5 media events*/
+
+       GF_EVENT_MEDIA_SETUP_BEGIN,     /*not HTML5 but should be :)*/\r
+       GF_EVENT_MEDIA_SETUP_DONE,      /*not HTML5 but should be :)*/\r
+       GF_EVENT_MEDIA_LOAD_START,\r
+       GF_EVENT_MEDIA_LOAD_DONE,       /*not HTML5 but should be :)*/\r
+       GF_EVENT_MEDIA_PROGRESS, \r
+       GF_EVENT_MEDIA_SUSPEND, \r
+       GF_EVENT_MEDIA_EMPTIED, \r
+       GF_EVENT_MEDIA_STALLED, \r
+       GF_EVENT_MEDIA_LOADED_METADATA, \r
+       GF_EVENT_MEDIA_LODADED_DATA, \r
+       GF_EVENT_MEDIA_CANPLAY, \r
+       GF_EVENT_MEDIA_CANPLAYTHROUGH, \r
+       GF_EVENT_MEDIA_PLAYING, \r
+       GF_EVENT_MEDIA_WAITING, \r
+       GF_EVENT_MEDIA_SEEKING, \r
+       GF_EVENT_MEDIA_SEEKED, \r
+       GF_EVENT_MEDIA_ENDED, \r
+       GF_EVENT_MEDIA_DURATION_CHANGED, \r
+       GF_EVENT_MEDIA_TIME_UPDATE, \r
+       GF_EVENT_MEDIA_RATECHANGE, \r
+       GF_EVENT_MEDIA_VOLUME_CHANGED, \r
+
+       GF_EVENT_BATTERY,
+       GF_EVENT_CPU,
+       GF_EVENT_UNKNOWN,
+
+
+       /******************************************************
+
+               Events used for GPAC internals only
+
+       *******************************************************/
+
+       /*same as mousedown, generated internally by GPAC*/
+       GF_EVENT_DBLCLICK,
+
+       /*scene attached event, dispatched when the root node of a scene is loaded and
+       attached to the window or parent object (animation, inline, ...)*/
+       GF_EVENT_SCENE_ATTACHED,
+
+       /*VP resize attached event, dispatched when viewport of a scene is being modified
+       attached to the window or parent object (animation, inline, ...)*/
+       GF_EVENT_VP_RESIZE,
+
+       /*window events*/
+       /*size has changed - indicate new w & h in .x end .y fields of event.
+       When sent from gpac to a video plugin, indicates the output size should be changed. This is only sent when the plugin
+       manages the output video himself
+       When sent from a video plugin to gpac, indicates the output size has been changed. This is only sent when the plugin
+       manages the output video himself
+       */
+       GF_EVENT_SIZE,
+       /*signals the scene size (if indicated in scene) upon connection (sent to the user event proc only)
+               if scene size hasn't changed (seeking or other) this event is not sent
+       */
+       GF_EVENT_SCENE_SIZE,
+       GF_EVENT_SHOWHIDE,      /*window show/hide (minimized or other). This is also sent to the user to signal focus switch in fullscreen*/
+       GF_EVENT_SET_CURSOR,    /*set mouse cursor*/
+       GF_EVENT_SET_CAPTION,   /*set window caption*/
+       GF_EVENT_MOVE,          /*move window*/
+       GF_EVENT_REFRESH, /*window needs repaint (whenever needed, eg restore, hide->show, background refresh, paint)*/
+       GF_EVENT_QUIT,  /*window is being closed*/
+       /*video hw setup message:
+               - when sent from gpac to plugin, indicates that the plugin should re-setup hardware context due to a window resize:
+                       * for 2D output, this means resizing the backbuffer if needed (depending on HW constraints)
+                       * for 3D output, this means re-setup of OpenGL context (depending on HW constraints). Depending on windowing systems
+                       and implementations, it could be possible to resize a window without destroying the GL context.
+
+               - when sent from plugin to gpac, indicates that hardware resources must be resetup before next render step (this is mainly
+               due to discard all openGL textures and cached objects)
+       */
+       GF_EVENT_VIDEO_SETUP,
+       /*queries the list of system colors - only exchanged between compositor and video output*/
+       GF_EVENT_SYS_COLORS,
+
+       /*indicates some text has been pasted - from video output to compositor only*/
+       GF_EVENT_PASTE_TEXT,
+       /*queries for text to be copied - from video output to compositor only*/
+       GF_EVENT_COPY_TEXT,
+
+       /*terminal events*/
+       GF_EVENT_CONNECT,       /*signal URL is connected*/
+       GF_EVENT_DURATION,      /*signal duration of presentation*/
+       GF_EVENT_EOS,   /*signal End of scene playback*/
+       GF_EVENT_AUTHORIZATION, /*indicates a user and pass is queried*/
+       GF_EVENT_NAVIGATE, /*indicates the user app should load or jump to the given URL.*/
+       GF_EVENT_NAVIGATE_INFO, /*indicates the link or its description under the mouse pointer*/
+       GF_EVENT_MESSAGE, /*message from the MPEG-4 terminal*/
+       GF_EVENT_PROGRESS, /*progress message from the MPEG-4 terminal*/
+       GF_EVENT_FORWARDED, /*event forwarded by service (MPEG-2, RTP, ...)*/
+       GF_EVENT_VIEWPOINTS,    /*indicates viewpoint list has changed - no struct associated*/
+       GF_EVENT_STREAMLIST,    /*indicates stream list has changed - no struct associated - only used when no scene info is present*/
+       GF_EVENT_METADATA, /*indicates a change in associated metadata*/
+       GF_EVENT_MIGRATE, /*indicates a session migration request*/
+       GF_EVENT_DISCONNECT, /*indicates the current url should be disconnected*/
+       GF_EVENT_RESOLUTION, /*indicates the screen resolution has changed*/
+       GF_EVENT_OPENFILE,
+    /* Events for Keyboad */
+    GF_EVENT_TEXT_EDITING_START,
+    GF_EVENT_TEXT_EDITING_END
+};
+
+/*GPAC/DOM3 key codes*/
+enum {
+       GF_KEY_UNIDENTIFIED = 0,
+       GF_KEY_ACCEPT = 1, /* "Accept"    The Accept (Commit) key.*/
+       GF_KEY_AGAIN, /* "Again"  The Again key.*/
+       GF_KEY_ALLCANDIDATES, /* "AllCandidates"    The All Candidates key.*/
+       GF_KEY_ALPHANUM, /*"Alphanumeric"    The Alphanumeric key.*/
+       GF_KEY_ALT, /*"Alt"    The Alt (Menu) key.*/
+       GF_KEY_ALTGRAPH, /*"AltGraph"    The Alt-Graph key.*/
+       GF_KEY_APPS, /*"Apps"    The Application key.*/
+       GF_KEY_ATTN, /*"Attn"    The ATTN key.*/
+       GF_KEY_BROWSERBACK, /*"BrowserBack"    The Browser Back key.*/
+       GF_KEY_BROWSERFAVORITES, /*"BrowserFavorites"    The Browser Favorites key.*/
+       GF_KEY_BROWSERFORWARD, /*"BrowserForward"    The Browser Forward key.*/
+       GF_KEY_BROWSERHOME, /*"BrowserHome"    The Browser Home key.*/
+       GF_KEY_BROWSERREFRESH, /*"BrowserRefresh"    The Browser Refresh key.*/
+       GF_KEY_BROWSERSEARCH, /*"BrowserSearch"    The Browser Search key.*/
+       GF_KEY_BROWSERSTOP, /*"BrowserStop"    The Browser Stop key.*/
+       GF_KEY_CAPSLOCK, /*"CapsLock"    The Caps Lock (Capital) key.*/
+       GF_KEY_CLEAR, /*"Clear"    The Clear key.*/
+       GF_KEY_CODEINPUT, /*"CodeInput"    The Code Input key.*/
+       GF_KEY_COMPOSE, /*"Compose"    The Compose key.*/
+       GF_KEY_CONTROL, /*"Control"    The Control (Ctrl) key.*/
+       GF_KEY_CRSEL, /*"Crsel"    The Crsel key.*/
+       GF_KEY_CONVERT, /*"Convert"    The Convert key.*/
+       GF_KEY_COPY, /*"Copy"    The Copy key.*/
+       GF_KEY_CUT, /*"Cut"    The Cut key.*/
+       GF_KEY_DOWN, /*"Down"    The Down Arrow key.*/
+       GF_KEY_END, /*"End"    The End key.*/
+       GF_KEY_ENTER, /*"Enter"    The Enter key.
+                   Note: This key identifier is also used for the Return (Macintosh numpad) key.*/
+       GF_KEY_ERASEEOF, /*"EraseEof"    The Erase EOF key.*/
+       GF_KEY_EXECUTE, /*"Execute"    The Execute key.*/
+       GF_KEY_EXSEL, /*"Exsel"    The Exsel key.*/
+       GF_KEY_F1, /*"F1"    The F1 key.*/
+       GF_KEY_F2, /*"F2"    The F2 key.*/
+       GF_KEY_F3, /*"F3"    The F3 key.*/
+       GF_KEY_F4, /*"F4"    The F4 key.*/
+       GF_KEY_F5, /*"F5"    The F5 key.*/
+       GF_KEY_F6, /*"F6"    The F6 key.*/
+       GF_KEY_F7, /*"F7"    The F7 key.*/
+       GF_KEY_F8, /*"F8"    The F8 key.*/
+       GF_KEY_F9, /*"F9"    The F9 key.*/
+       GF_KEY_F10, /*"F10"    The F10 key.*/
+       GF_KEY_F11, /*"F11"    The F11 key.*/
+       GF_KEY_F12, /*"F12"    The F12 key.*/
+       GF_KEY_F13, /*"F13"    The F13 key.*/
+       GF_KEY_F14, /*"F14"    The F14 key.*/
+       GF_KEY_F15, /*"F15"    The F15 key.*/
+       GF_KEY_F16, /*"F16"    The F16 key.*/
+       GF_KEY_F17, /*"F17"    The F17 key.*/
+       GF_KEY_F18, /*"F18"    The F18 key.*/
+       GF_KEY_F19, /*"F19"    The F19 key.*/
+       GF_KEY_F20, /*"F20"    The F20 key.*/
+       GF_KEY_F21, /*"F21"    The F21 key.*/
+       GF_KEY_F22, /*"F22"    The F22 key.*/
+       GF_KEY_F23, /*"F23"    The F23 key.*/
+       GF_KEY_F24, /*"F24"    The F24 key.*/
+       GF_KEY_FINALMODE, /*"FinalMode"    The Final Mode (Final) key used on some asian keyboards.*/
+       GF_KEY_FIND, /*"Find"    The Find key.*/
+       GF_KEY_FULLWIDTH, /*"FullWidth"    The Full-Width Characters key.*/
+       GF_KEY_HALFWIDTH, /*"HalfWidth"    The Half-Width Characters key.*/
+       GF_KEY_HANGULMODE, /*"HangulMode"    The Hangul (Korean characters) Mode key.*/
+       GF_KEY_HANJAMODE, /*"HanjaMode"    The Hanja (Korean characters) Mode key.*/
+       GF_KEY_HELP, /*"Help"    The Help key.*/
+       GF_KEY_HIRAGANA, /*"Hiragana"    The Hiragana (Japanese Kana characters) key.*/
+       GF_KEY_HOME, /*"Home"    The Home key.*/
+       GF_KEY_INSERT, /*"Insert"    The Insert (Ins) key.*/
+       GF_KEY_JAPANESEHIRAGANA, /*"JapaneseHiragana"    The Japanese-Hiragana key.*/
+       GF_KEY_JAPANESEKATAKANA, /*"JapaneseKatakana"    The Japanese-Katakana key.*/
+       GF_KEY_JAPANESEROMAJI, /*"JapaneseRomaji"    The Japanese-Romaji key.*/
+       GF_KEY_JUNJAMODE, /*"JunjaMode"    The Junja Mode key.*/
+       GF_KEY_KANAMODE, /*"KanaMode"    The Kana Mode (Kana Lock) key.*/
+       GF_KEY_KANJIMODE, /*"KanjiMode"    The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key.*/
+       GF_KEY_KATAKANA, /*"Katakana"    The Katakana (Japanese Kana characters) key.*/
+       GF_KEY_LAUNCHAPPLICATION1, /*"LaunchApplication1"    The Start Application One key.*/
+       GF_KEY_LAUNCHAPPLICATION2, /*"LaunchApplication2"    The Start Application Two key.*/
+       GF_KEY_LAUNCHMAIL, /*"LaunchMail"    The Start Mail key.*/
+       GF_KEY_LEFT, /*"Left"    The Left Arrow key.*/
+       GF_KEY_META, /*"Meta"    The Meta key.*/
+       GF_KEY_MEDIANEXTTRACK, /*"MediaNextTrack"    The Media Next Track key.*/
+       GF_KEY_MEDIAPLAYPAUSE, /*"MediaPlayPause"    The Media Play Pause key.*/
+       GF_KEY_MEDIAPREVIOUSTRACK, /*"MediaPreviousTrack"    The Media Previous Track key.*/
+       GF_KEY_MEDIASTOP, /*"MediaStop"    The Media Stok key.*/
+       GF_KEY_MODECHANGE, /*"ModeChange"    The Mode Change key.*/
+       GF_KEY_NONCONVERT, /*"Nonconvert"    The Nonconvert (Don't Convert) key.*/
+       GF_KEY_NUMLOCK, /*"NumLock"    The Num Lock key.*/
+       GF_KEY_PAGEDOWN, /*"PageDown"    The Page Down (Next) key.*/
+       GF_KEY_PAGEUP, /*"PageUp"    The Page Up key.*/
+       GF_KEY_PASTE, /*"Paste"    The Paste key.*/
+       GF_KEY_PAUSE, /*"Pause"    The Pause key.*/
+       GF_KEY_PLAY, /*"Play"    The Play key.*/
+       GF_KEY_PREVIOUSCANDIDATE, /*"PreviousCandidate"    The Previous Candidate function key.*/
+       GF_KEY_PRINTSCREEN, /*"PrintScreen"    The Print Screen (PrintScrn, SnapShot) key.*/
+       GF_KEY_PROCESS, /*"Process"    The Process key.*/
+       GF_KEY_PROPS, /*"Props"    The Props key.*/
+       GF_KEY_RIGHT, /*"Right"    The Right Arrow key.*/
+       GF_KEY_ROMANCHARACTERS, /*"RomanCharacters"    The Roman Characters function key.*/
+       GF_KEY_SCROLL, /*"Scroll"    The Scroll Lock key.*/
+       GF_KEY_SELECT, /*"Select"    The Select key.*/
+       GF_KEY_SELECTMEDIA, /*"SelectMedia"    The Select Media key.*/
+       GF_KEY_SHIFT, /*"Shift"    The Shift key.*/
+       GF_KEY_STOP, /*"Stop"    The Stop key.*/
+       GF_KEY_UP, /*"Up"    The Up Arrow key.*/
+       GF_KEY_UNDO, /*"Undo"    The Undo key.*/
+       GF_KEY_VOLUMEDOWN, /*"VolumeDown"    The Volume Down key.*/
+       GF_KEY_VOLUMEMUTE, /*"VolumeMute"    The Volume Mute key.*/
+       GF_KEY_VOLUMEUP, /*"VolumeUp"    The Volume Up key.*/
+       GF_KEY_WIN, /*"Win"    The Windows Logo key.*/
+       GF_KEY_ZOOM, /*"Zoom"    The Zoom key.*/
+       GF_KEY_BACKSPACE, /*"U+0008"    The Backspace (Back) key.*/
+       GF_KEY_TAB, /*"U+0009"    The Horizontal Tabulation (Tab) key.*/
+       GF_KEY_CANCEL, /*"U+0018"    The Cancel key.*/
+       GF_KEY_ESCAPE, /*"U+001B"    The Escape (Esc) key.*/
+       GF_KEY_SPACE, /*"U+0020"    The Space (Spacebar) key.*/
+       GF_KEY_EXCLAMATION, /*"U+0021"    The Exclamation Mark (Factorial, Bang) key (!).*/
+       GF_KEY_QUOTATION, /*"U+0022"    The Quotation Mark (Quote Double) key (").*/
+       GF_KEY_NUMBER, /*"U+0023"    The Number Sign (Pound Sign, Hash, Crosshatch, Octothorpe) key (#).*/
+       GF_KEY_DOLLAR, /*"U+0024"    The Dollar Sign (milreis, escudo) key ($).*/
+       GF_KEY_AMPERSAND, /*"U+0026"    The Ampersand key (&).*/
+       GF_KEY_APOSTROPHE, /*"U+0027"    The Apostrophe (Apostrophe-Quote, APL Quote) key (').*/
+       GF_KEY_LEFTPARENTHESIS, /*"U+0028"    The Left Parenthesis (Opening Parenthesis) key (().*/
+       GF_KEY_RIGHTPARENTHESIS, /*"U+0029"    The Right Parenthesis (Closing Parenthesis) key ()).*/
+       GF_KEY_STAR, /*"U+002A"    The Asterix (Star) key (*).*/
+       GF_KEY_PLUS, /*"U+002B"    The Plus Sign (Plus) key (+).*/
+       GF_KEY_COMMA, /*"U+002C"    The Comma (decimal separator) sign key (,).*/
+       GF_KEY_HYPHEN, /*"U+002D"    The Hyphen-minus (hyphen or minus sign) key (-).*/
+       GF_KEY_FULLSTOP, /*"U+002E"    The Full Stop (period, dot, decimal point) key (.).*/
+       GF_KEY_SLASH, /*"U+002F"    The Solidus (slash, virgule, shilling) key (/).*/
+       GF_KEY_0, /*"U+0030"    The Digit Zero key (0).*/
+       GF_KEY_1, /*"U+0031"    The Digit One key (1).*/
+       GF_KEY_2, /*"U+0032"    The Digit Two key (2).*/
+       GF_KEY_3, /*"U+0033"    The Digit Three key (3).*/
+       GF_KEY_4, /*"U+0034"    The Digit Four key (4).*/
+       GF_KEY_5, /*"U+0035"    The Digit Five key (5).*/
+       GF_KEY_6, /*"U+0036"    The Digit Six key (6).*/
+       GF_KEY_7, /*"U+0037"    The Digit Seven key (7).*/
+       GF_KEY_8, /*"U+0038"    The Digit Eight key (8).*/
+       GF_KEY_9, /*"U+0039"    The Digit Nine key (9).*/
+       GF_KEY_COLON, /*"U+003A"    The Colon key (:).*/
+       GF_KEY_SEMICOLON, /*"U+003B"    The Semicolon key (;).*/
+       GF_KEY_LESSTHAN, /*"U+003C"    The Less-Than Sign key (<).*/
+       GF_KEY_EQUALS, /*"U+003D"    The Equals Sign key (=).*/
+       GF_KEY_GREATERTHAN, /*"U+003E"    The Greater-Than Sign key (>).*/
+       GF_KEY_QUESTION, /*"U+003F"    The Question Mark key (?).*/
+       GF_KEY_AT, /*"U+0040"    The Commercial At (@) key.*/
+       GF_KEY_A, /*"U+0041"    The Latin Capital Letter A key (A).*/
+       GF_KEY_B, /*"U+0042"    The Latin Capital Letter B key (B).*/
+       GF_KEY_C, /*"U+0043"    The Latin Capital Letter C key (C).*/
+       GF_KEY_D, /*"U+0044"    The Latin Capital Letter D key (D).*/
+       GF_KEY_E, /*"U+0045"    The Latin Capital Letter E key (E).*/
+       GF_KEY_F, /*"U+0046"    The Latin Capital Letter F key (F).*/
+       GF_KEY_G, /*"U+0047"    The Latin Capital Letter G key (G).*/
+       GF_KEY_H, /*"U+0048"    The Latin Capital Letter H key (H).*/
+       GF_KEY_I, /*"U+0049"    The Latin Capital Letter I key (I).*/
+       GF_KEY_J, /*"U+004A"    The Latin Capital Letter J key (J).*/
+       GF_KEY_K, /*"U+004B"    The Latin Capital Letter K key (K).*/
+       GF_KEY_L, /*"U+004C"    The Latin Capital Letter L key (L).*/
+       GF_KEY_M, /*"U+004D"    The Latin Capital Letter M key (M).*/
+       GF_KEY_N, /*"U+004E"    The Latin Capital Letter N key (N).*/
+       GF_KEY_O, /*"U+004F"    The Latin Capital Letter O key (O).*/
+       GF_KEY_P, /*"U+0050"    The Latin Capital Letter P key (P).*/
+       GF_KEY_Q, /*"U+0051"    The Latin Capital Letter Q key (Q).*/
+       GF_KEY_R, /*"U+0052"    The Latin Capital Letter R key (R).*/
+       GF_KEY_S, /*"U+0053"    The Latin Capital Letter S key (S).*/
+       GF_KEY_T, /*"U+0054"    The Latin Capital Letter T key (T).*/
+       GF_KEY_U, /*"U+0055"    The Latin Capital Letter U key (U).*/
+       GF_KEY_V, /*"U+0056"    The Latin Capital Letter V key (V).*/
+       GF_KEY_W, /*"U+0057"    The Latin Capital Letter W key (W).*/
+       GF_KEY_X, /*"U+0058"    The Latin Capital Letter X key (X).*/
+       GF_KEY_Y, /*"U+0059"    The Latin Capital Letter Y key (Y).*/
+       GF_KEY_Z, /*"U+005A"    The Latin Capital Letter Z key (Z).*/
+       GF_KEY_LEFTSQUAREBRACKET, /*"U+005B"    The Left Square Bracket (Opening Square Bracket) key ([).*/
+       GF_KEY_BACKSLASH, /*"U+005C"    The Reverse Solidus (Backslash) key (\).*/
+       GF_KEY_RIGHTSQUAREBRACKET, /*"U+005D"    The Right Square Bracket (Closing Square Bracket) key (]).*/
+       GF_KEY_CIRCUM, /*"U+005E"    The Circumflex Accent key (^).*/
+       GF_KEY_UNDERSCORE, /*"U+005F"    The Low Sign (Spacing Underscore, Underscore) key (_).*/
+       GF_KEY_GRAVEACCENT, /*"U+0060"    The Grave Accent (Back Quote) key (`).*/
+       GF_KEY_LEFTCURLYBRACKET, /*"U+007B"    The Left Curly Bracket (Opening Curly Bracket, Opening Brace, Brace Left) key ({).*/
+       GF_KEY_PIPE, /*"U+007C"    The Vertical Line (Vertical Bar, Pipe) key (|).*/
+       GF_KEY_RIGHTCURLYBRACKET, /*"U+007D"    The Right Curly Bracket (Closing Curly Bracket, Closing Brace, Brace Right) key (}).*/
+       GF_KEY_DEL, /*"U+007F"    The Delete (Del) Key.*/
+       GF_KEY_INVERTEXCLAMATION, /*"U+00A1"    The Inverted Exclamation Mark key (�).*/
+       GF_KEY_DEADGRAVE, /*"U+0300"    The Combining Grave Accent (Greek Varia, Dead Grave) key.*/
+       GF_KEY_DEADEACUTE, /*"U+0301"    The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute) key.*/
+       GF_KEY_DEADCIRCUM, /*"U+0302"    The Combining Circumflex Accent (Hat, Dead Circumflex) key.*/
+       GF_KEY_DEADTILDE, /*"U+0303"    The Combining Tilde (Dead Tilde) key.*/
+       GF_KEY_DEADMACRON, /*"U+0304"    The Combining Macron (Long, Dead Macron) key.*/
+       GF_KEY_DEADBREVE, /*"U+0306"    The Combining Breve (Short, Dead Breve) key.*/
+       GF_KEY_DEADABOVEDOT, /*"U+0307"    The Combining Dot Above (Derivative, Dead Above Dot) key.*/
+       GF_KEY_DEADDIARESIS, /*"U+0308"    The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika, Double Derivative, Dead Diaeresis) key.*/
+       GF_KEY_DEADRINGABOVE, /*"U+030A"    The Combining Ring Above (Dead Above Ring) key.*/
+       GF_KEY_DEADDOUBLEACUTE, /*"U+030B"    The Combining Double Acute Accent (Dead Doubleacute) key.*/
+       GF_KEY_DEADCARON, /*"U+030C"    The Combining Caron (Hacek, V Above, Dead Caron) key.*/
+       GF_KEY_DEADCEDILLA, /*"U+0327"    The Combining Cedilla (Dead Cedilla) key.*/
+       GF_KEY_DEADOGONEK, /*"U+0328"    The Combining Ogonek (Nasal Hook, Dead Ogonek) key.*/
+       GF_KEY_DEADIOTA, /*"U+0345"    The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota Subscript, Dead Iota) key.*/
+       GF_KEY_EURO, /*"U+20AC"    The Euro Currency Sign key (�).*/
+       GF_KEY_DEADVOICESOUND, /*"U+3099"    The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key.*/
+       GF_KEY_DEADSEMIVOICESOUND, /*"U+309A"    The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced Sound) key. */
+       /* STB */
+       GF_KEY_CHANNELUP, /*ChannelUp*/
+       GF_KEY_CHANNELDOWN, /*ChannelDown*/
+       GF_KEY_TEXT, /*Text*/
+       GF_KEY_INFO, /*Info*/
+       GF_KEY_EPG, /*EPG*/
+       GF_KEY_RECORD, /*Record*/
+       GF_KEY_BEGINPAGE, /*BeginPage*/
+    /* end STB */
+
+       /*non-dom keys, used in LASeR*/
+       GF_KEY_CELL_SOFT1,      /*soft1 key of cell phones*/
+       GF_KEY_CELL_SOFT2,      /*soft2 key of cell phones*/
+
+       /*for joystick handling*/
+       GF_KEY_JOYSTICK
+};
+
+
+/*key modifiers state - set by terminal (not set by video driver)*/
+enum
+{
+       GF_KEY_MOD_SHIFT = (1),
+       GF_KEY_MOD_CTRL = (1<<2),
+       GF_KEY_MOD_ALT = (1<<3),
+
+       GF_KEY_EXT_NUMPAD = (1<<4),
+       GF_KEY_EXT_LEFT = (1<<5),
+       GF_KEY_EXT_RIGHT = (1<<6)
+};
+
+/*sensor signaling*/
+enum
+{
+       GF_CURSOR_NORMAL = 0x00,
+       GF_CURSOR_ANCHOR,
+       GF_CURSOR_TOUCH,
+       /*discSensor, cylinderSensor, sphereSensor*/
+       GF_CURSOR_ROTATE,
+       /*proximitySensor & proximitySensor2D*/
+       GF_CURSOR_PROXIMITY,
+       /*planeSensor & planeSensor2D*/
+       GF_CURSOR_PLANE,
+       /*collision*/
+       GF_CURSOR_COLLIDE,
+       GF_CURSOR_HIDE,
+};
+
+/*Mutation AttrChangeType Signaling*/
+enum
+{
+       GF_MUTATION_ATTRCHANGE_MODIFICATION = 0x01,
+       GF_MUTATION_ATTRCHANGE_ADDITION = 0x02,
+       GF_MUTATION_ATTRCHANGE_REMOVAL = 0x03,
+};
+
+enum
+{
+       /*events forwarded from MPEG-2 stack*/
+       GF_EVT_FORWARDED_MPEG2 = 0,
+       /*events forwarded from RTP/RTSP/IP stack (not used yet)*/
+       GF_EVT_FORWARDED_RTP_RTSP
+};
+
+#endif
index b7e897d7e40e6d59b14202bf95c7e3e47f3f9f51..29204271c11d6cf1f9a223f6367645c7e24fa66d 100644 (file)
@@ -136,9 +136,9 @@ struct __tag_bifs_dec
 GF_Node *gf_bifs_dec_node(GF_BifsDecoder * codec, GF_BitStream *bs, u32 NDT_Tag);
 /*decodes an SFField (to get a ptr to the field, use gf_node_get_field )
 the FieldIndex is used for Quantzation*/
-GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field);
+GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com);
 /*decodes a Field (either SF or MF). The field MUST BE EMPTY*/
-GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field);
+GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com);
 /*decodes a route*/
 GF_Err gf_bifs_dec_route(GF_BifsDecoder * codec, GF_BitStream *bs, Bool is_insert);
 /*get name*/
index b3c384d1c38d2be2c1edb48ff045d614d2ed7bd1..e07aae306d19fe327dd3cfc1fada62a622ffc819 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /*
-       DO NOT MOFIFY - File generated on GMT Wed Jul 20 05:50:21 2011
+       DO NOT MOFIFY - File generated on GMT Tue Nov 08 09:10:57 2011
 
        BY MPEG4Gen for GPAC Version 0.4.6-DEV
 */
index f6510f1b5aeeca70614ea10e9ff97179883b6909..c1b6a6e0e8ef823d49cbd5bc635e2ea7da180d35 100644 (file)
@@ -363,7 +363,8 @@ struct __tag_compositor
        /*user rotation angle - ALWAYS CENTERED*/
        Fixed rotation;
 
-       Bool skip_flush;
+       /*0: flush to be done - 1: flush can be skipped - 2: forces flush*/
+       u32 skip_flush;
 #ifndef GPAC_DISABLE_SVG
        u32 num_clicks;
 #endif
@@ -771,6 +772,7 @@ struct _traversing_state
 #ifndef GPAC_DISABLE_SVG
        SVG_Number *parent_use_opacity;
        SVGAllAttributes *parent_anim_atts;
+       Bool parent_is_use;
 
        /*SVG text rendering state*/
        Bool in_svg_text;
@@ -1064,7 +1066,7 @@ void gf_sc_audio_setup(GF_AudioInput *ai, GF_Compositor *sr, GF_Node *node);
 /*unregister interface from renderer/mixer and stops source - deleteing the interface is the caller responsability*/
 void gf_sc_audio_predestroy(GF_AudioInput *ai);
 /*open audio object*/
-GF_Err gf_sc_audio_open(GF_AudioInput *ai, MFURL *url, Double clipBegin, Double clipEnd);
+GF_Err gf_sc_audio_open(GF_AudioInput *ai, MFURL *url, Double clipBegin, Double clipEnd, Bool lock_timeline);
 /*closes audio object*/
 void gf_sc_audio_stop(GF_AudioInput *ai);
 /*restarts audio object (cf note in MediaObj)*/
@@ -1155,6 +1157,7 @@ const char *gf_scene_get_service_url(GF_SceneGraph *sg);
 
 
 Bool gf_scene_is_over(GF_SceneGraph *sg);
+GF_SceneGraph *gf_scene_enum_extra_scene(GF_SceneGraph *sg, u32 *i);
 
 #ifndef GPAC_DISABLE_SVG
 
index b943f14c4cc833abb756bc9b942516d91f6105b2..9949d07cbd06bc8664398e97e1811ef6007996ce 100644 (file)
@@ -30,6 +30,9 @@
 #include <gpac/internal/reedsolomon.h>
 
 
+#ifndef GPAC_DISABLE_MPEG2TS
+
+
 /*INT object*/
 typedef struct
 {
@@ -255,4 +258,7 @@ typedef enum {
 
 void descriptor_PRIVATE (u8 *b, DTAG_SCOPE tag_scope, GF_List * descriptors );
 
+
+#endif //GPAC_DISABLE_MPEG2TS
+
 #endif //_GF_DVB_MPE_DEV_H_
index 03d00404314a37af62cf60bbb8705d7f876b7994..e02a7ee60e05b3e1c77db4fd37c2a9fa479565c6 100644 (file)
@@ -80,7 +80,7 @@ void gf_rtp_reorderer_del(GF_RTPReorder *po);
 void gf_rtp_reorderer_reset(GF_RTPReorder *po);
 
 /*Adds a packet to the queue. Packet Data is memcopied*/
-GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, void *pck, u32 pck_size, u32 pck_seqnum);
+GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, const void * pck, u32 pck_size, u32 pck_seqnum);
 /*gets the output of the queue. Packet Data IS YOURS to delete*/
 void *gf_rtp_reorderer_get(GF_RTPReorder *po, u32 *pck_size);
 
index 9b68c4696703b0e5f2cae831739445b424fdf34b..41fd6bcf072212434978b9a66febfb6d26834641 100644 (file)
@@ -133,6 +133,10 @@ enum
        GF_ISOM_BOX_TYPE_PDIN   = GF_4CC( 'p', 'd', 'i', 'n' ),
        GF_ISOM_BOX_TYPE_SDTP   = GF_4CC( 's', 'd', 't', 'p' ),
 
+       GF_ISOM_BOX_TYPE_SBGP   = GF_4CC( 's', 'b', 'g', 'p' ),
+       GF_ISOM_BOX_TYPE_SGPD   = GF_4CC( 's', 'g', 'p', 'd' ),
+
+
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
        /*Movie Fragments*/
        GF_ISOM_BOX_TYPE_MVEX   = GF_4CC( 'm', 'v', 'e', 'x' ),
@@ -398,6 +402,8 @@ typedef struct
 {
        GF_ISOM_BOX
        GF_EditListBox *editList;
+
+       Bool last_is_empty;
 } GF_EditBox;
 
 
@@ -1085,6 +1091,9 @@ typedef struct
 
        GF_SubSampleInformationBox *SubSamples;
 
+       GF_List *sampleGroups;
+       GF_List *sampleGroupsDescription;
+
        u32 MaxSamplePerChunk;
        u16 groupID;
        u16 trackPriority;
@@ -1525,6 +1534,10 @@ typedef struct
        GF_TrackExtendsBox *trex;
        GF_SampleDependencyTypeBox *sdtp;
        GF_SubSampleInformationBox *subs;
+
+       GF_List *sampleGroups;
+       GF_List *sampleGroupsDescription;
+
        /*when data caching is on*/
        u32 DataCache;
     GF_TFBaseMediaDecodeTimeBox *tfdt;
@@ -1859,8 +1872,9 @@ typedef struct
        Bool reference_type;
        u32 reference_size;
        u32 subsegment_duration;
-       Bool contains_RAP;
-       u32 RAP_delta_time;
+       Bool starts_with_SAP;
+       u32 SAP_type;
+       u32 SAP_delta_time;
 } GF_SIDXReference;
 
 typedef struct __sidx_box
@@ -1876,6 +1890,58 @@ typedef struct __sidx_box
 } GF_SegmentIndexBox;
 #endif
 
+
+
+/***********************************************************
+                       Sample Groups
+***********************************************************/
+typedef struct
+{
+       u32 sample_count;
+       u32 group_description_index;
+} GF_SampleGroupEntry;
+
+typedef struct
+{
+       GF_ISOM_FULL_BOX
+       u32 grouping_type;
+       u32 grouping_type_parameter;
+    
+       u32 entry_count;
+       GF_SampleGroupEntry *sample_entries;
+
+} GF_SampleGroupBox;
+
+typedef struct
+{
+       GF_ISOM_FULL_BOX
+       u32 grouping_type;
+       u32 default_length;
+
+       GF_List *group_descriptions;
+} GF_SampleGroupDescriptionBox;
+
+/*default entry */
+typedef struct
+{
+       u32 length; 
+       u8 *data; 
+} GF_DefaultSampleGroupDescriptionEntry;
+
+/*VisualRandomAccessEntry - 'rap ' type*/
+typedef struct
+{
+       u8 num_leading_samples_known; 
+       u8 num_leading_samples; 
+} GF_VisualRandomAccessEntry;
+
+/*RollRecoveryEntry - 'roll' type*/
+typedef struct
+{
+       s16 roll_distance; 
+} GF_RollRecoveryEntry;
+
+
 /*
                Data Map (media storage) stuff
 */
@@ -2037,6 +2103,11 @@ struct __tag_isom {
        GF_List *moof_list;
        Bool use_segments, moof_first, append_segment;
 
+       /*used when building single-indexed self initializing media segments*/
+       GF_SegmentIndexBox *root_sidx;
+       u64 root_sidx_offset;
+       u32 root_sidx_index;
+
        Bool is_index_segment;
 #endif
 
@@ -2045,13 +2116,14 @@ struct __tag_isom {
 
        /*default track for sync of MPEG4 streams - this is the first accessed stream without OCR info - only set in READ mode*/
        s32 es_id_default_sync;
+
 };
 
 /*time function*/
 u64 gf_isom_get_mp4time();
 /*set the last error of the file. if file is NULL, set the static error (used for IO errors*/
 void gf_isom_set_last_error(GF_ISOFile *the_file, GF_Err error);
-GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing);
+GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progressive_mode);
 GF_ISOFile *gf_isom_new_movie();
 /*Movie and Track access functions*/
 GF_TrackBox *gf_isom_get_track_from_file(GF_ISOFile *the_file, u32 trackNumber);
@@ -2077,7 +2149,7 @@ Bool IsMP4Description(u32 entryType);
 /*Find a reference of a given type*/
 GF_Err Track_FindRef(GF_TrackBox *trak, u32 ReferenceType, GF_TrackReferenceTypeBox **dpnd);
 /*Time and sample*/
-GF_Err GetMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit);
+GF_Err GetMediaTime(GF_TrackBox *trak, Bool force_non_empty, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit);
 GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp, u32 *sampleDescriptionIndex, Bool no_data, u64 *out_offset);
 GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex);
 GF_Err Media_FindSyncSample(GF_SampleTableBox *stbl, u32 searchFromTime, u32 *sampleNumber, u8 mode);
@@ -2099,6 +2171,8 @@ GF_Err stbl_GetSampleDTS_and_Duration(GF_TimeToSampleBox *stts, u32 SampleNumber
 
 /*find a RAP or set the prev / next RAPs if vars are passed*/
 GF_Err stbl_GetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 *IsRAP, u32 *prevRAP, u32 *nextRAP);
+/*same as above but only look for open-gop RAPs and GDR (roll)*/
+GF_Err stbl_SearchSAPs(GF_SampleTableBox *stbl, u32 SampleNumber, u8 *IsRAP, u32 *prevRAP, u32 *nextRAP);
 GF_Err stbl_GetSampleInfos(GF_SampleTableBox *stbl, u32 sampleNumber, u64 *offset, u32 *chunkNumber, u32 *descIndex, u8 *isEdited);
 GF_Err stbl_GetSampleShadow(GF_ShadowSyncBox *stsh, u32 *sampleNumber, u32 *syncNum);
 GF_Err stbl_GetPaddingBits(GF_PaddingBitsBox *padb, u32 SampleNumber, u8 *PadBits);
@@ -2106,6 +2180,7 @@ u32 stbl_GetSampleFragmentCount(GF_SampleFragmentBox *stsf, u32 sampleNumber);
 u32 stbl_GetSampleFragmentSize(GF_SampleFragmentBox *stsf, u32 sampleNumber, u32 FragmentIndex);
 GF_Err stbl_GetSampleDepType(GF_SampleDependencyTypeBox *stbl, u32 SampleNumber, u32 *dependsOn, u32 *dependedOn, u32 *redundant);
 
+
 /*unpack sample2chunk and chunk offset so that we have 1 sample per chunk (edition mode only)*/
 GF_Err stbl_UnpackOffsets(GF_SampleTableBox *stbl);
 GF_Err SetTrackDuration(GF_TrackBox *trak);
@@ -2176,6 +2251,9 @@ GF_Err stbl_RemovePaddingBits(GF_SampleTableBox *stbl, u32 SampleNumber);
 GF_Err stbl_RemoveSampleFragments(GF_SampleTableBox *stbl, u32 sampleNumber);
 GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber);
 
+/*expands sampleGroup table for the given grouping type and sample_number. If sample_number is 0, just appends an entry at the end of the table*/
+GF_Err gf_isom_add_sample_group_entry(GF_List *sampleGroups, u32 sample_number, u32 grouping_type, u32 sampleGroupDescriptionIndex);
+
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
 GF_Err gf_isom_close_fragments(GF_ISOFile *movie);
 #endif
@@ -3357,6 +3435,21 @@ GF_Err rvcc_Size(GF_Box *s);
 GF_Err rvcc_Read(GF_Box *s, GF_BitStream *bs);
 GF_Err rvcc_dump(GF_Box *a, FILE * trace);
 
+
+GF_Box *sbgp_New();
+void sbgp_del(GF_Box *);
+GF_Err sbgp_Write(GF_Box *s, GF_BitStream *bs);
+GF_Err sbgp_Size(GF_Box *s);
+GF_Err sbgp_Read(GF_Box *s, GF_BitStream *bs);
+GF_Err sbgp_dump(GF_Box *a, FILE * trace);
+
+GF_Box *sgpd_New();
+void sgpd_del(GF_Box *);
+GF_Err sgpd_Write(GF_Box *s, GF_BitStream *bs);
+GF_Err sgpd_Size(GF_Box *s);
+GF_Err sgpd_Read(GF_Box *s, GF_BitStream *bs);
+GF_Err sgpd_dump(GF_Box *a, FILE * trace);
+
 #endif /*GPAC_DISABLE_ISOM*/
 
 #ifdef __cplusplus
index aaf37ab63e43f8ca66b405390e0b31b40f87c533..d8709e45fd2ab807cb2bc2dc9e01a66bab374e6f 100644 (file)
@@ -73,6 +73,7 @@ typedef struct s_playList {
     int target_duration;
     int mediaSequenceMin;
     int mediaSequenceMax;
+    int computed_duration;
     char is_ended;
     GF_List * elements;
 } Playlist;
@@ -84,6 +85,7 @@ typedef enum e_playlistElementType  { TYPE_PLAYLIST, TYPE_STREAM, TYPE_UNKNOWN}
  */
 typedef struct s_playlistElement {
     int durationInfo;
+    u64 byteRangeStart, byteRangeEnd;
     int bandwidth;
     char * title;
        char * codecs;
@@ -99,6 +101,7 @@ typedef struct s_program {
     int programId;
     GF_List * bitrates;
     int currentBitrateIndex;
+       int computed_duration;
 } Program;
 
 
@@ -143,7 +146,7 @@ GF_Err program_del(Program * program);
  * This element can be either a playlist of a stream according to first parameter.
  * @return NULL if element could not be created. Element deletion will be deleted recusivly by #playlist_del(Playlist*)
  */
-PlaylistElement * playlist_element_new(PlaylistElementType elementType, const char * url, const char * title, const char *codecs, int durationInfo);
+PlaylistElement * playlist_element_new(PlaylistElementType elementType, const char * url, const char * title, const char *codecs, int durationInfo, u64 byteRangeStart, u64 byteRangeEnd);
 
 /**
  * Creates a new VariantPlaylist
index d48143481fbd34eeb4d9478f6a9d726b59163562..df146917446054b8c11b2c39191ae20654046c5f 100644 (file)
  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  *             
  */
-#ifndef _MPD_IN_H_
-#define _MPD_IN_H_
+#ifndef _MPD_H_
+#define _MPD_H_
 
 #include <gpac/constants.h>
 #include <gpac/xml.h>
 #include <gpac/media_tools.h>
 #include <gpac/internal/terminal_dev.h>
 
-typedef struct
+
+/*TODO*/
+typedef struct 
+{
+       u32 dummy;
+} GF_MPD_Metrics;
+
+/*TODO*/
+typedef struct 
+{
+       u32 dummy;
+} GF_MPD_ContentComponent;
+
+/*TODO*/
+typedef struct 
+{
+       char *scheme_id_uri; /*MANDATORY*/
+       char *value;
+} GF_MPD_Descriptor;
+
+/*TODO*/
+typedef struct 
+{
+       u32 dummy;
+} GF_MPD_Subset;
+
+/*TODO*/
+typedef struct 
+{
+       u32 start_time;
+       u32 duration; /*MANDATORY*/
+       u32 repeat_count;
+} GF_MPD_SegmentTimelineEntry;
+
+typedef struct 
+{
+       GF_List *entries;
+} GF_MPD_SegmentTimeline;
+
+typedef struct 
+{
+       u64 start_range, end_range;
+} GF_MPD_ByteRange;
+
+
+typedef struct 
+{
+    char *URL;
+    char *service_location;
+    GF_MPD_ByteRange *byte_range;
+} GF_MPD_BaseURL;
+
+typedef struct 
+{
+    char *sourceURL;
+    GF_MPD_ByteRange *byte_range;
+} GF_MPD_URL;
+
+typedef struct 
+{
+    u32 num, den;
+} GF_MPD_Fractional;
+
+
+#define GF_MPD_SEGMENT_BASE    \
+       u32 timescale;  \
+       u32 presentation_time_offset;   \
+       u32 index_range;        \
+       Bool index_range_exact; \
+       GF_MPD_URL *initialization_segment;     \
+       GF_MPD_URL *representation_index;       \
+
+
+typedef struct 
 {
-    char *url;
-    Bool use_byterange;
-    u32 byterange_start;
-    u32 byterange_end;
-} GF_MPD_SegmentInfo;
+       GF_MPD_SEGMENT_BASE
+} GF_MPD_SegmentBase;
+
+/*WARNING: duration is expressed in GF_MPD_SEGMENT_BASE@timescale unit*/
+#define GF_MPD_MULTIPLE_SEGMENT_BASE   \
+       GF_MPD_SEGMENT_BASE     \
+       u64 duration;   \
+       u32 start_number;       \
+       GF_MPD_SegmentTimeline *segment_timeline;       \
+       GF_MPD_URL *bitstream_switching_url;    \
+
+typedef struct 
+{
+       GF_MPD_MULTIPLE_SEGMENT_BASE
+} GF_MPD_MultipleSegmentBase;
+
+typedef struct 
+{
+       char *media;
+       GF_MPD_ByteRange *media_range;
+       char *index;
+       GF_MPD_ByteRange *index_range;
+} GF_MPD_SegmentURL;
+
+typedef struct 
+{
+       GF_MPD_MULTIPLE_SEGMENT_BASE    
+       /*list of segments - can be NULL if no segment*/
+       GF_List *segment_URLs;
+} GF_MPD_SegmentList;
+
+typedef struct 
+{
+       GF_MPD_MULTIPLE_SEGMENT_BASE    
+       char *media;
+       char *index;
+       char *initialization;
+       char *bitstream_switching;
+} GF_MPD_SegmentTemplate;
+
+typedef enum
+{
+       GF_MPD_SCANTYPE_UNKNWON,
+       GF_MPD_SCANTYPE_PROGRESSIVE,
+       GF_MPD_SCANTYPE_INTERLACED
+} GF_MPD_ScanType;
+
+/*MANDATORY:
+       mime_type
+       codecs
+*/
+#define GF_MPD_COMMON_ATTRIBUTES_ELEMENTS      \
+       char *profiles; \
+       u32 width;      \
+       u32 height;     \
+       GF_MPD_Fractional *sar; \
+       GF_MPD_Fractional *framerate;   \
+       u32 samplerate; \
+       char *mime_type;        \
+       char *segmentProfiles;  \
+       char *codecs;   \
+       u32 maximum_sap_period; \
+       Bool starts_with_sap;   \
+       Double max_playout_rate;        \
+       Bool coding_dependency; \
+       GF_MPD_ScanType scan_type;      \
+       GF_List *frame_packing; \
+       GF_List *audio_channels;        \
+       GF_List *content_protection;    \
+
 
 typedef struct {
-    char *id;
-    u32 bandwidth;
-    u32 width;
-    u32 height;
-    char *lang;
-    char *mime;
-    u32 groupID;
-    Bool disabled;
-    Bool startWithRap;
-       /* TODO: maximumRAPPeriod */
-       /* TODO: depid*/
-       /* TODO: default rep*/
-
-    u32 qualityRanking;
-    char *content_protection_type;
-    char *content_protection_uri;
-    double alternatePlayoutRate;
-    u32 default_segment_duration;
-       /*TODO: multiple views */
-    char *default_base_url;
-
-    /* initialization segment */
-    char *init_url;
-    Bool init_use_range;
-    u32 init_byterange_start;
-    u32 init_byterange_end;
-    
-    /* other segments */
-    char *url_template;
-    u32 startIndex;
-    u32 endIndex;
-
-       GF_List *segments;
-} GF_MPD_Representation;
+       GF_MPD_COMMON_ATTRIBUTES_ELEMENTS
+} GF_MPD_CommonAttributes;
 
 typedef struct {
-    u32 start; /* expressed in seconds, relative to the start of the MPD */
-       u32 duration; /* TODO */
-       char *id; /* TODO */
-    u8 flags;
-    Bool segment_alignment_flag; /* to be merged into real flags */
-    Bool bitstream_switching_flag;
-
-    u32 default_segment_duration; /* milliseconds */
-    char *default_base_url;
-       /* TODO: default timeline */
-    char *url_template;
-
-       /* TODO: xlink:href & xlink:actuate */
-
-    GF_List *representations;
-       /* TODO: representation groups */
-       /* TODO: subset */
-} GF_MPD_Period;
+       GF_MPD_COMMON_ATTRIBUTES_ELEMENTS
+       
+       u32 level;
+       char *dependecy_level;
+       u32 bandwidth; /*MANDATORY if level set*/
+       char *content_components;
+} GF_MPD_SubRepresentation;
 
-typedef enum {
-    GF_MPD_TYPE_ON_DEMAND,
-    GF_MPD_TYPE_LIVE,
-} GF_MPD_Type;
 
 typedef struct {
-    GF_MPD_Type type;
-    char *base_url;
-       /* TODO: add alternate URL */
-    u32 duration; /* expressed in milliseconds */
-    u32 min_update_time; /* expressed in milliseconds */
-    u32 min_buffer_time; /* expressed in milliseconds */
-    /*start time*/
-    /*end time*/
-    u32 time_shift_buffer_depth; /* expressed in milliseconds */
+       GF_MPD_COMMON_ATTRIBUTES_ELEMENTS
+
+       char *id; /*MANDATORY*/
+    u32 bandwidth; /*MANDATORY*/
+       u32 quality_ranking;
+       char *dependency_id;
+       char *media_stream_structure_id;
+       
+       GF_List *base_URLs;
+       GF_MPD_SegmentBase *segment_base;
+       GF_MPD_SegmentList *segment_list;
+       GF_MPD_SegmentTemplate *segment_template;
+
+       GF_List *sub_representations;
+
+       /*GPAC playback implementation*/
+       Bool disabled;
+
+} GF_MPD_Representation;
+
+
+typedef struct 
+{      
+       GF_MPD_COMMON_ATTRIBUTES_ELEMENTS
+
+       u32 id;
+       /*default value is -1: not set in MPD*/
+       s32 group;
+
+       char *lang;
+       char *content_type;
+       GF_MPD_Fractional *par;
+       u32 min_bandwidth;
+       u32 max_bandwidth;
+       u32 min_width;
+       u32 max_width;
+       u32 min_height;
+       u32 max_height;
+       u32 min_framerate;
+       u32 max_framerate;
+       Bool segment_alignment;
+       Bool bitstream_switching;
+       Bool subsegment_alignment;
+       Bool subsegment_starts_with_sap;
+
+       GF_List *accessibility;
+       GF_List *role;
+       GF_List *rating;
+       GF_List *viewpoint;
+       GF_List *content_component;
+
+       GF_List *base_URLs;
+       GF_MPD_SegmentBase *segment_base;
+       GF_MPD_SegmentList *segment_list;
+       GF_MPD_SegmentTemplate *segment_template;
+
+       GF_List *representations;
+
+} GF_MPD_AdaptationSet;
+
+
+typedef struct 
+{
+       char *ID;
+    u32 start; /* expressed in ms, relative to the start of the MPD */
+       u32 duration; /* expressed in ms*/
+       Bool bitstream_switching;
+
+       GF_List *base_URLs;
+       GF_MPD_SegmentBase *segment_base;
+       GF_MPD_SegmentList *segment_list;
+       GF_MPD_SegmentTemplate *segment_template;
+
+       GF_List *adaptation_sets;
+       GF_List *subsets;
+} GF_MPD_Period;
+
+typedef struct 
+{
+    char *lang;
     char *title;
     char *source;
     char *copyright;
     char *more_info_url;
+} GF_MPD_ProgramInfo;
+
+
+typedef enum {
+    GF_MPD_TYPE_STATIC,
+    GF_MPD_TYPE_DYNAMIC,
+} GF_MPD_Type;
+
+typedef struct {
+    char *ID;
+    char *profiles;    /*MANDATORY*/
+    GF_MPD_Type type;
+       u64 availabilityStartTime; /*MANDATORY if type=dynamic*/
+       u64 availabilityEndTime;
+    u32 media_presentation_duration; /* expressed in milliseconds */   /*MANDATORY if type=static*/
+    u32 minimum_update_period; /* expressed in milliseconds */
+    u32 min_buffer_time; /* expressed in milliseconds */       /*MANDATORY*/
+
+       u32 time_shift_buffer_depth; /* expressed in milliseconds */
+       u32 suggested_presentaton_delay; /* expressed in milliseconds */
+
+       u32 max_segment_duration; /* expressed in milliseconds */
+       u32 max_subsegment_duration; /* expressed in milliseconds */
 
-    /* the number of periods is dynamic since we may update the MPD from time to time, cannot avoid GF_List */
+       /*list of GF_MPD_ProgramInfo */
+       GF_List *program_infos;
+       /*list of GF_MPD_BaseURL */
+       GF_List *base_URLs;
+       /*list of strings */
+       GF_List *locations;
+       /*list of Metrics */
+       GF_List *metrics;
+       /*list of GF_MPD_Period */
     GF_List *periods;
 } GF_MPD;
 
@@ -122,10 +315,10 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *base_url)
 
 GF_MPD *gf_mpd_new();
 void gf_mpd_del(GF_MPD *mpd);
+/*frees a SegmentURL*/
+void gf_mpd_segment_url_free(void *_item);
 
-GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const char *base_url, 
-                                         const char *mpd_file,
-                                         u32 reload_count, char *mimeTypeForM3U8Segments);
+GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, const char *mpd_file, u32 reload_count, char *mimeTypeForM3U8Segments, GF_ClientService *service, Bool do_import, Bool use_mpd_templates);
 
-#endif // _MPD_IN_H_
+#endif // _MPD_H_
 
index 8df8523a5d5f743676b1f85607104ea26c53a2a2..d3718829fbf96af67f3b4abd5a5b2effd9bdb8d6 100644 (file)
@@ -261,7 +261,7 @@ struct __tag_scene_graph
        u32 nb_evts_smil;
        u32 nb_evts_mutation;
        u32 nb_evts_laser;
-       u32 nb_evts_mae;
+       u32 nb_evts_media;
        u32 nb_evts_svg;
        u32 dom_evt_filter;
 
index 6cd64697d2b2cfce10b749529f7323be94d8679e..84d830f0a7e63a94ea3b43780f18ceb7cbe51c98 100644 (file)
@@ -74,6 +74,17 @@ struct _net_service
        /*quick hack for avoiding double session creation*/
        GF_DownloadSession *pending_service_session;
 
+       /*rebuffer window for http/...*/
+       u32 download_rebuffer;
+       Bool auto_rebuffer;
+
+       Bool is_paused;
+
+       /*used by DASH until we rewrite the input module API:
+       if set to 1 during a disconnect() call, the root scene of the service and all sub-objects will be disconnected
+       if set to 2 during a disconnect() call, the call will be skiped
+       */
+       u32 subservice_disconnect;
 };
 
 
@@ -356,10 +367,10 @@ struct _tag_terminal
 
        /*net services*/
        GF_List *net_services;
-       /*net services to be connected*/
-       GF_List *net_services_to_connect;
        /*net services to be destroyed*/
        GF_List *net_services_to_remove;
+       /*connection tasks pending*/
+       GF_List *connection_tasks;
        /*channels waiting for service CONNECT ack to be setup*/
        GF_List *channels_pending;
        /*media objects pending for stop/play*/
@@ -397,6 +408,9 @@ struct _tag_terminal
        GF_Mutex *evt_mx;
        u32 in_event_filter;
 
+       /*ID of the thread currently in handle_services routine, 0 if none*/
+       u32 thread_id_handling_services;
+
        /*static URI relocator for locales*/
        GF_TermLocales locales;
 
@@ -422,8 +436,8 @@ Bool gf_term_forward_event(GF_Terminal *term, GF_Event *evt, Bool consumed, Bool
 
 /*error report function*/
 void gf_term_message(GF_Terminal *app, const char *service, const char *message, GF_Err error);
-/*creates service for given OD / URL*/
-void gf_term_connect_object(GF_Terminal *app, GF_ObjectManager *odm, char *serviceURL, char *parent_url);
+/*posts a request to connect a given object*/
+void gf_term_post_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serviceURL, char *parent_url);
 /*creates service for given channel / URL*/
 GF_Err gf_term_connect_remote_channel(GF_Terminal *app, GF_Channel *ch, char *URL);
 
@@ -438,10 +452,11 @@ void gf_term_close_service(GF_Terminal *app, GF_ClientService *service);
 
 /*locks media quaue*/
 void gf_term_lock_media_queue(GF_Terminal *app, Bool LockIt);
-
 /*locks net manager*/
 void gf_term_lock_net(GF_Terminal *app, Bool LockIt);
 
+/*checks no connection on the ODM are pending - of so, remove them*/
+void gf_term_check_connections_for_delete(GF_Terminal *term, GF_ObjectManager *odm);
 
 /*locks scene compositor*/
 void gf_term_lock_compositor(GF_Terminal *app, Bool LockIt);
@@ -615,6 +630,9 @@ struct _es_channel
        /* used in Carousel, to skip packets until the end of AU */ 
        u8 carousel_type;
        Bool skip_carousel_au;
+
+       /*discard clock initialization when dispatching pending AU - this is used when TS discontinuities / MPA_TIME happen*/
+       Bool skip_time_check_for_pending;
        
        /* TimeStamp to Media Time mapping*/
        /*TS (in TSResolution) corresponding to the SeedTime of the decoder. Delivered by net, otherwise 0*/
@@ -692,6 +710,8 @@ void gf_es_init_dummy(GF_Channel *ch);
 void gf_es_config_drm(GF_Channel *ch, GF_NetComDRMConfig *isma_cryp);
 /*dispatch raw media AU to the composition buffer and BLOCKS until the AU is consumed by the decoder*/
 void gf_es_dispatch_raw_media_au(GF_Channel *ch, char *payload, u32 payload_size, u32 cts);
+/*returns true if this stream owns its clock, false if it simply refers to it*/
+Bool gf_es_owns_clock(GF_Channel *ch);
 
 /*
                decoder stuff
@@ -819,6 +839,9 @@ enum
        
        /*flag set if associated subscene must be regenerated*/
        GF_ODM_REGENERATE_SCENE = (1<<10),
+
+       /*flag set for first play request*/
+       GF_ODM_INITIAL_BROADCAST_PLAY = (1<<11),
 };
 
 enum
@@ -1017,6 +1040,7 @@ Bool gf_term_send_event(GF_Terminal *term, GF_Event *evt);
 
 /*media access events */
 void gf_term_service_media_event(GF_ObjectManager *odm, u32 event_type);
+void gf_term_service_media_event_with_download(GF_ObjectManager *odm, u32 event_type, u64 loaded_size, u64 total_size, u32 bytes_per_sec);
 
 /*checks the URL and returns the ODID (MPEG-4 od://) or GF_MEDIA_EXTERNAL_ID for all regular URLs*/
 u32 gf_mo_get_od_id(MFURL *url);
index 03bf281a69ecfae8ba6e183d5242558d749bbca7..c64d5d77c5eddded3f8942d1ef291eb610698aa9 100644 (file)
@@ -327,6 +327,8 @@ Bool gf_isom_is_JPEG2000(GF_ISOFile *mov);
 
 u64 gf_isom_get_file_size(GF_ISOFile *the_file);
 
+Bool gf_isom_moov_first(GF_ISOFile *movie);
+
 /********************************************************************
                                STREAMING API FUNCTIONS
 ********************************************************************/
@@ -336,11 +338,14 @@ to use for http streaming & co
 NOTE: you must buffer the data to a local file, this mode DOES NOT handle 
 http/ftp/... streaming
 
+start_range and end_range restricts the media byte range in the URL (used by DASH)
+if 0 or end_range<=start_range, the entire URL is used when parsing
+
 BytesMissing is the predicted number of bytes missing for the file to be loaded
 Note that if the file is not optimized for streaming, this number is not accurate
 If the movie is successfully loaded (the_file non-NULL), BytesMissing is zero
 */
-GF_Err gf_isom_open_progressive(const char *fileName, GF_ISOFile **the_file, u64 *BytesMissing);
+GF_Err gf_isom_open_progressive(const char *fileName, u64 start_range, u64 end_range, GF_ISOFile **the_file, u64 *BytesMissing);
 
 /*If requesting a sample fails with error GF_ISOM_INCOMPLETE_FILE, use this function
 to get the number of bytes missing to retrieve the sample*/
@@ -431,8 +436,8 @@ u64 gf_isom_get_media_duration(GF_ISOFile *the_file, u32 trackNumber);
 /*Get the timeScale of the media. */
 u32 gf_isom_get_media_timescale(GF_ISOFile *the_file, u32 trackNumber);
 
-/*return the maximum chunk duration of the track in milliseconds*/
-u32 gf_isom_get_max_chunk_duration(GF_ISOFile *the_file, u32 trackNumber);
+/*gets min, average and max maximum chunk durations (each of them s optional) of the track in media timescale*/
+GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min, u32 *dur_avg, u32 *dur_max, u32 *size_min, u32 *size_avg, u32 *size_max);
 
 /*Get the HandlerDescription name. The outName must be:
                 (outName != NULL && *outName == NULL)
@@ -1054,6 +1059,9 @@ special shortcut for stream description cloning from a given input file (this av
 */
 GF_Err gf_isom_clone_sample_description(GF_ISOFile *the_file, u32 trackNumber, GF_ISOFile *orig_file, u32 orig_track, u32 orig_desc_index, char *URLname, char *URNname, u32 *outDescriptionIndex);
 
+/*clones all sampleDescription entries in new track, after an optional reset of existing entries*/
+GF_Err gf_isom_clone_sample_descriptions(GF_ISOFile *the_file, u32 trackNumber, GF_ISOFile *orig_file, u32 orig_track, Bool reset_existing);
+
 /*special shortcut: clones a track (everything except media data and sample info (DTS? CTS, RAPs, etc...) 
 also clones sampleDescriptions
 @keep_data_ref: if set, external data references are kept, otherwise they are removed (track media data will be self-contained)
@@ -1071,7 +1079,7 @@ GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool cl
 /*returns true if same set of sample description in both tracks - this does include self-contained checking
 and reserved flags. The specific media cfg (DSI & co) is not analysed, only
 a brutal memory comparaison is done*/
-Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, GF_ISOFile *f2, u32 tk2);
+Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, u32 sdesc_index1, GF_ISOFile *f2, u32 tk2, u32 sdesc_index2);
 
 GF_Err gf_isom_set_JPEG2000(GF_ISOFile *mov, Bool set_on);
 
@@ -1079,8 +1087,9 @@ GF_Err gf_isom_set_JPEG2000(GF_ISOFile *mov, Bool set_on);
 If reset_tables is set, sample information for all tracks setup as segment are destroyed. This allows keeping the memory
 footprint low when playing segments. Note however that seeking in the file is then no longer possible*/
 GF_Err gf_isom_release_segment(GF_ISOFile *movie, Bool reset_tables);
-/*opens a new segment file. Access to samples in previous segments is no longer possible*/
-GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName);
+/*opens a new segment file. Access to samples in previous segments is no longer possible
+if end_range>start_range, restricts the URL to the given byterange when parsing*/
+GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName, u64 start_range, u64 end_range);
 
 #ifndef GPAC_DISBALE_ISOM_FRAGMENTS
 
@@ -1133,8 +1142,19 @@ GF_Err gf_isom_setup_track_fragment(GF_ISOFile *the_file, u32 TrackID,
                                                         u8 DefaultSamplePadding,
                                                         u16 DefaultDegradationPriority);
 
-/*flushes data to disk and prepare movie fragmentation*/
-GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file, Bool use_segments);
+/*change the default parameters of an existing trak fragment - should not be used if samples have 
+already been added - semantics are the same as in gf_isom_setup_track_fragment*/
+GF_Err gf_isom_change_track_fragment_defaults(GF_ISOFile *movie, u32 TrackID, 
+                                                        u32 DefaultSampleDescriptionIndex,
+                                                        u32 DefaultSampleDuration,
+                                                        u32 DefaultSampleSize,
+                                                        u8 DefaultSampleIsSync,
+                                                        u8 DefaultSamplePadding,
+                                                        u16 DefaultDegradationPriority);
+
+/*flushes data to disk and prepare movie fragmentation
+@media_segment_type: 0 if no segments, 1 if regular segment, 2 if single segment*/
+GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file, u32 media_segment_type);
 
 /*starts a new movie fragment - if force_cache is set, fragment metadata will be written before
 fragment media data for all tracks*/
@@ -1147,7 +1167,14 @@ GF_Err gf_isom_start_segment(GF_ISOFile *movie, char *SegName);
 GF_Err gf_isom_set_traf_base_media_decode_time(GF_ISOFile *movie, u32 TrackID, u64 decode_time);
 
 /*closes current segment - if fragments_per_sidx is <0, no sidx is used - if fragments_per_sidx is ==0, a single sidx is used*/
-GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 fragments_per_sidx, u32 referenceTrackID, u64 ref_track_decode_time, Bool daisy_chain_sidx, Bool last_segment);
+GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 subsegs_per_sidx, u32 referenceTrackID, u64 ref_track_decode_time, u64 ref_track_next_cts, Bool daisy_chain_sidx, Bool last_segment, u64 *index_start_range, u64 *index_end_range);
+
+/*writes an empty sidx in the current movie. The SIDX will be forced to have nb_segs entries - nb_segs shall match the number of calls to
+gf_isom_close_segment that will follow. This avoids wasting time and disk space moving data around. Once gf_isom_close_segment has then been called nb_segs times, 
+the pre-allocated SIDX is destroyed and sucessive calls to gf_isom_close_segment will create their own sidx (unless gf_isom_allocate_sidx is called again).
+frags_per_sidx, daisy_chain_sidx and frags_per_segment are currently ignored and reserved for future usages where multiple SIDX could be written
+if not NULL, start_range and end_range will contain the byte range of the SIDX box in the movie*/
+GF_Err gf_isom_allocate_sidx(GF_ISOFile *movie, s32 subsegs_per_sidx, Bool daisy_chain_sidx, u32 nb_segs, u32 *frags_per_segment, u32 *start_range, u32 *end_range);
 
 enum
 {
@@ -1194,6 +1221,8 @@ GF_Err gf_isom_fragment_add_sample(GF_ISOFile *the_file, u32 TrackID, GF_ISOSamp
 CANNOT be used with OD tracks*/
 GF_Err gf_isom_fragment_append_data(GF_ISOFile *the_file, u32 TrackID, char *data, u32 data_size, u8 PaddingBits);
 
+void gf_isom_reset_fragment_info(GF_ISOFile *movie);
+
 #endif /*GPAC_DISBALE_ISOM_FRAGMENTS*/
 
 
@@ -1965,7 +1994,8 @@ GF_Err gf_isom_add_subsample(GF_ISOFile *movie, u32 track, u32 sampleNumber, u32
 #endif
 /*add subsample information for the latest sample added to the current track fragment*/
 GF_Err gf_isom_fragment_add_subsample(GF_ISOFile *movie, u32 TrackID, u32 subSampleSize, u8 priority, u32 reserved, Bool discardable);
-/*copy over the subsample information of the given sample from the source track/file to the last sample added to the current track fragment of the destination file*/
+
+/*copy over the subsample and sampleToGroup information of the given sample from the source track/file to the last sample added to the current track fragment of the destination file*/
 GF_Err gf_isom_fragment_copy_subsample(GF_ISOFile *dest, u32 TrackID, GF_ISOFile *orig, u32 track, u32 sampleNumber);
 
 /*gets the number of the next moof to be produced*/
@@ -1973,6 +2003,21 @@ u32 gf_isom_get_next_moof_number(GF_ISOFile *movie);
 /*Sets the number of the next moof to be produced*/
 void gf_isom_set_next_moof_number(GF_ISOFile *movie, u32 value);
 
+
+/*returns 'rap ' and 'roll' group info for the given sample*/
+GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, Bool *is_rap, Bool *has_roll, s32 *roll_distance);
+
+/*sample groups information*/
+#ifndef GPAC_DISABLE_ISOM_WRITE
+/*sets rap flag for sample_number - this is used by non-IDR RAPs in AVC (also in USAC) were SYNC flag (stss table) cannot be used
+num_leading_sample is the number of samples to after this RAP that have dependences on samples before this RAP and hence should be discarded
+- currently sample group info MUST be added in order (no insertion in the tables)*/
+GF_Err gf_isom_set_sample_rap_group(GF_ISOFile *movie, u32 track, u32 sample_number, u32 num_leading_samples);
+/*sets roll_distance info for sample_number (number of frames before (<0) or after (>0) this sample to have a complete refresh of the decoded data (used by GDR in AVC)
+- currently sample group info MUST be added in order (no insertion in the tables)*/
+GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_number, s16 roll_distance);
+#endif
+
 #endif /*GPAC_DISABLE_ISOM*/
 
 #ifdef __cplusplus
index 1b9a8e4a50b1bf79b4517ec2b06b9cb93c70aaed..9187fdcca58a4f6bdea141409a5f2f3f765a483b 100644 (file)
@@ -157,6 +157,15 @@ GF_Err gf_list_rem_last(GF_List *ptr);
  */
 void *gf_list_enum(GF_List *ptr, u32 *pos);
 
+/*!
+ *     \brief list swap
+ *
+ *     Swaps content of two lists
+ *     \param l1 first list object
+ *     \param l2 second list object
+ */
+GF_Err gf_list_swap(GF_List *l1, GF_List *l2);
+
 /*! @} */
 
 #ifdef __cplusplus
index 6316945a36f65f546d651a39cd77430d429494be..3c61046727f34fdb63dca5c6bf4c4a4f76608eee 100644 (file)
@@ -250,6 +250,13 @@ typedef struct __vec2f
  *\return length of the vector
  */
 Fixed gf_v2d_len(GF_Point2D *vec);
+/*!
+ *\brief get distance between 2 points
+ *
+ *Gets the distance between the 2 points
+ *\return distance
+ */
+Fixed gf_v2d_distance(GF_Point2D *a, GF_Point2D *b);
 /*!
  *\brief 2D vector from polar coordinates
  *
index 1f6bb73a0f16c0871a4b0e9133bef6f5e42e148d..8c4a3f36514577c9f5dc93edfb036c1b233dcda6 100644 (file)
@@ -41,6 +41,8 @@ GF_ESD *gf_media_map_esd(GF_ISOFile *mp4, u32 track);
 #endif
 
 
+#define GF_IMPORT_DEFAULT_FPS  25.0
+
 #ifndef GPAC_DISABLE_MEDIA_IMPORT
 
 /*                     
@@ -94,6 +96,9 @@ enum
        /* set subsample information with SVC*/
        GF_IMPORT_SET_SUBSAMPLES = 1<<15,
 
+       /* force to mark non-IDR frmaes with sync data (I slices,) to be marked as sync points points 
+       THE RESULTING FILE IS NOT COMPLIANT*/
+       GF_IMPORT_FORCE_SYNC = 1<<16,
 
        /*when set, only updates tracks info and return*/
        GF_IMPORT_PROBE_ONLY    = 1<<20,
@@ -109,7 +114,8 @@ enum
        GF_IMPORT_DO_ABORT = 1<<31
 };
 
-#define GF_IMPORT_DEFAULT_FPS  25.0
+
+
 #define GF_IMPORT_AUTO_FPS             10000.0
 
 #define GF_IMPORT_MAX_TRACKS   100
@@ -136,6 +142,8 @@ struct __track_import_info
        struct __track_video_info video_info;
        struct __track_audio_info audio_info;
 
+       char szCodecProfile[20];
+
        u32 lang;
        /*for MPEG4 on MPEG-2 TS: mpeg4 ES-ID*/
        u32 mpeg4_es_id;
@@ -219,7 +227,7 @@ GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import
 
 /*save file as fragmented movie
 @dash_mode: 0 = DASH not used, 1 = DASH used without GOP spliting, 2 = DASH used with GOP spliting, */
-GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 fragments_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, const char *dash_ctx);
+GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file_radical, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool use_single_segment, const char *dash_ctx, GF_ISOFile *sample_descs, u32 rep_id);
 
 /*make the file ISMA compliant: creates ISMA BIFS / OD tracks if needed, and update audio/video IDs
 the file should not contain more than one audio and one video track
@@ -383,6 +391,9 @@ if force_end_of_session is set, this flushes the SAF Session - no more operation
 GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, char **out_data, u32 *out_size);
 
 
+GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, char *init_segment, Double period_duration);
+GF_Err gf_media_mpd_end(char *mpd_name);
+
 #ifdef __cplusplus
 }
 #endif
index 897edf5eccf81c2ef3fd5970c9df79a1e6d6ed71..fd330eba5c2549f899a6751319513867bf9ba713 100644 (file)
@@ -119,8 +119,9 @@ Bool gf_mo_get_audio_info(GF_MediaObject *mo, u32 *sample_rate, u32 *bits_per_sa
 
 Fixed gf_mo_get_current_speed(GF_MediaObject *mo);
 
-/*checks if the service associated withthis object has an audio stream*/
-Bool gf_mo_has_audio(GF_MediaObject *mo);
+/*checks if the service associated withthis object has an audio stream
+returns 0 if no audio is associated, 1 if there is an audio object associated, 2 if the service is not yet ready (not connected)*/
+u32 gf_mo_has_audio(GF_MediaObject *mo);
 
 /*checks if the service associated withthis object has an audio stream*/
 Bool gf_mo_is_private_media(GF_MediaObject *mo);
index fb74d093c8091bb10634ab6cb501bf058364f506..bff5805d4071f839929856a03afbc9289aa9cfa0 100644 (file)
@@ -100,6 +100,9 @@ typedef enum
 
        /*When using DASH or playlists, query the next file to concatenate to thecurrent one net->proxy only*/
        GF_NET_SERVICE_QUERY_NEXT,
+       /*When using DASH, query the media range of the url passed in COnnectService - this is only used for local 
+       playback/validation of DASH sequences*/
+       GF_NET_SERVICE_QUERY_INIT_RANGE,
 } GF_NET_CHAN_CMD;
 
 /*channel command for all commands that don't need params:
@@ -123,6 +126,9 @@ typedef struct
        Double start_range, end_range;
        /*params for GF_NET_CHAN_PLAY and GF_NET_CHAN_SPEED*/
        Double speed;
+       Bool dash_segment_switch;
+       /*indicates theis is the first PLAY on an elemnt inserted from bcast*/
+       Bool initial_broadcast_play;
 } GF_NetComPlay;
 
 
@@ -307,6 +313,15 @@ typedef struct
        u32 command_type;
        /*out: next url to play after current one*/
        const char *next_url;
+       /*out: range in given URL to be played - usually 0-0 as segments are downloaded to cache
+       but can be non-zero when playing local files*/
+       u64 start_range, end_range;
+       /*indicates discontinuity type at segment switch:
+               0: no discontinuity (eg, follow-up of previous segment
+               1: segment switch discontinuity (eg, bitrate/codec change)
+               2: time discontinuity - seeking has occured and some segments were skipped
+       */
+       u32 discontinuity_type;
 } GF_NetURLQuery;
 
 /*GF_NET_SERVICE_QUALITY_SWITCH*/
index 787a542fbd018a0da18558a41b20e28bb811758e..9bc29fad19a435879d514dc8a14f753ebb29288b 100644 (file)
@@ -498,7 +498,7 @@ typedef struct {
        /*input stream format (not required, guessed from file_name)*/
        char *streamFormat;
        /*time offset in ms from first TS (appends an edit list in mp4)*/
-       u32 startTime;
+       s32 startTime;
 
        /*media length to import in ms (from 0)*/
        u32 duration;
index f119b12ad64461004bc8a5d482afdff0a14252c8..542d5635dfb4352d04b39c462444d1ada201c461 100644 (file)
@@ -190,6 +190,8 @@ enum
        GF_M2TS_EVT_CAT_UPDATE,
        /*AIT has been found (carousel) */
        GF_M2TS_EVT_AIT_FOUND,
+       /*DSCM-CC has been found (carousel) */
+       GF_M2TS_EVT_DSMCC_FOUND,
 
 };
 
@@ -256,6 +258,9 @@ typedef struct GF_M2TS_SectionFilter
           not parsed by the TS demuxer and left for the application  */
        Bool direct_dispatch;
 
+       /* this field is used for AIT sections, to link the AIT with the program */
+       u32 service_id;
+
        gf_m2ts_section_callback process_section; 
 } GF_M2TS_SectionFilter;
 
@@ -313,6 +318,9 @@ enum
        GF_M2TS_ES_SEND_REPEATED_SECTIONS = 1<<16,
        /*Flag used by importers*/
        GF_M2TS_ES_FIRST_DTS = 1<<17,
+
+       /*flag used to signal next discontinuity on stream should be ignored*/
+       GF_M2TS_ES_IGNORE_NEXT_DISCONTINUITY = 1<<18
 };
 
 /*Abstract Section/PES stream object, only used for type casting*/
@@ -325,11 +333,12 @@ enum
                        GF_SLConfig *slcfg; \
                        s16 component_tag; \
                        void *user; \
-                       u64 first_dts;
+                       u64 first_dts; \
+                       u32 service_id;
 
 struct tag_m2ts_es
 {
-       ABSTRACT_ES
+       ABSTRACT_ES     
 };
 
 
@@ -375,7 +384,7 @@ typedef struct tag_m2ts_pes
        u32 lang;
 
        /*object info*/
-       u32 vid_w, vid_h, vid_par, aud_sr, aud_nb_ch;
+       u32 vid_w, vid_h, vid_par, aud_sr, aud_nb_ch, aud_obj_type;
        /*user private*/
 
 
@@ -406,12 +415,15 @@ typedef struct tag_m2ts_pes
 
 
        /*PES reframer - if NULL, pes processing is skiped*/
-       u32 frame_state;
        /*returns the number of bytes NOT consummed from the input data buffer - these bytes are kept when reassembling the next PES packet*/
-       u32 (*reframe)(struct tag_m2ts_demux *ts, struct tag_m2ts_pes *pes, u64 DTS, u64 CTS, unsigned char *data, u32 data_len);
+       u32 (*reframe)(struct tag_m2ts_demux *ts, struct tag_m2ts_pes *pes, Bool same_pts, unsigned char *data, u32 data_len);
+
+       /*used by several reframers to store their parsing state*/
+       u32 frame_state;
        /*LATM stuff - should be moved out of mpegts*/
        unsigned char *buf;
        u32 buf_len;
+       u64 prev_PTS;
 
        GF_M2TS_DVB_Subtitling_Descriptor sub;
 } GF_M2TS_PES;
@@ -570,6 +582,7 @@ struct tag_m2ts_demux
        char filename[GF_MAX_PATH];
        u32 start_range, end_range;
        u64 file_size;
+       u64 start_byterange, end_byterange;
        Double duration;
        u32 nb_playing;
        Bool file_regulate;
@@ -589,6 +602,7 @@ struct tag_m2ts_demux
        GF_List *programs;
        u32 nb_prog_pmt_received;
        Bool all_prog_pmt_received;
+       Bool all_prog_processed;
        /*keep it seperate for now - TODO check if we're sure of the order*/
        GF_List *SDTs;
        GF_M2TS_TDT_TOT *TDT_time; /*UTC time from both TDT and TOT (we currently ignore local offset)*/
@@ -624,8 +638,18 @@ struct tag_m2ts_demux
 
        const char *dvb_channels_conf_path;
 
-       const char *(*query_next)(void *udta);
-       void *udta_query;
+       /*for DASH*/
+       GF_Err (*query_next)(void *udta, Bool query_init_range, const char **next_url, u64 *next_start_range, u64 *next_end_range);
+       void *query_udta;
+       Bool segment_switch;
+
+       /*AIT*/
+       GF_List* ChannelAppList;
+
+       /*Carousel*/    
+       Bool process_dmscc;
+       char* dsmcc_root_dir;
+       GF_List* dsmcc_controler;
 };
 
 GF_M2TS_Demuxer *gf_m2ts_demux_new();
@@ -635,6 +659,7 @@ GF_ESD *gf_m2ts_get_esd(GF_M2TS_ES *es);
 GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode);
 GF_Err gf_m2ts_process_data(GF_M2TS_Demuxer *ts, char *data, u32 data_size);
 u32 gf_dvb_get_freq_from_url(const char *channels_config_path, const char *url);
+void gf_m2ts_demux_dmscc_init(GF_M2TS_Demuxer *ts);
 
 
 
@@ -712,8 +737,7 @@ enum
        GF_M2TS_DVB_TIME_SLICE_FEC_DESCRIPTOR              = 0x77,
        /* ... */
        GF_M2TS_DVB_EAC3_DESCRIPTOR                             = 0x7A,
-       GF_M2TS_DVB_LOGICAL_CHANNEL_DESCRIPTOR = 0x83,  
-       
+       GF_M2TS_DVB_LOGICAL_CHANNEL_DESCRIPTOR = 0x83,          
 };
 
 /* Reserved PID values */
@@ -748,7 +772,11 @@ enum {
        GF_M2TS_TABLE_ID_IPMP_CONTROL   = 0x07, 
        /* 0x08 - 0x37 reserved */
        /* 0x38 - 0x3D DSM-CC defined */
-       GF_M2TS_TABLE_ID_DSM_CC_PRIVATE = 0x3E, /* used for MPE (only, not MPE-FEC) */
+       GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA               = 0x3A, 
+       GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE                              = 0x3B, /* used for MPE (only, not MPE-FEC) */
+       GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE   = 0x3C, /* used for MPE (only, not MPE-FEC) */
+       GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION              = 0x3D, /* used for MPE (only, not MPE-FEC) */
+       GF_M2TS_TABLE_ID_DSM_CC_PRIVATE                                 = 0x3E, /* used for MPE (only, not MPE-FEC) */
        /* 0x3F DSM-CC defined */
        GF_M2TS_TABLE_ID_NIT_ACTUAL             = 0x40, /* max size for section 1024 */
        GF_M2TS_TABLE_ID_NIT_OTHER              = 0x41,
@@ -912,6 +940,9 @@ typedef struct __m2ts_mux_stream {
        Bool table_needs_update;
        Bool table_needs_send;
 
+       /*minimal amount of bytes we are allowed to copy frome next AU in the current PES. If no more than this 
+       is available in PES, don't copy from next*/
+       u32 min_bytes_copy_from_next;
        /*process PES or table update/framing
        returns the priority of the stream,  0 meaning not scheduled, 1->N highest priority sent first*/
        u32 (*process)(struct __m2ts_mux *muxer, struct __m2ts_mux_stream *stream);
@@ -934,6 +965,8 @@ typedef struct __m2ts_mux_stream {
 
        u32 reframe_overhead;
 
+       Bool start_pes_at_rap, prevent_two_au_start_in_pes;
+
        struct __elementary_stream_ifce *ifce;
        Double ts_scale;
 
@@ -995,6 +1028,13 @@ struct __m2ts_mux_program {
        GF_List *loop_descriptors;
        Bool mpeg4_signaling;
        Bool mpeg4_signaling_for_scene_only;
+
+       /*
+               1: signals to force pat/pmt after current PES
+               2: forces pat to be sent 
+               3: forces pmt to be sent after PAT
+       */
+       u32 force_pat_pmt_state;
 };
 
 struct __m2ts_mux {
@@ -1031,11 +1071,13 @@ struct __m2ts_mux {
     /* System time when the muxer is started */
     u32 init_sys_time;
 
+       Bool force_pat;
+
        Bool one_au_per_pes;
 
        Bool eos_found;
        u32 pck_sent_over_br_window, last_br_time, avg_br;
-       u64 tot_pck_sent, tot_pad_sent;
+       u64 tot_pck_sent, tot_pad_sent, tot_pes_pad_bytes;
 };
 
 
@@ -1075,8 +1117,8 @@ GF_Err gf_m2ts_program_stream_update_ts_scale(GF_ESInterface *_self, u32 time_sc
 #endif /*GPAC_DISABLE_MPEG2TS_MUX*/
 
 /******************* Demux DVB ****************************/
-#include <gpac/carousel.h>
-
+#include <gpac/ait.h>
+#include <gpac/dsmcc.h>
 
 #define UDP_BUFFER_SIZE        0x40000
 #define M2TS_BUFFER_MAX 400
index 04640a8060c4a510e47d1f2e2e533317e44b5df6..7652b0f3068f3956ea6bfa61da3d71d28d11926f 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /*
-       DO NOT MOFIFY - File generated on GMT Wed Jul 20 05:50:21 2011
+       DO NOT MOFIFY - File generated on GMT Tue Nov 08 09:10:57 2011
 
        BY MPEG4Gen for GPAC Version 0.4.6-DEV
 */
@@ -2115,6 +2115,8 @@ typedef struct _tagBitWrapper
        SFInt32 type;   /*field*/
        MFURL url;      /*field*/
        SFString buffer;        /*field*/
+       /*GPAC private*/
+       u32 buffer_len;
 } M_BitWrapper;
 
 
index a27fa1b8642f1ffd12a8e9f454d9d46876c3ae19..ed767f60f5028e7f7bed254127109c7ea984ee6a 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
 #endif
 
 #include <gpac/math.h>
-#include <gpac/constants.h>
+#include <gpac/tools.h>
 
 
 /*!
index 3539980b8c2aecfb089f501dd0dab5d5fa9c30cf..7d933dca62ca207f0fbf308e2fde0211f02f0bdd 100644 (file)
@@ -569,6 +569,10 @@ enum
        GF_JSAPI_OP_PAUSE_SVG,
        /*!resumes an SVG ELEMENT*/
        GF_JSAPI_OP_RESUME_SVG,
+       /*!restarts an SVG ELEMENT: this restarts all the media tunning on the main timeline*/
+       GF_JSAPI_OP_RESTART_SVG,
+       /*!sets scene speed*/
+       GF_JSAPI_OP_SET_SCENE_SPEED,
        /*!gets the DPI*/
        GF_JSAPI_OP_GET_DPI_X,
        GF_JSAPI_OP_GET_DPI_Y,
index 3811286f09b692754b325f674d2bae761f147680..168fc06fce7d920745638ad19b2cabb5fe4a01c3 100644 (file)
@@ -241,9 +241,8 @@ typedef struct
        Fixed remaining_time;
        u16 status;
        const char *session_name;
-       u32 nb_streams;
-       struct mae_item {u32 streamType; u32 mediaType; u32 transport; } streams[20];
-} GF_DOMMediaAccessEvent;
+       u64 loaded_size, total_size;
+} GF_DOMMediaEvent;
 
 /* 
        DOM event handling
@@ -334,7 +333,8 @@ typedef struct
 
        /*DOM event used in VRML (GPAC's internal)*/
        Bool is_vrml;
-       GF_DOMMediaAccessEvent *mae;
+       /*media event*/
+       GF_DOMMediaEvent *media_event;
 
        /*number of listeners triggered by the event*/
        u32 consumed;
@@ -405,8 +405,12 @@ enum
        GF_DOM_EVENT_SMIL = 1<<8,
        /*LASeR events*/
        GF_DOM_EVENT_LASER = 1<<9,
+       /*HTML Media events*/
+       GF_DOM_EVENT_MEDIA = 1<<10,
+#if 0
        /*MediaAccess events*/
-       GF_DOM_EVENT_MEDIA_ACCESS = 1<<10,
+       GF_DOM_EVENT_MEDIA_ACCESS = 1<<11,
+#endif
 
        /*fake events - these events are NEVER fired*/
        GF_DOM_EVENT_FAKE = 1<<31,
@@ -625,6 +629,7 @@ void gf_svg_flatten_attributes(SVG_Element *e, SVGAllAttributes *all_atts);
 const char *gf_svg_get_attribute_name(GF_Node *elt, u32 tag);
 u32 gf_svg_apply_inheritance(SVGAllAttributes *all_atts, SVGPropertiesPointers *render_svg_props) ;
 
+/*creates a DOMAttribute for the given tag - THE ATTRIOBUTE IS NOT ADDED TO THE NODE'S ATTRIBUTES*/
 GF_DOMAttribute *gf_xml_create_attribute(GF_Node *node, u32 tag);
 u32 gf_xml_get_attribute_type(u32 tag);
 u32 gf_xml_get_attribute_tag(GF_Node *node, char *attribute_name, u32 ns);
index 3fbe32d5590e355d0c11c0c02beb7117202b3fbe..437f8dd698034123691b1bab7c840e530eb82d0a 100644 (file)
@@ -345,7 +345,7 @@ void gf_memory_print(void); /*prints the state of current allocations*/
 
 /*end GPAC memory tracking*/
 
-#if (defined (WIN32) || defined (_WIN32_WCE)) && !defined(__GNUC__)
+#if (defined (WIN32) || defined (_WIN32_WCE)) && (defined(__MINGW32__) || !defined(__GNUC__))
 
 #define LLD "%I64d"
 #define LLU "%I64u"
index cfd5c0b21f45df6a7be3ea4434be312345bf25e4..9e3ccb7a9a4cefddf3c1272647720d56a8d9be23 100644 (file)
@@ -139,8 +139,10 @@ GF_Err gf_term_paste_text(GF_Terminal *term, const char *txt, Bool probe_only);
 
 /*decodes pending media and render frame. 
 NOTE: This can only be used when the terminal runs without visual thread (GF_TERM_NO_VISUAL_THREAD flag set)
+returns estimated time left until next frame should be drawn. If GF_TERM_NO_REGULATION is not set, the function will sleep
+for until next frame should be drawn before returning.
 */
-GF_Err gf_term_process_step(GF_Terminal *term);
+u32 gf_term_process_step(GF_Terminal *term);
 
 /*decodes all pending media and render frame until no scene changes are detected.
 NOTE: This can only be used when the terminal runs without visual thread (GF_TERM_NO_VISUAL_THREAD flag set)
@@ -165,7 +167,7 @@ void gf_term_mouse_input(GF_Terminal *term, GF_EventMouse *event);
        @isKeyUp: set if key is released
 */
 /*NOT NEEDED WHEN THE TERMINAL IS HANDLING THE DISPLAY WINDOW (cf user.h)*/
-void gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool isKeyUp);
+Bool gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool isKeyUp);
 
 /*post extended user character interaction to terminal 
        @character: unicode character input
index 0786530195bded38eb7a4d15bdac5a47704e7e9a..0dddee65d2184cb4a6acc80daf74a6fa501b809b 100644 (file)
@@ -216,6 +216,14 @@ void gf_mx_v(GF_Mutex *mx);
 */
 Bool gf_mx_try_lock(GF_Mutex *mx);
 
+/*
+ *\brief get mutex number of locks
+ *
+ *Returns the number of locks on the mutex if the caller thread is holding the mutex. 
+ *\param mx the mutex object
+ *\return -1 if the mutex is not hold by the calling thread, or the number of locks (possibly 0) otherwise.
+ */
+s32 gf_mx_get_num_locks(GF_Mutex *mx);
 
 /*********************************************************************
                                        Semaphore Object
index abc0f095f9b4a9fff0e2f4d9c5efce4b2bccf89e..72b24600547a2394a4741ed20669564cb2b26d89 100644 (file)
@@ -93,8 +93,9 @@ extern "C" {
  *
  *     Macro formating a 4-character code (or 4CC) "abcd" as 0xAABBCCDD
 */
+#ifndef GF_4CC
 #define GF_4CC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
-
+#endif
 
 /*!
  *     \brief GPAC feature list
@@ -118,6 +119,16 @@ const char *gf_4cc_to_str(u32 type);
 */
 int gf_asprintf(char **buffer, const char *fmt, ...);
 
+/*!
+ *     \brief file writing helper
+ *
+ *     Wrapper to properly handle calls to fwrite()
+ *     Ensures proper error handling is invoked when it fails.
+ *     \return Same as gf_fwrite
+ *
+*/
+size_t gf_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+
 /*!
  *     \brief large file opening
  *
@@ -170,7 +181,7 @@ u64 gf_f64_seek(FILE *f, s64 pos, s32 whence);
 typedef enum
 {
        /*!Message from any scripting engine used in the presentation (ECMAScript, MPEG-J, ...) (Info).*/
-       GF_SCRIPT_INFO                                          = 3,
+       GF_SCRIPT_INFO                                          = 3,
        /*!Indicates an data frame has several AU packed (not MPEG-4 compliant). This is used by decoders to force
        multiple decoding of the same data frame (Info).*/
        GF_PACKED_FRAMES                                        = 2,
@@ -277,8 +288,10 @@ const char *gf_error_to_string(GF_Err e);
  */
 enum
 {
+       /*! Disable all Log message*/
+       GF_LOG_QUIET = 0,
        /*! Log message describes an error*/
-       GF_LOG_ERROR = 1,
+       GF_LOG_ERROR,
        /*! Log message describes a warning*/
        GF_LOG_WARNING,
        /*! Log message is informational (state, etc..)*/
@@ -287,15 +300,6 @@ enum
        GF_LOG_DEBUG
 };
 
-/*!
- *     \brief Log level assignment
- *
- * Sets the level used for log filtering. By default no log is performed
- *     \param level log level used.
- *
- */
-void gf_log_set_level(u32 level);
-
 /*!
  *     \brief Log exits at first error assignment
  *
@@ -305,6 +309,14 @@ void gf_log_set_level(u32 level);
  */
 void gf_log_set_strict_error(Bool strict);
 
+/*!
+ *     \brief gets string-formated log tools
+ *
+ * Returns the string-formatted log tools and levels. Returned string shall be freed by the caller.
+ *     \return string-formatted log tools.
+ *
+ */
+char *gf_log_get_tools_levels();
 
 /*!
  * GPAC Log tools
@@ -315,61 +327,66 @@ void gf_log_set_strict_error(Bool strict);
 enum
 {
        /*! Log message from the core library (init, threads, network calls, etc)*/
-       GF_LOG_CORE = 1,
+       GF_LOG_CORE = 0,
        /*! Log message from a raw media parser (BIFS, LASeR, A/V formats)*/
-       GF_LOG_CODING= 1<<1,
+       GF_LOG_CODING,
        /*! Log message from a bitstream parser (IsoMedia, MPEG-2 TS, OGG, ...)*/
-       GF_LOG_CONTAINER = 1<<2,
+       GF_LOG_CONTAINER,
        /*! Log message from the network/service stack (messages & co)*/
-       GF_LOG_NETWORK = 1<<3,
+       GF_LOG_NETWORK,
        /*! Log message from the RTP/RTCP stack (TS info) and packet structure & hinting (debug)*/
-       GF_LOG_RTP = 1<<4,
+       GF_LOG_RTP,
        /*! Log message from authoring subsystem (file manip, import/export)*/
-       GF_LOG_AUTHOR = 1<<5,
+       GF_LOG_AUTHOR,
        /*! Log message from the sync layer of the terminal*/
-       GF_LOG_SYNC = 1<<6,
+       GF_LOG_SYNC,
        /*! Log message from a codec*/
-       GF_LOG_CODEC = 1<<7,
+       GF_LOG_CODEC,
        /*! Log message from any XML parser (context loading, etc)*/
-       GF_LOG_PARSER = 1<<8,
+       GF_LOG_PARSER,
        /*! Log message from the terminal/compositor, indicating media object state*/
-       GF_LOG_MEDIA = 1<<9,
+       GF_LOG_MEDIA,
        /*! Log message from the scene graph/scene manager (handling of nodes and attribute modif, DOM core)*/
-       GF_LOG_SCENE = 1<<10,
-       /*! Log message from the scripting engine*/
-       GF_LOG_SCRIPT = 1<<11,
+       GF_LOG_SCENE,
+       /*! Log message from the scripting engine APIs - does not cover alert() in the script code itself*/
+       GF_LOG_SCRIPT,
        /*! Log message from event handling*/
-       GF_LOG_INTERACT = 1<<12,
+       GF_LOG_INTERACT,
        /*! Log message from compositor*/
-       GF_LOG_COMPOSE = 1<<13,
+       GF_LOG_COMPOSE,
        /*! Log for video object cache */
-       GF_LOG_CACHE = 1<<14,
+       GF_LOG_CACHE,
        /*! Log message from multimedia I/O devices (audio/video input/output, ...)*/
-       GF_LOG_MMIO = 1<<15,
+       GF_LOG_MMIO,
        /*! Log for runtime info (times, memory, CPU usage)*/
-       GF_LOG_RTI = 1<<16,
+       GF_LOG_RTI,
        /*! Log for SMIL timing and animation*/
-       GF_LOG_SMIL = 1<<17,
+       GF_LOG_SMIL,
        /*! Log for memory tracker*/
-       GF_LOG_MEMORY = 1<<18,
+       GF_LOG_MEMORY,
        /*! Log for audio compositor*/
-       GF_LOG_AUDIO = 1<<19,
-       /*! generic Log for modules*/
-       GF_LOG_MODULE = 1<<20,
-       /*! log for threads and mutexes */
-    GF_LOG_MUTEX = 1<<21,
-       /*! All logs*/
-       GF_LOG_ALL = (1<<22)-1
+       GF_LOG_AUDIO,
+       /*! Generic Log for modules*/
+       GF_LOG_MODULE,
+       /*! Log for threads and mutexes */
+       GF_LOG_MUTEX,
+       /*! Log for all messages coming from GF_Terminal or script alert()*/
+       GF_LOG_CONSOLE,
+
+       /*! special value used to set a level for all tools*/
+       GF_LOG_ALL,
+       GF_LOG_TOOL_MAX = GF_LOG_ALL,
 };
 
 /*!
  *     \brief Log modules assignment
  *
- * Sets the modules to be checked for log filtering. By default no modules are logged.
- *     \param tools log tools filtered. This is an OR'ed combinaison of log module flags
+ * Sets the tools to be checked for log filtering. By default no logging is performed.
+ *     \param tool tool to be logged.
+ *     \param level level of logging for this tool.
  *
  */
-void gf_log_set_tools(u32 tools);
+void gf_log_set_tool_level(u32 tool, u32 level);
 
 /*!
  *     \brief Log Message Callback
@@ -394,10 +411,10 @@ typedef void (*gf_log_cbk)(void *cbck, u32 log_level, u32 log_tool, const char*
 */
 gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk);
 
+
 /*!
  \cond DUMMY_DOXY_SECTION
 */
-
 #ifndef GPAC_DISABLE_LOG
 /*note:
                to turn log on, change to GPAC_ENABLE_LOG
@@ -416,11 +433,43 @@ gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk);
 void gf_log(const char *fmt, ...);
 void gf_log_lt(u32 ll, u32 lt);
 
-u32 gf_log_get_level();
-u32 gf_log_get_tools();
 
-u32 gf_log_parse_level(const char *val);
-u32 gf_log_parse_tools(const char *val);
+/*!
+ *     \brief Log level checking
+ *
+ *     Checks if a given tool is logged for the given level
+ *     \param log_tool tool to check
+ *     \param log_level level to check
+ *     \return 1 if logged, 0 otherwise
+*/
+Bool gf_log_tool_level_on(u32 log_tool, u32 log_level);
+
+/*!
+ *     \brief Set log tools and levels
+ *
+ *     Set log tools and levels according to the log_tools_levels string. All previous log settings are discarded.
+ *     \param log_tools_levels string specifying the tools and levels. It is formatted as logToolX@logLevelX:logToolZ@logLevelZ:... 
+ *     \return GF_OK or GF_BAD_PARAM
+*/
+GF_Err gf_log_set_tools_levels(const char *log_tools_levels);
+
+/*!
+ *     \brief Modify log tools and levels
+ *
+ *     Modify log tools and levels according to the log_tools_levels string. Previous log settings are kept.
+ *     \param log_tools_levels string specifying the tools and levels. It is formatted as logToolX@logLevelX:logToolZ@logLevelZ:... 
+ *     \return GF_OK or GF_BAD_PARAM
+*/
+GF_Err gf_log_modify_tools_levels(const char *val);
+
+/*!
+ *     \brief Set log level for a given tool
+ *
+ *     Set log level for a given tool.
+ *     \param tool tool to log
+ *     \param level log level for this tool
+*/
+void gf_log_set_tool_level(u32 tool, u32 level);
 
 #ifdef GPAC_DISABLE_LOG
 #define GF_LOG(_ll, _lm, __args)
@@ -431,7 +480,7 @@ u32 gf_log_parse_tools(const char *val);
  *
  *     Macro for logging messages. Usage is GF_LOG(log_lev, log_module, (fmt, ...)). The log function is only called if log filtering allows it. This avoids fetching logged parameters when the tool is not being logged.
 */
-#define GF_LOG(_log_level, _log_tools, __args) if ((gf_log_get_level() >= (_log_level)) && (gf_log_get_tools() & (_log_tools))) { gf_log_lt(_log_level, _log_tools); gf_log __args ;}
+#define GF_LOG(_log_level, _log_tools, __args) if (gf_log_tool_level_on(_log_tools, _log_level) ) { gf_log_lt(_log_level, _log_tools); gf_log __args ;}
 #endif
 
 
@@ -624,6 +673,29 @@ u32 gf_sys_clock();
  */
 void gf_sleep(u32 ms);
 
+/*!
+ *     \brief Delete Directory
+ *
+ *     Delete a  dir within the full path.
+ *     \param DirPathName the file path name.
+ */
+GF_Err gf_rmdir(char *DirPathName);
+
+/*!
+ *     \brief Create Directory
+ *
+ *     Create a directory within the full path.
+ *     \param DirPathName the dir path name.
+ */
+GF_Err gf_mkdir(char* DirPathName);
+
+/*!
+ *     \brief Create Directory
+ *
+ *     Cleanup a directory within the full path, removing all the files and the directories.
+ *     \param DirPathName the dir path name.
+ */
+GF_Err gf_cleanup_dir(char* DirPathName);
 /*!
  *     \brief CRC32 compute
  *
@@ -752,6 +824,13 @@ GF_Err gf_gz_compress_payload(char **data, u32 data_len, u32 *out_size);
  */
 GF_Err gf_gz_decompress_payload(char *data, u32 data_len, char **uncompressed_data, u32 *out_size);
 
+
+#ifdef GPAC_ANDROID
+typedef void (*fm_callback_func)(void *cbk_obj, u32 type, u32 param, int *value);
+extern void gf_fm_request_set_callback(void *cbk_obj, fm_callback_func cbk_func);
+void gf_fm_request_call(u32 type, u32 param, int *value);
+#endif //GPAC_ANDROID
+
 /*! @} */
 
 
index 3265eeb8c0f96dbfcda6327f9897e3e4dca621f8..41d137498067f60d3b6eb677c81a54848de981af 100644 (file)
@@ -136,6 +136,7 @@ typedef struct _tag_dom_parser GF_DOMParser;
 GF_DOMParser *gf_xml_dom_new();
 void gf_xml_dom_del(GF_DOMParser *parser);
 GF_Err gf_xml_dom_parse(GF_DOMParser *parser, const char *file, gf_xml_sax_progress OnProgress, void *cbk);
+GF_Err gf_xml_dom_parse_string(GF_DOMParser *dom, char *string);
 GF_XMLNode *gf_xml_dom_get_root(GF_DOMParser *parser);
 const char *gf_xml_dom_get_error(GF_DOMParser *parser);
 u32 gf_xml_dom_get_line(GF_DOMParser *parser);
index 872cfaf6ef362c1b7aaf807c677381af72c50044..acd7af063deef2b7f8979ef9d369ac088b53a9c7 100644 (file)
@@ -1,7 +1,6 @@
 include ../config.mak
 
 #all OS and lib independent
-#PLUGDIRS=aac_in ac3_in audio_filter bifs_dec ctx_load dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in svg_in saf_in mpegts_in ismacryp widgetman redirect_av mpd_in
 PLUGDIRS=aac_in ac3_in audio_filter bifs_dec ctx_load dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in svg_in saf_in mpegts_in ismacryp widgetman mpd_in osd
 
 ifeq ($(DISABLE_SVG), no)
@@ -28,6 +27,11 @@ else
 PLUGDIRS+=ogg
 endif
 
+ifeq ($(CONFIG_FREENECT), no)
+else
+PLUGDIRS+=freenect
+endif
+
 ifeq ($(CONFIG_AMR_NB), yes)
 PLUGDIRS+=amr_dec
 endif
@@ -73,6 +77,17 @@ else
 PLUGDIRS+=gpac_js
 endif
 
+ifeq ($(CONFIG_PLATINUM),yes)
+PLUGDIRS+=platinum
+endif
+
+ifeq ($(CONFIG_AVCAP),yes)
+PLUGDIRS+=avcap
+endif
+
+ifeq ($(CONFIG_OPENSVC),yes)
+PLUGDIRS+=opensvc_dec
+endif
 
 ifeq ($(RENOIR_ENABLE),yes)
 PLUGDIRS+=viren_out
index d812ea59f336b0a89e830644d9fef858c35e5b93..dcd70a466f7fe71504656bdabeeae923f481e132 100644 (file)
@@ -543,6 +543,12 @@ void aac_download_file(AACReader *read, char *url)
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
 #endif
        }
+
+#ifndef DONT_USE_TERMINAL_MODULE_API
+       /*start our download (threaded)*/
+       gf_dm_sess_process(read->dnload);
+#endif
+
        /*service confirm is done once fetched*/
 }
 
index b7a19991b07ce935f6b9f7e1c168c3e191ac68c5..fd5c0297a23de9a89f880c064c183836468412a5 100644 (file)
@@ -24,6 +24,9 @@
 
 #ifdef GPAC_HAS_FAAD
 
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#endif
 #include <faad.h>
 
 #include <gpac/modules/codec.h>
index 8fa1bc2a25ba47fecbaf254b721c6636f213a40b..df933f7315d831e9257e2ebec6b2c55aa3e2dbbc 100644 (file)
@@ -330,6 +330,9 @@ void ac3_download_file(GF_InputService *plug, char *url)
        if (!read->dnload ) {
                read->needs_connection = 0;
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
        }
        /*service confirm is done once fetched*/
 }
index b9625b0977b165bf17cfda5afc89122be54bd551..bce7442f31beb7297a8880d146416064b1f2fed2 100644 (file)
@@ -262,6 +262,9 @@ static void AMR_DownloadFile(GF_InputService *plug, char *url)
        if (!read->dnload) {
                read->needs_connection = 0;
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
        }
        /*service confirm is done once fetched*/
 }
@@ -464,17 +467,17 @@ fetch_next:
                switch (read->mtype) {
                case TYPE_AMR:
                        ft = (toc >> 3) & 0x0F;
-                       read->data_size = GF_AMR_FRAME_SIZE[ft];
+                       read->data_size = (u32)GF_AMR_FRAME_SIZE[ft];
                        break;
                case TYPE_AMR_WB:
                        ft = (toc >> 3) & 0x0F;
-                       read->data_size = GF_AMR_WB_FRAME_SIZE[ft];
+                       read->data_size = (u32)GF_AMR_WB_FRAME_SIZE[ft];
                        break;
                default:
                        for (i=0; i<GF_SMV_EVRC_RATE_TO_SIZE_NB; i++) {
                                if (GF_SMV_EVRC_RATE_TO_SIZE[2*i]==toc) {
                                        /*remove rate_type byte*/
-                                       read->data_size = GF_SMV_EVRC_RATE_TO_SIZE[2*i+1] - 1;
+                                       read->data_size = (u32)GF_SMV_EVRC_RATE_TO_SIZE[2*i+1] - 1;
                                        break;
                                }
                        }
index c4d45b333cde147a49385af7319117cf368ff2ca..67a8dfd347aa3d0227cce355a2b9e2dcc0126825 100644 (file)
@@ -229,14 +229,14 @@ static GF_Err AMR_ProcessData(GF_MediaDecoder *ifcg,
                        D_IF_decode(ctx->wb_destate, inBuffer, (s16 *) outBuffer, 0);
                        *outBufferLength += 320*2;
                        outBuffer += 320*2;
-                       offset = GF_AMR_WB_FRAME_SIZE[ft] + 1;
+                       offset = (u32)GF_AMR_WB_FRAME_SIZE[ft] + 1;
 #endif
                } else {
 #ifdef GPAC_HAS_AMR_FT
                        Decoder_Interface_Decode(ctx->nb_destate, inBuffer, (s16 *) outBuffer, 0);
                        *outBufferLength += 160*2;
                        outBuffer += 160*2;
-                       offset = GF_AMR_FRAME_SIZE[ft] + 1;
+                       offset = (u32)GF_AMR_FRAME_SIZE[ft] + 1;
 #endif
                }
                /*don't complain but...*/
diff --git a/modules/avcap/Makefile b/modules/avcap/Makefile
new file mode 100644 (file)
index 0000000..81456ee
--- /dev/null
@@ -0,0 +1,57 @@
+include ../../config.mak
+
+vpath %.c $(SRC_PATH)/modules/avcap
+
+CFLAGS= $(CPPFLAGS) -I"$(SRC_PATH)/include" $(AVCAP_CFLAGS)
+
+ifeq ($(DEBUGBUILD), yes)
+CFLAGS+=-g
+LDFLAGS+=-g
+endif
+
+ifeq ($(GPROFBUILD), yes)
+CFLAGS+=-pg
+LDFLAGS+=-pg
+endif
+
+LINKLIBS= $(AVCAP_LDFLAGS) -L../../bin/gcc -lgpac
+
+
+#common objects
+OBJS=avcap.o
+
+SRCS := $(OBJS:.o=.c) 
+
+LIB=gm_avcap.$(DYN_LIB_SUFFIX)
+
+
+all: $(LIB)
+
+
+$(LIB): $(OBJS)
+       $(CXX) -w $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKLIBS)
+
+
+%.o: %.cpp
+       $(CXX) $(CFLAGS) -c -o $@ $< 
+
+
+clean: 
+       rm -f $(OBJS) ../../bin/gcc/$(LIB)
+
+dep: depend
+
+depend:
+       rm -f .depend   
+       $(CXX) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+distclean: clean
+       rm -f Makefile.bak .depend
+
+
+
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/modules/avcap/avcap.cpp b/modules/avcap/avcap.cpp
new file mode 100644 (file)
index 0000000..8d69650
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Authors: Jean Le Feuvre
+ *                     Copyright (c) Telecom ParisTech 2011-20XX
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / AVCAP video input module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+
+#include <gpac/modules/service.h>
+#include <gpac/modules/codec.h>
+/*for GF_STREAM_PRIVATE_SCENE definition*/
+#include <gpac/constants.h>
+#include <gpac/download.h>
+
+#if !defined(__GNUC__)&& (defined(_WIN32_WCE) || defined (WIN32))
+#  pragma comment(lib, "strmiids")
+#ifdef _DEBUG
+#  pragma comment(lib, "avcapd")
+#  pragma comment(lib, "strmbasd")
+#else
+#  pragma comment(lib, "avcap")
+#  pragma comment(lib, "strmbase")
+#endif
+#  pragma comment(lib, "winmm")
+#endif
+
+
+
+#include <avcap/avcap.h>
+using namespace avcap;
+
+class GPACCaptureHandler : public CaptureHandler
+{
+public:
+       GPACCaptureHandler(GF_ClientService *service, LPNETCHANNEL channel) 
+               : m_pService(service), m_pChannel(channel)
+       {
+               memset(&m_pSLHeader, 0, sizeof(GF_SLHeader));
+               m_pSLHeader.compositionTimeStampFlag = 1;
+       }
+       virtual ~GPACCaptureHandler() {}
+
+       GF_ClientService *m_pService;
+       LPNETCHANNEL m_pChannel;
+       GF_SLHeader m_pSLHeader;
+
+public:
+       /* This method is called by the CaptureManager, when new data was captured.
+        * \param io_buf The buffer, that contains the captured data. */
+       void handleCaptureEvent(IOBuffer* io_buf);
+};
+
+
+void GPACCaptureHandler::handleCaptureEvent(IOBuffer* io_buf)
+{
+       m_pSLHeader.compositionTimeStamp = io_buf->getTimestamp();
+       gf_term_on_sl_packet(m_pService, m_pChannel, (char *) io_buf->getPtr(), io_buf->getValidBytes(), &m_pSLHeader, GF_OK);
+       io_buf->release();
+}
+
+DeviceDescriptor* get_device_descriptor(char *name)
+{
+       // find the descriptor of the device in the device-list by index
+       const DeviceCollector::DeviceList& dl = DEVICE_COLLECTOR::instance().getDeviceList();
+       DeviceDescriptor* dd = 0;
+       int index = 0;
+
+       for(DeviceCollector::DeviceList::const_iterator i = dl.begin(); i != dl.end(); i++, index++) {
+               dd = *i;
+
+               if (!name || !stricmp(name, "default") ) 
+                       return dd;
+               if (strstr((char *) dd->getName().c_str(), name) != NULL)
+                       return dd;
+       }
+       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[VideoCapture] Cannot find capture driver %s\n", name));
+       return NULL;
+}
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+       /*the service we're responsible for*/
+       GF_ClientService *service;
+       u32 state;
+
+       DeviceDescriptor *device_desc;
+       CaptureDevice* device;
+
+       GPACCaptureHandler *video_handler;
+       GPACCaptureHandler *audio_handler;
+
+       u32 width, height, pixel_format, stride, out_size, fps;
+} AVCapIn;
+
+
+Bool AVCap_CanHandleURL(GF_InputService *plug, const char *url)
+{
+       if (!strnicmp(url, "camera://", 9)) return 1;
+       if (!strnicmp(url, "video://", 8)) return 1;
+       return 0;
+}
+
+
+GF_Err AVCap_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
+{
+       GF_ESD *esd;
+       GF_BitStream *bs;
+       GF_ObjectDescriptor *od;
+       AVCapIn *vcap = (AVCapIn *) plug->priv;
+
+       if (!vcap || !serv || !url) return GF_BAD_PARAM;
+
+       vcap->state = 0;
+       vcap->service = serv;
+
+       if (!vcap->device_desc) {
+               Format *format;
+               char *name;
+               char *params = (char *) strchr(url, '?');
+               if (params) params[0] = 0;
+               name = (char *) strstr(url, "://");
+               if (name) name += 3;
+               /* get device by name  */
+               vcap->device_desc = get_device_descriptor(name);
+               if (params) {
+                       params[0] = '?';
+                       params ++;
+               }
+
+               if (!vcap->device_desc) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[VideoCapture] Failed to instanciate AVCap\n"));
+                       gf_term_on_connect(serv, NULL, GF_REMOTE_SERVICE_ERROR);
+                       return GF_OK;
+               }
+               
+               vcap->device_desc->open();
+               if ( (!strnicmp(url, "camera://", 9) || !strnicmp(url, "video://", 8)) && !vcap->device_desc->isVideoCaptureDev()) {
+                       vcap->device_desc->close();
+                       gf_term_on_connect(serv, NULL, GF_URL_ERROR);
+                       return GF_OK;
+               }
+               else if (!strnicmp(url, "audio://", 8) && !vcap->device_desc->isAudioDev()) {
+                       vcap->device_desc->close();
+                       gf_term_on_connect(serv, NULL, GF_URL_ERROR);
+                       return GF_OK;
+               }
+               vcap->device = vcap->device_desc->getDevice();
+               if (!vcap->device) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[VideoCapture] Failed to initialize capture device\n"));
+                       vcap->device_desc->close();
+                       gf_term_on_connect(serv, NULL, GF_SERVICE_ERROR);
+                       return GF_OK;
+               }
+               vcap->device->getFormatMgr()->setFramerate(30);
+
+               while (params) {
+                       char *sep = (char *) strchr(params, '&');
+                       if (sep) sep[0] = 0;
+       
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Set camera option %s\n", params));
+
+                       if (!strnicmp(params, "resolution=", 11)) {
+                               u32 w, h;
+                               if (sscanf(params+11, "%dx%d", &w, &h)==2) {
+                                       vcap->device->getFormatMgr()->setResolution(w, h);
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Set resolution to %dx%d\n", w, h));
+                               }
+                       }
+                       else if (!strnicmp(params, "fps=", 4)) {
+                               u32 fps;
+                               if (sscanf(params+4, "%d", &fps)==1) {
+                                       vcap->device->getFormatMgr()->setFramerate(fps);
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Set framerate to %d\n", fps));
+                               }
+                       }
+                       else if (!strnicmp(params, "stereo=", 7)) {
+                       }
+                       else if (!strnicmp(params, "mode=", 5)) {
+                       }
+
+                       if (!sep) break;
+                       sep[0] = '&';
+                       params = sep+1;
+               }
+               vcap->width = vcap->device->getFormatMgr()->getWidth();
+               vcap->height = vcap->device->getFormatMgr()->getHeight();
+               vcap->fps = vcap->device->getFormatMgr()->getFramerate();
+               
+               format = vcap->device->getFormatMgr()->getFormat();
+               switch (format->getFourcc()) {
+               case GF_4CC('V', 'Y', 'U', 'Y'):
+               case GF_4CC('2', 'Y', 'U', 'Y'):
+                       vcap->pixel_format = GF_PIXEL_YUY2;
+                       vcap->stride = 2*vcap->width;
+                       vcap->out_size = 2*vcap->width*vcap->height;
+                       break;
+               default:
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[VideoCapture] Unsupported 4CC %s (%08x) from capture device\n", gf_4cc_to_str(format->getFourcc()), format->getFourcc()));
+                       vcap->device_desc->close();
+                       gf_term_on_connect(serv, NULL, GF_NOT_SUPPORTED);
+                       return GF_OK;
+               }
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Device configured - resolution %dx%d - Frame Rate %d - Pixel Format %s (Device 4CC %08x) \n", vcap->width, vcap->height, vcap->fps, gf_4cc_to_str(vcap->pixel_format), format->getFourcc()));
+       }
+
+       /*ACK connection is OK*/
+       gf_term_on_connect(serv, NULL, GF_OK);
+
+
+       /*setup object descriptor*/
+       od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
+       
+       esd = gf_odf_desc_esd_new(0);
+       esd->slConfig->timestampResolution = 1000;
+       if (!strnicmp(url, "camera://", 9) || !strnicmp(url, "video://", 8)) {
+               od->objectDescriptorID = 1;
+               esd->ESID = 1;
+               esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+       } else {
+               od->objectDescriptorID = 2;
+               esd->ESID = 2;
+               esd->decoderConfig->streamType = GF_STREAM_AUDIO;
+       }
+       esd->decoderConfig->objectTypeIndication = GPAC_OTI_RAW_MEDIA_STREAM;
+       
+       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+       gf_bs_write_u32(bs, vcap->pixel_format);
+       gf_bs_write_u16(bs, vcap->width);
+       gf_bs_write_u16(bs, vcap->height);
+       gf_bs_write_u32(bs, vcap->out_size);
+       gf_bs_write_u32(bs, vcap->stride);
+       gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
+       gf_bs_del(bs);
+
+       gf_list_add(od->ESDescriptors, esd);
+       gf_term_add_media(vcap->service, (GF_Descriptor*)od, 0);
+
+       return GF_OK;
+}
+
+GF_Err AVCap_CloseService(GF_InputService *plug)
+{
+       AVCapIn *vcap = (AVCapIn *) plug->priv;
+       if (vcap->device_desc) {
+               vcap->device_desc->close();
+               vcap->device_desc = NULL;
+       }
+
+       vcap->state = 0;
+       gf_term_on_disconnect(vcap->service, NULL, GF_OK);
+       return GF_OK;
+}
+
+/*Dummy input just send a file name, no multitrack to handle so we don't need to check sub_url nor expected type*/
+static GF_Descriptor *AVCap_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
+{
+       return NULL;
+}
+
+
+GF_Err AVCap_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
+{
+       AVCapIn *vcap = (AVCapIn *) plug->priv;
+
+       if (!com->base.on_channel) return GF_NOT_SUPPORTED;
+
+       switch (com->command_type) {
+       case GF_NET_CHAN_SET_PULL: return GF_NOT_SUPPORTED;
+       case GF_NET_CHAN_INTERACTIVE: return GF_OK;
+       /*since data is file-based, no padding is needed (decoder plugin will handle it itself)*/
+       case GF_NET_CHAN_SET_PADDING: return GF_OK;
+       case GF_NET_CHAN_BUFFER:
+               com->buffer.max = com->buffer.min = 500;
+               return GF_OK;
+       case GF_NET_CHAN_DURATION:
+               /*this module is not made for updates, use undefined duration*/
+               com->duration.duration = 0;
+               return GF_OK;
+       case GF_NET_CHAN_PLAY:
+               if (vcap->state==0) {
+                       /*start capture*/
+                       if (vcap->video_handler)
+                               vcap->device->getVidCapMgr()->registerCaptureHandler(vcap->video_handler);
+
+                       if (vcap->device->getVidCapMgr()->startCapture() != -1) 
+                               vcap->state = 1;
+                       else
+                               vcap->device->getVidCapMgr()->removeCaptureHandler();
+               }
+               return GF_OK;
+       case GF_NET_CHAN_STOP:
+               if (vcap->state==1) {
+                       /*stop capture*/
+                       vcap->device->getVidCapMgr()->removeCaptureHandler();
+                       vcap->device->getVidCapMgr()->stopCapture(); 
+                       vcap->state = 0;
+               }
+               return GF_OK;
+       case GF_NET_CHAN_CONFIG: return GF_OK;
+       case GF_NET_CHAN_GET_DSI:
+               com->get_dsi.dsi = NULL;
+               com->get_dsi.dsi_len = 0;
+               return GF_OK;
+       }
+       return GF_OK;
+}
+
+GF_Err AVCap_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
+{
+       u32 ESID;
+       AVCapIn *vcap = (AVCapIn *) plug->priv;
+       
+       sscanf(url, "ES_ID=%u", &ESID);
+       if (ESID == 1) {
+               /*video connect*/
+               vcap->video_handler = new GPACCaptureHandler(vcap->service, channel);
+               gf_term_on_connect(vcap->service, channel, GF_OK);
+       } else if (ESID == 2) {
+               /*audio connect*/
+               vcap->audio_handler = new GPACCaptureHandler(vcap->service, channel);
+               gf_term_on_connect(vcap->service, channel, GF_OK);
+       } else {
+               gf_term_on_connect(vcap->service, channel, GF_STREAM_NOT_FOUND);
+       }
+       return GF_OK;
+}
+
+GF_Err AVCap_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
+{
+       AVCapIn *vcap = (AVCapIn *) plug->priv;
+       if (vcap->video_handler && vcap->video_handler->m_pChannel==channel) {
+               delete vcap->video_handler;
+               vcap->video_handler = NULL;
+       }
+       else if (vcap->audio_handler && vcap->audio_handler->m_pChannel==channel) {
+               delete vcap->audio_handler;
+               vcap->audio_handler = NULL;
+       }
+       gf_term_on_disconnect(vcap->service, channel, GF_OK);
+       return GF_OK;
+}
+
+Bool AVCap_CanHandleURLInService(GF_InputService *plug, const char *url)
+{
+       return 0;
+}
+
+
+GF_EXPORT
+const u32 *QueryInterfaces() 
+{
+       static u32 si [] = {
+               GF_NET_CLIENT_INTERFACE,
+               0
+       };
+       return si;
+}
+
+GF_EXPORT
+GF_BaseInterface *LoadInterface(u32 InterfaceType)
+{
+       if (InterfaceType == GF_NET_CLIENT_INTERFACE) {
+               AVCapIn *vcap;
+               GF_InputService *plug;
+               GF_SAFEALLOC(plug, GF_InputService);
+               memset(plug, 0, sizeof(GF_InputService));
+               GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "Video Capture using libavcap", "gpac distribution")
+
+               plug->RegisterMimeTypes = NULL;
+               plug->CanHandleURL = AVCap_CanHandleURL;
+               plug->ConnectService = AVCap_ConnectService;
+               plug->CloseService = AVCap_CloseService;
+               plug->GetServiceDescriptor = AVCap_GetServiceDesc;
+               plug->ConnectChannel = AVCap_ConnectChannel;
+               plug->DisconnectChannel = AVCap_DisconnectChannel;
+               plug->ServiceCommand = AVCap_ServiceCommand;
+               plug->CanHandleURLInService = AVCap_CanHandleURLInService;
+
+               GF_SAFEALLOC(vcap, AVCapIn);
+               plug->priv = vcap;
+               return (GF_BaseInterface *)plug;
+       } 
+       return NULL;
+}
+
+GF_EXPORT
+void ShutdownInterface(GF_BaseInterface *bi)
+{
+       if (bi->InterfaceType==GF_NET_CLIENT_INTERFACE) {
+               GF_InputService *ifcn = (GF_InputService*)bi;
+               AVCapIn *vcap = (AVCapIn*)ifcn->priv;
+               gf_free(vcap);
+               gf_free(bi);
+       }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
index dff6a4410b9a3787835afef18fda485c0b2fbf25..48ec61cf029dc49ff90237a471007489ff2d8bab 100644 (file)
@@ -20,7 +20,7 @@ endif
 
 
 #common obj
-OBJS=directfb_out.o
+OBJS=directfb_out.o directfb_wrapper.o
 
 SRCS := $(OBJS:.o=.c) 
 
@@ -31,7 +31,7 @@ all: $(LIB)
 
 
 $(LIB): $(OBJS)
-       $(CC) $(SHFLAGS) $(LDFLAGS) -L../../bin/gcc -lgpac -o ../../bin/gcc/$@ $(OBJS)
+       $(CC) $(SHFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LDFLAGS) -L../../bin/gcc -lgpac
                                                                                                
 %.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $< 
index a751bd7bd0e52cdcbffe02de15f9eb6c58c139e4..a194bdf38ef076c1419062b26ad6d2423a19dc71 100755 (executable)
-#include "directfb_out.h"
-
-#define DirectFBVID() DirectFBVidCtx *ctx = (DirectFBVidCtx *)driv->opaque
-// this was supposed to contain argc and argv from main !!!!!
-int argc;
-char **argv = {"toto"};
-
-//static const PredefineKeyID(keyIDs);
-
-u32 DirectFBVid_TranslatePixelFormatToGPAC(u32 dfbpf)
-{
-  switch (dfbpf) {
-   case DSPF_RGB16: return  GF_PIXEL_RGB_565;
-   case DSPF_RGB555: return  GF_PIXEL_RGB_555;
-   case DSPF_RGB24: return  GF_PIXEL_RGB_24;
-   case DSPF_RGB32: return  GF_PIXEL_RGB_32;
-   case DSPF_ARGB: return  GF_PIXEL_ARGB;
-   default: return 0;
-  }
-}
-
-u32 DirectFBVid_TranslatePixelFormatFromGPAC(u32 gpacpf)
-{
-  switch (gpacpf) {
-   case GF_PIXEL_RGB_565: return DSPF_RGB16;
-   case GF_PIXEL_RGB_555 : return DSPF_RGB555;
-   case GF_PIXEL_BGR_24 : return DSPF_RGB24;
-   case GF_PIXEL_RGB_24 : return DSPF_RGB24;
-   case GF_PIXEL_RGB_32 : return DSPF_RGB32;
-   case GF_PIXEL_ARGB: return DSPF_ARGB;
-   case GF_PIXEL_RGBA: return DSPF_ARGB;
-   case GF_PIXEL_YUY2 : return DSPF_YUY2;
-   case GF_PIXEL_YV12 : return DSPF_YV12;
-   default:
-    GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectFB] pixel format %s not supported\n", gf_4cc_to_str(gpacpf)));
-    return 0;
-  }
-}
-
-static DFBEnumerationResult enum_input_device(DFBInputDeviceID device_id, DFBInputDeviceDescription desc, void *data )
-{
-     DeviceInfo **devices = data;
-     DeviceInfo  *device;
-
-     device = malloc( sizeof(DeviceInfo) );
-
-     device->device_id = device_id;
-     device->desc      = desc;
-     device->next      = *devices;
-
-     *devices = device;
-
-     return GF_OK;
-}
-
-static void directfb_translate_key(DFBInputDeviceKeySymbol DirectFBkey, GF_EventKey *evt)
-{
-       evt->flags = 0;
-       evt->hw_code = DirectFBkey;
-       switch (DirectFBkey){
-       case DIKS_BACKSPACE:
-               evt->key_code = GF_KEY_BACKSPACE; break;
-       case DIKS_RETURN:
-               evt->key_code = GF_KEY_ENTER; break;
-       case DIKS_CANCEL:
-               evt->key_code = GF_KEY_CANCEL; break;
-       case DIKS_ESCAPE:
-               evt->key_code = GF_KEY_ESCAPE; break;
-       case DIKS_SPACE:
-               evt->key_code = GF_KEY_SPACE; break;
-       case DIKS_EXCLAMATION_MARK:
-               evt->key_code = GF_KEY_EXCLAMATION; break;
-       case DIKS_QUOTATION:
-               evt->key_code = GF_KEY_QUOTATION; break;
-       case DIKS_NUMBER_SIGN:
-               evt->key_code = GF_KEY_NUMBER; break;
-       case DIKS_DOLLAR_SIGN:
-               evt->key_code = GF_KEY_DOLLAR; break;
-#if 0
-       case DIKS_PERCENT_SIGN:
-               evt->key_code = GF_KEY_PERCENT; break;
-#endif
-       case DIKS_AMPERSAND:
-               evt->key_code = GF_KEY_AMPERSAND; break;
-       case DIKS_APOSTROPHE:
-               evt->key_code = GF_KEY_APOSTROPHE; break;
-       case DIKS_PARENTHESIS_LEFT:
-               evt->key_code = GF_KEY_LEFTPARENTHESIS; break;
-       case DIKS_PARENTHESIS_RIGHT:
-               evt->key_code = GF_KEY_RIGHTPARENTHESIS; break;
-       case DIKS_ASTERISK:
-               evt->key_code = GF_KEY_STAR; break;
-       case DIKS_PLUS_SIGN:
-               evt->key_code = GF_KEY_PLUS; break;
-       case DIKS_COMMA:
-               evt->key_code = GF_KEY_COMMA; break;
-       case DIKS_MINUS_SIGN:
-               evt->key_code = GF_KEY_HYPHEN; break;
-       case DIKS_PERIOD:
-               evt->key_code = GF_KEY_FULLSTOP; break;
-       case DIKS_SLASH:
-               evt->key_code = GF_KEY_SLASH; break;
-       case DIKS_0:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_0; break;
-       case DIKS_1:
-                //fprintf(stderr, "DIKS_1: %d\n", GF_KEY_1);
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_1; break;
-       case DIKS_2:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_2; break;
-       case DIKS_3:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_3; break;
-       case DIKS_4:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_4; break;
-       case DIKS_5:
-               // fprintf(stderr, "DIKS_5\n");
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_5; break;
-       case DIKS_6:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_6; break;
-       case DIKS_7:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_7; break;
-       case DIKS_8:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_8; break;
-       case DIKS_9:
-               evt->flags = GF_KEY_EXT_NUMPAD; evt->key_code = GF_KEY_9; break;
-       case DIKS_COLON:
-               evt->key_code = GF_KEY_COLON; break;
-       case DIKS_SEMICOLON:
-               evt->key_code = GF_KEY_SEMICOLON; break;
-       case DIKS_LESS_THAN_SIGN:
-               evt->key_code = GF_KEY_LESSTHAN; break;
-       case DIKS_EQUALS_SIGN:
-               evt->key_code = GF_KEY_EQUALS; break;
-       case DIKS_GREATER_THAN_SIGN:
-               evt->key_code = GF_KEY_GREATERTHAN; break;
-       case DIKS_QUESTION_MARK:
-               evt->key_code = GF_KEY_QUESTION; break;
-       case DIKS_AT:
-               evt->key_code = GF_KEY_AT; break;
-       case DIKS_CAPITAL_A:
-               evt->key_code = GF_KEY_A; break;
-       case DIKS_CAPITAL_B:
-               evt->key_code = GF_KEY_B; break;
-       case DIKS_CAPITAL_C:
-               evt->key_code = GF_KEY_C; break;
-       case DIKS_CAPITAL_D:
-               evt->key_code = GF_KEY_D; break;
-       case DIKS_CAPITAL_E:
-               evt->key_code = GF_KEY_E; break;
-       case DIKS_CAPITAL_F:
-               evt->key_code = GF_KEY_F; break;
-       case DIKS_CAPITAL_G:
-               evt->key_code = GF_KEY_G; break;
-       case DIKS_CAPITAL_H:
-               evt->key_code = GF_KEY_H; break;
-       case DIKS_CAPITAL_I:
-               evt->key_code = GF_KEY_I; break;
-       case DIKS_CAPITAL_J:
-               evt->key_code = GF_KEY_J; break;
-       case DIKS_CAPITAL_K:
-               evt->key_code = GF_KEY_K; break;
-       case DIKS_CAPITAL_L:
-               evt->key_code = GF_KEY_L; break;
-       case DIKS_CAPITAL_M:
-               evt->key_code = GF_KEY_M; break;
-       case DIKS_CAPITAL_N:
-               evt->key_code = GF_KEY_N; break;
-       case DIKS_CAPITAL_O:
-               evt->key_code = GF_KEY_O; break;
-       case DIKS_CAPITAL_P:
-               evt->key_code = GF_KEY_P; break;
-       case DIKS_CAPITAL_Q:
-               evt->key_code = GF_KEY_Q; break;
-       case DIKS_CAPITAL_R:
-               evt->key_code = GF_KEY_R; break;
-       case DIKS_CAPITAL_S:
-               evt->key_code = GF_KEY_S; break;
-       case DIKS_CAPITAL_T:
-               evt->key_code = GF_KEY_T; break;
-       case DIKS_CAPITAL_U:
-               evt->key_code = GF_KEY_U; break;
-       case DIKS_CAPITAL_V:
-               evt->key_code = GF_KEY_V; break;
-       case DIKS_CAPITAL_W:
-               evt->key_code = GF_KEY_W; break;
-       case DIKS_CAPITAL_X:
-               evt->key_code = GF_KEY_X; break;
-       case DIKS_CAPITAL_Y:
-               evt->key_code = GF_KEY_Y; break;
-       case DIKS_CAPITAL_Z:
-               evt->key_code = GF_KEY_Z; break;
-       case DIKS_SQUARE_BRACKET_LEFT:
-               evt->key_code = GF_KEY_LEFTSQUAREBRACKET; break;
-       case DIKS_BACKSLASH:
-               evt->key_code = GF_KEY_BACKSLASH; break;
-       case DIKS_SQUARE_BRACKET_RIGHT:
-               evt->key_code = GF_KEY_RIGHTSQUAREBRACKET; break;
-       case DIKS_CIRCUMFLEX_ACCENT:
-               evt->key_code = GF_KEY_CIRCUM; break;
-       case DIKS_UNDERSCORE:
-               evt->key_code = GF_KEY_UNDERSCORE; break;
-       case DIKS_GRAVE_ACCENT:
-               evt->key_code = GF_KEY_GRAVEACCENT; break;
-       case DIKS_CURLY_BRACKET_LEFT:
-               evt->key_code = GF_KEY_LEFTCURLYBRACKET; break;
-       case DIKS_VERTICAL_BAR:
-               evt->key_code = GF_KEY_PIPE; break;
-       case DIKS_CURLY_BRACKET_RIGHT:
-               evt->key_code = GF_KEY_RIGHTCURLYBRACKET; break;
-       case DIKS_TILDE: break;
-       case DIKS_DELETE:
-               evt->key_code = GF_KEY_DEL; break;
-       case DIKS_CURSOR_LEFT:
-               evt->key_code = GF_KEY_LEFT; break;
-       case DIKS_CURSOR_RIGHT:
-               evt->key_code = GF_KEY_RIGHT; break;
-       case DIKS_CURSOR_UP:
-               evt->key_code = GF_KEY_UP; break;
-       case DIKS_CURSOR_DOWN:
-               evt->key_code = GF_KEY_DOWN; break;
-       case DIKS_INSERT:
-               evt->key_code = GF_KEY_INSERT; break;
-       case DIKS_HOME:
-               evt->key_code = GF_KEY_HOME; break;
-       case DIKS_END:
-               evt->key_code = GF_KEY_END; break;
-       case DIKS_PAGE_UP:
-               evt->key_code = GF_KEY_PAGEUP; break;
-       case DIKS_PAGE_DOWN:
-               evt->key_code = GF_KEY_PAGEDOWN; break;
-       case DIKS_PRINT:
-               evt->key_code = GF_KEY_PRINTSCREEN; break;
-       case DIKS_SELECT:
-               evt->key_code = GF_KEY_SELECT; break;
-       case DIKS_CLEAR:
-               evt->key_code = GF_KEY_CLEAR; break;
-       case DIKS_HELP:
-               evt->key_code = GF_KEY_HELP; break;
-       case DIKS_ZOOM:
-               evt->key_code = GF_KEY_ZOOM; break;
-       case DIKS_VOLUME_UP:
-               evt->key_code = GF_KEY_VOLUMEUP; break;
-       case DIKS_VOLUME_DOWN:
-               evt->key_code = GF_KEY_VOLUMEDOWN; break;
-       case DIKS_MUTE:
-               evt->key_code = GF_KEY_VOLUMEMUTE; break;
-       case DIKS_PLAYPAUSE:
-       case DIKS_PAUSE:
-               evt->key_code = GF_KEY_MEDIAPLAYPAUSE; break;
-       case DIKS_PLAY:
-               evt->key_code = GF_KEY_PLAY; break;
-       case DIKS_STOP:
-               evt->key_code = GF_KEY_MEDIASTOP; break;
-       case DIKS_PREVIOUS:
-               evt->key_code = GF_KEY_MEDIAPREVIOUSTRACK; break;
-       case DIKS_F1:
-               evt->key_code = GF_KEY_F1; break;
-       case DIKS_F2:
-               evt->key_code = GF_KEY_F2; break;
-       case DIKS_F3:
-               evt->key_code = GF_KEY_F3; break;
-       case DIKS_F4:
-               evt->key_code = GF_KEY_F4; break;
-       case DIKS_F5:
-               evt->key_code = GF_KEY_F5; break;
-       case DIKS_F6:
-               evt->key_code = GF_KEY_F6; break;
-       case DIKS_F7:
-               evt->key_code = GF_KEY_F7; break;
-       case DIKS_F8:
-               evt->key_code = GF_KEY_F8; break;
-       case DIKS_F9:
-               evt->key_code = GF_KEY_F9; break;
-       case DIKS_F10:
-               evt->key_code = GF_KEY_F10; break;
-       case DIKS_F11:
-               evt->key_code = GF_KEY_F11; break;
-       case DIKS_F12:
-               evt->key_code = GF_KEY_F12; break;
-       case DIKS_SHIFT:
-               evt->key_code = GF_KEY_SHIFT; break;
-       case DIKS_CONTROL:
-               evt->key_code = GF_KEY_CONTROL; break;
-       case DIKS_ALT:
-               evt->key_code = GF_KEY_ALT; break;
-       case DIKS_ALTGR:
-               evt->key_code = GF_KEY_ALTGRAPH; break;
-       case DIKS_META:
-               evt->key_code = GF_KEY_META; break;
-       case DIKS_CAPS_LOCK:
-               evt->key_code = GF_KEY_CAPSLOCK; break;
-       case DIKS_NUM_LOCK:
-               evt->key_code = GF_KEY_NUMLOCK; break;
-       case DIKS_SCROLL_LOCK:
-               evt->key_code = GF_KEY_SCROLL; break;
-       case DIKS_FAVORITES:
-               evt->key_code = GF_KEY_BROWSERFAVORITES; break;
-       case DIKS_CUSTOM0:
-               evt->key_code = GF_KEY_BROWSERREFRESH; break;
-       case DIKS_MENU:
-               evt->key_code = GF_KEY_BROWSERHOME; break;
-       case DIKS_POWER:
-               evt->key_code = GF_KEY_ENTER; break;
-       case DIKS_RED:
-               evt->key_code = GF_KEY_TAB; break;
-       case DIKS_GREEN:
-               evt->key_code = GF_KEY_CANCEL; break;
-       case DIKS_YELLOW:
-               evt->key_code = GF_KEY_COPY; break;
-       case DIKS_BLUE:
-               evt->key_code = GF_KEY_CUT; break;
-       case DIKS_MODE:
-               evt->key_code = GF_KEY_MODECHANGE; break;
-       case DIKS_BACK:
-               evt->key_code = GF_KEY_BROWSERBACK; break;
-       case DIKS_TV:
-               evt->key_code = GF_KEY_CLEAR; break;
-       case DIKS_OK:
-               evt->key_code = GF_KEY_SELECT; break;
-       case DIKS_REWIND:
-               evt->key_code = GF_KEY_BROWSERBACK; break;
-       case DIKS_FASTFORWARD:
-               evt->key_code = GF_KEY_BROWSERFORWARD; break;
-       case DIKS_SUBTITLE:
-               evt->key_code = GF_KEY_DEL; break;
-       case DIKS_CHANNEL_UP:
-               evt->key_code = GF_KEY_CHANNELUP; break;
-       case DIKS_CHANNEL_DOWN:
-               evt->key_code = GF_KEY_CHANNELDOWN; break;
-       case DIKS_TEXT:
-               evt->key_code = GF_KEY_TEXT; break;
-       case DIKS_INFO:
-               evt->key_code = GF_KEY_INFO; break;
-       case DIKS_EPG:
-               evt->key_code = GF_KEY_EPG; break;
-       case DIKS_RECORD:
-               evt->key_code = GF_KEY_RECORD; break;
-       case DIKS_AUDIO:
-               evt->key_code = GF_KEY_BEGINPAGE; break;
-       default:
-               evt->key_code = GF_KEY_UNIDENTIFIED; break;
-       }
-}
-#if 0
-
-static int compare_symbol( const void *a, const void *b )
-{
-     u32      *keycode  = (u32 *) a;
-     struct predef_keyid *idname = (struct predef_keyid *) b;
-
-     return *keycode - idname->key_code;
-}
-
-static const char *get_local_key_name(u32 key_code) {
-     struct predef_keyid      *predefine_keyid;
-
-     predefine_keyid = bsearch(&key_code, keyIDs, sizeof(keyIDs) / sizeof(keyIDs[0]) - 1, sizeof(keyIDs[0]), compare_symbol );
-     if (predefine_keyid) return predefine_keyid->name;
-     else return NULL;
-}
-
-static void show_key_event(DirectFBVidCtx *ctx, GF_EventKey *evt )
-{
-     //DirectFBVID();
-     char                               buf[16];
-     struct predef_keyid      *predefine_keyid;
-
-     predefine_keyid = bsearch(&evt->key_code, keyIDs, sizeof(keyIDs) / sizeof(keyIDs[0]) - 1, sizeof(keyIDs[0]), compare_symbol );
-
-
-     if (predefine_keyid) {
-         GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DirectFB] Predefined key ID from show_key_event():%s\n",predefine_keyid->name));
-     }
-     ctx->primary->SetColor( ctx->primary, 0x60, 0x60, 0x60, 0xFF );
-     snprintf (buf, sizeof(buf), "0x%X", evt->key_code);
-     ctx->primary->DrawString( ctx->primary, buf, -1,
-                          ctx->width - 40, ctx->height/3,
-                          DSTF_RIGHT );
+/*
+ *                                     GPAC Multimedia Framework
+ *
+ *                             Copyright (c) 2005-20XX Telecom-Paristech
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / DirectFB video output module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.0
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+
+#include <gpac/modules/video_out.h>
+#include <gpac/scenegraph_svg.h>
 
+#include "directfb_out.h"
 
-}
 
-#endif
+#define DirectFBVID() DirectFBVidCtx *ctx = (DirectFBVidCtx *)driv->opaque
 
+/**
+ *     function DirectFBVid_DrawHLine
+ *     - using hardware accelerator to a draw horizontal line   
+ **/
 static void DirectFBVid_DrawHLine(GF_VideoOutput *driv, u32 x, u32 y, u32 length, GF_Color color)
 {
+       u8 r = GF_COL_R(color);
+       u8 g = GF_COL_G(color);
+       u8 b = GF_COL_B(color);
        DirectFBVID();
-       u8 r, g, b;
-
-       //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawHLine(). Drawing line x %d y %d length %d color %08X\n", x, y, length, color));
-       SET_DRAWING_FLAGS( DSDRAW_NOFX );
-
-       r = GF_COL_R(color);
-       g = GF_COL_G(color);
-       b = GF_COL_B(color);
-
-       ctx->primary->SetColor(ctx->primary, r, g, b, 0xFF); // no alpha
-       //ctx->primary->DrawLine(ctx->primary, x, y, x+length, y);      // no acceleration
-       ctx->primary->FillRectangle(ctx->primary, x, y,length, 1);
 
+       DirectFBVid_DrawHLineWrapper(ctx, x, y, length, r, g, b);
 }
 
+
+/**
+ *     function DirectFBVid_DrawHLineAlpha
+ *     - using hardware accelerator to draw a horizontal line with alpha   
+ **/
 static void DirectFBVid_DrawHLineAlpha(GF_VideoOutput *driv, u32 x, u32 y, u32 length, GF_Color color, u8 alpha)
 {
+       u8 r = GF_COL_R(color);
+       u8 g = GF_COL_G(color);
+       u8 b = GF_COL_B(color);
        DirectFBVID();
-       u8 r, g, b;
-
-        //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawHLineAlpha(). Alpha line drawing x %d y %d length %d color %08X alpha %d\n", x, y, length, color, alpha));
-
-       SET_DRAWING_FLAGS( DSDRAW_BLEND ); // use alpha
 
-       r = GF_COL_R(color);
-       g = GF_COL_G(color);
-       b = GF_COL_B(color);
-
-       ctx->primary->SetColor(ctx->primary, r, g, b, alpha);
-       //ctx->primary->DrawLine(ctx->primary, x, y, x+length, y);
-       ctx->primary->FillRectangle(ctx->primary, x, y, length, 1);     // with acceleration
+       DirectFBVid_DrawHLineAlphaWrapper(ctx, x, y, length, r, g, b, alpha);
 }
 
+
+/**
+ *     function DirectFBVid_DrawRectangle
+ *     - using hardware accelerator to fill a rectangle   
+ **/
 static void DirectFBVid_DrawRectangle(GF_VideoOutput *driv, u32 x, u32 y, u32 width, u32 height, GF_Color color)
 {
+       u8 r = GF_COL_R(color);
+       u8 g = GF_COL_G(color);
+       u8 b = GF_COL_B(color);
+       u8 a = GF_COL_A(color);
        DirectFBVID();
-       u8 r, g, b, a;
-
-       //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawRectangle(). Drawing rectangle x %d y %d width %d height %d color %08x\n", x, y, width, height, color));
 
-
-       r = GF_COL_R(color);
-       g = GF_COL_G(color);
-       b = GF_COL_B(color);
-       a = GF_COL_A(color);
-
-       SET_DRAWING_FLAGS( DSDRAW_NOFX );
-
-       ctx->primary->SetColor(ctx->primary, r, g, b, a);
-       ctx->primary->FillRectangle(ctx->primary, x, y, width, height);
-       //ctx->primary->Blit( ctx->primary, ctx->primary, NULL, x, y );
+       DirectFBVid_DrawRectangleWrapper(ctx, x, y, width, height, r, g, b, a);
 }
 
-
+/**
+ *     function DirectFBVid_Setup
+ *     - DirectFB setup  
+ **/
 GF_Err DirectFBVid_Setup(GF_VideoOutput *driv, void *os_handle, void *os_display, u32 init_flags)
 {
-  const char* opt;
-  DFBResult err;
-  DFBSurfaceDescription dsc;
-  DFBSurfacePixelFormat dfbpf;
-  DFBAccelerationMask mask;
-  DeviceInfo *devices = NULL;
-
-  DirectFBVID();
-  ctx->is_init = 0;
-  argc=0;
-  DFBCHECK(DirectFBInit(&argc, & (argv) ));
-
-  DirectFBSetOption ("bg-none", NULL);
-  DirectFBSetOption ("no-init-layer", NULL);
-
-  /* create the super interface */
-  DFBCHECK(DirectFBCreate( &(ctx->dfb) ));
-
-  GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Initialization\n"));
-
-  /* create a list of input devices */
-  ctx->dfb->EnumInputDevices(ctx->dfb, enum_input_device, &devices );
-
-  /* create an event buffer for all devices */
-  DFBCHECK(ctx->dfb->CreateInputEventBuffer(ctx->dfb, DICAPS_KEYS, DFB_FALSE, &(ctx->events) ));
-
-  /* Set the cooperative level */
-  err = ctx->dfb->SetCooperativeLevel( ctx->dfb, DFSCL_FULLSCREEN );
-  if (err)
-    DirectFBError( "Failed to set cooperative level", err );
-
-  /* Get the primary surface, i.e. the surface of the primary layer. */
-  dsc.flags = DSDESC_CAPS;
-  dsc.caps = DSCAPS_PRIMARY | DSCAPS_DOUBLE;
-
-  if (ctx->use_systems_memory) dsc.caps |= DSCAPS_SYSTEMONLY;
-
-  DFBCHECK(ctx->dfb->CreateSurface( ctx->dfb, &dsc, &(ctx->primary) ));
-
-  ctx->primary->GetPixelFormat( ctx->primary, &dfbpf );
-  ctx->pixel_format = DirectFBVid_TranslatePixelFormatToGPAC(dfbpf);
-  ctx->primary->GetSize( ctx->primary, &(ctx->width), &(ctx->height) );
-  ctx->primary->Clear( ctx->primary, 0, 0, 0, 0xFF);
-
-  ctx->disable_acceleration = 0;
-  opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableAcceleration");
-  if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableAcceleration", "no");
-  if (opt && !strcmp(opt, "yes")) ctx->disable_acceleration = 1;
-
-  ctx->disable_display = 0;
-  opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableDisplay");
-  if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableDisplay", "no");
-  if (opt && !strcmp(opt, "yes")) ctx->disable_display = 1;
-
-
-  ctx->flip_mode = DSFLIP_BLIT;
-  opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "FlipSyncMode");
-  if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "FlipSyncMode", "waitsync");
-  if (!opt || !strcmp(opt, "waitsync")) ctx->flip_mode |= DSFLIP_WAITFORSYNC;
-  else if (opt && !strcmp(opt, "wait")) ctx->flip_mode |= DSFLIP_WAIT;
-  else if (opt && !strcmp(opt, "sync")) ctx->flip_mode |= DSFLIP_ONSYNC;
-  else if (opt && !strcmp(opt, "swap")) ctx->flip_mode &= ~DSFLIP_BLIT;
-
-  opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableBlit");
-  if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableBlit", "no");
-  if (opt && !strcmp(opt, "all")) {
-    driv->hw_caps &= ~(GF_VIDEO_HW_HAS_RGB | GF_VIDEO_HW_HAS_RGBA | GF_VIDEO_HW_HAS_YUV);
-  }
-  else if (opt && !strcmp(opt, "yuv")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_YUV;
-  else if (opt && !strcmp(opt, "rgb")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_RGB;
-  else if (opt && !strcmp(opt, "rgba")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_RGBA;
-
+       const char* opt;
+       
+       DirectFBVID();
+       DirectFBVid_CtxSetIsInit(ctx, 0);
+       
+       // initialisation and surface creation
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Initialization\n"));
+       // check window mode used - SDL or X11
+       {
+               WINDOW_MODE window_mode = 0;
+               opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "WindowMode");
+               if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "WindowMode", "X11");
+               if (!opt || !strcmp(opt, "X11")) window_mode = WINDOW_X11;
+               else if (opt && !strcmp(opt, "SDL")) window_mode = WINDOW_SDL;
+               DirectFBVid_InitAndCreateSurface(ctx, window_mode);
+       }
+       
+       // check hardware accelerator configuration
+       DirectFBVid_CtxSetDisableAcceleration(ctx, 0);
+       opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableAcceleration");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableAcceleration", "no");
+       if (opt && !strcmp(opt, "yes")) DirectFBVid_CtxSetDisableAcceleration(ctx, 1);
+
+       // check for display configuration
+       DirectFBVid_CtxSetDisableDisplay(ctx, 0);
+       opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableDisplay");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableDisplay", "no");
+       if (opt && !strcmp(opt, "yes")) DirectFBVid_CtxSetDisableDisplay(ctx, 1);
+
+       // set flip mode
+       {
+               FLIP_MODE flip_mode = 0;
+               opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "FlipSyncMode");
+               if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "FlipSyncMode", "waitsync");
+               if (!opt || !strcmp(opt, "waitsync")) flip_mode |= FLIP_WAITFORSYNC;
+               else if (opt && !strcmp(opt, "wait")) flip_mode |= FLIP_WAIT;
+               else if (opt && !strcmp(opt, "sync")) flip_mode |= FLIP_ONSYNC;
+               else if (opt && !strcmp(opt, "swap")) flip_mode |= FLIP_SWAP;
+               
+               DirectFBVid_CtxSetFlipMode(ctx, flip_mode);
+       }
 
-  if (!ctx->disable_acceleration){
-       ctx->primary->GetAccelerationMask( ctx->primary, NULL, &mask );
-       GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DirectFB] hardware acceleration mask %08x \n", mask));
+       // enable/disable blit
+       opt = gf_modules_get_option((GF_BaseInterface *)driv, "DirectFB", "DisableBlit");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)driv, "DirectFB", "DisableBlit", "no");
+       if (opt && !strcmp(opt, "all")) {
+               driv->hw_caps &= ~(GF_VIDEO_HW_HAS_RGB | GF_VIDEO_HW_HAS_RGBA | GF_VIDEO_HW_HAS_YUV);
+       }
+       else if (opt && !strcmp(opt, "yuv")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_YUV;
+       else if (opt && !strcmp(opt, "rgb")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_RGB;
+       else if (opt && !strcmp(opt, "rgba")) driv->hw_caps &= ~GF_VIDEO_HW_HAS_RGBA;
 
-       if (mask & DFXL_DRAWLINE ) // DrawLine() is accelerated. DFXL_DRAWLINE
-               ctx->accel_drawline = 1;
-       if (mask & DFXL_FILLRECTANGLE) // FillRectangle() is accelerated.
-               ctx->accel_fillrect = 1;
+       if (!DirectFBVid_CtxGetDisableAcceleration(ctx)) {
+               // check for functions that are hardware accelerated
+               DirectFBVid_CtxPrimaryProcessGetAccelerationMask(ctx);
 
-  GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DirectFB] hardware acceleration mask %08x - Line: %d Rectangle: %d\n", mask, ctx->accel_drawline, ctx->accel_fillrect));
+               driv->hw_caps |= GF_VIDEO_HW_HAS_LINE_BLIT;
+               driv->DrawHLine = DirectFBVid_DrawHLine;
+               driv->DrawHLineAlpha = DirectFBVid_DrawHLineAlpha;
+               driv->DrawRectangle = DirectFBVid_DrawRectangle;
 
-               driv->hw_caps |= GF_VIDEO_HW_HAS_LINE_BLIT;
-       driv->DrawHLine = DirectFBVid_DrawHLine;
-       driv->DrawHLineAlpha = DirectFBVid_DrawHLineAlpha;
-       driv->DrawRectangle = DirectFBVid_DrawRectangle;
-  }
+               //GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DirectFB] hardware acceleration mask %08x - Line: %d Rectangle: %d\n", mask, ctx->accel_drawline, ctx->accel_fillrect));
+       }
 
-  ctx->is_init = 1;
-  GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Initialization success - HW caps %08x\n", driv->hw_caps));
+       // end of initialization
+       DirectFBVid_CtxSetIsInit(ctx, 1);
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Initialization success - HW caps %08x\n", driv->hw_caps));
 
-//  GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Pixel format %s\n", gf_4cc_to_str(ctx->pixel_format)));
-  return GF_OK;
+//     GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Pixel format %s\n", gf_4cc_to_str(ctx->pixel_format)));
+       return GF_OK;
 }
 
+
+/**
+ *     function DirectFBVid_Shutdown
+ *     - shutdown DirectFB module
+ **/
 static void DirectFBVid_Shutdown(GF_VideoOutput *driv)
 {
-  DirectFBVID();
-  if (!ctx->is_init) return;
-  //ctx->primary->Clear(ctx->primary,0,0,0,0);
-  //ctx->primary->Flip( ctx->primary, NULL, DSFLIP_NONE);
-  //ctx->primary->Clear(ctx->primary,0,0,0,0);
-  ctx->primary->Release( ctx->primary );
-  ctx->events->Release( ctx->events );
-  ctx->dfb->Release( ctx->dfb );
-  ctx->is_init = 0;
-  system("stgfb_control /dev/fb0 a 0");
+       u32 ret;
+       DirectFBVID();
+       ret = DirectFBVid_ShutdownWrapper(ctx);
+       if (ret) {
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Failed to shutdown properly\n"));
+       }
 }
 
+
+/**
+ *     function DirectFBVid_Flush
+ *     - flushing buffer 
+ **/
 static GF_Err DirectFBVid_Flush(GF_VideoOutput *driv, GF_Window *dest)
 {
-  const char* opt;
-
-  DirectFBVID();
-  GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Flipping backbuffer\n"));
-  if (ctx->disable_display) return GF_OK;
+       DirectFBVID();
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] Flipping backbuffer\n"));
+       // if display is disabled, nothing to be done
+       if (DirectFBVid_CtxGetDisableDisplay(ctx)) return GF_OK;
 
-  ctx->primary->Flip( ctx->primary, NULL, ctx->flip_mode);
+       return DirectFBVid_CtxPrimaryFlip(ctx);
 }
 
 
+/**
+ *     function DirectFBVid_SetFullScreen
+ *     - set fullscreen mode  
+ **/
 GF_Err DirectFBVid_SetFullScreen(GF_VideoOutput *driv, u32 bFullScreenOn, u32 *screen_width, u32 *screen_height)
 {
-  DFBResult err;
-  DirectFBVID();
+       DirectFBVID();
 
-  *screen_width = ctx->width;
-  *screen_height = ctx->height;
+       *screen_width = DirectFBVid_CtxGetWidth(ctx);
+       *screen_height = DirectFBVid_CtxGetHeight(ctx);
 
-  return GF_OK;
+       return GF_OK;
 }
 
 
+/**
+ *     function DirectFBVid_ProcessMessageQueue
+ *     - handle DirectFB events 
+ **/
 Bool DirectFBVid_ProcessMessageQueue(DirectFBVidCtx *ctx, GF_VideoOutput *driv)
 {
-  DFBInputEvent directfb_evt;
-  GF_Event gpac_evt;
-
-  while (ctx->events->GetEvent( ctx->events, DFB_EVENT(&directfb_evt) ) == DFB_OK)
-  {
-       u32 i;
-       switch (directfb_evt.type){
-               case DIET_KEYPRESS:
-               case DIET_KEYRELEASE:
-                       //GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DirectFB] in ProcessMessageQueue\n"));
-                       directfb_translate_key(directfb_evt.key_symbol, &gpac_evt.key);
-                       gpac_evt.type = (directfb_evt.type == DIET_KEYPRESS) ? GF_EVENT_KEYDOWN : GF_EVENT_KEYUP;
-#if 0
-                       fprintf(stderr, "before %d %s\n", gpac_evt.key.key_code,
-                                                            gf_dom_get_key_name(gpac_evt.key.key_code));
-
-                       for (i=0;i<200; i++) {
-                         fprintf(stderr, "%03d %s\n", i, gf_dom_get_key_name(i));
-                       }
-#endif
-                       driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
-                       //fprintf(stderr, "after %d %s\n", gpac_evt.key.key_code, gf_dom_get_key_name(gpac_evt.key.key_code));
-               default:
-                       break;
+       GF_Event gpac_evt;
+       memset(&gpac_evt, 0, sizeof(gpac_evt));
+       while (DirectFBVid_ProcessMessageQueueWrapper(ctx, &gpac_evt.type, &gpac_evt.key.flags, &gpac_evt.key.key_code, &gpac_evt.mouse.x, &gpac_evt.mouse.y, &gpac_evt.mouse.button) == GF_OK)
+       {
+               driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
+               gpac_evt.key.flags = 0;
        }
 
-  }
-
-  return GF_OK;
+       return GF_OK;
 }
 
 
+/**
+ *     function DirectFBVid_ProcessEvent
+ *     - process events 
+ **/
 static GF_Err DirectFBVid_ProcessEvent(GF_VideoOutput *driv, GF_Event *evt)
 {
-  DirectFBVID();
+       DirectFBVID();
 
-  if (!evt) {
-    DirectFBVid_ProcessMessageQueue(ctx, driv);
-    return GF_OK;
-  }
+       if (!evt) {
+               DirectFBVid_ProcessMessageQueue(ctx, driv);
+               return GF_OK;
+       }
 
-  switch (evt->type) {
-  case GF_EVENT_SIZE:
-   if ((ctx->width !=evt->size.width) || (ctx->height != evt->size.height)) {
-       GF_Event gpac_evt;
-       gpac_evt.type = GF_EVENT_SIZE;
-       gpac_evt.size.width = ctx->width;
-       gpac_evt.size.height = ctx->height;
-       driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
-   }
-    return GF_OK;
+       switch (evt->type) {
+       case GF_EVENT_SIZE:
+               if ((DirectFBVid_CtxGetWidth(ctx) !=evt->size.width) || (DirectFBVid_CtxGetHeight(ctx) != evt->size.height)) {
+                       GF_Event gpac_evt;
+                       gpac_evt.type = GF_EVENT_SIZE;
+                       gpac_evt.size.width = DirectFBVid_CtxGetWidth(ctx);
+                       gpac_evt.size.height = DirectFBVid_CtxGetHeight(ctx);
+                       driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
+               }
+               return GF_OK;
 
-  case GF_EVENT_VIDEO_SETUP:
-   if (evt->setup.opengl_mode) return GF_NOT_SUPPORTED;
+       case GF_EVENT_VIDEO_SETUP:
+               if (evt->setup.opengl_mode) return GF_NOT_SUPPORTED;
 
-   if ((ctx->width !=evt->setup.width) || (ctx->height != evt->setup.height)) {
-       GF_Event gpac_evt;
-       gpac_evt.type = GF_EVENT_SIZE;
-       gpac_evt.size.width = ctx->width;
-       gpac_evt.size.height = ctx->height;
-       driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
-   }
-   return GF_OK;
-  default:
-    return GF_OK;
-  }
+               if ((DirectFBVid_CtxGetWidth(ctx) !=evt->setup.width) || (DirectFBVid_CtxGetHeight(ctx) != evt->setup.height)) {
+                       GF_Event gpac_evt;
+                       gpac_evt.type = GF_EVENT_SIZE;
+                       gpac_evt.size.width = DirectFBVid_CtxGetWidth(ctx);
+                       gpac_evt.size.height = DirectFBVid_CtxGetHeight(ctx);
+                       driv->on_event(driv->evt_cbk_hdl, &gpac_evt);
+               }
+               return GF_OK;
+       default:
+               return GF_OK;
+       }
 }
 
+
+/**
+ *     function DirectFBVid_LockBackBuffer
+ *     - lock the surface to access certain data
+ **/
 static GF_Err DirectFBVid_LockBackBuffer(GF_VideoOutput *driv, GF_VideoSurface *video_info, u32 do_lock)
 {
-  DFBResult ret;
-  u32 pitch;
-  void *buf;
-  u32 width, height;
-  DFBSurfacePixelFormat format;
-
-  DirectFBVID();
-  if (!ctx->primary) return GF_BAD_PARAM;
-  if (do_lock)
-  {
-    if (!video_info) return GF_BAD_PARAM;
-    ret = ctx->primary->Lock(ctx->primary, DSLF_READ | DSLF_WRITE, &buf, &pitch);
-    if (ret != DFB_OK) return GF_IO_ERR;
-
-    video_info->width = ctx->width;
-    video_info->height = ctx->height;
-    video_info->pitch_x = 0;
-    video_info->pitch_y = pitch;
-    video_info->video_buffer = buf;
-    video_info->pixel_format = ctx->pixel_format;
-    video_info->is_hardware_memory = !ctx->use_systems_memory;
-
-   GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] backbuffer locked\n"));
-  } else {
-    ctx->primary->Unlock(ctx->primary);
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] backbuffer unlocked\n"));
-  }
-  return GF_OK;
+       void *buf;
+       u32 pitch, ret;
 
+       DirectFBVID();
+       if (!DirectFBVid_CtxGetPrimary(ctx)) return GF_BAD_PARAM;
+       if (do_lock)
+       {
+               if (!video_info) return GF_BAD_PARAM;
+               // lock surface first in order to access data below
+               ret = DirectFBVid_CtxPrimaryLock(ctx, &buf, &pitch);
+               if (ret != 0) return GF_IO_ERR;
+
+               // fetch data
+               video_info->width = DirectFBVid_CtxGetWidth(ctx);
+               video_info->height = DirectFBVid_CtxGetHeight(ctx);
+               video_info->pitch_x = 0;
+               video_info->pitch_y = pitch;
+               video_info->video_buffer = buf;
+               video_info->pixel_format = DirectFBVid_CtxGetPixelFormat(ctx);
+               video_info->is_hardware_memory = !DirectFBVid_CtxIsHwMemory(ctx);
+
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] backbuffer locked\n"));
+       } else {
+               // unlock the surface after direct access
+               DirectFBVid_CtxPrimaryUnlock(ctx);
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] backbuffer unlocked\n"));
+       }
+       
+       return GF_OK;
 }
 
+
+/**
+ *     function DirectFBVid_Blit
+ *     - blit a surface  
+ **/
 static GF_Err DirectFBVid_Blit(GF_VideoOutput *driv, GF_VideoSurface *video_src, GF_Window *src_wnd, GF_Window *dst_wnd, u32 overlay_type)
 {
-  DirectFBVID();
-
-  DFBResult res;
-  DFBSurfaceDescription srcdesc;
-  IDirectFBSurface *src;
-  DFBRectangle dfbsrc, dfbdst;
-  DFBAccelerationMask mask;
-
-  if (overlay_type != 0) return GF_NOT_SUPPORTED;
-  if (ctx->disable_display) return GF_OK;
-
-  memset(&srcdesc, 0, sizeof(srcdesc));
-
-  srcdesc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED;
-  srcdesc.width = video_src->width;
-  srcdesc.height = video_src->height;
-  srcdesc.pixelformat = DirectFBVid_TranslatePixelFormatFromGPAC(video_src->pixel_format);
-  srcdesc.preallocated[0].data = video_src->video_buffer;
-  srcdesc.preallocated[0].pitch = video_src->pitch_y;
-
-
-  switch (video_src->pixel_format){
-  case GF_PIXEL_ARGB: //return DSPF_ARGB;
-  case GF_PIXEL_RGBA: //return DSPF_ARGB;
-       ctx->primary->SetBlittingFlags(ctx->primary, DSBLIT_BLEND_ALPHACHANNEL);
-       break;
-  default:
-       ctx->primary->SetBlittingFlags(ctx->primary, DSBLIT_NOFX);
-  }
-
-
-  res = ctx->dfb->CreateSurface(ctx->dfb, &srcdesc, &src);
-  if (res != DFB_OK) {
-   GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectFB] cannot create blit source surface for pixel format %s: %s (%d)\n", gf_4cc_to_str(video_src->pixel_format), DirectFBErrorString(res), res));
-   return GF_IO_ERR;
-  }
-
-
-   dfbsrc.x = src_wnd->x;
-   dfbsrc.y = src_wnd->y;
-   dfbsrc.w = src_wnd->w;
-   dfbsrc.h = src_wnd->h;
-
-   if (!src_wnd->x && !src_wnd->y && (dst_wnd->w==src_wnd->w) && (dst_wnd->h==src_wnd->h)) {
-          ctx->primary->Blit(ctx->primary, src, &dfbsrc, dst_wnd->x, dst_wnd->y);
-   } else {
-          dfbdst.x = dst_wnd->x;
-          dfbdst.y = dst_wnd->y;
-          dfbdst.w = dst_wnd->w;
-          dfbdst.h = dst_wnd->h;
-          ctx->primary->StretchBlit(ctx->primary, src, &dfbsrc, &dfbdst);
-  }
-
-  src->Release(src);
-  GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] blit successful\n"));
-
-  return GF_OK;
+       u32 ret;
+       DirectFBVID();
+
+       ret = DirectFBVid_BlitWrapper(ctx, video_src->width, video_src->height, video_src->pixel_format, video_src->video_buffer, video_src->pitch_y, src_wnd->x, src_wnd->y, src_wnd->w, src_wnd->h, dst_wnd->x, dst_wnd->y, dst_wnd->w, dst_wnd->h, overlay_type);
+       if (ret) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectFB] cannot create blit source surface for pixel format %s\n", gf_4cc_to_str(video_src->pixel_format)));
+               return GF_NOT_SUPPORTED;
+       }
+
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] blit successful\n"));
+
+       return GF_OK;
 }
 
+
+/**
+ *     function DirectFBNewVideo
+ *     - creates a DirectFb module  
+ **/
 void *DirectFBNewVideo()
 {
-  DirectFBVidCtx *ctx;
-  GF_VideoOutput *driv;
-
-  driv = gf_malloc(sizeof(GF_VideoOutput));
-  memset(driv, 0, sizeof(GF_VideoOutput));
-  GF_REGISTER_MODULE_INTERFACE(driv, GF_VIDEO_OUTPUT_INTERFACE, "DirectFB Video Output", "gpac distribution");
-
-  ctx = gf_malloc(sizeof(DirectFBVidCtx));
-  memset(ctx, 0, sizeof(DirectFBVidCtx));
-
-  /* GF_VideoOutput */
-  driv->opaque = ctx;
-  driv->Setup = DirectFBVid_Setup;
-  driv->Shutdown = DirectFBVid_Shutdown;
-  driv->Flush = DirectFBVid_Flush;
-  driv->SetFullScreen = DirectFBVid_SetFullScreen;
-  driv->ProcessEvent = DirectFBVid_ProcessEvent;
-  driv->LockBackBuffer = DirectFBVid_LockBackBuffer;
-  driv->LockOSContext = NULL;
-  driv->Blit = DirectFBVid_Blit;
-  driv->hw_caps |= GF_VIDEO_HW_HAS_RGB | GF_VIDEO_HW_HAS_RGBA | GF_VIDEO_HW_HAS_YUV | GF_VIDEO_HW_HAS_STRETCH;
-
-  return driv;
+       DirectFBVidCtx *ctx;
+       GF_VideoOutput *driv;
+
+       driv = gf_malloc(sizeof(GF_VideoOutput));
+       memset(driv, 0, sizeof(GF_VideoOutput));
+       GF_REGISTER_MODULE_INTERFACE(driv, GF_VIDEO_OUTPUT_INTERFACE, "DirectFB Video Output", "gpac distribution");
+
+       ctx = gf_malloc(DirectFBVid_GetCtxSizeOf());
+       memset(ctx, 0, DirectFBVid_GetCtxSizeOf());
+
+       /* GF_VideoOutput */
+       driv->opaque = ctx;
+       driv->Setup = DirectFBVid_Setup;
+       driv->Shutdown = DirectFBVid_Shutdown;
+       driv->Flush = DirectFBVid_Flush;
+       driv->SetFullScreen = DirectFBVid_SetFullScreen;
+       driv->ProcessEvent = DirectFBVid_ProcessEvent;
+       driv->LockBackBuffer = DirectFBVid_LockBackBuffer;
+       driv->LockOSContext = NULL;
+       driv->Blit = DirectFBVid_Blit;
+       driv->hw_caps |= GF_VIDEO_HW_HAS_RGB | GF_VIDEO_HW_HAS_RGBA | GF_VIDEO_HW_HAS_YUV | GF_VIDEO_HW_HAS_STRETCH;
+
+       return driv;
 }
 
+
+/**
+ *     function DirectFBDeleteVideo  
+ *     - delete video
+ **/
 void DirectFBDeleteVideo(void *ifce)
 {
-  GF_VideoOutput *driv = (GF_VideoOutput *)ifce;
-  DirectFBVID();
-  gf_free(ctx);
-  gf_free(driv);
+       GF_VideoOutput *driv = (GF_VideoOutput *)ifce;
+       DirectFBVID();
+       gf_free(ctx);
+       gf_free(driv);
 }
 
 
@@ -785,6 +373,7 @@ const u32 *QueryInterfaces()
        return si;
 }
 
+
 /*interface create*/
 GF_BaseInterface *LoadInterface(u32 InterfaceType)
 {
@@ -792,6 +381,7 @@ GF_BaseInterface *LoadInterface(u32 InterfaceType)
        return NULL;
 }
 
+
 /*interface destroy*/
 void ShutdownInterface(GF_BaseInterface *ifce)
 {
index ae24d617aef44bca0feaeea29917352ae8f16487..30ac3cf164db1d3b4954b337d2fccd873c1fa0b7 100755 (executable)
+/*
+ *                                     GPAC Multimedia Framework
+ *
+ *                             Copyright (c) 2005-20XX Telecom-Paristech
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / DirectFB video output module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
 #ifndef _DIRECTFB_OUT_H_
 #define _DIRECTFB_OUT_H_
 
+typedef struct __DirectFBVidCtx DirectFBVidCtx;
 
-#include <gpac/modules/video_out.h>
-#include <gpac/scenegraph_svg.h> 
-
-/* DirectFB */
-#define __DIRECT__STDTYPES__   //prevent u8, s8, ... definitions by directFB as we have them in GPAC
-#include <directfb.h>
-#include <directfb_strings.h>
-#include <directfb_util.h>
-#include <direct/util.h>
-
-static int do_xor       = 0;
-
-/* macro for a safe call to DirectFB functions */
-#define DFBCHECK(x...)                                                     \
-          do {                                                             \
-               err = x;                                                    \
-               if (err != DFB_OK) {                                        \
-                    fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
-                    DirectFBErrorFatal( #x, err );                         \
-               }                                                           \
-          } while (0)
-          
-#define SET_DRAWING_FLAGS( flags ) \
-          ctx->primary->SetDrawingFlags( ctx->primary, (flags) | (do_xor ? DSDRAW_XOR : 0) )
-          
-typedef struct _DeviceInfo DeviceInfo;
-
-struct _DeviceInfo {
-     DFBInputDeviceID           device_id;
-     DFBInputDeviceDescription  desc;
-     DeviceInfo                *next;
-};
-
-struct predef_keyid {
-  u32 key_code;  
-  const char *name; 
-};
+typedef enum {
+       WINDOW_X11 = 1,
+       WINDOW_SDL = 1 << 1,
+} WINDOW_MODE;
 
-#if 0
-#define PredefineKeyID(predefined_key_identifiers) struct predef_keyid predefined_key_identifiers[] = {\
-       { GF_KEY_ACCEPT, "Accept" },\
-       { GF_KEY_AGAIN, "Again" },\
-       { GF_KEY_ALLCANDIDATES, "AllCandidates" },\
-       { GF_KEY_ALPHANUM, "Alphanumeric" },\
-       { GF_KEY_ALT, "Alt" },\
-       { GF_KEY_ALTGRAPH, "AltGraph" },\
-       { GF_KEY_APPS, "Apps" },\
-       { GF_KEY_ATTN, "Attn" },\
-       { GF_KEY_BROWSERBACK, "BrowserBack" },\
-       { GF_KEY_BROWSERFAVORITES, "BrowserFavorites" },\
-       { GF_KEY_BROWSERFORWARD, "BrowserForward" },\
-       { GF_KEY_BROWSERHOME, "BrowserHome" },\
-       { GF_KEY_BROWSERREFRESH, "BrowserRefresh" },\
-       { GF_KEY_BROWSERSEARCH, "BrowserSearch" },\
-       { GF_KEY_BROWSERSTOP, "BrowserStop" },\
-       { GF_KEY_CAPSLOCK, "CapsLock" },\
-       { GF_KEY_CLEAR, "Clear" },\
-       { GF_KEY_CODEINPUT, "CodeInput" },\
-       { GF_KEY_COMPOSE, "Compose" },\
-       { GF_KEY_CONTROL, "Control" },\
-       { GF_KEY_CRSEL, "Crsel" },\
-       { GF_KEY_CONVERT, "Convert" },\
-       { GF_KEY_COPY, "Copy"  },\
-       { GF_KEY_CUT, "Cut" },\
-       { GF_KEY_DOWN, "Down" },\
-       { GF_KEY_END, "End" },\
-       { GF_KEY_ENTER, "Enter" },\
-       { GF_KEY_EPG, "EPG" }, \
-       { GF_KEY_ERASEEOF, "EraseEof" },\
-       { GF_KEY_EXECUTE, "Execute" },\
-       { GF_KEY_EXSEL, "Exsel" },\
-       { GF_KEY_F1, "F1" },\
-       { GF_KEY_F2, "F2" },\
-       { GF_KEY_F3, "F3" },\
-       { GF_KEY_F4, "F4" },\
-       { GF_KEY_F5, "F5" },\
-       { GF_KEY_F6, "F6" },\
-       { GF_KEY_F7, "F7" },\
-       { GF_KEY_F8, "F8" },\
-       { GF_KEY_F9, "F9" },\
-       { GF_KEY_F10, "F10" },\
-       { GF_KEY_F11, "F11" },\
-       { GF_KEY_F12, "F12" },\
-       { GF_KEY_F13, "F13" },\
-       { GF_KEY_F14, "F14" },\
-       { GF_KEY_F15, "F15" },\
-       { GF_KEY_F16, "F16" },\
-       { GF_KEY_F17, "F17" },\
-       { GF_KEY_F18, "F18" },\
-       { GF_KEY_F19, "F19" },\
-       { GF_KEY_F20, "F20" },\
-       { GF_KEY_F21, "F21" },\
-       { GF_KEY_F22, "F22" },\
-       { GF_KEY_F23, "F23" },\
-       { GF_KEY_F24, "F24" },\
-       { GF_KEY_FINALMODE, "FinalMode" },\
-       { GF_KEY_FIND, "Find" },\
-       { GF_KEY_FULLWIDTH, "FullWidth" },\
-       { GF_KEY_HALFWIDTH, "HalfWidth" },\
-       { GF_KEY_HANGULMODE, "HangulMode" },\
-       { GF_KEY_HANJAMODE, "HanjaMode"   },\
-       { GF_KEY_HELP, "Help" },\
-       { GF_KEY_HIRAGANA, "Hiragana" },\
-       { GF_KEY_HOME, "Home" },\
-       { GF_KEY_INFO, "Info" }, \
-       { GF_KEY_INSERT, "Insert" },\
-       { GF_KEY_JAPANESEHIRAGANA, "JapaneseHiragana" },\
-       { GF_KEY_JAPANESEKATAKANA, "JapaneseKatakana" },\
-       { GF_KEY_JAPANESEROMAJI, "JapaneseRomaji" },\
-       { GF_KEY_JUNJAMODE, "JunjaMode" },\
-       { GF_KEY_KANAMODE, "KanaMode"   },\
-       { GF_KEY_KANJIMODE, "KanjiMode" },\
-       { GF_KEY_KATAKANA, "Katakana"   },\
-       { GF_KEY_LAUNCHAPPLICATION1, "LaunchApplication1" },\
-       { GF_KEY_LAUNCHAPPLICATION2, "LaunchApplication2" },\
-       { GF_KEY_LAUNCHMAIL, "LaunchMail" },\
-       { GF_KEY_LEFT, "Left" },\
-       { GF_KEY_META, "Meta" },\
-       { GF_KEY_MEDIANEXTTRACK, "MediaNextTrack" },\
-       { GF_KEY_MEDIAPLAYPAUSE, "MediaPlayPause" },\
-       { GF_KEY_MEDIAPREVIOUSTRACK, "MediaPreviousTrack" },\
-       { GF_KEY_MEDIASTOP, "MediaStop" },\
-       { GF_KEY_MODECHANGE, "ModeChange" },\
-       { GF_KEY_NONCONVERT, "Nonconvert" },\
-       { GF_KEY_NUMLOCK, "NumLock" },\
-       { GF_KEY_PAGEDOWN, "PageDown" },\
-       { GF_KEY_PAGEUP, "PageUp" },\
-       { GF_KEY_PASTE, "Paste" },\
-       { GF_KEY_PAUSE, "Pause" },\
-       { GF_KEY_PLAY, "Play" },\
-       { GF_KEY_PREVIOUSCANDIDATE, "PreviousCandidate" },\
-       { GF_KEY_PRINTSCREEN, "PrintScreen" },\
-       { GF_KEY_PROCESS, "Process" },\
-       { GF_KEY_PROPS, "Props" },\
-       { GF_KEY_RIGHT, "Right" },\
-       { GF_KEY_ROMANCHARACTERS, "RomanCharacters" },\
-       { GF_KEY_SCROLL, "Scroll" },\
-       { GF_KEY_SELECT, "Select" },\
-       { GF_KEY_SELECTMEDIA, "SelectMedia" },\
-       { GF_KEY_SHIFT, "Shift" },\
-       { GF_KEY_STOP, "Stop" },\
-       { GF_KEY_UP, "Up" },\
-       { GF_KEY_UNDO, "Undo" },\
-       { GF_KEY_VOLUMEDOWN, "VolumeDown" },\
-       { GF_KEY_VOLUMEMUTE, "VolumeMute" },\
-       { GF_KEY_VOLUMEUP, "VolumeUp" },\
-       { GF_KEY_WIN, "Win" },\
-       { GF_KEY_ZOOM, "Zoom" },\
-       { GF_KEY_BACKSPACE, "U+0008" },\
-       { GF_KEY_TAB, "U+0009" },\
-       { GF_KEY_CANCEL, "U+0018" },\
-       { GF_KEY_ESCAPE, "U+001B" },\
-       { GF_KEY_SPACE, "U+0020" },\
-       { GF_KEY_EXCLAMATION, "U+0021" },\
-       { GF_KEY_QUOTATION, "U+0022" },\
-       { GF_KEY_NUMBER, "U+0023" },\
-       { GF_KEY_DOLLAR, "U+0024" },\
-       { GF_KEY_AMPERSAND, "U+0026" },\
-       { GF_KEY_APOSTROPHE, "U+0027" },\
-       { GF_KEY_LEFTPARENTHESIS, "U+0028" },\
-       { GF_KEY_RIGHTPARENTHESIS, "U+0029" },\
-       { GF_KEY_STAR, "U+002A" },\
-       { GF_KEY_PLUS, "U+002B" },\
-       { GF_KEY_COMMA, "U+002C" },\
-       { GF_KEY_HYPHEN, "U+002D" },\
-       { GF_KEY_FULLSTOP, "U+002E" },\
-       { GF_KEY_SLASH, "U+002F" },\
-       { GF_KEY_0, "U+0030" },\
-       { GF_KEY_1, "U+0031" },\
-       { GF_KEY_2, "U+0032" },\
-       { GF_KEY_3, "U+0033" },\
-       { GF_KEY_4, "U+0034" },\
-       { GF_KEY_5, "U+0035" },\
-       { GF_KEY_6, "U+0036" },\
-       { GF_KEY_7, "U+0037" },\
-       { GF_KEY_8, "U+0038" },\
-       { GF_KEY_9, "U+0039" },\
-       { GF_KEY_COLON, "U+003A" },\
-       { GF_KEY_SEMICOLON, "U+003B" },\
-       { GF_KEY_LESSTHAN, "U+003C" },\
-       { GF_KEY_EQUALS, "U+003D" },\
-       { GF_KEY_GREATERTHAN, "U+003E" },\
-       { GF_KEY_QUESTION, "U+003F" },\
-       { GF_KEY_AT, "U+0040" },\
-       { GF_KEY_A, "U+0041" },\
-       { GF_KEY_B, "U+0042" },\
-       { GF_KEY_C, "U+0043" },\
-       { GF_KEY_D, "U+0044" },\
-       { GF_KEY_E, "U+0045" },\
-       { GF_KEY_F, "U+0046" },\
-       { GF_KEY_G, "U+0047" },\
-       { GF_KEY_H, "U+0048" },\
-       { GF_KEY_I, "U+0049" },\
-       { GF_KEY_J, "U+004A" },\
-       { GF_KEY_K, "U+004B" },\
-       { GF_KEY_L, "U+004C" },\
-       { GF_KEY_M, "U+004D" },\
-       { GF_KEY_N, "U+004E" },\
-       { GF_KEY_O, "U+004F" },\
-       { GF_KEY_P, "U+0050" },\
-       { GF_KEY_Q, "U+0051" },\
-       { GF_KEY_R, "U+0052" },\
-       { GF_KEY_S, "U+0053" },\
-       { GF_KEY_T, "U+0054" },\
-       { GF_KEY_U, "U+0055" },\
-       { GF_KEY_V, "U+0056" },\
-       { GF_KEY_W, "U+0057" },\
-       { GF_KEY_X, "U+0058" },\
-       { GF_KEY_Y, "U+0059" },\
-       { GF_KEY_Z, "U+005A" },\
-       { GF_KEY_LEFTSQUAREBRACKET, "U+005B" },\
-       { GF_KEY_BACKSLASH, "U+005C" },\
-       { GF_KEY_RIGHTSQUAREBRACKET, "U+005D" },\
-       { GF_KEY_CIRCUM, "U+005E" },\
-       { GF_KEY_UNDERSCORE, "U+005F" },\
-       { GF_KEY_GRAVEACCENT, "U+0060" },\
-       { GF_KEY_LEFTCURLYBRACKET, "U+007B" },\
-       { GF_KEY_PIPE, "U+007C" },\
-       { GF_KEY_RIGHTCURLYBRACKET, "U+007D" },\
-       { GF_KEY_DEL, "U+007F" },\
-       { GF_KEY_INVERTEXCLAMATION, "U+00A1" },\
-       { GF_KEY_DEADGRAVE, "U+0300" },\
-       { GF_KEY_DEADEACUTE, "U+0301" },\
-       { GF_KEY_DEADCIRCUM, "U+0302" },\
-       { GF_KEY_DEADTILDE, "U+0303" },\
-       { GF_KEY_DEADMACRON, "U+0304" }, \
-       { GF_KEY_DEADBREVE, "U+0306" },\
-       { GF_KEY_DEADABOVEDOT, "U+0307" },\
-       { GF_KEY_DEADDIARESIS, "U+0308" }, \
-       { GF_KEY_DEADRINGABOVE, "U+030A" },\
-       { GF_KEY_DEADDOUBLEACUTE, "U+030B" },\
-       { GF_KEY_DEADCARON, "U+030C" },\
-       { GF_KEY_DEADCEDILLA, "U+0327" },\
-       { GF_KEY_DEADOGONEK, "U+0328" },\
-       { GF_KEY_DEADIOTA, "U+0345" },\
-       { GF_KEY_EURO, "U+20AC" },\
-       { GF_KEY_DEADVOICESOUND, "U+3099" },\
-       { GF_KEY_DEADSEMIVOICESOUND, "U+309A" }\
-};
-#endif 
-typedef struct
-{
-    /* the super interface */
-    IDirectFB *dfb;
-    /* the primary surface */
-    IDirectFBSurface *primary;
+typedef enum {
+       FLIP_SWAP        = 1,
+       FLIP_WAITFORSYNC = 1 << 1,
+       FLIP_WAIT        = 1 << 2,
+       FLIP_ONSYNC      = 1 << 3,
+} FLIP_MODE;
 
-    /* screen width, height */
-    u32 width, height, pixel_format;
-    Bool use_systems_memory, disable_acceleration, disable_aa, is_init, disable_display;
-
-     /* acceleration */
-    int accel_drawline, accel_fillrect;
-    DFBSurfaceFlipFlags flip_mode;
-
-    /*===== for key events =====*/
-
-    /* Input interfaces: devices and its buffer */
-    IDirectFBEventBuffer *events;
-
-     /*=============================
-       if using window
-    ============================= */
-    
-    /* DirectFB window */
-    IDirectFBWindow *window;
-    
-    /* display layer */
-    IDirectFBDisplayLayer *layer;
+#ifndef Bool
+#define Bool   u32
+#endif
 
-} DirectFBVidCtx;
+u32 DirectFBVid_TranslatePixelFormatToGPAC(u32 dfbpf);
+u32 DirectFBVid_TranslatePixelFormatFromGPAC(u32 gpacpf);
+size_t DirectFBVid_GetCtxSizeOf(void);
+void DirectFBVid_InitAndCreateSurface(DirectFBVidCtx *ctx, WINDOW_MODE window_mode);
+void DirectFBVid_CtxSetFlipMode(DirectFBVidCtx *ctx, FLIP_MODE flip_mode);
+void DirectFBVid_CtxPrimaryProcessGetAccelerationMask(DirectFBVidCtx *ctx);
+u32 DirectFBVid_ProcessMessageQueueWrapper(DirectFBVidCtx *ctx, u8 *type, u32 *flags, u32 *key_code, s32 *x, s32 *y, u32 *button);
+void DirectFBVid_DrawHLineWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 length, u8 r, u8 g, u8 b);
+void DirectFBVid_DrawHLineAlphaWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 length, u8 r, u8 g, u8 b, u8 alpha);
+void DirectFBVid_DrawRectangleWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 a);
+u32 DirectFBVid_CtxPrimaryLock(DirectFBVidCtx *ctx, void **buf, u32 *pitch);
+void DirectFBVid_CtxPrimaryUnlock(DirectFBVidCtx *ctx);
+u32 DirectFBVid_CtxGetWidth(DirectFBVidCtx *ctx);
+u32 DirectFBVid_CtxGetHeight(DirectFBVidCtx *ctx);
+void *DirectFBVid_CtxGetPrimary(DirectFBVidCtx *ctx);
+u32 DirectFBVid_CtxGetPixelFormat(DirectFBVidCtx *ctx);
+Bool DirectFBVid_CtxIsHwMemory(DirectFBVidCtx *ctx);
+u32 DirectFBVid_CtxPrimaryFlip(DirectFBVidCtx *ctx);
+void DirectFBVid_CtxSetDisableDisplay(DirectFBVidCtx *ctx, Bool val);
+Bool DirectFBVid_CtxGetDisableDisplay(DirectFBVidCtx *ctx);
+void DirectFBVid_CtxSetDisableAcceleration(DirectFBVidCtx *ctx, Bool val);
+Bool DirectFBVid_CtxGetDisableAcceleration(DirectFBVidCtx *ctx);
+void DirectFBVid_CtxSetIsInit(DirectFBVidCtx *ctx, Bool val);
+u32 DirectFBVid_ShutdownWrapper(DirectFBVidCtx *ctx);
+u32 DirectFBVid_BlitWrapper(DirectFBVidCtx *ctx, u32 video_src_width, u32 video_src_height, u32 video_src_pixel_format, char *video_src_buffer, s32 video_src_pitch_y, u32 src_wnd_x, u32 src_wnd_y, u32 src_wnd_w, u32 src_wnd_h, u32 dst_wnd_x, u32 dst_wnd_y, u32 dst_wnd_w, u32 dst_wnd_h, u32 overlay_type);
 
-void *DirectFBNewVideo();
-void DirectFBDeleteVideo(void *ifce);
 
 #endif
diff --git a/modules/directfb_out/directfb_wrapper.c b/modules/directfb_out/directfb_wrapper.c
new file mode 100644 (file)
index 0000000..fa536ed
--- /dev/null
@@ -0,0 +1,830 @@
+/*
+ *                                     GPAC Multimedia Framework
+ *
+ *                             Copyright (c) 2005-20XX Telecom-Paristech
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / DirectFB video output module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+
+/* DirectFB */
+#include <directfb.h>
+#include <directfb_strings.h>
+#include <directfb_util.h>
+#include <direct/util.h>
+
+#include <gpac/constants.h>
+#include <gpac/events_constants.h>
+
+#include "directfb_out.h"
+
+enum
+{
+       GF_MOUSE_LEFT = 0,
+       GF_MOUSE_MIDDLE,
+       GF_MOUSE_RIGHT
+};
+
+static int do_xor = 0;
+
+/* macro for a safe call to DirectFB functions */
+#define DFBCHECK(x...)                                                     \
+          do {                                                             \
+               err = x;                                                    \
+               if (err != DFB_OK) {                                        \
+                    fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
+                    DirectFBErrorFatal( #x, err );                         \
+               }                                                           \
+          } while (0)
+         
+#define SET_DRAWING_FLAGS( flags ) \
+          ctx->primary->SetDrawingFlags( ctx->primary, (flags) | (do_xor ? DSDRAW_XOR : 0) )
+
+
+/* Structs */
+
+struct __DirectFBVidCtx
+{
+    /* the super interface */
+    IDirectFB *dfb;
+    /* the primary surface */
+    IDirectFBSurface *primary;
+    
+    /* for keyboard input */
+    //~ IDirectFBInputDevice *keyboard;
+
+    /* screen width, height */
+    u32 width, height, pixel_format;
+    Bool use_systems_memory, disable_acceleration, disable_aa, is_init, disable_display;
+
+     /* acceleration */
+    int accel_drawline, accel_fillrect;
+    DFBSurfaceFlipFlags flip_mode;
+
+    /*===== for key events =====*/
+
+    /* Input interfaces: devices and its buffer */
+    IDirectFBEventBuffer *events;
+    
+    /* mouse events */
+    IDirectFBInputDevice *mouse;
+
+     /*=============================
+       if using window
+    ============================= */
+    
+    /* DirectFB window */
+    IDirectFBWindow *window;
+    
+    /* display layer */
+    IDirectFBDisplayLayer *layer;
+
+};
+
+
+size_t DirectFBVid_GetCtxSizeOf(void)
+{
+       return sizeof(DirectFBVidCtx);
+}
+
+
+typedef struct _DeviceInfo DeviceInfo;
+struct _DeviceInfo {
+     DFBInputDeviceID           device_id;
+     DFBInputDeviceDescription  desc;
+     DeviceInfo                *next;
+};
+
+
+
+/* Wrapper to DirectFB members */
+
+/**
+ *     function DirectFBVid_DrawHLineWrapper
+ *     - using hardware accelerator to draw horizontal line     
+ **/
+void DirectFBVid_DrawHLineWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 length, u8 r, u8 g, u8 b)
+{
+       //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawHLine(). Drawing line x %d y %d length %d color %08X\n", x, y, length, color));
+       
+       // DSDRAW_NOFX: flag controlling drawing command, drawing without using any effects 
+       SET_DRAWING_FLAGS( DSDRAW_NOFX );
+
+       // set the color used without alpha 
+       ctx->primary->SetColor(ctx->primary, r, g, b, 0xFF); 
+       
+       // to draw a line using hardware accelerators, we can use either DrawLine (in our STB, DrawLine() function is not accelerated) or FillRectangle function with height equals to 1
+       //ctx->primary->DrawLine(ctx->primary, x, y, x+length, y);      // no acceleration
+       ctx->primary->FillRectangle(ctx->primary, x, y,length, 1);
+}
+
+
+/**
+ *     function DirectFBVid_DrawHLineWrapper
+ *     - using hardware accelerator to draw horizontal line with alpha     
+ **/
+void DirectFBVid_DrawHLineAlphaWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 length, u8 r, u8 g, u8 b, u8 alpha)
+{
+       //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawHLineAlpha(). Alpha line drawing x %d y %d length %d color %08X alpha %d\n", x, y, length, color, alpha));
+
+       // DSDRAW_BLEND: using alpha from color
+       SET_DRAWING_FLAGS( DSDRAW_BLEND );
+
+       ctx->primary->SetColor(ctx->primary, r, g, b, alpha);
+       //ctx->primary->DrawLine(ctx->primary, x, y, x+length, y);
+       ctx->primary->FillRectangle(ctx->primary, x, y, length, 1);     // with acceleration
+}
+
+
+/**
+ *     function DirectFBVid_DrawRectangleWrapper
+ *     - using hardware accelerator to fill a rectangle with the given color  
+ **/
+void DirectFBVid_DrawRectangleWrapper(DirectFBVidCtx *ctx, u32 x, u32 y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 a)
+{
+       //GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DirectFB] in DirectFBVid_DrawRectangle(). Drawing rectangle x %d y %d width %d height %d color %08x\n", x, y, width, height, color));
+
+       SET_DRAWING_FLAGS( DSDRAW_NOFX );
+
+       ctx->primary->SetColor(ctx->primary, r, g, b, a);
+       ctx->primary->FillRectangle(ctx->primary, x, y, width, height);
+       //ctx->primary->Blit( ctx->primary, ctx->primary, NULL, x, y );
+}
+
+
+/**
+ *     function DirectFBVid_CtxPrimaryLock
+ *     - lock the surface (in order to access certain data)  
+ **/
+u32 DirectFBVid_CtxPrimaryLock(DirectFBVidCtx *ctx, void **buf, u32 *pitch)
+{
+       DFBResult ret = ctx->primary->Lock(ctx->primary, DSLF_READ | DSLF_WRITE, buf, pitch);
+       if (ret != DFB_OK) return 1;
+       return 0;
+}
+
+
+static DFBEnumerationResult enum_input_device(DFBInputDeviceID device_id, DFBInputDeviceDescription desc, void *data )
+{
+       DeviceInfo **devices = data;
+
+       DeviceInfo *device = malloc(sizeof(DeviceInfo) );
+       
+       device->device_id = device_id;
+       device->desc = desc;
+       device->next = *devices;
+
+       *devices = device;
+
+       return 0;
+}
+
+
+/**
+ *     function DirectFBVid_InitAndCreateSurface
+ *     - initialize and create DirectFB surface 
+ **/
+u32 DirectFBVid_TranslatePixelFormatToGPAC(u32 dfbpf);
+void DirectFBVid_InitAndCreateSurface(DirectFBVidCtx *ctx, u32 window_mode)
+{
+       DFBResult err;
+       DFBSurfaceDescription dsc;
+       DFBSurfacePixelFormat dfbpf;
+       DeviceInfo *devices = NULL;
+       
+       //fake arguments and DirectFBInit()
+       {
+               int i, argc=2, argc_ro=2;
+               char **argv = malloc(argc*sizeof(char*));
+               char *argv_ro[2];
+               //http://directfb.org/wiki/index.php/Configuring_DirectFB
+               argv_ro[0]=argv[0]=strdup("gpac");
+               // graphis system used is X11
+               if (window_mode == WINDOW_SDL) {
+                       argv_ro[1]=argv[1]=strdup("--dfb:system=sdl");
+               } else {
+                       argv_ro[1]=argv[1]=strdup("--dfb:system=x11");
+               }
+               
+               // screen resolution 640x480
+               //~ argv_ro[2]=argv[2]=strdup("--dfb:mode=640x480");
+               //~ argv_ro[2]=argv[2]=strdup("");
+
+               /* create the super interface */
+               DFBCHECK(DirectFBInit(&argc, &argv));
+       
+               for (i=0; i<argc_ro; i++)
+                       free(argv_ro[i]);
+               free(argv);
+       }
+
+       // disable background handling
+       DFBCHECK(DirectFBSetOption ("bg-none", NULL));
+       // disable layers
+       DFBCHECK(DirectFBSetOption ("no-init-layer", NULL));
+
+       /* create the surface */
+       DFBCHECK(DirectFBCreate( &(ctx->dfb) ));
+
+       /* create a list of input devices */
+       ctx->dfb->EnumInputDevices(ctx->dfb, enum_input_device, &devices );
+       if (devices->desc.type & DIDTF_JOYSTICK) {
+               // for mouse
+               DFBCHECK(ctx->dfb->GetInputDevice(ctx->dfb, devices->device_id, &(ctx->mouse)));
+       }
+       
+       /* create an event buffer for all devices */
+       DFBCHECK(ctx->dfb->CreateInputEventBuffer(ctx->dfb, DICAPS_KEYS, DFB_FALSE, &(ctx->events) ));
+
+       /* Set the cooperative level */
+       DFBCHECK(ctx->dfb->SetCooperativeLevel( ctx->dfb, DFSCL_FULLSCREEN ));
+
+       /* Get the primary surface, i.e. the surface of the primary layer. */
+       // capabilities field is valid
+       dsc.flags = DSDESC_CAPS;
+       // primary, double-buffered surface
+       dsc.caps = DSCAPS_PRIMARY | DSCAPS_DOUBLE;
+
+       // if using system memory, data is permanently stored in this memory (no video memory allocation)
+       if (ctx->use_systems_memory) dsc.caps |= DSCAPS_SYSTEMONLY;
+
+       DFBCHECK(ctx->dfb->CreateSurface( ctx->dfb, &dsc, &(ctx->primary) ));
+
+       // fetch pixel format
+       ctx->primary->GetPixelFormat( ctx->primary, &dfbpf );
+       // translate DirectFB pixel format to GPAC
+       ctx->pixel_format = DirectFBVid_TranslatePixelFormatToGPAC(dfbpf);
+       // surface width and height in pixel
+       ctx->primary->GetSize( ctx->primary, &(ctx->width), &(ctx->height) );
+       ctx->primary->Clear( ctx->primary, 0, 0, 0, 0xFF);
+}
+
+
+/**
+ *     function DirectFBVid_CtxPrimaryUnlock
+ *     - unlock a surface after direct access (in order to fetch data)
+ **/
+void DirectFBVid_CtxPrimaryUnlock(DirectFBVidCtx *ctx)
+{
+       ctx->primary->Unlock(ctx->primary);
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetWidth
+ *     - returns screen width 
+ **/
+u32 DirectFBVid_CtxGetWidth(DirectFBVidCtx *ctx)
+{
+       return ctx->width;
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetHeight
+ *     - returns screen height 
+ **/
+u32 DirectFBVid_CtxGetHeight(DirectFBVidCtx *ctx)
+{
+       return ctx->height;
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetPrimary
+ *     - return the primary surface  
+ **/
+void *DirectFBVid_CtxGetPrimary(DirectFBVidCtx *ctx)
+{
+       return ctx->primary;
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetPixelFormat
+ *     - get pixel format  
+ **/
+u32 DirectFBVid_CtxGetPixelFormat(DirectFBVidCtx *ctx)
+{
+       return ctx->pixel_format;
+}
+
+
+/**
+ *     function DirectFBVid_CtxIsHwMemory
+ *     - return value whether system memory is used or not  
+ **/
+Bool DirectFBVid_CtxIsHwMemory(DirectFBVidCtx *ctx)
+{
+       return ctx->use_systems_memory;
+}
+
+
+/**
+ *     function DirectFBVid_CtxPrimaryFlip
+ *     - flipping buffers 
+ **/
+u32 DirectFBVid_CtxPrimaryFlip(DirectFBVidCtx *ctx)
+{
+       return ctx->primary->Flip(ctx->primary, NULL, ctx->flip_mode);
+}
+
+
+/**
+ *     function DirectFBVid_CtxSetDisableDisplay
+ *     - set disable display value   
+ **/
+void DirectFBVid_CtxSetDisableDisplay(DirectFBVidCtx *ctx, Bool val)
+{
+       ctx->disable_display = val;
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetDisableDisplay
+ *     - boolean showing whether display is enabled/disabled   
+ **/
+Bool DirectFBVid_CtxGetDisableDisplay(DirectFBVidCtx *ctx)
+{
+       return ctx->disable_display;
+}
+
+
+/**
+ *     function DirectFBVid_CtxSetDisableAcceleration
+ *     - boolean showing whether hardware accelerator is enabled/disabled   
+ **/
+void DirectFBVid_CtxSetDisableAcceleration(DirectFBVidCtx *ctx, Bool val)
+{
+       ctx->disable_acceleration = val;
+}
+
+
+/**
+ *     function DirectFBVid_CtxGetDisableAcceleration
+ *     - return disable_acceleration value  
+ **/
+Bool DirectFBVid_CtxGetDisableAcceleration(DirectFBVidCtx *ctx)
+{
+       return ctx->disable_acceleration;
+}
+
+
+/**
+ *     function DirectFBVid_CtxSetIsInit
+ *     - boolean showing whether DirectFB is initialized   
+ **/
+void DirectFBVid_CtxSetIsInit(DirectFBVidCtx *ctx, Bool val)
+{
+       ctx->is_init = val;
+}
+
+
+/**
+ *     function DirectFBVid_CtxSetFlipMode
+ *     - set flip mode   
+ **/
+void DirectFBVid_CtxSetFlipMode(DirectFBVidCtx *ctx, u32 flip_mode)
+{
+       ctx->flip_mode = DSFLIP_BLIT;
+       switch(flip_mode) {
+               case FLIP_WAITFORSYNC:
+                       ctx->flip_mode |= DSFLIP_WAITFORSYNC;
+                       break;
+               case FLIP_WAIT:
+                       ctx->flip_mode |= DSFLIP_WAIT;
+                       break;
+               case FLIP_ONSYNC:
+                       ctx->flip_mode |= DSFLIP_ONSYNC;
+                       break;
+               case FLIP_SWAP:
+                       ctx->flip_mode &= ~DSFLIP_BLIT;
+                       break;
+       }
+}
+
+
+/**
+ *     function DirectFBVid_CtxPrimaryProcessGetAccelerationMask
+ *     - Get a mask of drawing functions that are hardware accelerated with the current settings.
+ **/
+void DirectFBVid_CtxPrimaryProcessGetAccelerationMask(DirectFBVidCtx *ctx)
+{
+       DFBAccelerationMask mask;
+       ctx->primary->GetAccelerationMask( ctx->primary, NULL, &mask );
+
+       if (mask & DFXL_DRAWLINE ) // DrawLine() is accelerated. DFXL_DRAWLINE
+               ctx->accel_drawline = 1;
+       if (mask & DFXL_FILLRECTANGLE) // FillRectangle() is accelerated.
+               ctx->accel_fillrect = 1;
+}
+
+
+/**
+ *     function DirectFBVid_ShutdownWrapper
+ *     - shutdown DirectFB module  
+ **/
+u32 DirectFBVid_ShutdownWrapper(DirectFBVidCtx *ctx)
+{
+       // case where initialization is not done
+       if (!ctx->is_init) return 1;
+
+       //~ ctx->keyboard->Release( ctx->keyboard );
+       ctx->primary->Release( ctx->primary );
+       ctx->events->Release( ctx->events );
+       ctx->dfb->Release( ctx->dfb );
+       ctx->is_init = 0;
+       //we use x11 thus it should be useless:
+       //system("stgfb_control /dev/fb0 a 0")
+       return 0;
+}
+
+
+/**
+ *     Blit a surface 
+ **/
+u32 DirectFBVid_TranslatePixelFormatFromGPAC(u32 gpacpf);
+u32 DirectFBVid_BlitWrapper(DirectFBVidCtx *ctx, u32 video_src_width, u32 video_src_height, u32 video_src_pixel_format, char *video_src_buffer, s32 video_src_pitch_y, u32 src_wnd_x, u32 src_wnd_y, u32 src_wnd_w, u32 src_wnd_h, u32 dst_wnd_x, u32 dst_wnd_y, u32 dst_wnd_w, u32 dst_wnd_h, u32 overlay_type)
+{
+       DFBResult res;
+       DFBSurfaceDescription srcdesc;
+       IDirectFBSurface *src;
+       DFBRectangle dfbsrc, dfbdst;
+
+       if (overlay_type != 0) return 1;
+       if (ctx->disable_display) return 0;
+
+       memset(&srcdesc, 0, sizeof(srcdesc));
+
+       srcdesc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED;
+       srcdesc.width = video_src_width;
+       srcdesc.height = video_src_height;
+       srcdesc.pixelformat = DirectFBVid_TranslatePixelFormatFromGPAC(video_src_pixel_format);
+       srcdesc.preallocated[0].data = video_src_buffer;
+       srcdesc.preallocated[0].pitch = video_src_pitch_y;
+
+
+       switch (video_src_pixel_format) {
+               case GF_PIXEL_ARGB: //return DSPF_ARGB;
+               case GF_PIXEL_RGBA: //return DSPF_ARGB;
+                       ctx->primary->SetBlittingFlags(ctx->primary, DSBLIT_BLEND_ALPHACHANNEL);
+                       break;
+               default:
+                       ctx->primary->SetBlittingFlags(ctx->primary, DSBLIT_NOFX);
+       }
+
+       // create a surface with the new surface description
+       res = ctx->dfb->CreateSurface(ctx->dfb, &srcdesc, &src);
+       if (res != DFB_OK) {
+               //GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectFB] cannot create blit source surface for pixel format %s: %s (%d)\n", gf_4cc_to_str(video_src->pixel_format), DirectFBErrorString(res), res));
+               return 1;
+       }
+
+
+       dfbsrc.x = src_wnd_x;
+       dfbsrc.y = src_wnd_y;
+       dfbsrc.w = src_wnd_w;
+       dfbsrc.h = src_wnd_h;
+
+       // blit on the surface
+       if (!src_wnd_x && !src_wnd_y && (dst_wnd_w==src_wnd_w) && (dst_wnd_h==src_wnd_h)) {
+                ctx->primary->Blit(ctx->primary, src, &dfbsrc, dst_wnd_x, dst_wnd_y);
+       // blit an area scaled from the source to the destination rectangle
+       } else {
+               dfbdst.x = dst_wnd_x;
+               dfbdst.y = dst_wnd_y;
+               dfbdst.w = dst_wnd_w;
+               dfbdst.h = dst_wnd_h;
+               ctx->primary->StretchBlit(ctx->primary, src, &dfbsrc, &dfbdst);
+       }
+
+       src->Release(src);
+       
+       return 0;
+}
+
+
+/**
+ *     function DirectFBVid_ProcessMessageQueueWrapper  
+ *     - handle DirectFB events
+ *     - key events
+ **/
+void directfb_translate_key(DFBInputDeviceKeyIdentifier DirectFBkey, u32 *flags, u32 *key_code);
+u32 DirectFBVid_ProcessMessageQueueWrapper(DirectFBVidCtx *ctx, u8 *type, u32 *flags, u32 *key_code, s32 *x, s32 *y, u32 *button)
+{
+       DFBInputEvent directfb_evt;
+
+       if (ctx->events->GetEvent( ctx->events, DFB_EVENT(&directfb_evt) ) == DFB_OK)
+       {
+               switch (directfb_evt.type) {
+                       case DIET_KEYPRESS:
+                       case DIET_KEYRELEASE:
+                               directfb_translate_key(directfb_evt.key_id, flags, key_code);
+                               *type = (directfb_evt.type == DIET_KEYPRESS) ? GF_EVENT_KEYDOWN : GF_EVENT_KEYUP;
+                               break;
+                       case DIET_BUTTONPRESS:
+                       case DIET_BUTTONRELEASE:
+                               *type = (directfb_evt.type == DIET_BUTTONPRESS) ? GF_EVENT_MOUSEUP : GF_EVENT_MOUSEDOWN;
+                               switch(directfb_evt.button) {
+                                       case DIBI_LEFT:
+                                               *button = GF_MOUSE_LEFT;
+                                               break;
+                                       case DIBI_RIGHT:
+                                               *button = GF_MOUSE_RIGHT;
+                                               break;
+                                       case DIBI_MIDDLE:
+                                               *button = GF_MOUSE_MIDDLE;
+                                               break;
+                                       default:
+                                               printf("in here for others\n");
+                                               break;
+                               }
+                               break;
+                       case DIET_AXISMOTION:
+                               *type = GF_EVENT_MOUSEMOVE;
+                               ctx->mouse->GetXY(ctx->mouse, x, y);
+                       default:
+                               break;
+               }
+               
+               return 0;
+       }
+
+       return 1;
+}
+
+
+/* Events translation */
+/**
+ *     function DirectFBVid_TranslatePixelFormatToGPAC
+ *     - translate pixel from DirectFb to GPAC  
+ **/
+u32 DirectFBVid_TranslatePixelFormatToGPAC(u32 dfbpf)
+{
+       switch (dfbpf) {
+               case DSPF_RGB16: return GF_PIXEL_RGB_565;
+               case DSPF_RGB555: return GF_PIXEL_RGB_555;
+               case DSPF_RGB24: return GF_PIXEL_RGB_24;
+               case DSPF_RGB32: return GF_PIXEL_RGB_32;
+               case DSPF_ARGB: return GF_PIXEL_ARGB;
+               default: return 0;
+       }
+}
+
+/**
+ *     function DirectFBVid_TranslatePixelFormatToGPAC
+ *     - translate pixel from GPAC to DirectFB  
+ **/
+u32 DirectFBVid_TranslatePixelFormatFromGPAC(u32 gpacpf)
+{
+       switch (gpacpf) {
+               case GF_PIXEL_RGB_565: return DSPF_RGB16;
+               case GF_PIXEL_RGB_555 : return DSPF_RGB555;
+               case GF_PIXEL_BGR_24 : return DSPF_RGB24;
+               case GF_PIXEL_RGB_24 : return DSPF_RGB24;
+               case GF_PIXEL_RGB_32 : return DSPF_RGB32;
+               case GF_PIXEL_ARGB: return DSPF_ARGB;
+               case GF_PIXEL_RGBA: return DSPF_ARGB;
+               case GF_PIXEL_YUY2 : return DSPF_YUY2;
+               case GF_PIXEL_YV12 : return DSPF_YV12;
+               default:
+                       ;//GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectFB] pixel format %s not supported\n", gf_4cc_to_str(gpacpf)));
+       }
+
+       return 0;
+}
+
+
+/**
+ *     function directfb_translate_key
+ *     - translate key from DirectFB to GPAC  
+ **/
+void directfb_translate_key(DFBInputDeviceKeyIdentifier DirectFBkey, u32 *flags, u32 *key_code)
+{
+       //~ printf("DirectFBkey=%d\n", DirectFBkey);
+
+       switch (DirectFBkey) {
+               case DIKI_BACKSPACE:
+                       *key_code = GF_KEY_BACKSPACE; 
+                       //~ printf("DIKI_BACKSPACE\n"); 
+                       break;
+               case DIKI_TAB:
+                       *key_code = GF_KEY_TAB; 
+                       //~ printf("DIKI_TAB\n"); 
+                       break;
+               case DIKI_ENTER:
+                       *key_code = GF_KEY_ENTER; 
+                       //~ printf("DIKI_ENTER\n"); 
+                       break;
+               case DIKI_ESCAPE:
+                       *key_code = GF_KEY_ESCAPE; 
+                       //~ printf("DIKI_ESCAPE\n"); 
+                       break;
+               case DIKI_SPACE:
+                       *key_code = GF_KEY_SPACE; 
+                       //~ printf("DIKI_SPACE\n"); 
+                       break;
+               case DIKI_SHIFT_L:
+               case DIKI_SHIFT_R:
+                       *key_code = GF_KEY_SHIFT; 
+                       //~ printf("DIKI_SHIFT_R/DIKI_SHIFT_L\n"); 
+                       break;
+               case DIKI_CONTROL_L:
+               case DIKI_CONTROL_R:
+                       *key_code = GF_KEY_CONTROL; 
+                       //~ printf("DIKI_CONTROL_L/DIKI_CONTROL_R\n"); 
+                       break;
+               case DIKI_ALT_L:
+               case DIKI_ALT_R:
+                       *key_code = GF_KEY_ALT; 
+                       //~ printf("DIKI_ALT_L/DIKI_ALT_R\n"); 
+                       break;
+               case DIKI_CAPS_LOCK:
+                       *key_code = GF_KEY_CAPSLOCK; 
+                       //~ printf("DIKI_CAPS_LOCK\n"); 
+                       break;
+               case DIKI_META_L:
+               case DIKI_META_R:
+                       *key_code = GF_KEY_META; break;
+               case DIKI_KP_EQUAL:
+                       *key_code = GF_KEY_EQUALS; break;
+               case DIKI_SUPER_L:
+               case DIKI_SUPER_R:
+                       *key_code = GF_KEY_WIN; break;
+               
+               /* alphabets */
+               case DIKI_A:
+                       *key_code = GF_KEY_A; 
+                       //~ printf("DIKI_A\n"); 
+                       break;
+               case DIKI_B:
+                       *key_code = GF_KEY_B; 
+                       //~ printf("DIKI_B\n"); 
+                       break;
+               case DIKI_C:
+                       *key_code = GF_KEY_C; 
+                       //~ printf("DIKI_C\n"); 
+                       break;
+               case DIKI_D:
+                       *key_code = GF_KEY_D; 
+                       //~ printf("DIKI_D\n"); 
+                       break;
+               case DIKI_E:
+                       *key_code = GF_KEY_E; 
+                       //~ printf("DIKI_E\n"); 
+                       break;
+               case DIKI_F:
+                       *key_code = GF_KEY_F; break;
+               case DIKI_G:
+                       *key_code = GF_KEY_G; break;
+               case DIKI_H:
+                       *key_code = GF_KEY_H; break;
+               case DIKI_I:
+                       *key_code = GF_KEY_I; break;
+               case DIKI_J:
+                       *key_code = GF_KEY_J; break;
+               case DIKI_K:
+                       *key_code = GF_KEY_K; break;
+               case DIKI_L:
+                       *key_code = GF_KEY_L; break;
+               case DIKI_M:
+                       *key_code = GF_KEY_M; break;
+               case DIKI_N:
+                       *key_code = GF_KEY_N; break;
+               case DIKI_O:
+                       *key_code = GF_KEY_O; break;
+               case DIKI_P:
+                       *key_code = GF_KEY_P; break;
+               case DIKI_Q:
+                       *key_code = GF_KEY_Q; break;
+               case DIKI_R:
+                       *key_code = GF_KEY_R; break;
+               case DIKI_S:
+                       *key_code = GF_KEY_S; break;
+               case DIKI_T:
+                       *key_code = GF_KEY_T; break;
+               case DIKI_U:
+                       *key_code = GF_KEY_U; break;
+               case DIKI_V:
+                       *key_code = GF_KEY_V; break;
+               case DIKI_W:
+                       *key_code = GF_KEY_W; break;
+               case DIKI_X:
+                       *key_code = GF_KEY_X; break;
+               case DIKI_Y:
+                       *key_code = GF_KEY_Y; break;
+               case DIKI_Z:
+                       *key_code = GF_KEY_Z; break;
+                       
+               case DIKI_PRINT:
+                       *key_code = GF_KEY_PRINTSCREEN; break;
+               case DIKI_SCROLL_LOCK:
+                       *key_code = GF_KEY_SCROLL; break;
+               case DIKI_PAUSE:
+                       *key_code = GF_KEY_PAUSE; break;
+               case DIKI_INSERT:
+                       *key_code = GF_KEY_INSERT; break;
+               case DIKI_DELETE:
+                       *key_code = GF_KEY_DEL; break;
+               case DIKI_HOME:
+                       *key_code = GF_KEY_HOME; break;
+               case DIKI_END:
+                       *key_code = GF_KEY_END; break;
+               case DIKI_PAGE_UP:
+                       *key_code = GF_KEY_PAGEUP; break;
+               case DIKI_PAGE_DOWN:
+                       *key_code = GF_KEY_PAGEDOWN; break;
+               
+               /* arrows */
+               case DIKI_UP:
+                       *key_code = GF_KEY_UP; break;
+               case DIKI_DOWN:
+                       *key_code = GF_KEY_DOWN; break;
+               case DIKI_RIGHT:
+                       *key_code = GF_KEY_RIGHT; break;
+               case DIKI_LEFT:
+                       *key_code = GF_KEY_LEFT; break;
+               /* extended numerical pad */
+               case DIKI_NUM_LOCK:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_NUMLOCK; break;
+               case DIKI_KP_DIV:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_SLASH; break;
+               case DIKI_KP_MULT:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_STAR; break;
+               case DIKI_KP_MINUS:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_HYPHEN; break;
+               case DIKI_KP_PLUS:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_PLUS; break;
+               case DIKI_KP_ENTER:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_ENTER; break; 
+               case DIKI_KP_DECIMAL:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_FULLSTOP; break;
+               case DIKI_KP_0:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_0; break;
+               case DIKI_KP_1:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_1; break;
+               case DIKI_KP_2:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_2; break;
+               case DIKI_KP_3:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_3; break;
+               case DIKI_KP_4:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_4; break;
+               case DIKI_KP_5: 
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_5; break;
+               case DIKI_KP_6:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_6; break;
+               case DIKI_KP_7:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_7; break;
+               case DIKI_KP_8:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_8; break;
+               case DIKI_KP_9:
+                       *flags = GF_KEY_EXT_NUMPAD; *key_code = GF_KEY_9; break;
+               
+               /* Fn functions */
+               case DIKI_F1:
+                       *key_code = GF_KEY_F1; break;
+               case DIKI_F2:
+                       *key_code = GF_KEY_F2; break;
+               case DIKI_F3:
+                       *key_code = GF_KEY_F3; break;
+               case DIKI_F4:
+                       *key_code = GF_KEY_F4; break;
+               case DIKI_F5:
+                       *key_code = GF_KEY_F5; break;
+               case DIKI_F6:
+                       *key_code = GF_KEY_F6; break;
+               case DIKI_F7:
+                       *key_code = GF_KEY_F7; break;
+               case DIKI_F8:
+                       *key_code = GF_KEY_F8; break;
+               case DIKI_F9:
+                       *key_code = GF_KEY_F9; break;
+               case DIKI_F10:
+                       *key_code = GF_KEY_F10; break;
+               case DIKI_F11:
+                       *key_code = GF_KEY_F11; break;
+               case DIKI_F12:
+                       *key_code = GF_KEY_F12; break;
+
+               default:
+                       *key_code = GF_KEY_UNIDENTIFIED; break;
+       }
+}
+
diff --git a/modules/droid_cam/droid_cam.c b/modules/droid_cam/droid_cam.c
new file mode 100644 (file)
index 0000000..ec6cbd7
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Authors: Ivica Arsov
+ *                     Copyright (c) Institut Telecom 2011-20XX
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Android camera module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  GPAC 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <gpac/terminal.h>
+#include <gpac/internal/terminal_dev.h>
+#include <gpac/modules/codec.h>
+#include <gpac/constants.h>
+#include <gpac/modules/service.h>
+#include <gpac/thread.h>
+#include <gpac/media_tools.h>
+
+#include <jni.h>
+#include <android/log.h>
+
+#define LOG_TAG "ANDROID_CAMERA"
+#ifdef ANDROID
+#  define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#  define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#else
+#  define QUOTEME_(x) #x
+#  define QUOTEME(x) QUOTEME_(x)
+#  define LOGI(...) printf("I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__)
+#  define LOGE(...) printf("E/" LOG_TAG "(" ")" __VA_ARGS__)
+#endif
+
+static JavaVM* javaVM = 0;
+static jclass camCtrlClass;
+static jmethodID cid;
+static jmethodID startCamera;
+static jmethodID stopCamera;
+static jmethodID startProcessing;
+static jmethodID stopProcessing;
+static jmethodID getImageFormat;
+static jmethodID getImageHeight;
+static jmethodID getImageWidth;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+       JNIEnv* env = 0;
+  javaVM = vm;
+
+       if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
+               return -1;
+
+       // Get the class and its methods in the main env
+
+       // Get the CameraController class
+       // This is just a local refenrece. Cannot be used in the other JNI calls.
+       camCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/Preview");
+       if (camCtrlClass == 0)
+       {
+               LOGE("CameraController class = null [myCamera.c, startCameraNative()]");
+               return -1;
+       }
+
+       // Get Global Reference to be able to use the class
+       camCtrlClass = (*env)->NewGlobalRef(env, camCtrlClass);
+       if ( camCtrlClass == 0 )
+       {
+               LOGE("[MPEG-V_IN] Cannot create Global Reference\n");
+               return -1;
+       }
+
+       // Get the method ID for the CameraController constructor.
+       cid = (*env)->GetMethodID(env, camCtrlClass, "<init>", "()V");
+       if (cid == 0)
+       {
+               LOGE("Method ID for CameraController constructor is null [myCamera.c, startCameraNative()]");
+               return -1;
+       }
+
+       // Get startCamera() method from class CameraController
+       startCamera = (*env)->GetMethodID(env, camCtrlClass, "initializeCamera", "(Z)Z");
+       if (startCamera == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function startCamera not found");
+               return -1;
+       }
+
+       stopCamera = (*env)->GetMethodID(env, camCtrlClass, "stopCamera", "()V");
+       if (stopCamera == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function stopCamera not found");
+               return -1;
+       }
+
+       startProcessing = (*env)->GetMethodID(env, camCtrlClass, "resumePreview", "()V");
+       if (startProcessing == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function startProcessing not found");
+               return -1;
+       }
+
+       stopProcessing = (*env)->GetMethodID(env, camCtrlClass, "pausePreview", "()V");
+       if (stopProcessing == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function stopProcessing not found");
+               return -1;
+       }
+
+       getImageFormat = (*env)->GetMethodID(env, camCtrlClass, "getPreviewFormat", "()I");
+       if (getImageFormat == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function getImageFormat not found");
+               return -1;
+       }
+
+       getImageHeight = (*env)->GetMethodID(env, camCtrlClass, "getImageHeight", "()I");
+       if (getImageHeight == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function getImageHeight not found");
+               return -1;
+       }
+
+       getImageWidth = (*env)->GetMethodID(env, camCtrlClass, "getImageWidth", "()I");
+       if (getImageWidth == 0)
+       {
+               LOGE("[ANDROID_CAMERA] Function getImageWidth not found");
+               return -1;
+       }
+
+       return JNI_VERSION_1_2;
+}
+//----------------------------------------------------------------------
+JavaVM* GetJavaVM()
+{
+    return javaVM;
+}
+
+JNIEnv* GetEnv()
+{
+       JNIEnv* env;
+       if ( (*GetJavaVM())->GetEnv(GetJavaVM(), (void**)&env, JNI_VERSION_1_2) != JNI_OK )
+               return NULL;
+
+       return env;
+}
+
+void JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+       JNIEnv* env = 0;
+       
+       if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
+               return;
+       
+       (*env)->DeleteGlobalRef(env, camCtrlClass);
+}
+//----------------------------------------------------------------------
+
+
+#define CAM_PIXEL_FORMAT GF_PIXEL_NV21
+//GF_PIXEL_RGB_32
+#define CAM_PIXEL_SIZE 1.5f
+//4
+#define CAM_WIDTH 640
+#define CAM_HEIGHT 480
+
+//GF_PIXEL_RGB_24;
+
+typedef struct
+{
+       GF_InputService *input;
+       /*the service we're responsible for*/
+       GF_ClientService *service;
+       LPNETCHANNEL* channel;
+
+       /*input file*/
+       u32 time_scale;
+
+       u32 base_track_id;
+
+       struct _tag_terminal *term;
+
+       u32 cntr;
+
+       u32 width;
+       u32 height;
+
+       Bool started;
+
+       JNIEnv* env;
+       u8 isAttached;
+       jclass camCtrlClass;
+       jmethodID cid;
+       jobject camCtrlObj;
+       jmethodID startCamera;
+       jmethodID stopCamera;
+       jmethodID startProcessing;
+       jmethodID stopProcessing;
+       jmethodID getImageFormat;
+       jmethodID getImageHeight;
+       jmethodID getImageWidth;
+
+} ISOMReader;
+
+ISOMReader* globReader;
+
+void loadCameraControler(ISOMReader *read);
+void camStartCamera(ISOMReader *read);
+void camStopCamera(ISOMReader *read);
+
+Bool CAM_CanHandleURL(GF_InputService *plug, const char *url)
+{
+       if (!strnicmp(url, "hw://camera", 11)) return 1;
+
+       return 0;
+}
+
+void unloadCameraControler(ISOMReader *read)
+{
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] unloadCameraControler: %d\n", gf_th_id()));
+       if ( read->isAttached )
+       {
+               //(*rc->env)->PopLocalFrame(rc->env, NULL);
+               (*GetJavaVM())->DetachCurrentThread(GetJavaVM());
+               read->isAttached = 0;
+       }
+
+       read->env = NULL;
+}
+
+u32 unregisterFunc(void* data)
+{
+       unloadCameraControler(globReader);
+}
+
+void loadCameraControler(ISOMReader *read)
+{
+       JNIEnv* env = NULL;
+       jint res = 0;
+
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] loadCameraControler: %d\n", gf_th_id()));
+
+       // Get the JNI interface pointer
+       res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2);
+       if ( res == JNI_EDETACHED )
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n"));
+               if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) )
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res));
+                       return;
+               }
+               gf_register_before_exit_function(gf_th_current(), unregisterFunc);
+               read->isAttached = 1;
+               //(*rc->env)->PushLocalFrame(rc->env, 2);
+       }
+       else 
+               if ( res == JNI_EVERSION )
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The specified version is not supported\n"));
+                       return;
+               }
+
+       read->env = env;
+       read->camCtrlClass = camCtrlClass;
+       read->cid = cid;
+       read->startCamera = startCamera;
+       read->stopCamera = stopCamera;
+       read->startProcessing = startProcessing;
+       read->stopProcessing = stopProcessing;
+       read->getImageFormat = getImageFormat;
+       read->getImageHeight = getImageHeight;
+       read->getImageWidth = getImageWidth;
+
+       // Create the object.
+       read->camCtrlObj = (*env)->NewObject(env, read->camCtrlClass, read->cid);
+       if (read->camCtrlObj == 0)
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("CameraController object creation failed. [myCamera.c, startCameraNative()]"));
+               return;
+       }
+}
+
+GF_Err CAM_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
+{
+       ISOMReader *read;
+       if (!plug || !plug->priv || !serv) return GF_SERVICE_ERROR;
+       read = (ISOMReader *) plug->priv;
+
+       read->input = plug;
+       read->service = serv;
+       read->base_track_id = 1;
+       read->time_scale = 1000;
+
+       read->term = serv->term;
+
+       loadCameraControler(read);
+
+       /*reply to user*/
+       gf_term_on_connect(serv, NULL, GF_OK);
+       //if (read->no_service_desc) isor_declare_objects(read);
+
+       return GF_OK;
+}
+
+GF_Err CAM_CloseService(GF_InputService *plug)
+{
+       GF_Err reply;
+       ISOMReader *read;
+       if (!plug || !plug->priv) return GF_SERVICE_ERROR;
+       read = (ISOMReader *) plug->priv;
+       reply = GF_OK;
+
+       (*GetEnv())->DeleteLocalRef( GetEnv(), read->camCtrlObj ); 
+
+       //unloadCameraControler(read);
+
+       gf_term_on_disconnect(read->service, NULL, reply);
+       return GF_OK;
+}
+
+u32 getWidth(ISOMReader *read);
+u32 getHeight(ISOMReader *read);
+
+static GF_Descriptor *CAM_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
+{
+       u32 trackID;
+       GF_ESD *esd;
+       ISOMReader *read;
+       GF_ObjectDescriptor *od;
+       GF_BitStream *bs;
+       char *buf;
+       u32 buf_size;
+       if (!plug || !plug->priv) return NULL;
+       read = (ISOMReader *) plug->priv;
+
+       trackID = 0;
+       trackID = read->base_track_id;
+       read->base_track_id = 0;
+
+       if (trackID && (expect_type==GF_MEDIA_OBJECT_VIDEO) ) {
+               od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
+               od->objectDescriptorID = 1;
+
+               esd = gf_odf_desc_esd_new(0);
+               esd->slConfig->timestampResolution = 1000;
+               esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+               esd->ESID = 1;
+               esd->decoderConfig->objectTypeIndication = GPAC_OTI_RAW_MEDIA_STREAM;
+               
+               bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+
+               read->width = getWidth(read);
+               read->height = getHeight(read);
+
+               gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc
+               gf_bs_write_u16(bs, read->width); // width
+               gf_bs_write_u16(bs, read->height); // height
+               gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize
+               gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride
+
+               gf_bs_align(bs);
+               gf_bs_get_content(bs, &buf, &buf_size);
+               gf_bs_del(bs);
+
+               esd->decoderConfig->decoderSpecificInfo->data = buf;
+               esd->decoderConfig->decoderSpecificInfo->dataLength = buf_size;
+
+               gf_list_add(od->ESDescriptors, esd);
+               return (GF_Descriptor *) od;
+       }
+
+       return NULL;
+}
+
+
+
+
+GF_Err CAM_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
+{
+       GF_Err e;
+       ISOMReader *read;
+       if (!plug || !plug->priv) return GF_SERVICE_ERROR;
+       read = (ISOMReader *) plug->priv;
+
+       e = GF_OK;
+       if (upstream) {
+               e = GF_ISOM_INVALID_FILE;
+       }
+
+       read->channel = channel;
+
+       camStartCamera(read);
+
+       gf_term_on_connect(read->service, channel, e);
+       return e;
+}
+
+GF_Err CAM_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
+{
+       GF_Err e;
+       ISOMReader *read;
+       if (!plug || !plug->priv) return GF_SERVICE_ERROR;
+       read = (ISOMReader *) plug->priv;
+
+       e = GF_OK;
+
+       camStopCamera(read);
+
+       gf_term_on_disconnect(read->service, channel, e);
+       return e;
+}
+
+int* decodeYUV420SP( char* yuv420sp, int width, int height)
+{
+       int frameSize = width * height;
+       int j, yp, uvp, i, y, y1192, r, g, b, u, v;
+       int ti, tj;
+
+       int* rgb = (int*)gf_malloc(width*height*4);
+       for (j = 0, yp = 0, tj=height-1; j < height; j++, tj--)
+       {
+               uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+               for (i = 0, ti=0; i < width; i++, yp++, ti+=width)
+               {
+                       y = (0xff & ((int) yuv420sp[yp])) - 16;
+                       if (y < 0) y = 0;
+                       if ((i & 1) == 0)
+                       {
+                               v = (0xff & yuv420sp[uvp++]) - 128;
+                               u = (0xff & yuv420sp[uvp++]) - 128;
+                       }
+
+                       y1192 = 1192 * y;
+                       r = (y1192 + 1634 * v);
+                       g = (y1192 - 833 * v - 400 * u);
+                       b = (y1192 + 2066 * u);
+
+                       if (r < 0)
+                               r = 0;
+                       else if (r > 262143)
+                               r = 262143;
+                       if (g < 0)
+                               g = 0;
+                       else if (g > 262143)
+                               g = 262143;
+                       if (b < 0)
+                               b = 0;
+                       else if (b > 262143)
+                               b = 262143;
+
+                       rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000)
+                                               | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
+//                     rgb[ti+tj] = 0xff000000 | ((r << 6) & 0xff0000)
+//                                     | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
+               }
+       }
+       return rgb;
+}
+
+void Java_com_gpac_Osmo4_Preview_processFrameBuf( JNIEnv* env, jobject thiz, jbyteArray arr)
+{
+       u8* data;
+       u32 datasize;
+       ISOMReader* ctx = globReader;
+       GF_SLHeader hdr;
+       u32 cts = 0;
+       u32 convTime = 0;
+       u32 j = 0;
+       jbyte *jdata;
+       jsize len;
+
+       if ( ctx->started )
+       {
+               len = (*env)->GetArrayLength(env, arr);
+               jdata = (*env)->GetByteArrayElements(env,arr,0);
+
+               convTime = gf_term_get_time(ctx->term);
+
+               data = (u8*)jdata;//(u8*)decodeYUV420SP((char*)jdata, ctx->width, ctx->height); //
+               datasize = len;//ctx->width * ctx->height * CAM_PIXEL_SIZE;//
+
+               cts = gf_term_get_time(ctx->term);
+
+               convTime = cts - convTime;
+
+               memset(&hdr, 0, sizeof(hdr));
+               hdr.compositionTimeStampFlag = 1;
+               hdr.compositionTimeStamp = cts;
+               gf_term_on_sl_packet(ctx->service, ctx->channel, (void*)data, datasize, &hdr, GF_OK);
+
+               //gf_free(data);
+
+               (*env)->ReleaseByteArrayElements(env,arr,jdata,JNI_ABORT);
+
+               //GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Camera Frame Sent %d\n", gf_sys_clock()));
+       }
+}
+
+void CallCamMethod(ISOMReader *read, jmethodID methodID)
+{
+       JNIEnv* env = NULL;
+       jint res = 0;
+       u8 isAttached = 0;
+
+       // Get the JNI interface pointer
+       res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2);
+       if ( res == JNI_EDETACHED )
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n"));
+               if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) )
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res));
+                       return;
+               }
+               if ( env != read->env )
+                       isAttached = 1;
+       }
+
+       (*env)->CallNonvirtualVoidMethod(env, read->camCtrlObj, read->camCtrlClass, methodID);
+
+       if (isAttached)
+       {       
+               (*GetJavaVM())->DetachCurrentThread(GetJavaVM());
+       }
+}
+
+void camStartCamera(ISOMReader *read)
+{
+       JNIEnv* env = NULL;
+       jboolean isPortrait = JNI_FALSE;
+
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] startCamera: %d\n", gf_th_id()));
+
+       // Get the JNI interface pointer
+       env = read->env;
+
+       (*env)->CallNonvirtualBooleanMethod(env, read->camCtrlObj, read->camCtrlClass, read->startCamera, isPortrait);
+}
+
+void camStopCamera(ISOMReader *read)
+{
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] stopCamera: %d\n", gf_th_id()));
+
+       CallCamMethod(read, read->stopCamera);
+}
+
+void pauseCamera(ISOMReader *read)
+{
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] pauseCamera: %d\n", gf_th_id()));
+
+       read->started = 0;
+       CallCamMethod(read, read->stopProcessing);
+}
+
+void resumeCamera(ISOMReader *read)
+{
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] resumeCamera: %d\n", gf_th_id()));
+
+       read->started = 1;
+       CallCamMethod(read, read->startProcessing);
+}
+
+u32 getWidth(ISOMReader *read)
+{
+       JNIEnv* env = NULL;
+
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getWidth: %d\n", gf_th_id()));
+
+       // Get the JNI interface pointer
+       env = read->env;
+
+       return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageWidth);
+}
+
+u32 getHeight(ISOMReader *read)
+{
+       JNIEnv* env = NULL;
+
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getHeight: %d\n", gf_th_id()));
+
+       // Get the JNI interface pointer
+       env = read->env;
+
+       return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageHeight);
+}
+
+GF_Err CAM_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
+{
+       ISOMReader *read;
+       GF_BitStream *bs;
+       char *buf;
+       u32 buf_size;
+       if (!plug || !plug->priv || !com) return GF_SERVICE_ERROR;
+       read = (ISOMReader *) plug->priv;
+
+       if (com->command_type==GF_NET_SERVICE_INFO) {
+               return GF_OK;
+       }
+       if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) {
+               return GF_NOT_SUPPORTED;
+       }
+       if (!com->base.on_channel) return GF_NOT_SUPPORTED;
+
+       switch (com->command_type) {
+       case GF_NET_CHAN_INTERACTIVE:
+               return GF_OK;
+       case GF_NET_CHAN_BUFFER:
+               com->buffer.max = com->buffer.min = 0;
+               return GF_OK;
+       case GF_NET_CHAN_PLAY:
+               resumeCamera(read);
+               return GF_OK;
+       case GF_NET_CHAN_STOP:
+               pauseCamera(read);
+               return GF_OK;
+       /*nothing to do on MP4 for channel config*/
+       case GF_NET_CHAN_CONFIG:
+               return GF_OK;
+       case GF_NET_CHAN_GET_PIXEL_AR:
+               return 1<<16;//gf_isom_get_pixel_aspect_ratio(read->mov, ch->track, 1, &com->par.hSpacing, &com->par.vSpacing);
+       case GF_NET_CHAN_GET_DSI:
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cam get DSI\n"));
+                       /*it may happen that there are conflicting config when using ESD URLs...*/
+                       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+
+                       read->width = getWidth(read);
+                       read->height = getHeight(read);
+
+                       gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc
+                       gf_bs_write_u16(bs, read->width); // width
+                       gf_bs_write_u16(bs, read->height); // height
+                       gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize
+                       gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride
+
+                       gf_bs_align(bs);
+                       gf_bs_get_content(bs, &buf, &buf_size);
+                       gf_bs_del(bs);
+
+                       com->get_dsi.dsi = buf;
+                       com->get_dsi.dsi_len = buf_size;
+                       return GF_OK;
+               }
+       }
+       return GF_NOT_SUPPORTED;
+}
+
+GF_InputService *CAM_client_load()
+{
+       ISOMReader *reader;
+       GF_InputService *plug;
+       GF_SAFEALLOC(plug, GF_InputService);
+       GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC Camera Plugin", "gpac distribution")
+       plug->CanHandleURL = CAM_CanHandleURL;
+       plug->ConnectService = CAM_ConnectService;
+       plug->CloseService = CAM_CloseService;
+       plug->GetServiceDescriptor = CAM_GetServiceDesc;
+       plug->ConnectChannel = CAM_ConnectChannel;
+       plug->DisconnectChannel = CAM_DisconnectChannel;
+       plug->ServiceCommand = CAM_ServiceCommand;
+
+       GF_SAFEALLOC(reader, ISOMReader);
+       plug->priv = reader;
+       globReader = reader;
+       return plug;
+}
+
+void CAM_client_del(GF_BaseInterface *bi)
+{
+       GF_InputService *plug = (GF_InputService *) bi;
+       ISOMReader *read = (ISOMReader *)plug->priv;
+
+       gf_free(read);
+       gf_free(bi);
+}
+
+GF_EXPORT
+const u32 *QueryInterfaces()
+{
+       static u32 si [] = {
+               GF_NET_CLIENT_INTERFACE,
+               0
+       };
+       return si;
+}
+
+GF_EXPORT
+GF_BaseInterface *LoadInterface(u32 InterfaceType)
+{
+       if (InterfaceType == GF_NET_CLIENT_INTERFACE)
+               return (GF_BaseInterface *)CAM_client_load();
+       return NULL;
+}
+
+GF_EXPORT
+void ShutdownInterface(GF_BaseInterface *ifce)
+{
+       switch (ifce->InterfaceType) {
+       case GF_NET_CLIENT_INTERFACE: CAM_client_del(ifce); break;
+       }
+}
diff --git a/modules/droid_mpegv/droid_mpegv.c b/modules/droid_mpegv/droid_mpegv.c
new file mode 100644 (file)
index 0000000..e0bf366
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Authors: Ivica Arsov
+ *                     Copyright (c) Institut Telecom 2011-20XX
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / MPEG-V Input sensor for android
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *             
+ */
+
+#include <jni.h>
+#include <android/log.h>
+
+/*driver interfaces*/
+
+#include <gpac/list.h>
+#include <gpac/constants.h>
+
+#include <gpac/setup.h>
+
+#include <gpac/modules/codec.h>
+#include <gpac/scenegraph_vrml.h>
+
+#include <gpac/thread.h>
+
+#define LOG_TAG "MPEG-V_IN"
+#ifdef ANDROID
+#  define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#  define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#else
+#  define QUOTEME_(x) #x
+#  define QUOTEME(x) QUOTEME_(x)
+#  define LOGI(...) printf("I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__)
+#  define LOGE(...) printf("E/" LOG_TAG "(" ")" __VA_ARGS__)
+#endif
+
+JNIEXPORT void JNICALL Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data);
+
+static JavaVM* javaVM = 0;
+static jclass sensCtrlClass;
+static jmethodID cid;
+static jmethodID startSensor;
+static jmethodID stopSensor;
+
+//----------------------------------------------------------------------
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+       JNIEnv* env = 0;
+       javaVM = vm;
+
+       if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
+               return -1;
+
+       // Get the class and its methods in the main env
+
+       // Get the CameraController class
+       // This is just a local refenrece. Cannot be used in the other JNI calls.
+       sensCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/MPEGVSensor");
+       if (sensCtrlClass == 0)
+       {
+               LOGE("[MPEG-V_IN] Class MPEGVSensor not found\n");
+               return -1;
+       }
+
+       // Get Global Reference to be able to use the class
+       sensCtrlClass = (*env)->NewGlobalRef(env, sensCtrlClass);
+       if ( sensCtrlClass == 0 )
+       {
+               LOGE("[MPEG-V_IN] Caanot create Global Reference\n");
+               return -1;
+       }
+
+       // Get the method ID for the CameraController constructor.
+       cid = (*env)->GetMethodID(env, sensCtrlClass, "<init>", "()V");
+       if (cid == 0)
+       {
+               LOGE("[MPEG-V_IN] MPEGVSensor Constructor not found\n");
+               return -1;
+       }
+
+       // Get startCamera() method from class CameraController
+       startSensor = (*env)->GetMethodID(env, sensCtrlClass, "startSensor", "(II)V");
+       if (startSensor == 0)
+       {
+               LOGE("[MPEG-V_IN] Function startSensor not found\n");
+               return -1;
+       }
+
+       stopSensor = (*env)->GetMethodID(env, sensCtrlClass, "stopSensor", "()V");
+       if (stopSensor == 0)
+       {
+               LOGE("[MPEG-V_IN] Function stopSensor not found\n");
+               return -1;
+       }
+
+       return JNI_VERSION_1_2;
+}
+
+void JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+       JNIEnv* env = 0;
+       
+       if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
+               return;
+       
+       (*env)->DeleteGlobalRef(env, sensCtrlClass);
+}
+//----------------------------------------------------------------------
+JavaVM* GetJavaVM()
+{
+       return javaVM;
+}
+//----------------------------------------------------------------------
+
+typedef struct
+{
+       char sensor[50];
+       u16 sensorAndroidType;
+       u8 isAttached;
+
+       GF_Thread *trd;
+       u8 stop;
+
+       JNIEnv* env;
+       jclass sensCtrlClass;
+       jmethodID cid;
+       jobject sensCtrlObj;
+       jmethodID startSensor;
+       jmethodID stopSensor;
+} MPEGVSensorContext;
+
+#define MPEGVSCTX      MPEGVSensorContext *rc = (MPEGVSensorContext *)dr->udta
+
+void unloadSensorController(MPEGVSensorContext *rc)
+{
+       if ( rc->isAttached )
+       {
+               (*rc->env)->PopLocalFrame(rc->env, NULL);
+               (*GetJavaVM())->DetachCurrentThread(GetJavaVM());
+               rc->isAttached = 0;
+       }
+
+       rc->env = NULL;
+}
+
+void loadSensorControler(MPEGVSensorContext *rc)
+{
+       JNIEnv* env = NULL;
+       jint res = 0;
+
+       // Here we can be in a thread
+
+       res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2);
+       if ( res == JNI_EDETACHED )
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The current thread is not attached to the VM, assuming native thread\n"));
+               if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) )
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Attach current thread failed: %d\n", res));
+                       return;
+               }
+               rc->isAttached = 1;
+               (*env)->PushLocalFrame(env, 2);
+       }
+       else 
+               if ( res == JNI_EVERSION )
+               {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The specified version is not supported\n"));
+                       return;
+               }
+       
+       rc->env = env;
+       rc->sensCtrlClass = sensCtrlClass;
+       rc->cid = cid;
+       rc->startSensor = startSensor;
+       rc->stopSensor = stopSensor;    
+
+       // Create the sensor object in the thread
+       rc->sensCtrlObj = (*rc->env)->NewObject(rc->env, rc->sensCtrlClass, rc->cid);
+       if (rc->sensCtrlObj == 0)
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Cannot create MPEGVSensor object\n"));
+               return;
+       }
+}
+
+Bool MPEGVS_RegisterDevice(struct __input_device *dr, const char *urn, GF_BitStream *dsi, void (*AddField)(struct __input_device *_this, u32 fieldType, const char *name))
+{
+       MPEGVSCTX;
+       
+       //"MPEG-V:siv:OrientationSensorType"
+
+       if ( strnicmp(urn, "MPEG-V", 6) )
+               return 0;
+
+       if ( strlen(urn) <= 6 )
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] No sensor type specified\n"));
+               return 0;
+       }
+       
+       if ( strnicmp(urn+6, ":siv:", 5) )
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] Not valid sensor type specified\n"));
+               return 0;
+       }
+
+       strcpy(rc->sensor, urn+11);
+
+       if ( !strcmp(rc->sensor, "OrientationSensorType") )
+       {
+               AddField(dr, GF_SG_VRML_SFVEC3F, "Orientation");
+
+               rc->sensorAndroidType = 3;
+               
+               AddField(dr, GF_SG_VRML_SFVEC3F, "pos");
+
+               return 1;
+       }
+       else
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V_IN] Unsupported sensor type: %s\n", rc->sensor));
+               return 0;
+       }
+}
+
+u32 MPEGVS_OnData(struct __input_device * dr, const char* data)
+{
+       GF_BitStream *bs;
+       char *buf;
+       u32 buf_size;
+       float x, y, z;
+       
+       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+
+       sscanf(data, "%f;%f;%f;", &x, &y, &z);
+
+       gf_bs_write_int(bs, 1, 1);
+       gf_bs_write_float(bs, x);
+       gf_bs_write_float(bs, y);
+       gf_bs_write_float(bs, z);
+
+       gf_bs_align(bs);
+       gf_bs_get_content(bs, &buf, &buf_size);
+       gf_bs_del(bs);
+
+       dr->DispatchFrame(dr, (u8*)buf, buf_size);
+       gf_free(buf);
+
+       return GF_OK;
+}
+
+JNIEXPORT void Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data)
+{
+       jboolean isCopy;
+       const char * cData = (*env)->GetStringUTFChars(env, data, &isCopy);
+
+       MPEGVS_OnData((struct __input_device *)ptr, cData);
+
+       (*env)->ReleaseStringUTFChars(env, data, cData);
+}
+
+u32 ThreadRun(void* param)
+{
+       struct __input_device * dr = (struct __input_device *)param;
+       MPEGVSCTX;
+
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Start: %d\n", gf_th_id()));
+
+       loadSensorControler(rc);
+
+       if (!rc->env || !rc->sensCtrlObj)
+               return;
+
+       (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->startSensor, (s32)dr, rc->sensorAndroidType);
+
+       while (!rc->stop)
+               gf_sleep(10);
+       
+       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Stop: %d\n", gf_th_id()));
+
+       if (!rc->env)
+               return;
+
+       if ( rc->sensCtrlObj )
+       {
+               (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->stopSensor);
+
+               (*rc->env)->DeleteLocalRef( rc->env, rc->sensCtrlObj );
+       }
+
+       unloadSensorController(rc);
+}
+
+void MPEGVS_Start(struct __input_device * dr)
+{
+       MPEGVSCTX;
+       
+       rc->trd = gf_th_new("MPEG-V_IN");
+       gf_th_run(rc->trd, ThreadRun, dr);
+}
+
+void MPEGVS_Stop(struct __input_device * dr)
+{
+       MPEGVSCTX;
+
+       if ( rc->trd )
+       {
+               rc->stop = 1;
+               while ( gf_th_status(rc->trd) == GF_THREAD_STATUS_RUN )
+                       gf_sleep(5);
+
+               gf_th_del(rc->trd);
+               rc->trd = NULL;
+               rc->stop = 0;
+       }
+}
+
+GF_InputSensorDevice* NewMPEGVSInputSesor()
+{
+       MPEGVSensorContext* ctx = NULL;
+       GF_InputSensorDevice* driv = NULL;
+       
+       driv = (GF_InputSensorDevice *) gf_malloc(sizeof(GF_InputSensorDevice));
+       memset(driv, 0, sizeof(GF_InputSensorDevice));
+       GF_REGISTER_MODULE_INTERFACE(driv, GF_INPUT_DEVICE_INTERFACE, "MPEG-V Sensors Input Module", "gpac distribution");
+
+       driv->RegisterDevice = MPEGVS_RegisterDevice;
+       driv->Start = MPEGVS_Start;
+       driv->Stop = MPEGVS_Stop;
+
+       ctx = (MPEGVSensorContext*) gf_malloc (sizeof(MPEGVSensorContext));
+       memset(ctx, 0, sizeof(MPEGVSensorContext));
+       
+       driv->udta = (void*)ctx;
+
+       return driv;
+}
+
+void DeleteMPEGVSInputSensor(GF_InputSensorDevice* dev)
+{
+       MPEGVS_Stop(dev);
+       gf_free(dev->udta);
+       gf_free(dev);
+}
+
+/*interface query*/
+GF_EXPORT
+const u32 *QueryInterfaces() 
+{
+       static u32 si [] = {
+               GF_INPUT_DEVICE_INTERFACE,
+               0
+       };
+       return si; 
+}
+/*interface create*/
+GF_BaseInterface *LoadInterface(u32 InterfaceType)
+{
+       if (InterfaceType == GF_INPUT_DEVICE_INTERFACE) return (GF_BaseInterface *) NewMPEGVSInputSesor();
+       return NULL;
+}
+/*interface destroy*/
+void ShutdownInterface(GF_BaseInterface *ifce)
+{
+       switch (ifce->InterfaceType) {
+       case GF_INPUT_DEVICE_INTERFACE:
+               DeleteMPEGVSInputSensor((GF_InputSensorDevice *)ifce);
+               break;
+       }
+}
+
index 0b0cd498fa64102cbac7b85387f2dced03864de3..6dc2605dec2f6609791ad66348641effa720b94a 100644 (file)
@@ -186,7 +186,12 @@ void DC_DownloadFile(GF_InputService *plug, char *url)
        DCReader *read = (DCReader *) plug->priv;
 
        read->dnload = gf_term_download_new(read->service, url, 0, DC_NetIO, read);
-       if (!read->dnload) gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       if (!read->dnload) {
+               gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
+       }
 }
 
 
index fc050dbc6bbf154986ddfb1b4f634c761994b8b2..0ce8e5930f6bc867ebc97d9d260733612ab4dc77 100644 (file)
@@ -106,11 +106,9 @@ static GF_Err DD_ClearBackBuffer(GF_VideoOutput *dr, u32 color)
        rc.left = rc.top = 0;
        rc.right = dd->width;
        rc.bottom = dd->height;
-#ifdef USE_DX_3
-       hr = IDirectDrawSurface_Blt(dd->pBack, &rc, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
-#else
-       hr = IDirectDrawSurface7_Blt(dd->pBack, &rc, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
-#endif
+
+       hr = dd->pBack->lpVtbl->Blt(dd->pBack, &rc, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
+
        return FAILED(hr) ? GF_IO_ERR : GF_OK;
 }
 
@@ -119,11 +117,7 @@ GF_Err CreateBackBuffer(GF_VideoOutput *dr, u32 Width, u32 Height, Bool use_syst
        Bool force_reinit;
        HRESULT hr;
        const char *opt; 
-#ifdef USE_DX_3
-    DDSURFACEDESC ddsd;
-#else
-    DDSURFACEDESC2 ddsd;
-#endif
+    DDSURFDESC ddsd;
 
        DDCONTEXT;
 
@@ -141,7 +135,7 @@ GF_Err CreateBackBuffer(GF_VideoOutput *dr, u32 Width, u32 Height, Bool use_syst
                return GF_OK;
        }
 
-       if (dd->pBack)  SAFE_DD_RELEASE(dd->pBack);
+       SAFE_DD_RELEASE(dd->pBack);
 
        /*create backbuffer*/
        ZeroMemory(&ddsd, sizeof(ddsd));
@@ -167,11 +161,8 @@ GF_Err CreateBackBuffer(GF_VideoOutput *dr, u32 Width, u32 Height, Bool use_syst
        ddsd.dwWidth = Width;
        ddsd.dwHeight = Height;
 
-#ifdef USE_DX_3
-    hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
-#else
-    hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
-#endif
+       hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
+
        if (FAILED(hr)) {
                if (!dd->systems_memory) {
                        ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
@@ -179,11 +170,7 @@ GF_Err CreateBackBuffer(GF_VideoOutput *dr, u32 Width, u32 Height, Bool use_syst
                        dd->systems_memory = 2;
                        GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[DX Out] Hardware Video not available for backbuffer)\n"));
 
-#ifdef USE_DX_3
-                   hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
-#else
-                   hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
-#endif
+                       hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &dd->pBack, NULL );
                }
                if (FAILED(hr)) return GF_IO_ERR;
        }
@@ -208,27 +195,19 @@ GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
        HRESULT hr;
        DWORD cooplev;
        LPDIRECTDRAW ddraw;
-#ifdef USE_DX_3
-    DDSURFACEDESC ddsd;
-#else
-    DDSURFACEDESC2 ddsd;
-#endif
+    DDSURFDESC ddsd;
        DDPIXELFORMAT pixelFmt;
     LPDIRECTDRAWCLIPPER pcClipper;
        DDCONTEXT;
        
-       if (!dd->cur_hwnd || !Width || !Height) return GF_BAD_PARAM;
+       if (!dd->cur_hwnd || !Width || !Height || !dd->DirectDrawCreate) return GF_BAD_PARAM;
        DestroyObjects(dd);
 
-       if( FAILED( hr = DirectDrawCreate(NULL, &ddraw, NULL ) ) )
+       if( FAILED( hr = dd->DirectDrawCreate(NULL, &ddraw, NULL ) ) )
                return GF_IO_ERR;
 
-#ifdef USE_DX_3
-       hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw, (LPVOID *)&dd->pDD);
-#else
-       hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw7, (LPVOID *)&dd->pDD);
-#endif         
-       IDirectDraw_Release(ddraw);
+       hr = ddraw->lpVtbl->QueryInterface(ddraw, &IID_IDirectDraw7, (LPVOID *)&dd->pDD);
+       ddraw->lpVtbl->Release(ddraw);
        if (FAILED(hr)) return GF_IO_ERR;
 
        dd->switch_res = 0;
@@ -239,9 +218,9 @@ GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
                /*change display mode*/
                if (dd->switch_res) {
 #ifdef USE_DX_3
-                       hr = IDirectDraw_SetDisplayMode(dd->pDD, dd->fs_width, dd->fs_height, dd->video_bpp);
+                       hr = dd->pDD->lpVtbl->SetDisplayMode(dd->pDD, dd->fs_width, dd->fs_height, dd->video_bpp);
 #else
-                       hr = IDirectDraw7_SetDisplayMode(dd->pDD, dd->fs_width, dd->fs_height, dd->video_bpp, 0, 0 );
+                       hr = dd->pDD->lpVtbl->SetDisplayMode(dd->pDD, dd->fs_width, dd->fs_height, dd->video_bpp, 0, 0 );
 #endif
                        if( FAILED(hr)) return GF_IO_ERR;
                }
@@ -249,12 +228,7 @@ GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
                cooplev = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
        }
 
-       
-#ifdef USE_DX_3
-       hr = IDirectDraw_SetCooperativeLevel(dd->pDD, dd->cur_hwnd, cooplev);
-#else
-       hr = IDirectDraw7_SetCooperativeLevel(dd->pDD, dd->cur_hwnd, cooplev);
-#endif
+       hr = dd->pDD->lpVtbl->SetCooperativeLevel(dd->pDD, dd->cur_hwnd, cooplev);
        if( FAILED(hr) ) return GF_IO_ERR;
 
        /*create primary*/
@@ -263,18 +237,15 @@ GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
     ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
 
-#ifdef USE_DX_3
-    if( FAILED(IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->pPrimary, NULL ) ) )
+    hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &dd->pPrimary, NULL);
+       if( FAILED(hr) )
         return GF_IO_ERR;
-#else
-    if( FAILED(hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->pPrimary, NULL ) ) ) 
-               return GF_IO_ERR;
-#endif
 
        /*get pixel format of video board*/
        memset (&pixelFmt, 0, sizeof(pixelFmt));
        pixelFmt.dwSize = sizeof(pixelFmt);
-       hr = IDirectDrawSurface_GetPixelFormat(dd->pPrimary, &pixelFmt);
+
+       hr = dd->pPrimary->lpVtbl->GetPixelFormat(dd->pPrimary, &pixelFmt);
        if( FAILED(hr) ) return GF_IO_ERR;
 
        switch(pixelFmt.dwRGBBitCount) {
@@ -306,53 +277,40 @@ GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
                return GF_IO_ERR;
        }
 
+       hr = dd->pDD->lpVtbl->CreateClipper(dd->pDD, 0, &pcClipper, NULL);
+    if( FAILED(hr)) 
+               return GF_IO_ERR;
 
-#ifdef USE_DX_3
-       if( FAILED( hr = IDirectDraw_CreateClipper(dd->pDD, 0, &pcClipper, NULL ) ) )
-        return GF_IO_ERR;
-#else
-       if( FAILED( hr = IDirectDraw7_CreateClipper(dd->pDD, 0, &pcClipper, NULL ) ) )
-        return GF_IO_ERR;
-#endif
-       
-       if( FAILED( hr = IDirectDrawClipper_SetHWnd(pcClipper, 0, dd->cur_hwnd) ) ) {
-        IDirectDrawClipper_Release(pcClipper);
+       hr = pcClipper->lpVtbl->SetHWnd(pcClipper, 0, dd->cur_hwnd);
+       if( FAILED(hr) ) {
+        pcClipper->lpVtbl->Release(pcClipper);
         return GF_IO_ERR;
     }
-    if( FAILED( hr = IDirectDrawSurface_SetClipper(dd->pPrimary, pcClipper ) ) ) {
-        IDirectDrawClipper_Release(pcClipper);
+    hr = dd->pPrimary->lpVtbl->SetClipper(dd->pPrimary, pcClipper);
+       if( FAILED(hr)) {
+               pcClipper->lpVtbl->Release(pcClipper);
         return GF_IO_ERR;
     }
-       IDirectDrawClipper_Release(pcClipper);
+       pcClipper->lpVtbl->Release(pcClipper);
        dd->ddraw_init = 1;
        /*if YUV not initialize, init using HW video memory to setup HW caps*/
        return CreateBackBuffer(dr, Width, Height, dd->yuv_init);
 }
 
-static GF_Err DD_LockSurface(DDContext *dd, GF_VideoSurface *vi, void *surface)
+static GF_Err DD_LockSurface(DDContext *dd, GF_VideoSurface *vi, LPDDRAWSURFACE surface)
 {
     HRESULT hr;
-#ifdef USE_DX_3
-       DDSURFACEDESC desc;
-#else
-       DDSURFACEDESC2 desc;
-#endif
+       DDSURFDESC desc;
        
        if (!dd || !vi || !surface) return GF_BAD_PARAM;
 
-#ifdef USE_DX_3
-       ZeroMemory(&desc, sizeof(DDSURFACEDESC));
+       ZeroMemory(&desc, sizeof(desc));
        desc.dwSize = sizeof(DDSURFACEDESC);
-       if (FAILED(hr = IDirectDrawSurface_Lock( (LPDIRECTDRAWSURFACE)surface, NULL, &desc, DDLOCK_SURFACEMEMORYPTR | /*DDLOCK_WRITEONLY | */ DDLOCK_WAIT, NULL))) {
-               return GF_IO_ERR;
-       }       
-#else
-       ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
-       desc.dwSize = sizeof(DDSURFACEDESC2);
-       if (FAILED(hr = IDirectDrawSurface7_Lock( (LPDIRECTDRAWSURFACE7) surface, NULL, &desc, DDLOCK_SURFACEMEMORYPTR | /*DDLOCK_WRITEONLY | */ DDLOCK_WAIT, NULL))) {
+
+       hr = surface->lpVtbl->Lock(surface, NULL, &desc, DDLOCK_SURFACEMEMORYPTR | /*DDLOCK_WRITEONLY | */ DDLOCK_WAIT, NULL);
+       if (FAILED(hr)) 
                return GF_IO_ERR;
-       }       
-#endif
+
        vi->video_buffer = desc.lpSurface;
        vi->width = desc.dwWidth;
        vi->height = desc.dwHeight;
@@ -362,15 +320,11 @@ static GF_Err DD_LockSurface(DDContext *dd, GF_VideoSurface *vi, void *surface)
        return GF_OK;
 }
 
-static GF_Err DD_UnlockSurface(DDContext *dd, void *surface)
+static GF_Err DD_UnlockSurface(DDContext *dd, LPDDRAWSURFACE surface)
 {
     HRESULT hr;
        if (!dd || !dd->ddraw_init) return GF_IO_ERR;
-#ifdef USE_DX_3
-       hr = IDirectDrawSurface_Unlock( (LPDIRECTDRAWSURFACE)surface, NULL);
-#else
-       hr = IDirectDrawSurface7_Unlock((LPDIRECTDRAWSURFACE7)surface, NULL);
-#endif
+       hr = surface->lpVtbl->Unlock(surface, NULL);
        return FAILED(hr) ? GF_IO_ERR : GF_OK;
 }
 
@@ -393,12 +347,12 @@ static void *LockOSContext(GF_VideoOutput *dr, Bool do_lock)
        if (!dd->pBack) return NULL;
 
        if (do_lock) {
-               if (!dd->lock_hdc && ! IDirectDrawSurface_IsLost(dd->pBack)) {
-                       if (FAILED(IDirectDrawSurface_GetDC(dd->pBack, &dd->lock_hdc)) ) 
+               if (!dd->lock_hdc && ! dd->pBack->lpVtbl->IsLost(dd->pBack)) {
+                       if (FAILED(dd->pBack->lpVtbl->GetDC(dd->pBack, &dd->lock_hdc)) ) 
                                dd->lock_hdc = NULL;
                } 
        } else if (dd->lock_hdc) {
-               IDirectDrawSurface_ReleaseDC(dd->pBack, dd->lock_hdc);
+               dd->pBack->lpVtbl->ReleaseDC(dd->pBack, dd->lock_hdc);
                dd->lock_hdc = NULL;
        }
        return (void *)dd->lock_hdc ;
@@ -424,7 +378,7 @@ static GF_Err DD_BlitSurface(DDContext *dd, DDSurface *src, GF_Window *src_wnd,
                DDCOLORKEY ck;
                col = GF_COL_ARGB(0xFF, key->r, key->g, key->b);
                ck.dwColorSpaceHighValue = ck.dwColorSpaceLowValue = col;
-               hr = IDirectDrawSurface_SetColorKey(src->pSurface, DDCKEY_SRCBLT, &ck);
+               hr = src->pSurface->lpVtbl->SetColorKey(src->pSurface, DDCKEY_SRCBLT, &ck);
                if (FAILED(hr)) 
                        return GF_IO_ERR;
        }
@@ -433,11 +387,11 @@ static GF_Err DD_BlitSurface(DDContext *dd, DDSurface *src, GF_Window *src_wnd,
                flags = DDBLTFAST_WAIT;
                if (key) flags |= DDBLTFAST_SRCCOLORKEY;
                if (dst_wnd) { left = r_dst.left; top = r_dst.top; } else left = top = 0; 
-               hr = IDirectDrawSurface_BltFast(dd->pBack, left, top, src->pSurface, src_wnd ? &r_src : NULL, flags);
+               hr = dd->pBack->lpVtbl->BltFast(dd->pBack, left, top, src->pSurface, src_wnd ? &r_src : NULL, flags);
        } else {
                flags = DDBLT_WAIT;
                if (key) flags |= DDBLT_KEYSRC;
-               hr = IDirectDrawSurface_Blt(dd->pBack, dst_wnd ? &r_dst : NULL, src->pSurface, src_wnd ? &r_src : NULL, flags, NULL);
+               hr = dd->pBack->lpVtbl->Blt(dd->pBack, dst_wnd ? &r_dst : NULL, src->pSurface, src_wnd ? &r_src : NULL, flags, NULL);
        }
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DX Out] Hardware blit src w=%d,h=%d to dst w=%d,h=%d - result: %08x\n", src_w, src_h, dst_w, dst_h, hr));
        return FAILED(hr) ? GF_IO_ERR : GF_OK;
@@ -445,11 +399,7 @@ static GF_Err DD_BlitSurface(DDContext *dd, DDSurface *src, GF_Window *src_wnd,
 
 static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 pixel_format, Bool check_caps)
 {
-#ifdef USE_DX_3
-       DDSURFACEDESC ddsd;
-#else
-       DDSURFACEDESC2 ddsd;
-#endif
+       DDSURFDESC ddsd;
        HRESULT hr;
        DDCONTEXT;
 
@@ -487,11 +437,8 @@ static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 p
                        ddsd.dwHeight = height;
                        ddsd.ddpfPixelFormat.dwFourCC = get_win_4CC(dr->yuv_pixel_format);
 
-#ifdef USE_DX_3
-                       if( FAILED( hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL ) ) ) {
-#else
-                       if( FAILED( hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL ) ) ) {
-#endif
+                       hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL);
+                       if (FAILED(hr) ) {
                                if (!check_caps) return NULL;
 
                                /*try withou overlay cap*/
@@ -499,11 +446,8 @@ static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 p
                                        dr->hw_caps &= ~GF_VIDEO_HW_HAS_YUV_OVERLAY;
                                        ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
 
-#ifdef USE_DX_3
-                                       if( FAILED( hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL ) ) ) {
-#else
-                                       if( FAILED( hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL ) ) ) {
-#endif
+                                       hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL);
+                                       if( FAILED(hr) ) {
                                                return NULL;
                                        }
                                }
@@ -536,14 +480,9 @@ static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 p
        ddsd.dwWidth = width;
        ddsd.dwHeight = height;
 
-#ifdef USE_DX_3
-       if( FAILED( hr = IDirectDraw_CreateSurface(dd->pDD, &ddsd, &dd->rgb_pool.pSurface, NULL ) ) )
-               return NULL;
-#else
-       if( FAILED( hr = IDirectDraw7_CreateSurface(dd->pDD, &ddsd, &dd->rgb_pool.pSurface, NULL ) ) )
+       hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &dd->rgb_pool.pSurface, NULL);
+       if (FAILED(hr))
                return NULL;
-#endif
-
        dd->rgb_pool.width = width;
        dd->rgb_pool.height = height;
        dd->rgb_pool.format = dd->pixelFormat;
@@ -560,7 +499,8 @@ static GF_Err DD_Blit(GF_VideoOutput *dr, GF_VideoSurface *video_src, GF_Window
        DDCONTEXT;
 
        if (!video_src) {
-               if (overlay_type && dd->yuv_pool.pSurface) IDirectDrawSurface2_UpdateOverlay(dd->yuv_pool.pSurface, NULL, dd->pPrimary, NULL, DDOVER_HIDE, NULL);
+               if (overlay_type && dd->yuv_pool.pSurface) 
+                       dd->yuv_pool.pSurface->lpVtbl->UpdateOverlay(dd->yuv_pool.pSurface, NULL, dd->pPrimary, NULL, DDOVER_HIDE, NULL);
                return GF_OK;
        }
        if (src_wnd) {
@@ -609,21 +549,21 @@ static GF_Err DD_Blit(GF_VideoOutput *dr, GF_VideoSurface *video_src, GF_Window
 
 #if 1
                if (overlay_type==1) {
-                       hr = IDirectDrawSurface2_UpdateOverlay(pool->pSurface, &src_rc, dd->pPrimary, &dst_rc, DDOVER_SHOW, NULL);
+                       hr = pool->pSurface->lpVtbl->UpdateOverlay(pool->pSurface, &src_rc, dd->pPrimary, &dst_rc, DDOVER_SHOW, NULL);
                } else {
                        DDOVERLAYFX ddofx;
                        memset(&ddofx, 0, sizeof(DDOVERLAYFX));
                        ddofx.dwSize = sizeof(DDOVERLAYFX);
                        ddofx.dckDestColorkey.dwColorSpaceLowValue = dr->overlay_color_key;
                        ddofx.dckDestColorkey.dwColorSpaceHighValue = dr->overlay_color_key;
-                       hr = IDirectDrawSurface2_UpdateOverlay(pool->pSurface, &src_rc, dd->pPrimary, &dst_rc, DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE, &ddofx);
+                       hr = pool->pSurface->lpVtbl->UpdateOverlay(pool->pSurface, &src_rc, dd->pPrimary, &dst_rc, DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE, &ddofx);
                }
                if (FAILED(hr)) {
-                       IDirectDrawSurface2_UpdateOverlay(pool->pSurface, NULL, dd->pPrimary, NULL, DDOVER_HIDE, NULL);
+                       pool->pSurface->lpVtbl->UpdateOverlay(pool->pSurface, NULL, dd->pPrimary, NULL, DDOVER_HIDE, NULL);
                }
 #else
                if (overlay_type==1) {
-                       hr = IDirectDrawSurface_Blt(dd->pPrimary, &dst_rc, pool->pSurface, &src_rc, 0, NULL);
+                       hr = dd->pPrimary->lpVtbl->Blt(dd->pPrimary, &dst_rc, pool->pSurface, &src_rc, 0, NULL);
                } else {
                        DDBLTFX ddfx;
                        memset(&ddfx, 0, sizeof(DDBLTFX));
@@ -631,7 +571,7 @@ static GF_Err DD_Blit(GF_VideoOutput *dr, GF_VideoSurface *video_src, GF_Window
                        ddfx.ddckDestColorkey.dwColorSpaceLowValue = dr->overlay_color_key;
                        ddfx.ddckDestColorkey.dwColorSpaceHighValue = dr->overlay_color_key;
 
-                       hr = IDirectDrawSurface_Blt(dd->pPrimary, &dst_rc, pool->pSurface, &src_rc, DDBLT_WAIT | DDBLT_KEYDESTOVERRIDE, &ddfx);
+                       hr = dd->pPrimary->lpVtbl->Blt(dd->pPrimary, &dst_rc, pool->pSurface, &src_rc, DDBLT_WAIT | DDBLT_KEYDESTOVERRIDE, &ddfx);
                }
 #endif
                return FAILED(hr) ? GF_IO_ERR : GF_OK;
@@ -720,17 +660,10 @@ void DD_InitYUV(GF_VideoOutput *dr)
 
                dr->hw_caps |= GF_VIDEO_HW_HAS_YUV | GF_VIDEO_HW_HAS_YUV_OVERLAY;
 
-#ifdef USE_DX_3
-               IDirectDraw_GetFourCCCodes(dd->pDD, &numCodes, NULL);
+               dd->pDD->lpVtbl->GetFourCCCodes(dd->pDD, &numCodes, NULL);
                if (!numCodes) return;
                codes = (DWORD *)gf_malloc(numCodes*sizeof(DWORD));
-               IDirectDraw_GetFourCCCodes(dd->pDD, &numCodes, codes);
-#else
-               IDirectDraw7_GetFourCCCodes(dd->pDD, &numCodes, NULL);
-               if (!numCodes) return;
-               codes = (DWORD *)gf_malloc(numCodes*sizeof(DWORD));
-               IDirectDraw7_GetFourCCCodes(dd->pDD, &numCodes, codes);
-#endif
+               dd->pDD->lpVtbl->GetFourCCCodes(dd->pDD, &numCodes, codes);
                
                num_yuv = 0;
                for (i=0; i<numCodes; i++) {
index 6396be673f3e021bcad7b17c00d3c55436ed1e99..3c5f02fa9dfdbb8a9990774a192d4f95cffbd9fc 100644 (file)
@@ -37,6 +37,7 @@ const static GUID  GPAC_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,
 #endif
 
 
+typedef HRESULT (WINAPI *DIRECTSOUNDCREATEPROC)(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
 
 /*
                DirectSound audio output
@@ -60,6 +61,9 @@ typedef struct
     u32 frame_state[MAX_NUM_BUFFERS];
     DSBPOSITIONNOTIFY notif_events[MAX_NUM_BUFFERS];
     HANDLE events[MAX_NUM_BUFFERS];
+
+       HMODULE hDSoundLib;
+       DIRECTSOUNDCREATEPROC DirectSoundCreate;
 } DSContext;
 
 #define DSCONTEXT()            DSContext *ctx = (DSContext *)dr->opaque;
@@ -84,9 +88,9 @@ static GF_Err DS_Setup(GF_AudioOutput *dr, void *os_handle, u32 num_buffers, u32
        ctx->cfg_duration = total_duration;
        if (ctx->cfg_num_buffers <= 1) ctx->cfg_num_buffers = 2;
 
-       if ( FAILED( hr = DirectSoundCreate( NULL, &ctx->pDS, NULL ) ) ) return GF_IO_ERR;
+       if ( FAILED( hr = ctx->DirectSoundCreate( NULL, &ctx->pDS, NULL ) ) ) return GF_IO_ERR;
        flags = DSSCL_EXCLUSIVE;
-       if( FAILED( hr = IDirectSound_SetCooperativeLevel(ctx->pDS, ctx->hWnd, DSSCL_EXCLUSIVE) ) ) {
+       if( FAILED( hr = ctx->pDS->lpVtbl->SetCooperativeLevel(ctx->pDS, ctx->hWnd, DSSCL_EXCLUSIVE) ) ) {
                SAFE_DS_RELEASE( ctx->pDS ); 
                return GF_IO_ERR;
        }
@@ -99,10 +103,10 @@ void DS_ResetBuffer(DSContext *ctx)
     VOID *pLock = NULL;
     DWORD size;
 
-    if( FAILED(IDirectSoundBuffer_Lock(ctx->pOutput, 0, ctx->buffer_size*ctx->num_audio_buffer, &pLock, &size, NULL, NULL, 0 ) ) )
+    if( FAILED(ctx->pOutput->lpVtbl->Lock(ctx->pOutput, 0, ctx->buffer_size*ctx->num_audio_buffer, &pLock, &size, NULL, NULL, 0 ) ) )
         return;
        memset(pLock, 0, (size_t) size);
-       IDirectSoundBuffer_Unlock(ctx->pOutput, pLock, size, NULL, 0L); 
+       ctx->pOutput->lpVtbl->Unlock(ctx->pOutput, pLock, size, NULL, 0L); 
 }
 
 void DS_ReleaseBuffer(GF_AudioOutput *dr)
@@ -111,7 +115,7 @@ void DS_ReleaseBuffer(GF_AudioOutput *dr)
        DSCONTEXT();
 
        /*stop playing and notif proc*/
-       if (ctx->pOutput) IDirectSoundBuffer_Stop(ctx->pOutput);
+       if (ctx->pOutput) ctx->pOutput->lpVtbl->Stop(ctx->pOutput);
        SAFE_DS_RELEASE(ctx->pOutput);
        
        /*use notif, shutdown notifier and event watcher*/
@@ -195,20 +199,20 @@ static GF_Err DS_ConfigureOutput(GF_AudioOutput *dr, u32 *SampleRate, u32 *NbCha
 #endif
 
 
-       hr = IDirectSound_CreateSoundBuffer(ctx->pDS, &dsbBufferDesc, &ctx->pOutput, NULL );
+       hr = ctx->pDS->lpVtbl->CreateSoundBuffer(ctx->pDS, &dsbBufferDesc, &ctx->pOutput, NULL );
        if (FAILED(hr)) {
 retry:
                if (ctx->use_notif) gf_modules_set_option((GF_BaseInterface *)dr, "Audio", "DisableNotification", "yes");
                ctx->use_notif = 0;
                dsbBufferDesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
-               hr = IDirectSound_CreateSoundBuffer(ctx->pDS, &dsbBufferDesc, &ctx->pOutput, NULL );
+               hr = ctx->pDS->lpVtbl->CreateSoundBuffer(ctx->pDS, &dsbBufferDesc, &ctx->pOutput, NULL );
                if (FAILED(hr)) return GF_IO_ERR;
        }
 
        for (i=0; i<ctx->num_audio_buffer; i++) ctx->frame_state[i] = 0;
 
        if (ctx->use_notif) {
-               hr = IDirectSoundBuffer_QueryInterface(ctx->pOutput, &IID_IDirectSoundNotify , (void **)&pNotify);
+               hr = ctx->pOutput->lpVtbl->QueryInterface(ctx->pOutput, &IID_IDirectSoundNotify , (void **)&pNotify);
                if (hr == S_OK) {
                        /*setup the notification positions*/
                        for (i=0; i<ctx->num_audio_buffer; i++) {
@@ -218,16 +222,16 @@ retry:
                        }
 
                        /*Tell DirectSound when to notify us*/
-                       hr = IDirectSoundNotify_SetNotificationPositions(pNotify, ctx->num_audio_buffer, ctx->notif_events);
+                       hr = pNotify->lpVtbl->SetNotificationPositions(pNotify, ctx->num_audio_buffer, ctx->notif_events);
 
                        if (hr != S_OK) {
-                               IDirectSoundNotify_Release(pNotify);
+                               pNotify->lpVtbl->Release(pNotify);
                                for (i=0; i<ctx->num_audio_buffer; i++) CloseHandle(ctx->events[i]);
                                SAFE_DS_RELEASE(ctx->pOutput);
                                goto retry;
                        }
 
-                       IDirectSoundNotify_Release(pNotify);
+                       pNotify->lpVtbl->Release(pNotify);
                } else {
                        ctx->use_notif = 0;
                }
@@ -243,18 +247,18 @@ retry:
        /*reset*/
        DS_ResetBuffer(ctx);
        /*play*/
-       IDirectSoundBuffer_Play(ctx->pOutput, 0, 0, DSBPLAY_LOOPING);   
+       ctx->pOutput->lpVtbl->Play(ctx->pOutput, 0, 0, DSBPLAY_LOOPING);        
        return GF_OK;
 }
 
 static Bool DS_RestoreBuffer(LPDIRECTSOUNDBUFFER pDSBuffer)
 {
        DWORD dwStatus;
-    IDirectSoundBuffer_GetStatus(pDSBuffer, &dwStatus );
+    pDSBuffer->lpVtbl->GetStatus(pDSBuffer, &dwStatus );
     if( dwStatus & DSBSTATUS_BUFFERLOST ) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] buffer lost\n"));
-               IDirectSoundBuffer_Restore(pDSBuffer);
-           IDirectSoundBuffer_GetStatus(pDSBuffer, &dwStatus);
+               pDSBuffer->lpVtbl->Restore(pDSBuffer);
+           pDSBuffer->lpVtbl->GetStatus(pDSBuffer, &dwStatus);
                if( dwStatus & DSBSTATUS_BUFFERLOST ) return 1;
     }
        return 0;
@@ -279,7 +283,7 @@ void DS_FillBuffer(GF_AudioOutput *dr, u32 buffer)
        /*lock and fill from current pos*/
        pos = buffer * ctx->buffer_size;
        pLock = NULL;
-    if( FAILED( hr = IDirectSoundBuffer_Lock(ctx->pOutput, pos, ctx->buffer_size,  
+    if( FAILED( hr = ctx->pOutput->lpVtbl->Lock(ctx->pOutput, pos, ctx->buffer_size,  
                        &pLock,  &size, NULL, NULL, 0L ) ) ) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] Error locking sound buffer\n"));
         return;
@@ -290,7 +294,7 @@ void DS_FillBuffer(GF_AudioOutput *dr, u32 buffer)
        dr->FillBuffer(dr->audio_renderer, pLock, size);
 
        /*update current pos*/
-    if( FAILED( hr = IDirectSoundBuffer_Unlock(ctx->pOutput, pLock, size, NULL, 0)) ) {
+    if( FAILED( hr = ctx->pOutput->lpVtbl->Unlock(ctx->pOutput, pLock, size, NULL, 0)) ) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] Error unlocking sound buffer\n"));
        }
        ctx->frame_state[buffer] = 1;
@@ -323,14 +327,14 @@ void DS_WriteAudio(GF_AudioOutput *dr)
        DSCONTEXT();
 
        /*wait for end of current play buffer*/
-       if (IDirectSoundBuffer_GetCurrentPosition(ctx->pOutput, &in_play, NULL) != DS_OK ) {
+       if (ctx->pOutput->lpVtbl->GetCurrentPosition(ctx->pOutput, &in_play, NULL) != DS_OK ) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer poitions\n"));
                return;
        }
        in_play = (in_play / ctx->buffer_size);
        retry = 6;
        while (retry) {
-               if (IDirectSoundBuffer_GetCurrentPosition(ctx->pOutput, &cur_play, NULL) != DS_OK ) {
+               if (ctx->pOutput->lpVtbl->GetCurrentPosition(ctx->pOutput, &cur_play, NULL) != DS_OK ) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer poitions\n"));
                        return;
                }
@@ -358,12 +362,12 @@ static void DS_Play(GF_AudioOutput *dr, u32 PlayType)
        DSCONTEXT();
        switch (PlayType) {
        case 0:
-               IDirectSoundBuffer_Stop(ctx->pOutput);
+               ctx->pOutput->lpVtbl->Stop(ctx->pOutput);
                break;
        case 2:
                DS_ResetBuffer(ctx);
        case 1:
-               IDirectSoundBuffer_Play(ctx->pOutput, 0, 0, DSBPLAY_LOOPING);
+               ctx->pOutput->lpVtbl->Play(ctx->pOutput, 0, 0, DSBPLAY_LOOPING);
                break;
        }
 }
@@ -375,7 +379,7 @@ static void DS_SetVolume(GF_AudioOutput *dr, u32 Volume)
        if (Volume > 100) Volume = DSBVOLUME_MAX;
        else if(Volume == 0) Vol = DSBVOLUME_MIN;
        else Vol = DSBVOLUME_MIN/2 + Volume * (DSBVOLUME_MAX-DSBVOLUME_MIN/2) / 100;
-       IDirectSoundBuffer_SetVolume(ctx->pOutput, Vol);
+       ctx->pOutput->lpVtbl->SetVolume(ctx->pOutput, Vol);
 }
 
 static void DS_SetPan(GF_AudioOutput *dr, u32 Pan)
@@ -391,7 +395,7 @@ static void DS_SetPan(GF_AudioOutput *dr, u32 Pan)
        } else {
                dspan = 0;
        }
-       IDirectSoundBuffer_SetPan(ctx->pOutput, dspan);
+       ctx->pOutput->lpVtbl->SetPan(ctx->pOutput, dspan);
 }
 
 
@@ -422,6 +426,15 @@ void *NewAudioOutput()
        
        ctx = gf_malloc(sizeof(DSContext));
        memset(ctx, 0, sizeof(DSContext));
+       ctx->hDSoundLib = LoadLibrary("dsound.dll");
+       if (ctx->hDSoundLib) {
+               ctx->DirectSoundCreate = (DIRECTSOUNDCREATEPROC) GetProcAddress(ctx->hDSoundLib, "DirectSoundCreate");
+       }
+       if (!ctx->DirectSoundCreate) {
+               if (ctx->hDSoundLib) FreeLibrary(ctx->hDSoundLib);
+               gf_free(ctx);return NULL;
+       }
+
 
        driv = gf_malloc(sizeof(GF_AudioOutput));
        memset(driv, 0, sizeof(GF_AudioOutput));
@@ -450,6 +463,8 @@ void DeleteAudioOutput(void *ifce)
        GF_AudioOutput *dr = (GF_AudioOutput *)ifce;
        DSCONTEXT();
 
+       if (ctx->hDSoundLib) 
+               FreeLibrary(ctx->hDSoundLib);
        gf_free(ctx);
        gf_free(ifce);
        CoUninitialize();
index 0a89cda2ffcb5d0209903b03345121282d7709f9..d6ba1be8f4323d498bb28df255db779954b65f55 100644 (file)
 #include <gpac/constants.h>
 #include <gpac/thread.h>
 
+#define INITGUID
 
 /*
 #include <windows.h>
 */
-#include <ddraw.h>
 
+#define HAS_DDRAW_H
+
+#ifdef HAS_DDRAW_H
+#include <ddraw.h>
 #include <mmsystem.h>
 #include <dsound.h>
 
 #include <vfw.h>
 #endif
 
+/*DirectDraw video output*/
+#if (DIRECTDRAW_VERSION < 0x0700)
+#define USE_DX_3
+#endif
+
+
+#ifdef USE_DX_3
+typedef LPDIRECTDRAWSURFACE LPDDRAWSURFACE;
+typedef DDSURFACEDESC DDSURFDESC;
+#else
+typedef LPDIRECTDRAWSURFACE7 LPDDRAWSURFACE;
+typedef DDSURFACEDESC2 DDSURFDESC;
+#endif
+typedef DDSURFDESC *LPDDSURFDESC;
+
+typedef HRESULT(WINAPI * DIRECTDRAWCREATEPROC) (GUID *, LPDIRECTDRAW *, IUnknown *);
+
+#endif
+
+
+
 #ifdef _WIN32_WCE
 # ifndef SWP_ASYNCWINDOWPOS
 #  define SWP_ASYNCWINDOWPOS 0
 #include "GLES/egl.h"
 #endif
 
-/*
-               DirectDraw video output
-*/
-
-#if (DIRECTDRAW_VERSION < 0x0700)
-#define USE_DX_3
-#endif
-
 typedef struct
 {
-#ifdef USE_DX_3
-    LPDIRECTDRAWSURFACE pSurface;
-#else
-    LPDIRECTDRAWSURFACE7 pSurface;
-#endif
+    LPDDRAWSURFACE pSurface;
        u32 width, height, format, pitch;
 } DDSurface;
 
@@ -166,6 +179,13 @@ typedef struct
 
        u32 last_mouse_move, timer, cursor_type_backup;
        Bool windowless, hidden;
+
+       Bool dd_lost;
+
+
+       HMODULE hDDrawLib;
+    DIRECTDRAWCREATEPROC DirectDrawCreate;
+
 } DDContext;
 
 void DD_SetupWindow(GF_VideoOutput *dr, Bool hide);
@@ -195,19 +215,16 @@ GF_Err DD_SetupOpenGL(GF_VideoOutput *dr, u32 offscreen_width, u32 offscreen_hei
 #endif
 
 
-#ifdef USE_DX_3
-#define SAFE_DD_RELEASE(p) { if(p) { IDirectDraw_Release(p); (p)=NULL; } }
-#else
-#define SAFE_DD_RELEASE(p) { if(p) { IDirectDraw7_Release(p); (p)=NULL; } }
-#endif
+#define SAFE_DD_RELEASE(p) { if(p) { (p)->lpVtbl->Release( (p) ); (p)=NULL; } }
 
 
 void *NewAudioOutput();
 void DeleteAudioOutput(void *);
 
 
-#define SAFE_DS_RELEASE(p) { if(p) { IDirectSound_Release(p); (p)=NULL; } }
+#define SAFE_DS_RELEASE(p) { if(p) { p->lpVtbl->Release(p); (p)=NULL; } }
 
 LRESULT APIENTRY DD_WindowProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam);
 
+
 #endif
index d3738864494c8b4bc378a146fa42ff5316b3ab7c..1280ba3f301baea39a206a5c48569f3c2c394fee 100644 (file)
@@ -151,14 +151,8 @@ static void RestoreWindow(DDContext *dd)
        } else 
 #endif
 
-       {
-#ifdef USE_DX_3
-               IDirectDraw_SetCooperativeLevel(dd->pDD, dd->cur_hwnd, DDSCL_NORMAL);
-#else
-               IDirectDraw7_SetCooperativeLevel(dd->pDD, dd->cur_hwnd, DDSCL_NORMAL);
-#endif
-               dd->NeedRestore = 0;
-       }
+       dd->pDD->lpVtbl->SetCooperativeLevel(dd->pDD, dd->cur_hwnd, DDSCL_NORMAL);
+       dd->NeedRestore = 0;
 
 //     SetForegroundWindow(dd->cur_hwnd);
        SetFocus(dd->cur_hwnd);
@@ -386,6 +380,7 @@ GF_Err DD_SetupOpenGL(GF_VideoOutput *dr, u32 offscreen_width, u32 offscreen_hei
 
 
        if (dd->output_3d_type==1) {
+               memset(&evt, 0, sizeof(GF_Event));
                evt.type = GF_EVENT_VIDEO_SETUP;
                evt.setup.opengl_mode = 1;
                dr->on_event(dr->evt_cbk_hdl, &evt);    
@@ -610,24 +605,20 @@ GF_Err DD_Flush(GF_VideoOutput *dr, GF_Window *dest)
                dest->x = pt.x;
                dest->y = pt.y;
                MAKERECT(rc, dest);
-               hr = IDirectDrawSurface_Blt(dd->pPrimary, &rc, dd->pBack, NULL, DDBLT_WAIT, NULL);
+               hr = dd->pPrimary->lpVtbl->Blt(dd->pPrimary, &rc, dd->pBack, NULL, DDBLT_WAIT, NULL);
        } else {
-               hr = IDirectDrawSurface_Blt(dd->pPrimary, NULL, dd->pBack, NULL, DDBLT_WAIT, NULL);
+               hr = dd->pPrimary->lpVtbl->Blt(dd->pPrimary, NULL, dd->pBack, NULL, DDBLT_WAIT, NULL);
        }
        if (hr == DDERR_SURFACELOST) {
-               IDirectDrawSurface_Restore(dd->pPrimary);
-               IDirectDrawSurface_Restore(dd->pBack);
+               dd->pPrimary->lpVtbl->Restore(dd->pPrimary);
+               dd->pBack->lpVtbl->Restore(dd->pBack);
        }
        return FAILED(hr) ? GF_IO_ERR : GF_OK;
 }
 
 
 
-#ifdef USE_DX_3
-HRESULT WINAPI EnumDisplayModes( LPDDSURFACEDESC lpDDDesc, LPVOID lpContext)
-#else
-HRESULT WINAPI EnumDisplayModes( LPDDSURFACEDESC2 lpDDDesc, LPVOID lpContext)
-#endif
+HRESULT WINAPI EnumDisplayModes( LPDDSURFDESC lpDDDesc, LPVOID lpContext)
 {
        DDContext *dd = (DDContext *) lpContext;
        
@@ -649,27 +640,20 @@ HRESULT WINAPI EnumDisplayModes( LPDDSURFACEDESC2 lpDDDesc, LPVOID lpContext)
 
 GF_Err GetDisplayMode(DDContext *dd)
 {
-       if (dd->switch_res) {
+       if (dd->switch_res && dd->DirectDrawCreate) {
                HRESULT hr;
                Bool temp_dd = 0;;
                if (!dd->pDD) {
                        LPDIRECTDRAW ddraw;
-                       DirectDrawCreate(NULL, &ddraw, NULL);
-#ifdef USE_DX_3
-                       IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw, (LPVOID *)&dd->pDD);
-#else
-                       IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw7, (LPVOID *)&dd->pDD);
-#endif         
+                       dd->DirectDrawCreate(NULL, &ddraw, NULL);
+                       ddraw->lpVtbl->QueryInterface(ddraw, &IID_IDirectDraw7, (LPVOID *)&dd->pDD);
                        temp_dd = 1;
                }
                //we start with a hugde res and downscale
                dd->fs_width = dd->fs_height = 50000;
 
-#ifdef USE_DX_3
-               hr = IDirectDraw_EnumDisplayModes(dd->pDD, 0L, NULL, dd,  (LPDDENUMMODESCALLBACK) EnumDisplayModes);
-#else
-               hr = IDirectDraw7_EnumDisplayModes(dd->pDD, 0L, NULL, dd,  (LPDDENUMMODESCALLBACK2) EnumDisplayModes);
-#endif
+               hr = dd->pDD->lpVtbl->EnumDisplayModes(dd->pDD, 0L, NULL, dd,  EnumDisplayModes);
+
                if (temp_dd) SAFE_DD_RELEASE(dd->pDD);
                if (FAILED(hr)) return GF_IO_ERR;
        } else {
@@ -697,6 +681,11 @@ static void *NewDXVideoOutput()
        driv->SetFullScreen = DD_SetFullScreen;
        driv->ProcessEvent = DD_ProcessEvent;
 
+       pCtx->hDDrawLib = LoadLibrary("ddraw.dll");
+       if (pCtx->hDDrawLib) {
+               pCtx->DirectDrawCreate = (DIRECTDRAWCREATEPROC) GetProcAddress(pCtx->hDDrawLib, "DirectDrawCreate");
+       }
+
     driv->max_screen_width = GetSystemMetrics(SM_CXSCREEN);
     driv->max_screen_height = GetSystemMetrics(SM_CYSCREEN);
        driv->hw_caps = GF_VIDEO_HW_OPENGL | GF_VIDEO_HW_OPENGL_OFFSCREEN | GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA | GF_VIDEO_HW_HAS_HWND_HDC;
@@ -710,6 +699,11 @@ static void DeleteVideoOutput(void *ifce)
 {
        GF_VideoOutput *driv = (GF_VideoOutput *) ifce;
        DDContext *dd = (DDContext *)driv->opaque;
+
+       if (dd->hDDrawLib) {
+               FreeLibrary(dd->hDDrawLib);
+       }
+
        gf_free(dd);
        gf_free(driv);
 }
index 20cc9a73a3408d684f3ac5e3b557ca0f87dc980e..3939c4cbbe254eaad6519953181d4f121630a1f6 100644 (file)
@@ -372,6 +372,13 @@ LRESULT APIENTRY DD_WindowProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
                        ctx->orig_wnd_proc = 0L;
                }
                break;
+       case WM_DISPLAYCHANGE:
+               ctx->dd_lost = 1;
+               memset(&evt, 0, sizeof(GF_Event));
+               evt.type = GF_EVENT_VIDEO_SETUP;
+               evt.setup.back_buffer = 1;
+               vout->on_event(vout->evt_cbk_hdl, &evt);
+               break;
 
        case WM_ACTIVATE:
                if (!ctx->on_secondary_screen && ctx->fullscreen && (LOWORD(wParam)==WA_INACTIVE) 
@@ -1015,19 +1022,23 @@ GF_Err DD_ProcessEvent(GF_VideoOutput*dr, GF_Event *evt)
        /*if scene resize resize window*/
        case GF_EVENT_SIZE:
                if (ctx->owns_hwnd) {
-                       if (ctx->windowless)
-                               SetWindowPos(ctx->os_hwnd, NULL, 0, 0, evt->size.width, evt->size.height, SWP_NOZORDER | SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
-                       else 
-                               SetWindowPos(ctx->os_hwnd, NULL, 0, 0, evt->size.width + ctx->off_w, evt->size.height + ctx->off_h, SWP_NOZORDER | SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
-
                        if (ctx->fullscreen) {
                                ctx->store_width = evt->size.width;
                                ctx->store_height = evt->size.height;
+                       } else {
+                               if (ctx->windowless)
+                                       SetWindowPos(ctx->os_hwnd, NULL, 0, 0, evt->size.width, evt->size.height, SWP_NOZORDER | SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
+                               else 
+                                       SetWindowPos(ctx->os_hwnd, NULL, 0, 0, evt->size.width + ctx->off_w, evt->size.height + ctx->off_h, SWP_NOZORDER | SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
                        }
                }
                break;
        /*HW setup*/
        case GF_EVENT_VIDEO_SETUP:
+               if (ctx->dd_lost) {
+                       ctx->dd_lost = 0;
+                       DestroyObjects(ctx);
+               }
                ctx->is_setup=1;
                switch (evt->setup.opengl_mode) {
                case 0:
index 19808a9745d7b5593ac118b9f4aa1453ef11aec2..c2ff738ca496e36fe8ab93e51bf9b7074888ad1b 100644 (file)
@@ -130,7 +130,7 @@ static void FFDEC_LoadDSI(FFDec *ffd, GF_BitStream *bs, AVCodec *codec, AVCodecC
 
 static GF_Err FFDEC_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
 {
-       u32 codec_id;
+       u32 codec_id = 0;
        int gotpic;
        GF_BitStream *bs;
        AVCodecContext **ctx;
@@ -192,8 +192,8 @@ static GF_Err FFDEC_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
                        (*ctx)->height = gf_bs_read_u16(bs);
                }
                (*ctx)->bit_rate = gf_bs_read_u32(bs);
-
                (*ctx)->codec_tag = gf_bs_read_u32(bs);
+               ffd->raw_pix_fmt = gf_bs_read_u32(bs);
 
                *codec = avcodec_find_decoder(codec_id);
                FFDEC_LoadDSI(ffd, bs, *codec, *ctx, 1);
@@ -312,12 +312,16 @@ static GF_Err FFDEC_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
                }
                *frame = avcodec_alloc_frame();
        }
-
-       if (avcodec_open((*ctx), (*codec) )<0) return GF_NON_COMPLIANT_BITSTREAM;
+       if (codec_id == CODEC_ID_RAWVIDEO) {
+               (*ctx)->codec_id = CODEC_ID_RAWVIDEO;
+               (*ctx)->pix_fmt = ffd->raw_pix_fmt;
+               if ((*ctx)->extradata && strstr((*ctx)->extradata, "BottomUp")) ffd->flipped = 1;
+       } else {
+               if (avcodec_open((*ctx), (*codec) )<0) return GF_NON_COMPLIANT_BITSTREAM;
+       }
 
        /*setup audio streams*/
        if (ffd->st==GF_STREAM_AUDIO) {
-               /* souchay : test was wrong I think, was codec->type but must be codec->id */
                if ((*codec)->id == CODEC_ID_MP2) {
                        (*ctx)->frame_size = ((*ctx)->sample_rate > 24000) ? 1152 : 576;
                }
@@ -330,11 +334,13 @@ static GF_Err FFDEC_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
                case CODEC_ID_MJPEG:
                case CODEC_ID_MJPEGB:
                case CODEC_ID_LJPEG:
-#if (LIBAVCODEC_VERSION_INT > ((51<<16)+(20<<8)+0) )
+#if (LIBAVCODEC_VERSION_INT > AV_VERSION_INT(51, 20, 0))
                case CODEC_ID_GIF:
 #endif
+               case CODEC_ID_RAWVIDEO:
                        ffd->pix_fmt = GF_PIXEL_RGB_24;
                        break;
+
                case CODEC_ID_DVD_SUBTITLE:
                        *frame = avcodec_alloc_frame();
 #ifdef USE_AVCODEC2
@@ -401,7 +407,7 @@ static GF_Err FFDEC_DetachStream(GF_BaseDecoder *plug, u16 ES_ID)
        if (*ctx) {
                if ((*ctx)->extradata) gf_free((*ctx)->extradata);
                (*ctx)->extradata = NULL;
-               avcodec_close((*ctx));
+               if ((*ctx)->codec) avcodec_close((*ctx));
                *ctx = NULL;
        }
        *codec = NULL;
@@ -517,8 +523,8 @@ static GF_Err FFDEC_SetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability cap
        case GF_CODEC_WAIT_RAP:
                ffd->frame_start = 0;
                if (ffd->st==GF_STREAM_VISUAL) {
-                       if (ffd->base_ctx) avcodec_flush_buffers(ffd->base_ctx);
-                       if (ffd->depth_ctx) avcodec_flush_buffers(ffd->depth_ctx);
+                       if (ffd->base_ctx && ffd->base_ctx->codec) avcodec_flush_buffers(ffd->base_ctx);
+                       if (ffd->depth_ctx && ffd->depth_ctx->codec) avcodec_flush_buffers(ffd->depth_ctx);
                }
                return GF_OK;
        default:
@@ -649,6 +655,41 @@ redecode:
                return GF_PACKED_FRAMES;
        }
 
+
+       if ( ctx->codec_id == CODEC_ID_RAWVIDEO) {
+               if (*outBufferLength != ffd->out_size) {
+                       *outBufferLength = ffd->out_size;
+                       return GF_BUFFER_TOO_SMALL;
+               }
+               if (inBufferLength) {
+                       *outBufferLength = ffd->out_size;
+                       assert(inBufferLength==ffd->out_size);
+
+                       if (ffd->raw_pix_fmt==PIX_FMT_BGR24) {
+                               s32 i, j;
+                               for (j=0; j<ctx->height; j++) {
+                                       u8 *src = inBuffer + j*3*ctx->width;
+                                       u8 *dst = outBuffer + j*3*ctx->width;
+                                       if (ffd->flipped) {
+                                               dst = outBuffer + (ctx->height-j-1) * 3*ctx->width;
+                                       }
+                                       for (i=0; i<ctx->width; i++) {
+                                               dst[0] = src[2];
+                                               dst[1] = src[1];
+                                               dst[2] = src[2];
+                                               src += 3;
+                                               dst += 3;
+                                       }
+                               }
+                       } else {
+                               memcpy(outBuffer, inBuffer, ffd->out_size);
+                       }
+               } else {
+                       *outBufferLength = 0;
+               }
+               return GF_OK;
+       }
+
        *outBufferLength = 0;
        /*visual stream*/
        w = ctx->width;
@@ -846,8 +887,12 @@ redecode:
                                           ctx->width, ctx->height, ctx->pix_fmt,
                                           ctx->width, ctx->height, pix_out,
                                           SWS_BICUBIC, NULL, NULL, NULL);
-       if ((*cached_sws)){
+       if ((*cached_sws)) {
+#if LIBSWSCALE_VERSION_INT < AV_VERSION_INT(0, 9, 0)
+               int sz = sws_scale((*cached_sws), frame->data, frame->linesize, 0, ctx->height, pict.data, pict.linesize);
+#else
                int sz = sws_scale((*cached_sws), (const uint8_t * const*)frame->data, frame->linesize, 0, ctx->height, pict.data, pict.linesize);
+#endif
                assert( sz > 0 );
        }
 #endif
@@ -1019,22 +1064,22 @@ void FFDEC_Delete(void *ifce)
 {
        GF_BaseDecoder *dec = ifce;
        FFDec *ffd;
-        if (!ifce)
-          return;
-        ffd = dec->privateStack;
+       if (!ifce)
+               return;
+       ffd = dec->privateStack;
        dec->privateStack = NULL;
-        if (ffd){
-          if (ffd->base_ctx) avcodec_close(ffd->base_ctx);
-          ffd->base_ctx = NULL;
-          if (ffd->depth_ctx) avcodec_close(ffd->depth_ctx);
-          ffd->depth_ctx = NULL;
+       if (ffd){
+               if (ffd->base_ctx && ffd->base_ctx->codec) avcodec_close(ffd->base_ctx);
+               ffd->base_ctx = NULL;
+               if (ffd->depth_ctx && ffd->depth_ctx->codec) avcodec_close(ffd->depth_ctx);
+               ffd->depth_ctx = NULL;
 #ifdef FFMPEG_SWSCALE
-          if (ffd->base_sws) sws_freeContext(ffd->base_sws);
-          ffd->base_sws = NULL;
-          if (ffd->depth_sws) sws_freeContext(ffd->base_sws);
-          ffd->depth_sws = NULL;
+               if (ffd->base_sws) sws_freeContext(ffd->base_sws);
+               ffd->base_sws = NULL;
+               if (ffd->depth_sws) sws_freeContext(ffd->base_sws);
+               ffd->depth_sws = NULL;
 #endif
-          gf_free(ffd);
-        }
-        gf_free(dec);
+               gf_free(ffd);
+       }
+       gf_free(dec);
 }
index 6f87ae2c762ea81a8af8f59f118b0bdc51176e29..6f0e71fe59bc1ac8c2591f1efb21d0f53f31e39c 100644 (file)
@@ -212,6 +212,14 @@ static u32 FFD_RegisterMimeTypes(const GF_InputService *plug){
     return i/3;
 }
 
+static int open_file(AVFormatContext **        ic_ptr, const char *    filename, AVInputFormat *       fmt){
+#ifdef USE_PRE_0_7
+       return av_open_input_file(ic_ptr, filename, fmt, 0, NULL);
+#else
+       return avformat_open_input(ic_ptr, filename, fmt, NULL);
+#endif
+}
+
 
 static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
 {
@@ -273,12 +281,12 @@ static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
        }
 
        ctx = NULL;
-    if (av_open_input_file(&ctx, szName, NULL, 0, NULL)<0) {
+    if (open_file(&ctx, szName, NULL)<0) {
                AVInputFormat *av_in = NULL;;
                /*some extensions not supported by ffmpeg*/
                if (ext && !strcmp(szExt, "cmp")) av_in = av_find_input_format("m4v");
 
-               if (av_open_input_file(&ctx, szName, av_in, 0, NULL)<0) {
+               if (open_file(&ctx, szName, av_in)<0) {
                        return 0;
                }
        }
@@ -421,6 +429,7 @@ opaque_video:
                        /*ffmpeg specific*/
                        gf_bs_write_u32(bs, dec->bit_rate);
                        gf_bs_write_u32(bs, dec->codec_tag);
+                       gf_bs_write_u32(bs, dec->pix_fmt);
 
                        if (dec->extradata_size) {
                                gf_bs_write_data(bs, dec->extradata, dec->extradata_size);
@@ -482,7 +491,7 @@ static int ff_url_read(void *h, unsigned char *buf, int size)
                        ffd->buffer_used-=size;
                        memcpy(ffd->buffer, ffd->buffer+size, sizeof(char)*ffd->buffer_used);
 #ifdef FFMPEG_DUMP_REMOTE
-                       if (ffd->outdbg) fwrite(buf, size, 1, ffd->outdbg);
+                       if (ffd->outdbg) gf_fwrite(buf, size, 1, ffd->outdbg);
 #endif
                        return size;
                }
@@ -515,7 +524,7 @@ static int ff_url_read(void *h, unsigned char *buf, int size)
                buf += read;
        }
 #ifdef FFMPEG_DUMP_REMOTE
-       if (ffd->outdbg) fwrite(ffd->buffer, full_size, 1, ffd->outdbg);
+       if (ffd->outdbg) gf_fwrite(ffd->buffer, full_size, 1, ffd->outdbg);
 #endif
        return full_size ? (int) full_size : -1;
 }
@@ -570,8 +579,16 @@ static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv,
 #ifdef FFMPEG_DUMP_REMOTE
                ffd->outdbg = gf_f64_open("ffdeb.raw", "wb");
 #endif
+/*#ifdef USE_PRE_0_7*/
                init_put_byte(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
+/*#else
+                ffio_init_context(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
+#endif*/
+#ifdef USE_PRE_0_7
                ffd->io.is_streamed = 1;
+#else
+               ffd->io.seekable = 1;
+#endif
 
                ffd->dnload = gf_term_download_new(ffd->service, url, GF_NETIO_SESSION_NOT_THREADED  | GF_NETIO_SESSION_NOT_CACHED, NULL, ffd);
                if (!ffd->dnload) return GF_URL_ERROR;
@@ -587,7 +604,7 @@ static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv,
                }
                if (e==GF_EOS) {
                        const char *cache_file = gf_dm_sess_get_cache_name(ffd->dnload);
-                       res = av_open_input_file(&ffd->ctx, cache_file, av_in, 0, NULL);
+                       res = open_file(&ffd->ctx, cache_file, av_in);
                } else {
                        pd.filename = szName;
                        pd.buf_size = ffd->buffer_used;
@@ -602,7 +619,7 @@ static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv,
                        res = av_open_input_stream(&ffd->ctx, &ffd->io, szName, av_in, NULL);
                }
        } else {
-               res = av_open_input_file(&ffd->ctx, szName, av_in, 0, NULL);
+               res = open_file(&ffd->ctx, szName, av_in);
        }
 
        switch (res) {
@@ -679,7 +696,7 @@ static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv,
                ffd->seekable = (av_seek_frame(ffd->ctx, -1, 0, AVSEEK_FLAG_BACKWARD)<0) ? 0 : 1;
                if (!ffd->seekable) {
                        av_close_input_file(ffd->ctx);
-                       av_open_input_file(&ffd->ctx, szName, av_in, 0, NULL);
+                       open_file(&ffd->ctx, szName, av_in);
                        av_find_stream_info(ffd->ctx);
                }
        }
@@ -715,6 +732,7 @@ static GF_Descriptor *FFD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
 
        /*since we don't handle multitrack in ffmpeg, we don't need to check sub_url, only use expected type*/
        if (expect_type==GF_MEDIA_OBJECT_AUDIO) {
+               if (ffd->audio_st<0) return NULL;
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
                od->objectDescriptorID = 1;
                esd = FFD_GetESDescriptor(ffd, 1);
@@ -725,6 +743,7 @@ static GF_Descriptor *FFD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
                return (GF_Descriptor *) od;
        }
        if (expect_type==GF_MEDIA_OBJECT_VIDEO) {
+               if (ffd->video_st<0) return NULL;
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
                od->objectDescriptorID = 1;
                esd = FFD_GetESDescriptor(ffd, 0);
@@ -751,7 +770,7 @@ static GF_Err FFD_CloseService(GF_InputService *plug)
 
        if (ffd->dnload) {
                if (ffd->is_running) {
-                       while (!ffd->is_running) gf_sleep(0);
+                       while (!ffd->is_running) gf_sleep(1);
                        ffd->is_running = 0;
                }
                gf_term_download_del(ffd->dnload);
index 57e6d66b0101d962b20e75892483916c955cb771..cf2a20ed5ef1928fd4dfb50bfbb8d4424caca0fc 100644 (file)
@@ -79,7 +79,7 @@
 void gf_av_vlog(void* avcl, int level, const char *fmt, va_list vl);
 
 
-#if LIBAVCODEC_VERSION_INT > ((52<<16)+(0<<8)+0)
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 0, 0)
 #define FFMPEG_SWSCALE
 #ifdef FFMPEG_OLD_HEADERS
 #include <ffmpeg/swscale.h>
@@ -112,6 +112,9 @@ typedef struct
        u32 out_pix_fmt;
        Bool is_image;
 
+       u32 raw_pix_fmt;
+       Bool flipped;
+
        /*for audio packed frames*/
        u32 frame_start;
        char audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
@@ -149,6 +152,10 @@ void FFDEC_Delete(void *ifce);
 
 //#define FFMPEG_DUMP_REMOTE
 
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 102, 0)
+#define USE_PRE_0_7 1
+#endif
+
 typedef struct
 {
        /*the service we're responsible for*/
@@ -181,7 +188,11 @@ typedef struct
        /*file downloader*/
        GF_DownloadSession *dnload;
 
+#ifdef USE_PRE_0_7
        ByteIOContext   io;
+#else
+       AVIOContext io;
+#endif
        char *buffer;
        u32 buffer_size;
 
diff --git a/modules/freenect/Makefile b/modules/freenect/Makefile
new file mode 100644 (file)
index 0000000..cb4810c
--- /dev/null
@@ -0,0 +1,65 @@
+include ../../config.mak
+
+vpath %.c $(SRC_PATH)/modules/freenect
+
+CFLAGS= $(CPPFLAGS) -I"$(SRC_PATH)/include" $(FREENECT_CFLAGS)
+
+ifeq ($(DEBUGBUILD), yes)
+CFLAGS+=-g
+LDFLAGS+=-g
+endif
+
+ifeq ($(GPROFBUILD), yes)
+CFLAGS+=-pg
+LDFLAGS+=-pg
+endif
+
+
+LINKLIBS=
+
+ifeq ($(CONFIG_FREENECT), local)
+LINKLIBS+=-L../../extra_lib/lib/gcc
+CFLAGS+= -I"$(LOCAL_INC_PATH)"
+endif
+
+LINKLIBS+=-lfreenect -L../../bin/gcc -lgpac
+
+
+#common objects
+OBJS=freenect.o
+
+SRCS := $(OBJS:.o=.c) 
+
+LIB=gm_freenect.$(DYN_LIB_SUFFIX)
+
+
+all: $(LIB)
+
+
+$(LIB): $(OBJS)
+       $(CXX) -w $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKLIBS)
+
+
+%.o: %.cpp
+       $(CXX) $(CFLAGS) -c -o $@ $< 
+
+
+clean: 
+       rm -f $(OBJS) ../../bin/gcc/$(LIB)
+
+dep: depend
+
+depend:
+       rm -f .depend   
+       $(CXX) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+distclean: clean
+       rm -f Makefile.bak .depend
+
+
+
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/modules/freenect/freenect.c b/modules/freenect/freenect.c
new file mode 100644 (file)
index 0000000..bf4b9cf
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ *                     GPAC - Multimedia Framework C SDK
+ *
+ *                     Authors: Jean Le Feuvre
+ *                     Copyright (c) Telecom ParisTech 2011-20XX
+ *                                     All rights reserved
+ *
+ *  This file is part of GPAC / Freenect video input module
+ *
+ *  GPAC is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  GPAC 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 Lesser General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ */
+
+
+#include <gpac/modules/service.h>
+#include <gpac/modules/codec.h>
+#include <gpac/constants.h>
+#include <gpac/download.h>
+
+#include <libfreenect/libfreenect.h>
+
+#include <gpac/thread.h>
+
+typedef struct
+{
+       /*the service we're responsible for*/
+       GF_ClientService *service;
+
+       freenect_context *f_ctx;
+       freenect_device *f_dev;
+
+       u32 width, height, fps, out_depth_size, out_color_size, color_stride, depth_stride, color_pixel_format, depth_pixel_format;
+       u32 depth_format;
+
+       u8 *vid_buf;
+       u8 *depth_buf;
+       u16 gamma[2048];
+
+       GF_SLHeader depth_sl_header, color_sl_header;
+       LPNETCHANNEL depth_channel, color_channel;
+
+       GF_Thread *th;
+       u32 nb_running;
+       Bool done;
+
+} FreenectIn;
+
+
+void Freenect_DepthCallback_RGBD(freenect_device *dev, void *v_depth, uint32_t timestamp)
+{
+       FreenectIn *vcap = freenect_get_user(dev);
+       if (vcap->depth_channel) {
+               u32 i, j;
+               u16 *depth = (u16*)v_depth;
+
+               for (i=0; i<vcap->height; i++) {
+                       for (j=0; j<vcap->width; j++) {
+                               int idx_col = 3 * (j + i*vcap->width) ;
+                               int idx_depth = 4*(j + i*vcap->width) ;
+                               int pval = depth[i*vcap->width + j];
+                               pval = 255 - (255*pval) / 2048;
+
+                               vcap->depth_buf[idx_depth ] = vcap->vid_buf[idx_col];
+                               vcap->depth_buf[idx_depth + 1] = vcap->vid_buf[idx_col+1];
+                               vcap->depth_buf[idx_depth + 2] = vcap->vid_buf[idx_col+2];
+                               vcap->depth_buf[idx_depth + 3] = pval;
+                       }
+               }
+               vcap->depth_sl_header.compositionTimeStamp = timestamp;
+               gf_term_on_sl_packet(vcap->service, vcap->depth_channel, (char *) vcap->depth_buf, vcap->out_depth_size, &vcap->depth_sl_header, GF_OK);
+       }
+}
+
+
+void Freenect_DepthCallback_GREY16(freenect_device *dev, void *v_depth, uint32_t timestamp)
+{
+       FreenectIn *vcap = freenect_get_user(dev);
+       if (vcap->depth_channel) {
+               memcpy(vcap->depth_buf, v_depth, vcap->out_depth_size);
+
+               vcap->depth_sl_header.compositionTimeStamp = timestamp;
+               gf_term_on_sl_packet(vcap->service, vcap->depth_channel, (char *) vcap->depth_buf, vcap->out_depth_size, &vcap->depth_sl_header, GF_OK);
+       }
+}
+
+void Freenect_DepthCallback_GREY8(freenect_device *dev, void *v_depth, uint32_t timestamp)
+{
+       FreenectIn *vcap = freenect_get_user(dev);
+       if (vcap->depth_channel) {
+               u32 i, j;
+               u16 *depth = (u16*)v_depth;
+
+               for (i=0; i<vcap->height; i++) {
+                       for (j=0; j<vcap->width; j++) {
+                               int pval = depth[j + i*vcap->width];
+                               pval = (255*pval) / 2048;
+                               vcap->depth_buf[j + i*vcap->width] = pval;
+                       }
+               }
+//             vcap->depth_sl_header.compositionTimeStamp = timestamp;
+               vcap->depth_sl_header.compositionTimeStamp ++;
+               gf_term_on_sl_packet(vcap->service, vcap->depth_channel, (char *) vcap->depth_buf, vcap->out_depth_size, &vcap->depth_sl_header, GF_OK);
+       }
+}
+
+void Freenect_DepthCallback_ColorGradient(freenect_device *dev, void *v_depth, uint32_t timestamp)
+{
+       FreenectIn *vcap = freenect_get_user(dev);
+       if (vcap->depth_channel) {
+               u32 i;
+               u16 *depth = (u16*)v_depth;
+               /*remap to color RGB using freenect gamma*/
+               for (i=0; i<vcap->width*vcap->height; i++) {
+                       int pval = vcap->gamma[depth[i]];
+                       int lb = pval & 0xff;
+                       switch (pval>>8) {
+                               case 0:
+                                       vcap->depth_buf[3*i+0] = 255;
+                                       vcap->depth_buf[3*i+1] = 255-lb;
+                                       vcap->depth_buf[3*i+2] = 255-lb;
+                                       break;
+                               case 1:
+                                       vcap->depth_buf[3*i+0] = 255;
+                                       vcap->depth_buf[3*i+1] = lb;
+                                       vcap->depth_buf[3*i+2] = 0;
+                                       break;
+                               case 2:
+                                       vcap->depth_buf[3*i+0] = 255-lb;
+                                       vcap->depth_buf[3*i+1] = 255;
+                                       vcap->depth_buf[3*i+2] = 0;
+                                       break;
+                               case 3:
+                                       vcap->depth_buf[3*i+0] = 0;
+                                       vcap->depth_buf[3*i+1] = 255;
+                                       vcap->depth_buf[3*i+2] = lb;
+                                       break;
+                               case 4:
+                                       vcap->depth_buf[3*i+0] = 0;
+                                       vcap->depth_buf[3*i+1] = 255-lb;
+                                       vcap->depth_buf[3*i+2] = 255;
+                                       break;
+                               case 5:
+                                       vcap->depth_buf[3*i+0] = 0;
+                                       vcap->depth_buf[3*i+1] = 0;
+                                       vcap->depth_buf[3*i+2] = 255-lb;
+                                       break;
+                               default:
+                                       vcap->depth_buf[3*i+0] = 0;
+                                       vcap->depth_buf[3*i+1] = 0;
+                                       vcap->depth_buf[3*i+2] = 0;
+                                       break;
+                       }
+               }
+               vcap->depth_sl_header.compositionTimeStamp = timestamp;
+               gf_term_on_sl_packet(vcap->service, vcap->depth_channel, (char *) vcap->depth_buf, vcap->out_depth_size, &vcap->depth_sl_header, GF_OK);
+       }
+}
+
+void Freenect_RGBCallback(freenect_device *dev, void *rgb, uint32_t timestamp)
+{
+       FreenectIn *vcap = freenect_get_user(dev);
+       if (vcap->color_channel) {
+               vcap->color_sl_header.compositionTimeStamp = timestamp;
+               gf_term_on_sl_packet(vcap->service, vcap->color_channel, (char *) rgb, vcap->out_color_size, &vcap->color_sl_header, GF_OK);
+       }
+}
+
+
+u32 FreenectRun(void *par)
+{
+       FreenectIn *vcap = par;
+
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] Starting device thread\n"));
+       freenect_start_depth(vcap->f_dev);
+       freenect_start_video(vcap->f_dev);
+       vcap->done = 0;
+       while (vcap->nb_running && (freenect_process_events(vcap->f_ctx)>=0) ) {
+               gf_sleep(0);
+       }
+       freenect_stop_depth(vcap->f_dev);
+       freenect_stop_video(vcap->f_dev);
+       vcap->done = 1;
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] Stoping device thread\n"));
+       return 0;
+}
+
+Bool Freenect_CanHandleURL(GF_InputService *plug, const char *url)
+{
+       if (!strnicmp(url, "camera://", 9)) return 1;
+       if (!strnicmp(url, "video://", 8)) return 1;
+       if (!strnicmp(url, "kinect://", 8)) return 1;
+       return 0;
+}
+
+void Freenect_Logs(freenect_context *dev, freenect_loglevel level, const char *msg)
+{
+       switch (level) {
+       case FREENECT_LOG_ERROR:
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Freenect] %s", msg));
+               break;
+       case FREENECT_LOG_WARNING:
+               GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[Freenect] %s", msg));
+               break;
+       case FREENECT_LOG_NOTICE:
+       case FREENECT_LOG_INFO:
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] %s", msg));
+               break;
+       case FREENECT_LOG_DEBUG:
+       case FREENECT_LOG_SPEW:
+       case FREENECT_LOG_FLOOD:
+       default:
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Freenect] %s", msg));
+               break;
+       }
+}
+
+
+GF_Err Freenect_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
+{
+       GF_ESD *esd;
+       GF_BitStream *bs;
+       GF_ObjectDescriptor *od;
+       FreenectIn *vcap = (FreenectIn *) plug->priv;
+
+       if (!vcap || !serv || !url) return GF_BAD_PARAM;
+
+       vcap->service = serv;
+
+       if (!vcap->f_ctx) {
+               int i;
+               Bool use_depth = 1;
+               freenect_frame_mode frame_mode;
+               freenect_resolution frame_format = FREENECT_RESOLUTION_MEDIUM;
+               char *name, *params;
+               int res = freenect_init(&vcap->f_ctx, NULL);
+               if (res < 0) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("freenect_init() failed - ret code %d\n", res));
+                       return GF_IO_ERR;
+               }
+               freenect_set_log_level(vcap->f_ctx, FREENECT_LOG_DEBUG);
+               freenect_set_log_callback(vcap->f_ctx, Freenect_Logs);
+               freenect_select_subdevices(vcap->f_ctx, FREENECT_DEVICE_CAMERA);
+
+               res = freenect_num_devices (vcap->f_ctx);
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] %d devices found\n", res));
+               if (res<1) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Freenect] No device found\n"));
+                       return GF_URL_ERROR;
+               }
+
+               res = freenect_open_device(vcap->f_ctx, &vcap->f_dev, 0);
+               if (res < 0) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Freenect] Could not open Kinect - error %d\n", res));
+                       return GF_SERVICE_ERROR;
+               }
+
+
+               params = (char *) strchr(url, '?');
+               if (params) params[0] = 0;
+               name = (char *) strstr(url, "://");
+               if (name) name += 3;
+
+               if (!stricmp(name, "color")) {
+                       use_depth = 0;
+               }
+
+               if (params) {
+                       params[0] = '?';
+                       params ++;
+               }
+               while (params) {
+                       char *sep = (char *) strchr(params, '&');
+                       if (sep) sep[0] = 0;
+       
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Set camera option %s\n", params));
+
+                       if (!strnicmp(params, "resolution=", 11)) {
+                               u32 w, h;
+                               if (sscanf(params+11, "%dx%d", &w, &h)==2) {
+                                       if ((w<=320) || (h<=240)) frame_format = FREENECT_RESOLUTION_LOW;
+                                       else if ((w<=640) || (h<=480)) frame_format = FREENECT_RESOLUTION_MEDIUM;
+                                       else frame_format = FREENECT_RESOLUTION_HIGH;
+                               }
+                       }
+                       else if (!strnicmp(params, "format=", 7)) {
+                               if (!stricmp(params+7, "standard")) vcap->depth_format = 0;
+                               else if (!stricmp(params+7, "grey")) vcap->depth_format = 1;
+                               else if (!stricmp(params+7, "rgbd")) vcap->depth_format = 2;
+                               else if (!stricmp(params+7, "grey16")) vcap->depth_format = 3;
+                               else {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[VideoCapture] Unrecognized value %s for parameter \"format\"\n", params+7));
+                               }
+                       }
+                       else {
+                               GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[VideoCapture] Unrecognized parameter %s\n", params));
+                       }
+
+                       if (!sep) break;
+                       sep[0] = '&';
+                       params = sep+1;
+               }
+
+               frame_mode = freenect_find_video_mode(frame_format, FREENECT_VIDEO_RGB);
+               res = freenect_set_video_mode(vcap->f_dev, frame_mode);
+               res = freenect_set_depth_mode(vcap->f_dev, freenect_find_depth_mode(frame_format, FREENECT_DEPTH_11BIT));
+
+               vcap->width = frame_mode.width;
+               vcap->height = frame_mode.height;
+               vcap->fps = frame_mode.framerate;
+               /*currently hardcoded*/
+               vcap->color_pixel_format = GF_PIXEL_RGB_24;
+               vcap->color_stride = 3*vcap->width;
+               vcap->out_color_size = vcap->color_stride * vcap->height;
+               vcap->vid_buf = gf_malloc(sizeof(char) * vcap->out_color_size);
+               freenect_set_video_callback(vcap->f_dev, Freenect_RGBCallback);
+
+               switch (vcap->depth_format) {
+               case 1:
+                       vcap->depth_pixel_format = GF_PIXEL_GREYSCALE;
+                       vcap->depth_stride = vcap->width;
+                       freenect_set_depth_callback(vcap->f_dev, Freenect_DepthCallback_GREY8);
+                       break;
+               case 2:
+                       vcap->depth_pixel_format = GF_PIXEL_RGBD;
+                       vcap->depth_stride = 4*vcap->width;
+                       freenect_set_depth_callback(vcap->f_dev, Freenect_DepthCallback_RGBD);
+                       break;
+               case 3:
+                       vcap->depth_pixel_format = GF_PIXEL_RGB_565;
+                       vcap->depth_stride = 2*vcap->width;
+                       freenect_set_depth_callback(vcap->f_dev, Freenect_DepthCallback_GREY16);
+                       break;
+               default:
+                       vcap->depth_pixel_format = GF_PIXEL_RGB_24;
+                       vcap->depth_stride = 3*vcap->width;
+                       freenect_set_depth_callback(vcap->f_dev, Freenect_DepthCallback_ColorGradient);
+               }
+               vcap->out_depth_size = vcap->depth_stride * vcap->height;
+               vcap->depth_buf = gf_malloc(sizeof(char) * vcap->out_depth_size);
+
+
+               res = freenect_set_video_buffer(vcap->f_dev, vcap->vid_buf);
+
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] Device configured - resolution %dx%d - Frame Rate %d - Depth Pixel Format %s\n", vcap->width, vcap->height, vcap->fps, gf_4cc_to_str(vcap->depth_pixel_format) ));
+
+
+               for (i=0; i<2048; i++) {
+                       float v = i/2048.0f;
+                       v = powf(v, 3)* 6;
+                       vcap->gamma[i] = (u16) (v*6*256);
+               }
+
+               freenect_set_user(vcap->f_dev, vcap);
+
+               vcap->th = gf_th_new("Freenect");
+       }
+
+       /*ACK connection is OK*/
+       gf_term_on_connect(serv, NULL, GF_OK);
+
+
+       /*setup object descriptor*/
+       od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
+       
+       esd = gf_odf_desc_esd_new(0);
+       esd->slConfig->timestampResolution = 1000;
+       if (!strnicmp(url, "camera://", 9) || !strnicmp(url, "video://", 8) || !strnicmp(url, "kinect://", 8)) {
+               if (strstr(url, "color") || strstr(url, "COLOR")) {
+                       od->objectDescriptorID = 2;
+                       esd->ESID = 2;
+                       esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+               } else {
+                       od->objectDescriptorID = 1;
+                       esd->ESID = 1;
+                       esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+               }
+       } else {
+               od->objectDescriptorID = 3;
+               esd->ESID = 3;
+               esd->decoderConfig->streamType = GF_STREAM_AUDIO;
+       }
+       esd->decoderConfig->objectTypeIndication = GPAC_OTI_RAW_MEDIA_STREAM;
+       
+       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+       gf_bs_write_u32(bs, (esd->ESID==2) ? vcap->color_pixel_format : vcap->depth_pixel_format);
+       gf_bs_write_u16(bs, vcap->width);
+       gf_bs_write_u16(bs, vcap->height);
+       gf_bs_write_u32(bs, (esd->ESID==2) ? vcap->out_color_size : vcap->out_depth_size);
+       gf_bs_write_u32(bs, (esd->ESID==2) ? vcap->color_stride : vcap->depth_stride);
+       gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
+       gf_bs_del(bs);
+
+       gf_list_add(od->ESDescriptors, esd);
+       gf_term_add_media(vcap->service, (GF_Descriptor*)od, 0);
+
+       return GF_OK;
+}
+
+GF_Err Freenect_CloseService(GF_InputService *plug)
+{
+       FreenectIn *vcap = (FreenectIn *) plug->priv;
+       if (vcap->f_dev) freenect_close_device(vcap->f_dev);
+       if (vcap->f_ctx) freenect_shutdown(vcap->f_ctx);
+       vcap->f_ctx = NULL;
+       vcap->f_dev = NULL;
+       gf_term_on_disconnect(vcap->service, NULL, GF_OK);
+       return GF_OK;
+}
+
+/*Dummy input just send a file name, no multitrack to handle so we don't need to check sub_url nor expected type*/
+static GF_Descriptor *Freenect_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
+{
+       return NULL;
+}
+
+
+GF_Err Freenect_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
+{
+       FreenectIn *vcap = (FreenectIn *) plug->priv;
+
+       if (!com->base.on_channel) return GF_NOT_SUPPORTED;
+
+       switch (com->command_type) {
+       case GF_NET_CHAN_SET_PULL: return GF_NOT_SUPPORTED;
+       case GF_NET_CHAN_INTERACTIVE: return GF_OK;
+       /*since data is file-based, no padding is needed (decoder plugin will handle it itself)*/
+       case GF_NET_CHAN_SET_PADDING: return GF_OK;
+       case GF_NET_CHAN_BUFFER:
+               com->buffer.max = com->buffer.min = 500;
+               return GF_OK;
+       case GF_NET_CHAN_DURATION:
+               /*this module is not made for updates, use undefined duration*/
+               com->duration.duration = 0;
+               return GF_OK;
+       case GF_NET_CHAN_PLAY:
+               if (!vcap->nb_running) {
+                       vcap->nb_running++;
+                       gf_th_run(vcap->th, FreenectRun, vcap);
+               }
+               return GF_OK;
+       case GF_NET_CHAN_STOP:
+               if (vcap->nb_running) {
+                       vcap->nb_running--;
+                       if (!vcap->nb_running) {
+                               while (! vcap->done) {
+                                       gf_sleep(10);
+                               }
+                       }
+               }
+               return GF_OK;
+       case GF_NET_CHAN_CONFIG: return GF_OK;
+       case GF_NET_CHAN_GET_DSI:
+               com->get_dsi.dsi = NULL;
+               com->get_dsi.dsi_len = 0;
+               return GF_OK;
+       }
+       return GF_OK;
+}
+
+GF_Err Freenect_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
+{
+       u32 ESID;
+       FreenectIn *vcap = (FreenectIn *) plug->priv;
+       
+       sscanf(url, "ES_ID=%u", &ESID);
+       if (ESID == 1) {
+               vcap->depth_channel = channel;
+               memset(&vcap->depth_sl_header, 0, sizeof(GF_SLHeader));
+               vcap->depth_sl_header.compositionTimeStampFlag = 1;
+               gf_term_on_connect(vcap->service, channel, GF_OK);
+       } else if (ESID == 2) {
+               vcap->color_channel = channel;
+               memset(&vcap->color_sl_header, 0, sizeof(GF_SLHeader));
+               vcap->color_sl_header.compositionTimeStampFlag = 1;
+               gf_term_on_connect(vcap->service, channel, GF_OK);
+       } else {
+               /*TODO*/
+               gf_term_on_connect(vcap->service, channel, GF_STREAM_NOT_FOUND);
+       }
+       return GF_OK;
+}
+
+GF_Err Freenect_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
+{
+       FreenectIn *vcap = (FreenectIn *) plug->priv;
+       if (vcap->depth_channel == channel) {
+               vcap->depth_channel = NULL;
+       }
+       else if (vcap->color_channel == channel) {
+               vcap->color_channel = NULL;
+       }
+       gf_term_on_disconnect(vcap->service, channel, GF_OK);
+       return GF_OK;
+}
+
+Bool Freenect_CanHandleURLInService(GF_InputService *plug, const char *url)
+{
+       return 0;
+}
+
+
+GF_EXPORT
+const u32 *QueryInterfaces() 
+{
+       static u32 si [] = {
+               GF_NET_CLIENT_INTERFACE,
+               0
+       };
+       return si;
+}
+
+GF_EXPORT
+GF_BaseInterface *LoadInterface(u32 InterfaceType)
+{
+       if (InterfaceType == GF_NET_CLIENT_INTERFACE) {
+               FreenectIn *vcap;
+               GF_InputService *plug;
+               GF_SAFEALLOC(plug, GF_InputService);
+               memset(plug, 0, sizeof(GF_InputService));
+               GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "Video Capture using libfreenect", "gpac distribution")
+
+               plug->RegisterMimeTypes = NULL;
+               plug->CanHandleURL = Freenect_CanHandleURL;
+               plug->ConnectService = Freenect_ConnectService;
+               plug->CloseService = Freenect_CloseService;
+               plug->GetServiceDescriptor = Freenect_GetServiceDesc;
+               plug->ConnectChannel = Freenect_ConnectChannel;
+               plug->DisconnectChannel = Freenect_DisconnectChannel;
+               plug->ServiceCommand = Freenect_ServiceCommand;
+               plug->CanHandleURLInService = Freenect_CanHandleURLInService;
+
+               GF_SAFEALLOC(vcap, FreenectIn);
+               plug->priv = vcap;
+               return (GF_BaseInterface *)plug;
+       } 
+       return NULL;
+}
+
+GF_EXPORT
+void ShutdownInterface(GF_BaseInterface *bi)
+{
+       if (bi->InterfaceType==GF_NET_CLIENT_INTERFACE) {
+               GF_InputService *ifcn = (GF_InputService*)bi;
+               FreenectIn *vcap = (FreenectIn*)ifcn->priv;
+
+               if (vcap->vid_buf) gf_free(vcap->vid_buf);
+               if (vcap->depth_buf) gf_free(vcap->depth_buf);
+               if (vcap->th) gf_th_del(vcap->th);
+               gf_free(vcap);
+               gf_free(bi);
+       }
+}
+
+
index 76ad5b0d8f3fad195ad3770739a6cabeb37cc382..22f8036f39277135bb4428ae4d80341be9f9ddc6 100644 (file)
@@ -99,8 +99,9 @@ void setBestFont(const char * listOfFonts[], char ** currentBestFont, const char
                        gf_free(*currentBestFont);
                *currentBestFont = NULL;
        }
-       if (! (*currentBestFont))
+       if (! (*currentBestFont)){
                *currentBestFont = gf_strdup(fontName);
+       }
 }
 
 static Bool ft_enum_fonts(void *cbck, char *file_name, char *file_path)
@@ -228,15 +229,67 @@ static void ft_rescan_fonts(GF_FontReader *dr)
        font_default = ftpriv->font_dir;
        ftpriv->font_dir = font_dir;
 
+
+       if (ftpriv->font_fixed) gf_free(ftpriv->font_fixed);
+       ftpriv->font_fixed = NULL;
+       if (ftpriv->font_sans) gf_free(ftpriv->font_sans);
+       ftpriv->font_sans = NULL;
+       if (ftpriv->font_serif) gf_free(ftpriv->font_serif);
+       ftpriv->font_serif = NULL;
+
+       /* let's check we have fonts that match our default Bol/Italic/BoldItalic conventions*/
+       count = gf_cfg_get_key_count(cfg, "FontEngine");
+       for (i=0; i<count; i++) {
+               const char *opt;
+               char fkey[GF_MAX_PATH];
+               const char *key = gf_cfg_get_key_name(cfg, "FontEngine", i);
+               opt = gf_cfg_get_key(cfg, "FontEngine", key);
+               if (!strchr(opt, '/') && !strchr(opt, '\\')) continue;
+               if (!strcmp(key, "FontDirectory")) continue;
+
+               if (strstr(key, "Bold")) continue; 
+               if (strstr(key, "Italic")) continue; 
+
+               strcpy(fkey, key);
+               strcat(fkey, " Italic");
+               opt = gf_cfg_get_key(cfg, "FontEngine", fkey);
+               if (!opt) continue;
+
+               strcpy(fkey, key);
+               strcat(fkey, " Bold");
+               opt = gf_cfg_get_key(cfg, "FontEngine", fkey);
+               if (!opt) continue;
+
+               strcpy(fkey, key);
+               strcat(fkey, " Bold Italic");
+               opt = gf_cfg_get_key(cfg, "FontEngine", fkey);
+               if (!opt) continue;
+
+               strcpy(fkey, key);
+               strlwr(fkey);
+               
+               /*this font is suited for our case*/
+               if (isBestFontFor(BEST_FIXED_FONTS, ftpriv->font_fixed, key) || (!ftpriv->font_fixed && (strstr(fkey, "fixed") || strstr(fkey, "mono")) ) ) {
+                       if (ftpriv->font_fixed) gf_free(ftpriv->font_fixed);
+                       ftpriv->font_fixed = gf_strdup(key);
+               }
+               
+               if (isBestFontFor(BEST_SANS_FONTS, ftpriv->font_sans, key) || (!ftpriv->font_sans && strstr(fkey, "sans")) ) {
+                       if (ftpriv->font_sans) gf_free(ftpriv->font_sans);
+                       ftpriv->font_sans = gf_strdup(key);
+               }
+               
+               if (isBestFontFor(BEST_SERIF_FONTS, ftpriv->font_serif, key) || (!ftpriv->font_serif && strstr(fkey, "serif")) ) {
+                       if (ftpriv->font_serif) gf_free(ftpriv->font_serif);
+                       ftpriv->font_serif = gf_strdup(key);
+               }
+       }
+
        if (!ftpriv->font_serif) ftpriv->font_serif = gf_strdup(font_default ?  font_default : "");
        if (!ftpriv->font_sans) ftpriv->font_sans = gf_strdup(font_default ?  font_default : "");
        if (!ftpriv->font_fixed) ftpriv->font_fixed = gf_strdup(font_default ?  font_default : "");
-
        if (font_default) gf_free(font_default);
 
-        /* We try these fonts in this order */
-       
-
        gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontFixed", ftpriv->font_fixed);
        gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontSerif", ftpriv->font_serif);
        gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontSans", ftpriv->font_sans);
@@ -389,22 +442,41 @@ static GF_Err ft_set_font(GF_FontReader *dr, const char *OrigFontName, u32 style
        in the cfg file*/
        if (!fontName || !strlen(fontName)) return GF_NOT_SUPPORTED;
        fname = gf_malloc(sizeof(char) * (strlen(fontName) + 50));
-       strcpy(fname, fontName);
-       if (styles & GF_FONT_WEIGHT_BOLD) strcat(fname, " Bold");
-       if (styles & GF_FONT_ITALIC) strcat(fname, " Italic");
 
-       opt = gf_modules_get_option((GF_BaseInterface *)dr, "FontEngine", fname);
-       gf_free(fname);
-       if (opt) {
-               FT_Face face;
-               if (FT_New_Face(ftpriv->library, opt, 0, & face )) return GF_IO_ERR;
-               if (!face) return GF_IO_ERR;
-               gf_list_add(ftpriv->loaded_fonts, face);
-               ftpriv->active_face = face;
-               return GF_OK;
+       {
+               int checkStyles = (styles & GF_FONT_WEIGHT_BOLD) | (styles & GF_FONT_ITALIC);
+       checkFont:
+               strcpy(fname, fontName);
+               if (styles & GF_FONT_WEIGHT_BOLD & checkStyles) strcat(fname, " Bold");
+               if (styles & GF_FONT_ITALIC & checkStyles) strcat(fname, " Italic");
+
+               opt = gf_modules_get_option((GF_BaseInterface *)dr, "FontEngine", fname);
+
+               if (opt) {
+                       FT_Face face;
+                       gf_free(fname);
+                       if (FT_New_Face(ftpriv->library, opt, 0, & face )) return GF_IO_ERR;
+                       if (!face) return GF_IO_ERR;
+                       gf_list_add(ftpriv->loaded_fonts, face);
+                       ftpriv->active_face = face;
+                       return GF_OK;
+               }
+               if (checkStyles){
+                       /* If we tried font + bold + italic -> we will try font + [bold | italic]
+                          If we tried font + [bold | italic] -> we try font
+                        */
+                       if (checkStyles == (GF_FONT_WEIGHT_BOLD | GF_FONT_ITALIC))
+                               checkStyles = GF_FONT_WEIGHT_BOLD;
+                       else if (checkStyles == GF_FONT_WEIGHT_BOLD && (styles & GF_FONT_ITALIC))
+                               checkStyles = GF_FONT_ITALIC;
+                       else if (checkStyles == GF_FONT_WEIGHT_BOLD || checkStyles == GF_FONT_ITALIC)
+                               checkStyles = 0;
+                       goto checkFont;
+               }
        }
 
-       GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FreeType] Font %s not found\n", fontName));
+       GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FreeType] Font '%s' (%s) not found\n", fontName, fname));
+       gf_free(fname);
        return GF_NOT_SUPPORTED;
 }
 
@@ -523,7 +595,10 @@ static GF_Glyph *ft_load_glyph(GF_FontReader *dr, u32 glyph_name)
 
        glyph_idx = FT_Get_Char_Index(ftpriv->active_face, glyph_name);
        /*missing glyph*/
-       if (!glyph_idx) return NULL;
+       if (!glyph_idx) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FreeType] Glyph not found for char %d in font %s (style %s)\n", glyph_name, ftpriv->active_face->family_name, ftpriv->active_face->style_name));
+               return NULL;
+       }
 
        /*work in design units*/
        FT_Load_Glyph(ftpriv->active_face, glyph_idx, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
index cd1e9b64e4bd4a95a86d4681570985b0dd31c972..32e8d47f94297c9dd32a3e59c697d77f8a3126ce 100644 (file)
@@ -695,6 +695,7 @@ GF_Err GAPI_SetupOGL_ES(GF_VideoOutput *dr)
                return GF_IO_ERR;
        }
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[GAPI] OpenGL initialize - %d x %d \n", gctx->bb_width, gctx->bb_height));
+       memset(&evt, 0, sizeof(GF_Event));
        evt.type = GF_EVENT_VIDEO_SETUP;
        dr->on_event(dr->evt_cbk_hdl, &evt);    
        return GF_OK;
index 62e50461d00eb1f9e1a7fdf4e17b2a7e8111c77d..05910974f75bb6643f1ff4459753008a1c05d375 100644 (file)
@@ -38,6 +38,9 @@
 
 #ifdef GPAC_HAS_SPIDERMONKEY
 
+#if defined(GPAC_ANDROID) && !defined(XP_UNIX)
+#define XP_UNIX
+#endif
 
 #if !defined(__GNUC__)
 #  pragma comment(lib, "js32")
@@ -724,7 +727,12 @@ static Bool gjs_event_filter(void *udta, GF_Event *evt, Bool consumed_by_composi
        if (consumed_by_compositor) return 0;
 
        if (gjs->evt != NULL) return 0;
-       gf_sg_lock_javascript(gjs->c, 1);
+       res = 0;
+       while (gjs->nb_loaded) {
+               res = gf_sg_try_lock_javascript(gjs->c);
+               if (res) break;
+       }
+       if (!res) return 0;
 
        rval = JSVAL_VOID;
        gjs->evt = evt;
diff --git a/modules/hyb_in/Makefile b/modules/hyb_in/Makefile
new file mode 100644 (file)
index 0000000..bdc9531
--- /dev/null
@@ -0,0 +1,57 @@
+include ../../config.mak
+
+vpath %.c $(SRC_PATH)/modules/hyb_in
+
+CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include"
+
+ifeq ($(DEBUGBUILD), yes)
+CFLAGS+=-g
+LDFLAGS+=-g
+endif
+
+ifeq ($(GPROFBUILD), yes)
+CFLAGS+=-pg
+LDFLAGS+=-pg
+endif
+
+#common obj
+OBJS=hyb_in.o fm_fake_pull.o fm_fake_push.o
+
+SRCS := $(OBJS:.o=.c) 
+
+LIB=gm_hyb_in.$(DYN_LIB_SUFFIX)
+
+
+all: $(LIB)
+
+
+$(LIB): $(OBJS)
+       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac
+ifeq ($(STATICBUILD),yes)
+       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_hyb_in-static.$(DYN_LIB_SUFFIX) $(OBJS) -L../../bin/gcc -lgpac_static
+endif
+
+
+%.o: %.c
+       $(CC) $(CFLAGS) -c -o $@ $< 
+
+
+clean: 
+       rm -f $(OBJS) ../../bin/gcc/$(LIB)
+
+dep: depend
+
+depend:
+       rm -f .depend   
+       $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+distclean: clean
+       rm -f Makefile.bak .depend
+
+
+
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
index 2680791a72c8228d9fe8f02842e9bc583d6c9813..e99920f60e52a523bb69f2cf91f302dcc9d3f157 100644 (file)
 \r
 /**********************************************************************************************************************/\r
 \r
+#define EXT_MEDIA_LOAD_THREADED\r
+\r
+/**********************************************************************************************************************/\r
+\r
 #define FM_FAKE_PULL_AUDIO_FREQ 44100\r
 #define FM_FAKE_PULL_CHAN_NUM  2\r
 #define FM_FAKE_PULL_BITS              16\r
@@ -44,6 +48,9 @@ typedef struct s_FM_FAKE_PULL {
        unsigned char buffer10[FM_FAKE_PULL_FRAME_LEN]; /*played 10 percent of time*/\r
        unsigned char buffer90[FM_FAKE_PULL_FRAME_LEN]; /*played 90 percent of time*/\r
 \r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+       GF_Thread *media_th;\r
+#endif\r
 } FM_FAKE_PULL;\r
 FM_FAKE_PULL FM_FAKE_PULL_private_data;\r
 \r
@@ -118,6 +125,17 @@ static GF_ObjectDescriptor* FM_FAKE_PULL_GetOD(void)
 \r
 /**********************************************************************************************************************/\r
 \r
+static u32 ext_media_load_th(void *par) {\r
+       GF_HYBMEDIA *self = (GF_HYBMEDIA*) par;\r
+       /*declare object to terminal*/\r
+       GF_ObjectDescriptor *od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);\r
+       od->URLString = gf_strdup("http://gpac.sourceforge.net/screenshots/lion.jpg");\r
+       od->objectDescriptorID = 0;\r
+       gf_sleep(2000); //TODO: remove the sleep\r
+       gf_term_add_media(self->owner, (GF_Descriptor*)od, 0);\r
+       return 0;\r
+}\r
+\r
 static GF_Err FM_FAKE_PULL_Connect(GF_HYBMEDIA *self, GF_ClientService *service, const char *url)\r
 {\r
        u32 i;\r
@@ -138,6 +156,20 @@ static GF_Err FM_FAKE_PULL_Connect(GF_HYBMEDIA *self, GF_ClientService *service,
                        *((FM_FAKE_PULL_TYPE*)((FM_FAKE_PULL*)self->private_data)->buffer10+i) = 1 << (FM_FAKE_PULL_BITS-1);\r
        }\r
 \r
+       /*for hybrid scenarios: add an external media*/\r
+       if (1) {\r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+               GF_Thread **th = &((FM_FAKE_PULL*)self->private_data)->media_th;\r
+               assert(*th == NULL);    //once at a time\r
+               *th = gf_th_new("HYB-FM fake external media load thread");\r
+               gf_th_run(*th, ext_media_load_th, self);\r
+#else\r
+               ext_media_load_th(self);\r
+#endif\r
+               //wait for video to begin as late video creates desynchro.\r
+               //gf_sleep(5000);\r
+       }\r
+\r
        return GF_OK;\r
 }\r
 \r
@@ -145,7 +177,11 @@ static GF_Err FM_FAKE_PULL_Connect(GF_HYBMEDIA *self, GF_ClientService *service,
 \r
 static GF_Err FM_FAKE_PULL_Disconnect(GF_HYBMEDIA *self)\r
 {\r
+       FM_FAKE_PULL *priv = (FM_FAKE_PULL*)self->private_data;\r
        self->owner = NULL;\r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+       gf_th_del(priv->media_th);\r
+#endif\r
        return GF_OK;\r
 }\r
 \r
index 1ef2c358e60c72263881fa23b7de88547fe9acc3..10e8950853ded7cdcf79934bcc74bbcc734682a6 100644 (file)
 \r
 /**********************************************************************************************************************/\r
 \r
-#define FM_FAKE_PUSH_AUDIO_FREQ 44100\r
+#define EXT_MEDIA_LOAD_THREADED\r
+\r
+/**********************************************************************************************************************/\r
+\r
+#define FM_FAKE_PUSH_AUDIO_FREQ 22050\r
 #define FM_FAKE_PUSH_CHAN_NUM  2\r
 #define FM_FAKE_PUSH_BITS              16\r
 #define FM_FAKE_PUSH_TYPE              s16\r
@@ -47,7 +51,9 @@ typedef struct s_FM_FAKE_PUSH {
        unsigned char buffer90[FM_FAKE_PUSH_FRAME_LEN]; /*played 90 percent of time*/\r
 \r
        GF_Thread *th;\r
-\r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+       GF_Thread *media_th;\r
+#endif\r
 } FM_FAKE_PUSH;\r
 FM_FAKE_PUSH FM_FAKE_PUSH_private_data;\r
 \r
@@ -146,71 +152,84 @@ static GF_Err GetData(const GF_HYBMEDIA *self, char **out_data_ptr, u32 *out_dat
 \r
 /**********************************************************************************************************************/\r
 \r
+u32 ext_media_load_th(void *par) {\r
+       GF_HYBMEDIA *self = (GF_HYBMEDIA*) par;\r
+       /*declare object to terminal*/\r
+       GF_ObjectDescriptor *od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);\r
+       od->URLString = gf_strdup("http://gpac.sourceforge.net/screenshots/lion.jpg");\r
+       od->objectDescriptorID = 0;\r
+       gf_sleep(2000); //TODO: remove the sleep\r
+       gf_term_add_media(self->owner, (GF_Descriptor*)od, 0);\r
+       return 0;\r
+}\r
+\r
 static u32 audio_gen_th(void *par) \r
 {\r
        GF_Err e;\r
        char *data;\r
        u32 data_size, init_time;\r
-       s32 time_to_wait = 0;\r
+       volatile s32 time_to_wait = 0;\r
        GF_SLHeader slh;\r
        GF_HYBMEDIA *self = (GF_HYBMEDIA*) par;\r
        FM_FAKE_PUSH *fm_fake_push = (FM_FAKE_PUSH*)self->private_data;\r
        memset(&slh, 0, sizeof(GF_SLHeader));\r
 \r
-       while (self->state >= 0) /*pause or play*/\r
        {\r
-               if (self->state == HYB_STATE_PAUSE) {\r
-                       gf_sleep(10);\r
-                       init_time = (u32)(gf_sys_clock() - ((u64)slh.compositionTimeStamp*1000)/FM_FAKE_PUSH_AUDIO_FREQ);       /*pause: won't wait at resume*/\r
-                       continue;\r
+               /*for hybrid scenarios: add an external media*/\r
+               if (1) {\r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+                       GF_Thread **th = &((FM_FAKE_PUSH*)self->private_data)->media_th;\r
+                       assert(*th == NULL);    //once at a time\r
+                       *th = gf_th_new("HYB-FM fake external media load thread");\r
+                       gf_th_run(*th, ext_media_load_th, par);\r
+#else\r
+                       ext_media_load_th(par);\r
+#endif\r
+                       gf_sleep(2000); //TODO: remove the sleep\r
                }\r
 \r
-               if (!time_to_wait)\r
-               {\r
-                       /*TODO: remove the sleep*/\r
-                       gf_sleep(1000);\r
-\r
-                       /*for hybrid scenarios: add an external media*/\r
+               if (0) {\r
+                       time_t now;\r
+                       struct tm *now_tm;\r
+                       time(&now);\r
+                       now_tm = gmtime(&now);\r
                        {\r
-                               /*declare object to terminal*/\r
-                               GF_ObjectDescriptor *od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);\r
-                               od->URLString = PUT_TOUR_URL_HERE;\r
-                               od->objectDescriptorID = 0;\r
-                               gf_term_add_media(self->owner, (GF_Descriptor*)od, 0);\r
+                               GF_NetworkCommand com;\r
+                               memset(&com, 0, sizeof(com));\r
+                               com.command_type = GF_NET_CHAN_MAP_TIME;\r
+\r
+                               com.map_time.media_time = now_tm->tm_hour*3600+now_tm->tm_min*60+now_tm->tm_sec;\r
+                               com.map_time.timestamp = slh.compositionTimeStamp;\r
+                               com.map_time.reset_buffers = 0;\r
+                               com.base.on_channel = self->channel;\r
+                               gf_term_on_command(self->owner, &com, GF_OK);\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[HYB In] Mapping WC  Time %04d/%02d/%02d %02d:%02d:%02d and Hyb time "LLD"\n",\r
+                                       (now_tm->tm_year + 1900), (now_tm->tm_mon + 1), now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec,\r
+                                       com.map_time.timestamp));\r
                        }\r
+               }\r
 \r
-                       /*for hybrid scenarios: map clocks*/\r
-                       {\r
-                               time_t now;\r
-                               struct tm *now_tm;\r
-                               time(&now);\r
-                               now_tm = gmtime(&now);\r
-                               {\r
-                                       GF_NetworkCommand com;\r
-                                       memset(&com, 0, sizeof(com));\r
-                                       com.command_type = GF_NET_CHAN_MAP_TIME;\r
-                                       com.map_time.media_time = now_tm->tm_hour*3600+now_tm->tm_min*60+now_tm->tm_sec;\r
-                                       com.map_time.timestamp = slh.compositionTimeStamp;\r
-                                       com.map_time.reset_buffers = 0;\r
-                                       com.base.on_channel = self->channel;\r
-                                       gf_term_on_command(self->owner, &com, GF_OK);\r
-                                       GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[HYB In] Mapping WC  Time %04d/%02d/%02d %02d:%02d:%02d and Hyb time "LLD"\n",\r
-                                               (now_tm->tm_year + 1900), (now_tm->tm_mon + 1), now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec,\r
-                                               com.map_time.timestamp));\r
-                               }\r
-                       }\r
+               /*initialize clock*/\r
+               init_time = gf_sys_clock();\r
+       }\r
 \r
-                       /*initialize clock*/\r
-                       init_time = gf_sys_clock();\r
+       while (self->state >= 0) /*pause or play*/\r
+       {\r
+               if (self->state == HYB_STATE_PAUSE) {\r
+                       gf_sleep(10);\r
+                       init_time = (u32)(gf_sys_clock() - ((u64)slh.compositionTimeStamp*1000)/FM_FAKE_PUSH_AUDIO_FREQ - 50/*50ms delay*/);    /*pause: won't wait at resume*/\r
+                       continue;\r
                }\r
 \r
-               time_to_wait = (u32)(init_time + ((u64)slh.compositionTimeStamp*1000)/FM_FAKE_PUSH_AUDIO_FREQ - gf_sys_clock());\r
+#if 0\r
+               time_to_wait = (s32)(init_time + ((u64)slh.compositionTimeStamp*1000)/FM_FAKE_PUSH_AUDIO_FREQ - gf_sys_clock());\r
                GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] FM_FAKE_PUSH - %d ms before next AU\n", time_to_wait));\r
                if (time_to_wait > 0) {\r
                        if (time_to_wait > 1000) /*TODO: understand the big shifts when playing icecasts contents*/\r
                                GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[HYB_IN] FM_FAKE_PUSH - audio asked to sleep for %d ms\n", time_to_wait));\r
                        gf_sleep(time_to_wait);\r
                }\r
+#endif\r
 \r
                e = GetData(self, &data, &data_size, &slh);\r
                gf_term_on_sl_packet(self->owner, self->channel, data, data_size, &slh, e);\r
@@ -274,6 +293,9 @@ static GF_Err FM_FAKE_PUSH_Disconnect(GF_HYBMEDIA *self)
 \r
        audio_gen_stop(self);\r
        gf_th_del(priv->th);\r
+#ifdef EXT_MEDIA_LOAD_THREADED\r
+       gf_th_del(priv->media_th);\r
+#endif\r
        priv->th = NULL;\r
 \r
        self->owner = NULL;\r
index bf598fcec31f77283774711b3dd3231ec8cf2906..6c3d0092196d05e061d030042148081e19385677 100644 (file)
 \r
 /*hybrid media interface implementation using MMB Tools from the Communication Research Center Canada (http://mmbtools.crc.ca/)*/\r
 \r
-#include <gpac/thread.h>\r
 \r
-#if 0\r
-\r
-\r
-GF_HYBMEDIA master_fm_mmbtools = {\r
-};\r
-\r
-\r
-typedef struct {\r
-       Bool clock_found_time; /*simulate the discovery of a RDS clock: arrives within the first minutes with a 100ms jitter*/\r
-\r
-       GF_Thread *fm_th;\r
-       volatile u32 fm_th_state;\r
-} FM_MMBTOOLS;\r
-\r
-\r
-\r
-static Bool FM_MMBTOOLS_CanHandleURL(const char *url)\r
-{\r
-       if (!strnicmp(url, "fm://", 5))\r
-               return 1;\r
-\r
-       return 0;\r
-}\r
-\r
-static GF_ObjectDescriptor* FM_MMBTOOLS_GetOD()\r
-{\r
-\r
-       return od;\r
-}\r
-\r
-static GF_Err HYB_FM_Close(GF_HYB_In *hyb_in)\r
-{\r
-       /*stop the audio_generation thread*/\r
-       hyb_in->fm_th_state = HYB_STATE_STOPPING;\r
-       while (hyb_in->fm_th_state != HYB_STATE_STOPPED)\r
-               gf_sleep(10);\r
-\r
-       return GF_OK;\r
-}\r
-\r
-static GF_Err HYB_FM_Connect(GF_HYB_In *hyb_in, const char *url)\r
-{\r
-       FM_MMBTOOLS* audio_gen;\r
-       if (hyb_in->fm_thread)\r
-               return GF_ERR;\r
-       GF_SAFEALLOC(audio_gen, FM_MMBTOOLS);\r
-       hyb_in->fm_thread = gf_th_new("HYB-FM fake audio generation thread");\r
-       gf_th_run(hyb_in->fm_thread, audio_gen_th, audio_gen);\r
-\r
-       return GF_OK;\r
-}\r
-\r
-static u32 audio_gen_th(void *par) \r
-{\r
-       FM_MMBTOOLS audio_gen = (FM_MMBTOOLS*) par;\r
-\r
-       /*RDS clock discovery time*/\r
-       clock_found_time = rand() % XXX; //radom in the 1st minute\r
-\r
-       while (!audio_gen->state) /*FM_MMBTOOLS_STATE_RUNNING*/\r
-       {\r
-               gf_sleep (remaining);\r
-\r
-               if (clock > clock_found_time && ) {\r
-                       gf_term_clock clock();\r
-               } else {\r
-                       gf_term_clock utc_clock();\r
-               }\r
-       }\r
-\r
-       audio_gen->state = FM_MMBTOOLS_STATE_STOPPED;\r
-}\r
-\r
-#endif\r
index 5500f5578a92293b4c6ea1cc66323a58484d5ebc..0fdd1729fb43e7bd0ecec668c8ccaa7d9cc908fa 100644 (file)
@@ -102,12 +102,12 @@ static GF_Err HYB_ConnectService(GF_InputService *plug, GF_ClientService *serv,
        GF_Err e = GF_OK;\r
        const size_t nb_masters = sizeof(hyb_masters) / sizeof(GF_HYBMEDIA*);\r
 \r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
 \r
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Connection request from service %p for %s\n", serv, url));\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Connection request from service %p for %s\n", serv, url));\r
 \r
-    if (!hyb_in || !serv || !url) return GF_BAD_PARAM;\r
-    hyb_in->service = serv;\r
+       if (!hyb_in || !serv || !url) return GF_BAD_PARAM;\r
+       hyb_in->service = serv;\r
 \r
        /*choose the master service*/\r
        for (i=0; i<nb_masters; i++) {\r
@@ -122,7 +122,7 @@ static GF_Err HYB_ConnectService(GF_InputService *plug, GF_ClientService *serv,
        e = hybmedia_sanity_check(hyb_in->master);\r
        if (e) {\r
                GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - object \"%s\" failed the sanity checks\n", hyb_in->master->name));\r
-        gf_term_on_connect(hyb_in->service, NULL, e);\r
+               gf_term_on_connect(hyb_in->service, NULL, e);\r
                return e;\r
        }\r
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Selected master object \"%s\" for URL: %s\n", hyb_in->master->name, url));\r
@@ -131,7 +131,7 @@ static GF_Err HYB_ConnectService(GF_InputService *plug, GF_ClientService *serv,
        e = hyb_in->master->Connect(hyb_in->master, hyb_in->service, url);\r
        if (e) {\r
                GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - cannot connect service, wrong URL %s\n", url));\r
-        gf_term_on_connect(hyb_in->service, NULL, GF_BAD_PARAM);\r
+               gf_term_on_connect(hyb_in->service, NULL, GF_BAD_PARAM);\r
                return e;\r
        }\r
        gf_term_on_connect(hyb_in->service, NULL, GF_OK);\r
@@ -143,41 +143,43 @@ static GF_Err HYB_ConnectService(GF_InputService *plug, GF_ClientService *serv,
 static GF_Err HYB_CloseService(GF_InputService *plug)\r
 {\r
        GF_Err e;\r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
 \r
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Close Service (%p) request from terminal\n", ((GF_HYB_In*)plug->priv)->service));\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Close Service (%p) request from terminal\n", ((GF_HYB_In*)plug->priv)->service));\r
 \r
        /*force to stop and disconnect the master*/\r
        hyb_in->master->SetState(hyb_in->master, GF_NET_CHAN_STOP);\r
        e = hyb_in->master->Disconnect(hyb_in->master);\r
        if (e) {\r
-        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - cannot disconnect service %p\n", hyb_in->service));\r
-        gf_term_on_connect(hyb_in->service, NULL, GF_BAD_PARAM);\r
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[HYB_IN] Error - cannot disconnect service %p\n", hyb_in->service));\r
+               gf_term_on_connect(hyb_in->service, NULL, GF_BAD_PARAM);\r
                return e;\r
        }\r
 \r
+       gf_term_on_disconnect(hyb_in->service, NULL, GF_OK);\r
+\r
        return GF_OK;\r
 }\r
 \r
 static GF_Descriptor *HYB_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)\r
 {\r
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Service Description request from terminal for %s\n", sub_url));\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Service Description request from terminal for %s\n", sub_url));\r
 \r
        return NULL;\r
 }\r
 \r
 static GF_Err HYB_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)\r
 {\r
-    GF_HYB_In *hyb_in;\r
+       GF_HYB_In *hyb_in;\r
        GF_HYBMEDIA *master;\r
 \r
-    if (!plug || !plug->priv)\r
+       if (!plug || !plug->priv)\r
                return GF_SERVICE_ERROR;\r
        \r
        hyb_in = (GF_HYB_In*)plug->priv;\r
        master = (GF_HYBMEDIA*)hyb_in->master;\r
 \r
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Channel Connection request from service %p for %s\n", channel, url));\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Channel Connection request from service %p for %s\n", channel, url));\r
        \r
        master->channel = channel;\r
        gf_term_on_connect(hyb_in->service, channel, GF_OK);\r
@@ -187,19 +189,19 @@ static GF_Err HYB_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, co
 \r
 static GF_Err HYB_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)\r
 {\r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
 \r
-    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Channel Disconnect Service (%p) request from terminal\n", hyb_in->service));\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[HYB_IN] Received Channel Disconnect Service (%p) request from terminal\n", hyb_in->service));\r
 \r
+       gf_term_on_disconnect(hyb_in->service, channel, GF_OK);\r
        hyb_in->master->channel = NULL;\r
-       gf_term_on_disconnect(hyb_in->service, NULL, GF_OK);\r
 \r
        return GF_OK;\r
 }\r
 \r
 static GF_Err HYB_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)\r
 {\r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
 \r
        switch (com->command_type) {\r
        case GF_NET_CHAN_SET_SPEED:\r
@@ -238,7 +240,7 @@ static Bool HYB_CanHandleURLInService(GF_InputService *plug, const char *url)
 \r
 static GF_Err HYB_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data)\r
 {\r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
        assert(hyb_in->master->data_mode == HYB_PULL && hyb_in->master->GetData && hyb_in->master->ReleaseData);\r
 \r
        assert(((GF_HYB_In*)plug->priv)->master->channel == channel);\r
@@ -251,7 +253,7 @@ static GF_Err HYB_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, cha
 \r
 static GF_Err HYB_ChannelReleaseSLP(GF_InputService *plug, LPNETCHANNEL channel)\r
 {\r
-    GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
+       GF_HYB_In *hyb_in = (GF_HYB_In*)plug->priv;\r
        assert(((GF_HYB_In*)plug->priv)->master->channel == channel);\r
        return GF_OK;\r
 }\r
@@ -259,38 +261,38 @@ static GF_Err HYB_ChannelReleaseSLP(GF_InputService *plug, LPNETCHANNEL channel)
 GF_EXPORT\r
 const u32 *QueryInterfaces()\r
 {\r
-    static u32 si [] = {\r
-        GF_NET_CLIENT_INTERFACE,\r
-        0\r
-    };\r
-    return si;\r
+       static u32 si [] = {\r
+               GF_NET_CLIENT_INTERFACE,\r
+               0\r
+       };\r
+       return si;\r
 }\r
 \r
 GF_EXPORT\r
 GF_BaseInterface *LoadInterface(u32 InterfaceType)\r
 {\r
-    GF_HYB_In *hyb_in;\r
-    GF_InputService *plug;\r
-    if (InterfaceType != GF_NET_CLIENT_INTERFACE) return NULL;\r
-\r
-    GF_SAFEALLOC(plug, GF_InputService);\r
-    GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC HYBRID MEDIA Loader", "gpac distribution")\r
-    plug->RegisterMimeTypes=   HYB_RegisterMimeTypes;\r
-    plug->CanHandleURL=                        HYB_CanHandleURL;\r
-    plug->ConnectService=              HYB_ConnectService;\r
-    plug->CloseService=                        HYB_CloseService;\r
-    plug->GetServiceDescriptor=        HYB_GetServiceDesc;\r
-    plug->ConnectChannel=              HYB_ConnectChannel;\r
-    plug->DisconnectChannel=   HYB_DisconnectChannel;\r
-    plug->ServiceCommand=              HYB_ServiceCommand;\r
-    plug->CanHandleURLInService=HYB_CanHandleURLInService;\r
-    plug->ChannelGetSLP=               HYB_ChannelGetSLP;\r
-    plug->ChannelReleaseSLP=   HYB_ChannelReleaseSLP;\r
-\r
-    GF_SAFEALLOC(hyb_in, GF_HYB_In);\r
-    plug->priv = hyb_in;\r
-\r
-    return (GF_BaseInterface *)plug;\r
+       GF_HYB_In *hyb_in;\r
+       GF_InputService *plug;\r
+       if (InterfaceType != GF_NET_CLIENT_INTERFACE) return NULL;\r
+\r
+       GF_SAFEALLOC(plug, GF_InputService);\r
+       GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC HYBRID MEDIA Loader", "gpac distribution")\r
+       plug->RegisterMimeTypes=        HYB_RegisterMimeTypes;\r
+       plug->CanHandleURL=                     HYB_CanHandleURL;\r
+       plug->ConnectService=           HYB_ConnectService;\r
+       plug->CloseService=                     HYB_CloseService;\r
+       plug->GetServiceDescriptor=     HYB_GetServiceDesc;\r
+       plug->ConnectChannel=           HYB_ConnectChannel;\r
+       plug->DisconnectChannel=        HYB_DisconnectChannel;\r
+       plug->ServiceCommand=           HYB_ServiceCommand;\r
+       plug->CanHandleURLInService=HYB_CanHandleURLInService;\r
+       plug->ChannelGetSLP=            HYB_ChannelGetSLP;\r
+       plug->ChannelReleaseSLP=        HYB_ChannelReleaseSLP;\r
+\r
+       GF_SAFEALLOC(hyb_in, GF_HYB_In);\r
+       plug->priv = hyb_in;\r
+\r
+       return (GF_BaseInterface *)plug;\r
 }\r
 \r
 GF_EXPORT\r
@@ -306,3 +308,4 @@ void ShutdownInterface(GF_BaseInterface *ifce)
                GF_LOG(GF_LOG_MEDIA, GF_LOG_ERROR, ("DeleteLoaderInterface %p: 2\n", ifce));\r
        }\r
 }\r
+\r
index 89789ee0a8b53e57117de9c7a7a68cbb82826d8f..7ce064f56296600ac7ace4c659b7702301a94699 100644 (file)
@@ -73,9 +73,15 @@ GF_ESD *IMG_GetESD(IMGLoader *read)
                u32 mtype, w, h;
                GF_BitStream *bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ);
                gf_img_parse(bs, &OTI, &mtype, &w, &h, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
-               esd->decoderConfig->objectTypeIndication = OTI;
                gf_bs_del(bs);
 
+               if (!OTI) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[IMG_IN] Unable to guess format image - assigning from extension\n"));
+                       if (read->img_type==IMG_JPEG) OTI = GPAC_OTI_IMAGE_JPEG;
+                       else if (read->img_type==IMG_PNG) OTI = GPAC_OTI_IMAGE_PNG;
+               }
+               esd->decoderConfig->objectTypeIndication = OTI;
+
                if (read->img_type == IMG_PNGD) {
                        GF_Descriptor *d = gf_odf_desc_new(GF_ODF_AUX_VIDEO_DATA);
                        ((GF_AuxVideoDescriptor*)d)->aux_video_type = 1;
@@ -190,7 +196,12 @@ void jp_download_file(GF_InputService *plug, const char *url)
        IMGLoader *read = (IMGLoader *) plug->priv;
 
        read->dnload = gf_term_download_new(read->service, url, 0, IMG_NetIO, read);
-       if (!read->dnload) gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       if (!read->dnload) {
+               gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
+       }
        /*service confirm is done once fetched*/
 }
 
@@ -315,6 +326,8 @@ static GF_Err IMG_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
 {
        IMGLoader *read = (IMGLoader *)plug->priv;
 
+       if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) return GF_NOT_SUPPORTED;
+
        if (!com->base.on_channel) return GF_NOT_SUPPORTED;
        switch (com->command_type) {
        case GF_NET_CHAN_SET_PADDING:
index 40a0398092800e92060003432de635f46f2282af..e3a13c9255fa4f1eb7e7d19571eead12bb4c8b28 100644 (file)
@@ -1,26 +1,26 @@
 /*
- *                     GPAC - Multimedia Framework C SDK
- *
- *                     Copyright (c) Jean Le Feuvre 2000-2005 
- *                                     All rights reserved
- *
- *  This file is part of GPAC / image format module
- *
- *  GPAC is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  GPAC 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 Lesser General Public License for more details.
- *   
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- */
+                     GPAC - Multimedia Framework C SDK
+*
+                     Copyright (c) Jean Le Feuvre 2000-2005 
+                                     All rights reserved
+*
+*  This file is part of GPAC / image format module
+*
+*  GPAC is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU Lesser General Public License as published by
+*  the Free Software Foundation; either version 2, or (at your option)
+*  any later version.
+*   
+*  GPAC 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 Lesser General Public License for more details.
+*   
+*  You should have received a copy of the GNU Lesser General Public
+*  License along with this library; see the file COPYING.  If not, write to
+*  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+*
+*/
 
 #include "img_in.h"
 
@@ -33,6 +33,7 @@ typedef struct
        /*no support for scalability with JPEG (progressive JPEG to test)*/
        u32 bpp, nb_comp, width, height, out_size, pixel_format, dsi_size;
        char *dsi;
+       opj_image_t *image;
 } JP2Dec;
 
 #define JP2CTX()       JP2Dec *ctx = (JP2Dec *) ((IMGDec *)ifcg->privateStack)->opaque
@@ -59,7 +60,7 @@ static GF_Err JP2_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
                case 1: ctx->pixel_format = GF_PIXEL_GREYSCALE; break;
                case 2: ctx->pixel_format = GF_PIXEL_ALPHAGREY; break;
                case 3: ctx->pixel_format = GF_PIXEL_RGB_24; break;
-               case 4: ctx->pixel_format = GF_PIXEL_ARGB; break;
+               case 4: ctx->pixel_format = GF_PIXEL_RGBA; break;
                default: return GF_NOT_SUPPORTED;
                }
        } else {
@@ -92,6 +93,11 @@ static GF_Err JP2_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
 }
 static GF_Err JP2_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID)
 {
+       JP2CTX();
+       if (ctx->image) {
+               opj_image_destroy(ctx->image);
+               ctx->image = NULL;
+       }
        return GF_OK;
 }
 static GF_Err JP2_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability)
@@ -167,26 +173,26 @@ void info_callback(const char *msg, void *client_data)
 }
 
 /*
- * Divide an integer by a power of 2 and round upwards.
- *
- * a divided by 2^b
- */
+* Divide an integer by a power of 2 and round upwards.
+*
+* a divided by 2^b
+*/
 static int int_ceildivpow2(int a, int b) {
        return (a + (1 << b) - 1) >> b;
 }
 
 static GF_Err JP2_ProcessData(GF_MediaDecoder *ifcg, 
-               char *inBuffer, u32 inBufferLength,
-               u16 ES_ID,
-               char *outBuffer, u32 *outBufferLength,
-               u8 PaddingBits, u32 mmlevel)
+                                                         char *inBuffer, u32 inBufferLength,
+                                                         u16 ES_ID,
+                                                         char *outBuffer, u32 *outBufferLength,
+                                                         u8 PaddingBits, u32 mmlevel)
 {
        u32 i, w, wr, h, hr, wh;
        opj_dparameters_t parameters;   /* decompression parameters */
        opj_event_mgr_t event_mgr;              /* event manager */
-       opj_image_t *image = NULL;
        opj_dinfo_t* dinfo = NULL;      /* handle to a decompressor */
        opj_cio_t *cio = NULL;
+       opj_codestream_info_t cinfo;
 
        JP2CTX();
 
@@ -199,14 +205,15 @@ static GF_Err JP2_ProcessData(GF_MediaDecoder *ifcg,
        }
 #endif
 
-       /* configure the event callbacks (not required) */
-       memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-       event_mgr.error_handler = error_callback;
-       event_mgr.warning_handler = warning_callback;
-       event_mgr.info_handler = info_callback;
+       if (!ctx->image) {
+               /* configure the event callbacks (not required) */
+               memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+               event_mgr.error_handler = error_callback;
+               event_mgr.warning_handler = warning_callback;
+               event_mgr.info_handler = info_callback;
 
-       /* set decoding parameters to default values */
-       opj_set_default_decoder_parameters(&parameters);
+               /* set decoding parameters to default values */
+               opj_set_default_decoder_parameters(&parameters);
 
                /* get a decoder handle */
                dinfo = opj_create_decompress(CODEC_JP2);
@@ -218,126 +225,179 @@ static GF_Err JP2_ProcessData(GF_MediaDecoder *ifcg,
                opj_setup_decoder(dinfo, &parameters);
 
 
-       /* open a byte stream */
-       if (ctx->dsi) {
-               char *data;
-               
-               data = gf_malloc(sizeof(char) * (ctx->dsi_size+inBufferLength));
-               memcpy(data, ctx->dsi, ctx->dsi_size);
-               memcpy(data+ctx->dsi_size, inBuffer, inBufferLength);
-               cio = opj_cio_open((opj_common_ptr)dinfo, data, ctx->dsi_size+inBufferLength);
-               /* decode the stream and fill the image structure */
-               image = opj_decode(dinfo, cio);
-               gf_free(data);
-       } else {
-               cio = opj_cio_open((opj_common_ptr)dinfo, inBuffer, inBufferLength);
-               /* decode the stream and fill the image structure */
-               image = opj_decode(dinfo, cio);
-       }
+               /* open a byte stream */
+               if (ctx->dsi) {
+                       char *data;
 
-       if(!image) {
-               opj_destroy_decompress(dinfo);
+                       data = gf_malloc(sizeof(char) * (ctx->dsi_size+inBufferLength));
+                       memcpy(data, ctx->dsi, ctx->dsi_size);
+                       memcpy(data+ctx->dsi_size, inBuffer, inBufferLength);
+                       cio = opj_cio_open((opj_common_ptr)dinfo, data, ctx->dsi_size+inBufferLength);
+                       /* decode the stream and fill the image structure */
+                       ctx->image = opj_decode(dinfo, cio);
+                       gf_free(data);
+               } else {
+                       cio = opj_cio_open((opj_common_ptr)dinfo, inBuffer, inBufferLength);
+                       /* decode the stream and fill the image structure */
+                       ctx->image = opj_decode_with_info(dinfo, cio, &cinfo);
+               }
+
+               //Fill the ctx info because dsi was not present
+               if (ctx->image) {
+                       ctx->nb_comp = cinfo.numcomps;
+                       ctx->width = cinfo.image_w;
+                       ctx->height = cinfo.image_h;
+                       ctx->bpp = ctx->nb_comp * 8;
+                       ctx->out_size = ctx->width * ctx->height * ctx->nb_comp /* * ctx->bpp / 8 */;
+
+                       switch (ctx->nb_comp) {
+                       case 1: ctx->pixel_format = GF_PIXEL_GREYSCALE; break;
+                       case 2: ctx->pixel_format = GF_PIXEL_ALPHAGREY; break;
+                       case 3: ctx->pixel_format = GF_PIXEL_RGB_24; break;
+                       case 4: ctx->pixel_format = GF_PIXEL_RGBA; break;
+                       default: return GF_NOT_SUPPORTED;
+                       }
+
+                       if ( *outBufferLength < ctx->out_size ) {
+                               *outBufferLength = ctx->out_size;
+                               opj_destroy_decompress(dinfo);
+                               opj_cio_close(cio);
+                               return GF_BUFFER_TOO_SMALL;
+                       }
+               }
+
+               if(!ctx->image) {
+                       opj_destroy_decompress(dinfo);
+                       opj_cio_close(cio);
+                       return GF_IO_ERR;
+               }
+
+               /* close the byte stream */
                opj_cio_close(cio);
-               return GF_IO_ERR;
+               cio = NULL;
+
+               /* gf_free( remaining structures */
+               if(dinfo) {
+                       opj_destroy_decompress(dinfo);
+                       dinfo = NULL;
+               }
        }
 
-       /* close the byte stream */
-       opj_cio_close(cio);
-       
-       w = image->comps[0].w;
-       wr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor);
-       h = image->comps[0].h;
-       hr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor);
+       w = ctx->image->comps[0].w;
+       wr = int_ceildivpow2(ctx->image->comps[0].w, ctx->image->comps[0].factor);
+       h = ctx->image->comps[0].h;
+       hr = int_ceildivpow2(ctx->image->comps[0].h, ctx->image->comps[0].factor);
        wh = wr*hr;
 
        if (ctx->nb_comp==1) {
                if ((w==wr) && (h==hr)) {
                        for (i=0; i<wh; i++) {
-                               outBuffer[i] = image->comps[0].data[i];
+                               outBuffer[i] = ctx->image->comps[0].data[i];
                        }
                } else {
                        for (i=0; i<wh; i++) {
-                               outBuffer[i] = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                               outBuffer[i] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
                        }
                }
        }
        else if (ctx->nb_comp==3) {
 
-               if ((image->comps[0].w==2*image->comps[1].w) && (image->comps[1].w==image->comps[2].w)
-               && (image->comps[0].h==2*image->comps[1].h) && (image->comps[1].h==image->comps[2].h)) {
-
-                       if (ctx->pixel_format != GF_PIXEL_YV12) {
-                               ctx->pixel_format = GF_PIXEL_YV12;
-                               ctx->out_size = 3*ctx->width*ctx->height/2;
-                               *outBufferLength = ctx->out_size;
-                               return GF_BUFFER_TOO_SMALL;
-                       }
+               if ((ctx->image->comps[0].w==2*ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w)
+                       && (ctx->image->comps[0].h==2*ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h)) {
 
-                       if ((w==wr) && (h==hr)) {
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[0].data[i];
-                                       outBuffer++;
-                               }
-                               w = image->comps[1].w;
-                               wr = int_ceildivpow2(image->comps[1].w, image->comps[1].factor);
-                               h = image->comps[1].h;
-                               hr = int_ceildivpow2(image->comps[1].h, image->comps[1].factor);
-                               wh = wr*hr;
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[1].data[i];
-                                       outBuffer++;
-                               }
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[2].data[i];
-                                       outBuffer++;
-                               }
-                       } else {
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
-                               }
-                               w = image->comps[1].w;
-                               wr = int_ceildivpow2(image->comps[1].w, image->comps[1].factor);
-                               h = image->comps[1].h;
-                               hr = int_ceildivpow2(image->comps[1].h, image->comps[1].factor);
-                               wh = wr*hr;
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                               if (ctx->pixel_format != GF_PIXEL_YV12) {
+                                       ctx->pixel_format = GF_PIXEL_YV12;
+                                       ctx->out_size = 3*ctx->width*ctx->height/2;
+                                       *outBufferLength = ctx->out_size;
+                                       return GF_BUFFER_TOO_SMALL;
                                }
-                               for (i=0; i<wh; i++) {
-                                       *outBuffer = image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
-                               }
-                       }
 
+                               if ((w==wr) && (h==hr)) {
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[0].data[i];
+                                               outBuffer++;
+                                       }
+                                       w = ctx->image->comps[1].w;
+                                       wr = int_ceildivpow2(ctx->image->comps[1].w, ctx->image->comps[1].factor);
+                                       h = ctx->image->comps[1].h;
+                                       hr = int_ceildivpow2(ctx->image->comps[1].h, ctx->image->comps[1].factor);
+                                       wh = wr*hr;
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[1].data[i];
+                                               outBuffer++;
+                                       }
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[2].data[i];
+                                               outBuffer++;
+                                       }
+                               } else {
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                       }
+                                       w = ctx->image->comps[1].w;
+                                       wr = int_ceildivpow2(ctx->image->comps[1].w, ctx->image->comps[1].factor);
+                                       h = ctx->image->comps[1].h;
+                                       hr = int_ceildivpow2(ctx->image->comps[1].h, ctx->image->comps[1].factor);
+                                       wh = wr*hr;
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                       }
+                                       for (i=0; i<wh; i++) {
+                                               *outBuffer = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                       }
+                               }
 
-               } else if ((image->comps[0].w==image->comps[1].w) && (image->comps[1].w==image->comps[2].w)
-               && (image->comps[0].h==image->comps[1].h) && (image->comps[1].h==image->comps[2].h)) {
 
-                       if ((w==wr) && (h==hr)) {
-                               for (i=0; i<wh; i++) {
-                                       u32 idx = 3*i;
-                                       outBuffer[idx] = image->comps[0].data[i];
-                                       outBuffer[idx+1] = image->comps[1].data[i];
-                                       outBuffer[idx+2] = image->comps[2].data[i];
+               } else if ((ctx->image->comps[0].w==ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w)
+                       && (ctx->image->comps[0].h==ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h)) {
+
+                               if ((w==wr) && (h==hr)) {
+                                       for (i=0; i<wh; i++) {
+                                               u32 idx = 3*i;
+                                               outBuffer[idx] = ctx->image->comps[0].data[i];
+                                               outBuffer[idx+1] = ctx->image->comps[1].data[i];
+                                               outBuffer[idx+2] = ctx->image->comps[2].data[i];
+                                       }
+                               } else {
+                                       for (i=0; i<wh; i++) {
+                                               u32 idx = 3*i;
+                                               outBuffer[idx] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                               outBuffer[idx+1] = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                               outBuffer[idx+2] = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                       }
                                }
-                       } else {
-                               for (i=0; i<wh; i++) {
-                                       u32 idx = 3*i;
-                                       outBuffer[idx] = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
-                                       outBuffer[idx+1] = image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
-                                       outBuffer[idx+2] = image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
-                               }
-                       }
                }
        }
+       else if (ctx->nb_comp==4) {
+               if ((ctx->image->comps[0].w==ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w) && (ctx->image->comps[2].w==ctx->image->comps[3].w)
+                       && (ctx->image->comps[0].h==ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h) && (ctx->image->comps[2].h==ctx->image->comps[3].h)) {
+
+                               if ((w==wr) && (h==hr)) {
+                                       for (i=0; i<wh; i++) {
+                                               u32 idx = 4*i;
+                                               outBuffer[idx] = ctx->image->comps[0].data[i];
+                                               outBuffer[idx+1] = ctx->image->comps[1].data[i];
+                                               outBuffer[idx+2] = ctx->image->comps[2].data[i];
+                                               outBuffer[idx+3] = ctx->image->comps[3].data[i];
+                                       }
+                               } else {
+                                       for (i=0; i<wh; i++) {
+                                               u32 idx = 4*i;
+                                               outBuffer[idx] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                               outBuffer[idx+1] = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                               outBuffer[idx+2] = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                               outBuffer[idx+3] = ctx->image->comps[3].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+                                       }
+                               }
+               }
+       }       
 
-       /* gf_free( remaining structures */
-       if(dinfo) {
-               opj_destroy_decompress(dinfo);
+       /* gf_free( image data structure */
+       if (ctx->image) {
+               opj_image_destroy(ctx->image);
+               ctx->image = NULL;
        }
 
-       /* gf_free( image data structure */
-       opj_image_destroy(image);
-       
        *outBufferLength = ctx->out_size;
        return GF_OK;
 }
index 12ec5a94ae314c33a6f6ccf240cf81853a387ebb..db86ff80e34515ef42e23f7cc72fc48a643cf22f 100644 (file)
@@ -80,6 +80,8 @@ static GF_Err ISMA_GetGPAC_KMS(ISMAEAPriv *priv, GF_Channel *ch, const char *kms
 
        sess = gf_term_download_new(ch->service, kms_url, 0, ISMA_KMS_NetIO, ch);
        if (!sess) return GF_IO_ERR;
+       /*start our download (threaded)*/
+       gf_dm_sess_process(sess);
 
        while (1) {
                e = gf_dm_sess_get_stats(sess, NULL, NULL, NULL, NULL, NULL, NULL);
index 539647ce4ee342f3e2219890b9a60f59af0cc3b4..2ef8bbd761b245add95169e2524d99654b5c980a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <gpac/constants.h>
 #include <gpac/modules/service.h>
+#include <gpac/thread.h>
 
 #ifndef GPAC_DISABLE_ISOM
 
@@ -59,6 +60,9 @@ typedef struct
 
        /*0: not fragmented - 1 fragmented - 2 fragmented and last fragment received*/
        u32 frag_type;
+
+       GF_Mutex *segment_mutex;
+
 } ISOMReader;
 
 
index 26c05d90b65ffd1316f02ced360b686754afed8a..3bc504de6f13c975e17819bda7b98b57886600ff 100644 (file)
@@ -140,7 +140,7 @@ void isor_declare_objects(ISOMReader *read)
 
                                /*write cover data*/
                                assert(!(tlen & 0x80000000));
-                               fwrite(tag, tlen & 0x7FFFFFFF, 1, t);
+                               gf_fwrite(tag, tlen & 0x7FFFFFFF, 1, t);
                                fclose(t);
 
                                /*don't display cover art when video is present*/
index 05b39f2bc310a4e40933912a02d2227bcb982a0e..e844cb2187b0e1118747cb00706707dcc7815156 100644 (file)
@@ -162,7 +162,7 @@ void isor_net_io(void *cbk, GF_NETIO_Parameter *param)
                return;
        }
        
-       e = gf_isom_open_progressive(local_name, &read->mov, &read->missing_bytes);
+       e = gf_isom_open_progressive(local_name, 0, 0, &read->mov, &read->missing_bytes);
        switch (e) {
        case GF_ISOM_INCOMPLETE_FILE:
                return;
@@ -185,7 +185,12 @@ void isor_setup_download(GF_InputService *plug, const char *url)
 {
        ISOMReader *read = (ISOMReader *) plug->priv;
        read->dnload = gf_term_download_new(read->service, url, 0, isor_net_io, read);
-       if (!read->dnload) gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       if (!read->dnload) {
+               gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
+       }
        /*service confirm is done once IOD can be fetched*/
 }
 
@@ -221,7 +226,18 @@ GF_Err ISOR_ConnectService(GF_InputService *plug, GF_ClientService *serv, const
        }
 
        if (isor_is_local(szURL)) {
-               GF_Err e = gf_isom_open_progressive(szURL, &read->mov, &read->missing_bytes);
+               GF_Err e;
+               u64 start_range, end_range;
+               start_range = end_range = 0;
+               if (plug->query_proxy) {
+                       GF_NetworkCommand param;
+                       param.command_type = GF_NET_SERVICE_QUERY_INIT_RANGE;
+                       if (read->input->query_proxy(read->input, &param)==GF_OK) {
+                               start_range = param.url_query.start_range;
+                               end_range = param.url_query.end_range;
+                       }
+               }
+               e = gf_isom_open_progressive(szURL, start_range, end_range, &read->mov, &read->missing_bytes);
                if (e != GF_OK){
                    GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IsoMedia] : error while opening %s, error=%s\n", szURL, gf_error_to_string(e)));
                        gf_term_on_connect(serv, NULL, e);
@@ -775,6 +791,7 @@ GF_Err ISOR_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                        if (com->play.end_range >= 0) ch->end = (u64) (s64) (com->play.end_range*ch->time_scale);
                }
                ch->is_playing = 1;
+               if (com->play.dash_segment_switch) ch->wait_for_segment_switch = 1;
                GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Starting channel playback "LLD" to "LLD" (%g to %g)\n", ch->start, ch->end, com->play.start_range, com->play.end_range));
                return GF_OK;
        case GF_NET_CHAN_STOP:
@@ -846,6 +863,8 @@ GF_InputService *isor_client_load()
 
        GF_SAFEALLOC(reader, ISOMReader);
        reader->channels = gf_list_new();
+       reader->segment_mutex = gf_mx_new("ISO Segment");
+       
        plug->priv = reader;
        return plug;
 }
index 801a02bfbd23be1cce7ca22bd9b42fd0d1097688..8328e3c923c27a599c3d2cee9b4d3d6221f4b4a2 100644 (file)
@@ -41,10 +41,72 @@ void isor_reset_reader(ISOMChannel *ch)
        ch->is_playing = 0;
 }
 
+static void check_segment_switch(ISOMReader *read)
+{
+       GF_NetworkCommand param;
+       u32 i, count;
+       GF_Err e;
+
+       /*access to the segment switching must be protected in case several decoders are threaded on the file using GetSLPacket */
+       gf_mx_p(read->segment_mutex);
+
+       if (!read->frag_type || !read->input->query_proxy) {
+               gf_mx_v(read->segment_mutex);
+               return;
+       }
+
+       count = gf_list_count(read->channels);
+       for (i=0; i<count; i++) {
+               ISOMChannel *ch = gf_list_get(read->channels, i);
+               /*check all playing channels are waiting for next segment*/
+               if (ch->is_playing && !ch->wait_for_segment_switch) {
+                       gf_mx_v(read->segment_mutex);
+                       return;
+               }
+       }
+       /*close current segment*/
+       gf_isom_release_segment(read->mov, 1);
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Done playing segment - querying new one\n"));
+
+       /*update current fragment if any*/
+       param.command_type = GF_NET_SERVICE_QUERY_NEXT;
+       if ((read->input->query_proxy(read->input, &param)==GF_OK) && param.url_query.next_url){
+               if (param.url_query.discontinuity_type==2)
+                       gf_isom_reset_fragment_info(read->mov);
+
+               e = gf_isom_open_segment(read->mov, param.url_query.next_url, param.url_query.start_range, param.url_query.end_range);
+
+#ifndef GPAC_DISABLE_LOG
+               if (e<0) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IsoMedia] Error opening new segment %s: %s\n", param.url_query.next_url, gf_error_to_string(e) ));
+               } else if (param.url_query.end_range) {
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Playing new range in %s: "LLU"-"LLU"\n", param.url_query.next_url, param.url_query.start_range, param.url_query.end_range ));
+               } else {
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] playing new segment %s\n", param.url_query.next_url));
+               }
+#endif
+
+               for (i=0; i<count; i++) {
+                       ISOMChannel *ch = gf_list_get(read->channels, i);
+                       ch->wait_for_segment_switch = 0;
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track %d - cur sample %d - new sample count %d\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track) ));
+               }
+       } else {
+               /*consider we are done*/
+               read->frag_type = 2;
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] No more segments - done playing file\n"));
+       }
+       gf_mx_v(read->segment_mutex);
+}
 
 static void init_reader(ISOMChannel *ch)
 {
        u32 ivar;
+       if (ch->wait_for_segment_switch) {
+               check_segment_switch(ch->owner);
+               if (ch->wait_for_segment_switch) 
+                       return;
+       }
 
        ch->current_slh.accessUnitEndFlag = 1;
        ch->current_slh.accessUnitStartFlag = 1;
@@ -64,7 +126,7 @@ static void init_reader(ISOMChannel *ch)
                ch->last_state=GF_OK;
        } else {
                /*take care of seeking out of the track range*/
-               if (ch->duration<ch->start) {
+               if (!ch->owner->frag_type && (ch->duration<ch->start)) {
                        ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->duration, &ivar, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->sample, &ch->sample_num);
                } else {
                        ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->start, &ivar, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->sample, &ch->sample_num);
@@ -100,44 +162,7 @@ static void init_reader(ISOMChannel *ch)
 
 }
 
-static void check_segment_switch(ISOMReader *read)
-{
-       GF_NetworkCommand param;
-       u32 i, count;
-       GF_Err e;
-       if (!read->frag_type) return;
-       if (!read->input->query_proxy) return;
 
-       count = gf_list_count(read->channels);
-       for (i=0; i<count; i++) {
-               ISOMChannel *ch = gf_list_get(read->channels, i);
-               /*check all playing channels are waiting for next segment*/
-               if (ch->is_playing && !ch->wait_for_segment_switch) {
-                       return;
-               }
-       }
-       /*close current segment*/
-       gf_isom_release_segment(read->mov, 1);
-       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Done playing segment - querying new one\n"));
-
-       /*update current fragment if any*/
-       param.command_type = GF_NET_SERVICE_QUERY_NEXT;
-       if ((read->input->query_proxy(read->input, &param)==GF_OK) && param.url_query.next_url){
-
-               e = gf_isom_open_segment(read->mov, param.url_query.next_url);
-               GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] playing new segment %s: %s\n", param.url_query.next_url, gf_error_to_string(e) ));
-
-               for (i=0; i<count; i++) {
-                       ISOMChannel *ch = gf_list_get(read->channels, i);
-                       ch->wait_for_segment_switch = 0;
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track %d - cur sample %d - new sample count %d\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track) ));
-               }
-       } else {
-               /*consider we are done*/
-               read->frag_type = 2;
-               GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] No more segments - done playing file\n"));
-       }
-}
 
 void isor_reader_get_sample(ISOMChannel *ch)
 {
@@ -151,43 +176,66 @@ void isor_reader_get_sample(ISOMChannel *ch)
                u32 prev_sample = ch->sample_num;
                e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &ivar, GF_ISOM_SEARCH_FORWARD, &ch->sample, &ch->sample_num);
 
-               /*we are in forced seek mode: fetch all samples before the one matching the sample time*/
-               if (ch->edit_sync_frame) {
-                       ch->edit_sync_frame++;
-                       if (ch->edit_sync_frame < ch->sample_num) {
-                               gf_isom_sample_del(&ch->sample);
-                               ch->sample = gf_isom_get_sample(ch->owner->mov, ch->track, ch->edit_sync_frame, &ivar);
-                               ch->sample->DTS = ch->sample_time;
-                               ch->sample->CTS_Offset = 0;
-                       } else {
-                               ch->edit_sync_frame = 0;
-                               if (ch->sample) ch->sample_time = ch->sample->DTS;
-                       }
-               } else {
-                       /*we jumped to another segment - if RAP is needed look for closest rap in decoding order and
-                       force seek mode*/
-                       if (ch->sample && !ch->sample->IsRAP && ch->has_rap && (ch->sample_num != prev_sample+1)) {
-                               GF_ISOSample *found = ch->sample;
-                               u32 samp_num = ch->sample_num;
-                               ch->sample = NULL;
-                               e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &ivar, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->sample, &ch->sample_num);
-                               /*if no sync point in the past, use the first non-sync for the given time*/
-                               if (!ch->sample || !ch->sample->data) {
+               if (e == GF_OK) {
+
+                       /*we are in forced seek mode: fetch all samples before the one matching the sample time*/
+                       if (ch->edit_sync_frame) {
+                               ch->edit_sync_frame++;
+                               if (ch->edit_sync_frame < ch->sample_num) {
                                        gf_isom_sample_del(&ch->sample);
-                                       ch->sample = found;
-                                       ch->sample_time = ch->sample->DTS;
-                                       ch->sample_num = samp_num;
-                               } else {
-                                       gf_isom_sample_del(&found);
-                                       ch->edit_sync_frame = ch->sample_num;
+                                       ch->sample = gf_isom_get_sample(ch->owner->mov, ch->track, ch->edit_sync_frame, &ivar);
                                        ch->sample->DTS = ch->sample_time;
                                        ch->sample->CTS_Offset = 0;
+                               } else {
+                                       ch->edit_sync_frame = 0;
+                                       if (ch->sample) ch->sample_time = ch->sample->DTS;
                                }
                        } else {
-                               if (ch->sample) ch->sample_time = ch->sample->DTS;
+                               /*if we get the same sample, figure out next interesting time (current sample + DTS gap to next sample should be a good bet)*/
+                               if (prev_sample == ch->sample_num) {
+                                       u32 time_diff = 2;
+                                       u32 sample_num = ch->sample_num ? ch->sample_num : 1;
+                                       GF_ISOSample *s1 = gf_isom_get_sample(ch->owner->mov, ch->track, sample_num, NULL);
+                                       GF_ISOSample *s2 = gf_isom_get_sample(ch->owner->mov, ch->track, sample_num+1, NULL);
+
+                                       gf_isom_sample_del(&ch->sample);
+
+                                       if (s2 && s1) {
+                                               time_diff = (u32) (s2->DTS - s1->DTS);
+                                               e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + time_diff, &ivar, GF_ISOM_SEARCH_FORWARD, &ch->sample, &ch->sample_num);
+                                       } else if (s1 && !s2) {
+                                               e = GF_EOS;
+                                       }
+                                       gf_isom_sample_del(&s1);
+                                       gf_isom_sample_del(&s2);
+
+                               }
+
+                               /*we jumped to another segment - if RAP is needed look for closest rap in decoding order and
+                               force seek mode*/
+                               if (ch->sample && !ch->sample->IsRAP && ch->has_rap && (ch->sample_num != prev_sample+1)) {
+                                       GF_ISOSample *found = ch->sample;
+                                       u32 samp_num = ch->sample_num;
+                                       ch->sample = NULL;
+                                       e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &ivar, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->sample, &ch->sample_num);
+                                       assert (e == GF_OK);
+                                       /*if no sync point in the past, use the first non-sync for the given time*/
+                                       if (!ch->sample || !ch->sample->data) {
+                                               gf_isom_sample_del(&ch->sample);
+                                               ch->sample = found;
+                                               ch->sample_time = ch->sample->DTS;
+                                               ch->sample_num = samp_num;
+                                       } else {
+                                               gf_isom_sample_del(&found);
+                                               ch->edit_sync_frame = ch->sample_num;
+                                               ch->sample->DTS = ch->sample_time;
+                                               ch->sample->CTS_Offset = 0;
+                                       }
+                               } else {
+                                       if (ch->sample) ch->sample_time = ch->sample->DTS;
+                               }
                        }
                }
-
        } else {
                ch->sample_num++;
 fetch_next:
@@ -225,7 +273,8 @@ fetch_next:
                } else {
                        GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track #%d fail to fetch sample %d / %d: %s\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track), gf_error_to_string(gf_isom_last_error(ch->owner->mov)) ));
                }
-               if (ch->wait_for_segment_switch) check_segment_switch(ch->owner);
+               if (ch->wait_for_segment_switch)
+                       check_segment_switch(ch->owner);
                return;
        }
        ch->last_state = GF_OK;
index 67276d4797011a7948118a274c77ddb7cd7db576..57dda9110d70788fa9a85b063af98225219dc40f 100644 (file)
@@ -44,7 +44,24 @@ typedef s32 off_t;
 
 #endif
 
+// variable used to detect the number of libplayer instances created - up to 2 instances  
 static int libplayer_id = 0;
+//! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user 
+//! uses the navigation button
+// value for input output windows, when save_data_instance1 equals to 1 <=> the second instance is already created with the correct size, 
+// save these values in in_instance1 and out_instance1 so that we do not need to recalculate every time  
+//~ static video_rect_t in_instance1, out_instance1;
+//~ static save_data_instance1 = 0;
+
+// variable use to detect whether a dvb instance has already started for instance 1
+static int start_dvb = 0;
+
+enum
+{
+       PLAYER_FILE = 0,
+       PLAYER_DVB = 1
+};
+
 
 typedef struct
 {
@@ -53,6 +70,7 @@ typedef struct
        u32 init;
        u32 state;
        u32 player_id;
+       u32 player_type;
        u32 width;
        u32 height;
     char *url;
@@ -102,6 +120,8 @@ Bool LIBPLAYER_CanHandleURL(GF_InputService *plug, const char *url)
                u32 i;
                Bool ok = 0;
                char *cgi_par;
+               // case dvb
+               if (!strnicmp(url, "dvb://", 6)) return 1;
                if (!strnicmp(sExt, ".gz", 3)) sExt = strrchr(sExt, '.');
                if (!strnicmp(url, "rtsp://", 7)) return 0;
                sExt++;
@@ -118,6 +138,7 @@ Bool LIBPLAYER_CanHandleURL(GF_InputService *plug, const char *url)
                if (cgi_par) cgi_par[0] = '?';
                if (ok) return 1;
        }
+       
        return 0;
 }
 
@@ -169,6 +190,8 @@ GF_Err LIBPLAYER_ConnectService(GF_InputService *plug, GF_ClientService *serv, c
                read->height = 20;
                read->url = url;
                read->player_id = libplayer_id;
+               read->player_type = PLAYER_FILE;
+               
 #ifndef TEST_LIBPLAYER
                read->player = player_init(PLAYER_TYPE_DUMMY, PLAYER_AO_AUTO, PLAYER_VO_AUTO, PLAYER_MSG_INFO, read->player_id, on_libplayer_event);
                
@@ -184,7 +207,84 @@ GF_Err LIBPLAYER_ConnectService(GF_InputService *plug, GF_ClientService *serv, c
        
 #ifndef TEST_LIBPLAYER
        mrl = NULL;
+       
+       // dvb 
        if (!strnicmp(url, "dvb://", 6)) {
+               read->player_type = PLAYER_DVB;
+               mrl_resource_dvb_args_t *mrl_dvb_args;
+               mrl_dvb_args = calloc(1, sizeof(mrl_resource_dvb_args_t));
+               char *frequency;
+               
+               // fetch frequency
+               if (frequency = strchr(url+6, '@')) {
+                       char *enc, *pid;
+                       mrl_dvb_args->frequency = atoi(frequency+1);
+
+                       /*
+                        * video
+                        */
+                       // video codec
+                       if (enc = strstr(url+6, "mpeg2")) {
+                               mrl_dvb_args->video_enc = PLAYER_VIDEO_MPEG2;
+                       }
+                       else if (enc = strstr(url+6, "h264")) {
+                               mrl_dvb_args->video_enc = PLAYER_VIDEO_H264;
+                       }
+                       else {
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Unknown video encoding\n"));
+                               mrl_dvb_args->video_enc = PLAYER_VIDEO_UNKNOWN;
+                       }
+                       
+                       // video PID
+                       if (mrl_dvb_args->video_enc != PLAYER_VIDEO_UNKNOWN) {
+                               pid = strchr(enc, ':');
+                               mrl_dvb_args->video_pid = atoi(pid+1);
+                       }
+                       
+                       /*
+                        * audio 
+                        */
+                       // audio codec
+                       if (enc = strstr(url+6, "mp2")) {
+                               mrl_dvb_args->audio_enc = PLAYER_AUDIO_MP2;
+                       }
+                       else if (enc = strstr(url+6, "ac3")) {
+                               mrl_dvb_args->audio_enc = PLAYER_AUDIO_AC3;
+                       }
+                       else {
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Unknown audio encoding\n"));
+                               mrl_dvb_args->audio_enc = PLAYER_AUDIO_UNKNOWN;
+                       }
+                       
+                       // audio PID
+                       if (mrl_dvb_args->audio_enc != PLAYER_AUDIO_UNKNOWN) {
+                               pid = strchr(enc, ':');
+                               mrl_dvb_args->audio_pid = atoi(pid+1);
+                       }
+                       
+                       if (mrl_dvb_args->video_enc == PLAYER_VIDEO_UNKNOWN && mrl_dvb_args->audio_enc == PLAYER_AUDIO_UNKNOWN) {
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Unknown video and audio encoding\n"));
+                               free(mrl_dvb_args);
+                               return GF_BAD_PARAM;
+                       }
+               }
+               else {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Unknown frequency\n"));
+                       free(mrl_dvb_args);
+                       return GF_BAD_PARAM;
+               }
+
+               // player instance 1 has not starter yet in dvb case <=> player instance 1 is not created yet 
+               if (start_dvb == 0) {
+                       mrl = mrl_new(read->player, MRL_RESOURCE_DVB, mrl_dvb_args);
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] MRL created for DVB\n"));
+               
+               // player has already started, zapping case, make sure the player is not recreated
+               } else {
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Starting DVB PES filtering\n"));
+                       player_dvb_pes_filter_start(read->player, mrl_dvb_args->video_enc, mrl_dvb_args->video_pid, mrl_dvb_args->audio_enc, mrl_dvb_args->audio_pid);
+               }
+
        }
        else if (!strnicmp(url, "file://", 7) || !strstr(url, "://")) {
                mrl_resource_local_args_t *mrl_args;
@@ -195,17 +295,19 @@ GF_Err LIBPLAYER_ConnectService(GF_InputService *plug, GF_ClientService *serv, c
                        mrl_args->location = strdup(url);
                }
                mrl = mrl_new (read->player, MRL_RESOURCE_FILE, mrl_args);
-       }
-       else {
+               
        }
 
-       if (!mrl) {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Failed to create MRL for url %s\n", url));
-               gf_term_on_connect(serv, NULL, GF_URL_ERROR);
-               return GF_OK;
+       // only for DVB case to make sure player is only set once
+       if (start_dvb == 0) {
+               if (!mrl) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Failed to create MRL for url %s\n", url));
+                       gf_term_on_connect(serv, NULL, GF_URL_ERROR);
+                       return GF_OK;
+               }
+               
+               player_mrl_set(read->player, mrl);
        }
-       
-    player_mrl_set(read->player, mrl);
 
 #endif
        read->state = 0;
@@ -242,20 +344,29 @@ GF_Err LIBPLAYER_CloseService(GF_InputService *plug)
        LibPlayerIn *read = (LibPlayerIn *) plug->priv;
        
 #ifndef TEST_LIBPLAYER
+       // only disconnect if 
+       if (read->player_type == PLAYER_FILE) {
                player_playback_stop(read->player);
                printf("[LibPlayerIN]player_playback_stop for instance %d\n", read->player_id);
                player_uninit(read->player);
                printf("[LibPlayerIN]player_uninit for instance %d\n", read->player_id);
                read->player = NULL;
                libplayer_id--;
-
-
-#endif
+               
                read->state = 0;
 
-       gf_term_on_disconnect(read->service, NULL, GF_OK);
-       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIn] Closing libplayer instance %d\n", read->player_id));
+               gf_term_on_disconnect(read->service, NULL, GF_OK);
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIn] Closing libplayer instance %d\n", read->player_id));
+               
+               
+       
+       // channel zapping dvb case, don't disconnect service
+       } else {
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIn] Don't close service libplayer instance %d, use this instance for channel zapping\n", read->player_id));
+       }
+
        return GF_OK;
+#endif
 }
 
 /*Dummy input just send a file name, no multitrack to handle so we don't need to check sub_url nor expected type*/
@@ -290,19 +401,34 @@ GF_Err LIBPLAYER_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
        case GF_NET_CHAN_PLAY:
                if (read->state==0) {
 #ifndef TEST_LIBPLAYER
-                       player_playback_start(read->player);
+                       if ((read->player_id == 0) && (read->player_type == PLAYER_DVB) && (start_dvb == 1)) {
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Instance %d has already started, zapping mode\n", read->player_id));
+                       
+                       } else {
+                               player_playback_start(read->player);
+                               if ((read->player_id == 0) && (read->player_type == PLAYER_DVB)) {
+                                       start_dvb = 1;
+                               }
+                               
+                               read->state = 1;
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Starting playback for instance %d\n", read->player_id));
+                       }
 #endif
-                       read->state = 1;
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Starting playback for instance %d\n", read->player_id));
                }
+               
                return GF_OK;
        case GF_NET_CHAN_STOP:
                if (read->state==1) {
 #ifndef TEST_LIBPLAYER
-                       player_playback_pause(read->player);
+                       // channel zapping, don't stop channel
+            if ((read->player_id == 0) && (read->player_type == PLAYER_DVB) && (start_dvb = 1)) {
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Instance %d is in zapping mode, don't stop channel\n", read->player_id));
+                       } else {
+                               player_playback_stop(read->player);
+                               read->state = 0;
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Stopping playback for instance %d\n", read->player_id));
+                       }
 #endif
-                       read->state = 0;
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Stopping playback for instance %d\n", read->player_id));
                }
                return GF_OK;
        case GF_NET_CHAN_CONFIG:  return GF_OK;
@@ -341,6 +467,7 @@ GF_Err LIBPLAYER_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
 Bool LIBPLAYER_CanHandleURLInService(GF_InputService *plug, const char *url)
 {
        return 0;
+       //return 1;
 }
 
 static GF_Err LIBPLAYER_AttachStream(GF_BaseDecoder *dec, GF_ESD *esd)
@@ -408,11 +535,24 @@ static GF_Err LIBPLAYER_Control(GF_PrivateMediaDecoder *dec, Bool mute, GF_Windo
        
        if (!read) return GF_OK;
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] Control instance %d\n",read->player_id));
-
+       //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user 
+       //! uses the navigation button
+       //~ if (read->player_id == 1 && save_data_instance1 == 1) {
+               //~ printf("in here for save data instance\n");
+               //~ player_video_io_windows_set(read->player, &in_instance1, &out_instance1);
+               //~ 
+               //~ return GF_OK;
+               //~ 
+       //~ } else {
        width = mrl_get_property(read->player, NULL, MRL_PROPERTY_VIDEO_WIDTH);
        height = mrl_get_property(read->player, NULL, MRL_PROPERTY_VIDEO_HEIGHT);
+       //~ }
+
+       
 
        if((width != read->width) || (height != read->height))  {
+               printf("in here for video size changed\t");
+               printf("width %d read->width %d height %d read->height %d\n", width, read->width, height, read->height);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] video size changed to width %d - height %d\n", width, height));
                if (width && height) {
                        read->width = width;
@@ -421,15 +561,26 @@ static GF_Err LIBPLAYER_Control(GF_PrivateMediaDecoder *dec, Bool mute, GF_Windo
                return GF_BUFFER_TOO_SMALL;
        }
        
-               in.x = src->x;
-               in.y = src->y;
-               in.w = src->w;
-               in.h = src->h;
-               out.x = dst->x;
-               out.y = dst->y;
-               out.w = dst->w;
-               out.h = dst->h;
-               player_video_io_windows_set(read->player, &in, &out);
+       in.x = src->x;
+       in.y = src->y;
+       in.w = src->w;
+       in.h = src->h;
+       out.x = dst->x;
+       out.y = dst->y;
+       out.w = dst->w;
+       out.h = dst->h;
+       player_video_io_windows_set(read->player, &in, &out);
+       
+       //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user 
+       //! uses the navigation button
+       //~ if (read->player_id == 1) {
+               //~ in_instance1 = in;
+       //~ //  //~ out_instance1.w = out.w;
+       //~ //  //~ out_instance1.h = out.h;
+               //~ out_instance1 = out;
+               //~ save_data_instance1 = 1;
+       //~ }
+       //~ 
        
 #endif
        
index 2565a434e0bde65266de98d11ace0595b53ed14f..6ae3255961a0ee3186d914ac588da0e78099efae 100644 (file)
@@ -354,6 +354,9 @@ void mp3_download_file(GF_InputService *plug, char *url)
        if (!read->dnload) {
                read->needs_connection = 0;
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
        }
        /*service confirm is done once fetched*/
 }
index 6e03e95143d647c582cb3584f46859a4aff31efd..c7734f1882fbe760454e10a4232199d6547d11c7 100644 (file)
 #include <gpac/internal/m3u8.h>
 #include <string.h>
 
+/*set to 1 if you want MPD to use SegmentTemplate if possible instead of SegmentList*/
+#define M3U8_TO_MPD_USE_TEMPLATE       0
 
 /*!
  * All the possible Mime-types for MPD files
  */
-static const char * MPD_MIME_TYPES[] = { "video/vnd.3gpp.mpd", "audio/vnd.3gpp.mpd", NULL };
+static const char * MPD_MIME_TYPES[] = { "application/dash+xml", "video/vnd.3gpp.mpd", "audio/vnd.3gpp.mpd", NULL };
 
 /*!
  * All the possible Mime-types for M3U8 files
@@ -55,21 +57,29 @@ typedef struct
 {
     char *cache;
     char *url;
+       u64 start_range, end_range;
 } segment_cache_entry;
 
+/*this structure Group is the implementation of the adaptationSet element of the MPD.*/
 typedef struct __mpd_group 
 {
-       GF_List *representations;
-       u32 group_id;
+       /*pointer to adaptation set*/
+       GF_MPD_AdaptationSet *adaptation_set;
+       /*pointer to active period*/
+       GF_MPD_Period *period;
+
+       /*active representation index in adaptation_set->representations*/
+       u32 active_rep_index;
+
        Bool selected;
        Bool done;
        Bool force_switch_bandwidth;
        u32 nb_bw_check;
-       /*pointer toactive period*/
-       GF_MPD_Period *period;
-       /*active representation index in period->representations*/
-       u32 active_rep_index;
        u32 active_bitrate, max_bitrate, min_bitrate;
+
+       u32 nb_segments_in_rep;
+       Double segment_duration;
+
        /*local file playback, do not delete them*/
        Bool local_files;
        /*next segment to download for this group*/
@@ -77,20 +87,28 @@ typedef struct __mpd_group
 
        /*next file (cached) to delete at next GF_NET_SERVICE_QUERY_NEXT for this group*/
     char * urlToDeleteNext;
-    volatile u32 max_cached, nb_cached;
+    volatile u32 max_cached_segments, nb_cached_segments;
     segment_cache_entry *cached;
 
     GF_DownloadSession *segment_dnload;
     const char *segment_local_url;
+       /*usually 0-0 (no range) but can be non-zero when playing local MPD/DASH sessions*/
+       u64 local_url_start_range, local_url_end_range;
 
     u32 nb_segments_done;
 
     Bool segment_must_be_streamed;
 
        /* Service really managing the segments */
-    GF_InputService *service;
+    GF_InputService *input_module;
     char *service_mime;
-    Bool service_connected;
+    Bool service_connected, service_descriptor_fetched;
+
+       struct __mpd_module *mpd_in;
+
+       u32 force_representation_idx_plus_one;
+
+       Bool force_segment_switch;
 } GF_MPD_Group;
 
 typedef struct __mpd_module {
@@ -102,7 +120,7 @@ typedef struct __mpd_module {
 
     u32 option_max_cached;
     u32 auto_switch_count;
-    Bool keep_files;
+    Bool keep_files, disable_switching;
 
        /* MPD downloader*/
     GF_DownloadSession *mpd_dnload;
@@ -117,6 +135,9 @@ typedef struct __mpd_module {
 
        /* active period in MPD (only one currently supported) */
     u32 active_period_index;
+       u32 request_period_switch;
+
+       u64 start_time_in_active_period;
 
        /*list of groups in the active period*/
        GF_List *groups;
@@ -134,9 +155,23 @@ typedef struct __mpd_module {
 
 
     /* TODO - handle playback status for SPEED/SEEK through SIDX */
-    Double playback_speed, playback_start_range, playback_end_range;
+    Double playback_speed, playback_start_range, previous_start_range;
+       Bool in_seek;
 } GF_MPD_In;
 
+void MPD_ResetGroups(GF_MPD_In *mpdin);
+GF_Err MPD_SetupPeriod(GF_MPD_In *mpdin);
+void MPD_SeekGroupsDownloads(GF_MPD_In *mpdin);
+
+
+static const char *MPD_GetMimeType(GF_MPD_SubRepresentation *subrep, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set)
+{
+       if (subrep && subrep->mime_type) return subrep->mime_type;
+       if (rep && rep->mime_type) return rep->mime_type;
+       if (set && set->mime_type) return set->mime_type;
+       return NULL;
+}
+
 
 static Bool MPD_CheckRootType(const char *local_url)
 {
@@ -171,40 +206,41 @@ void MPD_NetIO_Segment(void *cbk, GF_NETIO_Parameter *param)
        }       
        
     if ((param->msg_type == GF_NETIO_PARSE_HEADER) && !strcmp(param->name, "Content-Type")) {
-               if (!group->service_mime) group->service_mime = gf_strdup(param->value);
-               else if (strcmp(group->service_mime, param->value)) {
-                       GF_MPD_Representation *rep = gf_list_get(group->period->representations, group->active_rep_index);
-                       if (!rep->mime) rep->mime = gf_strdup(param->value);
+               if (!group->service_mime) {
+                       group->service_mime = gf_strdup(param->value);
+               } else if (strcmp(group->service_mime, param->value)) {
+                       GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index);
+                       if (! MPD_GetMimeType(NULL, rep, group->adaptation_set) ) rep->mime_type = gf_strdup(param->value);
                        rep->disabled = 1;
                        group->force_switch_bandwidth = 1;
-            gf_dm_sess_abort(group->segment_dnload);
+                       gf_dm_sess_abort(group->segment_dnload);
                        return;
                }
        }
 
        e = param->error;
-    if (param->msg_type == GF_NETIO_PARSE_REPLY) {
-        if (! gf_dm_sess_can_be_cached_on_disk(group->segment_dnload)) {
-            GF_LOG(GF_LOG_INFO, GF_LOG_MODULE,
-                   ("[MPD_IN] Segment %s cannot be cached on disk, will use direct streaming\n", gf_dm_sess_get_resource_name(group->segment_dnload)));
-            group->segment_must_be_streamed = 1;
-            gf_dm_sess_abort(group->segment_dnload);
-        } else {
-            group->segment_must_be_streamed = 0;
-        }
-    }
+       if (param->msg_type == GF_NETIO_PARSE_REPLY) {
+               if (! gf_dm_sess_can_be_cached_on_disk(group->segment_dnload)) {
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE,
+                               ("[MPD_IN] Segment %s cannot be cached on disk, will use direct streaming\n", gf_dm_sess_get_resource_name(group->segment_dnload)));
+                       group->segment_must_be_streamed = 1;
+                       gf_dm_sess_abort(group->segment_dnload);
+               } else {
+                       group->segment_must_be_streamed = 0;
+               }
+       }
        else if ((param->msg_type == GF_NETIO_DATA_EXCHANGE) || (param->msg_type == GF_NETIO_DATA_TRANSFERED)) {
-               if (gf_dm_sess_get_stats(group->segment_dnload, NULL, NULL, NULL, NULL, &download_rate, NULL) == GF_OK) {
+               if (!group->mpd_in->disable_switching && (gf_dm_sess_get_stats(group->segment_dnload, NULL, NULL, NULL, NULL, &download_rate, NULL) == GF_OK)) {
                        if (download_rate) {
                                download_rate *= 8;
                                if (download_rate<group->min_bitrate) group->min_bitrate = download_rate;
                                if (download_rate>group->max_bitrate) group->max_bitrate = download_rate;
 
                                if (download_rate && (download_rate < group->active_bitrate)) {
-                                       fprintf(stdout, "Downloading from group %d at rate %d kbps but group bitrate is %d kbps\n", group->group_id, download_rate/1024, group->active_bitrate/1024);
+                                       fprintf(stdout, "Downloading from set %s at rate %d kbps but group bitrate is %d kbps\n", group->adaptation_set->id, download_rate/1024, group->active_bitrate/1024);
                                        group->nb_bw_check ++;
                                        if (group->nb_bw_check>2) {
-                                               fprintf(stdout, "Downloading from group %d at rate %d kbps but group bitrate is %d kbps - switching\n", group->group_id, download_rate/1024, group->active_bitrate/1024);
+                                               fprintf(stdout, "Downloading from group %s at rate %d kbps but group bitrate is %d kbps - switching\n", group->adaptation_set->id, download_rate/1024, group->active_bitrate/1024);
                                                group->force_switch_bandwidth = 1;
                                                gf_dm_sess_abort(group->segment_dnload);
                                        }
@@ -248,15 +284,6 @@ static Bool MPD_isM3U8_mime(const char * mime) {
     return 0;
 }
 
-static Bool MPD_segments_are_equals(GF_MPD_SegmentInfo * info1, GF_MPD_SegmentInfo * info2) {
-    assert( info1 );
-    assert( info2 );
-    return info1->byterange_end == info2->byterange_end &&
-           info1->byterange_start == info2->byterange_start &&
-           info1->use_byterange == info2->use_byterange &&
-           (info1->url == info2->url || !strcmp(info1->url, info2->url));
-}
-
 void MPD_NetIO(void *cbk, GF_NETIO_Parameter *param)
 {
     GF_Err e;
@@ -270,19 +297,17 @@ void MPD_NetIO(void *cbk, GF_NETIO_Parameter *param)
 static GF_Err MPD_UpdatePlaylist(GF_MPD_In *mpdin)
 {
     GF_Err e;
-    u32 i, j, rep_idx, group_idx;
+    u32 group_idx, rep_idx, i, j;
     Bool seg_found = 0;
     GF_DOMParser *mpd_parser;
     GF_MPD_Period *period, *new_period;
-    GF_MPD_Representation *rep, *new_rep;
-    GF_List *segs;
     const char *local_url;
     char mime[128];
     char * purl;
     Bool is_m3u8 = 0;
-    u32 oldUpdateTime = mpdin->mpd->min_update_time;
+       u32 oldUpdateTime = mpdin->mpd->minimum_update_period;
     /*reset update time - if any error occurs, we will no longer attempt to update the MPD*/
-    mpdin->mpd->min_update_time = 0;
+    mpdin->mpd->minimum_update_period = 0;
 
     if (!mpdin->mpd_dnload) {
         GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing downloader\n"));
@@ -314,7 +339,7 @@ static GF_Err MPD_UpdatePlaylist(GF_MPD_In *mpdin)
 
     /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */
     if (MPD_isM3U8_mime(mime) || strstr(purl, ".m3u8")) {
-        gf_m3u8_to_mpd(mpdin->service, local_url, purl, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments);
+        gf_m3u8_to_mpd(local_url, purl, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, mpdin->service, 0, M3U8_TO_MPD_USE_TEMPLATE);
     } else if (!MPD_is_MPD_mime(mime)) {
         GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] mime '%s' should be m3u8 or mpd\n", mime));
         gf_term_on_connect(mpdin->service, NULL, GF_BAD_PARAM);
@@ -338,10 +363,9 @@ static GF_Err MPD_UpdatePlaylist(GF_MPD_In *mpdin)
             if (! memcmp( signature, mpdin->lastMPDSignature, sizeof(mpdin->lastMPDSignature))) {
                 GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] MPD file did not change\n"));
                 mpdin->reload_count++;
-                mpdin->mpd->min_update_time = oldUpdateTime;
+                mpdin->mpd->minimum_update_period = oldUpdateTime;
             } else {
                 GF_MPD *new_mpd;
-                GF_MPD_SegmentInfo *info1;
                 mpdin->reload_count = 0;
                 memccpy(mpdin->lastMPDSignature, signature, sizeof(char), sizeof(mpdin->lastMPDSignature));
 
@@ -372,101 +396,121 @@ static GF_Err MPD_UpdatePlaylist(GF_MPD_In *mpdin)
                     return GF_NON_COMPLIANT_BITSTREAM;
                 }
 
-                if (gf_list_count(period->representations) != gf_list_count(new_period->representations)) {
-                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing representation\n"));
+                               if (gf_list_count(period->adaptation_sets) != gf_list_count(new_period->adaptation_sets)) {
+                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing AdaptationSet\n"));
                     gf_mpd_del(new_mpd);
                     return GF_NON_COMPLIANT_BITSTREAM;
                 }
 
                                for (group_idx=0; group_idx<gf_list_count(mpdin->groups); group_idx++) {
+                                       GF_MPD_AdaptationSet *set, *new_set;
                                        GF_MPD_Group *group = gf_list_get(mpdin->groups, group_idx);
                                        if (!group->selected) continue;
+                                       set = group->adaptation_set;
+                                       new_set = gf_list_get(new_period->adaptation_sets, group_idx);
 
-                                       rep = gf_list_get(period->representations, group->active_rep_index);
-                                       info1 = gf_list_get(rep->segments, group->download_segment_index - 1);
+                                       if (gf_list_count(new_set->representations) != gf_list_count(group->adaptation_set->representations)) {
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing representation in adaptation set\n"));
+                                               gf_mpd_del(new_mpd);
+                                               return GF_NON_COMPLIANT_BITSTREAM;
+                                       }
+                                       
+                                       /*get all representations in both periods*/
+                                       for (rep_idx = 0; rep_idx <gf_list_count(group->adaptation_set->representations); rep_idx++) {
+                                               GF_List *segments, *new_segments;
+                                               GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_idx);
+                                               GF_MPD_Representation *new_rep = gf_list_get(new_set->representations, rep_idx);
+
+                                               if (rep->segment_base || group->adaptation_set->segment_base || period->segment_base) {
+                                                       if (!new_rep->segment_base && !new_set->segment_base && !new_period->segment_base) {
+                                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment base as previous version\n"));
+                                                               gf_mpd_del(new_mpd);
+                                                               return GF_NON_COMPLIANT_BITSTREAM;
+                                                       }
+                                                       /*what else should we check ??*/
 
-                                       for (rep_idx = 0; rep_idx<gf_list_count(period->representations); rep_idx++) {
-                                               rep = gf_list_get(period->representations, rep_idx);
-                                               new_rep = gf_list_get(new_period->representations, rep_idx);
-                                               if (!new_rep) {
-                                                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing representation in period\n"));
-                                                       gf_mpd_del(new_mpd);
-                                                       return GF_NON_COMPLIANT_BITSTREAM;
+                                                       /*OK, this rep is fine*/
                                                }
-                                               /*merge init segment*/
-                                               if (new_rep->init_url) {
-                                                       seg_found = 0;
-
-                                                       if (!strcmp(new_rep->init_url, rep->init_url)) {
-                                                               seg_found = 1;
-                                                       } else {
-                                                               for (j=0; j<gf_list_count(rep->segments); j++) {
-                                                                       GF_MPD_SegmentInfo *seg = gf_list_get(rep->segments, j);
-                                                                       if (!strcmp(new_rep->init_url, seg->url)) {
-                                                                               seg_found = 1;
-                                                                               break;
-                                                                       }
-                                                               }
-                                                       }
-                                                       /*remove from new list and push to old one*/
-                                                       if (!seg_found) {
-                                                               GF_MPD_SegmentInfo *new_seg;
-                                                               GF_SAFEALLOC(new_seg, GF_MPD_SegmentInfo);
-                                                               new_seg->url = gf_strdup(new_rep->init_url);
-                                                               new_seg->use_byterange = new_rep->init_use_range;
-                                                               new_seg->byterange_start = new_rep->init_byterange_start;
-                                                               new_seg->byterange_end = new_rep->init_byterange_end;
-                                                               gf_list_add(rep->segments, new_seg);
-                                                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Representation #%d: Adding new segment from initialization segment %s\n", rep_idx+1, new_seg->url));
+
+                                               else if (rep->segment_template || group->adaptation_set->segment_template || period->segment_template) {
+                                                       if (!new_rep->segment_template && !new_set->segment_template && !new_period->segment_template) {
+                                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment template as previous version\n"));
+                                                               gf_mpd_del(new_mpd);
+                                                               return GF_NON_COMPLIANT_BITSTREAM;
                                                        }
+                                                       /*what else should we check ??*/
+
+                                                       /*OK, this rep is fine*/
                                                }
 
-                                               /*merge segment list*/
-                                               for (i=0; i<gf_list_count(new_rep->segments); i++) {
-                                                       GF_MPD_SegmentInfo *new_seg = gf_list_get(new_rep->segments, i);
-                                                       assert( new_seg );
-                                                       assert( new_seg->url);
-                                                       seg_found = 0;
-                                                       for (j=0; j<gf_list_count(rep->segments); j++) {
-                                                               GF_MPD_SegmentInfo *seg = gf_list_get(rep->segments, j);
-                                                               assert( seg );
-                                                               assert( seg->url);
-                                                               if (!strcmp(new_seg->url, seg->url)) {
-                                                                       seg_found = 1;
-                                                                       break;
+                                               else {
+                                                       /*we're using segment list*/
+                                                       assert(rep->segment_list || group->adaptation_set->segment_list || period->segment_list);
+
+                                                       if (!new_rep->segment_list && !new_set->segment_list && !new_period->segment_list) {
+                                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment list as previous version\n"));
+                                                               gf_mpd_del(new_mpd);
+                                                               return GF_NON_COMPLIANT_BITSTREAM;
+                                                       }
+                                                       /*what else should we check ??*/
+
+                                                       /*get the segment list*/
+                                                       segments = new_segments = NULL;
+                                                       if (period->segment_list && period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs;
+                                                       if (set->segment_list && set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs;
+                                                       if (rep->segment_list && rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs;
+
+                                                       if (new_period->segment_list && new_period->segment_list->segment_URLs) new_segments = new_period->segment_list->segment_URLs;
+                                                       if (new_set->segment_list && new_set->segment_list->segment_URLs) new_segments = new_set->segment_list->segment_URLs;
+                                                       if (new_rep->segment_list && new_rep->segment_list->segment_URLs) new_segments = new_rep->segment_list->segment_URLs;
+
+
+                                                       for (i=0; i<gf_list_count(new_segments); i++) {
+                                                               GF_MPD_SegmentURL *new_seg = gf_list_get(new_segments, i);
+                                                               Bool found = 0;
+                                                               for (j=0; j<gf_list_count(segments); j++) {
+                                                                       GF_MPD_SegmentURL *seg = gf_list_get(segments, j);
+                                                                       if (seg->media && new_seg->media && !strcmp(seg->media, new_seg->media)) {
+                                                                               found=1;
+                                                                               break;
+                                                                       }
+                                                                       if (seg->media_range && new_seg->media_range && (seg->media_range->start_range==new_seg->media_range->start_range) && (seg->media_range->end_range==new_seg->media_range->end_range) ) {
+                                                                               found=1;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                               /*this is a new segment, merge it: we remove from new list and push to old one, before doing a final swap
+                                                               this ensures that indexing in the segment_list is still correct after merging*/
+                                                               if (!found) {
+                                                                       gf_list_rem(new_segments, i);
+                                                                       i--;
+                                                                       gf_list_add(segments, new_seg);
+                                                                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Representation #%d: Adding new segment %s\n", rep_idx+1, new_seg->media));
                                                                }
                                                        }
-                                                       /*remove from new list and push to old one*/
-                                                       if (!seg_found) {
-                                                               gf_list_rem(new_rep->segments, i);
-                                                               gf_list_add(rep->segments, new_seg);
-                                                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Representation #%d: Adding new segment %s\n", rep_idx+1, new_seg->url));
-                                                               i--;
+
+                                                       /*what else should we check ?*/
+
+                                                       /*swap segment list content*/
+                                                       gf_list_swap(new_segments, segments);
+
+                                                       /*current representation is the active one in the group - update the number of segments*/
+                                                       if (group->active_rep_index==rep_idx) {
+                                                               group->nb_segments_in_rep = gf_list_count(new_segments);
                                                        }
                                                }
-                                               /*swap lists*/
-                                               {
-                                                       GF_MPD_SegmentInfo *info2;
-                                                       segs = new_rep->segments;
-                                                       new_rep->segments = rep->segments;
-                                                       new_rep->disabled = rep->disabled;
-                                                       if (!new_rep->mime) {
-                                                               new_rep->mime = rep->mime;
-                                                               rep->mime = NULL;
-                                                       }
-                                                       rep->segments = segs;
-                                                       info2 = gf_list_get(rep->segments, group->download_segment_index);
+
+                                               /*copy over a few things from former rep*/
+                                               new_rep->disabled = rep->disabled;
+                                               if (!new_rep->mime_type) {
+                                                       new_rep->mime_type = rep->mime_type;
+                                                       rep->mime_type = NULL;
                                                }
                                        }
                                        /*update group/period to new period*/
+                                       j = gf_list_find(group->period->adaptation_sets, group->adaptation_set);
+                                       group->adaptation_set = gf_list_get(new_period->adaptation_sets, j);
                                        group->period = new_period;
-
-                                       /*and rebuild representations for this group*/
-                                       gf_list_reset(group->representations);
-                                       for (i=0; i<gf_list_count(new_period->representations); i++) {
-                                           GF_MPD_Representation *rep = gf_list_get(new_period->representations, i);
-                                               if (rep->groupID==group->group_id) gf_list_add(group->representations, rep);
-                                       }
                                }
                 /*swap representations - we don't need to update download_segment_index as it still points to the right entry in the merged list*/
                 if (mpdin->mpd)
@@ -484,17 +528,43 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
 {
        u32 i;
        GF_MPD_Group *group = NULL;
+       GF_MPD_In *mpdin = (GF_MPD_In *) ifce->proxy_udta;
     if (!param || !ifce || !ifce->proxy_udta) return GF_BAD_PARAM;
 
+       if (param->command_type==GF_NET_SERVICE_QUERY_INIT_RANGE) {
+               param->url_query.next_url = NULL;
+               param->url_query.start_range = 0;
+               param->url_query.end_range = 0;
+               
+               mpdin->in_seek = 0;
+
+               for (i=0; i<gf_list_count(mpdin->groups); i++) {
+                       group = gf_list_get(mpdin->groups, i);
+                       if (group->selected && (group->input_module == ifce)) break;
+                       group = NULL;
+               }
+               
+               if (!group) return GF_SERVICE_ERROR;
+               param->url_query.start_range = group->local_url_start_range;
+               param->url_query.end_range = group->local_url_end_range;
+               
+               return GF_OK;
+       }
        if (param->command_type==GF_NET_SERVICE_QUERY_NEXT) {
         u32 timer = gf_sys_clock();
-        GF_MPD_In *mpdin = (GF_MPD_In *) ifce->proxy_udta;
         GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Query Next request from terminal\n"));
         gf_mx_p(mpdin->dl_mutex);
 
+
+               param->url_query.discontinuity_type = 0;
+               if (mpdin->in_seek) {
+                       mpdin->in_seek = 0;
+                       param->url_query.discontinuity_type = 2;
+               }
+
                for (i=0; i<gf_list_count(mpdin->groups); i++) {
                        group = gf_list_get(mpdin->groups, i);
-                       if (group->selected && (group->service == ifce)) break;
+                       if (group->selected && (group->input_module == ifce)) break;
                        group = NULL;
                }
                
@@ -502,17 +572,31 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
                gf_mx_v(mpdin->dl_mutex);
                        return GF_SERVICE_ERROR;
                }
+               group->force_segment_switch = 0;
 
         /* Wait until no file is scheduled to be downloaded */
-        while (mpdin->mpd_is_running && group->nb_cached<2) {
+        while (mpdin->mpd_is_running && group->nb_cached_segments<2) {
             gf_mx_v(mpdin->dl_mutex);
                        if (group->done) {
+                               if (!mpdin->request_period_switch && (mpdin->active_period_index<gf_list_count(mpdin->mpd->periods))) {
+                                       GF_NetworkCommand com;
+                                       memset(&com, 0, sizeof(GF_NetworkCommand));
+                                       com.command_type = GF_NET_BUFFER_QUERY;
+                                       while (mpdin->request_period_switch != 1) {
+                                               gf_term_on_command(mpdin->service, &com, GF_OK);
+                                               if (!com.buffer.occupancy) {
+                                                       mpdin->request_period_switch = 1;
+                                                       break;
+                                               }
+                                               gf_sleep(20);
+                                       }
+                               }
                                return GF_EOS;
                        }
             gf_sleep(16);
             gf_mx_p(mpdin->dl_mutex);
         }
-        if (group->nb_cached<2) {
+        if (group->nb_cached_segments<2) {
             GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] No more file in cache, EOS\n"));
             gf_mx_v(mpdin->dl_mutex);
             return GF_EOS;
@@ -522,7 +606,7 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
         if (group->cached[0].cache) {
             if (group->urlToDeleteNext) {
                                if (!group->local_files && !mpdin->keep_files)
-                               gf_dm_delete_cached_file_entry_session(mpdin->mpd_dnload, group->urlToDeleteNext);
+                                       gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext);
 
                                gf_free( group->urlToDeleteNext);
                 group->urlToDeleteNext = NULL;
@@ -535,17 +619,23 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
             group->cached[0].url = NULL;
             group->cached[0].cache = NULL;
         }
-        memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached-1));
-        memset(&(group->cached[group->nb_cached-1]), 0, sizeof(segment_cache_entry));
-        group->nb_cached--;
+        memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached_segments-1));
+        memset(&(group->cached[group->nb_cached_segments-1]), 0, sizeof(segment_cache_entry));
+        group->nb_cached_segments--;
         param->url_query.next_url = group->cached[0].cache;
+               param->url_query.start_range = group->cached[0].start_range;
+               param->url_query.end_range = group->cached[0].end_range;
         gf_mx_v(mpdin->dl_mutex);
         {
             u32 timer2 = gf_sys_clock() - timer ;
             if (timer2 > 1000) {
-                GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[MPD_IN] We were stuck waiting for download to end during too much time : %u ms !\n", timer2));
+                GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] We were stuck waiting for download to end during too much time : %u ms !\n", timer2));
             }
-            GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching segment playback to \n\tURL: %s in %u ms\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[0].url, timer2, group->cached[0].cache, group->nb_cached, group->max_cached));
+                       if (group->cached[0].end_range) {
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching segment playback to \n\tURL: %s in %u ms\n\tMedia Range: "LLD"-"LLD"\n\tElements in cache: %u/%u\n", group->cached[0].url, timer2, group->cached[0].start_range, group->cached[0].end_range, group->nb_cached_segments, group->max_cached_segments));
+                       } else {
+                   GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching segment playback to \n\tURL: %s in %u ms\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[0].url, timer2, group->cached[0].cache, group->nb_cached_segments, group->max_cached_segments));
+                       }
         }
     } else {
         GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Client Query request (%d) from terminal\n", param->command_type));
@@ -563,10 +653,10 @@ static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const
                if (sPlug) sPlug = strrchr(sPlug, '"');
                if (sPlug) {
                        sPlug += 2;
-                       group->service = (GF_InputService *) gf_modules_load_interface_by_name(mpdin->service->term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE);
-                       if (group->service) {
-                               group->service->proxy_udta = mpdin;
-                               group->service->query_proxy = MPD_ClientQuery;
+                       group->input_module = (GF_InputService *) gf_modules_load_interface_by_name(mpdin->service->term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE);
+                       if (group->input_module) {
+                               group->input_module->proxy_udta = mpdin;
+                               group->input_module->query_proxy = MPD_ClientQuery;
                                return GF_OK;
                        }
                }
@@ -577,9 +667,9 @@ static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const
                        if (!ifce) continue;
                        
                        if (ifce->CanHandleURL && ifce->CanHandleURL(ifce, init_segment_name)) {
-                               group->service = ifce;
-                               group->service->proxy_udta = mpdin;
-                               group->service->query_proxy = MPD_ClientQuery;
+                               group->input_module = ifce;
+                               group->input_module->proxy_udta = mpdin;
+                               group->input_module->query_proxy = MPD_ClientQuery;
                                return GF_OK;
                        }
                        gf_modules_close_interface((GF_BaseInterface *) ifce);
@@ -599,9 +689,11 @@ static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const
  */
 GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession **sess, const char *url, gf_dm_user_io user_io,  void *usr_cbk, u64 start_range, u64 end_range, Bool persistent)
 {
+       Bool had_sess = 0;
     GF_Err e;
 
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Downloading %s...\n", url));
+
        if (! *sess) {
                u32 flags = GF_NETIO_SESSION_NOT_THREADED;
                if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT; 
@@ -612,6 +704,7 @@ GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession **s
                        return GF_OUT_OF_MEM;
                }
        } else {
+               had_sess = 1;
                e = gf_dm_sess_setup_from_url(*sess, url);
                if (e) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot resetup session for url %s: %s\n", url, gf_error_to_string(e) ));
@@ -622,6 +715,13 @@ GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession **s
        if (end_range) {
                e = gf_dm_sess_set_range(*sess, start_range, end_range);
                if (e) {
+                       if (had_sess) {
+                               gf_term_download_del(*sess);
+                               *sess = NULL;
+                               return MPD_downloadWithRetry(service, sess, url, user_io, usr_cbk, start_range, end_range, persistent);
+                       }
+
+
                        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot setup byte-range download for %s: %s\n", url, gf_error_to_string(e) ));
                        return e;
                }
@@ -655,6 +755,106 @@ GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession **s
     }
 }
 
+static void MPD_SetGroupRepresentation(GF_MPD_Group *group, GF_MPD_Representation *rep)
+{
+       u64 duration = 0;
+       u64 mediaDuration = 0;
+#ifndef GPAC_DISABLE_LOG
+       u32 width=0, height=0, samplerate=0;
+       GF_MPD_Fractional *framerate=NULL;
+#endif
+       u32 timescale = 1;
+       GF_MPD_AdaptationSet *set;
+       GF_MPD_Period *period;
+       u32 i = gf_list_find(group->adaptation_set->representations, rep);
+       assert((s32) i >= 0);
+
+       group->active_rep_index = i;
+       group->active_bitrate = rep->bandwidth;
+       group->nb_segments_in_rep = 1;
+
+       set = group->adaptation_set;
+       period = group->period;
+
+#ifndef GPAC_DISABLE_LOG
+
+#define GET_REP_ATTR(_a)       _a = rep->_a; if (!_a) _a = set->_a;
+
+       GET_REP_ATTR(width);
+       GET_REP_ATTR(height);
+       GET_REP_ATTR(samplerate);
+       GET_REP_ATTR(framerate);
+
+       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPDIn] Switched to representation bandwidth %d kbps\n", rep->bandwidth/1024));
+       if (group->max_bitrate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tmax download bandwidth: %d kbps\n", group->max_bitrate/1024));
+       if (width&&height) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tWidth %d Height %d", width, height));
+               if (framerate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("framerate %d/%d", framerate->num, framerate->den));
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\n"));
+       } else if (samplerate) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tsamplerate %d\n", samplerate));
+       }
+#endif
+
+       /*single segment*/
+       if (rep->segment_base || set->segment_base || period->segment_base) {
+               return;
+       }
+       if (rep->segment_list || set->segment_list || period->segment_list) {
+               GF_List *segments = NULL;
+               if (period->segment_list) {
+                       if (period->segment_list->duration) duration = period->segment_list->duration;
+                       if (period->segment_list->timescale) timescale = period->segment_list->timescale;
+                       if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs;
+               }
+               if (set->segment_list) {
+                       if (set->segment_list->duration) duration = set->segment_list->duration;
+                       if (set->segment_list->timescale) timescale = set->segment_list->timescale;
+                       if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs;
+               }
+               if (rep->segment_list) {
+                       if (rep->segment_list->duration) duration = rep->segment_list->duration;
+                       if (rep->segment_list->timescale) timescale = rep->segment_list->timescale;
+                       if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs;
+               }
+               if (segments) 
+                       group->nb_segments_in_rep = gf_list_count(segments);
+
+               if (!timescale) timescale=1;
+               group->segment_duration = (Double) duration;
+               group->segment_duration /= timescale;
+               return;
+       }
+
+       if (period->segment_template) {
+               if (period->segment_template->duration) duration = period->segment_template->duration;
+               if (period->segment_template->timescale) timescale = period->segment_template->timescale;
+       }
+       if (set->segment_template) {
+               if (set->segment_template->duration) duration = set->segment_template->duration;
+               if (set->segment_template->timescale) timescale = set->segment_template->timescale;
+       }
+       if (rep->segment_template) {
+               if (rep->segment_template->duration) duration = rep->segment_template->duration;
+               if (rep->segment_template->timescale) timescale = rep->segment_template->timescale;
+       }
+       if (!timescale) timescale=1;
+       group->segment_duration = (Double) duration;
+       group->segment_duration /= timescale;
+       mediaDuration = period->duration;
+       if (!mediaDuration) mediaDuration = group->mpd_in->mpd->media_presentation_duration;
+       if (mediaDuration && duration) {
+               Double nb_seg = (Double) mediaDuration;
+               /*duration is given in ms*/
+               nb_seg /= 1000;
+               nb_seg *= timescale;
+               nb_seg /= duration;
+               group->nb_segments_in_rep = (u32) ceil(nb_seg);
+       } else {
+               group->nb_segments_in_rep = 0;
+       }
+}
+
 static void MPD_SwitchGroupRepresentation(GF_MPD_In *mpd, GF_MPD_Group *group)
 {
        u32 i, bandwidth, min_bandwidth;
@@ -666,24 +866,32 @@ static void MPD_SwitchGroupRepresentation(GF_MPD_In *mpd, GF_MPD_Group *group)
 
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPDIn] Checking representations between %d and %d kbps\n", group->min_bitrate/1024, group->max_bitrate/1024));
 
-       for (i=0; i<gf_list_count(group->representations); i++) {
-               GF_MPD_Representation *rep = gf_list_get(group->representations, i);
-               if (rep->disabled) continue;
-               if ((rep->bandwidth > bandwidth) && (rep->bandwidth < group->max_bitrate )) {
-                       rep_sel = rep;
-                       bandwidth = rep->bandwidth;
-               }
-               if (rep->bandwidth < min_bandwidth) {
-                       min_rep_sel = rep;
-                       min_bandwidth = rep->bandwidth;
+       if (group->force_representation_idx_plus_one) {
+               rep_sel = gf_list_get(group->adaptation_set->representations, group->force_representation_idx_plus_one - 1);
+               group->force_representation_idx_plus_one = 0;
+       } 
+
+       if (!rep_sel) {
+               for (i=0; i<gf_list_count(group->adaptation_set->representations); i++) {
+                       GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, i);
+                       if (rep->disabled) continue;
+                       if ((rep->bandwidth > bandwidth) && (rep->bandwidth < group->max_bitrate )) {
+                               rep_sel = rep;
+                               bandwidth = rep->bandwidth;
+                       }
+                       if (rep->bandwidth < min_bandwidth) {
+                               min_rep_sel = rep;
+                               min_bandwidth = rep->bandwidth;
+                       }
                }
        }
+
        if (!rep_sel) {
                rep_sel = min_rep_sel;
                min_bandwidth_selected = 1;
        }
        assert(rep_sel);
-       i = gf_list_find(group->period->representations, rep_sel);
+       i = gf_list_find(group->adaptation_set->representations, rep_sel);
 
        assert((s32) i >= 0);
 
@@ -693,75 +901,394 @@ static void MPD_SwitchGroupRepresentation(GF_MPD_In *mpd, GF_MPD_Group *group)
 
        if (i != group->active_rep_index) {
                if (min_bandwidth_selected) {
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPDIn] No representation found with bandwidth below %d kbps - using representation @ %d kbps\n", group->max_bitrate/1024, rep_sel->bandwidth/1024));
-               } else {
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPDIn] Switching to representation bandwidth %d kbps for download bandwidth %d kbps\n", rep_sel->bandwidth/1024, group->max_bitrate/1024));
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[MPDIn] No representation found with bandwidth below %d kbps - using representation @ %d kbps\n", group->max_bitrate/1024, rep_sel->bandwidth/1024));
+               }
+               MPD_SetGroupRepresentation(group, rep_sel);
+       }
+}
+
+
+u64 MPD_ResolveDuration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, u32 item_index)
+{
+       GF_MPD_SegmentTimeline *segment_timeline;
+       GF_MPD_MultipleSegmentBase *mbase_rep, *mbase_set, *mbase_period;
+       /*single media segment - duration is not known unless indicated in period*/
+       if (rep->segment_base || set->segment_base || period->segment_base) {
+               return period ? period->duration : 0;
+       }
+       /*we have a segment template list or template*/
+       mbase_rep = rep->segment_list ? (GF_MPD_MultipleSegmentBase *) rep->segment_list : (GF_MPD_MultipleSegmentBase *) rep->segment_template;
+       mbase_set = set->segment_list ? (GF_MPD_MultipleSegmentBase *)set->segment_list : (GF_MPD_MultipleSegmentBase *)set->segment_template;
+       mbase_period = period->segment_list ? (GF_MPD_MultipleSegmentBase *)period->segment_list : (GF_MPD_MultipleSegmentBase *)period->segment_template;
+
+       segment_timeline = NULL;
+       if (mbase_period) segment_timeline =  mbase_period->segment_timeline;
+       if (mbase_set) segment_timeline =  mbase_set->segment_timeline;
+       if (mbase_rep) segment_timeline =  mbase_rep->segment_timeline;
+       
+       if (segment_timeline) {
+               /*not supported yet*/
+               assert(0);
+               return 0;
+       }
+       if (mbase_rep && mbase_rep->duration) return mbase_rep->duration;
+       if (mbase_set && mbase_set->duration) return mbase_set->duration;
+       if (mbase_period && mbase_period->duration) return mbase_period->duration;
+       return 0;
+}
+
+typedef enum
+{
+       GF_MPD_RESOLVE_URL_MEDIA,
+       GF_MPD_RESOLVE_URL_INIT,
+       GF_MPD_RESOLVE_URL_INDEX,
+} GF_MPDURLResolveType;
+
+
+GF_Err MPD_ResolveURL(GF_MPD *mpd, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, char *mpd_url, GF_MPDURLResolveType resolve_type, u32 item_index, char **out_url, u64 *out_range_start, u64 *out_range_end)
+{
+       GF_MPD_BaseURL *url_child;
+       u32 start_number = 1;
+       char *url;
+       char *url_to_solve, *solved_template, *first_sep, *media_url;
+       char *init_template, *index_template;
+
+       *out_range_start = *out_range_end = 0;
+       *out_url = NULL;
+
+       /*resolve base URLs from document base (download location) to representation (media)*/
+       url = gf_strdup(mpd_url);
+       url_child = gf_list_get(mpd->base_URLs, 0);
+       if (url_child) {
+               char *t_url = gf_url_concatenate(url, url_child->URL);
+               gf_free(url);
+               url = t_url;
+       }
+
+       url_child = gf_list_get(period->base_URLs, 0);
+       if (url_child) {
+               char *t_url = gf_url_concatenate(url, url_child->URL);
+               gf_free(url);
+               url = t_url;
+       }
+
+       url_child = gf_list_get(set->base_URLs, 0);
+       if (url_child) {
+               char *t_url = gf_url_concatenate(url, url_child->URL);
+               gf_free(url);
+               url = t_url;
+       }
+
+       url_child = gf_list_get(rep->base_URLs, 0);
+       if (url_child) {
+               char *t_url = gf_url_concatenate(url, url_child->URL);
+               gf_free(url);
+               url = t_url;
+       }
+
+       /*single URL*/
+       if (rep->segment_base || set->segment_base || period->segment_base) {
+               GF_MPD_URL *res_url;
+               if (item_index>0) return GF_EOS;
+               switch (resolve_type) {
+               case GF_MPD_RESOLVE_URL_MEDIA:
+                       if (!url) return GF_NON_COMPLIANT_BITSTREAM;
+                       *out_url = url;
+                       return GF_OK;
+               case GF_MPD_RESOLVE_URL_INIT:
+               case GF_MPD_RESOLVE_URL_INDEX:
+                       res_url = NULL;
+                       if (resolve_type == GF_MPD_RESOLVE_URL_INDEX) {
+                               if (period->segment_base) res_url = period->segment_base->representation_index;
+                               if (set->segment_base) res_url = set->segment_base->representation_index;
+                               if (rep->segment_base) res_url = rep->segment_base->representation_index;
+                       } else {
+                               if (period->segment_base) res_url = period->segment_base->initialization_segment;
+                               if (set->segment_base) res_url = set->segment_base->initialization_segment;
+                               if (rep->segment_base) res_url = rep->segment_base->initialization_segment;
+                       }
+                       /*no initialization segment / index*/
+                       if (!res_url) {
+                               gf_free(url);
+                               return GF_OK;
+                       }
+                       if (res_url->sourceURL) {
+                               *out_url = gf_url_concatenate(url, res_url->sourceURL);
+                               gf_free(url);
+                       } else {
+                               *out_url = url;
+                       }
+                       if (res_url->byte_range) {
+                               *out_range_start = res_url->byte_range->start_range;
+                               *out_range_end = res_url->byte_range->end_range;
+                       }
+                       return GF_OK;
+               default:
+                       break;
+               }
+               gf_free(url);
+               return GF_BAD_PARAM;
+       }
+
+       /*segmentList*/
+       if (rep->segment_list || set->segment_list || period->segment_list) {   
+               GF_MPD_URL *init_url, *index_url;
+               GF_MPD_SegmentURL *segment;
+               GF_List *segments = NULL;
+               u32 segment_count;
+
+               init_url = index_url = NULL;
+
+               /*apply inheritance of attributes, lowest level having preceedence*/
+               if (period->segment_list) {
+                       if (period->segment_list->initialization_segment) init_url = period->segment_list->initialization_segment;
+                       if (period->segment_list->representation_index) index_url = period->segment_list->representation_index;
+                       if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs;
+                       if (period->segment_list->start_number != (u32) -1) start_number = period->segment_list->start_number;
+               }
+               if (set->segment_list) {
+                       if (set->segment_list->initialization_segment) init_url = set->segment_list->initialization_segment;
+                       if (set->segment_list->representation_index) index_url = set->segment_list->representation_index;
+                       if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs;
+                       if (set->segment_list->start_number != (u32) -1) start_number = set->segment_list->start_number;
+               }
+               if (rep->segment_list) {
+                       if (rep->segment_list->initialization_segment) init_url = rep->segment_list->initialization_segment;
+                       if (rep->segment_list->representation_index) index_url = rep->segment_list->representation_index;
+                       if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs;
+                       if (rep->segment_list->start_number != (u32) -1) start_number = rep->segment_list->start_number;
+               }
+
+
+               segment_count = gf_list_count(segments);
+
+               switch (resolve_type) {
+               case GF_MPD_RESOLVE_URL_INIT:
+
+                       if (init_url) {
+                               if (init_url->sourceURL) {
+                                       *out_url = gf_url_concatenate(url, init_url->sourceURL);
+                                       gf_free(url);
+                               } else {
+                                       *out_url = url;
+                               }
+                               if (init_url->byte_range) {
+                                       *out_range_start = init_url->byte_range->start_range;
+                                       *out_range_end = init_url->byte_range->end_range;
+                               }
+                       } else {
+                               gf_free(url);
+                       }
+                       return GF_OK;
+               case GF_MPD_RESOLVE_URL_MEDIA:
+                       if (!url) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Media URL is not set in segment list\n"));
+                               return GF_SERVICE_ERROR;
+                       }
+                       if (item_index >= segment_count) {
+                               gf_free(url);
+                               return GF_EOS;
+                       }
+                       *out_url = url;
+                       segment = gf_list_get(segments, item_index);
+                       if (segment->media) {
+                               *out_url = gf_url_concatenate(url, segment->media);
+                               gf_free(url);
+                       }
+                       if (segment->media_range) {
+                               *out_range_start = segment->media_range->start_range;
+                               *out_range_end = segment->media_range->end_range;
+                       }
+                       return GF_OK;
+               case GF_MPD_RESOLVE_URL_INDEX:
+                       if (item_index >= segment_count) {
+                               gf_free(url);
+                               return GF_EOS;
+                       }
+                       *out_url = url;
+                       segment = gf_list_get(segments, item_index);
+                       if (segment->index) {
+                               *out_url = gf_url_concatenate(url, segment->index);
+                               gf_free(url);
+                       }
+                       if (segment->index_range) {
+                               *out_range_start = segment->index_range->start_range;
+                               *out_range_end = segment->index_range->end_range;
+                       }
+                       return GF_OK;
+               default:
+                       break;
+               }
+               gf_free(url);
+               return GF_BAD_PARAM;
+       }
+
+       /*segmentTemplate*/
+       init_template = index_template = NULL;
+
+       /*apply inheritance of attributes, lowest level having preceedence*/
+       if (period->segment_template) {
+               if (period->segment_template->initialization) init_template = period->segment_template->initialization;
+               if (period->segment_template->index) index_template = period->segment_template->index;
+               if (period->segment_template->media) media_url = period->segment_template->media;
+               if (period->segment_template->start_number != (u32) -1) start_number = period->segment_template->start_number;
+       }
+       if (set->segment_template) {
+               if (set->segment_template->initialization) init_template = set->segment_template->initialization;
+               if (set->segment_template->index) index_template = set->segment_template->index;
+               if (set->segment_template->media) media_url = set->segment_template->media;
+               if (set->segment_template->start_number != (u32) -1) start_number = set->segment_template->start_number;
+       }
+       if (rep->segment_template) {
+               if (rep->segment_template->initialization) init_template = rep->segment_template->initialization;
+               if (rep->segment_template->index) index_template = rep->segment_template->index;
+               if (rep->segment_template->media) media_url = rep->segment_template->media;
+               if (rep->segment_template->start_number != (u32) -1) start_number = rep->segment_template->start_number;
+       }
+       url_to_solve = NULL;
+       switch (resolve_type) {
+       case GF_MPD_RESOLVE_URL_INIT:
+               url_to_solve = init_template;
+               break;
+       case GF_MPD_RESOLVE_URL_MEDIA:
+               url_to_solve = media_url;
+               break;
+       case GF_MPD_RESOLVE_URL_INDEX:
+               url_to_solve = index_template;
+               break;
+       default:
+               gf_free(url);
+               return GF_BAD_PARAM;
+       }
+       if (!url_to_solve) {
+               gf_free(url);
+               return GF_OK;
+       }
+       /*let's solve the template*/
+       solved_template = gf_malloc(sizeof(char)*strlen(url_to_solve)*2);
+       solved_template[0] = 0;
+       strcpy(solved_template, url_to_solve);
+       first_sep = strchr(solved_template, '$');
+       if (first_sep) first_sep[0] = 0;
+
+       first_sep = strchr(url_to_solve, '$');
+       while (first_sep) {
+               char szFormat[100];
+               char *format_tag;
+               char *second_sep = strchr(first_sep+1, '$');
+               if (!second_sep) {
+                       gf_free(url);
+                       gf_free(solved_template);
+                       return GF_NON_COMPLIANT_BITSTREAM;
+               }
+               second_sep[0] = 0;
+               format_tag = strchr(first_sep+1, '%');
+               if (format_tag) format_tag[0] = 0;
+               /* identifier is $$ -> replace by $*/
+               if (!strlen(first_sep+1)) {
+                       strcat(solved_template, "$");
+               }
+               else if (!strcmp(first_sep+1, "RepresentationID")) {
+                       strcat(solved_template, rep->id);
+               }
+               else if (!strcmp(first_sep+1, "Number")) {
+                       if (format_tag) {
+                               char szPrintFormat[20];
+                               strcpy(szPrintFormat, "%");
+                               strcat(szPrintFormat, format_tag+1);
+                               strcat(szPrintFormat, "d");
+                               sprintf(szFormat, szPrintFormat, start_number + item_index);
+                       } else {
+                               sprintf(szFormat, "%d", start_number + item_index);
+                       }
+                       strcat(solved_template, szFormat);
                }
-               group->active_rep_index = i;
-               group->active_bitrate = rep_sel->bandwidth;
+               else if (!strcmp(first_sep+1, "Bandwidth")) {
+                       if (format_tag) {
+                               char szPrintFormat[20];
+                               strcpy(szPrintFormat, "%");
+                               strcat(szPrintFormat, format_tag+1);
+                               strcat(szPrintFormat, "d");
+                               sprintf(szFormat, format_tag+1, rep->bandwidth);
+                       } else {
+                               sprintf(szFormat, "%d", rep->bandwidth);
+                       }
+                       strcat(solved_template, szFormat);
+               }
+               else if (!strcmp(first_sep+1, "Time")) {
+                       assert(0);
+                       /*uses segment timeline, not supported yet*/
+               }
+               if (format_tag) format_tag[0] = '%';
+               second_sep[0] = '$';
+               /*look for next keyword - copy over remaining text if any*/
+               first_sep = strchr(second_sep+1, '$');
+               if (first_sep) first_sep[0] = 0;
+               if (strlen(second_sep+1)) 
+                       strcat(solved_template, second_sep+1);
+               if (first_sep) first_sep[0] = '$';
        }
+       *out_url = gf_url_concatenate(url, solved_template);
+       gf_free(url);
+       gf_free(solved_template);
+       return GF_OK;
 }
 
 static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group)
 {
     GF_Err e;
     char *base_init_url;
-    char * url_to_dl;
     GF_MPD_Representation *rep;
        u64 start_range, end_range;
     /* This variable is 0 if there is a initURL, the index of first segment downloaded otherwise */
-    u32 firstSegment = 0;
+    u32 nb_segment_read = 0;
     if (!mpdin || !group)
         return GF_BAD_PARAM;
     gf_mx_p(mpdin->dl_mutex);
     
-       assert( group->period && group->period->representations );
-    rep = gf_list_get(group->period->representations, group->active_rep_index);
+       assert( group->adaptation_set && group->adaptation_set->representations );
+    rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index);
     if (!rep) {
         gf_mx_v(mpdin->dl_mutex);
         GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to find any representation, aborting.\n"));
         return GF_IO_ERR;
     }
        start_range = end_range = 0;
-    if (!rep->init_url) {
-        GF_MPD_SegmentInfo * seg = gf_list_get(rep->segments, 0);
-        /* No init URL provided, we have to download the first segment then */
-        if (!seg->url) {
-            mpdin->mpd_stop_request = 1;
-            gf_mx_v(mpdin->dl_mutex);
-            return GF_BAD_PARAM;
-        }
-        firstSegment = 1;
-        url_to_dl = seg->url;
-               if (seg->use_byterange) {
-                       start_range = seg->byterange_start;
-                       end_range = seg->byterange_end;
-               }
-    } else {
-        url_to_dl = rep->init_url;
-               if (rep->init_use_range) {
-                       start_range = rep->init_byterange_start;
-                       end_range = rep->init_byterange_end;
-               }
-    }
-    if (rep->default_base_url) {
-        base_init_url = gf_url_concatenate(rep->default_base_url, url_to_dl);
-    } else {
-        base_init_url = gf_strdup(url_to_dl);
-    }
+       
+       e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_INIT, 0, &base_init_url, &start_range, &end_range);
+       if (e) {
+        gf_mx_v(mpdin->dl_mutex);
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to resolve initialization URL: %s\n", gf_error_to_string(e) ));
+        return e;
+       }
 
+       /*no error and no init segment, go for media segment*/
+       if (!base_init_url) {
+               e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index, &base_init_url, &start_range, &end_range);
+               if (e) {
+                       gf_mx_v(mpdin->dl_mutex);
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to resolve media URL: %s\n", gf_error_to_string(e) ));
+                       return e;
+               }
+               nb_segment_read = 1;
+       }
 
        if (!strstr(base_init_url, "://") || !strnicmp(base_init_url, "file://", 7)) {
-        assert(!group->nb_cached);
+        assert(!group->nb_cached_segments);
         group->cached[0].cache = gf_strdup(base_init_url);
         group->cached[0].url = gf_strdup(base_init_url);
-        group->nb_cached = 1;
+        group->nb_cached_segments = 1;
                /*do not erase local files*/
                group->local_files = 1;
-        group->download_segment_index = firstSegment;
+               group->download_segment_index += nb_segment_read;
         group->segment_local_url = group->cached[0].cache;
+               group->local_url_start_range = start_range;
+               group->local_url_end_range = end_range;
         GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Setup initialization segment %s \n", group->segment_local_url));
-               if (!group->service) e = MPD_LoadMediaService(mpdin, group, rep->mime, group->segment_local_url);
+               if (!group->input_module) {
+                       const char *mime_type = MPD_GetMimeType(NULL, rep, group->adaptation_set);
+                       e = MPD_LoadMediaService(mpdin, group, mime_type, group->segment_local_url);
+               }
         gf_mx_v(mpdin->dl_mutex);
         gf_free(base_init_url);
                return GF_OK;
@@ -782,19 +1309,16 @@ static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group)
     if (e == GF_URL_ERROR && !base_init_url) { /* We have a 404 and started with segments */
         /* It is possible that the first segment has been deleted while we made the first request...
          * so we try with the next segment on some M3U8 servers */
-        GF_MPD_SegmentInfo * seg = gf_list_get(rep->segments, 1);
-        gf_free(base_init_url);
-        if (!seg || !seg->url) {
+
+               gf_free(base_init_url);
+
+               e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index + 1, &base_init_url, &start_range, &end_range);
+               if (!e) {
             gf_mx_v(mpdin->dl_mutex);
             return e;
         }
-        if (rep->default_base_url) {
-            base_init_url = gf_url_concatenate(rep->default_base_url, seg->url);
-        } else {
-            base_init_url = gf_strdup(seg->url);
-        }
         GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("Download of first segment failed... retrying with second one : %s\n", base_init_url));
-        firstSegment = 2;
+        nb_segment_read = 2;
                /*use persistent connection for segment downloads*/
         e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), base_init_url, MPD_NetIO_Segment, group, 0, 0, 1);
     } /* end of 404 */
@@ -806,42 +1330,52 @@ static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group)
         return e;
     } else {
         char mime[128];
-        u32 count = gf_list_count(rep->segments) + 1;
-        if (count < group->max_cached) {
+               const char *mime_type;
+        u32 count = group->nb_segments_in_rep + 1;
+        if (count < group->max_cached_segments) {
             if (count < 1) {
                 GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] 0 representations, aborting\n"));
                 gf_free(base_init_url);
                        gf_mx_v(mpdin->dl_mutex);
                 return GF_BAD_PARAM;
             }
-            GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Resizing to %u max_cached elements instead of %u.\n", count, group->max_cached));
+            GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Resizing to %u max_cached_segments elements instead of %u.\n", count, group->max_cached_segments));
             /* OK, we have a problem, it may ends download */
-            group->max_cached = count;
+            group->max_cached_segments = count;
         }
         e = gf_dm_sess_process(group->segment_dnload);
         /* Mime-Type check */
                strncpy(mime, gf_dm_sess_mime_type(group->segment_dnload), sizeof(mime));
         strlwr(mime);
-        if (mime && group->service == NULL) {
+        if (mime && group->input_module == NULL) {
             GF_Err e;
             GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Searching an input plugin for mime type : %s...\n", mime));
             gf_free( mpdin->mimeTypeForM3U8Segments);
             mpdin->mimeTypeForM3U8Segments = gf_strdup( mime );
-            gf_free( rep->mime);
-            rep->mime = gf_strdup( mime );
+                       if (rep->mime_type) gf_free( rep->mime_type);
+            rep->mime_type = gf_strdup( mime );
             e = MPD_LoadMediaService(mpdin, group, mime, base_init_url);
                        if (e != GF_OK) {
                        gf_mx_v(mpdin->dl_mutex);
                 return e;
                        }
         }
-        if (!mime || (stricmp(mime, rep->mime))) {
-            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Mime '%s' is not correct for '%s', it should be '%s'\n", mime, base_init_url, rep->mime));
-            mpdin->mpd_stop_request = 0;
-            gf_mx_v(mpdin->dl_mutex);
-            gf_free(base_init_url);
-            base_init_url = NULL;
-            return GF_BAD_PARAM;
+               mime_type = MPD_GetMimeType(NULL, rep, group->adaptation_set);
+        if (!mime || (stricmp(mime, mime_type))) {
+                       Bool valid = 0;
+                       char *stype1, *stype2;
+                       stype1 = strchr(mime_type, '/');
+                       stype2 = mime ? strchr(mime, '/') : NULL;
+                       if (stype1 && stype2 && !strcmp(stype1, stype2)) valid = 1;
+
+                       if (!valid) {
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Mime '%s' is not correct for '%s', it should be '%s'\n", mime, base_init_url, mime_type));
+                               mpdin->mpd_stop_request = 0;
+                               gf_mx_v(mpdin->dl_mutex);
+                               gf_free(base_init_url);
+                               base_init_url = NULL;
+                               return GF_BAD_PARAM;
+                       }
         }
         if (group->segment_must_be_streamed ) {
             group->segment_local_url = gf_dm_sess_get_resource_name(group->segment_dnload);
@@ -857,11 +1391,11 @@ static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group)
             gf_free(base_init_url);
             return GF_BAD_PARAM;
         } else {
-            assert(!group->nb_cached);
+            assert(!group->nb_cached_segments);
             group->cached[0].cache = gf_strdup(group->segment_local_url);
             group->cached[0].url = gf_strdup(gf_dm_sess_get_resource_name(group->segment_dnload));
-            group->nb_cached = 1;
-            group->download_segment_index = firstSegment;
+            group->nb_cached_segments = 1;
+            group->download_segment_index += nb_segment_read;
             GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Adding initialization segment %s to cache: %s\n", group->segment_local_url, group->cached[0].url ));
             gf_mx_v(mpdin->dl_mutex);
             gf_free(base_init_url);
@@ -872,26 +1406,25 @@ static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group)
 
 static void MPDIn_skip_disabled_rep(GF_MPD_Group *group, GF_MPD_Representation *rep)
 {
-       s32 rep_idx = gf_list_find(group->representations, rep);
+       s32 rep_idx = gf_list_find(group->adaptation_set->representations, rep);
        while (1) {
                rep_idx++;
-               if (rep_idx==gf_list_count(group->representations)) rep_idx = 0;
-               rep = gf_list_get(group->representations, rep_idx);
+               if (rep_idx==gf_list_count(group->adaptation_set->representations)) rep_idx = 0;
+               rep = gf_list_get(group->adaptation_set->representations, rep_idx);
                if (!rep->disabled) break;
        }
        assert(rep && !rep->disabled);
-       group->active_rep_index = gf_list_find(group->period->representations, rep);
-       group->active_bitrate = rep->bandwidth;
+       MPD_SetGroupRepresentation(group, rep);
        GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching to representation %d - BW %d\n", group->active_rep_index, group->active_bitrate ));
 }
 
+
 static u32 download_segments(void *par)
 {
     GF_Err e;
     GF_MPD_In *mpdin = (GF_MPD_In*) par;
     GF_MPD_Period *period;
     GF_MPD_Representation *rep;
-    GF_MPD_SegmentInfo *seg;
     u32 i, group_count, ret = 0;
        Bool go_on = 1;
     char *new_base_seg_url;
@@ -906,6 +1439,7 @@ static u32 download_segments(void *par)
     mpdin->mpd_is_running = MPD_STATE_CONNECTING;
     gf_mx_v(mpdin->dl_mutex);
 
+restart_period:
        e = GF_OK;
     period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
        group_count = gf_list_count(mpdin->groups);
@@ -932,17 +1466,18 @@ static u32 download_segments(void *par)
        for (i=0; i<group_count; i++) {
                GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Connecting initial service... %s\n", group->segment_local_url));
-               if (! group->service) {
+               if (! group->input_module) {
                        e = GF_SERVICE_ERROR;
                gf_term_on_connect(mpdin->service, NULL, e);
                        ret = 1;
                        goto exit;
                }
-               e = group->service->ConnectService(group->service, mpdin->service, group->segment_local_url);
+               e = group->input_module->ConnectService(group->input_module, mpdin->service, group->segment_local_url);
                if (e) {
                        ret = 1;
                        goto exit;
                }
+               group->service_connected = 1;
                GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Connecting initial service DONE\n", group->segment_local_url));
        }
 
@@ -956,29 +1491,44 @@ static u32 download_segments(void *par)
         /*wait until next segment is needed*/
         while (!mpdin->mpd_stop_request) {
             u32 timer = gf_sys_clock() - mpdin->last_update_time;
-            Bool shouldParsePlaylist = mpdin->mpd->min_update_time && (timer > mpdin->mpd->min_update_time);
+            Bool shouldParsePlaylist = mpdin->mpd->minimum_update_period && (timer > mpdin->mpd->minimum_update_period);
 
                        if (shouldParsePlaylist) {
-                GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Next segment in cache, but it is time to update the playlist (%u ms/%u)\n", timer, mpdin->mpd->min_update_time));
+                GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Next segment in cache, but it is time to update the playlist (%u ms/%u)\n", timer, mpdin->mpd->minimum_update_period));
                 e = MPD_UpdatePlaylist(mpdin);
                                group_count = gf_list_count(mpdin->groups);
                 if (e) {
-                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MDP %s\n", gf_error_to_string(e)));
+                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MPD %s\n", gf_error_to_string(e)));
                 }
             } else {
+                               Bool all_groups_done = 1;
                                Bool cache_full = 1;
                            gf_mx_p(mpdin->dl_mutex);
                                for (i=0; i<group_count; i++) {
                                        GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
                                        if (!group->selected || group->done) continue;
-                                       if (group->nb_cached<group->max_cached) {
+                                       all_groups_done = 0;
+                                       if (group->nb_cached_segments<group->max_cached_segments) {
                                                cache_full = 0;
                                                break;
                                        }
                                }
                    gf_mx_v(mpdin->dl_mutex);
                                if (!cache_full) break;
-                               
+
+                               if (mpdin->request_period_switch==2) all_groups_done = 1;
+
+                               if (all_groups_done && mpdin->request_period_switch) {
+                                       MPD_ResetGroups(mpdin);
+                                       if (mpdin->request_period_switch == 1) 
+                                               mpdin->active_period_index++;
+                                       
+                                       MPD_SetupPeriod(mpdin);
+                                       mpdin->request_period_switch = 0;
+
+                                       goto restart_period;
+                               }
+
                                gf_sleep(16);
             }
         }
@@ -994,37 +1544,39 @@ static u32 download_segments(void *par)
 
                /*for each selected groups*/
                for (i=0; i<group_count; i++) {         
+                       u64 start_range, end_range;
+                       Bool use_byterange;
                        GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
                        if (! group->selected) continue;
                        if (group->done) continue;
 
 
-                       if (group->nb_cached>=group->max_cached) {
+                       if (group->nb_cached_segments>=group->max_cached_segments) {
                                continue;
                        }
 
-                       rep = gf_list_get(period->representations, group->active_rep_index);
+                       rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index);
 
                        /* if the index of the segment to be downloaded is greater or equal to the last segment (as seen in the playlist),
                           we need to check if a new playlist is ready */
-                       if (group->download_segment_index>=gf_list_count(rep->segments)) {
+                       if (group->download_segment_index>=group->nb_segments_in_rep) {
                                u32 timer = gf_sys_clock() - mpdin->last_update_time;
                                /* update of the playlist, only if indicated */
-                               if (mpdin->mpd->min_update_time && timer > mpdin->mpd->min_update_time) {
+                               if (mpdin->mpd->minimum_update_period && timer > mpdin->mpd->minimum_update_period) {
                                        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Last segment in current playlist downloaded, checking updates after %u ms\n", timer));
                                        e = MPD_UpdatePlaylist(mpdin);
                                        if (e) {
-                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MDP %s\n", gf_error_to_string(e)));
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MPD %s\n", gf_error_to_string(e)));
                                        }
                                        group_count = gf_list_count(mpdin->groups);
                                        period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
-                                       rep = gf_list_get(period->representations, group->active_rep_index);
+                                       rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index);
                                } else {
                                        gf_sleep(16);
                                }
                                /* Now that the playlist is up to date, we can check again */
-                               if (group->download_segment_index >= gf_list_count(rep->segments)) {
-                                       if (mpdin->mpd->min_update_time) {
+                               if (group->download_segment_index >= group->nb_segments_in_rep) {
+                                       if (mpdin->mpd->minimum_update_period) {
                                                /* if there is a specified update period, we redo the whole process */
                                                continue;
                                        } else {
@@ -1036,41 +1588,39 @@ static u32 download_segments(void *par)
                                }
                        }
                        gf_mx_p(mpdin->dl_mutex);
+
                        /* At this stage, there are some segments left to be downloaded */
-                       seg = gf_list_get(rep->segments, group->download_segment_index);
+                       e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index, &new_base_seg_url, &start_range, &end_range);
                        gf_mx_v(mpdin->dl_mutex);
-
-                       if (!seg->url) {
-                               if (rep->init_url)
-                                       new_base_seg_url = gf_url_concatenate(rep->default_base_url, rep->init_url);
-                               else
-                                       new_base_seg_url = gf_strdup(rep->default_base_url);
-                       } else if (rep->default_base_url) {
-                               new_base_seg_url = gf_url_concatenate(rep->default_base_url, seg->url);
-                       } else {
-                               new_base_seg_url = gf_strdup(seg->url);
+                       if (e) {
+                               /*do something!!*/
+                               break;
                        }
-                       if (seg->use_byterange) {
-                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Downloading new segment: %s (range: %d-%d)\n", new_base_seg_url, seg->byterange_start, seg->byterange_end));
+                       use_byterange = (start_range || end_range) ? 1 : 0;
+
+                       if (use_byterange) {
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Downloading new segment: %s (range: "LLD"-"LLD")\n", new_base_seg_url, start_range, end_range));
                        }
 
                        /*local file*/
                        if (!strstr(new_base_seg_url, "://") || !strnicmp(new_base_seg_url, "file://", 7)) {
-                               /*byte-range request from file are ignored*/
-                               if (seg->use_byterange) {
-                                       group->done = 1;
-                                       break;
-                               }
                                resource_name = local_file_name = (char *) new_base_seg_url; 
                                e = GF_OK;
                                /*do not erase local files*/
                                group->local_files = 1;
+                               if (group->force_switch_bandwidth && !mpdin->auto_switch_count) {
+                                       MPD_SwitchGroupRepresentation(mpdin, group);
+                                       /*restart*/
+                                       i--;
+                                       continue;
+                               }
+
                        } else {
                                group->max_bitrate = 0;
                                group->min_bitrate = (u32)-1;
                                /*use persistent connection for segment downloads*/
-                               if (seg->use_byterange) {
-                                       e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), new_base_seg_url, MPD_NetIO_Segment, group, seg->byterange_start, seg->byterange_end, 1);
+                               if (use_byterange) {
+                                       e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), new_base_seg_url, MPD_NetIO_Segment, group, start_range, end_range, 1);
                                } else {
                                        e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), new_base_seg_url, MPD_NetIO_Segment, group, 0, 0, 1);
                                }
@@ -1097,28 +1647,42 @@ static u32 download_segments(void *par)
 
                                {
                                        u32 total_size, bytes_per_sec;
+                                       u64 duration;
                                        Double bitrate;
                                        gf_dm_sess_get_stats(group->segment_dnload, NULL, NULL, &total_size, NULL, &bytes_per_sec, NULL);
                                        bitrate = 8*total_size;
                                        bitrate *= 1000;
-                                       bitrate /= rep->default_segment_duration;
-                                       bitrate /= 1024;
-                                       fprintf(stdout, "Downloaded segment bitrate %d kbps with bandwith %d kbps\n", (u32) bitrate, 8*bytes_per_sec/1024);
+                                       duration = MPD_ResolveDuration(rep, group->adaptation_set, group->period, 0);
+                                       if (!duration) {
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Downloaded segment (bandwidth %d) with bandwith %d kbps\n", 8*rep->bandwidth/1024, 8*bytes_per_sec/1024));
+                                       } else {
+                                               bitrate /= duration;
+                                               bitrate /= 1024;
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Downloaded segment (bandwidth %d) bitrate %d with bandwith %d kbps\n", 8*rep->bandwidth/1024, (u32) bitrate, 8*bytes_per_sec/1024));
+                                       }
                                        /*TODO switch quality*/
 
                                        if (!mpdin->auto_switch_count) {
-                                               MPD_SwitchGroupRepresentation(mpdin, group);
+//                                             MPD_SwitchGroupRepresentation(mpdin, group);
                                        }
                                }
                        }
 
                        if (e == GF_OK || group->segment_must_be_streamed) {
                                gf_mx_p(mpdin->dl_mutex);
-                               assert(group->nb_cached<group->max_cached);
-                               group->cached[group->nb_cached].cache = gf_strdup(local_file_name);
-                               group->cached[group->nb_cached].url = gf_strdup( resource_name );
-                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Added file to cache\n\tURL: %s\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[group->nb_cached].url, group->cached[group->nb_cached].cache, group->nb_cached+1, group->max_cached));
-                               group->nb_cached++;
+                               assert(group->nb_cached_segments<group->max_cached_segments);
+                               group->cached[group->nb_cached_segments].cache = gf_strdup(local_file_name);
+                               group->cached[group->nb_cached_segments].url = gf_strdup( resource_name );
+                               group->cached[group->nb_cached_segments].start_range = 0;
+                               group->cached[group->nb_cached_segments].end_range = 0;
+                               if (group->local_files && use_byterange) {
+                                       group->cached[group->nb_cached_segments].start_range = start_range;
+                                       group->cached[group->nb_cached_segments].end_range = end_range;
+                               }
+                               if (!group->local_files) {
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Added file to cache\n\tURL: %s\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[group->nb_cached_segments].url, group->cached[group->nb_cached_segments].cache, group->nb_cached_segments+1, group->max_cached_segments));
+                               }
+                               group->nb_cached_segments++;
                                group->download_segment_index++;
                                if (mpdin->auto_switch_count) {
                                        group->nb_segments_done++;
@@ -1137,9 +1701,6 @@ static u32 download_segments(void *par)
                                break;
                        }
                }
-
-               if (!go_on) break;
-
     }
 
 exit:
@@ -1192,7 +1753,7 @@ Bool MPD_CanHandleURL(GF_InputService *plug, const char *url)
 GF_InputService *MPD_GetInputServiceForChannel(GF_MPD_In *mpdin, LPNETCHANNEL channel)
 {
        GF_Channel *ch;
-       if (mpdin->group_zero_selected) return mpdin->group_zero_selected->service;
+       if (mpdin->group_zero_selected) return mpdin->group_zero_selected->input_module;
        ch = (GF_Channel *) channel;
        assert(ch && ch->odm && ch->odm->OD);
 
@@ -1204,7 +1765,7 @@ GF_MPD_Group *MPD_GetGroupForInputService(GF_MPD_In *mpdin, GF_InputService *ifc
        u32 i;
        for (i=0; i<gf_list_count(mpdin->groups); i++) {
                GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
-               if (group->service==ifce) return group;
+               if (group->input_module==ifce) return group;
        }
        return NULL;
 }
@@ -1245,13 +1806,17 @@ static u32 MPD_GetPeriodIndexFromTime(GF_MPD_In *mpdin, u32 time)
 static void MPD_DownloadStop(GF_MPD_In *mpdin)
 {
        u32 i;
+    assert( mpdin );
+    if (mpdin->groups){
        for (i=0; i<gf_list_count(mpdin->groups); i++) {
                GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
+               assert( group );
                if (group->selected && group->segment_dnload) {
                        gf_dm_sess_abort(group->segment_dnload);
                        group->done = 1;
                }
        }
+    }
     /* stop the download thread */
     gf_mx_p(mpdin->dl_mutex);
     if (mpdin->mpd_is_running != MPD_STATE_STOPPED) {
@@ -1273,16 +1838,116 @@ static void MPD_DownloadStop(GF_MPD_In *mpdin)
     }
 }
 
+Bool MPD_SeekPeriods(GF_MPD_In *mpdin)
+{
+       Double start_time;
+       u32 i, period_idx;
+
+       gf_mx_p(mpdin->dl_mutex);
+       start_time = 0;
+       period_idx = 0;
+       for (i=0; i<=gf_list_count(mpdin->mpd->periods); i++) {
+               GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, i);
+               Double dur = period->duration;
+               dur /= 1000;
+               if (mpdin->playback_start_range >= start_time) {
+                       if ((i+1==gf_list_count(mpdin->mpd->periods)) || (mpdin->playback_start_range < start_time + dur) ) {
+                               period_idx = i;
+                               break;
+                       }
+               }
+               start_time += dur;
+       }
+       if (period_idx != mpdin->active_period_index) {
+               mpdin->playback_start_range -= start_time;
+               mpdin->active_period_index = period_idx;
+               mpdin->request_period_switch = 2;
+       }
+       gf_mx_v(mpdin->dl_mutex);
+       
+       return mpdin->request_period_switch ? 1 : 0;
+}
+
+void MPD_SeekGroup(GF_MPD_In *mpdin, GF_MPD_Group *group)
+{
+       Double seg_start;
+       u32 first_downloaded, last_downloaded, segment_idx;
+
+       group->force_segment_switch = 0;
+
+       /*figure out where to seek*/
+       segment_idx = 0;
+       seg_start = 0.0;
+       while (1) {
+               if ((mpdin->playback_start_range >= seg_start) && (mpdin->playback_start_range < seg_start + group->segment_duration)) 
+                       break;
+               seg_start += group->segment_duration;
+               segment_idx++;
+       }
+       /*todo - seek to given duration*/
+       mpdin->playback_start_range -= seg_start;
+
+       first_downloaded = last_downloaded = group->download_segment_index;
+       if (group->download_segment_index +1 >= group->nb_cached_segments) {
+               first_downloaded = group->download_segment_index + 1 - group->nb_cached_segments;
+       }
+       /*we are seeking in our download range, just go on*/
+       if ((segment_idx >= first_downloaded) && (segment_idx<=last_downloaded)) return;
+
+       group->force_segment_switch = 1;
+       group->download_segment_index = segment_idx;
+
+       if (group->segment_dnload) 
+               gf_dm_sess_abort(group->segment_dnload);
+
+       if (group->urlToDeleteNext) {
+               if (!mpdin->keep_files && !group->local_files)
+                       gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext);
+    
+               gf_free(group->urlToDeleteNext);
+               group->urlToDeleteNext = NULL;
+       }
+       if (group->segment_dnload) {
+               gf_term_download_del(group->segment_dnload);
+               group->segment_dnload = NULL;
+       }
+       while (group->nb_cached_segments) {
+               group->nb_cached_segments --;
+               if (!mpdin->keep_files && !group->local_files)
+                       gf_delete_file(group->cached[group->nb_cached_segments].cache);
+
+               gf_free(group->cached[group->nb_cached_segments].cache);
+               gf_free(group->cached[group->nb_cached_segments].url);
+               memset(&group->cached[group->nb_cached_segments], 0, sizeof(segment_cache_entry));
+       }
+}
+
+void MPD_SeekGroupsDownloads(GF_MPD_In *mpdin)
+{
+       u32 i;
+
+       gf_mx_p(mpdin->dl_mutex);
+       for (i=0; i<gf_list_count(mpdin->groups); i++) {
+               GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
+               MPD_SeekGroup(mpdin, group);
+       }
+       gf_mx_v(mpdin->dl_mutex);
+}
+
+
 void MPD_ResetGroups(GF_MPD_In *mpdin)
 {
+       mpdin->service->subservice_disconnect = 1;
+       gf_term_on_disconnect(mpdin->service, NULL, GF_OK);
+
+       mpdin->service->subservice_disconnect = 2;
        while (gf_list_count(mpdin->groups)) {
                GF_MPD_Group *group = gf_list_last(mpdin->groups);
                gf_list_rem_last(mpdin->groups);
-               gf_list_del(group->representations);
 
                if (group->urlToDeleteNext) {
                        if (!mpdin->keep_files && !group->local_files)
-                               gf_dm_delete_cached_file_entry_session(mpdin->mpd_dnload, group->urlToDeleteNext);
+                               gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext);
            
                        gf_free(group->urlToDeleteNext);
                        group->urlToDeleteNext = NULL;
@@ -1291,21 +1956,33 @@ void MPD_ResetGroups(GF_MPD_In *mpdin)
                        gf_term_download_del(group->segment_dnload);
                        group->segment_dnload = NULL;
                }
-               while (group->nb_cached) {
-                       group->nb_cached --;
+               while (group->nb_cached_segments) {
+                       group->nb_cached_segments --;
                        if (!mpdin->keep_files && !group->local_files)
-                               gf_delete_file(group->cached[group->nb_cached].cache);
+                               gf_delete_file(group->cached[group->nb_cached_segments].cache);
 
-                       gf_free(group->cached[group->nb_cached].cache);
-                       gf_free(group->cached[group->nb_cached].url);
+                       gf_free(group->cached[group->nb_cached_segments].cache);
+                       gf_free(group->cached[group->nb_cached_segments].url);
                }
                gf_free(group->cached);
+
+               if (group->input_module) {
+                       if (group->service_connected) {
+                               group->input_module->CloseService(group->input_module);
+                               group->service_connected = 0;
+                       }
+                       gf_modules_close_interface((GF_BaseInterface *) group->input_module);
+                       group->input_module = NULL;
+               }
+
                gf_free(group);
        }
        gf_list_del(mpdin->groups);
        mpdin->groups = NULL;
+       mpdin->service->subservice_disconnect = 0;
 }
 
+/* create groups (implemntation of adaptations set) */
 GF_Err MPD_SetupGroups(GF_MPD_In *mpdin)
 {
        GF_Err e;
@@ -1319,16 +1996,14 @@ GF_Err MPD_SetupGroups(GF_MPD_In *mpdin)
        period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
        if (!period) return GF_BAD_PARAM;
 
-       count = gf_list_count(period->representations);
+       count = gf_list_count(period->adaptation_sets);
        for (i=0; i<count; i++) {
         Bool found = 0;
-               GF_MPD_Representation *rep = gf_list_get(period->representations, i);
+               GF_MPD_AdaptationSet *set = gf_list_get(period->adaptation_sets, i);
                for (j=0; j<gf_list_count(mpdin->groups); j++) {
                        GF_MPD_Group *group = gf_list_get(mpdin->groups, j);
-                       if (group->group_id==rep->groupID) {
+                       if (group->adaptation_set==set) {
                        found = 1;
-                               e = gf_list_add(group->representations, rep);
-                               if (e) return e;
                                break;
                        }
                }
@@ -1336,57 +2011,32 @@ GF_Err MPD_SetupGroups(GF_MPD_In *mpdin)
                        GF_MPD_Group *group;
                        GF_SAFEALLOC(group, GF_MPD_Group);
                        if (!group) return GF_OUT_OF_MEM;
-                       group->representations = gf_list_new();
-                       if (!group->representations) {
-                               gf_free(group);
-                               return GF_OUT_OF_MEM;
-                       }
-                       group->group_id = rep->groupID;
+                       group->mpd_in = mpdin;
+                       group->adaptation_set = set;
+                       group->period = period;
                        group->period = period;
-                       group->max_cached = mpdin->option_max_cached;
-                       group->cached = gf_malloc(sizeof(segment_cache_entry)*group->max_cached);
-                       memset(group->cached, 0, sizeof(segment_cache_entry)*group->max_cached);
+                       group->max_cached_segments = mpdin->option_max_cached;
+                       group->cached = gf_malloc(sizeof(segment_cache_entry)*group->max_cached_segments);
+                       memset(group->cached, 0, sizeof(segment_cache_entry)*group->max_cached_segments);
                        if (!group->cached) {
-                               gf_list_del(group->representations);
                                gf_free(group);
                                return GF_OUT_OF_MEM;
                        }
                        e = gf_list_add(mpdin->groups, group);
                        if (e) {
                                gf_free(group->cached);
-                               gf_list_del(group->representations);
                                gf_free(group);
                                return e;
                        }
-
-                       e = gf_list_add(group->representations, rep);
-                       if (e) return e;
-
                }
        }
        return GF_OK;
 }
 
-static GF_Err MPD_SegmentsProcessStart(GF_MPD_In *mpdin, u32 time)
+GF_Err MPD_SetupPeriod(GF_MPD_In *mpdin)
 {
-    GF_Err e;
+       GF_Err e;
     u32 rep_i, group_i;
-    GF_MPD_Period *period;
-    e = GF_BAD_PARAM;
-
-#if 0
-    MPD_DownloadStop(mpdin);
-#endif
-
-       MPD_ResetGroups(mpdin);
-
-       /* Get the right period from the given time */
-    mpdin->active_period_index = MPD_GetPeriodIndexFromTime(mpdin, time);
-    period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
-    if (!period || !gf_list_count(period->representations) ) {
-        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: not enough periods or representations in MPD\n"));
-        goto exit;
-    }
 
        /*setup all groups*/
        MPD_SetupGroups(mpdin);
@@ -1395,53 +2045,88 @@ static GF_Err MPD_SegmentsProcessStart(GF_MPD_In *mpdin, u32 time)
        for (group_i=0; group_i<gf_list_count(mpdin->groups); group_i++) {
                GF_MPD_Representation *rep_sel;
                u32 active_rep;
+               const char *mime_type;
                GF_MPD_Group *group = gf_list_get(mpdin->groups, group_i);
 
-               if (group->group_id==0) {
+               if (group->adaptation_set->group==0) {
                        mpdin->group_zero_selected = group;
                } else if (mpdin->group_zero_selected) {
+                       /* if this group is not the group 0 and we have found the group 0, 
+                       we can safely ignore this group. */
                        break;
                }
 
                /* Select the appropriate representation in the given period */
                active_rep = 0;
-               for (rep_i = 0; rep_i < gf_list_count(group->representations); rep_i++) {
-                       GF_MPD_Representation *rep = gf_list_get(group->representations, rep_i);
-                       rep_sel = gf_list_get(group->representations, active_rep);
+               for (rep_i = 0; rep_i < gf_list_count(group->adaptation_set->representations); rep_i++) {
+                       GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_i);
+                       rep_sel = gf_list_get(group->adaptation_set->representations, active_rep);
+
+                       if (rep_i && ( !rep->codecs || !rep_sel->codecs || strcmp(rep->codecs, rep_sel->codecs) ) ) continue;
+
                        /*by default tune to best quality and/or full bandwith*/
-                       if (rep->qualityRanking > rep_sel->qualityRanking) {
+                       if (rep->quality_ranking > rep_sel->quality_ranking) {
                                active_rep = rep_i;
-                       } else if (rep->bandwidth > rep_sel->bandwidth) {
+                       } else if (rep->bandwidth < rep_sel->bandwidth) {
                                active_rep = rep_i;
                        }
+
                }
 
-               rep_sel = gf_list_get(group->representations, active_rep);
-               group->active_rep_index = gf_list_find(group->period->representations, rep_sel);
-               group->active_bitrate = rep_sel->bandwidth;
+               rep_sel = gf_list_get(group->adaptation_set->representations, active_rep);
+               MPD_SetGroupRepresentation(group, rep_sel);
+
+               if (mpdin->playback_start_range>=0) 
+                       MPD_SeekGroup(mpdin, group);
 
+               mime_type = MPD_GetMimeType(NULL, rep_sel, group->adaptation_set);
+
+               if (!mime_type) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing mime\n"));
+                       return GF_NON_COMPLIANT_BITSTREAM;
+               }
 
                /* TODO: Generate segment names if urltemplates are used */
-               if (!gf_list_count(rep_sel->segments) || !rep_sel->mime) {
-                       if (!rep_sel->mime) {
-                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing mime\n"));
-                       } else {
-                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing segments\n"));
-                       }
-                       goto exit;
+               if (!rep_sel->segment_base && !rep_sel->segment_list && !rep_sel->segment_template
+                       && !group->adaptation_set->segment_base && !group->adaptation_set->segment_list && !group->adaptation_set->segment_template
+                       && !group->period->segment_base && !group->period->segment_list && !group->period->segment_template
+                       
+               ) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing segments\n"));
+                       return GF_NON_COMPLIANT_BITSTREAM;
                }
 
-               group->service = NULL;
-               if (strcmp(M3U8_UNKOWN_MIME_TYPE, rep_sel->mime)) {
-                       e = MPD_LoadMediaService(mpdin, group, rep_sel->mime, NULL);
-                       if (e != GF_OK)
-                               goto exit;
+               group->input_module = NULL;
+               if (strcmp(M3U8_UNKOWN_MIME_TYPE, mime_type)) {
+                       e = MPD_LoadMediaService(mpdin, group, mime_type, NULL);
+                       if (e != GF_OK) return e;
                } else {
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Ignoring mime type %s, wait for first file...\n", rep_sel->mime));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Ignoring mime type %s, wait for first file...\n", mime_type));
                }
                group->selected = 1;
        }
 
+       /*and seek if needed*/
+       return GF_OK;
+}
+
+static GF_Err MPD_SegmentsProcessStart(GF_MPD_In *mpdin, u32 time)
+{
+    GF_Err e = GF_BAD_PARAM;
+    GF_MPD_Period *period;
+
+       MPD_ResetGroups(mpdin);
+
+       /* Get the right period from the given time */
+    mpdin->active_period_index = MPD_GetPeriodIndexFromTime(mpdin, time);
+    period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
+       if (!period || !gf_list_count(period->adaptation_sets) ) {
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: not enough periods or representations in MPD\n"));
+        goto exit;
+    }
+
+       e = MPD_SetupPeriod(mpdin);
+       if (e) goto exit;
 
        gf_th_run(mpdin->mpd_thread, download_segments, mpdin);
     return GF_OK;
@@ -1488,9 +2173,15 @@ GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const c
     opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "KeepFiles");
     if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "KeepFiles", "no");
     if (opt && !strcmp(opt, "yes")) mpdin->keep_files = 1;
+
+       opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "DisableSwitching");
+    if (opt && !strcmp(opt, "yes")) mpdin->disable_switching = 1;
        
        if (mpdin->mpd_dnload) gf_term_download_del(mpdin->mpd_dnload);
     mpdin->mpd_dnload = NULL;
+       mpdin->in_seek = 0;
+       mpdin->previous_start_range = -1;
+
 
     if (!strnicmp(url, "file://", 7)) {
         local_url = url + 7;
@@ -1557,10 +2248,10 @@ GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const c
                        if (sep) sep[0]=0;
                        strcat(local_path, ".mpd");
 
-               gf_m3u8_to_mpd(mpdin->service, local_url, url, local_path, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments);
+               gf_m3u8_to_mpd(local_url, url, local_path, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, mpdin->service, 0, M3U8_TO_MPD_USE_TEMPLATE);
                        local_url = local_path;
                } else {
-               gf_m3u8_to_mpd(mpdin->service, local_url, url, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments);
+               gf_m3u8_to_mpd(local_url, url, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, mpdin->service, 0, M3U8_TO_MPD_USE_TEMPLATE);
                }
     }
 
@@ -1576,7 +2267,7 @@ GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const c
     mpd_parser = gf_xml_dom_new();
     e = gf_xml_dom_parse(mpd_parser, local_url, NULL, NULL);
     if (e != GF_OK) {
-        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: MPD parsing problem %s\n", gf_error_to_string(e)));
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: MPD parsing problem %s\n", gf_xml_dom_get_error(mpd_parser) ));
         gf_xml_dom_del(mpd_parser);
         gf_term_on_connect(mpdin->service, NULL, e);
         gf_term_download_del(mpdin->mpd_dnload);
@@ -1612,8 +2303,8 @@ static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
     GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv;
     GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Description request from terminal for %s\n", sub_url));
        if (mpdin->group_zero_selected) {
-               if (mpdin->group_zero_selected->service) {
-               return mpdin->group_zero_selected->service->GetServiceDescriptor(mpdin->group_zero_selected->service, expect_type, sub_url);
+               if (mpdin->group_zero_selected->input_module) {
+               return mpdin->group_zero_selected->input_module->GetServiceDescriptor(mpdin->group_zero_selected->input_module, expect_type, sub_url);
                } else {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot provide service description: no segment service hanlder created\n"));
                        return NULL;
@@ -1623,9 +2314,9 @@ static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
                for (i=0; i<gf_list_count(mpdin->groups); i++) {
                        GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
                        if (!group->selected) continue;
-                       if (group->service_connected) continue;
-                       group->service_connected = 1;
-               return group->service->GetServiceDescriptor(group->service, expect_type, sub_url);
+                       if (group->service_descriptor_fetched) continue;
+                       group->service_descriptor_fetched = 1;
+               return group->input_module->GetServiceDescriptor(group->input_module, expect_type, sub_url);
                }
                return NULL;
        }
@@ -1633,6 +2324,7 @@ static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
 
 void MPD_Stop(GF_MPD_In *mpdin)
 {
+    assert( mpdin );
     GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Stopping service %p\n", mpdin->service));
     MPD_DownloadStop(mpdin);
     MPD_ResetGroups(mpdin);
@@ -1648,22 +2340,13 @@ void MPD_Stop(GF_MPD_In *mpdin)
 
 GF_Err MPD_CloseService(GF_InputService *plug)
 {
-       u32 i;
     GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv;
+    assert( mpdin );
     GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Close Service (%p) request from terminal\n", mpdin->service));
    
-       for (i=0; i<gf_list_count(mpdin->groups); i++) {
-               GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
-       
-               if (group->service && group->service_connected) {
-                       group->service->CloseService(group->service);
-                       group->service_connected = 0;
-                       group->service = NULL;
-               }
-       }
     MPD_Stop(mpdin);
-       MPD_ResetGroups(mpdin);
-    gf_term_on_disconnect(mpdin->service, NULL, GF_OK);
+
+       gf_term_on_disconnect(mpdin->service, NULL, GF_OK);
 
        return GF_OK;
 }
@@ -1676,7 +2359,7 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
        GF_MPD_Group *group = NULL;
     if (!plug || !plug->priv || !com ) return GF_SERVICE_ERROR;
 
-       if (mpdin->group_zero_selected) segment_ifce = mpdin->group_zero_selected->service;
+       if (mpdin->group_zero_selected) segment_ifce = mpdin->group_zero_selected->input_module;
 
        switch (com->command_type) {
     case GF_NET_SERVICE_INFO:
@@ -1690,12 +2373,13 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                }
 
                if (e!= GF_OK || !com->info.name || 2 > strlen(com->info.name)) {
-                       com->info.name = mpdin->mpd->title;
+                       GF_MPD_ProgramInfo *info = gf_list_get(mpdin->mpd->program_infos, 0);
+                       if (info) {
+                               com->info.name = info->title;
+                               com->info.comment = info->source;
+                       }
                        if (!com->info.name && mpdin->group_zero_selected)
-                   com->info.name = mpdin->group_zero_selected->cached[0].url;
-
-                       if (mpdin->mpd->source)
-                com->info.comment = mpdin->mpd->source;
+                               com->info.name = mpdin->group_zero_selected->cached[0].url;
         }
         return GF_OK;
     }
@@ -1706,6 +2390,47 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                    return segment_ifce->ServiceCommand(segment_ifce, com);
                }
         return GF_NOT_SUPPORTED;
+
+       case GF_NET_SERVICE_QUALITY_SWITCH:
+               {
+                       u32 i;
+
+                       for (i=0; i<gf_list_count(mpdin->groups); i++) {
+                               Bool do_switch = 0;
+                               GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
+                               u32 current_idx = group->active_rep_index;
+                               if (! group->selected) continue;
+
+                               if (group->force_representation_idx_plus_one) current_idx = group->force_representation_idx_plus_one - 1;
+                               if (com->switch_quality.up) {
+                                       if (current_idx + 1 < gf_list_count(group->adaptation_set->representations)) {
+                                               group->force_representation_idx_plus_one = 1 + current_idx+1;
+                                               do_switch = 1;
+                                       }
+                               } else {
+                                       if (current_idx) {
+                                               group->force_representation_idx_plus_one = 1 + current_idx - 1;
+                                               do_switch = 1;
+                                       }
+                               }
+                               if (do_switch) {
+                                       gf_mx_p(mpdin->dl_mutex);
+                                       group->force_switch_bandwidth = 1;
+                                       /*in local playback just switch at the end of the current segment*/
+                                       while (group->local_files && (group->nb_cached_segments>1)) {
+                                               group->nb_cached_segments--;
+                                               gf_free(group->cached[group->nb_cached_segments].url);
+                                               group->cached[group->nb_cached_segments].url = NULL;
+                                               group->cached[group->nb_cached_segments].start_range = 0;
+                                               group->cached[group->nb_cached_segments].end_range = 0;
+                                               assert(group->download_segment_index>1);
+                                               group->download_segment_index--;
+                                       }
+                                       gf_mx_v(mpdin->dl_mutex);
+                               }
+                       }
+               }
+        return GF_OK;
        }
        /*not supported*/
        if (!com->base.on_channel) return GF_NOT_SUPPORTED;
@@ -1745,7 +2470,14 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
            Note: the duration of the initial segment will be 0 anyway (in MP4).*/
         {
             Double duration;
-            duration = (Double)mpdin->mpd->duration;
+                       duration = (Double)mpdin->mpd->media_presentation_duration;
+                       if (!duration) {
+                               u32 i;
+                               for (i=0; i<gf_list_count(mpdin->mpd->periods); i++) {
+                                       GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, i);
+                                       duration += (Double)period->duration;
+                               }
+                       }
             duration /= 1000;
             com->duration.duration = duration;
             return GF_OK;
@@ -1753,11 +2485,38 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
         break;
     case GF_NET_CHAN_PLAY:
         GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Play command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service));
-        mpdin->playback_speed = com->play.speed;
-        mpdin->playback_start_range = com->play.start_range;
-        mpdin->playback_end_range = com->play.end_range;
+
+               if (!com->play.dash_segment_switch && ! mpdin->in_seek) {
+                       Bool skip_seek;
+                       
+                       mpdin->in_seek = 1;
+                       
+                       /*if start range request is the same as previous one, don't process it
+                       - this happens at period switch when new objects are declared*/
+                       skip_seek = (mpdin->previous_start_range==com->play.start_range) ? 1 : 0;
+                       mpdin->previous_start_range = com->play.start_range;
+
+               mpdin->playback_speed = com->play.speed;
+                   mpdin->playback_start_range = com->play.start_range;
+
+                       /*first check if we seek to another period*/
+                       if (! MPD_SeekPeriods(mpdin)) {
+                               /*if no, seek in group*/
+                               MPD_SeekGroupsDownloads(mpdin);
+                       }
+               } 
+               /*For MPEG-2 TS or formats not using Init Seg: since objects are declared and started once the first
+               segment is playing, we will stay in playback_start_range!=-1 until next segment (because we won't have a query_next),
+               which will prevent seeking until then ... we force a reset of playback_start_range to allow seeking asap*/
+               else if (mpdin->in_seek && (com->play.start_range==0)) {
+//                     mpdin->in_seek = 0;
+               }
                group->done = 0;
-        return segment_ifce->ServiceCommand(segment_ifce, com);
+               com->play.dash_segment_switch = group->force_segment_switch;
+               /*don't forward commands, we are killing the service anyway ...*/
+               if (mpdin->request_period_switch) return GF_OK;
+
+               return segment_ifce->ServiceCommand(segment_ifce, com);
 
        case GF_NET_CHAN_STOP:
         GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Stop command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service));
@@ -1855,19 +2614,24 @@ GF_Err MPD_ChannelReleaseSLP(GF_InputService *plug, LPNETCHANNEL channel)
 
 Bool MPD_CanHandleURLInService(GF_InputService *plug, const char *url)
 {
-       /*JLF: commented out, this shall not happen*/
-#if 0
+       /**
+        * May arrive when using pid:// URLs into a TS stream
+        */
        GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv;
     GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Can Handle URL In Service (%p) request from terminal for %s\n", mpdin->service, url));
     if (!plug || !plug->priv) return GF_SERVICE_ERROR;
     if (mpdin->url && !strcmp(mpdin->url, url)) {
         return 1;
     } else {
+       GF_InputService *segment_ifce = NULL;
+        GF_MPD_Group *group = NULL;
+        if (mpdin->group_zero_selected)
+               segment_ifce = mpdin->group_zero_selected->input_module;
+       if (segment_ifce && segment_ifce->CanHandleURLInService){
+               return segment_ifce->CanHandleURLInService(plug, url);
+       }
         return 0;
     }
-#endif
-
-       return 0;
 }
 
 GF_EXPORT
@@ -1914,16 +2678,24 @@ void ShutdownInterface(GF_BaseInterface *bi)
     GF_InputService *ifcn = (GF_InputService*)bi;
     if (ifcn->InterfaceType==GF_NET_CLIENT_INTERFACE) {
         GF_MPD_In *mpdin = (GF_MPD_In*)ifcn->priv;
+       assert( mpdin );
         if (mpdin->mpd)
             gf_mpd_del(mpdin->mpd);
         mpdin->mpd = NULL;
        if (mpdin->url)
          gf_free(mpdin->url);
        mpdin->url = NULL;
-        gf_th_del(mpdin->mpd_thread);
-        gf_mx_del(mpdin->dl_mutex);
-        gf_free(mpdin->mimeTypeForM3U8Segments);
+       if (mpdin->mpd_thread)
+          gf_th_del(mpdin->mpd_thread);
+        mpdin->mpd_thread = NULL;
+       if (mpdin->dl_mutex)
+          gf_mx_del(mpdin->dl_mutex);
+        mpdin->dl_mutex = NULL;
+        if (mpdin->mimeTypeForM3U8Segments)
+               gf_free(mpdin->mimeTypeForM3U8Segments);
+       mpdin->mimeTypeForM3U8Segments = NULL;
         gf_free(mpdin);
+       ifcn->priv = NULL;
         gf_free(bi);
     }
 }
index 6d84d6be3b99e972997cd6dd9f0f05af8fbbe515..bb512c6214be45164d1ca9e2a0fbe398e6ebf155 100644 (file)
@@ -192,9 +192,11 @@ static GF_ObjectDescriptor *MP2TS_GetOD(M2TSIn *m2ts, GF_M2TS_PES *stream, char
        case GF_M2TS_AUDIO_LATM_AAC:
        case GF_M2TS_AUDIO_AAC:
                if (!dsi) {
-                       /*discard regulate until we fetch the AAC config*/
-                       m2ts->ts->file_regulate = 0;
-                       /*turn on parsing*/
+                       /*turn on parsing to get AAC config
+                               NB: we removed "no file regulation" since we may get broken files where PMT declares an AAC stream but no AAC PID is in the MUX
+                               (filtered out). In this case, "no regulation" will make the entire TS to be read as fast as possible
+                       */
+                       m2ts->ts->file_regulate = 2;
                        gf_m2ts_set_pes_framing(stream, GF_M2TS_PES_FRAMING_DEFAULT);
                        gf_odf_desc_del((GF_Descriptor *)esd);
                        return NULL;
@@ -264,7 +266,9 @@ static void MP2TS_SetupProgram(M2TSIn *m2ts, GF_M2TS_Program *prog, Bool regener
                if (!found) return;
        }
 #endif
-       if (m2ts->ts->file || m2ts->ts->dnload) m2ts->ts->file_regulate = no_declare ? 0 : 1;
+
+       /*TS is a file, start regulation regardless of how the TS is access (with or without fragment URI)*/
+       if (m2ts->ts->file || m2ts->ts->dnload) m2ts->ts->file_regulate = 1;
 
        for (i=0; i<count; i++) {
                GF_M2TS_ES *es = gf_list_get(prog->streams, i);
@@ -273,13 +277,13 @@ static void MP2TS_SetupProgram(M2TSIn *m2ts, GF_M2TS_Program *prog, Bool regener
                if (!es->user)
                        gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_SKIP);
 
-               if (!prog->pmt_iod && !no_declare) {
+               if (!prog->pmt_iod && !no_declare) {                                            
                        MP2TS_DeclareStream(m2ts, (GF_M2TS_PES *)es, NULL, 0);
                } 
                /*if IOD, streams not declared through OD framework are refered to by pid:// scheme, and will be declared upon
                request by the terminal through GetServiceDesc*/
        }
-
+       
        /*force scene regeneration*/
        if (!prog->pmt_iod && regenerate_scene)
                gf_term_add_media(m2ts->service, NULL, 0);
@@ -465,15 +469,27 @@ static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param)
                evt.forwarded_event.param = ts;
                gf_term_on_service_event(m2ts->service, &evt);          
                break;
+       case GF_M2TS_EVT_DSMCC_FOUND:
+               evt.type = GF_EVENT_FORWARDED;
+               evt.forwarded_event.forward_type = GF_EVT_FORWARDED_MPEG2;
+               evt.forwarded_event.service_event_type = evt_type;
+               evt.forwarded_event.param = param;                
+               gf_term_on_service_event(m2ts->service, &evt);
+               break;
        case GF_M2TS_EVT_PMT_FOUND:
                if (gf_list_count(m2ts->ts->programs) == 1) {
                        gf_term_on_connect(m2ts->service, NULL, GF_OK);
                        m2ts->is_connected = 1;
-               }
-
+               }               
                /*do not declare if  single program was requested for playback*/
                MP2TS_SetupProgram(m2ts, param, m2ts->request_all_pids, m2ts->request_all_pids ? 0 : 1);
-               M2TS_FlushRequested(m2ts);
+               M2TS_FlushRequested(m2ts);              
+               /* Send the TS to the a user if needed. Useful to check the number of received programs*/
+               evt.type = GF_EVENT_FORWARDED;
+               evt.forwarded_event.forward_type = GF_M2TS_EVT_PMT_FOUND;
+               evt.forwarded_event.service_event_type = evt_type;
+               evt.forwarded_event.param = param;
+               gf_term_on_service_event(m2ts->service, &evt);          
                break;
        case GF_M2TS_EVT_PMT_REPEAT:
 //     case GF_M2TS_EVT_PMT_UPDATE:
@@ -539,7 +555,7 @@ static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param)
                        u32 stb = gf_sys_clock();
                        
                        if (m2ts->regulation_pcr_pid==0) {
-                               /*we pick the first PCR PID for file regulation - we don't need to make sure this is the PCR of a program being plyaed as we
+                               /*we pick the first PCR PID for file regulation - we don't need to make sure this is the PCR of a program being played as we
                                only check buffer levels, not DTS/PTS of the streams in the regulation step*/
                                m2ts->regulation_pcr_pid = ((GF_M2TS_PES_PCK *) param)->stream->pid;
                        } else if (m2ts->regulation_pcr_pid != ((GF_M2TS_PES_PCK *) param)->stream->pid) {
@@ -558,7 +574,7 @@ static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param)
                                        u64 pcr_diff = (pcr - ts->pcr_last);
                                        pcr_diff /= 27000;
                                        if (pcr_diff>1000) {
-                                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS In] PCR diff too big: "LLU" ms - PCR "LLU" - previous PCR "LLU" - error in TS ?\n", pcr_diff, ((GF_M2TS_PES_PCK *) param)->PTS, ts->pcr_last));
+                                               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TS In] PCR diff too big: "LLU" ms - PCR "LLU" - previous PCR "LLU" - error in TS ?\n", pcr_diff, ((GF_M2TS_PES_PCK *) param)->PTS, ts->pcr_last));
                                                diff = 100;
                                        } else {
                                                diff = (u32) pcr_diff - (stb - ts->stb_at_last_pcr);
@@ -660,7 +676,7 @@ void m2ts_net_io(void *cbk, GF_NETIO_Parameter *param)
 {
        GF_Err e;
        M2TSIn *m2ts = (M2TSIn *) cbk;
-        assert( m2ts );
+       assert( m2ts );
        /*handle service message*/
        gf_term_download_update_stats(m2ts->ts->dnload);
 
@@ -668,33 +684,35 @@ void m2ts_net_io(void *cbk, GF_NETIO_Parameter *param)
                e = GF_EOS;
        } else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) {
                e = GF_OK;
-                assert( m2ts->ts);
-                if (param->size > 0){
-                  /*process chunk*/
-                  assert(param->data);
-                 if (m2ts->network_buffer_size < param->size){
-                         m2ts->network_buffer = gf_realloc(m2ts->network_buffer, sizeof(char) * param->size);
-                         m2ts->network_buffer_size = param->size;
-                 }
-                 assert( m2ts->network_buffer );
-                 memcpy(m2ts->network_buffer, param->data, param->size);
-                  gf_m2ts_process_data(m2ts->ts, m2ts->network_buffer, param->size);
-                }
+               assert( m2ts->ts);
+               if (param->size > 0){
+                       /*process chunk*/
+                       assert(param->data);
+                       if (m2ts->network_buffer_size < param->size){
+                               m2ts->network_buffer = gf_realloc(m2ts->network_buffer, sizeof(char) * param->size);
+                               m2ts->network_buffer_size = param->size;
+                       }
+                       assert( m2ts->network_buffer );
+                       memcpy(m2ts->network_buffer, param->data, param->size);
+                       gf_m2ts_process_data(m2ts->ts, m2ts->network_buffer, param->size);
+               }
 
                /*if asked to regulate, wait until we get a play request*/
-               if (m2ts->ts->run_state && !m2ts->ts->nb_playing && m2ts->ts->file_regulate) {
-                       while (m2ts->ts->run_state && !m2ts->ts->nb_playing && m2ts->ts->file_regulate) {
+               if (m2ts->ts->run_state && !m2ts->ts->nb_playing && (m2ts->ts->file_regulate==1)) {
+                       while (m2ts->ts->run_state && !m2ts->ts->nb_playing && (m2ts->ts->file_regulate==1) ) {
                                gf_sleep(50);
                                continue;
                        }
                } else {
                        gf_sleep(1);
                }
+#if 1 //see commit 3642: crashes when reload quickly with http
                if (!m2ts->ts->run_state) {
                        if (m2ts->ts->dnload) 
                                gf_term_download_del( m2ts->ts->dnload );
                        m2ts->ts->dnload = NULL;
                }
+#endif
 
        } else {
                e = param->error;
@@ -712,12 +730,12 @@ void m2ts_net_io(void *cbk, GF_NETIO_Parameter *param)
                  if (!m2ts->ts_setup) {
                          m2ts->ts_setup = 1;
                  }
-                 GF_LOG( GF_LOG_ERROR, GF_LOG_CONTAINER,("[MPEGTSIn] : Error while getting data : %s\n", gf_error_to_string(e)));
+                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[MPEGTSIn] : Error while getting data : %s\n", gf_error_to_string(e)));
                  gf_term_on_connect(m2ts->service, NULL, e);
        }
 }
 
-static const char *M2TS_QueryNextFile(void *udta)
+static GF_Err M2TS_QueryNextFile(void *udta, Bool query_init, const char **out_url, u64 *out_start_range, u64 *out_end_range)
 {
        GF_NetworkCommand param;
        GF_Err query_ret;
@@ -725,18 +743,25 @@ static const char *M2TS_QueryNextFile(void *udta)
        assert(m2ts->owner);
        assert( m2ts->owner->query_proxy);
 
-       param.command_type = GF_NET_SERVICE_QUERY_NEXT;
+       if (out_url) *out_url = NULL;
+       if (out_start_range) *out_start_range = 0;
+       if (out_end_range) *out_end_range = 0;
+
+       param.command_type = query_init ? GF_NET_SERVICE_QUERY_INIT_RANGE : GF_NET_SERVICE_QUERY_NEXT;
        param.url_query.next_url = NULL;
        query_ret = m2ts->owner->query_proxy(m2ts->owner, &param);
-       if ((query_ret==GF_OK) && param.url_query.next_url){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TS In] Switching to next segment %s\n", param.url_query.next_url));
-               return param.url_query.next_url;
-       } else if (query_ret==GF_OK){
+
+
+       if ((query_ret==GF_OK) && !query_init && !param.url_query.next_url){
                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS In] Cannot query next file: no file provided but no error raised\n"));
+       } else if (query_ret) {
+               GF_LOG((query_ret<0) ? GF_LOG_ERROR : GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TS In] Cannot query next file: error: %s\n", gf_error_to_string(query_ret)));
        } else {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS In] Cannot query next file: error: %s\n", gf_error_to_string(query_ret)));
-       }       
-       return NULL;
+               if (out_url) *out_url = param.url_query.next_url;
+               if (out_start_range) *out_start_range = param.url_query.start_range;
+               if (out_end_range) *out_end_range = param.url_query.end_range;
+       }
+       return query_ret;
 }
 
 
@@ -753,12 +778,17 @@ static GF_Err M2TS_ConnectService(GF_InputService *plug, GF_ClientService *serv,
        opt = gf_modules_get_option((GF_BaseInterface *)m2ts->owner, "HybRadio", "Activated");
        if (opt && !strcmp(opt, "true")) {
                m2ts->hybrid_on = 1;
-       }
+       }       
 
        m2ts->service = serv;
        if (m2ts->owner->query_proxy) {
                m2ts->ts->query_next = M2TS_QueryNextFile;
-               m2ts->ts->udta_query = m2ts;
+               m2ts->ts->query_udta = m2ts;
+       }
+
+       opt = gf_modules_get_option((GF_BaseInterface *)m2ts->owner, "DSMCC", "Activated");
+       if (opt && !strcmp(opt, "true")) {
+               gf_m2ts_demux_dmscc_init(m2ts->ts);
        }
 
        if (!strnicmp(url, "http://", 7)) {
@@ -854,6 +884,7 @@ static GF_Descriptor *M2TS_GetServiceDesc(GF_InputService *plug, u32 expect_type
                        if (prog->pmt_iod) {
                                m2ts->request_all_pids = 0;
                                gf_odf_desc_copy((GF_Descriptor *)prog->pmt_iod, &desc);
+                               ((GF_InitialObjectDescriptor *)desc)->service_ifce = m2ts->owner;
                                return desc;
                        }
                }
@@ -996,11 +1027,15 @@ static GF_Err M2TS_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                /*mark pcr as not initialized*/
                if (pes->program->pcr_pid==pes->pid) pes->program->first_dts=0;
                gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
-               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSIn] Setting default reframing for PID %d\n", pes->pid));
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSIn] Setting default reframing for PID %d\n", pes->pid));
                /*this is a multplex, only trigger the play command for the first stream activated*/
                if (!ts->nb_playing) {
                        ts->start_range = (u32) (com->play.start_range*1000);
                        ts->end_range = (com->play.end_range>0) ? (u32) (com->play.end_range*1000) : 0;
+
+                       if (ts->query_next && ts->file) 
+                               ts->segment_switch = 1;
+
                        /*start demuxer*/
                        if (ts->run_state!=1) {
                                return TSDemux_DemuxPlay(ts);
@@ -1016,8 +1051,6 @@ static GF_Err M2TS_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                        }
                        return GF_STREAM_NOT_FOUND;
                }
-
-               gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);
                /* In case of EOS, we may receive a stop command after no one is playing */
                if (ts->nb_playing)
                  ts->nb_playing--;
@@ -1027,9 +1060,11 @@ static GF_Err M2TS_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                        while (ts->run_state!=2) gf_sleep(2);
                        if (gf_list_count(m2ts->ts->requested_progs)) {
                                ts->file_regulate = 0;
+                               gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);
                                return TSDemux_DemuxPlay(ts);
                        }
                }
+               gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);
                return GF_OK;
        case GF_NET_CHAN_CONFIG:
                pes = M2TS_GetChannel(m2ts, com->base.on_channel);
index 883c17872120513ed0b3a725ba3681050e47a515..b0b2e5bf7987fa512676c914c2271cf80eb1ecbb 100644 (file)
@@ -15,11 +15,11 @@ LDFLAGS+=-pg
 endif
 
 #common obj
-OBJS= opencv.o
+OBJS= opencv_is.o
 
 SRCS := $(OBJS:.o=.c) 
 
-LDFLAGS+=-lcv -lcvaux -lhighgui -lcxcore
+EXTRALIBS+=-lcv -lcvaux -lhighgui -lcxcore
 
 LIB=gm_opencv.$(DYN_LIB_SUFFIX)
 ifeq ($(CONFIG_WIN32),yes)
index dec8bf2b3358da977bb7be65c7127a5330e53b6e..fa9e92383b44def417d671c66e50820ddb38f4af 100644 (file)
@@ -2,7 +2,7 @@ include ../../config.mak
 
 vpath %.c $(SRC_PATH)/modules/opensvc_dec
 
-CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include"
+CFLAGS=$(OPTFLAGS) -I"$(SRC_PATH)/include" $(OSVC_CFLAGS)
 
 ifeq ($(DEBUGBUILD), yes)
 CFLAGS+=-g
@@ -14,7 +14,7 @@ CFLAGS+=-pg
 LDFLAGS+=-pg
 endif
 
-LDFLAGS+=-lOpenSVCDec
+EXTRALIBS+=-L../../bin/gcc -lgpac $(OSVC_LDFLAGS)
 
 #common obj
 OBJS= opensvc_dec.o
@@ -28,11 +28,7 @@ all: $(LIB)
 
 
 $(LIB): $(OBJS)
-       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac
-ifeq ($(STATICBUILD),yes)
-       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_opensvc_dec-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static
-endif
-
+       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS)
 
 %.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $< 
index 20639f73c5f14f4df3c943e71ef1769cf577aa6e..02a12e75482aebb97262283e934740cfd398a2c2 100644 (file)
 #  pragma comment(lib, "OpenSVCDecoder")
 #endif
 
-typedef struct{
-       int Width;
-       int Height;
-       unsigned char* pY[1];
-       unsigned char* pU[1]; 
-       unsigned char* pV[1];
-} OPENSVCFRAME;
-
-
-enum {
-       SVC_STATUS_ERROR        = -1,
-       SVC_STATUS_OK       = 0,        // no error and no frame ready
-       SVC_IMAGE_READY     = 1,        // no error and image ready
-       SVC_GHOST_IMAGE         = 2             // no image for chosen layer but image could be ready for other layers
-};
-
-int SVCDecoder_init(void **PlayerStruct);
-int SVCDecoder_close(void *PlayerStruct);
-//TODO
-int decodeNAL(void *PlayerStruct, unsigned char* nal, int nal_length, OPENSVCFRAME *Frame, int *LayerCommand); 
-/*ID vient du NAL type 14 et 20*/
-//TODO
-void SetCommandLayer(int *Command, int DqIdMax, int CurrDqId, int *TemporalCom, int TemporalId);
-void ParseAuPlayers(void *PlayerStruct, const unsigned char *buf, int buf_size, int nal_length_size, int is_avc);
-int GetDqIdMax(const unsigned char *buf, int buf_size, int nal_length_size, int *DqidTable, int is_avc);
-
+#include <OpenSVCDecoder/SVCDecoder_ietr_api.h>
+#include <OpenSVCDecoder/ParseAU.h>
 
 typedef struct
 {
@@ -205,15 +181,11 @@ static GF_Err OSVC_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capa
        switch (capability.CapCode) {
        case GF_CODEC_MEDIA_SWITCH_QUALITY:
                if (capability.cap.valueInt) {
-                       if (ctx->layer<32) {
-                               ctx->layer += 8;
-                               ctx->CurrDqId = ctx->layer;
-                       }
+                       // set layer up (command=1)
+                       UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 1 );
                } else {
-                       if (ctx->layer>=8) {
-                               ctx->layer -= 8;
-                ctx->CurrDqId = ctx->layer;
-                       }
+                       // set layer down (command=0)
+                       UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 0 );
                }
                return GF_OK;
        }
index 40c2cfc52dc2aab9b50218f177b9a410b88a591e..74913f8920e76f3a069d85e4f61a6fcbe3c1be28 100644 (file)
@@ -179,8 +179,9 @@ Bool osd_load_scene(GF_OSD *osd)
 }\r
 \r
 \r
-Bool osd_on_event_play(GF_OSD*osd , GF_Event *event, Bool consumed_by_compositor)\r
+Bool osd_on_event_play(void *udta, GF_Event *event, Bool consumed_by_compositor)\r
 {\r
+       GF_OSD* osd = (GF_OSD*)udta;\r
        switch (event->type) {\r
        case GF_EVENT_SCENE_SIZE:\r
                gf_sg_set_scene_size_info(osd->odm->subscene->graph, event->size.width, event->size.height, 1);\r
@@ -239,8 +240,8 @@ static Bool osd_process(GF_TermExt *termext, u32 action, void *param)
 \r
        case GF_TERM_EXT_PROCESS:\r
                /*flush all events until current time if reached*/\r
-               if (gf_sys_get_rti(osd->refresh_time_ms, &osd->rti, 0)) {\r
-                       sprintf(osd->statBuffer, "CPU %02d - FPS %02.2f - MEM %d KB", osd->rti.process_cpu_usage, gf_sc_get_fps(osd->term->compositor, 0), osd->rti.process_memory/1000);\r
+               if ((osd->visible->whichChoice==0) && gf_sys_get_rti(osd->refresh_time_ms, &osd->rti, 0)) {\r
+                       sprintf(osd->statBuffer, "CPU %02d - FPS %02.2f - MEM "LLU" KB", osd->rti.process_cpu_usage, gf_sc_get_fps(osd->term->compositor, 0), osd->rti.process_memory/1000);\r
                        gf_node_dirty_set((GF_Node *) osd->text, GF_SG_NODE_DIRTY, 1);\r
                }\r
                break;\r
index 8b55958a6593d0064e0936295984cd84895dfb1a..cdc337dc67943b1797c5f526d0eef03396ff9561 100644 (file)
@@ -466,7 +466,7 @@ void GPAC_FileMediaServer::ShareVirtualResource(const char *res_uri, const char
        if (sep) {
                sep = strchr(sep+3, '/');
                if (sep) uri = sep;
-               else uri="/";
+               else uri = (char*)"/";
        }
        the_uri = "";
        while (1) {
index 6431d7ea6f376e7212e172445dae13b80631a7fd..e1286a21b48eaa1def0701810c83081e7d361d15 100644 (file)
@@ -64,10 +64,12 @@ GF_UPnP::~GF_UPnP()
 #endif
 }
 
+#ifdef GPAC_HAS_SPIDERMONKEY
 void GF_UPnP::LockJavascript(Bool do_lock)
 {
        gf_sg_lock_javascript(m_pJSCtx, do_lock);
 }
+#endif
 
 void GF_UPnP::OnStop(const char *src_url)
 {
@@ -218,8 +220,8 @@ void GF_UPnP::onTimeChanged(s32 renderer_idx, Double time)
                        JS_CallFunctionValue(m_pJSCtx, m_pObj, funval, 2, argv, &rval);
                }
                LockJavascript(0);
-       }
 #endif
+       }
 }
 
 void GF_UPnP::onDurationChanged(s32 renderer_idx, Double dur)
@@ -237,8 +239,8 @@ void GF_UPnP::onDurationChanged(s32 renderer_idx, Double dur)
                        JS_CallFunctionValue(m_pJSCtx, m_pObj, funval, 2, argv, &rval);
                }
                LockJavascript(0);
-       }
 #endif
+       }
 }
 
 
@@ -547,6 +549,7 @@ static JSBool upnpdevice_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETT
        return JS_TRUE;
 }
 
+#ifdef GPAC_UNUSED_FUNC
 static JSBool upnp_device_subscribe(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     PLT_Service* service;
@@ -564,6 +567,8 @@ static JSBool upnp_device_subscribe(JSContext *c, JSObject *obj, uintN argc, jsv
        SMJS_FREE(c, service_uuid);
        return JS_TRUE;
 }
+#endif
+
 static JSBool SMJS_FUNCTION(upnp_device_find_service)
 {
        char *service_uuid;
@@ -835,7 +840,6 @@ static JSBool SMJS_FUNCTION(upnp_renderer_open)
                        NPT_String objID = item;
 
                        // look back for the PLT_MediaItem in the results
-                       PLT_MediaObject* track = NULL;
                        NPT_List<PLT_MediaObject*>::Iterator item = server->m_BrowseResults->GetFirstItem();
                        while (item) {
                                if ((*item)->m_ObjectID == objID) {
@@ -970,9 +974,9 @@ static JSBool SMJS_FUNCTION(upnp_server_browse)
        _dir = _filter = NULL;
 
        dir = _dir = SMJS_CHARS(c, argv[0]);
-       if (!dir) dir = "0";
+       if (!dir) dir = (char*)"0";
        filter = _filter = SMJS_CHARS(c, argv[1]);
-       if (!filter) filter = "*";
+       if (!filter) filter = (char*)"*";
 
        PLT_Service* service;
        if (NPT_SUCCEEDED(server->m_device->FindServiceByType("urn:schemas-upnp-org:service:ContentDirectory:1", service))) {
@@ -1324,6 +1328,7 @@ static JSBool SMJS_FUNCTION(upnp_device_start)
        return JS_TRUE;
 }
 
+#ifdef GPAC_UNUSED_FUNC
 static JSBool SMJS_FUNCTION(upnp_device_stop)
 {
        SMJS_OBJ
@@ -1335,7 +1340,7 @@ static JSBool SMJS_FUNCTION(upnp_device_stop)
 
        return JS_TRUE;
 }
-
+#endif
 
 static GPAC_GenericDevice *upnp_create_generic_device(GF_UPnP *upnp, JSObject*global, const char *id, const char *name)
 {
@@ -1574,15 +1579,20 @@ static Bool upnp_process(GF_TermExt *termext, u32 action, void *param)
                        u32 now;
                        now = gf_sys_clock() - upnp->upnp_init_time;
                        if (now - upnp->last_time > 200) {
-                               u32 i, count; 
+                               u32 i, count, arg_set
                                jsval argv[1], rval;
                                upnp->LockJavascript(1);
-                               argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(upnp->m_pJSCtx, (Double)now / 1000.0) );
+                               arg_set = 0;
                                count = gf_list_count(upnp->m_Devices);
                                for (i=0; i<count; i++) {
                                        GPAC_GenericDevice *device = (GPAC_GenericDevice *)gf_list_get(upnp->m_Devices, i);
-                                       if (device->run_proc)
+                                       if (device->run_proc) {
+                                               if (!arg_set) {
+                                                       argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(upnp->m_pJSCtx, (Double)now / 1000.0) );
+                                                       arg_set = 1;
+                                               }
                                                JS_CallFunctionValue(upnp->m_pJSCtx, device->obj, device->run_proc, 1, argv, &rval);
+                                       }
                                }
                                upnp->LockJavascript(0);
                                upnp->last_time = now;
index 58ac6923242b2644f68ccd519890306ba4ef88e0..bb32dcc3f0d7ee4aa6ec90949f269188ca27da9e 100644 (file)
@@ -212,13 +212,14 @@ static JSBool SMJS_FUNCTION(upnp_service_set_action_listener)
        i=0;
        while ((argl = (GPAC_ActionArgListener *)gf_list_enum(service->m_ArgListeners, &i))) {
                if (argl->arg == desc) break;
+               argl = NULL;
        }
        if (!argl) {
                argl = new GPAC_ActionArgListener();
                argl->arg = desc;
-               argl->action = action;
                gf_list_add(service->m_ArgListeners, argl);
        }
+       argl->action = action;
        if (argl->on_event) gf_js_remove_root(c, &argl->on_event, GF_JSGC_VAL);
        if (JSVAL_IS_NULL(argv[1])) {
                gf_list_del_item(service->m_ArgListeners, argl);
@@ -294,7 +295,6 @@ static JSBool SMJS_FUNCTION(upnp_service_has_action)
 
 static JSBool SMJS_FUNCTION(upnp_service_call_action)
 {
-       u32 i=1;
        GPAC_ActionUDTA *act_udta = NULL;
        char *action_name = NULL;
        SMJS_OBJ
@@ -303,13 +303,13 @@ static JSBool SMJS_FUNCTION(upnp_service_call_action)
        if (!service || !argc || !JSVAL_IS_STRING(argv[0]) ) return JS_FALSE;
 
        action_name = SMJS_CHARS(c, argv[0]);
-    PLT_ActionDesc* action_desc = service->m_service->FindActionDesc(action_name);
+       PLT_ActionDesc* action_desc = service->m_service->FindActionDesc(action_name);
        SMJS_FREE(c, action_name);
 
        if (action_desc == NULL) return JS_FALSE;
-    PLT_ActionReference action;
+       PLT_ActionReference action;
 
-    NPT_CHECK_SEVERE(
+       NPT_CHECK_SEVERE(
                service->m_device->m_pUPnP->m_pGenericController->m_CtrlPoint->CreateAction(
                        service->m_device->m_device, 
                        service->m_service->GetServiceType(), 
@@ -335,7 +335,7 @@ static JSBool SMJS_FUNCTION(upnp_service_call_action)
 
                        JS_GetElement(c, list, (jsint) i+1, &an_arg);
 
-                       param_val = "";
+                       param_val = (char*)"";
                        if (JSVAL_IS_STRING(an_arg)) {
                                param_val = _param_val = SMJS_CHARS(c, an_arg);
                        } else if (JSVAL_IS_BOOLEAN(an_arg)) {
@@ -506,7 +506,6 @@ static JSBool SMJS_FUNCTION(upnp_action_get_argument_value)
 static JSBool SMJS_FUNCTION(upnp_action_get_error_code)
 {
        NPT_String res;
-       char *arg_name = NULL;
        SMJS_OBJ
        PLT_Action *action = (PLT_Action *) JS_GetPrivate(c, obj);
        if (!action ) return JS_FALSE;
@@ -518,7 +517,6 @@ static JSBool SMJS_FUNCTION(upnp_action_get_error)
 {
        NPT_String res;
        unsigned int code;
-       char *arg_name = NULL;
        SMJS_OBJ
        PLT_Action *action = (PLT_Action *) JS_GetPrivate(c, obj);
        if (!action ) return JS_FALSE;
@@ -847,7 +845,6 @@ static JSBool SMJS_FUNCTION(upnp_action_get_argument)
 
 static JSBool SMJS_FUNCTION(upnp_action_send_reply)
 {
-       u32 i=1;
        SMJS_OBJ
        SMJS_ARGS
        GPAC_GenericDevice *device = (GPAC_GenericDevice *)JS_GetPrivate(c, obj);
@@ -870,7 +867,7 @@ static JSBool SMJS_FUNCTION(upnp_action_send_reply)
 
                        JS_GetElement(c, list, (jsint) i+1, &an_arg);
 
-                       param_val = "";
+                       param_val = (char*)"";
                        if (JSVAL_IS_STRING(an_arg)) {
                                param_val = _param_val = SMJS_CHARS(c, an_arg);
                        } else if (JSVAL_IS_BOOLEAN(an_arg)) {
@@ -916,10 +913,14 @@ GPAC_GenericDevice::OnAction(PLT_ActionReference&          action,
 {
     NPT_COMPILER_UNUSED(context);
 
+#ifdef GPAC_HAS_SPIDERMONKEY
        gf_mx_p(m_pMutex);
+#endif
        PLT_ActionDesc &act_desc = action->GetActionDesc();
         NPT_String name = act_desc.GetName();
+#ifdef GPAC_HAS_SPIDERMONKEY
        assert(!m_pSema);
+#endif
        GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[UPnP] Action %s called (thread %d)\n", (char *) name, gf_th_id() ));
        
 #ifdef GPAC_HAS_SPIDERMONKEY
index 0c7f15c8790e9382ef09b897bd9782b065826dc3..b89a490454b186b56da5dab137818872cc09b47d 100644 (file)
@@ -165,7 +165,7 @@ static Bool audio_encoding_thread_run(void *param)
     while (avr->is_running) {
         u32 readen;
         if (U32_ABS(avr->audioCurrentTime, myTime) > 25000) {
-            //GF_LOG( GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] Drift in audio : audioCurrentTime = %u, myTime=%u, resync...\n", avr->audioCurrentTime, myTime));
+            //GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] Drift in audio : audioCurrentTime = %u, myTime=%u, resync...\n", avr->audioCurrentTime, myTime));
             //myTime = lastCurrentTime = avr->audioCurrentTime;
             //frameCountSinceReset = 0;
             sendPts = 1;
@@ -188,7 +188,7 @@ static Bool audio_encoding_thread_run(void *param)
                     ts_encode_audio_frame(avr->ts_implementation, outBuff, encoded, sendPts ? myTime : AV_NOPTS_VALUE );
                     frameCountSinceReset++;
 #ifdef DUMP_MP3
-                    fwrite( outBuff, sizeof(char), encoded, mp3);
+                    gf_fwrite( outBuff, sizeof(char), encoded, mp3);
 #endif /* DUMP_MP3 */
                     //if (ctx->codec->id == CODEC_ID_MP3) {
                     /* It seems the MP3 codec only fetches 50% of data... */
@@ -271,7 +271,7 @@ static Bool video_encoding_thread_run(void *param)
 #ifdef AVR_DUMP_RAW_AVI
                 if ( AVI_write_frame ( avr->avi_out, avr->frame, avr->size, 1 ) <0 )
                 {
-                    GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error writing video frame\n" ) );
+                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error writing video frame\n" ) );
                 }
 #endif /* AVR_DUMP_RAW_AVI */
                 gf_mx_v(avr->frameMutex);
@@ -285,7 +285,7 @@ static Bool video_encoding_thread_run(void *param)
                     //ctx->coded_frame->pts = currentFrameTimeProcessed;
                     if ( written < 0 )
                     {
-                        GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while encoding video frame =%d\n", written ) );
+                        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while encoding video frame =%d\n", written ) );
                     } else
                         if ( written > 0 )
                         {
@@ -329,7 +329,7 @@ static Bool start_if_needed(GF_AVRedirect *avr) {
     if ( !avr->avi_out )
     {
         gf_mx_v(avr->frameMutex);
-        GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error opening output AVI file\n" ) );
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error opening output AVI file\n" ) );
         return 4;
     }
 #endif /* AVR_DUMP_RAW_AVI */
@@ -345,14 +345,14 @@ static Bool start_if_needed(GF_AVRedirect *avr) {
         if ( !avr->audioCodec)
         {
             gf_mx_v(avr->frameMutex);
-            GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Cannot find audio codec.\n" ) );
+            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Cannot find audio codec.\n" ) );
             return 1;
         }
 #endif
 
         if ( !avr->videoCodec )
         {
-            GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Cannot find video codec.\n" ) );
+            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Cannot find video codec.\n" ) );
             return 2;
         }
 
@@ -378,7 +378,7 @@ static Bool start_if_needed(GF_AVRedirect *avr) {
         memset ( avr->videoOutbuf, 0, avr->videoOutbufSize );
     }
 #ifdef AVR_DUMP_RAW_AVI
-    GF_LOG ( GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Open output AVI file %s\n", "dump.avi" ) );
+    GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Open output AVI file %s\n", "dump.avi" ) );
 #endif /* AVR_DUMP_RAW_AVI */
     /* Setting up the TS mux */
     {
@@ -400,7 +400,7 @@ static Bool start_if_needed(GF_AVRedirect *avr) {
     /*
         if ( e )
         {
-            GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while initializing UDP address %s\n", gf_error_to_string ( e ) ) );
+            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while initializing UDP address %s\n", gf_error_to_string ( e ) ) );
             return e;
         }
     */
@@ -466,7 +466,7 @@ static void avr_on_video_frame ( void *udta, u32 time )
     e = gf_sc_get_screen_buffer ( avr->term->compositor, &fb, 0 );
     if ( e )
     {
-        GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error grabing frame buffer %s\n", gf_error_to_string ( e ) ) );
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error grabing frame buffer %s\n", gf_error_to_string ( e ) ) );
         return;
     }
     /*convert frame*/
@@ -486,7 +486,7 @@ static void avr_on_video_frame ( void *udta, u32 time )
     avr->frameTime = time;
     gf_mx_v(avr->frameMutex);
     gf_sc_release_screen_buffer ( avr->term->compositor, &fb );
-    GF_LOG ( GF_LOG_DEBUG, GF_LOG_MODULE, ( "[AVRedirect] Writing video frame\n" ) );
+    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ( "[AVRedirect] Writing video frame\n" ) );
 }
 
 static void avr_on_video_reconfig ( void *udta, u32 width, u32 height )
@@ -501,7 +501,7 @@ static void avr_on_video_reconfig ( void *udta, u32 width, u32 height )
         comp[0] = comp[1] = comp[2] = comp[3] = comp[4] = 0;
         AVI_set_video ( avr->avi_out, width, height, 30, comp );
 #endif /* AVR_DUMP_RAW_AVI */
-        GF_LOG ( GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Video reconfig width %d height %d\n", width, height ) );
+        GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Video reconfig width %d height %d\n", width, height ) );
         gf_mx_p(avr->frameMutex);
         if ( avr->frame ) gf_free ( avr->frame );
         avr->size = 3*width*height;
@@ -558,7 +558,7 @@ static void avr_close ( GF_AVRedirect *avr )
     if ( !avr->is_open ) return;
     avr->is_open = 0;
 #ifdef AVR_DUMP_RAW_AVI
-    GF_LOG ( GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Closing output AVI file\n" ) );
+    GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ( "[AVRedirect] Closing output AVI file\n" ) );
     AVI_close ( avr->avi_out );
     avr->avi_out = NULL;
 #endif /* AVR_DUMP_RAW_AVI */
@@ -660,7 +660,7 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param )
             }
             else
             {
-                GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Not a known Video codec : %s, using MPEG-2 video instead, %s\n", opt, possibleCodecs ) );
+                GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Not a known Video codec : %s, using MPEG-2 video instead, %s\n", opt, possibleCodecs ) );
                 avr->videoCodec = avcodec_find_encoder ( CODEC_ID_MPEG2VIDEO );
             }
         }
@@ -672,7 +672,7 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param )
                 if (!opt) {
                     gf_modules_set_option ( ( GF_BaseInterface* ) termext, moduleName, AVR_UDP_ADDRESS_OPTION, DEFAULT_UDP_OUT_ADDRESS);
                     avr->udp_address = DEFAULT_UDP_OUT_ADDRESS;
-                    GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s not set, using %s\n", AVR_UDP_ADDRESS_OPTION, DEFAULT_UDP_OUT_ADDRESS ) );
+                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s not set, using %s\n", AVR_UDP_ADDRESS_OPTION, DEFAULT_UDP_OUT_ADDRESS ) );
                 } else
                     avr->udp_address = opt;
                 opt = gf_modules_get_option ( ( GF_BaseInterface* ) termext, moduleName, AVR_UDP_PORT_OPTION);
@@ -687,7 +687,7 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param )
                 }
                 if (!opt) {
                     gf_modules_set_option ( ( GF_BaseInterface* ) termext, moduleName, AVR_UDP_PORT_OPTION, DEFAULT_UDP_OUT_PORT_STR);
-                    GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s is not set or valid, using %s\n", AVR_UDP_PORT_OPTION, DEFAULT_UDP_OUT_PORT_STR ) );
+                    GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s is not set or valid, using %s\n", AVR_UDP_PORT_OPTION, DEFAULT_UDP_OUT_PORT_STR ) );
                     avr->udp_port = DEFAULT_UDP_OUT_PORT;
                 }
         */
@@ -695,7 +695,7 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param )
         if (!opt) {
             gf_modules_set_option ( ( GF_BaseInterface* ) termext, moduleName, AVR_DESTINATION, AVR_DEFAULT_DESTINATION);
             avr->destination = AVR_DEFAULT_DESTINATION;
-            GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s not set, using %s\n", AVR_DESTINATION, AVR_DEFAULT_DESTINATION ) );
+            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] %s not set, using %s\n", AVR_DESTINATION, AVR_DEFAULT_DESTINATION ) );
         } else
             avr->destination = opt;
         avr->audio_listen.udta = avr;
index f68801927152c81cb3f0f49dae6545aa9a3fe2c5..2f67cf9b71a4eb4d6eb369708cd43992e39f0e6f 100644 (file)
@@ -361,7 +361,7 @@ void RP_RemoveStream(RTPClient *rtp, RTPStream *ch)
 void RP_ResetSession(RTSPSession *sess, GF_Err e)
 {
        GF_RTSPCommand *com;
-       u32 first = 1;
+       //u32 first = 1;
 
        //destroy command list
        while (gf_list_count(sess->rtsp_commands)) {
@@ -370,7 +370,7 @@ void RP_ResetSession(RTSPSession *sess, GF_Err e)
                //this destroys stacks if any
 //             RP_SendFailure(sess, com, first ? e : GF_OK);
                gf_rtsp_command_del(com);
-               first = 0;
+               //first = 0;
        }
        /*reset session state*/ 
        gf_rtsp_session_reset(sess->session, 1);
index 6551d6fde81381444cc9c95dd17ac25e526c5071..ec61e42cea0ed6c042f1154e9ae818747f0bbeb3 100644 (file)
@@ -148,7 +148,6 @@ void SDP_NetIO(void *cbk, GF_NETIO_Parameter *param)
 
 void RP_FetchSDP(RTPClient *rtp, char *url, RTPStream *stream, char *original_url)
 {
-       u32 flags = 0;
        SDPFetch *sdp;
        /*if local URL get file*/
        if (strstr(url, "data:application/sdp")) {
@@ -174,8 +173,13 @@ void RP_FetchSDP(RTPClient *rtp, char *url, RTPStream *stream, char *original_ur
        rtp->dnload = NULL;
 
        rtp->sdp_temp = sdp;
-       rtp->dnload = gf_term_download_new(rtp->service, url, flags, SDP_NetIO, rtp);
-       if (!rtp->dnload) gf_term_on_connect(rtp->service, NULL, GF_NOT_SUPPORTED);
+       rtp->dnload = gf_term_download_new(rtp->service, url, 0, SDP_NetIO, rtp);
+       if (!rtp->dnload) {
+               gf_term_on_connect(rtp->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(rtp->dnload);
+       }
        /*service confirm is done once fetched*/
 }
 
index 7d691d4e908b4a4cc176fbfdc09f0aae0ddf84e4..6cb2a5c94997a534e11fd2c3f965706c02814e97 100644 (file)
@@ -352,10 +352,8 @@ void RP_LoadSDP(RTPClient *rtp, char *sdp_text, u32 sdp_len, RTPStream *stream)
 
 void MigrateSDP_NetIO(void *cbk, GF_NETIO_Parameter *param)
 {
-       GF_Err e;
        RTPClient *rtp = (RTPClient *)cbk;
 
-       e = param->error;
        switch (param->msg_type) {
        case GF_NETIO_GET_METHOD:
                param->name = "POST";
@@ -513,7 +511,7 @@ void RP_SaveSessionState(RTPClient *rtp)
                        FILE *f = gf_f64_open(opt, "wt");
                        if (f) {
                                sdp_buf = rtp->session_state_data + strlen("data:application/sdp,");
-                               fwrite(sdp_buf, 1, strlen(sdp_buf), f);
+                               gf_fwrite(sdp_buf, 1, strlen(sdp_buf), f);
                                fclose(f);
                        } else {
                                e = GF_IO_ERR;
index 008d85f565d436439bd7334085b7417f4e1c5de0..b28709b2b9eece5f4f5e0437bf28538aefb98ccf 100644 (file)
@@ -14,7 +14,7 @@ CFLAGS+=-pg
 LDFLAGS+=-pg
 endif
 
-LDFLAGS+=-lRVCDecoder
+EXTRALIBS+=-lRVCDecoder
 
 #common obj
 OBJS= rvc_dec.o
index cb7c8ce56c7658b3b446581ddc65e343549731d7..3649c02dee992e0e195e685a7926381cca85466b 100644 (file)
@@ -98,7 +98,7 @@ static GF_Err RVCD_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
                FILE *f;\r
                u32 size;\r
                sprintf(opt, "Predefined_%d", esd->decoderConfig->predefined_rvc_config);\r
-               path = gf_modules_get_option((GF_BaseInterface *)ifcg, "RVCDecoder", (const char *)opt);\r
+               path = (char *) gf_modules_get_option((GF_BaseInterface *)ifcg, "RVCDecoder", (const char *)opt);\r
                if (!opt) return GF_NOT_SUPPORTED;\r
                f = fopen(path, "rt");\r
                if (!f) return GF_NOT_SUPPORTED;\r
index ce0e082981e95323d92acb5beb73718c8ff0af82..bfbccc9ceed40ad62db38531947714d4513b40c8 100644 (file)
@@ -332,6 +332,9 @@ static void SAF_DownloadFile(GF_InputService *plug, char *url)
        if (!read->dnload) {
                read->needs_connection = 0;
                gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(read->dnload);
        }
        /*service confirm is done once fetched*/
 }
@@ -426,7 +429,7 @@ static GF_Err SAF_CloseService(GF_InputService *plug)
        if (read->th) {
                if (read->run_state == 1) {
                        read->run_state=0;
-                       while (read->run_state!=2) gf_sleep(0);
+                       while (read->run_state!=2) gf_sleep(2);
                }
                gf_th_del(read->th);
                read->th = NULL;
index 0d4da20cab50365e27f0e904c21130455c07c465..826ea1d7175cb5256091402865d7537ef7034f57 100644 (file)
@@ -384,8 +384,9 @@ static void sdl_translate_key(u32 SDLkey, GF_EventKey *evt)
                        
        default:
                if ((SDLkey>=0x30) && (SDLkey<=0x39))  evt->key_code = GF_KEY_0 + SDLkey-0x30;
-               else if ((SDLkey>=0x41) && (SDLkey<=0x5A))  evt->key_code = GF_KEY_A + SDLkey-0x51;
-               else
+               else if ((SDLkey>=0x41) && (SDLkey<=0x5A))  evt->key_code = GF_KEY_A + SDLkey-0x41;
+               else if ((SDLkey>=0x61) && (SDLkey<=0x7A))  evt->key_code = GF_KEY_A + SDLkey-0x61;
+               else    
                {
                        evt->key_code = GF_KEY_UNIDENTIFIED;
                }
@@ -474,6 +475,7 @@ GF_Err SDLVid_ResizeWindow(GF_VideoOutput *dr, u32 width, u32 height)
                assert(ctx->screen);
                ctx->width = width;
                ctx->height = height;
+               memset(&evt, 0, sizeof(GF_Event));
                evt.type = GF_EVENT_VIDEO_SETUP;
                dr->on_event(dr->evt_cbk_hdl, &evt);            
        } else {
@@ -832,6 +834,7 @@ GF_Err SDLVid_SetFullScreen(GF_VideoOutput *dr, u32 bFullScreenOn, u32 *screen_w
                /*GL has changed*/
                if (ctx->output_3d_type==1) {
                        GF_Event evt;
+                       memset(&evt, 0, sizeof(GF_Event));
                        evt.type = GF_EVENT_VIDEO_SETUP;
                        dr->on_event(dr->evt_cbk_hdl, &evt);
                }
@@ -1122,6 +1125,39 @@ static void copy_yuv(u8 *pYD, u8 *pVD, u8 *pUD, u32 pixel_format , u32 pitch_y,
                memcpy(pYD, pY, sizeof(unsigned char)*src_width*src_height);
                memcpy(pVD, pV, sizeof(unsigned char)*src_width*src_height/4);
                memcpy(pUD, pU, sizeof(unsigned char)*src_width*src_height/4);
+       } else if (src_pf==GF_PIXEL_YUY2){
+               u32 i, j;
+               unsigned char *dst_y, *dst_u, *dst_v;
+
+               pY = src + src_stride * src_wnd->y + src_wnd->x;
+               pU = src + src_stride * src_wnd->y + src_wnd->x + 1;
+               pV = src + src_stride * src_wnd->y + src_wnd->x + 3;
+
+
+               dst_y = pYD;
+               dst_v = pVD;
+               dst_u = pUD;
+               for (i=0; i<src_wnd->h; i++) {
+                       for (j=0; j<src_wnd->w; j+=2) {
+                               *dst_y = * pY;
+                               *(dst_y+1) = * (pY+2);
+                               dst_y += 2;
+                               pY += 4;
+                               if (i%2) continue;
+
+                               *dst_u = (*pU + *(pU + src_stride)) / 2;
+                               *dst_v = (*pV + *(pV + src_stride)) / 2;
+                               dst_u++;
+                               dst_v++;
+                               pU += 4;
+                               pV += 4;
+                       }
+                       if (i%2) {
+                               pU += src_stride;
+                               pV += src_stride;
+                       }
+               }
+
        } else {
                u32 i;
                unsigned char *dst, *src, *dst2, *src2, *dst3, *src3;
index b49f2c3db11d072a69d1fd056f625d7384fea792..5e769f0011bbc20a5c23c5d8369a32bc98ed67a2 100644 (file)
@@ -364,7 +364,7 @@ static GFINLINE void gray_render_line(TRaster *raster, TPos  to_x, TPos  to_y, i
        }
        /* vertical line - avoid calling gray_render_scanline */
        incr = 1;
-       if ( dx == 0 ) {
+       if (dx == 0 ) {
                TCoord  ex     = TRUNC( raster->x );
                TCoord  two_fx = (TCoord)( ( raster->x - SUBPIXELS( ex ) ) << 1 );
                TPos    area;
@@ -458,14 +458,12 @@ End:
  
 static int EVG_Outline_Decompose(EVG_Outline *outline, TRaster *user)
 {
-       EVG_Vector   v_last;
        EVG_Vector   v_start;
        EVG_Vector*  point;
        EVG_Vector*  limit;
        char*       tags;
        int   n;         /* index of contour in outline     */
        int   first;     /* index of first point in contour */
-       char  tag;       /* current point's state           */
 #ifdef INLINE_POINT_CONVERSION
        TPos _x, _y;
 #endif
@@ -475,13 +473,9 @@ static int EVG_Outline_Decompose(EVG_Outline *outline, TRaster *user)
                int  last;  /* index of last point in contour */
                last  = outline->contours[n];
                limit = outline->points + last;
-               
                v_start = outline->points[first];
-               v_last  = outline->points[last];
-
                point = outline->points + first;
                tags  = (char*) outline->tags  + first;
-               tag   = tags[0];
                gray_move_to(&v_start, user);
                while ( point < limit ) {
                        point++;
index 1fa4dae41fa3296dc318c3b057dc8fca1a5472c4..34d128f6486cc2714f3926943bb437753cd23569 100644 (file)
@@ -126,8 +126,6 @@ struct _evg_surface
        /*color buffer for variable stencils - size of width*/
        u32 *stencil_pix_run;
 
-       /*aliasing flag (on/off only)*/
-       u8 AALevel;
        /*default texture filter level*/
        u32 texture_filter;
 
index 836cb6f20b56d3667a345de8a1bd9a3ca1fd63cf..7e8f9964d62d8f8b9183c6ebcd365c793464db7e 100644 (file)
@@ -95,12 +95,10 @@ void evg_565_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        register s32 i;
        u32 len;
        s32 x;
-       u8 aa_lev = surf->AALevel;
 
        col_no_a = col&0x00FFFFFF;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                x = spans[i].x * surf->pitch_x;
                len = spans[i].len;
                if (spans[i].coverage != 0xFF) {
@@ -122,12 +120,10 @@ void evg_565_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u32 col = surf->fill_col;
        register u32 a, fin, col_no_a;
        register s32 i;
-       u8 aa_lev = surf->AALevel;
 
        a = (col>>24)&0xFF;
        col_no_a = col&0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_565_const_run(fin, (u16*) (dst + spans[i].x * surf->pitch_x), surf->pitch_x, spans[i].len);
@@ -142,10 +138,8 @@ void evg_565_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        register s32 i, x;
        register u32 len;
        register u32 *col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
                surf->sten->fill_run(surf->sten, surf, spans[i].x, y, len);
index a0b37e30629ed97877cad0acc4b09a35d745b618..f3ab03d3e1d0309c7324347286f26c3104d58020 100644 (file)
@@ -99,7 +99,6 @@ void evg_bgra_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i, x;
        u32 len;
        u8 col_a, col_r, col_g, col_b;
-       u8 aa_lev = surf->AALevel;
 
        col_a = GF_COL_A(col);
        col_r = GF_COL_R(col);
@@ -107,7 +106,6 @@ void evg_bgra_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        col_b = GF_COL_B(col);
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                x = spans[i].x * surf->pitch_x;
                len = spans[i].len;
        
@@ -132,13 +130,11 @@ void evg_bgra_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 *dst = surf->pixels + y * surf->pitch_y;
        u32 col = surf->fill_col;
        u32 a, fin, col_no_a;
-       u8 aa_lev = surf->AALevel;
        s32 i;
 
        a = (col>>24)&0xFF;
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_bgra_const_run(fin, dst + surf->pitch_x*spans[i].x, surf->pitch_x, spans[i].len);
@@ -153,10 +149,8 @@ void evg_bgra_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i, x;
        u32 len;
        u32 *col, _col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
                surf->sten->fill_run(surf->sten, surf, spans[i].x, y, len);
@@ -275,7 +269,6 @@ void evg_bgrx_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 *dst = surf->pixels + y * surf->pitch_y;
        s32 i, x;
        u32 len;
-       u8 aa_lev = surf->AALevel;
 
        col_no_a = col & 0x00FFFFFF;
        col_r = GF_COL_R(col);
@@ -283,7 +276,6 @@ void evg_bgrx_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        col_b = GF_COL_B(col);
        for (i=0; i<count; i++) {
                spana = spans[i].coverage;
-               if (spana<aa_lev) continue;
                x = spans[i].x * surf->pitch_x;
                len = spans[i].len;
 
@@ -307,13 +299,11 @@ void evg_bgrx_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 *dst = surf->pixels + y * surf->pitch_y;
        u32 col = surf->fill_col;
        u32 a, fin, col_no_a;
-       u8 aa_lev = surf->AALevel;
        s32 i;
 
        a = (col>>24)&0xFF;
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_bgrx_const_run(fin, dst + surf->pitch_x*spans[i].x, surf->pitch_x, spans[i].len);
@@ -328,10 +318,8 @@ void evg_bgrx_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i, x;
        u32 len;
        u32 *col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
                surf->sten->fill_run(surf->sten, surf, spans[i].x, y, len);
@@ -403,7 +391,6 @@ void evg_rgbx_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 r, g, b;
        s32 i, x;
        u32 len;
-       u8 aa_lev = surf->AALevel;
 
        col_no_a = col & 0x00FFFFFF;
        r = GF_COL_R(col);
@@ -412,7 +399,6 @@ void evg_rgbx_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 
        for (i=0; i<count; i++) {
                spana = spans[i].coverage;
-               if (spana<aa_lev) continue;
                x = spans[i].x * surf->pitch_x;
                len = spans[i].len;
 
@@ -436,13 +422,11 @@ void evg_rgbx_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 *dst = surf->pixels + y * surf->pitch_y;
        u32 col = surf->fill_col;
        u32 a, fin, col_no_a;
-       u8 aa_lev = surf->AALevel;
        s32 i;
 
        a = (col>>24)&0xFF;
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_rgbx_const_run(fin, dst + surf->pitch_x*spans[i].x, surf->pitch_x, spans[i].len);
@@ -457,10 +441,8 @@ void evg_rgbx_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i, x;
        u32 len;
        u32 *col, _col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
                surf->sten->fill_run(surf->sten, surf, spans[i].x, y, len);
@@ -585,7 +567,6 @@ void evg_rgba_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        char *p;
        s32 i;
        u32 len;
-       u8 aa_lev = surf->AALevel;
 
        a = GF_COL_A(col);
        r = GF_COL_R(col);
@@ -594,7 +575,6 @@ void evg_rgba_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        col_no_a = col & 0x00FFFFFF;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                p = dst + spans[i].x*surf->pitch_x;
                len = spans[i].len;
        
@@ -618,14 +598,12 @@ void evg_rgba_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 {
        u8 *dst = surf->pixels + y * surf->pitch_y;
        u32 a, fin, col_no_a;
-       u8 aa_lev = surf->AALevel;
        s32 i;
 
        a = GF_COL_A(surf->fill_col);
        col_no_a = surf->fill_col & 0x00FFFFFF;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_rgba_const_run(fin, dst + spans[i].x*surf->pitch_x, surf->pitch_x, spans[i].len);
@@ -641,10 +619,8 @@ void evg_rgba_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i;
        u32 len;
        u32 *col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                p = dst + spans[i].x * surf->pitch_x;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
index c151980c487d6228b3befc977e0834e998114af3..34fe84674936a0dad0a722f7e3f39709e01b11b1 100644 (file)
@@ -81,7 +81,6 @@ void evg_rgb_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        char *p;
        s32 i;
        u32 len, r, g, b;
-       u8 aa_lev = surf->AALevel;
 
        r = GF_COL_R(col);
        g = GF_COL_G(col);
@@ -89,7 +88,6 @@ void evg_rgb_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                p = dst + spans[i].x * surf->pitch_x;
        
@@ -112,14 +110,11 @@ void evg_rgb_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 {
        char *dst = surf->pixels + y * surf->pitch_y;
        u32 col = surf->fill_col;
-       u32 a, fin, col_no_a;
+       u32 a, fin;
        s32 i;
-       u8 aa_lev = surf->AALevel;
 
        a = (col>>24)&0xFF;
-       col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | (col&0x00FFFFFF);
                overmask_rgb_const_run(fin, dst + surf->pitch_x * spans[i].x, surf->pitch_x, spans[i].len);
@@ -133,13 +128,10 @@ void evg_rgb_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u8 spanalpha, col_a;
        s32 i;
        s32 x;
-       u32 len, bpp;
+       u32 len;
        u32 *col;
-       u8 aa_lev = surf->AALevel;
-       bpp = surf->BPP;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
                surf->sten->fill_run(surf->sten, surf, spans[i].x, y, len);
@@ -241,7 +233,6 @@ void evg_bgr_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        char *p;
        s32 i;
        u32 len, r, g, b;
-       u8 aa_lev = surf->AALevel;
 
        r = GF_COL_R(col);
        g = GF_COL_G(col);
@@ -249,7 +240,6 @@ void evg_bgr_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                p = dst + spans[i].x * surf->pitch_x;
        
@@ -274,12 +264,10 @@ void evg_bgr_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        u32 col = surf->fill_col;
        u32 a, fin, col_no_a;
        s32 i;
-       u8 aa_lev = surf->AALevel;
 
        a = (col>>24)&0xFF;
        col_no_a = col & 0x00FFFFFF;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                fin = mul255(a, spans[i].coverage);
                fin = (fin<<24) | col_no_a;
                overmask_bgr_const_run(fin, dst + surf->pitch_x * spans[i].x, surf->pitch_x, spans[i].len);
@@ -294,10 +282,8 @@ void evg_bgr_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
        s32 i, x;
        u32 len;
        u32 *col, _col;
-       u8 aa_lev = surf->AALevel;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                x = spans[i].x;
                len = spans[i].len;
                spanalpha = spans[i].coverage;
@@ -360,12 +346,9 @@ void evg_user_fill_const(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 {
        u32 col_no_a;
        s32 i;
-       u8 aa_lev = surf->AALevel;
 
        col_no_a = surf->fill_col;
-       for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
-       
+       for (i=0; i<count; i++) {       
                if (spans[i].coverage != 0xFF) {
                        u32 a = mul255(0xFF, spans[i].coverage);
                        surf->raster_fill_run_alpha(surf->raster_cbk, spans[i].x, y, spans[i].len, col_no_a, a);
@@ -379,12 +362,9 @@ void evg_user_fill_const_a(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 {
        u32 col, a, col_no_a;
        s32 i;
-       u8 aa_lev = surf->AALevel;
-
        a = (surf->fill_col>>24)&0xFF;
        col_no_a = surf->fill_col | 0xFF000000;
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                col = mul255(a, spans[i].coverage);
                surf->raster_fill_run_alpha(surf->raster_cbk, spans[i].x, y, spans[i].len, col_no_a, col);
        }
@@ -394,13 +374,10 @@ void evg_user_fill_var(s32 y, s32 count, EVG_Span *spans, EVGSurface *surf)
 {
        u8 spanalpha, col_a, a;
        s32 i;
-       u32 x, len, bpp;
+       u32 x, len;
        u32 *col;
-       u8 aa_lev = surf->AALevel;
-       bpp = surf->BPP;
 
        for (i=0; i<count; i++) {
-               if (spans[i].coverage<aa_lev) continue;
                len = spans[i].len;
                x = spans[i].x;
                spanalpha = spans[i].coverage;
index e4318bdedd2872a4d982a3522e0f065b5292e041..b860c8a6efde43e277878a03c4daba46b6505e6e 100644 (file)
@@ -285,16 +285,13 @@ GF_Err evg_surface_set_raster_level(GF_SURFACE _this, GF_RasterLevel RasterSetti
        if (!surf) return GF_BAD_PARAM;
        switch (RasterSetting) {
        case GF_RASTER_HIGH_QUALITY:
-               surf->AALevel = 1;/*don't draw pixels with 0 alpha...*/
                surf->texture_filter = GF_TEXTURE_FILTER_HIGH_QUALITY;
                break;
        case GF_RASTER_MID:
-               surf->AALevel = 90;
                surf->texture_filter = GF_TEXTURE_FILTER_HIGH_QUALITY;
                break;
        case GF_RASTER_HIGH_SPEED:
        default:
-               surf->AALevel = 254;
                surf->texture_filter = GF_TEXTURE_FILTER_HIGH_SPEED;
                break;
        }
index cfa5c3b69cc60bac4bff62c2b57b02da87485359..c810e25d95d839f01f127bb0e9987c0063bb509b 100644 (file)
@@ -205,7 +205,7 @@ static GF_Err SVG_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 i
                                        size = gf_bs_read_u32(bs);
                                        nb_bytes = 6;
                                }
-//                 fwrite( inBuffer + pos + nb_bytes + 1, 1, size - 1, f );
+//                 gf_fwrite( inBuffer + pos + nb_bytes + 1, 1, size - 1, f );
 
                                dims_hdr = gf_bs_read_u8(bs);
                                prev = buf2[pos + nb_bytes + size];
@@ -230,13 +230,14 @@ static GF_Err SVG_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 i
        }
 
 exit:
-       if ((svgin->scene->graph_attached!=1) && (gf_sg_get_root_node(svgin->loader.scene_graph)!=NULL) ) {
+       if ((e>=GF_OK) && (svgin->scene->graph_attached!=1) && (gf_sg_get_root_node(svgin->loader.scene_graph)!=NULL) ) {
                gf_scene_attach_to_compositor(svgin->scene);
        }
        /*prepare for next playback*/
-       if (e==GF_EOS) {
+       if (e) {
                gf_sm_load_done(&svgin->loader);
                svgin->loader.fileName = NULL;
+               e = GF_EOS;
        }
        return e;
 }
index f16519e4ab0a2e6b675f6106fdbdc2a815360997..d4a8c5c7009bf221418f32deedfd2e8aa7e266d5 100644 (file)
@@ -188,6 +188,9 @@ void TTIn_download_file(GF_InputService *plug, const char *url)
        if (!tti->dnload) {
                tti->needs_connection = 0;
                gf_term_on_connect(tti->service, NULL, GF_NOT_SUPPORTED);
+       } else {
+               /*start our download (threaded)*/
+               gf_dm_sess_process(tti->dnload);
        }
        /*service confirm is done once fetched*/
 }
index 4ddbd582ad7beb8da131412c6df5ce6a3ba01cb2..b34dd7c667358d462d11610c05dacd0107e8eb2c 100644 (file)
@@ -152,7 +152,7 @@ static Bool uir_process(GF_TermExt *termext, u32 action, void *param)
                opt = gf_modules_get_option((GF_BaseInterface*)termext, "UIRecord", "Mode");
                if (!opt) return 0;
                uifile = gf_modules_get_option((GF_BaseInterface*)termext, "UIRecord", "File");
-               if (!opt) return 0;
+               if (!uifile) return 0;
 
                if (!strcmp(opt, "Play")) {
                        uir->uif = gf_f64_open(uifile, "rb");
@@ -166,7 +166,7 @@ static Bool uir_process(GF_TermExt *termext, u32 action, void *param)
 
                        uir_load_event(uir);
                } else if (!strcmp(opt, "Record")) {
-                       uir->uif = fopen(uifile, "wb");
+                       uir->uif = gf_f64_open(uifile, "wb");
                        if (!uir->uif) return 0;
                        uir->bs = gf_bs_from_file(uir->uif, GF_BITSTREAM_WRITE);
 
diff --git a/modules/validator/README.TXT b/modules/validator/README.TXT
new file mode 100644 (file)
index 0000000..8fb86ac
--- /dev/null
@@ -0,0 +1,41 @@
+The validator allows recording user interactions and taking snapshots when playing back interactive content; and replaying the content simulating the interactions, generating and comparing snapshots. To activate it you need to modify the GPAC configuration as follows: \r
+\r
+Add a section:\r
+[Validator]\r
+Mode=Play\r
+\r
+Mode can be: Play, Record, or Disable\r
+\r
+The validator will try to load a single file to be tested or a playlist.\r
+Single files are indicated with:\r
+XVS=C:\Users\Cyril Concolato\code\tsi_svn\trunk\gpac_public\regression_tests\svg\file.xvs\r
+XVS means XML Validation Sequence. An example of XVS is:\r
+\r
+<TestValidationScript file="C:\Users\Cyril Concolato\standards\SVG_WG\SVG\profiles\1.1F2\test\svg\animate-elem-09-t.svg" >\r
+<snapshot time="237" image="animate-elem-09-t-reference-000.png" />\r
+<mousemove time="4749.000000" x="99" y="354" />\r
+<mousemove time="4749.000000" x="103" y="343" />\r
+<mousemove time="4749.000000" x="108" y="333" />\r
+</TestValidationScript>\r
+\r
+\r
+Playlist of XVS are givin with:\r
+XVL=C:\Users\Cyril Concolato\code\tsi_svn\trunk\gpac_public\regression_tests\svg\svg1.1f2.xvl\r
+XVL means XML Validation List. An example of XVL is:\r
+\r
+<TestSuiteValidationScript content-base="C:\Users\Cyril Concolato\standards\SVG_WG\SVG\profiles\1.1F2\test\svg" >\r
+<Test scenario="animate-elem-02-t.xvs" content="animate-elem-02-t.svg" />\r
+<Test scenario="animate-elem-03-t.xvs" content="animate-elem-03-t.svg" />\r
+<Test scenario="animate-dom-01-f.xvs" content="animate-dom-01-f.svg" />\r
+<Test scenario="animate-dom-02-f.xvs" content="animate-dom-02-f.svg" />\r
+</TestSuiteValidationScript>\r
+\r
+When recording and playing back, the GPAC player rendering is switched to 5 FPS without antialiasing.\r
+\r
+When recording, you can trigger some actions as follows:\r
+CTRL+Insert: takes a snapshot and records it as a PNG. In replay mode, a PNG will be taken at the same scene time and the PNG will be compared.\r
+CTRL+Fin: Quit\r
+CTRL+F1: Takes snapshot at next frame change.\r
+Page Down: Ends current XVS and switches to next in the XVL\r
+\r
+Note: after recording, upon closing the player, the Validator mode is automatically switched to Play to avoid losing recorded interactions.
\ No newline at end of file
diff --git a/modules/validator/validator.c b/modules/validator/validator.c
new file mode 100644 (file)
index 0000000..7863caf
--- /dev/null
@@ -0,0 +1,1013 @@
+/*\r
+ *                     GPAC - Multimedia Framework C SDK\r
+ *\r
+ *                     Authors: Cyril Concolato\r
+ *                     Copyright (c) 2010 Telecom ParisTech\r
+ *                     All rights reserved\r
+ *\r
+ *  This file is part of GPAC / Test Suite Validator Recorder sub-project\r
+ *\r
+ *  GPAC is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU Lesser General Public License as published by\r
+ *  the Free Software Foundation; either version 2, or (at your option)\r
+ *  any later version.\r
+ *   \r
+ *  GPAC is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU Lesser General Public License for more details.\r
+ *   \r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; see the file COPYING.  If not, write to\r
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. \r
+ *\r
+ */\r
+\r
+#include <gpac/modules/term_ext.h>\r
+#include <gpac/internal/terminal_dev.h>\r
+#include <gpac/internal/compositor_dev.h>\r
+#include <gpac/internal/media_dev.h>\r
+#include <gpac/xml.h>\r
+#include <gpac/options.h>\r
+\r
+typedef struct __validation_module\r
+{\r
+    GF_Terminal *term;\r
+\r
+    Bool is_recording;\r
+    char *prev_fps;\r
+    char *prev_alias;\r
+\r
+    /* Clock used to synchronize events in recording and playback*/\r
+       GF_Clock *ck;\r
+\r
+    /* Next event to process */\r
+    Bool next_event_snapshot;\r
+       GF_Event next_event;\r
+    u32 xvs_event_index;\r
+       u32 next_time;\r
+       Bool evt_loaded;\r
+\r
+    GF_VideoListener video_listener;\r
+\r
+    /* XML Validation List (the list of files to be tested) */\r
+    char *xvl_filename;\r
+    GF_DOMParser *xvl_parser;\r
+    GF_XMLNode *xvl_node;\r
+    GF_XMLNode *xvs_node_in_xvl;\r
+    u32 xvl_node_index;\r
+\r
+    /* Pointer to the current validation script file being tested */\r
+    char *xvs_filename;\r
+    GF_DOMParser *xvs_parser;\r
+    GF_XMLNode *xvs_node;\r
+    Bool xvs_result;\r
+\r
+    /* test sequence */\r
+    char *test_base;\r
+    char *test_filename;\r
+    \r
+    Bool snapshot_next_frame;\r
+    u32 snapshot_number;\r
+\r
+    GF_TermEventFilter evt_filter;\r
+} GF_Validator;\r
+\r
+static void validator_xvs_close(GF_Validator *validator);\r
+static Bool validator_xvs_next(GF_Validator *validator, Bool reverse);\r
+\r
+static void validator_xvs_add_snapshot_node(GF_Validator *validator, const char *filename, u32 scene_time)\r
+{\r
+    GF_XMLNode *snap_node;\r
+    GF_XMLAttribute *att;\r
+    GF_SAFEALLOC(snap_node, GF_XMLNode);\r
+    snap_node->name = gf_strdup("snapshot");\r
+    snap_node->attributes = gf_list_new();\r
+    GF_SAFEALLOC(att, GF_XMLAttribute);\r
+    att->name = gf_strdup("time");\r
+    att->value = gf_malloc(100);\r
+    sprintf(att->value, "%d", scene_time);\r
+    gf_list_add(snap_node->attributes, att);\r
+    GF_SAFEALLOC(att, GF_XMLAttribute);\r
+    att->name = gf_strdup("image");\r
+    att->value = gf_strdup(filename);\r
+    gf_list_add(snap_node->attributes, att);\r
+    gf_list_add(validator->xvs_node->content, snap_node);\r
+\r
+    /* adding an extra text node for line break in serialization */\r
+    GF_SAFEALLOC(snap_node, GF_XMLNode);\r
+    snap_node->type = GF_XML_TEXT_TYPE;\r
+    snap_node->name = gf_strdup("\n");\r
+    gf_list_add(validator->xvs_node->content, snap_node);\r
+}\r
+\r
+static char *validator_get_snapshot_name(char *test_filename, Bool is_reference, u32 number)\r
+{\r
+    char *dot;\r
+    char dumpname[GF_MAX_PATH];\r
+    dot = strrchr(test_filename, '.');\r
+    dot[0] = 0;\r
+    sprintf(dumpname, "%s-%s-%03d.png", test_filename, (is_reference?"reference":"newest"), number);\r
+    dot[0] = '.';\r
+    return gf_strdup(dumpname);\r
+}\r
+\r
+static char *validator_create_snapshot(GF_Validator *validator) \r
+{\r
+    GF_Err e;\r
+       GF_VideoSurface fb;\r
+    GF_Terminal *term = validator->term;\r
+    char *dumpname;\r
+    \r
+    dumpname = validator_get_snapshot_name(validator->test_filename, validator->is_recording, validator->snapshot_number);\r
+    \r
+    e = gf_term_get_screen_buffer(term, &fb);\r
+    if (e) {\r
+           GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Error dumping screen buffer %s\n", gf_error_to_string(e)));\r
+    } else {\r
+           u32 dst_size = fb.width*fb.height*3;\r
+           char *dst=gf_malloc(sizeof(char)*dst_size);\r
+\r
+           e = gf_img_png_enc(fb.video_buffer, fb.width, fb.height, fb.pitch_y, fb.pixel_format, dst, &dst_size);\r
+           if (e) {\r
+                   GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Error encoding PNG %s\n", gf_error_to_string(e)));\r
+           } else {\r
+                   FILE *png = gf_f64_open(dumpname, "wb");\r
+                   if (!png) {\r
+                           GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Error writing file %s\n", dumpname));\r
+                   } else {\r
+                           gf_fwrite(dst, dst_size, 1, png);\r
+                           fclose(png);\r
+                           GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Validator] Writing file %s\n", dumpname));\r
+                   }\r
+           }\r
+           if (dst) gf_free(dst);\r
+           gf_term_release_screen_buffer(term, &fb);\r
+    }\r
+    validator->snapshot_number++;\r
+    return dumpname;\r
+}\r
+\r
+static Bool validator_compare_snapshots(GF_Validator *validator)\r
+{\r
+    char *ref_name, *new_name;\r
+    u32 ref_width, ref_height, ref_pixel_format, ref_data_size;\r
+    u32 new_width, new_height, new_pixel_format, new_data_size;\r
+    char *ref_data, *new_data;\r
+    Bool result = 0;\r
+    GF_Err e;\r
+    u32 i;\r
+\r
+    u32 snap_number = validator->snapshot_number - 1;\r
+    ref_name = validator_get_snapshot_name(validator->test_filename, 1, snap_number);\r
+    new_name = validator_get_snapshot_name(validator->test_filename, 0, snap_number);\r
+\r
+    e = gf_img_file_dec(ref_name, NULL, &ref_width, &ref_height, &ref_pixel_format, &ref_data, &ref_data_size);\r
+    if (e) {\r
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Cannot decode PNG file %s\n", ref_name));\r
+        goto end;\r
+    }\r
+    e = gf_img_file_dec(new_name, NULL, &new_width, &new_height, &new_pixel_format, &new_data, &new_data_size);\r
+    if (e) {\r
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Cannot decode PNG file %s\n", new_name));\r
+        goto end;\r
+    }\r
+    if (ref_width != new_width) {\r
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Snapshots have different widths: %d vs %d\n", ref_width, new_width));\r
+        goto end;\r
+    }\r
+    if (ref_height != new_height) {\r
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Snapshots have different heights: %d vs %d\n", ref_height, new_height));\r
+        goto end;\r
+    }\r
+    if (ref_pixel_format != new_pixel_format) {\r
+        GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Snapshots have different pixel formats: %d vs %d\n", ref_pixel_format, new_pixel_format));\r
+        goto end;\r
+    }\r
+\r
+    for (i = 0; i<ref_data_size; i++) {\r
+        if (ref_data[i] != new_data[i]) {\r
+            GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Snapshots have different pixel values at position %d: %d vs %d\n", i, ref_data[i], new_data[i]));\r
+            break;\r
+        }\r
+    }\r
+    if (i==ref_data_size) result = 1;\r
+\r
+end:\r
+    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Validator] PNG Comparison result: %s\n", (result?"Same":"Different")));\r
+    if (ref_name) gf_free(ref_name);\r
+    if (new_name) gf_free(new_name);\r
+    return result;\r
+}\r
+\r
+static void validator_on_video_frame(void *udta, u32 time)\r
+{\r
+       GF_Validator *validator = (GF_Validator *)udta;\r
+    if (validator->snapshot_next_frame) {\r
+        char *snap_name = validator_create_snapshot(validator);\r
+        validator_xvs_add_snapshot_node(validator, snap_name, gf_clock_time(validator->ck));\r
+        gf_free(snap_name);\r
+        validator->snapshot_next_frame = 0;\r
+    }\r
+}\r
+\r
+static void validator_on_video_reconfig(void *udta, u32 width, u32 height)\r
+{\r
+}\r
+\r
+Bool validator_on_event_play(GF_Validator *validator, GF_Event *event, Bool consumed_by_compositor)\r
+{\r
+       switch (event->type) {\r
+       case GF_EVENT_CONNECT:\r
+               if (event->connect.is_connected) {\r
+            gf_sc_add_video_listener(validator->term->compositor, &validator->video_listener);\r
+                       validator->ck = validator->term->root_scene->scene_codec ? \r
+                            validator->term->root_scene->scene_codec->ck : \r
+                            validator->term->root_scene->dyn_ck;\r
+               }\r
+               break;\r
+       case GF_EVENT_CLICK: \r
+       case GF_EVENT_MOUSEUP:\r
+       case GF_EVENT_MOUSEDOWN: \r
+       case GF_EVENT_MOUSEOVER: \r
+       case GF_EVENT_MOUSEOUT:\r
+       case GF_EVENT_MOUSEMOVE:\r
+       case GF_EVENT_MOUSEWHEEL:\r
+       case GF_EVENT_KEYDOWN:\r
+       case GF_EVENT_TEXTINPUT:\r
+        return 1;\r
+       case GF_EVENT_KEYUP:\r
+        if ((event->key.key_code == GF_KEY_END)&&(event->key.flags & GF_KEY_MOD_CTRL)) { \r
+            GF_Event evt;\r
+            evt.type = GF_EVENT_QUIT;\r
+            validator->term->compositor->video_out->on_event(validator->term->compositor->video_out->evt_cbk_hdl, &evt);                \r
+        }\r
+        return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void validator_xvs_add_event_dom(GF_Validator *validator, GF_Event *event) \r
+{\r
+    GF_XMLNode *evt_node;\r
+    GF_XMLAttribute *att;\r
+    \r
+    GF_SAFEALLOC(evt_node, GF_XMLNode);\r
+\r
+    switch (event->type) {\r
+       case GF_EVENT_CLICK: \r
+       case GF_EVENT_MOUSEUP:\r
+       case GF_EVENT_MOUSEDOWN: \r
+       case GF_EVENT_MOUSEOVER: \r
+       case GF_EVENT_MOUSEOUT:\r
+       case GF_EVENT_MOUSEMOVE:\r
+       case GF_EVENT_MOUSEWHEEL:\r
+       case GF_EVENT_KEYUP:\r
+       case GF_EVENT_KEYDOWN:\r
+       case GF_EVENT_TEXTINPUT:\r
+        evt_node->name = gf_strdup(gf_dom_event_get_name(event->type));\r
+        break;\r
+    }\r
+    \r
+    if (!evt_node->name) {\r
+        gf_free(evt_node);\r
+        return;\r
+    }\r
+\r
+    evt_node->attributes = gf_list_new();\r
+\r
+    GF_SAFEALLOC(att, GF_XMLAttribute);\r
+    att->name = gf_strdup("time");\r
+    att->value = gf_malloc(100);\r
+    sprintf(att->value, "%f", gf_scene_get_time(validator->term->root_scene)*1000);\r
+    gf_list_add(evt_node->attributes, att);\r
+\r
+    switch (event->type) {\r
+       case GF_EVENT_CLICK: \r
+       case GF_EVENT_MOUSEUP:\r
+       case GF_EVENT_MOUSEDOWN: \r
+       case GF_EVENT_MOUSEOVER: \r
+       case GF_EVENT_MOUSEOUT:\r
+       case GF_EVENT_MOUSEMOVE:\r
+       case GF_EVENT_MOUSEWHEEL:\r
+        if (event->type == GF_EVENT_MOUSEDOWN || event->type == GF_EVENT_MOUSEUP) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("button");\r
+            switch (event->mouse.button) {\r
+                case 0:\r
+                    att->value = gf_strdup("Left");\r
+                    break;\r
+                case 1:\r
+                    att->value = gf_strdup("Middle");\r
+                    break;\r
+                case 2:\r
+                    att->value = gf_strdup("Right");\r
+                    break;\r
+            }\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        GF_SAFEALLOC(att, GF_XMLAttribute);\r
+        att->name = gf_strdup("x");\r
+        att->value = gf_malloc(100);\r
+        sprintf(att->value, "%d", event->mouse.x);\r
+        gf_list_add(evt_node->attributes, att);\r
+        GF_SAFEALLOC(att, GF_XMLAttribute);\r
+        att->name = gf_strdup("y");\r
+        att->value = gf_malloc(100);\r
+        sprintf(att->value, "%d", event->mouse.y);\r
+        gf_list_add(evt_node->attributes, att);\r
+        if (event->type == GF_EVENT_MOUSEWHEEL) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("wheel_pos");\r
+            att->value = gf_malloc(100);\r
+            sprintf(att->value, "%f", event->mouse.wheel_pos);\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        if (event->mouse.key_states & GF_KEY_MOD_SHIFT) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("shift");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        if (event->mouse.key_states & GF_KEY_MOD_CTRL) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("ctrl");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        if (event->mouse.key_states & GF_KEY_MOD_ALT) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("alt");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        break;\r
+       /*Key Events*/\r
+       case GF_EVENT_KEYUP:\r
+       case GF_EVENT_KEYDOWN:\r
+       case GF_EVENT_LONGKEYPRESS:\r
+        GF_SAFEALLOC(att, GF_XMLAttribute);\r
+        att->name = gf_strdup("key_identifier");\r
+        att->value = gf_strdup(gf_dom_get_key_name(event->key.key_code));\r
+        gf_list_add(evt_node->attributes, att);        \r
+        if (event->key.flags & GF_KEY_MOD_SHIFT) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("shift");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        if (event->key.flags & GF_KEY_MOD_CTRL) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("ctrl");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+        if (event->key.flags & GF_KEY_MOD_ALT) {\r
+            GF_SAFEALLOC(att, GF_XMLAttribute);\r
+            att->name = gf_strdup("alt");\r
+            att->value = gf_strdup("true");\r
+            gf_list_add(evt_node->attributes, att);\r
+        }\r
+               break;\r
+       case GF_EVENT_TEXTINPUT:\r
+        GF_SAFEALLOC(att, GF_XMLAttribute);\r
+        att->name = gf_strdup("unicode-char");\r
+        att->value = gf_malloc(100);\r
+        sprintf(att->value, "%d", event->character.unicode_char);\r
+        gf_list_add(evt_node->attributes, att);\r
+        break;\r
+    }\r
+    gf_list_add(validator->xvs_node->content, evt_node);\r
+    /* adding an extra text node for line break in serialization */\r
+    GF_SAFEALLOC(evt_node, GF_XMLNode);\r
+    evt_node->type = GF_XML_TEXT_TYPE;\r
+    evt_node->name = gf_strdup("\n");\r
+    gf_list_add(validator->xvs_node->content, evt_node);\r
+} \r
+\r
+Bool validator_on_event_record(GF_Validator *validator, GF_Event *event, Bool consumed_by_compositor)\r
+{\r
+    Bool rec_event = 1;\r
+       switch (event->type) {\r
+       case GF_EVENT_CONNECT:\r
+               if (event->connect.is_connected) {\r
+            gf_sc_add_video_listener(validator->term->compositor, &validator->video_listener);\r
+                       validator->ck = validator->term->root_scene->scene_codec ? validator->term->root_scene->scene_codec->ck : validator->term->root_scene->dyn_ck;\r
+               }\r
+               break;\r
+       case GF_EVENT_KEYDOWN:\r
+        if (event->key.key_code == GF_KEY_INSERT) { \r
+            rec_event = 0;\r
+        } else if (event->key.key_code == GF_KEY_PAGEDOWN) { \r
+            rec_event = 0;\r
+        } else if (event->key.key_code == GF_KEY_PAGEUP) { \r
+            rec_event = 0;\r
+        } else if (event->key.key_code == GF_KEY_END) { \r
+            rec_event = 0;\r
+        } else if (event->key.key_code == GF_KEY_CONTROL) { \r
+            rec_event = 0;\r
+        } else if (event->key.flags & GF_KEY_MOD_CTRL) {\r
+            rec_event = 0;\r
+        }\r
+        break;\r
+       case GF_EVENT_KEYUP:\r
+        if (event->key.flags & GF_KEY_MOD_CTRL) {\r
+            rec_event = 0;\r
+            if (event->key.key_code == GF_KEY_INSERT) { \r
+                char *snap_name = validator_create_snapshot(validator);\r
+                validator_xvs_add_snapshot_node(validator, snap_name, gf_clock_time(validator->ck));\r
+                gf_free(snap_name);\r
+            } else if (event->key.key_code == GF_KEY_END) {\r
+                GF_Event evt;\r
+                evt.type = GF_EVENT_QUIT;\r
+                validator->term->compositor->video_out->on_event(validator->term->compositor->video_out->evt_cbk_hdl, &evt);                \r
+            } else if (event->key.key_code == GF_KEY_F1) {\r
+                validator->snapshot_next_frame = 1;\r
+            }\r
+        } else if (event->key.key_code == GF_KEY_PAGEDOWN) { \r
+            rec_event = 0;\r
+            validator_xvs_close(validator);\r
+            gf_term_disconnect(validator->term);\r
+            gf_sc_remove_video_listener(validator->term->compositor, &validator->video_listener);\r
+            validator_xvs_next(validator, 0);\r
+        } else if (event->key.key_code == GF_KEY_PAGEUP) { \r
+            rec_event = 0;\r
+            validator_xvs_close(validator);\r
+            gf_term_disconnect(validator->term);\r
+            gf_sc_remove_video_listener(validator->term->compositor, &validator->video_listener);\r
+            validator_xvs_next(validator, 1);\r
+        } else if (event->key.key_code == GF_KEY_CONTROL) { \r
+            rec_event = 0;\r
+        }\r
+        break;\r
+       }\r
+    if (rec_event) {\r
+        validator_xvs_add_event_dom(validator, event);\r
+    }\r
+       return 0;\r
+}\r
+\r
+static void validator_xvl_open(GF_Validator *validator) \r
+{\r
+    GF_Err e;\r
+    u32 att_index;\r
+    GF_XMLAttribute *att;\r
+    validator->xvl_parser = gf_xml_dom_new();\r
+    e = gf_xml_dom_parse(validator->xvl_parser, validator->xvl_filename, NULL, NULL);\r
+    if (e != GF_OK) {\r
+        gf_xml_dom_del(validator->xvl_parser);\r
+        validator->xvl_parser = NULL;\r
+        return;\r
+    }\r
+    validator->xvl_node = gf_xml_dom_get_root(validator->xvl_parser);\r
+    if (!validator->xvl_node) {\r
+        gf_xml_dom_del(validator->xvl_parser);\r
+        validator->xvl_parser = NULL;\r
+        return;\r
+    }\r
+    att_index = 0;\r
+    while (1) {\r
+        att = gf_list_get(validator->xvl_node->attributes, att_index);\r
+        if (!att) break;\r
+        if (!strcmp(att->name, "content-base")) {\r
+            validator->test_base = gf_strdup(att->value);\r
+        }\r
+        att_index++;\r
+    }\r
+}\r
+\r
+static void validator_xvl_close(GF_Validator *validator) \r
+{\r
+    if (validator->xvl_parser) {\r
+        /* writing the validation results */\r
+        if (!validator->is_recording) {\r
+            FILE *xvl_fp;\r
+            char *xvl_content;\r
+            char result_filename[GF_MAX_PATH];\r
+            char *dot;\r
+            xvl_content = gf_xml_dom_serialize(validator->xvl_node, 0);\r
+            dot = strrchr(validator->xvl_filename, '.');\r
+            dot[0] = 0;\r
+            sprintf(result_filename, "%s-result.xml", validator->xvl_filename);\r
+            dot[0] = '.';\r
+            xvl_fp = gf_f64_open(result_filename, "wt");\r
+            gf_fwrite(xvl_content, strlen(xvl_content), 1, xvl_fp);\r
+            fclose(xvl_fp);\r
+            gf_free(xvl_content);\r
+        } \r
+        gf_xml_dom_del(validator->xvl_parser);\r
+        validator->xvl_parser = NULL;\r
+        validator->xvl_filename = NULL;\r
+    }\r
+}\r
+\r
+static void validator_xvl_get_next_xvs(GF_Validator *validator, Bool reverse)\r
+{    \r
+    u32 xvl_att_index;\r
+    validator->xvs_node = NULL;\r
+    validator->xvs_filename = NULL;\r
+    validator->test_filename = NULL;\r
+    while (1) {\r
+        validator->xvs_node_in_xvl = gf_list_get(validator->xvl_node->content, validator->xvl_node_index);\r
+        if (!validator->xvs_node_in_xvl) {\r
+            return;\r
+        } \r
+        if (validator->xvs_node_in_xvl->type != GF_XML_NODE_TYPE) {\r
+            if (!reverse) validator->xvl_node_index++;\r
+            else validator->xvl_node_index--;\r
+            continue;\r
+        }\r
+        xvl_att_index = 0;\r
+        while(1) {\r
+            GF_XMLAttribute *att = gf_list_get(validator->xvs_node_in_xvl->attributes, xvl_att_index);\r
+            if (!att) break;\r
+            if (!strcmp(att->name, "scenario")) {\r
+                validator->xvs_filename = att->value;\r
+            } else if (!strcmp(att->name, "content")) {\r
+                validator->test_filename = att->value;\r
+            }\r
+            xvl_att_index++;\r
+        }\r
+        if (!reverse) validator->xvl_node_index++;\r
+        else validator->xvl_node_index--;\r
+        break;\r
+    }\r
+}\r
+\r
+static Bool validator_xvs_open(GF_Validator *validator) \r
+{\r
+    GF_Err e;\r
+    GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Validator] Opening Validation Script: %s\n", validator->xvs_filename));\r
+    validator->snapshot_number = 0;\r
+    validator->xvs_parser = gf_xml_dom_new();\r
+    e = gf_xml_dom_parse(validator->xvs_parser, validator->xvs_filename, NULL, NULL);\r
+    if (e != GF_OK) {\r
+        if (validator->is_recording) {\r
+            GF_SAFEALLOC(validator->xvs_node, GF_XMLNode);\r
+            validator->xvs_node->name = gf_strdup("TestValidationScript");\r
+            validator->xvs_node->attributes = gf_list_new();\r
+            validator->xvs_node->content = gf_list_new();\r
+        } else {\r
+            gf_xml_dom_del(validator->xvs_parser);\r
+            validator->xvs_parser = NULL;\r
+            return 0;\r
+        }\r
+    } else {\r
+        validator->xvs_node = gf_xml_dom_get_root(validator->xvs_parser);\r
+    }\r
+    /* Get the file name from the XVS if not found in the XVL */\r
+    if (!validator->test_filename) {\r
+        GF_XMLAttribute *att;\r
+        GF_XMLAttribute *att_file;\r
+        u32 att_index = 0;\r
+        att_file = NULL;\r
+        while (1) {\r
+            att = gf_list_get(validator->xvs_node->attributes, att_index);\r
+            if (!att) {\r
+                break;\r
+            } else if (!strcmp(att->name, "file")) {\r
+                att_file = att;\r
+            }\r
+            att_index++;\r
+        }\r
+        if (!att_file) {\r
+            gf_xml_dom_del(validator->xvs_parser);\r
+            validator->xvs_parser = NULL;\r
+            validator->xvs_node = NULL;\r
+            return 0;\r
+        } else {\r
+            char *sep;\r
+            sep = strrchr(att_file->value, GF_PATH_SEPARATOR);\r
+            if (!sep) {\r
+                validator->test_filename = att_file->value;\r
+            } else {\r
+                sep[0] = 0;\r
+                validator->test_base = gf_strdup(att_file->value);\r
+                sep[0] = GF_PATH_SEPARATOR;\r
+                validator->test_filename = sep+1;\r
+            }\r
+        }        \r
+    }\r
+    if (validator->is_recording) {\r
+        GF_XMLNode *node;\r
+        /* Removing prerecorded interactions */\r
+               while (gf_list_count(validator->xvs_node->content)) {\r
+                       GF_XMLNode *child = (GF_XMLNode *)gf_list_last(validator->xvs_node->content);\r
+                       gf_list_rem_last(validator->xvs_node->content);\r
+                       gf_xml_dom_node_del(child);\r
+               }\r
+        /* adding an extra text node for line break in serialization */\r
+        GF_SAFEALLOC(node, GF_XMLNode);\r
+        node->type = GF_XML_TEXT_TYPE;\r
+        node->name = gf_strdup("\n");\r
+        gf_list_add(validator->xvs_node->content, node);\r
+    } else {\r
+        validator->xvs_result = 1;\r
+    }\r
+    return 1;\r
+}\r
+\r
+static void validator_xvs_close(GF_Validator *validator)\r
+{\r
+    if (validator->xvs_parser) {\r
+        if (validator->is_recording) {\r
+            FILE *xvs_fp;\r
+            char *xvs_content;\r
+            char filename[100];\r
+            GF_XMLAttribute *att;\r
+            GF_XMLAttribute *att_file = NULL;\r
+            u32 att_index = 0;\r
+            while (1) {\r
+                att = gf_list_get(validator->xvs_node->attributes, att_index);\r
+                if (!att) {\r
+                    break;\r
+                } else if (!strcmp(att->name, "file")) {\r
+                    att_file = att;\r
+                }\r
+                att_index++;\r
+            }\r
+\r
+            if (!att_file) {\r
+                GF_SAFEALLOC(att, GF_XMLAttribute);\r
+                att->name = gf_strdup("file");\r
+                gf_list_add(validator->xvs_node->attributes, att);\r
+            } else {\r
+                att = att_file;\r
+                if (att->value) gf_free(att->value);\r
+            }\r
+            sprintf(filename, "%s%c%s", validator->test_base, GF_PATH_SEPARATOR, validator->test_filename);\r
+            att->value = gf_strdup(filename);\r
+            xvs_content = gf_xml_dom_serialize(validator->xvs_node, 0);\r
+            xvs_fp = gf_f64_open(validator->xvs_filename, "wt");\r
+            gf_fwrite(xvs_content, strlen(xvs_content), 1, xvs_fp);\r
+            fclose(xvs_fp);\r
+            gf_free(xvs_content);\r
+        } else {\r
+            GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Validator] XVS Result : %s\n", (validator->xvs_result?"Success":"Failure")));\r
+            if (validator->xvs_node_in_xvl) {\r
+                GF_XMLAttribute *att;\r
+                GF_XMLAttribute *att_result = NULL;\r
+                u32 att_index = 0;\r
+                while (1) {\r
+                    att = gf_list_get(validator->xvs_node_in_xvl->attributes, att_index);\r
+                    if (!att) {\r
+                        break;\r
+                    } else if (!strcmp(att->name, "result")) {\r
+                        att_result = att;\r
+                    }\r
+                    att_index++;\r
+                }\r
+                if (!att_result) {\r
+                    GF_SAFEALLOC(att_result, GF_XMLAttribute);\r
+                    att_result->name = gf_strdup("result");\r
+                    gf_list_add(validator->xvs_node_in_xvl->attributes, att_result);\r
+                } \r
+                if (att_result->value) gf_free(att_result->value);\r
+                att_result->value = gf_strdup(validator->xvs_result ? "pass" : "fail");\r
+            }\r
+        }\r
+        gf_xml_dom_del(validator->xvs_parser);\r
+        validator->xvs_parser = NULL;\r
+    } \r
+    validator->xvs_node = NULL;\r
+    validator->xvs_node_in_xvl = NULL;\r
+    validator->xvs_filename = NULL;\r
+    validator->test_filename = NULL;\r
+    validator->ck = NULL;\r
+    validator->xvs_event_index = 0;\r
+    validator->snapshot_number = 0;\r
+}\r
+\r
+static void validator_test_open(GF_Validator *validator)\r
+{\r
+    char filename[100];\r
+    if (validator->test_base) \r
+        sprintf(filename, "%s%c%s", validator->test_base, GF_PATH_SEPARATOR, validator->test_filename);\r
+    else \r
+        sprintf(filename, "%s", validator->test_filename);\r
+    gf_sc_add_video_listener(validator->term->compositor, &validator->video_listener);\r
+    if (validator->is_recording) \r
+        validator->snapshot_next_frame = 1;\r
+    gf_term_connect(validator->term, filename);\r
+       validator->ck = validator->term->root_scene->scene_codec ? \r
+                    validator->term->root_scene->scene_codec->ck : \r
+                    validator->term->root_scene->dyn_ck;\r
+}\r
+\r
+static Bool validator_xvs_next(GF_Validator *validator, Bool reverse)\r
+{\r
+    if (validator->xvl_node) {\r
+        validator_xvl_get_next_xvs(validator, reverse);            \r
+        if (validator->xvs_filename) {\r
+            validator_xvs_open(validator);\r
+            if (!validator->xvs_node) {\r
+                return 0;\r
+            }\r
+            if (validator->test_filename) {\r
+                validator_test_open(validator);\r
+            } else {\r
+                validator_xvs_close(validator);\r
+                return 0;\r
+            }\r
+        } else {\r
+            return 0;\r
+        }\r
+        return 1;\r
+    } else {\r
+        return 0;\r
+    }\r
+}\r
+\r
+static Bool validator_load_event(GF_Validator *validator) \r
+{\r
+    GF_XMLNode *event_node;\r
+    GF_XMLAttribute *att;\r
+    u32 att_index;\r
+\r
+       memset(&validator->next_event, 0, sizeof(GF_Event));\r
+       validator->evt_loaded = 0;\r
+    validator->next_event_snapshot = 0;\r
+\r
+    if (!validator->xvs_node) return 0;\r
+\r
+    while (1) {\r
+        event_node = gf_list_get(validator->xvs_node->content, validator->xvs_event_index);\r
+        if (!event_node) {\r
+            return 0;\r
+        } else if (event_node->type == GF_XML_NODE_TYPE) {\r
+            validator->xvs_event_index++;\r
+            break;\r
+        } else {\r
+            validator->xvs_event_index++;\r
+        }\r
+    }\r
+\r
+    if (!strcmp(event_node->name, "snapshot")) {\r
+        validator->next_event_snapshot = 1;\r
+    } else {\r
+        validator->next_event.type = gf_dom_event_type_by_name(event_node->name);\r
+        if (validator->next_event.type == GF_EVENT_UNKNOWN) {\r
+            return 1;\r
+        }\r
+    }\r
+\r
+    att_index = 0;\r
+    while (1) {\r
+        att = gf_list_get(event_node->attributes, att_index);\r
+        if (!att) break;\r
+        if (!strcmp(att->name, "time")) {\r
+            validator->next_time = atoi(att->value);\r
+        } else if (!strcmp(att->name, "button")) {\r
+            if (!strcmp(att->value, "Left")) {\r
+                validator->next_event.mouse.button = 0;\r
+            } else if (!strcmp(att->value, "Middle")) {\r
+                validator->next_event.mouse.button = 1;\r
+            } else if (!strcmp(att->value, "Right")) {\r
+                validator->next_event.mouse.button = 2;\r
+            }\r
+        } else if (!strcmp(att->name, "x")) {\r
+            validator->next_event.mouse.x = atoi(att->value);\r
+        } else if (!strcmp(att->name, "y")) {\r
+            validator->next_event.mouse.y = atoi(att->value);\r
+        } else if (!strcmp(att->name, "wheel_pos")) {\r
+            validator->next_event.mouse.wheel_pos = FLT2FIX(atof(att->value));\r
+        } else if (!strcmp(att->name, "shift") && !strcmp(att->value, "true")) {\r
+            validator->next_event.mouse.key_states |= GF_KEY_MOD_SHIFT;\r
+        } else if (!strcmp(att->name, "alt") && !strcmp(att->value, "true")) {\r
+            validator->next_event.mouse.key_states |= GF_KEY_MOD_ALT;\r
+        } else if (!strcmp(att->name, "ctrl") && !strcmp(att->value, "true")) {\r
+            validator->next_event.mouse.key_states |= GF_KEY_MOD_CTRL;\r
+        } else if (!strcmp(att->name, "key_identifier")) {\r
+            validator->next_event.key.key_code = gf_dom_get_key_type(att->value); \r
+        } else if (!strcmp(att->name, "unicode-char")) {\r
+            validator->next_event.character.unicode_char = atoi(att->value);\r
+        } \r
+        att_index++;\r
+    }\r
+       validator->evt_loaded = 1;\r
+    return 1;\r
+}\r
+\r
+static Bool validator_process(GF_TermExt *termext, u32 action, void *param)\r
+{\r
+       const char *opt;\r
+       GF_Validator *validator = termext->udta;\r
+\r
+       switch (action) {\r
+\r
+    /* Upon starting of the terminal, we parse (possibly an XVL file), an XVS file, and start the first test sequence */\r
+    case GF_TERM_EXT_START:\r
+               validator->term = (GF_Terminal *) param;\r
+\r
+               /* if the validator is loaded, we switch off anti-aliasing for image comparison and we put a low framerate, \r
+               but we store the previous value to restore it upon termination of the validator */\r
+        opt = (char *)gf_modules_get_option((GF_BaseInterface*)termext, "Compositor", "FrameRate");\r
+        if (opt) validator->prev_fps = gf_strdup(opt);\r
+        opt = (char *)gf_modules_get_option((GF_BaseInterface*)termext, "Compositor", "AntiAlias");\r
+        if (opt) validator->prev_alias = gf_strdup(opt);\r
+\r
+               /* Check if the validator should be loaded and in which mode */\r
+        opt = gf_modules_get_option((GF_BaseInterface*)termext, "Validator", "Mode");\r
+               if (!opt) {\r
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("Validator missing configuration, stopping.\n"));\r
+                       return 0;\r
+               } else if (!strcmp(opt, "Play")) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Validator starting in playback mode.\n"));\r
+            validator->is_recording = 0;\r
+        } else if (!strcmp(opt, "Record")) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Validator starting in recording mode.\n"));\r
+            validator->is_recording = 1;\r
+        } else if (!strcmp(opt, "Disable")) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Validator is disabled.\n"));\r
+            return 0;\r
+        } else {\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("Validator configuration using wrong mode, stopping.\n"));\r
+            return 0;\r
+        }\r
+\r
+               /* initializes the validator and starts */\r
+        validator->xvs_filename = NULL;\r
+        validator->xvl_filename = (char *)gf_modules_get_option((GF_BaseInterface*)termext, "Validator", "XVL");\r
+        if (!validator->xvl_filename) {\r
+            validator->xvs_filename = (char *)gf_modules_get_option((GF_BaseInterface*)termext, "Validator", "XVS");\r
+                       if (!validator->xvs_filename) {\r
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("Validator configuration without input, stopping.\n"));\r
+                               return 0;\r
+                       } else {\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Validator using scenario file: %s\n", validator->xvs_filename));\r
+                       }\r
+               } else {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Validator using scenario playlist: %s\n", validator->xvl_filename));\r
+               }\r
+\r
+               /* since we changed parameters of the compositor, we need to trigger a reconfiguration */\r
+        gf_modules_set_option((GF_BaseInterface*)termext, "Compositor", "FrameRate", "5.0");\r
+        gf_modules_set_option((GF_BaseInterface*)termext, "Compositor", "AntiAlias", "None");\r
+        gf_term_set_option(validator->term, GF_OPT_RELOAD_CONFIG, 1);\r
+\r
+               validator->evt_filter.udta = validator;\r
+               if (!validator->is_recording) {\r
+                       validator->evt_filter.on_event = validator_on_event_play;\r
+            termext->caps |= GF_TERM_EXTENSION_NOT_THREADED;\r
+        } else {\r
+                       validator->evt_filter.on_event = validator_on_event_record;\r
+        } \r
+               gf_term_add_event_filter(validator->term, &validator->evt_filter);\r
+           validator->video_listener.udta = validator;\r
+           validator->video_listener.on_video_frame = validator_on_video_frame;\r
+           validator->video_listener.on_video_reconfig = validator_on_video_reconfig;\r
+\r
+               /* TODO: if start returns 0, the module is not loaded, so the above init (filter registration) is not removed,\r
+                  should probably return 1 all the time, to make sure stop is called */\r
+        if (validator->xvl_filename) {\r
+            validator_xvl_open(validator);\r
+            if (!validator->xvl_node) {\r
+                return 0;\r
+            }\r
+            validator_xvs_next(validator, 0);\r
+            if (!validator->xvs_node) {\r
+                return 0;\r
+            }\r
+        } else if (validator->xvs_filename) {\r
+            validator_xvs_open(validator);\r
+            if (!validator->xvs_node) {\r
+                return 0;\r
+            }\r
+            if (validator->test_filename) {\r
+                validator_test_open(validator);\r
+            } else {\r
+                validator_xvs_close(validator);\r
+                return 0;\r
+            }\r
+        } else {\r
+            return 0;\r
+        }\r
+        if (!validator->is_recording) {\r
+            validator_load_event(validator);\r
+        }\r
+               return 1;\r
+\r
+    /* when the terminal stops, we close the XVS parser and XVL parser if any, restore the config, \r
+    and free all validator data (the validator will be destroyed when the module is unloaded)\r
+    Note: we don't need to disconnect the terminal since it's already stopping */\r
+       case GF_TERM_EXT_STOP:\r
+        gf_term_remove_event_filter(validator->term, &validator->evt_filter);\r
+               validator_xvs_close(validator);\r
+        validator_xvl_close(validator);\r
+               validator->term = NULL;\r
+        if (validator->test_base) {\r
+            gf_free(validator->test_base);\r
+            validator->test_base = NULL;\r
+        }\r
+               /*auto-disable the recording by default*/\r
+               if (validator->is_recording) {\r
+                       gf_modules_set_option((GF_BaseInterface*)termext, "Validator", "Mode", "Play");\r
+               } else {\r
+                       gf_modules_set_option((GF_BaseInterface*)termext, "Validator", "Mode", "Disable");\r
+               }\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Stopping validator\n"));\r
+               if (validator->prev_fps) {\r
+                       gf_modules_set_option((GF_BaseInterface*)termext, "Compositor", "FrameRate", validator->prev_fps);\r
+            gf_free(validator->prev_fps);\r
+            validator->prev_fps = NULL;\r
+               }\r
+        if (validator->prev_alias) {\r
+               gf_modules_set_option((GF_BaseInterface*)termext, "Compositor", "AntiAlias", validator->prev_alias);\r
+            gf_free(validator->prev_alias);\r
+            validator->prev_alias = NULL;\r
+        }\r
+               break;\r
+\r
+    /* When called in the main loop of the terminal, we don't do anything in the recording mode.\r
+       In the playing/validating mode, we need to check if an event needs to be dispatched or if snapshots need to be made,\r
+       until there is no more event, in which case we trigger either the load of the next XVS or the quit */\r
+       case GF_TERM_EXT_PROCESS:\r
+        /* if the time is right, dispatch the event and load the next one */\r
+               while (!validator->is_recording && validator->evt_loaded && validator->ck && (validator->next_time <= gf_clock_time(validator->ck) )) {\r
+            Bool has_more_events;\r
+            u32 diff = gf_clock_time(validator->ck) - validator->next_time;\r
+            //GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Validator] Time diff: evt_time=%d  clock_time = %d, diff=%d\n", validator->next_time, gf_clock_time(validator->ck), diff));\r
+            if (validator->next_event_snapshot) {\r
+                Bool res;\r
+                char *snap_name = validator_create_snapshot(validator);\r
+                gf_free(snap_name);\r
+                res = validator_compare_snapshots(validator);\r
+                validator->xvs_result &= res; \r
+                validator->next_event_snapshot = 0;\r
+            } else {\r
+                validator->term->compositor->video_out->on_event(validator->term->compositor->video_out->evt_cbk_hdl, &validator->next_event);\r
+            }\r
+                   has_more_events = validator_load_event(validator);\r
+            if (!has_more_events) {\r
+                validator_xvs_close(validator);\r
+                gf_term_disconnect(validator->term);\r
+                gf_sc_remove_video_listener(validator->term->compositor, &validator->video_listener);\r
+                validator_xvs_next(validator, 0);\r
+                if (!validator->xvs_node) {\r
+                    GF_Event evt;\r
+                    evt.type = GF_EVENT_QUIT;\r
+                    validator->term->compositor->video_out->on_event(validator->term->compositor->video_out->evt_cbk_hdl, &evt);                \r
+                } else {\r
+                    if (!validator->is_recording) {\r
+                        validator_load_event(validator);\r
+                    }\r
+                }\r
+            }\r
+               }\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+\r
+GF_TermExt *validator_new()\r
+{\r
+       GF_TermExt *dr;\r
+       GF_Validator *validator;\r
+       dr = (GF_TermExt*)gf_malloc(sizeof(GF_TermExt));\r
+       memset(dr, 0, sizeof(GF_TermExt));\r
+       GF_REGISTER_MODULE_INTERFACE(dr, GF_TERM_EXT_INTERFACE, "GPAC Test Validator", "gpac distribution");\r
+\r
+       GF_SAFEALLOC(validator, GF_Validator);\r
+       dr->process = validator_process;\r
+       dr->udta = validator;\r
+       return dr;\r
+}\r
+\r
+\r
+void validator_delete(GF_BaseInterface *ifce)\r
+{\r
+       GF_TermExt *dr = (GF_TermExt *) ifce;\r
+       GF_Validator *validator = dr->udta;\r
+       if (validator->prev_fps) gf_free(validator->prev_fps);\r
+       if (validator->prev_alias) gf_free(validator->prev_alias);\r
+    gf_free(validator);\r
+       gf_free(dr);\r
+}\r
+\r
+GF_EXPORT\r
+const u32 *QueryInterfaces() \r
+{\r
+       static u32 si [] = {\r
+               GF_TERM_EXT_INTERFACE,\r
+               0\r
+       };\r
+       return si; \r
+}\r
+\r
+GF_EXPORT\r
+GF_BaseInterface *LoadInterface(u32 InterfaceType) \r
+{\r
+       if (InterfaceType == GF_TERM_EXT_INTERFACE) return (GF_BaseInterface *)validator_new();\r
+       return NULL;\r
+}\r
+\r
+GF_EXPORT\r
+void ShutdownInterface(GF_BaseInterface *ifce)\r
+{\r
+       switch (ifce->InterfaceType) {\r
+       case GF_TERM_EXT_INTERFACE:\r
+               validator_delete(ifce);\r
+               break;\r
+       }\r
+}\r
index 7c111cef7a5b0e5257308c56c9ae809ee9237fee..0c1e0d36719530037b0aa43d76912e2d05d5fb32 100644 (file)
@@ -25,26 +25,26 @@ endif
 
 ifeq ($(X11_LIB_PATH), )
 else
-LDFLAGS+=-L$(X11_LIB_PATH)
+EXTRALIBS+=-L$(X11_LIB_PATH)
 endif
 
 ifeq ($(USE_X11_XV), yes)
 CFLAGS+=-DGPAC_HAS_X11_XV
-LDFLAGS+=-lXv
+EXTRALIBS+=-lXv
 endif
 
 ifeq ($(USE_X11_SHM), yes)
 CFLAGS+=-DGPAC_HAS_X11_SHM
-LDFLAGS+=-lXext
+EXTRALIBS+=-lXext
 endif
 
 ifeq ($(HAS_OPENGL), yes)
 ifeq ($(GPAC_USE_TINYGL), yes)
 else
 CFLAGS+=$(OGL_INCLS)
-LDFLAGS+=$(OGL_LIBS)
+EXTRALIBS+=$(OGL_LIBS)
 ifeq ($(CONFIG_DARWIN),yes)
-LDFLAGS+=-lGL -lGLU
+EXTRALIBS+=-lGL -lGLU
 endif
 endif
 endif
@@ -64,9 +64,9 @@ all: $(LIB)
 
 
 $(LIB): $(OBJS)
-       $(CC) $(SHFLAGS) $(LDFLAGS) -lX11 -L../../bin/gcc -lgpac -o ../../bin/gcc/$@ $(OBJS)
+       $(CC) $(SHFLAGS) $(LDFLAGS) -lX11 -L../../bin/gcc -lgpac -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS)
 ifeq ($(STATICBUILD),yes)
-       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_x11_out-static.$(DYN_LIB_SUFFIX) $(OBJS) -lX11 -L../../bin/gcc -lgpac_static
+       $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_x11_out-static.$(DYN_LIB_SUFFIX) $(OBJS) -lX11 -L../../bin/gcc -lgpac_static $(EXTRALIBS)
 endif
 
 #static-bin:
index a25466218033b420ee730307dc810bc341196e99..b9ef39686b8289d9e550ae8238b9ac4d443850a7 100644 (file)
@@ -680,6 +680,7 @@ static GF_Err X11_SetupGL(GF_VideoOutput *vout)
 
   if ( ! glXMakeCurrent(xWin->display, xWin->fullscreen ? xWin->full_wnd : xWin->wnd, xWin->glx_context) ) return GF_IO_ERR;
   XSync(xWin->display, False);
+  memset(&evt, 0, sizeof(GF_Event));
   evt.type = GF_EVENT_VIDEO_SETUP;
   vout->on_event (vout->evt_cbk_hdl,&evt);
   xWin->is_init = 1;
@@ -970,7 +971,9 @@ GF_Err X11_SetFullScreen (struct _video_out * vout, u32 bFullScreenOn, u32 * scr
                XUnmapWindow (xWindow->display, xWindow->full_wnd);
                XMapWindow (xWindow->display, xWindow->wnd);
                XUngrabKeyboard(xWindow->display, CurrentTime);
-               if (xWindow->par_wnd) XSetInputFocus(xWindow->display, xWindow->wnd, RevertToNone, CurrentTime);
+               /*looks like this makes osmozilla crash*/
+               //if (xWindow->par_wnd) XSetInputFocus(xWindow->display, xWindow->wnd, RevertToNone, CurrentTime);
+
                /*backbuffer resize will be done right after this is called */
        }
 #ifdef GPAC_HAS_OPENGL
index da27339990305cfb27a6bf17f5a5f3e754f949ad..d105a1286b1595cbf60ccfed2f48aaf8fc3a4e43 100644 (file)
@@ -20,7 +20,7 @@ OBJS=xvid_dec.o
 #local xvid lib
 ifeq ($(CONFIG_XVID), local)
 CFLAGS+= -I"$(LOCAL_INC_PATH)/xvid"
-LDFLAGS+= -L../../extra_lib/lib/gcc
+EXTRALIBS+= -L../../extra_lib/lib/gcc
 endif
 EXTRALIBS+= -lxvidcore -lpthread
 
index 11c3eb66566676201c03e94f66556687518cf8c9..a733e108627d2b5e4dbaea47e2a400f2a7cd6760 100644 (file)
@@ -31,7 +31,7 @@ OrderedGroup {
    title "Anchor Test"
   }
   Anchor {
-   url ["bifs-linking-anchor-mp4-prev.mp4"]
+   url ["bifs-linking-anchor-mp4-prev.bt"]
    children [
     Shape {
      appearance Appearance {
index 4965245aae4aa13022774ce543023aca8df0cab7..a1d3866c4e97751c729d7bb9a7bfc115fbde796e 100644 (file)
@@ -41,7 +41,7 @@ OrderedGroup {
    scale 1.5 1
    children [
     Inline {
-     url ["bifs-linking-inline-direct-inline.mp4"]
+     url ["bifs-linking-inline-direct-inline.bt"]
     }
    ]
   }
index 248abcbafde38de774c78eb0d9c94636bbfb7798..06c8800587d49a2977a713f11b46483fcfa9c8b6 100644 (file)
@@ -36,7 +36,7 @@ LIBGPAC_SCENE=scenegraph/base_scenegraph.o scenegraph/mpeg4_animators.o scenegra
 LIBGPAC_MCRYPT=mcrypt/cbc.o mcrypt/cfb.o mcrypt/ctr.o mcrypt/des.o mcrypt/ecb.o mcrypt/g_crypt.o mcrypt/ncfb.o mcrypt/nofb.o mcrypt/ofb.o mcrypt/rijndael-128.o mcrypt/rijndael-192.o mcrypt/rijndael-256.o mcrypt/stream.o mcrypt/tripledes.o mcrypt/sha1.o 
 
 ## libgpac objects gathering: src/media tools
-LIBGPAC_MEDIATOOLS=media_tools/av_parsers.o media_tools/avilib.o media_tools/dvb.o media_tools/filestreamer.o media_tools/gpac_ogg.o media_tools/img.o media_tools/ismacryp.o media_tools/isom_hinter.o media_tools/isom_tools.o media_tools/media_export.o media_tools/media_import.o media_tools/mpeg2_ps.o media_tools/text_import.o media_tools/saf.o media_tools/mpegts.o media_tools/dvb_mpe.o  media_tools/reedsolomon.o media_tools/vobsub.o media_tools/m2ts_mux.o media_tools/m3u8.o media_tools/mpd.o media_tools/carousel.o  
+LIBGPAC_MEDIATOOLS=media_tools/ait.o media_tools/av_parsers.o media_tools/avilib.o media_tools/dsmcc.o media_tools/dvb.o media_tools/filestreamer.o media_tools/gpac_ogg.o media_tools/img.o media_tools/ismacryp.o media_tools/isom_hinter.o media_tools/isom_tools.o media_tools/media_export.o media_tools/media_import.o media_tools/mpeg2_ps.o media_tools/text_import.o media_tools/saf.o media_tools/mpegts.o media_tools/dvb_mpe.o  media_tools/reedsolomon.o media_tools/vobsub.o media_tools/m2ts_mux.o media_tools/m3u8.o media_tools/mpd.o
 
 ## libgpac objects gathering: src/scene_manager
 LIBGPAC_SCENEMANAGER=scene_manager/loader_bt.o scene_manager/loader_isom.o scene_manager/loader_qt.o scene_manager/loader_xmt.o scene_manager/scene_dump.o scene_manager/scene_manager.o scene_manager/scene_stats.o scene_manager/swf_parse.o scene_manager/swf_bifs.o scene_manager/text_to_bifs.o scene_manager/scene_engine.o scene_manager/encode_isom.o scene_manager/loader_svg.o
@@ -175,6 +175,7 @@ endif
 
 ifeq ($(CONFIG_SUNOS), yes)
 LD_SONAME="-Wl,-h,$(LIB)"
+LINKLIBS+= -lrt
 endif
 
 SRCS := $(OBJS:.o=.c) 
index 0c9829f626b154c59601a5b46cd218726bfb430a..220014bf3db32ec198e58d888bac15a388899258 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /*
-       DO NOT MOFIFY - File generated on GMT Wed Jul 20 05:50:21 2011
+       DO NOT MOFIFY - File generated on GMT Tue Nov 08 09:10:57 2011
 
        BY MPEG4Gen for GPAC Version 0.4.6-DEV
 */
index 3a9044d0d67dbd0bc4f7dd0248b18ae024b6b756..21d8f19f00aa464257abea5caaebe266158b19a8 100644 (file)
@@ -179,7 +179,7 @@ static GF_Err BD_XReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
                                memcpy(&sffield, &targetField, sizeof(GF_FieldInfo));
                                sffield.fieldType = sftype;
                                sffield.far_ptr = slot_ptr;
-                               gf_bifs_dec_sf_field(codec, bs, target, &sffield);
+                               gf_bifs_dec_sf_field(codec, bs, target, &sffield, 0);
                        }
                }
                gf_bifs_check_field_change(target, &targetField);
@@ -227,7 +227,7 @@ static GF_Err BD_XReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
                                list = list->next;
                        }
                } else {
-                       e = gf_bifs_dec_field(codec, bs, target, &targetField);
+                       e = gf_bifs_dec_field(codec, bs, target, &targetField, 0);
                        if (e) return e;
                }
                if (previous)
@@ -245,7 +245,7 @@ static GF_Err BD_XReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
                        if (fromField.fieldType == targetField.fieldType) 
                                gf_sg_vrml_field_clone(targetField.far_ptr, fromField.far_ptr, targetField.fieldType, codec->current_graph);
                } else {        
-                       e = gf_bifs_dec_field(codec, bs, target, &targetField);
+                       e = gf_bifs_dec_field(codec, bs, target, &targetField, 0);
                }
                break;
        }
@@ -332,7 +332,7 @@ static GF_Err BD_DecMultipleIndexReplace(GF_BifsDecoder * codec, GF_BitStream *b
 
                e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & sffield.far_ptr, pos);
                if (e) return e;
-               e = gf_bifs_dec_sf_field(codec, bs, node, &sffield);
+               e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 0);
                if (e) break;
                count--;
        }
@@ -641,7 +641,7 @@ static GF_Err BD_DecIndexInsert(GF_BifsDecoder * codec, GF_BitStream *bs)
                        e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & sffield.far_ptr, pos);
                }
                if (e) return e;
-               e = gf_bifs_dec_sf_field(codec, bs, def, &sffield);
+               e = gf_bifs_dec_sf_field(codec, bs, def, &sffield, 0);
                if (!e) gf_bifs_check_field_change(def, &field);
        }
        return e;
@@ -806,7 +806,7 @@ static GF_Err BD_DecFieldReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
 
        /*parse the field*/
        codec->is_com_dec = 1;
-       e = gf_bifs_dec_field(codec, bs, node, &field);
+       e = gf_bifs_dec_field(codec, bs, node, &field, 0);
        codec->is_com_dec = 0;
        /*remove prev nodes*/
        if (field.fieldType == GF_SG_VRML_SFNODE) {
@@ -883,7 +883,7 @@ static GF_Err BD_DecIndexValueReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
 
                e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & sffield.far_ptr, pos);
                if (e) return e;
-               e = gf_bifs_dec_sf_field(codec, bs, node, &sffield);
+               e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 0);
                if (!e) gf_bifs_check_field_change(node, &field);
        }
 
@@ -981,7 +981,7 @@ static GF_Err BD_DecReplace(GF_BifsDecoder * codec, GF_BitStream *bs)
 GF_Err gf_bifs_dec_proto_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List *proto_list)
 {
        u8 flag, field_type, event_type, useQuant, useAnim, f;
-       u32 i, NbRoutes, ID, numProtos, numFields, count, qpsftype, QP_Type, NumBits, Anim_Type;
+       u32 i, NbRoutes, ID, numProtos, numFields, count, qpsftype, QP_Type, NumBits;
        GF_Node *node;
        char name[1000];
        GF_ProtoFieldInterface *proto_field;
@@ -1045,7 +1045,7 @@ GF_Err gf_bifs_dec_proto_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List
                        case GF_SG_EVENT_FIELD:
                                /*parse default value except nodes ...*/
                                if (gf_sg_vrml_is_sf_field(field_type)) {
-                                       e = gf_bifs_dec_sf_field(codec, bs, NULL, &field);
+                                       e = gf_bifs_dec_sf_field(codec, bs, NULL, &field, 0);
                                } else {
                                        f = 0;
                                        if (codec->info->config.UsePredictiveMFField) {
@@ -1121,6 +1121,9 @@ GF_Err gf_bifs_dec_proto_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List
                                e = gf_node_register(node, NULL);
                                if (e) goto exit;
 
+                               //Ivica patch - Flush immediately because of proto instantiation
+                               gf_bifs_flush_command_list(codec);
+
                                gf_sg_proto_add_node_code(proto, node);
                                flag = gf_bs_read_int(bs, 1);
                        }
@@ -1186,12 +1189,12 @@ GF_Err gf_bifs_dec_proto_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List
                                        qp_min_value = gf_sg_vrml_field_pointer_new(qpsftype);
                                        field.name = "QPMinValue";
                                        field.far_ptr = qp_min_value;
-                                       gf_bifs_dec_sf_field(codec, bs, NULL, &field);
+                                       gf_bifs_dec_sf_field(codec, bs, NULL, &field, 0);
 
                                        qp_max_value = gf_sg_vrml_field_pointer_new(qpsftype);
                                        field.name = "QPMaxValue";
                                        field.far_ptr = qp_max_value;
-                                       gf_bifs_dec_sf_field(codec, bs, NULL, &field);
+                                       gf_bifs_dec_sf_field(codec, bs, NULL, &field, 0);
                                }
 
                                /*and store*/
@@ -1206,9 +1209,7 @@ GF_Err gf_bifs_dec_proto_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List
                        if (useAnim && ( (field.eventType == GF_SG_EVENT_IN) || (field.eventType == GF_SG_EVENT_EXPOSED_FIELD) )) {
                                flag = gf_bs_read_int(bs, 1);
                                if (flag) {
-                                       Anim_Type = gf_bs_read_int(bs, 4);
-                               } else {
-                                       Anim_Type = 0;
+                                       /*Anim_Type = */gf_bs_read_int(bs, 4);
                                }
                        }
                }
index cb4a5a03406f21605ead9ca457abccc47b4775b4..71ba7420639e7d1d7ef111d3acda09f5b0920a32 100644 (file)
@@ -34,9 +34,14 @@ GF_Err BE_EncProtoList(GF_BifsEncoder *codec, GF_List *protoList, GF_BitStream *
 void gf_bifs_enc_name(GF_BifsEncoder *codec, GF_BitStream *bs, char *name)
 {
        u32 i = 0;
-       while (name[i]) {
-               gf_bs_write_int(bs, name[i], 8);
-               i++;
+       if (!name) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] Coding IDs using names but no name is specified\n"));
+               i = 1;
+       } else {
+               while (name[i]) {
+                       gf_bs_write_int(bs, name[i], 8);
+                       i++;
+               }
        }
        gf_bs_write_int(bs, 0, 8);
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] DEF\t\t%d\t\t%s\n", 8*i, name));
index 2de3b9a6cbf6a0ece3b914d542acbe59905255cb..2016cf6ebba42383a8251299221446d452252157 100644 (file)
@@ -55,19 +55,18 @@ void Conditional_BufferReplaced(GF_BifsDecoder *codec, GF_Node *n)
 
 static void Conditional_execute(M_Conditional *node)
 {
-       GF_Err e;
        char *buffer;
        u32 len;
        GF_BitStream *bs;
        GF_BifsDecoder *codec;
        GF_Proto *prevproto;
-       GF_SceneGraph *prev_graph, *cur_graph;
+       GF_SceneGraph *prev_graph;
        ConditionalStack *priv = (ConditionalStack*)gf_node_get_private((GF_Node*)node);
        if (!priv) return;
 
        /*set the codec working graph to the node one (to handle conditional in protos)*/
        prev_graph = priv->codec->current_graph;
-       cur_graph = priv->codec->current_graph = gf_node_get_graph((GF_Node*)node);
+       priv->codec->current_graph = gf_node_get_graph((GF_Node*)node);
        assert(priv->codec->current_graph);
 
        priv->codec->info = priv->info;
@@ -94,7 +93,7 @@ static void Conditional_execute(M_Conditional *node)
        /*and a conditional may destroy the entire scene!*/
        cur_graph->graph_has_been_reset = 0;
 #endif
-       e = gf_bifs_dec_command(codec, bs);
+       gf_bifs_dec_command(codec, bs);
        gf_bs_del(bs);
 #ifdef GF_SELF_REPLACE_ENABLE
        if (cur_graph->graph_has_been_reset) {
@@ -104,7 +103,7 @@ static void Conditional_execute(M_Conditional *node)
        if (node->buffer.buffer) {
                gf_free(buffer);
        } else {
-               node->buffer.buffer = buffer;
+               node->buffer.buffer = (u8*)buffer;
                node->buffer.bufferSize = len;
        }
        //set isActive - to clarify in the specs
index 1653e99d0cec997f73bcf57d804ef7e9975f2020..b39422ea164016870e6ad7093afe8fbca14e3539 100644 (file)
@@ -70,7 +70,7 @@ Fixed BD_ReadSFFloat(GF_BifsDecoder * codec, GF_BitStream *bs)
 }
 
 
-GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
+GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com)
 {
        GF_Err e;
        GF_Node *new_node;
@@ -125,8 +125,15 @@ GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *n
                if (node && (node->sgprivate->tag==TAG_MPEG4_CacheTexture) && (field->fieldIndex<=2)) {
                        M_CacheTexture *ct = (M_CacheTexture *) node;
                        ct->data_len = length;
+                       if (ct->data) gf_free(ct->data);
                        ct->data = gf_malloc(sizeof(char)*length);
-                       gf_bs_read_data(bs, ct->data, length);
+                       gf_bs_read_data(bs, (char*)ct->data, length);
+               } else if (node && (node->sgprivate->tag==TAG_MPEG4_BitWrapper) ) {
+                       M_BitWrapper *bw = (M_BitWrapper*) node;
+                       if (bw->buffer.buffer) gf_free(bw->buffer.buffer);
+                       bw->buffer_len = length;
+                       bw->buffer.buffer = gf_malloc(sizeof(char)*length);
+                       gf_bs_read_data(bs, (char*)bw->buffer.buffer, length);
                } else {
                        if ( ((SFString *)field->far_ptr)->buffer ) gf_free( ((SFString *)field->far_ptr)->buffer);
                        ((SFString *)field->far_ptr)->buffer = (char *)gf_malloc(sizeof(char)*(length+1));
@@ -231,7 +238,7 @@ GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *n
                //for nodes the field ptr is a ptr to the field, which is a node ptr ;)
                new_node = gf_bifs_dec_node(codec, bs, field->NDTtype);
                if (new_node) {
-                       e = gf_node_register(new_node, node);
+                       e = gf_node_register(new_node, is_mem_com ? NULL : node);
                        if (e) return e;
                }
                //it may happen that new_node is NULL (this is valid for a proto declaration)
@@ -264,7 +271,7 @@ GF_Err gf_bifs_dec_sf_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *n
        return codec->LastError;
 }
 
-GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
+GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com)
 {
        GF_Node *new_node;
        GF_Err e;
@@ -288,12 +295,12 @@ GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node
                e = GF_OK;;
                if (field->fieldType != GF_SG_VRML_MFNODE) {
                        e = gf_sg_vrml_mf_append(field->far_ptr, field->fieldType, & sffield.far_ptr);
-                       e = gf_bifs_dec_sf_field(codec, bs, node, &sffield);
+                       e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 0);
                } else {
                        new_node = gf_bifs_dec_node(codec, bs, field->NDTtype);
                        //append
                        if (new_node) {
-                               e = gf_node_register(new_node, node);
+                               e = gf_node_register(new_node, is_mem_com ? NULL : node);
                                if (e) return e;
 
                                //regular coding
@@ -353,7 +360,7 @@ GF_Err BD_DecMFFieldList(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node
        return GF_OK;
 }
 
-GF_Err BD_DecMFFieldVec(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
+GF_Err BD_DecMFFieldVec(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com)
 {
        GF_Err e;
        u32 NbBits, nbFields;
@@ -387,14 +394,14 @@ GF_Err BD_DecMFFieldVec(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node,
                for (i=0;i<nbFields; i++) {
                        e = gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, & sffield.far_ptr, i);
                        if (e) return e;
-                       e = gf_bifs_dec_sf_field(codec, bs, node, &sffield);
+                       e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 0);
                }
        } else {
                last = NULL;
                for (i=0;i<nbFields; i++) {
                        new_node = gf_bifs_dec_node(codec, bs, field->NDTtype);
                        if (new_node) {
-                               e = gf_node_register(new_node, node);
+                               e = gf_node_register(new_node, is_mem_com ? NULL : node);
                                if (e) return e;
 
                                if (node) {
@@ -463,7 +470,7 @@ void gf_bifs_check_field_change(GF_Node *node, GF_FieldInfo *field)
 
 }
 
-GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
+GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com)
 {
        GF_Err e;
        u8 flag;
@@ -474,7 +481,7 @@ GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node
 //     if (field->fieldType == GF_SG_VRML_UNKNOWN) return GF_NON_COMPLIANT_BITSTREAM;
        
        if (gf_sg_vrml_is_sf_field(field->fieldType)) {
-               e = gf_bifs_dec_sf_field(codec, bs, node, field);
+               e = gf_bifs_dec_sf_field(codec, bs, node, field, is_mem_com);
                if (e) return e;
        } else {
                /*clean up the eventIn field if not done*/
@@ -512,9 +519,9 @@ GF_Err gf_bifs_dec_field(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node
                        /*List description - alloc is dynamic*/
                        flag = gf_bs_read_int(bs, 1);
                        if (flag) {
-                               e = BD_DecMFFieldList(codec, bs, node, field);
+                               e = BD_DecMFFieldList(codec, bs, node, field, is_mem_com);
                        } else {
-                               e = BD_DecMFFieldVec(codec, bs, node, field);
+                               e = BD_DecMFFieldVec(codec, bs, node, field, is_mem_com);
                        }
                        if (e) return e;
                }
@@ -576,7 +583,7 @@ GF_Err gf_bifs_dec_node_list(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *
                if (e) return e;
                e = gf_node_get_field(node, field_all, &field);
                if (e) return e;
-               e = gf_bifs_dec_field(codec, bs, node, &field);
+               e = gf_bifs_dec_field(codec, bs, node, &field, 0);
                if (e) return e;
                flag = gf_bs_read_int(bs, 1);
 
@@ -614,7 +621,7 @@ GF_Err gf_bifs_dec_node_mask(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *
                        else {
                                e = gf_node_get_field(node, i, &field);
                                if (e) return e;
-                               e = gf_bifs_dec_field(codec, bs, node, &field);
+                               e = gf_bifs_dec_field(codec, bs, node, &field, 0);
                        }
                        if (e) return e;
                }
@@ -628,7 +635,7 @@ GF_Err gf_bifs_dec_node_mask(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *
                        gf_bifs_get_field_index(node, i, GF_SG_FIELD_CODING_DEF, &index);
                        e = gf_node_get_field(node, index, &field);
                        if (e) return e;
-                       e = gf_bifs_dec_field(codec, bs, node, &field);
+                       e = gf_bifs_dec_field(codec, bs, node, &field, 0);
                        if (e) return e;
 
                        if (is_proto) gf_sg_proto_mark_field_loaded(node, &field);
@@ -683,7 +690,6 @@ static void UpdateTimeNode(GF_BifsDecoder * codec, GF_Node *node)
 GF_Node *gf_bifs_dec_node(GF_BifsDecoder * codec, GF_BitStream *bs, u32 NDT_Tag)
 {
        u32 nodeID, NDTBits, node_type, node_tag, ProtoID, BVersion;
-       u8 node_flag;
        Bool skip_init, reset_qp14;
        GF_Node *new_node;
        GF_Err e;
@@ -703,7 +709,6 @@ GF_Node *gf_bifs_dec_node(GF_BifsDecoder * codec, GF_BitStream *bs, u32 NDT_Tag)
 
 
        BVersion = GF_BIFS_V1;
-       node_flag = 0;
 
        /*this is a USE statement*/
        if (gf_bs_read_int(bs, 1)) {
index 1d3c0950dea0c9532b0f3ff63916d22a2857b1f1..56e4f920a292c66adb57caa19cdb8b46e7a1c7bd 100644 (file)
@@ -107,10 +107,14 @@ GF_Err gf_bifs_enc_sf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *no
                                size -= read;
                        }
                } else {
-                       u32 i;
+                       u32 i, len, val;
                        char *str = (char *) ((SFString*)field->far_ptr)->buffer;
-                       u32 len = str ? strlen(str) : 0;
-                       u32 val = gf_get_bit_size(len);
+                       if (node && (node->sgprivate->tag==TAG_MPEG4_BitWrapper) ) {
+                               len = ((M_BitWrapper*)node)->buffer_len;
+                       } else {
+                               len = str ? strlen(str) : 0;
+                       }
+                       val = gf_get_bit_size(len);
                        GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL);
                        GF_BIFS_WRITE_INT(codec, bs, len, val, "length", NULL);
                        for (i=0; i<len; i++) gf_bs_write_int(bs, str[i], 8);
index 012781ae10c52d57a8bcb85bd1b2015114e3bd58..ae4f9de61b88dcd4dcdbee8519b0d7557788f023 100644 (file)
@@ -79,7 +79,7 @@ static GF_Err BM_ParseMultipleIndexedReplace(GF_BifsDecoder *codec, GF_BitStream
                        gf_node_register(inf->new_node, NULL);
                } else {
                        field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
-                       e = gf_bifs_dec_sf_field(codec, bs, node, &field);
+                       e = gf_bifs_dec_sf_field(codec, bs, node, &field, 1);
                        if (e) goto err;
                }
                count--;
@@ -126,7 +126,7 @@ static GF_Err BM_ParseMultipleReplace(GF_BifsDecoder *codec, GF_BitStream *bs, G
                        } else {
                                field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
                        }
-                       e = gf_bifs_dec_field(codec, bs, node, &field);
+                       e = gf_bifs_dec_field(codec, bs, node, &field, 1);
                        if (e) goto exit;
                }
        } else {
@@ -148,7 +148,7 @@ static GF_Err BM_ParseMultipleReplace(GF_BifsDecoder *codec, GF_BitStream *bs, G
                        } else {
                                field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
                        }
-                       e = gf_bifs_dec_field(codec, bs, node, &field);
+                       e = gf_bifs_dec_field(codec, bs, node, &field, 1);
                        if (e) goto exit;
                        flag = gf_bs_read_int(bs, 1);
                }
@@ -342,7 +342,7 @@ static GF_Err BM_XReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_
        } else {
                decfield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType);
        }
-       e = gf_bifs_dec_sf_field(codec, bs, target, &decfield);
+       e = gf_bifs_dec_sf_field(codec, bs, target, &decfield, 1);
        if (e) return e;
 
        gf_list_add(com_list, com);
@@ -511,7 +511,7 @@ GF_Err BM_ParseIndexInsert(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com
                inf->fieldIndex = field_ind;
                inf->fieldType = sffield.fieldType;
                sffield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(sffield.fieldType);
-               codec->LastError = gf_bifs_dec_sf_field(codec, bs, def, &sffield);
+               codec->LastError = gf_bifs_dec_sf_field(codec, bs, def, &sffield, 1);
                gf_list_add(com_list, com);
        }
        return codec->LastError;
@@ -723,7 +723,7 @@ GF_Err BM_ParseFieldReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *co
                field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(field.fieldType);
        }
        /*parse the field*/
-       codec->LastError = gf_bifs_dec_field(codec, bs, node, &field);
+       codec->LastError = gf_bifs_dec_field(codec, bs, node, &field, 1);
 
        gf_list_add(com_list, com);
        return codec->LastError;
@@ -783,7 +783,7 @@ GF_Err BM_ParseIndexValueReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_Lis
                sffield.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
                inf->fieldType = sffield.fieldType;
                sffield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(sffield.fieldType);
-               codec->LastError = gf_bifs_dec_sf_field(codec, bs, node, &sffield);
+               codec->LastError = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 1);
        }
        gf_list_add(com_list, com);
        return codec->LastError;
@@ -794,12 +794,9 @@ GF_Err BM_ParseRouteReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *co
        GF_Err e;
        GF_Command *com;
        u32 RouteID, numBits, ind, node_id, fromID, toID;
-       GF_Route *r;
        GF_Node *OutNode, *InNode;
 
        RouteID = 1+gf_bs_read_int(bs, codec->info->config.RouteIDBits);
-       
-       r = gf_sg_route_find(codec->current_graph, RouteID);
 
        /*origin*/
        node_id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits);
index e86426afc11dca2b61478ba35c60e4c06b553fb6..3f5be2474cf1327d0b3383ee80825c4a936b62f9 100644 (file)
@@ -128,7 +128,7 @@ GF_Err ParseScriptField(ScriptParser *parser)
                if (gf_bs_read_int(parser->bs, 1)) {
                        e = gf_sg_script_field_get_info(field, &info);
                        if (e) return e;
-                       gf_bifs_dec_field(parser->codec, parser->bs, parser->script, &info);
+                       gf_bifs_dec_field(parser->codec, parser->bs, parser->script, &info, 0);
                }
        }
 
@@ -159,7 +159,6 @@ GF_Err SFScript_Parse(GF_BifsDecoder *codec, SFScript *script_field, GF_BitStrea
        u32 i, count, nbBits;
        char *ptr;
        ScriptParser parser;
-       Bool has_fields = 0;
        e = GF_OK;
        if (gf_node_get_tag(n) != TAG_MPEG4_Script) return GF_NON_COMPLIANT_BITSTREAM;
 
@@ -180,7 +179,6 @@ GF_Err SFScript_Parse(GF_BifsDecoder *codec, SFScript *script_field, GF_BitStrea
                while (!gf_bs_read_int(bs, 1)){
                        e = ParseScriptField(&parser);
                        if (e) goto exit;
-                       else has_fields = 1;
                }
        } else {
                nbBits = gf_bs_read_int(bs, 4);
@@ -188,7 +186,6 @@ GF_Err SFScript_Parse(GF_BifsDecoder *codec, SFScript *script_field, GF_BitStrea
                for (i=0; i<count; i++) {
                        e = ParseScriptField(&parser);
                        if (e) goto exit;
-                       else has_fields = 1;
                }
        }
        //reserevd
index 3b01a7873cee7bab73e7db10f6345dbf788ac9dc..c02b2323144585311405059fefc1e916d0029359 100644 (file)
@@ -191,13 +191,13 @@ void gf_sc_audio_predestroy(GF_AudioInput *ai)
 }
 
 GF_EXPORT
-GF_Err gf_sc_audio_open(GF_AudioInput *ai, MFURL *url, Double clipBegin, Double clipEnd)
+GF_Err gf_sc_audio_open(GF_AudioInput *ai, MFURL *url, Double clipBegin, Double clipEnd, Bool lock_timeline)
 {
        u32 i;
        if (ai->is_open) return GF_BAD_PARAM;
 
        /*get media object*/
-       ai->stream = gf_mo_register(ai->owner, url, 0, 0);
+       ai->stream = gf_mo_register(ai->owner, url, lock_timeline, 0);
        /*bad URL*/
        if (!ai->stream) return GF_NOT_SUPPORTED;
 
index 02b047d26d891d9c47d1abc318390c4c57b0d1fa..cc9704b0b2f62dd0e175234fadcef5e8681f31b6 100644 (file)
@@ -362,7 +362,7 @@ u32 gf_ar_proc(void *p)
                /*THIS IS NEEDED FOR SYMBIAN - if no yield here, the audio module always grabs the 
                main mixer mutex and it takes forever before it can be grabed by another thread, 
                for instance when reconfiguring scene*/
-               gf_sleep(0);
+               gf_sleep(1);
 
                gf_mixer_lock(ar->mixer, 1);
                if (ar->Frozen || gf_mixer_empty(ar->mixer) ) {
index 5a4a7ba7e2e60d098f4d554fb4c807f2f030fbba..d92ea3e09e3843a3f8ea65643f139a2164bdb799 100644 (file)
@@ -401,6 +401,7 @@ void camera_reset_viewpoint(GF_Camera *cam, Bool animate)
        if (!animate || (cam->had_viewpoint==2) ) {
                camera_set_vectors(cam, cam->vp_position, cam->vp_orientation, cam->vp_fov);
                cam->last_pos = cam->vp_position;
+               cam->anim_len = 0;
                return;
        }
 #ifndef FORCE_CAMERA_3D
index fea5db4d6fe4ab1f21201def7bc75fa120c5d682..7bdfb702b6bf5b4b7c1d44abb6ec288c294861aa 100644 (file)
@@ -44,6 +44,8 @@ void gf_sc_next_frame_state(GF_Compositor *compositor, u32 state)
 {
        GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor] Forcing frame redraw state: %d\n", state));
        compositor->frame_draw_type = state;
+       if (state==GF_SC_DRAW_FLUSH)
+               compositor->skip_flush = 2;
 }
 
 
@@ -474,7 +476,7 @@ GF_Compositor *gf_sc_new(GF_User *user, Bool self_threaded, GF_Terminal *term)
 
                /*wait until init is done*/
                while (tmp->video_th_state < GF_COMPOSITOR_THREAD_RUN) {
-                       gf_sleep(0);
+                       gf_sleep(1);
                }
                /*init failure*/                
                if (tmp->video_th_state == GF_COMPOSITOR_THREAD_INIT_FAILED) {
@@ -1001,6 +1003,14 @@ void gf_sc_reload_config(GF_Compositor *compositor)
        /*changing drivers needs exclusive access*/
        gf_sc_lock(compositor, 1);
        
+
+       sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "FrameRate");
+       if (!sOpt) {
+               sOpt = "30.0";
+               gf_cfg_set_key(compositor->user->config, "Compositor", "FrameRate", "30.0");
+       }
+       gf_sc_set_fps(compositor, atof(sOpt));
+
        sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "ForceSceneSize");
        if (sOpt && ! stricmp(sOpt, "yes")) {
                compositor->override_size_flags = 1;
@@ -1244,7 +1254,7 @@ void gf_sc_reload_config(GF_Compositor *compositor)
        
 #ifdef GF_SR_USE_DEPTH
        sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "AutoStereoCalibration");
-       compositor->auto_calibration = (!sOpt || !strcmp(sOpt, "yes")) ? 1 : 0;
+       compositor->auto_calibration = (sOpt && !strcmp(sOpt, "yes")) ? 1 : 0;
 
        sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "DisplayDepth");
        compositor->display_depth = sOpt ? (!strcmp(sOpt, "auto") ? -1 : atoi(sOpt)) : 0;
@@ -1632,10 +1642,10 @@ GF_Err gf_sc_get_screen_buffer(GF_Compositor *compositor, GF_VideoSurface *frame
 
 GF_Err gf_sc_get_offscreen_buffer(GF_Compositor *compositor, GF_VideoSurface *framebuffer, u32 view_idx, u32 depth_dump_mode)
 {
-       GF_Err e;
        if (!compositor || !framebuffer) return GF_BAD_PARAM;
 #ifndef GPAC_DISABLE_3D
        if (compositor->visual->type_3d && compositor->visual->nb_views && (compositor->visual->autostereo_type>GF_3D_STEREO_SIDE)) {
+               GF_Err e;
                gf_mx_p(compositor->mx);
                e = compositor_3d_get_offscreen_buffer(compositor, framebuffer, view_idx, depth_dump_mode);
                if (e != GF_OK) gf_mx_v(compositor->mx);
@@ -1736,8 +1746,8 @@ static void gf_sc_setup_root_visual(GF_Compositor *compositor, GF_Node *top_node
                        /*move to perspective 3D when simulating depth*/
 #ifdef GF_SR_USE_DEPTH
                        if (compositor->display_depth) {
-                               compositor->visual->type_3d = 2;
-                               compositor->visual->camera.is_3D = 1;
+                               compositor->visual->type_3d = 0;
+                               compositor->visual->camera.is_3D = 0;
                        } else 
 #endif
                        {
@@ -1837,7 +1847,7 @@ static void gf_sc_recompute_ar(GF_Compositor *compositor, GF_Node *top_node)
 #ifndef GPAC_DISABLE_LOG
                u32 time=0;
                
-               if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_RTI)) { 
+               if (gf_log_tool_level_on(GF_LOG_RTI, GF_LOG_DEBUG)) { 
                        time = gf_sys_clock();
                }
 #endif
@@ -1856,7 +1866,7 @@ static void gf_sc_recompute_ar(GF_Compositor *compositor, GF_Node *top_node)
                gf_sc_next_frame_state(compositor, GF_SC_DRAW_NONE);
 
 #ifndef GPAC_DISABLE_LOG
-               if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_RTI)) { 
+               if (gf_log_tool_level_on(GF_LOG_RTI, GF_LOG_DEBUG)) { 
                        compositor->visual_config_time = gf_sys_clock() - time;
                }
 #endif
@@ -1885,13 +1895,18 @@ static void gf_sc_draw_scene(GF_Compositor *compositor)
 
        flags = compositor->traverse_state->immediate_draw;
 
-       if (! visual_draw_frame(compositor->visual, top_node, compositor->traverse_state, 1))
-               compositor->skip_flush = 1;
-       
-               /*if using OpenGL, flush even if no changes as the display may be dirty (as seen on android, likely other devices)*/
+       if (! visual_draw_frame(compositor->visual, top_node, compositor->traverse_state, 1)) {
+               /*android backend uses opengl without telling it to us, we need an ugly hack here ...*/
 #ifdef GPAC_ANDROID
-                compositor->skip_flush = 0;
+               compositor->skip_flush = 0;
+#else
+               if (compositor->skip_flush==2) {
+                       compositor->skip_flush = 0;
+               } else {
+                       compositor->skip_flush = 1;
+               }
 #endif
+       }
 
 
        compositor->traverse_state->immediate_draw = flags;
@@ -2155,7 +2170,7 @@ void gf_sc_simulation_tick(GF_Compositor *compositor)
 
                if(compositor->user->init_flags & GF_TERM_INIT_HIDE) compositor->skip_flush = 1;
 
-               if (!compositor->skip_flush) {
+               if (compositor->skip_flush!=1) {
                        rc.x = rc.y = 0; 
                        rc.w = compositor->display_width;       
                        rc.h = compositor->display_height;              
@@ -2245,7 +2260,7 @@ void gf_sc_simulation_tick(GF_Compositor *compositor)
 
        /*TO CHECK - THERE WAS A BUG HERE WITH TRISCOPE@SHIX*/
        if (end_time > compositor->frame_duration) {
-               gf_sleep(0);
+               gf_sleep(1);
                return;
        }
 
@@ -2275,7 +2290,7 @@ void gf_sc_visual_unregister(GF_Compositor *compositor, GF_VisualManager *visual
        gf_list_del_item(compositor->visuals, visual);
 }
 
-void gf_sc_traverse_subscene(GF_Compositor *compositor, GF_Node *inline_parent, GF_SceneGraph *subscene, void *rs)
+void gf_sc_traverse_subscene_ex(GF_Compositor *compositor, GF_Node *inline_parent, GF_SceneGraph *subscene, void *rs)
 {
        Fixed min_hsize, vp_scale;
        Bool use_pm, prev_pm, prev_coord;
@@ -2516,6 +2531,17 @@ static Bool gf_sc_handle_event_intern(GF_Compositor *compositor, GF_Event *event
 #endif
 }
 
+void gf_sc_traverse_subscene(GF_Compositor *compositor, GF_Node *inline_parent, GF_SceneGraph *subscene, void *rs)
+{
+       u32 i=0;
+       GF_SceneGraph *subsg;
+
+       gf_sc_traverse_subscene_ex(compositor, inline_parent, subscene, rs);
+
+       while ( (subsg = gf_scene_enum_extra_scene(subscene, &i))) 
+               gf_sc_traverse_subscene_ex(compositor, inline_parent, subsg, rs);
+
+}
 
 static Bool gf_sc_on_event_ex(GF_Compositor *compositor , GF_Event *event, Bool from_user)
 {
@@ -2525,6 +2551,8 @@ static Bool gf_sc_on_event_ex(GF_Compositor *compositor , GF_Event *event, Bool
        if (compositor->msg_type & GF_SR_IN_RECONFIG) {
                if (event->type==GF_EVENT_VIDEO_SETUP) {
                        compositor->reset_graphics = 2;
+                       if (event->setup.back_buffer) 
+                               compositor->recompute_ar = 1;
                }
                return 0;
        }
@@ -2549,6 +2577,8 @@ static Bool gf_sc_on_event_ex(GF_Compositor *compositor , GF_Event *event, Bool
                {
                        Bool locked = gf_mx_try_lock(compositor->mx);
                        compositor->reset_graphics = 2;
+                       if (event->setup.back_buffer) 
+                               compositor->recompute_ar = 1;
                        if (locked) gf_mx_v(compositor->mx);
                }
                break;
@@ -2578,6 +2608,8 @@ static Bool gf_sc_on_event_ex(GF_Compositor *compositor , GF_Event *event, Bool
 
        case GF_EVENT_KEYDOWN:
        case GF_EVENT_KEYUP:
+       {
+               Bool ret;
                switch (event->key.key_code) {
                case GF_KEY_SHIFT: 
                        if (event->type==GF_EVENT_KEYDOWN) {
@@ -2602,14 +2634,16 @@ static Bool gf_sc_on_event_ex(GF_Compositor *compositor , GF_Event *event, Bool
                        break;
                
                }       
-               
+       
+               ret = 0;
                event->key.flags |= compositor->key_states;
                /*key sensor*/
                if (compositor->term && (compositor->interaction_level & GF_INTERACT_INPUT_SENSOR) ) {
-                       gf_term_keyboard_input(compositor->term, event->key.key_code, event->key.hw_code, (event->type==GF_EVENT_KEYUP) ? 1 : 0);
-               }       
-               
-               return gf_sc_handle_event_intern(compositor, event, from_user);
+                       ret = gf_term_keyboard_input(compositor->term, event->key.key_code, event->key.hw_code, (event->type==GF_EVENT_KEYUP) ? 1 : 0);
+               }                       
+               ret += gf_sc_handle_event_intern(compositor, event, from_user);
+               return ret;
+       }
 
        case GF_EVENT_TEXTINPUT:
                if (compositor->term && (compositor->interaction_level & GF_INTERACT_INPUT_SENSOR) )
index 4d7e66262e2075229db3fce6fed6b3f7d3d6096a..22636281af554d13a9ee657fd4824a31287aac3e 100644 (file)
@@ -282,6 +282,8 @@ GF_Err compositor_2d_get_video_access(GF_VisualManager *visual)
        }
        compositor->hw_locked = 0;
        visual->is_attached = 0;
+       /*if using BlitTexture, return OK to still be able to blit images*/
+       if (compositor->video_out->BlitTexture) e = GF_OK;
        return e;
 }
 
@@ -314,8 +316,8 @@ Bool compositor_texture_rectangles(GF_VisualManager *visual, GF_TextureHandler *
        if (disable_blit) *disable_blit = 0;
        if (has_scale) *has_scale = 0;
 
-       /*this should never happen but we check for float rounding safety*/
        if (final.width<=0 || final.height <=0) return 0;
+       if (txh->width==0 || txh->height==0) return 0;
 
 
        w_scale = final.width / txh->width;
@@ -456,7 +458,7 @@ static Bool compositor_2d_draw_bitmap_ex(GF_VisualManager *visual, GF_TextureHan
        }
 
        if (!compositor_texture_rectangles(visual, txh, clip, unclip, &src_wnd, &dst_wnd, &use_blit, &has_scale)) return 1;
-
+       
        /*can we use hardware blitter ?*/
        hw_caps = visual->compositor->video_out->hw_caps;
        overlay_type = 0;
@@ -483,8 +485,8 @@ static Bool compositor_2d_draw_bitmap_ex(GF_VisualManager *visual, GF_TextureHan
                case GF_PIXEL_BGR_24:
                case GF_PIXEL_RGBS:
                case GF_PIXEL_RGBD:
-               case GF_PIXEL_RGB_555:
-               case GF_PIXEL_RGB_565:
+//             case GF_PIXEL_RGB_555:
+//             case GF_PIXEL_RGB_565:
                        if (hw_caps & GF_VIDEO_HW_HAS_RGB)
                                use_soft_stretch = 0;
                        break;
@@ -635,7 +637,7 @@ static Bool compositor_2d_draw_bitmap_ex(GF_VisualManager *visual, GF_TextureHan
                                visual->compositor->video_memory = 2;
                        }
                        /*force a reconfigure of video output*/
-                       else {
+                       else if (visual->compositor->video_memory!=2) {
                                GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor2D] Reconfiguring video output to use video memory\n"));
                                visual->compositor->request_video_memory = 1;
                                visual->compositor->root_visual_setup = 0;
@@ -696,6 +698,8 @@ Bool compositor_2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_st
        if (!alpha) return 1;
 
        switch (ctx->aspect.fill_texture->pixelformat) {
+       case GF_PIXEL_ALPHAGREY:
+       case GF_PIXEL_GREYSCALE:
        case GF_PIXEL_RGB_24:
        case GF_PIXEL_BGR_24:
        case GF_PIXEL_RGB_555:
@@ -707,9 +711,10 @@ Bool compositor_2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_st
        case GF_PIXEL_YVYU:
        case GF_PIXEL_YUY2:
        case GF_PIXEL_I420:
+       case GF_PIXEL_NV21:
        case GF_PIXEL_YUVA:
        case GF_PIXEL_RGBS:
-       case GF_PIXEL_RGBAS:
+       case GF_PIXEL_RGBAS:            
                break;
        case GF_PIXEL_YUVD:
        case GF_PIXEL_RGBD:
index 74a389a27ab1dcce2015a1017b9e9cae05b83ce7..d1ab3966df8af3ed59bc48d52ef851de578cfd11 100644 (file)
 #include <gpac/nodes_x3d.h>
 
 
+
 void compositor_init_afx_node(GF_Compositor *compositor, GF_Node *node, MFURL *url)
 {
        GF_MediaObject *mo = gf_mo_register(node, url, 0, 0);
        if (!mo) {
-               GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] AFX Decoder not found for node %s - node will not be rendered\n", gf_node_get_class_name(node)));
+               GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] AFX Decoder not found for node %s - node may not be completely/correctly rendered\n", gf_node_get_class_name(node)));
+       }
+#ifndef GPAC_DISABLE_VRML
+       if (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper) {
+               compositor_init_bitwrapper(compositor, node);
        }
+#endif
 }
 
 
@@ -396,6 +402,9 @@ void gf_sc_on_node_init(GF_Compositor *compositor, GF_Node *node)
        case TAG_MPEG4_SBVCAnimation:                   
                compositor_init_afx_node(compositor, node, & ((M_SBVCAnimation *)node)->url); 
                break;
+       case TAG_MPEG4_BitWrapper:                      
+               compositor_init_afx_node(compositor, node, & ((M_BitWrapper *)node)->url); 
+               break;
 
        default:
                GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor] node %s will not be rendered\n", gf_node_get_class_name(node)));
@@ -452,6 +461,10 @@ void gf_sc_invalidate(GF_Compositor *compositor, GF_Node *byObj)
 
 #endif /*GPAC_DISABLE_VRML*/
 
+#ifndef GPAC_DISABLE_SVG
+       case TAG_SVG_video: compositor_svg_video_modified(compositor, byObj); break;
+#endif /*GPAC_DISABLE_SVG*/
+
        default:
                /*for all nodes, invalidate parent graph - note we do that for sensors as well to force recomputing
                sensor list cached at grouping node level*/
index f63ee46e5e306912ca4dea92978b538dfacb5740..cfb13404df8dcf6f0ad9fd9cea6421f87a4de09c 100644 (file)
@@ -803,9 +803,12 @@ void drawable_compute_line_scale(GF_TraverseState *tr_state, DrawAspect2D *asp)
        asp->line_scale = MAX(gf_divfix(tr_state->visual->compositor->scale_x, rc.width), gf_divfix(tr_state->visual->compositor->scale_y, rc.height));
 }
 
+//#define REMOVE_UNUSED_CTX
 void drawable_finalize_sort_ex(DrawableContext *ctx, GF_TraverseState *tr_state, GF_Rect *orig_bounds, Bool skip_focus)
 {
-       Bool can_remove;
+#ifdef REMVE_UNUSED_CTX
+       Bool can_remove = 0;
+#endif
        Fixed pw;
        GF_Rect unclip, store_orig_bounds;
 
@@ -867,14 +870,19 @@ void drawable_finalize_sort_ex(DrawableContext *ctx, GF_TraverseState *tr_state,
                ctx->bi->clip.width = 0;
        }
 
-
+#ifdef REMVE_UNUSED_CTX
        can_remove = drawable_finalize_end(ctx, tr_state);
+#else
+       drawable_finalize_end(ctx, tr_state);
+#endif
        if (ctx->drawable && !skip_focus)
                drawable_check_focus_highlight(ctx->drawable->node, tr_state, &store_orig_bounds);
 
        /*remove if this is the last context*/
-//     if (can_remove && (tr_state->visual->cur_context == ctx)) 
-//             tr_state->visual->cur_context->drawable = NULL;
+#ifdef REMVE_UNUSED_CTX
+       if (can_remove && (tr_state->visual->cur_context == ctx)) 
+               tr_state->visual->cur_context->drawable = NULL;
+#endif
 }
 
 void drawable_finalize_sort(struct _drawable_context *ctx, GF_TraverseState *tr_state, GF_Rect *orig_bounds)
index bb4c25c4f707b66e94107d851ad8001307a794d8..5059bfd9d9df4a60068bf1a060f448e25834d43b 100644 (file)
@@ -69,16 +69,19 @@ static Bool exec_text_selection(GF_Compositor *compositor, GF_Event *event)
 static void flush_text_node_edit(GF_Compositor *compositor, Bool final_flush)
 {
        Bool signal;
-       u8 *txt;
+       char *txt;
        u32 len;
        if (!compositor->edited_text) return;
 
+    /* if this is the final editing and there is text, 
+    we need to remove the caret from the text selection buffer */
        if (final_flush && compositor->sel_buffer_len) {
                memmove(&compositor->sel_buffer[compositor->caret_pos], &compositor->sel_buffer[compositor->caret_pos+1], sizeof(u16)*(compositor->sel_buffer_len-compositor->caret_pos));
                compositor->sel_buffer_len--;
                compositor->sel_buffer[compositor->sel_buffer_len] = 0;
        }
 
+    /* Recomputes the edited text */
        if (*compositor->edited_text) {
                gf_free(*compositor->edited_text);
                *compositor->edited_text = NULL;
@@ -101,8 +104,11 @@ static void flush_text_node_edit(GF_Compositor *compositor, Bool final_flush)
        gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
        /*notify compositor that text has been edited, in order to update composite textures*/
        //compositor->text_edit_changed = 1;
+
        gf_node_set_private(compositor->focus_highlight->node, NULL);
 
+    /* if this is the final flush, we free the selection buffer and edited text buffer 
+    and signal a text content change in the focus node */
        if (final_flush) {
                GF_FieldInfo info;
                if (compositor->sel_buffer) gf_free(compositor->sel_buffer);
@@ -782,6 +788,15 @@ TODO clean: figure out whether we use a mouse or a touch device - if touch devic
                evt.detail = event->key.key_code;
                evt.key_hw_code = event->key.hw_code;
                target = compositor->focus_node;
+               
+               /*dirty hack to simulate browserback*/
+               if (event->key.key_code==GF_KEY_BACKSPACE && (event->key.flags & GF_KEY_MOD_CTRL)) {
+                       event->key.key_code = GF_KEY_BROWSERBACK;
+               }
+
+               if ((event->key.key_code>=GF_KEY_BROWSERBACK) && (event->key.key_code<=GF_KEY_BROWSERSTOP)) {
+                       target = NULL;
+               }
                if (!target) target = gf_sg_get_root_node(compositor->scene);
                ret += gf_dom_event_fire(target, &evt);
 
@@ -800,7 +815,7 @@ TODO clean: figure out whether we use a mouse or a touch device - if touch devic
                case '\r':
                case '\n':
                case '\t':
-               case '\b':
+               //case '\b':
                        break;
                default:
                        memset(&evt, 0, sizeof(GF_DOM_Event));
@@ -827,7 +842,7 @@ TODO clean: figure out whether we use a mouse or a touch device - if touch devic
 Bool gf_sc_exec_event_vrml(GF_Compositor *compositor, GF_Event *ev)
 {
        u32 res = 0;
-       GF_SensorHandler *hs, *hs_grabbed;
+       GF_SensorHandler *hs;
        GF_List *tmp;
        u32 i, count, stype;
 
@@ -866,8 +881,6 @@ Bool gf_sc_exec_event_vrml(GF_Compositor *compositor, GF_Event *ev)
                compositor->prev_hit_appear = compositor->hit_appear;
        }
 
-
-       hs_grabbed = NULL;
        /*if we have a hit node at the compositor level, use "touch" as default cursor - this avoid
        resetting the cursor when the picked node is a DOM node in a composite texture*/
        stype = (compositor->hit_node!=NULL) ? GF_CURSOR_TOUCH : GF_CURSOR_NORMAL;
@@ -877,15 +890,25 @@ Bool gf_sc_exec_event_vrml(GF_Compositor *compositor, GF_Event *ev)
        for (i=0; i<count; i++) {
                GF_Node *keynav;
                hs = (GF_SensorHandler*)gf_list_get(compositor->sensors, i);
-               res += hs->OnUserEvent(hs, 1, 0, ev, compositor);
 
                /*try to remove this sensor from the previous sensor list*/
                gf_list_del_item(compositor->previous_sensors, hs);
-
                stype = gf_node_get_tag(hs->sensor);
-
                keynav = gf_scene_get_keynav(gf_node_get_graph(hs->sensor), hs->sensor);
                if (keynav) gf_sc_change_key_navigator(compositor, keynav);
+
+               /*call the sensor LAST, as this may triger a destroy of the scene the sensor is in 
+               this is only true for anchors, as other other sensors output events are queued as routes untill next pass*/
+               res += hs->OnUserEvent(hs, 1, 0, ev, compositor);
+               if ((stype == TAG_MPEG4_Anchor)
+#ifndef GPAC_DISABLE_X3D
+                                               || (stype == TAG_X3D_Anchor) 
+#endif
+               ) {
+                       /*subscene with active sensor has been deleted, we cannot continue process the sensors stack*/
+                       if (count != gf_list_count(compositor->sensors))
+                               break;
+               }
        }
        compositor->grabbed_sensor = 0;
        /*check if we have grabbed sensors*/
@@ -1702,8 +1725,7 @@ static GF_Node *browse_parent_for_focus(GF_Compositor *compositor, GF_Node *elt,
        }
 
        if (prev_focus) {
-               u32 i, count;
-               count = gf_node_list_get_count(child);
+               u32 i;
                /*!! this may happen when walking up PROTO nodes !!*/
                for (i=idx; i>0; i--) {
                        n = gf_node_list_get_child(child, i-1);
@@ -1926,7 +1948,7 @@ static Bool forward_event(GF_Compositor *compositor, GF_Event *ev, Bool consumed
 
 Bool gf_sc_exec_event(GF_Compositor *compositor, GF_Event *evt)
 {
-       s32 x, y;
+       s32 x=0, y=0;
        Bool switch_coords=0;
        Bool ret=0;
        if (evt->type<=GF_EVENT_MOUSEWHEEL) {
@@ -1940,9 +1962,13 @@ Bool gf_sc_exec_event(GF_Compositor *compositor, GF_Event *evt)
        }
 
        /*process regular events except if navigation is grabbed*/
-       if ( (compositor->navigation_state<2) && (compositor->interaction_level & GF_INTERACT_NORMAL) && gf_sc_execute_event(compositor, compositor->traverse_state, evt, NULL)) {
-               compositor->navigation_state = 0;
-               ret = 1;
+    if ( (compositor->navigation_state<2) && (compositor->interaction_level & GF_INTERACT_NORMAL)) {
+        Bool res;
+        res = gf_sc_execute_event(compositor, compositor->traverse_state, evt, NULL);
+        if (res) {
+                   compositor->navigation_state = 0;
+                   ret = 1;
+        }
        }
        if (switch_coords) {
                evt->mouse.x = x;
index 8dc10722990ee0b65512e089e16218dac0c5442c..26c12e6b368c978153315f85e68acd55ceeff6b7 100644 (file)
@@ -356,6 +356,8 @@ static GF_Glyph *gf_font_get_glyph(GF_FontManager *fm, GF_Font *font, u32 name)
                glyph->width = 0;
                glyph->ID = name;
                glyph->utf_name=name;
+       } else if (name==(u32) '\t') {
+               return NULL;
        } else {
                /*load glyph*/
                if (font->load_glyph) {
@@ -498,7 +500,7 @@ void gf_font_manager_refresh_span_bounds(GF_TextSpan *span)
 {
        u32 i;
        Fixed descent, ascent, bline;
-       Fixed min_x, min_y, width, max_y;
+       Fixed min_x, min_y, max_y;
 
        if (!span->nb_glyphs) {
                span->bounds.width = span->bounds.height = 0;
@@ -517,8 +519,6 @@ void gf_font_manager_refresh_span_bounds(GF_TextSpan *span)
 
        bline = span->font->baseline * span->font_scale;
 
-       width = (span->flags & GF_TEXT_SPAN_HORIZONTAL) ? 0 : span->font->max_advance_h*span->font_scale;
-
        min_x = span->dx ? FIX_MAX : span->off_x;
        min_y = span->dy ? FIX_MAX : span->off_y - descent;
        max_y = span->dy ? -FIX_MAX : span->off_y + ascent;
index d0aa84b9bad51c6140f4cbb40eba732e37135af8..177e3858f483124e6d10bf6a172aee8e9f59fc58 100644 (file)
@@ -281,20 +281,10 @@ extern void (*glXGetProcAddress(const GLubyte *procname))( void );
 GLDECL(void, glActiveTexture, (GLenum texture) )
 GLDECL(void, glClientActiveTexture, (GLenum texture) )
 
-#define GL_ARRAY_BUFFER        0x8892
-#define GL_STREAM_DRAW 0x88E0
-#define GL_STATIC_DRAW 0x88E4
-#define GL_DYNAMIC_DRAW 0x88E8
 
-GLDECL(void, glGenBuffers, (GLsizei , GLuint *) )
-GLDECL(void, glDeleteBuffers, (GLsizei , GLuint *) )
-GLDECL(void, glBindBuffer, (GLenum, GLuint ) )
-GLDECL(void, glBufferData, (GLenum, int, void *, GLenum) )
-GLDECL(void, glBufferSubData, (GLenum, int, int, void *) )
+GLDECL(void, glBlendEquation, (GLint mode) )
 #endif //GL_VERSION_1_3
 
-
-
 #ifndef GL_VERSION_1_4
 
 #ifdef LOAD_GL_FUNCS
@@ -308,13 +298,33 @@ GLDECL(void, glBufferSubData, (GLenum, int, int, void *) )
 #define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
 
 
-GLDECL(void, glBlendEquation, (GLint mode) )
 GLDECL(void, glPointParameterf, (GLenum , GLfloat) )
 GLDECL(void, glPointParameterfv, (GLenum, const GLfloat *) )
 
 #endif
 
 
+
+#ifndef GL_VERSION_1_5
+
+#ifdef LOAD_GL_FUNCS
+#define LOAD_GL_1_5
+#endif
+
+#define GL_ARRAY_BUFFER        0x8892
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+GLDECL(void, glGenBuffers, (GLsizei , GLuint *) )
+GLDECL(void, glDeleteBuffers, (GLsizei , GLuint *) )
+GLDECL(void, glBindBuffer, (GLenum, GLuint ) )
+GLDECL(void, glBufferData, (GLenum, int, void *, GLenum) )
+GLDECL(void, glBufferSubData, (GLenum, int, int, void *) )
+
+#endif //GL_VERSION_1_5
+
+
 #ifndef GL_VERSION_2_0
 
 #ifdef LOAD_GL_FUNCS
index 09e0a1d22c514c2b53e6cfa39bcde39b3d6d9e03..a8e764ec5b7559534ed15b34a6bd00b4fc03b4aa 100644 (file)
@@ -89,7 +89,7 @@ static void build_shape(FSStack *st, GF_Node *node)
        u32 wi, li, fi, ci, command, i, has_ci;
        FSItem *fill_item, *line_item;
        Fixed w;
-       SFVec2f cur, pt, ct1, ct2, *pts;
+       SFVec2f cur, pt, ct1={0,0}, ct2, *pts;
        GF_Rect rc;
        u32 line_col, fill_col;
        Bool need_line, need_fill;
index 3b978e0baa38655a57d325c9876a64a945d433c5..df401c7d4eba871441dc36d2d27de28ed8f8a17e 100644 (file)
@@ -1032,10 +1032,9 @@ void mesh_new_ifs_intern(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex,
                                                        GF_Node *__texCoords, MFInt32 *texCoordIndex,
                                                        Fixed creaseAngle)
 {
-       u32 i, n, count, c_count, col_count, nor_count;
+       u32 i, n, count, c_count, nor_count;
        u32 index;
-       u32 first_idx, last_idx;
-       Bool move_to, smooth_normals;
+       Bool smooth_normals;
        SFVec2f tx;
        u32 s_axis, t_axis;
        SFVec3f pt, nor, bounds, center;
@@ -1133,14 +1132,12 @@ void mesh_new_ifs_intern(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex,
                        if (!colorIndex->vals) colorIndex = coordIndex;
                }
        }
-       col_count = colorIndex->count ? colorIndex->count : c_count;
 
        if (has_normal && !normalPerVertex) {
                index = normalIndex->count ? normalIndex->vals[0] : 0;
                if (index < nor_count) nor = normal->vector.vals[index];
        }
 
-       move_to = 1;
        count = coordIndex->count;
        has_coord = count ? 1 : 0;
        if (!has_coord) count = c_count; 
@@ -1151,9 +1148,7 @@ void mesh_new_ifs_intern(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex,
        if (!has_coord) {
                face_count = 1;
        } else {
-               u32 pt_p_face;
                face_count = 0;
-               pt_p_face = 0;
                for (i=0; i<count; i++) {
                        if (coordIndex->vals[i] == -1) face_count++;
                }
@@ -1178,10 +1173,8 @@ void mesh_new_ifs_intern(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex,
        }
 
        cur_face = 0;
-       first_idx = last_idx = 0;
        for (i=0; i<count; i++) {
                if (has_coord && coordIndex->vals[i] == -1) {
-                       move_to = 1;
                        n++;
                        if (has_color && !colorPerVertex) {
                                GET_IDX(n, colorIndex);
@@ -1982,17 +1975,20 @@ static void mesh_extrude_path_intern(GF_Mesh *mesh, GF_Path *path, MFVec3f *thes
 
                n = SCPbegin.yaxis;
                gf_vec_norm(&n);
-               MESH_SET_NORMAL(vx, n);
 
                convexity = gf_polygone2d_get_convexity(path->points, path->n_points);
                switch (convexity) {
                case GF_POLYGON_CONVEX_CCW:
                case GF_POLYGON_COMPLEX_CCW:
-                       gf_vec_rev(vx.normal);
+                       break;
+               default:
                        gf_vec_rev(n);
                        break;
                }
 
+               MESH_SET_NORMAL(vx, n);
+
+
                if (smooth_normals) {
                        faces_info[begin_face].nor = n;
                        assert(gf_vec_len(n));
index 086c4eba371809a6fface2bb1b9cdcc064e7f395..c83e93315b9d21f70a8ecd0aa0b903ce33e6769f 100644 (file)
@@ -38,7 +38,7 @@ typedef struct
 
 static void audioclip_activate(AudioClipStack *st, M_AudioClip *ac)
 {
-       if (gf_sc_audio_open(&st->input, &ac->url, 0, -1) != GF_OK) {
+       if (gf_sc_audio_open(&st->input, &ac->url, 0, -1, 0) != GF_OK) {
                st->failure = 1;
                return;
        }
@@ -149,7 +149,7 @@ void compositor_audioclip_modified(GF_Node *node)
        if (st->input.is_open && st->input.is_open) {
                if (gf_sc_audio_check_url(&st->input, &ac->url)) {
                        gf_sc_audio_stop(&st->input);
-                       gf_sc_audio_open(&st->input, &ac->url, 0, -1);
+                       gf_sc_audio_open(&st->input, &ac->url, 0, -1, 0);
                        /*force unregister to resetup audio cfg*/
                        gf_sc_audio_unregister(&st->input);
                        gf_sc_invalidate(st->input.compositor, NULL);
@@ -181,7 +181,7 @@ typedef struct
 
 static void audiosource_activate(AudioSourceStack *st, M_AudioSource *as)
 {
-       if (gf_sc_audio_open(&st->input, &as->url, 0, -1) != GF_OK)
+       if (gf_sc_audio_open(&st->input, &as->url, 0, -1, 0) != GF_OK)
                return;
        st->is_active = 1;
        gf_mo_set_speed(st->input.stream, st->input.speed);
@@ -281,7 +281,7 @@ void compositor_audiosource_modified(GF_Node *node)
                gf_sc_audio_unregister(&st->input);
                gf_sc_invalidate(st->input.compositor, NULL);
 
-               if (st->is_active) gf_sc_audio_open(&st->input, &as->url, 0, -1);
+               if (st->is_active) gf_sc_audio_open(&st->input, &as->url, 0, -1, 0);
        }
 
        //update state if we're active
index 0dde9517477082acd3865098f4574a0cc1da82e7..c2eee0723ca459e8f4224cc5059999ae249346e2 100644 (file)
@@ -53,7 +53,11 @@ static void Bitmap_BuildGraph(GF_Node *node, BitmapStack *st, GF_TraverseState *
        if (! ((M_Appearance *)tr_state->appear)->texture) return;
        txh = gf_sc_texture_get_handler( ((M_Appearance *)tr_state->appear)->texture );
        /*bitmap not ready*/
-       if (!txh || !txh->tx_io || !txh->width || !txh->height) {
+       if (!txh || !txh->width || !txh->height
+#ifndef GPAC_DISABLE_3D
+               || (tr_state->visual->type_3d && !txh->tx_io) 
+#endif
+               ) {
                if (notify_changes) gf_node_dirty_set(node, 0, 1);
                return;
        }
@@ -123,12 +127,10 @@ static void draw_bitmap_3d(GF_Node *node, GF_TraverseState *tr_state)
 static void draw_bitmap_2d(GF_Node *node, GF_TraverseState *tr_state)
 {
        GF_ColorKey *key, keyColor;
-       GF_Compositor *compositor;
        DrawableContext *ctx = tr_state->ctx;
        BitmapStack *st = (BitmapStack *) gf_node_get_private(node);
 
 
-       compositor = tr_state->visual->compositor;
        /*bitmaps are NEVER rotated (forbidden in spec). In case a rotation was done we still display (reset the skew components)*/
        ctx->transform.m[1] = ctx->transform.m[3] = 0;
 
@@ -215,6 +217,7 @@ static void TraverseBitmap(GF_Node *node, void *rs, Bool is_destroy)
 
        memset(&rc, 0, sizeof(rc));
        Bitmap_BuildGraph(node, st, tr_state, &rc, 1);
+       if (!rc.width || !rc.height) return;
 
        ctx = drawable_init_context_mpeg4(st->graph, tr_state);
        if (!ctx || !ctx->aspect.fill_texture ) {
index d669440a3ed7f20d9ffd43dd727c1ee227f5620e..4c2b8cfa65d25fb1ee6fbba1b870174003fa3c97 100644 (file)
@@ -201,7 +201,7 @@ static void form_apply(FormStack *st, const char *constraint, u32 *group_idx, u3
 static void TraverseForm(GF_Node *n, void *rs, Bool is_destroy)
 {
 #if FORM_CLIPS
-       GF_Rect clip, prev_clipper;
+       GF_Rect prev_clipper;
        Bool had_clip;
        GF_IRect prev_clip;
 #endif
@@ -338,7 +338,7 @@ static void TraverseForm(GF_Node *n, void *rs, Bool is_destroy)
        /*update clipper*/
        if (tr_state->traversing_mode==TRAVERSE_SORT) {
                prev_clip = tr_state->visual->top_clipper;
-               clip = compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 0);
+               compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 0);
                if (tr_state->has_clip) {
                        tr_state->visual->top_clipper = gf_rect_pixelize(&tr_state->clipper);
                        gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
index 2850f3b238144dfbc8b896399d41ddc3918c2aee..501d21f0252ecf35b5ffdf8c8fd4736b583002bf 100644 (file)
@@ -34,6 +34,7 @@ Bool compositor_get_2d_plane_intersection(GF_Ray *ray, SFVec3f *res)
        if (!ray->dir.x && !ray->dir.y) {
                res->x = ray->orig.x;
                res->y = ray->orig.y;
+               res->z = 0;
                return 1;
        }
        p.normal.x = p.normal.y = 0; p.normal.z = FIX_ONE;
@@ -689,4 +690,29 @@ void compositor_init_pointset2d(GF_Compositor  *compositor, GF_Node *node)
        gf_node_set_callback_function(node, TraversePointSet2D);
 }
 
+static void TraverseBitWrapper(GF_Node *node, void *rs, Bool is_destroy)
+{
+       GF_TraverseState *tr_state;
+       M_BitWrapper *bitWrap;
+
+       if (is_destroy) {
+               gf_node_set_private(node, NULL);
+               return;
+       }
+
+       tr_state = (GF_TraverseState *)rs;
+       // Traverse the node here
+       bitWrap = (M_BitWrapper *)node;
+       gf_node_traverse(bitWrap->node, tr_state);
+}
+
+void compositor_init_bitwrapper(GF_Compositor *compositor, GF_Node *node)
+{
+       M_BitWrapper *bit;
+       bit = (M_BitWrapper *)node;
+       gf_node_set_private(node, gf_node_get_private(bit->node));
+       gf_node_set_callback_function(node, TraverseBitWrapper);
+}
+
+
 #endif /*GPAC_DISABLE_VRML*/
index 95d1760effcb9849fff3845f7a5c68268fae538e..b79e8e847c9f1ebdb444df2c4c352c6ce61de52e 100644 (file)
@@ -78,7 +78,7 @@ static void ifs2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState
 static void IFS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
 {
        u32 i, count, ci_count;
-       u32 start_pts, j, ind_col, num_col;
+       u32 j, ind_col, num_col;
        SFVec2f center, end;
        SFColor col_cen;
        GF_STENCIL grad;
@@ -184,7 +184,6 @@ static void IFS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
                start = pts[ifs2D->coordIndex.vals[i]];
                center = start;
                gf_path_add_move_to(path, start.x, start.y);
-               start_pts = i;
                num_col = 1;
                i+=1;
                while (ifs2D->coordIndex.vals[i] != -1) {       
index 4b507ae982e2d223c46aca690c07ffc51a4cf891..ec81c5d14d1096e018d097b4291b8a25ecacb0ef 100644 (file)
@@ -36,7 +36,7 @@ typedef struct
 static void TraverseSwitch(GF_Node *node, void *rs, Bool is_destroy)
 {
        GF_ChildNodeItem *l;
-       u32 i, count;
+       u32 i;
        Bool prev_switch;
        GF_ChildNodeItem *children;
        s32 whichChoice;
@@ -67,8 +67,6 @@ static void TraverseSwitch(GF_Node *node, void *rs, Bool is_destroy)
        }
 
        if (tr_state->traversing_mode!=TRAVERSE_GET_BOUNDS) {
-               count = gf_node_list_get_count(children);
-
                prev_switch = tr_state->switched_off;
                /*check changes in choice field*/
                if ((gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) || (st->last_switch != whichChoice) ) {
index 02efc8f1a88855997dfce2a613ed9d1963b7a6c6..d140cd580925fb174d22654fc6eaea181768884a 100644 (file)
@@ -112,8 +112,8 @@ static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy)
        GF_TraverseState *tr_state = (GF_TraverseState *) rs;
        
        if (is_destroy) {
-               gf_list_del(st->backs);
-               gf_list_del(st->views);
+               BindableStackDelete(st->backs);
+               BindableStackDelete(st->views);
                group_2d_destroy(node, (GroupingNode2D*)st);
                gf_free(st);
                return;
index 7b864e934a48917f7419f10acc2b31a55e345aa3..7cb9f22fc5f2e6ef443b704782ec2af5f4b83186 100644 (file)
@@ -622,7 +622,7 @@ static void TraverseLayout(GF_Node *node, void *rs, Bool is_destroy)
        GF_IRect prev_clip;
        Bool mode_bckup, had_clip;
        ParentNode2D *parent_bck;
-       GF_Rect clip, prev_clipper;
+       GF_Rect prev_clipper;
        M_Layout *l = (M_Layout *)node;
        LayoutStack *st = (LayoutStack *) gf_node_get_private(node);
        GF_TraverseState *tr_state = (GF_TraverseState *)rs;
@@ -673,7 +673,7 @@ static void TraverseLayout(GF_Node *node, void *rs, Bool is_destroy)
        /*setup clipping*/
        prev_clip = tr_state->visual->top_clipper;
        if (tr_state->traversing_mode==TRAVERSE_SORT) {
-               clip = compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 0);
+               compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 0);
                if (tr_state->has_clip) {
                        tr_state->visual->top_clipper = gf_rect_pixelize(&tr_state->clipper);
                        gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
index 7d29cf2e67d66e52b99bb48a2c726121948d99c9..d211f85b9d97062160fef6a1dc7fe28c7165936f 100644 (file)
@@ -200,7 +200,7 @@ static void build_text_split(TextStack *st, M_Text *txt, GF_TraverseState *tr_st
 static void build_text(TextStack *st, M_Text *txt, GF_TraverseState *tr_state)
 {
        u32 i, j, int_major, k, styles, count;
-       Fixed fontSize, start_x, start_y, line_spacing, tot_width, tot_height, max_scale, space, maxExtent;
+       Fixed fontSize, start_x, start_y, line_spacing, tot_width, tot_height, max_scale, maxExtent;
        u32 size, trim_size;
        GF_Font *font;
        Bool horizontal;
@@ -229,7 +229,6 @@ static void build_text(TextStack *st, M_Text *txt, GF_TraverseState *tr_state)
        /*NOTA: we could use integer maths here but we have a risk of overflow with large fonts, so use fixed maths*/
        st->ascent = gf_muldiv(fontSize, INT2FIX(font->ascent), INT2FIX(font->em_size));
        st->descent = -gf_muldiv(fontSize, INT2FIX(font->descent), INT2FIX(font->em_size));
-       space = gf_muldiv(fontSize, INT2FIX(font->line_spacing), INT2FIX(font->em_size)) ;
        line_spacing = gf_mulfix(FSSPACE, fontSize);
 
        maxExtent = txt->maxExtent;
index 62d6fe539a19c7ef7518d48a38f860d37e3cfd60..3ae06d00df11ccd88030d812779033a236a21f9f 100644 (file)
@@ -278,40 +278,52 @@ static void imagetexture_update(GF_TextureHandler *txh)
                M_CacheTexture *ct = (M_CacheTexture *) txh->owner;
 
                /*decode cacheTexture data */
-               if (ct->data && !txh->data) {
+               if ((ct->data || ct->image.buffer) && !txh->data) {
                        u32 out_size;
                        GF_Err e;
-                       switch (ct->objectTypeIndication) {
-                       case GPAC_OTI_IMAGE_JPEG:
-                               out_size = 0;
-                               e = gf_img_jpeg_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, NULL, &out_size, 3);
-                               if (e==GF_BUFFER_TOO_SMALL) {
-                                       u32 BPP;
-                                       txh->data = gf_malloc(sizeof(char) * out_size);
-                                       if (txh->pixelformat==GF_PIXEL_GREYSCALE) BPP = 1;
-                                       else BPP = 3;
-
-                                       e = gf_img_jpeg_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, txh->data, &out_size, BPP);
-                                       if (e==GF_OK) {
-                                               txh->needs_refresh = 1;
-                                               txh->stride = out_size / txh->height;
-                                       }
+
+                       /*BT/XMT playback*/
+                       if (ct->image.buffer) {
+                               e = gf_img_file_dec(ct->image.buffer, &ct->objectTypeIndication, &txh->width, &txh->height, &txh->pixelformat, &txh->data, &out_size);
+                               if (e==GF_OK) {
+                                       txh->needs_refresh = 1;
+                                       txh->stride = out_size / txh->height;
                                }
-                               break;
-                       case GPAC_OTI_IMAGE_PNG:
-                               out_size = 0;
-                               e = gf_img_png_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, NULL, &out_size);
-                               if (e==GF_BUFFER_TOO_SMALL) {
-                                       txh->data = gf_malloc(sizeof(char) * out_size);
-                                       e = gf_img_png_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, txh->data, &out_size);
-                                       if (e==GF_OK) {
-                                               txh->needs_refresh = 1;
-                                               txh->stride = out_size / txh->height;
+                       } 
+                       /*BIFS decoded playback*/
+                       else {
+                               switch (ct->objectTypeIndication) {
+                               case GPAC_OTI_IMAGE_JPEG:
+                                       out_size = 0;
+                                       e = gf_img_jpeg_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, NULL, &out_size, 3);
+                                       if (e==GF_BUFFER_TOO_SMALL) {
+                                               u32 BPP;
+                                               txh->data = gf_malloc(sizeof(char) * out_size);
+                                               if (txh->pixelformat==GF_PIXEL_GREYSCALE) BPP = 1;
+                                               else BPP = 3;
+
+                                               e = gf_img_jpeg_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, txh->data, &out_size, BPP);
+                                               if (e==GF_OK) {
+                                                       txh->needs_refresh = 1;
+                                                       txh->stride = out_size / txh->height;
+                                               }
                                        }
+                                       break;
+                               case GPAC_OTI_IMAGE_PNG:
+                                       out_size = 0;
+                                       e = gf_img_png_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, NULL, &out_size);
+                                       if (e==GF_BUFFER_TOO_SMALL) {
+                                               txh->data = gf_malloc(sizeof(char) * out_size);
+                                               e = gf_img_png_dec(ct->data, ct->data_len, &txh->width, &txh->height, &txh->pixelformat, txh->data, &out_size);
+                                               if (e==GF_OK) {
+                                                       txh->needs_refresh = 1;
+                                                       txh->stride = out_size / txh->height;
+                                               }
+                                       }
+                                       break;
                                }
-                               break;
                        }
-                       
+
                        /*cacheURL is specified, store the image*/
                        if (ct->cacheURL.buffer) {
                                u32 i;
@@ -341,7 +353,7 @@ static void imagetexture_update(GF_TextureHandler *txh)
                                strcat(szExtractName, ct->cacheURL.buffer);
                                cached_texture = gf_f64_open(szExtractName, "wb");
                                if (cached_texture) {
-                                       fwrite(ct->data, 1, ct->data_len, cached_texture);
+                                       gf_fwrite(ct->data, 1, ct->data_len, cached_texture);
                                        fclose(cached_texture);
                                }
 
@@ -366,8 +378,8 @@ static void imagetexture_update(GF_TextureHandler *txh)
                        }
 
                        /*done with image, destroy buffer*/
-                       gf_free(ct->data);
-                       ct->data  =NULL;
+                       if (ct->data) gf_free(ct->data);
+                       ct->data NULL;
                        ct->data_len = 0;
                }
        }
index 5ba9bc86fb7c156dc4c8e8816ed0b91680d43f83..8e539854d1ceeb4fd39d2a8ca63ea5a736937e2d 100644 (file)
@@ -132,7 +132,7 @@ static void viewport_set_bind(GF_Node *node, GF_Route *route)
 
 static void TraverseViewport(GF_Node *node, void *rs, Bool is_destroy)
 {
-       Fixed ar, sx, sy, w, h, tx, ty;
+       Fixed sx, sy, w, h, tx, ty;
 #ifndef GPAC_DISABLE_3D
        GF_Matrix mx;
 #endif
@@ -200,7 +200,6 @@ static void TraverseViewport(GF_Node *node, void *rs, Bool is_destroy)
        sx = (vp->size.x>=0) ? vp->size.x : w;
        sy = (vp->size.y>=0) ? vp->size.y : h;
        rc = gf_rect_center(sx, sy);
-       ar = gf_divfix(h, w);
        rc_bckup = rc;
 
        switch (vp->fit) {
index d4cf4b1a09570088103d5601acd6072defd69ce4..7490bc013f55857b535298780dc7ecc5b9cc318f 100644 (file)
@@ -280,13 +280,13 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event
                is_pixel_metrics = compositor->traverse_state->pixel_metrics;
        }
 
-       if (!cam->navigate_mode) return 0;
        keys = compositor->key_states;
+       if (!cam->navigate_mode && !(keys & GF_KEY_MOD_ALT) ) return 0;
        x = y = 0;
        /*renorm between -1, 1*/
        if (ev->type<=GF_EVENT_MOUSEWHEEL) {
-               x = gf_divfix( INT2FIX(ev->mouse.x + (s32) compositor->visual->width/2), INT2FIX(compositor->visual->width));
-               y = gf_divfix( INT2FIX(ev->mouse.y + (s32) compositor->visual->height/2), INT2FIX(compositor->visual->height));
+               x = gf_divfix( INT2FIX(ev->mouse.x - (s32) compositor->visual->width/2), INT2FIX(compositor->visual->width));
+               y = gf_divfix( INT2FIX(ev->mouse.y - (s32) compositor->visual->height/2), INT2FIX(compositor->visual->height));
        }
 
        dx = (x - compositor->grab_x); 
@@ -296,13 +296,13 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event
        key_trans = is_pixel_metrics ? INT2FIX(10) : cam->avatar_size.x;
 */
        trans_scale = cam->width/20;
-       key_trans = cam->avatar_size.x;
+       key_trans = cam->avatar_size.x/2;
        if (cam->world_bbox.is_set && (key_trans*5 > cam->world_bbox.radius)) {
-               key_trans = cam->world_bbox.radius / 10;
+               key_trans = cam->world_bbox.radius / 100;
        }
 
        key_pan = FIX_ONE/25;
-       key_exam = FIX_ONE/10;
+       key_exam = FIX_ONE/20;
        key_inv = 1;
 
        if (keys & GF_KEY_MOD_SHIFT) {
@@ -467,7 +467,7 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event
                case GF_KEY_RIGHT:
                        if (keys & GF_KEY_MOD_ALT) {
                                if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) {
-                                       compositor->view_distance_offset += key_inv * INT2FIX((is_pixel_metrics ? 5 : 1));
+                                       compositor->view_distance_offset += key_inv * (is_pixel_metrics ? INT2FIX(1) : FLT2FIX(0.1));
                                        cam->flags |= CAM_IS_DIRTY;
                                        fprintf(stdout, "AutoStereo view distance %f\n", FIX2FLT(compositor->view_distance_offset + compositor->video_out->view_distance)/100);
                                        gf_sc_invalidate(compositor, NULL);
@@ -570,7 +570,7 @@ static Bool compositor_handle_navigation_2d(GF_VisualManager *visual, GF_Event *
        if (visual->type_3d) navigation_mode = visual->camera.navigate_mode;
 #endif
 
-       if (!navigation_mode /*&& !(keys & GF_KEY_MOD_ALT) */) return 0;
+       if (!navigation_mode && !(keys & GF_KEY_MOD_ALT) ) return 0;
 
 
        x = y = 0;
@@ -580,7 +580,11 @@ static Bool compositor_handle_navigation_2d(GF_VisualManager *visual, GF_Event *
                y = INT2FIX(ev->mouse.y);
        }
        dx = x - visual->compositor->grab_x;
-       dy = visual->compositor->grab_y - y;
+       if (visual->center_coords) {
+               dy = visual->compositor->grab_y - y;
+       } else {
+               dy = y - visual->compositor->grab_y;
+       }
        if (!is_pixel_metrics) { dx /= visual->width; dy /= visual->height; }
 
        key_inv = 1;
index 31419412fae0b5a04cce1e2b4f0d49641cb5a9f3..6968d6918e920ccd6fd02f5eab4f7f0be27fbc00 100644 (file)
@@ -156,6 +156,8 @@ void compositor_init_transformmatrix2d(GF_Compositor *compositor, GF_Node *node)
 void compositor_init_indexed_line_set2d(GF_Compositor *compositor, GF_Node *node);
 void compositor_init_indexed_face_set2d(GF_Compositor *compositor, GF_Node *node);
 
+void compositor_init_bitwrapper(GF_Compositor *compositor, GF_Node *node);
+
 void compositor_init_viewport(GF_Compositor *compositor, GF_Node *node);
 
 void tr_mx2d_get_matrix(GF_Node *n, GF_Matrix2D *mat);
@@ -321,6 +323,8 @@ void svg_pause_animation(GF_Node *n, Bool pause);
 void svg_pause_audio(GF_Node *n, Bool pause);
 void svg_pause_video(GF_Node *n, Bool pause);
 
+void compositor_svg_video_modified(GF_Compositor *compositor, GF_Node *node);
+
 #endif
 
 
index 2d0a6668db9d4cc15f4917b19a733956cb87814b..0d309b03a123d4f499d4ea39ac4b5dc59ec54877 100644 (file)
@@ -278,6 +278,7 @@ void svg_drawable_pick(GF_Node *node, Drawable *drawable, GF_TraverseState *tr_s
 
        memcpy(&backup_props, tr_state->svg_props, sizeof(SVGPropertiesPointers));
        gf_svg_apply_inheritance(&all_atts, tr_state->svg_props);
+       if (compositor_svg_is_display_off(tr_state->svg_props)) return;
 
        compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
 
index ffd6e7d4a3e099f7d843272cff2d4bcf1a301912..5d0e1b78d6b654e475b41eb66b5443802aee7c8d 100644 (file)
@@ -90,7 +90,7 @@ static void svg_recompute_viewport_transformation(GF_Node *node, SVGsvgStack *st
 
        gf_mx2d_init(mx);
 
-       if (stack->root_svg) {
+       if (stack->root_svg && !tr_state->parent_is_use) {
                const char *frag_uri = gf_scene_get_fragment_uri(node);
                if (frag_uri) {
                        /*SVGView*/
@@ -994,7 +994,7 @@ static void svg_traverse_resource(GF_Node *node, void *rs, Bool is_destroy, Bool
        GF_Matrix2D translate;
        SVGPropertiesPointers backup_props;
        u32 backup_flags, dirty;
-       Bool is_fragment;
+       Bool is_fragment, parent_is_use;
        GF_Node *used_node;
        GF_TraverseState *tr_state = (GF_TraverseState *)rs;
        SVGAllAttributes all_atts;
@@ -1075,6 +1075,8 @@ static void svg_traverse_resource(GF_Node *node, void *rs, Bool is_destroy, Bool
 
        prev_opacity = tr_state->parent_use_opacity;
        tr_state->parent_use_opacity = all_atts.opacity;
+       parent_is_use = tr_state->parent_is_use;
+       tr_state->parent_is_use = is_foreign_object ? 0 : 1;
 
        if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
                compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
@@ -1117,6 +1119,7 @@ static void svg_traverse_resource(GF_Node *node, void *rs, Bool is_destroy, Bool
        gf_list_rem_last(tr_state->use_stack);
        tr_state->vp_size = prev_vp;
 
+       tr_state->parent_is_use = parent_is_use;
        tr_state->parent_use_opacity = prev_opacity;
 
 end:
@@ -1308,11 +1311,16 @@ static void svg_traverse_animation(GF_Node *node, void *rs, Bool is_destroy)
        gf_mx2d_apply_rect(&tr_state->transform, &rc);
        prev_clip = tr_state->visual->top_clipper;
        clip = gf_rect_pixelize(&rc);
-//     gf_irect_intersect(&tr_state->visual->top_clipper, &clip);
+       gf_irect_intersect(&tr_state->visual->top_clipper, &clip);
 
        if (!stack->inline_sg && stack->resource) {
                stack->inline_sg = gf_mo_get_scenegraph(stack->resource);
        }
+       /*if we have the focus, move it to the subtree*/
+       if (tr_state->visual->compositor->focus_node==node) {
+               GF_Node *subroot = gf_sg_get_root_node(stack->inline_sg);
+               if (subroot) tr_state->visual->compositor->focus_node = subroot;
+       }
 
        if (stack->inline_sg) {
                gf_sc_traverse_subscene(tr_state->visual->compositor, node, stack->inline_sg, tr_state);
index 59f2732c0cd47a2667835711300841f2e6995579..648c76400493a778d350e129f8671e2d646731a2 100644 (file)
@@ -80,7 +80,6 @@ static Bool svg_video_get_transform_behavior(GF_TraverseState *tr_state, SVGAllA
 static void SVG_Draw_bitmap(GF_TraverseState *tr_state)
 {
        DrawableContext *ctx = tr_state->ctx;
-
        if (!tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx, NULL)) {
                visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
        }
@@ -287,7 +286,7 @@ static void svg_traverse_bitmap(GF_Node *node, void *rs, Bool is_destroy)
                        stack->audio = NULL;
                }
                stack->audio_dirty = 1;
-
+               
                if (stack->txurl.count) svg_play_texture(stack, &all_atts);
                gf_node_dirty_clear(node, GF_SG_SVG_XLINK_HREF_DIRTY);
        }
@@ -298,6 +297,7 @@ static void svg_traverse_bitmap(GF_Node *node, void *rs, Bool is_destroy)
                        gf_node_dirty_clear(node, 0);
                        SVG_Build_Bitmap_Graph((SVG_video_stack*)gf_node_get_private(node), tr_state);
                }
+               
        } 
 
        if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
@@ -437,11 +437,9 @@ static void SVG_Update_video(GF_TextureHandler *txh)
        SVG_video_stack *stack = (SVG_video_stack *) gf_node_get_private(txh->owner);
        
        if (!txh->is_open) {
-               u32 tag;
                SVG_InitialVisibility init_vis;
                if (stack->first_frame_fetched) return;
 
-               tag = gf_node_get_tag(txh->owner);
                init_vis = SVG_INITIALVISIBILTY_WHENSTARTED;
 
                if (gf_node_get_attribute_by_tag(txh->owner, TAG_SVG_ATT_initialVisibility, 0, 0, &init_vis_info) == GF_OK) {
@@ -473,17 +471,20 @@ static void SVG_Update_video(GF_TextureHandler *txh)
        }
 
        if (!stack->audio && stack->audio_dirty) {
-               stack->audio_dirty = 0;
-               if (gf_mo_has_audio(stack->txh.stream)) {
-                       GF_FieldInfo att_vid, att_aud;
-                       stack->audio = gf_node_new(gf_node_get_graph(stack->txh.owner), TAG_SVG_audio);
-                       gf_node_register(stack->audio, NULL);
-                       if (gf_node_get_attribute_by_tag(stack->txh.owner, TAG_XLINK_ATT_href, 0, 0, &att_vid)==GF_OK) {
-                               gf_node_get_attribute_by_tag(stack->audio, TAG_XLINK_ATT_href, 1, 0, &att_aud);
-                               gf_svg_attributes_copy(&att_aud, &att_vid, 0);
+               u32 res = gf_mo_has_audio(stack->txh.stream);
+               if (res != 2) {
+                       stack->audio_dirty = 0;
+                       if (res) {
+                               GF_FieldInfo att_vid, att_aud;
+                               stack->audio = gf_node_new(gf_node_get_graph(stack->txh.owner), TAG_SVG_audio);
+                               gf_node_register(stack->audio, NULL);
+                               if (gf_node_get_attribute_by_tag(stack->txh.owner, TAG_XLINK_ATT_href, 0, 0, &att_vid)==GF_OK) {
+                                       gf_node_get_attribute_by_tag(stack->audio, TAG_XLINK_ATT_href, 1, 0, &att_aud);
+                                       gf_svg_attributes_copy(&att_aud, &att_vid, 0);
+                               }
+                               /*BYPASS SMIL TIMING MODULE!!*/
+                               compositor_init_svg_audio(stack->txh.compositor, stack->audio, 1);
                        }
-                       /*BYPASS SMIL TIMING MODULE!!*/
-                       compositor_init_svg_audio(stack->txh.compositor, stack->audio, 1);
                }
        }
        
@@ -562,6 +563,30 @@ void svg_pause_video(GF_Node *n, Bool pause)
        else gf_mo_resume(st->txh.stream);
 }
 
+void compositor_svg_video_modified(GF_Compositor *compositor, GF_Node *node)
+{
+       /*if href has been modified, stop the video (and associated audio if any) right away - we cannot wait for next traversal to
+       process this as the video could be in a hidden subtree not traversed*/
+       if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
+               SVG_video_stack *st = gf_node_get_private(node);
+               /*WARNING - stack may be NULL at this point when inserting the video from script*/
+               if (st && st->txh.is_open) {
+                       if (st->audio) {
+                               svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, st->audio, st->txh.owner);
+                               gf_node_unregister(st->audio, NULL);
+                               st->audio = NULL;
+                       }
+                       /*reset cached URL to avoid reopening the resource in the smil timing callback*/
+                       gf_sg_vrml_mf_reset(&st->txurl, GF_SG_VRML_MFURL);
+                       gf_sc_texture_stop(&st->txh);
+               }
+       }
+       gf_node_dirty_set(node, 0, 0);
+       /*and force a redraw of next frame*/
+       gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME);
+}
+
+
 /*********************/
 /* SVG audio element */
 /*********************/
@@ -587,11 +612,15 @@ static void svg_audio_smil_evaluate_ex(SMIL_Timing_RTI *rti, Fixed normalized_sc
                if (!stack->is_active && !stack->is_error) { 
                        if (stack->aurl.count) {
                                SVGAllAttributes atts;
+                               Bool lock_timeline = 0;
                                gf_svg_flatten_attributes((SVG_Element*) (video ? video : audio), &atts);
 
+                               if (atts.syncBehavior) lock_timeline = (*atts.syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? 1 : 0;                
+
                                if (gf_sc_audio_open(&stack->input, &stack->aurl,
                                                atts.clipBegin ? (*atts.clipBegin) : 0.0,
-                                               atts.clipEnd ? (*atts.clipEnd) : -1.0) == GF_OK) 
+                                               atts.clipEnd ? (*atts.clipEnd) : -1.0,
+                                               lock_timeline) == GF_OK) 
                                {
                                        gf_mo_set_speed(stack->input.stream, FIX_ONE);
                                        stack->is_active = 1;
@@ -666,6 +695,7 @@ static void svg_traverse_audio_ex(GF_Node *node, void *rs, Bool is_destroy, SVGP
 
        if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
                SVGAllAttributes atts;
+               Bool lock_timeline = 0;
                if (stack->is_active) 
                        gf_sc_audio_stop(&stack->input);
 
@@ -675,10 +705,12 @@ static void svg_traverse_audio_ex(GF_Node *node, void *rs, Bool is_destroy, SVGP
                gf_term_get_mfurl_from_xlink(node, &(stack->aurl));
 
                gf_svg_flatten_attributes((SVG_Element*) node, &atts);
+               if (atts.syncBehavior) lock_timeline = (*atts.syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? 1 : 0;                
 
                if (stack->aurl.count && (gf_sc_audio_open(&stack->input, &stack->aurl,
                                atts.clipBegin ? (*atts.clipBegin) : 0.0,
-                               atts.clipEnd ? (*atts.clipEnd) : -1.0) == GF_OK) 
+                               atts.clipEnd ? (*atts.clipEnd) : -1.0,
+                               lock_timeline) == GF_OK) 
 
                ) {
                        gf_mo_set_speed(stack->input.stream, FIX_ONE);
index 832031f3d6dd64d7d7fda236c61efad2d568e607..63a1164d437fbb0622a94ac12153ae8ef51ce370 100644 (file)
@@ -671,6 +671,21 @@ static void SVG_RG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Mat
                focal.y = center.y;
        }
 
+       /* clamping fx/fy according to:
+       http://www.w3.org/TR/SVG11/pservers.html#RadialGradients
+       If the point defined by \91fx\92 and \91fy\92 lies outside the circle defined by \91cx\92\91cy\92 and \91r\92
+       then the user agent shall set the focal point to the intersection of the line from (\91cx\92\91cy\92
+       to (\91fx\92\91fy\92) with the circle defined by \91cx\92\91cy\92 and \91r\92.*/
+       {
+               Fixed norm = gf_v2d_distance(&focal, &center);
+               if (norm > radius) {
+                       Fixed xdelta = gf_muldiv(radius, focal.x-center.x, norm);
+                       Fixed ydelta = gf_muldiv(radius, focal.y-center.y, norm);
+                       focal.x = center.x + xdelta;
+                       focal.y = center.y + ydelta;
+               }
+       }
+
        if (bounds && (!all_atts.gradientUnits || (*(SVG_GradientUnit*)all_atts.gradientUnits==SVG_GRADIENTUNITS_OBJECT)) ) {
                /*move to local coord system - cf SVG spec*/
                gf_mx2d_add_scale(mat, bounds->width, bounds->height);
index 5ac769624ec90de508697cc1d8ad6387a5ced005..8f5cfc45e3d0eb395bbfae44ec08ebc5be967556 100644 (file)
@@ -187,6 +187,7 @@ void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
                }
                if (gf_mo_is_private_media(txh->stream)) {
                        setup_texture_object(txh, 1);
+                       gf_node_dirty_set(txh->owner, 0, 0);
                }
        }
        txh->data = gf_mo_fetch_data(txh->stream, !disable_resync, &txh->stream_finished, &ts, &size);
index 300bb4444c2671448260a8d2c5fb98447f84575b..49b036ee46b1215961b78688d8177fe34807c9c5 100644 (file)
@@ -310,6 +310,7 @@ static Bool tx_setup_format(GF_TextureHandler *txh)
                break;
 #endif
        case GF_PIXEL_YV12:
+       case GF_PIXEL_NV21:
 #ifndef GPAC_USE_OGL_ES 
                if (!compositor->disable_yuvgl && compositor->gl_caps.yuv_texture && !(txh->tx_io->flags & TX_MUST_SCALE) ) {
                        txh->tx_io->gl_format = compositor->gl_caps.yuv_texture;
@@ -486,6 +487,7 @@ assert(txh->data );
                txh->tx_io->flags |= TX_IS_FLIPPED;
                return 1;
        case GF_PIXEL_YV12:
+       case GF_PIXEL_NV21:
                if (txh->tx_io->gl_format == compositor->gl_caps.yuv_texture) {
                        txh->tx_io->conv_format = GF_PIXEL_YVYU;
                        txh->tx_io->flags |= TX_NEEDS_HW_LOAD;
@@ -536,6 +538,7 @@ assert(txh->data );
        switch (txh->pixelformat) {
        case GF_PIXEL_YUY2:
        case GF_PIXEL_YV12:
+       case GF_PIXEL_NV21:
                txh->tx_io->conv_format = dst.pixel_format = GF_PIXEL_RGB_24;
                /*stretch and flip*/
                gf_stretch_bits(&dst, &src, NULL, NULL, 0xFF, 1, NULL, NULL);
@@ -920,8 +923,7 @@ static Bool gf_sc_texture_enable_matte_texture(GF_Node *n)
        char * action ;
        int tmp;
        u8 texture[4];
-       MFFloat coefficients ;
-       GF_Compositor *compositor;
+       MFFloat coefficients;
 #endif
        M_MatteTexture *matte = (M_MatteTexture *)n;
        
@@ -937,7 +939,6 @@ static Bool gf_sc_texture_enable_matte_texture(GF_Node *n)
        return 1;
 #else
 
-       compositor = b_surf->compositor;
        if (glActiveTexture==NULL) {
                tx_bind(b_surf);
                return 1;
index b1e0302bf60e928c77377f14e8ae7fab8c1c0fc4..156082da6767fb69946efa6eb4199bd475b75229 100644 (file)
@@ -242,7 +242,6 @@ GF_Err visual_2d_init_draw(GF_VisualManager *visual, GF_TraverseState *tr_state)
        M_Background2D *bck;
 #endif
        u32 draw_mode;
-       u32 time;
        
        /*reset display list*/
        visual->cur_context = visual->context;
@@ -271,7 +270,6 @@ GF_Err visual_2d_init_draw(GF_VisualManager *visual, GF_TraverseState *tr_state)
        }
        tr_state->invalidate_all = 0;
 
-       time = gf_sys_clock();
        /*reset prev nodes if any (previous traverse was indirect)*/
        rem = count = 0;
        prev = NULL;
@@ -441,7 +439,10 @@ void ra_refresh(GF_RectArray *ra)
 static Bool register_context_rect(GF_RectArray *ra, DrawableContext *ctx, u32 ctx_idx, DrawableContext **first_opaque)
 {
        u32 i;
-       Bool is_transparent, needs_redraw;
+       Bool needs_redraw;
+#ifdef TRACK_OPAQUE_REGIONS
+       Bool is_transparent = 1;
+#endif
        GF_IRect *rc = &ctx->bi->clip;
        assert(rc->width && rc->height);
 
@@ -449,10 +450,10 @@ static Bool register_context_rect(GF_RectArray *ra, DrawableContext *ctx, u32 ct
        needs_redraw = (ctx->flags & CTX_REDRAW_MASK) ? 1 : 0;
 
        /*node is transparent*/
-       is_transparent = 1;
        if ((ctx->flags & CTX_NO_ANTIALIAS) && !(ctx->flags & CTX_IS_TRANSPARENT) ) {
+#ifdef TRACK_OPAQUE_REGIONS
                is_transparent = 0;
-
+#endif
                if ((*first_opaque==NULL) && needs_redraw) *first_opaque = ctx;
        }
 
@@ -651,8 +652,6 @@ Bool visual_2d_terminate_draw(GF_VisualManager *visual, GF_TraverseState *tr_sta
                        it = it->next;
                }
        }
-       /*no visual */
-       //if (!visual->compositor->output_width && !visual->compositor->output_height) goto exit;
 
        if (redraw_all) {
                ra_clear(&visual->to_redraw);
@@ -722,12 +721,12 @@ Bool visual_2d_terminate_draw(GF_VisualManager *visual, GF_TraverseState *tr_sta
 skip_background:
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_COMPOSE)) {
-               GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redraw %d / %d nodes (all: %s)", num_changed, num_nodes, redraw_all ? "yes" : "no"));
+       if (gf_log_tool_level_on(GF_LOG_COMPOSE, GF_LOG_INFO)) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Visual2D] Redraw %d / %d nodes (all: %s - %d dirty rects\n)", num_changed, num_nodes, redraw_all ? "yes" : "no", visual->to_redraw.count));
                if (visual->to_redraw.count>1) GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("\n"));
 
                for (i=0; i<visual->to_redraw.count; i++) {
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("\tDirtyRect #%d: %d:%d@%dx%d\n", i+1, visual->to_redraw.list[i].x, visual->to_redraw.list[i].y, visual->to_redraw.list[i].width, visual->to_redraw.list[i].height));
+                       GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("\tDirtyRect #%d: %d:%d@%dx%d\n", i+1, visual->to_redraw.list[i].x, visual->to_redraw.list[i].y, visual->to_redraw.list[i].width, visual->to_redraw.list[i].height));
                        assert(visual->to_redraw.list[i].width);
                }
        }
@@ -776,7 +775,6 @@ exit:
        visual_2d_release_raster(visual);
        visual_clean_contexts(visual);
        visual->num_nodes_prev_frame = visual->num_nodes_current_frame;
-       GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redraw done - %schanged\n", has_changed ? "" : "un"));
        return has_changed;
 }
 
@@ -796,6 +794,7 @@ Bool visual_2d_draw_frame(GF_VisualManager *visual, GF_Node *root, GF_TraverseSt
        e = visual_2d_init_draw(visual, tr_state);
        if (e) {
                gf_mx2d_copy(tr_state->transform, backup);
+               GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Visual2D] Cannot init draw phase: %s\n", gf_error_to_string(e)));
                return 0;
        }
 
index 9bc86d3242ac3f2e1d38d2d025b16cd249020fda..e5840eab09bffbd753759ad3b83c11cfed7ad97c 100644 (file)
@@ -98,7 +98,7 @@ static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx,
        /*background & direct drawing : use ctx clip*/
        if ((ctx->flags & CTX_IS_BACKGROUND) || tr_state->immediate_draw) {
                if (ctx->bi->clip.width && ctx->bi->clip.height) {
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s (direct draw)\n", gf_node_get_log_name(ctx->drawable->node) ));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (direct draw)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node) ));
 
                        if (stencil) {
                                raster->surface_set_clipper(visual->raster_surface, &ctx->bi->clip);
@@ -121,7 +121,7 @@ static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx,
                        clip = ctx->bi->clip;
                        gf_irect_intersect(&clip, &visual->to_redraw.list[i]);
                        if (clip.width && clip.height) {
-                               GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), i));
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node), i));
                                if (stencil) {
                                        raster->surface_set_clipper(visual->raster_surface, &clip);
                                        raster->surface_fill(visual->raster_surface, stencil);
@@ -275,7 +275,10 @@ void visual_2d_texture_path_text(GF_VisualManager *visual, DrawableContext *txt_
        GF_Rect orig_rc;
        u8 alpha, r, g, b;
        GF_ColorMatrix cmat;
-       GF_Raster2D *raster = visual->compositor->rasterizer;
+       GF_Raster2D *raster;
+
+       if (!visual->is_attached) return;
+       raster = visual->compositor->rasterizer;
 
        stencil = gf_sc_texture_get_stencil(txh);
        if (!stencil) return;
@@ -337,8 +340,10 @@ void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF
        u32 tx_tile;
        GF_STENCIL tx_raster;
        GF_Matrix2D mx_texture;
-       GF_Rect rc, orig_rc;
-       GF_Raster2D *raster = visual->compositor->rasterizer;
+       GF_Rect orig_rc;
+       GF_Raster2D *raster;
+       if (!visual->is_attached) return;
+       raster = visual->compositor->rasterizer;
 
        if (!txh) txh = ctx->aspect.fill_texture;
        if (!txh) return;
@@ -394,10 +399,6 @@ void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF
                gf_path_get_bounds(path, &orig_rc);
        }
 
-       /*get active texture window in pixels*/
-       rc.width = INT2FIX(txh->width);
-       rc.height = INT2FIX(txh->height);
-
        /*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
        sS = orig_rc.width / txh->width;
        sT = orig_rc.height / txh->height;
@@ -461,7 +462,7 @@ void visual_2d_texture_path(GF_VisualManager *visual, GF_Path *path, struct _dra
 #ifdef SKIP_DRAW
        return;
 #endif
-       if (!visual->raster_surface || (ctx->flags & CTX_PATH_FILLED) || !ctx->aspect.fill_texture || visual->compositor->is_hidden) return;
+       if (!visual->is_attached || (ctx->flags & CTX_PATH_FILLED) || !ctx->aspect.fill_texture || visual->compositor->is_hidden) return;
 
        /*this is ambiguous in the spec, what if the material is filled and the texture is transparent ?
        let's draw, it's nicer */
@@ -485,8 +486,7 @@ void visual_2d_draw_path_extended(GF_VisualManager *visual, GF_Path *path, Drawa
 #ifdef SKIP_DRAW
        return;
 #endif
-       
-       assert(visual->raster_surface);
+       if (!visual->is_attached) return;
 
        if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
                if (visual->compositor->draw_bvol) draw_clipper(visual, ctx);
@@ -579,7 +579,7 @@ void visual_2d_fill_rect(GF_VisualManager *visual, DrawableContext *ctx, GF_Rect
        return;
 #endif
 
-       if (!visual->raster_surface) return;
+       if (!visual->is_attached) return;
        if (!color && !strike_color) return;
 
        if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
@@ -643,7 +643,7 @@ void visual_2d_fill_irect(GF_VisualManager *visual, GF_IRect *rc, u32 fill, u32
 #endif
 
        if (!rc) return;
-       if (!visual->raster_surface) return;
+       if (!visual->is_attached) return;
        if (!fill && !strike ) return;
 
        /*no aa*/
index 9f537ef25173d95dd3b2c02922caadf374f18a56..a458758814af17a9acfa066e2be0fb97ec2c9073 100644 (file)
@@ -173,6 +173,7 @@ void visual_3d_viewpoint_change(GF_TraverseState *tr_state, GF_Node *vp, Bool an
        Fixed dist;
        SFVec3f d;
 
+
        /*update znear&zfar*/
        tr_state->camera->z_near = tr_state->camera->avatar_size.x ; 
 
@@ -665,7 +666,13 @@ void visual_3d_register_context(GF_TraverseState *tr_state, GF_Node *geometry)
                }
                
                gf_node_traverse(geometry, tr_state);
-       
+
+               /*clear appearance flag once drawn in 3D - not doing so would prevent
+               dirty flag propagation in the tree, whcih would typically prevent redrawing 
+               layers/offscreen groups when texture changes*/
+               if (tr_state->appear)
+                       gf_node_dirty_clear(tr_state->appear, 0);
+               
                /*back to SORT*/
                tr_state->traversing_mode = TRAVERSE_SORT;
 
@@ -773,8 +780,15 @@ void visual_3d_flush_contexts(GF_VisualManager *visual, GF_TraverseState *tr_sta
                tr_state->depth_offset = ctx->depth_offset;
 #endif
                gf_node_traverse(ctx->geometry, tr_state);
-               tr_state->appear = NULL;
-               
+
+               /*clear appearance flag once drawn in 3D - not doing so would prevent
+               dirty flag propagation in the tree, whcih would typically prevent redrawing 
+               layers/offscreen groups when texture changes*/
+               if (tr_state->appear) {
+                       gf_node_dirty_clear(tr_state->appear, 0);
+                       tr_state->appear = NULL;
+               }
+
                /*reset directional lights*/
                tr_state->local_light_on = 0;
                for (i=gf_list_count(ctx->directional_lights); i>0; i--) {
@@ -890,7 +904,7 @@ static void reset_collide_cursor(GF_Compositor *compositor)
 
 void visual_3d_check_collisions(GF_TraverseState *tr_state, GF_ChildNodeItem *node_list)
 {
-       SFVec3f n, pos, dir;
+       SFVec3f n, dir;
        Bool go;
        Fixed diff, pos_diff;
 
@@ -917,7 +931,6 @@ void visual_3d_check_collisions(GF_TraverseState *tr_state, GF_ChildNodeItem *no
        gf_vec_diff(dir, tr_state->camera->position, tr_state->camera->last_pos);
        pos_diff = gf_vec_len(dir);
        gf_vec_norm(&dir);
-       pos = tr_state->camera->position;
        
        diff = 0;
        go = 1;
@@ -1322,8 +1335,7 @@ void visual_3d_vrml_drawable_pick(GF_Node *n, GF_TraverseState *tr_state, GF_Mes
 
        if (compositor_is_composite_texture(tr_state->appear)) {
                compositor->hit_appear = tr_state->appear;
-       } else 
-       {
+       } else {
                compositor->hit_appear = NULL;
        }
        compositor->hit_node = n;
@@ -1400,7 +1412,7 @@ void visual_3d_vrml_drawable_collide(GF_Node *node, GF_TraverseState *tr_state)
                        tr_state->camera->collide_point = collide_pt;
 
 #ifndef GPAC_DISABLE_LOG
-                       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_COMPOSE)) {                            
+                       if (gf_log_tool_level_on(GF_LOG_COMPOSE, GF_LOG_DEBUG)) {                               
                                gf_vec_diff(v1, pos, collide_pt);
                                gf_vec_norm(&v1);
                                GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Collision] found at %g %g %g (WC) - dist (%g) - local normal %g %g %g\n", 
index 12699082de370d77aed44ab41a1691ddfcf35f2d..e4d50bea2f781cc49e5c23c04019573cf0d86d7c 100644 (file)
 #undef GL_MAX_CLIP_PLANES
 #endif
 
-#ifdef GPAC_ANDROID
-#define GPAC_USE_TINYGL
-#endif
-
 #ifdef GPAC_USE_OGL_ES
 #define GL_CLAMP GL_CLAMP_TO_EDGE
 #endif
 
 GLDECL_STATIC(glActiveTexture);
 GLDECL_STATIC(glClientActiveTexture);
-GLDECL_STATIC(glGenBuffers);
-GLDECL_STATIC(glDeleteBuffers);
-GLDECL_STATIC(glBindBuffer);
-GLDECL_STATIC(glBufferData);
-GLDECL_STATIC(glBufferSubData);
+GLDECL_STATIC(glBlendEquation);
 
 #endif //LOAD_GL_1_3
 
@@ -92,6 +84,15 @@ GLDECL_STATIC(glPointParameterfv);
 
 #endif //LOAD_GL_1_4
 
+
+#ifdef LOAD_GL_1_5
+GLDECL_STATIC(glGenBuffers);
+GLDECL_STATIC(glDeleteBuffers);
+GLDECL_STATIC(glBindBuffer);
+GLDECL_STATIC(glBufferData);
+GLDECL_STATIC(glBufferSubData);
+#endif //LOAD_GL_1_5
+
 #ifdef LOAD_GL_2_0
 
 GLDECL_STATIC(glCreateProgram);
@@ -132,7 +133,6 @@ GLDECL_STATIC(glUniformMatrix2x4fv);
 GLDECL_STATIC(glUniformMatrix4x2fv);
 GLDECL_STATIC(glUniformMatrix3x4fv);
 GLDECL_STATIC(glUniformMatrix4x3fv);
-GLDECL_STATIC(glBlendEquation);
 
 
 #endif //LOAD_GL_2_0
@@ -196,13 +196,7 @@ void gf_sc_load_opengl_extensions(GF_Compositor *compositor, Bool has_gl_context
                GET_GLFUN(glActiveTexture);
                GET_GLFUN(glClientActiveTexture);
        }
-       if (compositor->gl_caps.vbo) {
-               GET_GLFUN(glGenBuffers);
-               GET_GLFUN(glDeleteBuffers);
-               GET_GLFUN(glBindBuffer);
-               GET_GLFUN(glBufferData);
-               GET_GLFUN(glBufferSubData);
-       }
+       GET_GLFUN(glBlendEquation);
 #endif
 
 #ifdef LOAD_GL_1_4
@@ -210,7 +204,16 @@ void gf_sc_load_opengl_extensions(GF_Compositor *compositor, Bool has_gl_context
                GET_GLFUN(glPointParameterf);
                GET_GLFUN(glPointParameterfv);
        }
-       GET_GLFUN(glBlendEquation);
+#endif
+
+#ifdef LOAD_GL_1_5
+       if (compositor->gl_caps.vbo) {
+               GET_GLFUN(glGenBuffers);
+               GET_GLFUN(glDeleteBuffers);
+               GET_GLFUN(glBindBuffer);
+               GET_GLFUN(glBufferData);
+               GET_GLFUN(glBufferSubData);
+       }
 #endif
 
 
@@ -2353,10 +2356,10 @@ void visual_3d_point_sprite(GF_VisualManager *visual, Drawable *stack, GF_Textur
                                z = p[3]; z = z / 255;
 
                                glColor4f(r, g, b, 1.0);
-                               glVertex3f(x, y, -z*60);
-                               x += inc;
+                               glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(-z)*60);
+                               x += FLT2FIX(inc);
                        }
-                       y -= inc;
+                       y -= FLT2FIX(inc);
                }
                glEnd();
 
@@ -2365,7 +2368,7 @@ void visual_3d_point_sprite(GF_VisualManager *visual, Drawable *stack, GF_Textur
        }
 
        if (visual->compositor->depth_gl_type==GF_SC_DEPTH_GL_STRIPS) {
-               delta = visual->compositor->depth_gl_strips_filter;
+               delta = FIX2FLT(visual->compositor->depth_gl_strips_filter);
                if (!delta) first_pass = 2;
                else first_pass = 1;
 
@@ -2409,7 +2412,7 @@ restart:
                                                        glEnd();
                                                        in_strip = 0;
                                                }
-                                               x += inc;
+                                               x += FLT2FIX(inc);
                                                continue;
                                        }
                                } else if (first_pass==0) {
@@ -2419,7 +2422,7 @@ restart:
                                                        glEnd();
                                                        in_strip = 0;
                                                }
-                                               x += inc;
+                                               x += FLT2FIX(inc);
                                                continue;
                                        }
                                }
@@ -2439,7 +2442,7 @@ restart:
                                }
 
                                glColor3f(r, g, b);
-                               glVertex3f(x, y, z1*scale);
+                               glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(z1)*scale);
 
                                r = p2[0];
                                r /= 255;
@@ -2449,15 +2452,15 @@ restart:
                                b /= 255;
 
                                glColor3f(r, g, b);
-                               glVertex3f(x, y-inc, z2*scale);
+                               glVertex3f(FIX2FLT(x), FIX2FLT(y)-inc, FIX2FLT(z2)*scale);
 
-                               x += inc;
+                               x += FLT2FIX(inc);
                        }
                        if (in_strip) {
                                glEnd();
                                in_strip = 0;
                        }
-                       y -= inc;
+                       y -= FLT2FIX(inc);
                }
 
                if (first_pass==1) {
@@ -2485,7 +2488,7 @@ restart:
 
                        for (w=0; w<txh->width; w++) {
                                mesh_set_vertex(stack->mesh, x, y, 0, 0, 0, -FIX_ONE, INT2FIX(w) / (txh->width-1), INT2FIX(txh->height - h  -1) / (txh->height-1) );
-                               x += inc;
+                               x += FLT2FIX(inc);
 
                                /*set triangle*/
                                if (h && w) {
@@ -2494,7 +2497,7 @@ restart:
                                        mesh_set_triangle(stack->mesh, first_idx, txh->width + first_idx, txh->width + first_idx +1);
                                }
                        }
-                       y -= inc;
+                       y -= FLT2FIX(inc);
                }
                /*force recompute of Z*/
                txh->needs_refresh = 1;
index ba7efe3e35171a817f48d66d074f0181a59b81b8..87b1536c8f47a07d4ac9fcd0c4ad723554cad5b4 100644 (file)
@@ -43,6 +43,9 @@
 #pragma comment (linker, EXPORT_SYMBOL(gf_sys_init) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sys_close) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sleep) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_mkdir) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_rmdir) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_cleanup_dir) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sys_clock) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sys_get_rti) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sys_get_battery_state) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_rand) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_get_user_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_enum_directory) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_get_tools) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_get_level) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_set_level) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_set_tools) )
+
+#pragma comment (linker, EXPORT_SYMBOL(gf_log_modify_tools_levels) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_log_set_tools_levels) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_log_set_tool_level) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_log_set_strict_error) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_log_set_callback) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_parse_level) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_log_parse_tools) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_log_get_tools_levels) )
+
+#ifndef GPAC_DISABLE_LOG
+#pragma comment (linker, EXPORT_SYMBOL(gf_log_tool_level_on) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_log) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_log_lt) )
+#endif
+
 #pragma comment (linker, EXPORT_SYMBOL(gf_set_progress) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_set_progress_callback) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_delete_file) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_move_file) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_temp_file_new) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_file_modification_time) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_fwrite) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_f64_open) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_f64_seek) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_f64_tell) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_list_reset) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_list_last) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_list_rem_last) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_list_swap) )
 
 /* Bitstream */
 #pragma comment (linker, EXPORT_SYMBOL(gf_bs_new) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_xml_dom_get_line) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_xml_dom_serialize) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_xml_dom_node_del) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_xml_dom_parse_string) )
+
 
 #ifndef GPAC_DISABLE_SVG
 #pragma comment (linker, EXPORT_SYMBOL(gf_dom_get_key_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_angle_diff) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_v2d_len) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_v2d_from_polar) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_v2d_distance) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_rect_union) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_rect_center) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_rect_overlaps) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_delete) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_mode) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_file_size) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_moov_first) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_timed_meta_data_info) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_box_new) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_box_del) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_self_contained) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_media_duration) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_media_timescale) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_max_chunk_duration) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_chunks_infos) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_handler_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_media_language) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_check_data_reference) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_meta_primary_item_id) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_JPEG2000) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_rvc_config) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_reset_fragment_info) )
 
 
 # ifndef GPAC_DISABLE_ISOM_DUMP
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_new_dims_description) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_update_dims_description) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_rvc_config) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_sample_rap_group) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_sample_roll_group) )
+
 #ifndef GPAC_DISABLE_ISOM_HINTING
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_setup_hint_track) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_new_hint_description) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_img_parse) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_img_jpeg_dec) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_img_png_dec) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_img_png_file_dec) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_img_png_enc) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_img_file_dec) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_m4v_get_profile_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_mp3_version) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_mp3_version_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sm_load_run) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sm_load_suspend) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sm_import_bifs_subtitle) )
+#ifndef GPAC_DISABLE_LOADER_BT
 #pragma comment (linker, EXPORT_SYMBOL(gf_sm_load_bt_from_string) )
+#endif
 
 #ifndef GPAC_DISABLE_SCENE_ENCODER
 #pragma comment (linker, EXPORT_SYMBOL(gf_sm_encode_to_file) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_js_add_root) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_js_add_named_root) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_js_remove_root) )
-
+#pragma comment (linker, EXPORT_SYMBOL(gf_js_vrml_flush_event_out) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_js_has_instance) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_sg_lock_javascript) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_sg_try_lock_javascript) )
 
 #ifndef GPAC_DISABLE_SVG
+#pragma comment (linker, EXPORT_SYMBOL(dom_js_pre_destroy) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_js_event_add_listener) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_js_event_remove_listener) )
 #endif
-#endif
+
+#endif /*GPAC_HAS_SPIDERMONKEY*/
 
 /* scenegraph_vrml.h exports*/
 #pragma comment (linker, EXPORT_SYMBOL(gf_node_replace_child) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_get_next_available_proto_id) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_set_proto_loader) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sg_sfcolor_to_rgba) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_sg_lock_javascript) )
 
 #ifndef GPAC_DISABLE_X3D
 #pragma comment (linker, EXPORT_SYMBOL(gf_node_x3d_type_by_class_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sc_add_audio_listener) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sc_remove_audio_listener) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sc_focus_switch_ring) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_sc_animation_get_scenegraph) )
 
 #ifndef GPAC_DISABLE_SVG
+#pragma comment (linker, EXPORT_SYMBOL(gf_sc_animation_get_scenegraph) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_sc_svg_convert_length_to_display) )
 #endif
 
 #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_stream_name) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_crc32_check) )
 
+/* carousel.h */
+#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_channel_application_info) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_process_dsmcc) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_init_dsmcc_overlord) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_dmscc_overlord) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_demux_dmscc_init) )
+
+
+
 #ifndef GPAC_DISABLE_MPEG2TS_MUX
 #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_mux_new) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_mux_del) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_mpd_init_from_dom) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_mpd_del) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_m3u8_to_mpd) )
+#pragma comment (linker, EXPORT_SYMBOL(parse_root_playlist) )
+#pragma comment (linker, EXPORT_SYMBOL(variant_playlist_del) )
+
 
 #pragma comment (linker, EXPORT_SYMBOL(TSDemux_Demux_Setup))
 #pragma comment (linker, EXPORT_SYMBOL(TSDemux_DemuxPlay) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_font_manager_refresh_span_bounds) )
 
 /*download.h exports*/
- #pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget) )
- #pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget_with_cache) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget_with_cache) )
+
+#ifndef GPAC_DISABLE_ISOM
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_start) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_end) )
+#endif
 
 /* dvb_mpe.h */
 #ifdef GPAC_ENST_PRIVATE
 #pragma comment (linker, EXPORT_SYMBOL(gf_dvb_mpe_shutdown) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_print_mpe_info) )
 #endif
-
-/* carousel.h */
-#pragma comment (linker, EXPORT_SYMBOL(on_ait_section) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_process_ait) )
-
-
-
index fa6044a6cb5ef3d6aee28e424ebbd811ddf83756..b0444f011a60f59ffc5162dc1670f27c7f50de16 100644 (file)
@@ -53,7 +53,7 @@ GF_Err gf_rtp_decode_rtcp(GF_RTPChannel *ch, char *pck, u32 pck_size, Bool *has_
        GF_RTCPHeader rtcp_hdr;
        GF_BitStream *bs;
        char sdes_buffer[300];
-       u32 i, sender_ssrc, cur_ssrc, val, sdes_type, sdes_len, res, first, nb_bytes, nb_pck;
+       u32 i, sender_ssrc, cur_ssrc, val, sdes_type, sdes_len, res, first;
        GF_Err e = GF_OK;
 
        if (has_sr) *has_sr=0;
@@ -115,14 +115,14 @@ GF_Err gf_rtp_decode_rtcp(GF_RTPChannel *ch, char *pck, u32 pck_size, Bool *has_
                        ch->last_SR_NTP_sec = gf_bs_read_u32(bs);
                        ch->last_SR_NTP_frac = gf_bs_read_u32(bs);
                        ch->last_SR_rtp_time = gf_bs_read_u32(bs);
-                       nb_pck = gf_bs_read_u32(bs);
-                       nb_bytes = gf_bs_read_u32(bs);
+                       /*nb_pck =  */gf_bs_read_u32(bs);
+                       /*nb_bytes =*/gf_bs_read_u32(bs);
 
                        rtcp_hdr.Length -= 5;
                        if (has_sr) *has_sr=1;
 
 #ifndef GPAC_DISABLE_LOG
-                       if ((gf_log_get_level() >= (GF_LOG_INFO)) && (gf_log_get_tools() & (GF_LOG_RTP)))  {
+                       if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_INFO))  {
 #ifndef _WIN32_WCE
                                time_t gtime = ch->last_SR_NTP_sec - GF_NTP_SEC_1900_TO_1970;
                                const char *ascTime = asctime(gmtime(&gtime));
@@ -351,7 +351,7 @@ static u32 RTCP_FormatReport(GF_RTPChannel *ch, GF_BitStream *bs, u32 NTP_Time)
 
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= (GF_LOG_DEBUG)) && (gf_log_get_tools() & (GF_LOG_RTP)))  {
+       if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_DEBUG))  {
 #ifndef _WIN32_WCE
                time_t gtime = ch->last_SR_NTP_sec - GF_NTP_SEC_1900_TO_1970;
                const char *ascTime = asctime(gmtime(&gtime));
index b280bcbc45a26368631dc5235d4fb65a8c0c9cf7..20d178e4a48f2fc8311733e6931c862a68c0cfe2 100644 (file)
@@ -277,7 +277,7 @@ GF_Err gf_rtp_initialize(GF_RTPChannel *ch, u32 UDPBufferSize, Bool IsSource, u3
        
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= (GF_LOG_DEBUG)) && (gf_log_get_tools() & (GF_LOG_RTP)))  {
+       if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_DEBUG))  {
                GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] Packet Log Format: SSRC SequenceNumber TimeStamp NTP@recvTime deviance, Jiter, PckLost PckTotal BytesTotal\n"));
        }
 #endif
@@ -329,7 +329,10 @@ u32 gf_rtp_read_rtp(GF_RTPChannel *ch, char *buffer, u32 buffer_size)
 
        e = gf_sk_receive(ch->rtp, buffer, buffer_size, 0, &res);
        if (!res || e || (res < 12)) res = 0;
-
+    if (res){
+        ch->total_bytes+=res;
+        ch->total_pck++;
+    }
        //add the packet to our Queue if any
        if (ch->po) {
                if (res) {
@@ -351,6 +354,7 @@ u32 gf_rtp_read_rtp(GF_RTPChannel *ch, char *buffer, u32 buffer_size)
                        ch->last_nat_keepalive_time = now; 
                } else {
                        if (now - ch->last_nat_keepalive_time >= ch->nat_keepalive_time_period) {
+#if 0
                                char rtp_nat[12];
                                rtp_nat[0] = (u8) 0xC0;
                                rtp_nat[1] = ch->PayloadType;
@@ -364,7 +368,7 @@ u32 gf_rtp_read_rtp(GF_RTPChannel *ch, char *buffer, u32 buffer_size)
                                rtp_nat[9] = (ch->SenderSSRC>>16)&0xFF;
                                rtp_nat[10] = (ch->SenderSSRC>>8)&0xFF;
                                rtp_nat[11] = (ch->SenderSSRC)&0xFF;
-
+#endif
                                e = gf_sk_send(ch->rtp, buffer, 12);
                                if (e) {
                                        GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Error sending NAT keep-alive packet: %s - disabling NAT\n", gf_error_to_string(e) ));
@@ -478,7 +482,7 @@ GF_Err gf_rtp_decode_rtp(GF_RTPChannel *ch, char *pck, u32 pck_size, GF_RTPHeade
        ch->last_pck_sn = CurrSeq;
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= (GF_LOG_DEBUG)) && (gf_log_get_tools() & (GF_LOG_RTP)))  {
+       if (gf_log_tool_level_on(GF_LOG_RTP, GF_LOG_DEBUG))  {
                ch->total_pck++;
                ch->total_bytes += pck_size-12;
 
@@ -644,7 +648,6 @@ static u16 NextAvailablePort = 0;
 GF_EXPORT
 GF_Err gf_rtp_set_ports(GF_RTPChannel *ch, u16 first_port)
 {
-       u32 retry;
        u16 p;
        GF_Socket *sock;
        if (!ch) return GF_BAD_PARAM;
@@ -659,7 +662,6 @@ GF_Err gf_rtp_set_ports(GF_RTPChannel *ch, u16 first_port)
        if (!sock) return GF_IO_ERR;
 
        /*should be way enough (more than 100 rtp streams open on the machine)*/
-       retry = 100;
        while (1) {
                /*try to bind without reuse. If fails this means the port is used on the machine, don't reuse it*/
                GF_Err e = gf_sk_bind(sock, NULL, p, NULL, 0, 0);
@@ -782,7 +784,7 @@ void gf_rtp_reorderer_reset(GF_RTPReorder *po)
        po->in = NULL;
 }
 
-GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, void *pck, u32 pck_size, u32 pck_seqnum)
+GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, const void * pck, u32 pck_size, u32 pck_seqnum)
 {
        GF_POItem *it, *cur;
        u32 bounds;
index 1d952f568019d6e42f5bc853e0958762769f3f57..067b69847cf48b0c457e85aa34248ce2c7d901fa 100644 (file)
@@ -355,9 +355,9 @@ static void gf_rtp_parse_amr(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *p
                c = payload[i + 1];
                type = ((c & 0x78) >> 3);
                if (rtp->payt==GF_RTP_PAYT_AMR) {
-                       frame_size = GF_AMR_FRAME_SIZE[type];
+                       frame_size = (u32)GF_AMR_FRAME_SIZE[type];
                } else {
-                       frame_size = GF_AMR_WB_FRAME_SIZE[type];
+                       frame_size = (u32)GF_AMR_WB_FRAME_SIZE[type];
                }
 
                rtp->sl_hdr.compositionTimeStampFlag = 1;
@@ -381,7 +381,7 @@ static void gf_rtp_parse_h263(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *
 {
        GF_BitStream *bs;
        Bool P_bit, V_bit;
-       u32 plen, plen_bits;
+       u32 plen;
        u64 offset;
        char blank[2];
 
@@ -391,7 +391,7 @@ static void gf_rtp_parse_h263(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *
        P_bit = gf_bs_read_int(bs, 1);
        V_bit = gf_bs_read_int(bs, 1);
        plen = gf_bs_read_int(bs, 6);
-       plen_bits = gf_bs_read_int(bs, 3);
+       /*plen_bits = */gf_bs_read_int(bs, 3);
 
        /*VRC not supported yet*/
        if (V_bit) {
@@ -821,12 +821,12 @@ static void gf_rtp_parse_3gpp_dims(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, c
 
 static void gf_rtp_parse_ac3(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size)
 {
-       u8 ft, nb_pck;
+       u8 ft;
 
        rtp->sl_hdr.compositionTimeStampFlag = 1;
        rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
        ft = payload[0];
-       nb_pck = payload[1];
+       /*nb_pck = payload[1];*/
        payload += 2;
        size -= 2;
 
@@ -835,7 +835,7 @@ static void gf_rtp_parse_ac3(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *p
                rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1;
                while (size) {
                        u32 offset;
-                       if (!gf_ac3_parser(payload, size, &offset, &hdr, 0)) {
+                       if (!gf_ac3_parser((u8*)payload, size, &offset, &hdr, 0)) {
                                return;
                        }
                        if (offset) {
index 80940dab1ed7190fbfbb13f2e9b54b9ad1e31286..f7c4049998bc62d1156d7c0d1ea66755a1f6f8f1 100644 (file)
@@ -130,7 +130,7 @@ void gf_rtp_builder_init(GP_RTPPacketizer *builder, u8 PayloadType, u32 PathMTU,
                                           u32 IV_length, u32 KI_length,
                                           char *pref_mode) 
 {
-       u32 k, totDelta, ismacrypt_flags;
+       u32 k, ismacrypt_flags;
 
        memset(&builder->slMap, 0, sizeof(GP_RTPSLMap));
        builder->Path_MTU = PathMTU;
@@ -339,7 +339,6 @@ void gf_rtp_builder_init(GP_RTPPacketizer *builder, u8 PayloadType, u32 PathMTU,
 
        if (builder->flags & GP_RTP_PCK_SIGNAL_TS) {
                /*compute CTS delta*/
-               totDelta = k*avgTS;
                builder->slMap.CTSDeltaLength = gf_get_bit_size(k*avgTS);
 
                /*compute DTS delta. Delta is ALWAYS from the CTS of the same sample*/ 
index d7eb761e283b18352d75d4fa0d86ddf3073cde0e..ffc7c7cd43c671172d61a0edeeb3ee25e94964fe 100644 (file)
@@ -62,10 +62,10 @@ GF_Err gp_rtp_builder_do_amr(GP_RTPPacketizer *builder, char *data, u32 data_siz
                u8 size;
 
                if (builder->rtp_payt == GF_RTP_PAYT_AMR_WB) {
-                       size = GF_AMR_WB_FRAME_SIZE[ft];
+                       size = (u32)GF_AMR_WB_FRAME_SIZE[ft];
                        block_size = 320;
                } else {
-                       size = GF_AMR_FRAME_SIZE[ft];
+                       size = (u32)GF_AMR_FRAME_SIZE[ft];
                        block_size = 160;
                }
 
@@ -118,7 +118,7 @@ GF_Err gp_rtp_builder_do_amr(GP_RTPPacketizer *builder, char *data, u32 data_siz
        return GF_OK;
 }
 
-static GFINLINE u8 qes_get_rate_size(u32 idx, const u32 *rates, u32 nb_rates)
+static GFINLINE u8 qes_get_rate_size(u32 idx, const unsigned int *rates, const unsigned int nb_rates)
 {
        u32 i;
        for (i=0; i<nb_rates; i++) {
@@ -226,7 +226,7 @@ GF_Err gp_rtp_builder_do_smv(GP_RTPPacketizer *builder, char *data, u32 data_siz
        offset = 0;
        while (data_size>offset) {
                u8 frame_type = data[offset];
-               u8 size = qes_get_rate_size(frame_type, (u32 *)GF_SMV_EVRC_RATE_TO_SIZE, GF_SMV_EVRC_RATE_TO_SIZE_NB);
+               u8 size = qes_get_rate_size(frame_type, GF_SMV_EVRC_RATE_TO_SIZE, GF_SMV_EVRC_RATE_TO_SIZE_NB);
 
                /*reserved, not sent)*/
                if (frame_type>=5) {
index 08a3dbd1ee949a30c143b2323213196775f66277..c9d59319e4c0a3832821dbcfbb4b514a7defc1d3 100644 (file)
@@ -205,12 +205,11 @@ GF_Err gp_rtp_builder_do_mpeg4(GP_RTPPacketizer *builder, char *data, u32 data_s
 {
        char *sl_buffer, *payl_buffer;
        u32 sl_buffer_size, payl_buffer_size; 
-       u32 auh_size_tmp, rslh_tmp, bytesLeftInPacket, infoSize, pckSize;
+       u32 auh_size_tmp, bytesLeftInPacket, infoSize, pckSize;
        u64 pos;
        u8 flush_pck, no_split;
 
        flush_pck = 0;
-       rslh_tmp = 0;
 
        bytesLeftInPacket = data_size;
        /*flush everything*/
index c111b30b7fd8cb5005d04cd80f09cbf899670b45..be74f8f93725bf636543213cc8182ab763ae8fb6 100644 (file)
@@ -438,6 +438,8 @@ GF_RTPStreamer *gf_rtp_streamer_new_extended(u32 streamType, u32 oti, u32 timeSc
                                           streamType, oti, PL_ID, MinSize, MaxSize, avgTS, maxDTSDelta, IV_length, KI_length, mpeg4mode);
 
 
+       if (force_dts_delta) stream->packetizer->slMap.DTSDeltaLength = force_dts_delta;
+
        e = rtp_stream_init_channel(stream, MTU + 12, ip_dest, port, TTL, ifce_addr);
        if (e) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP Packetizer] Failed to create RTP channel - error %s\n", gf_error_to_string(e) ));
index 61628f133366cf8d2fb83234b9be442600d5037d..3d3da54b32f73184610abe14ffc99846e45c155c 100644 (file)
@@ -32,7 +32,7 @@
 GF_Err gf_rtsp_read_reply(GF_RTSPSession *sess)
 {
        GF_Err e;
-       u32 res, body_size;
+       u32 res, body_size = 0;
        u32 BodyStart = 0;
 
        //fetch more data on the socket if needed
index 27d5fef9de149b700c1c4ce774d39de65c6798d3..df6b8f5d6a18a76c3f6fe271ff5a027ae19136fe 100644 (file)
@@ -615,6 +615,7 @@ GF_Err styl_Write(GF_Box *s, GF_BitStream *bs)
        u32 i;
        GF_TextStyleBox*ptr = (GF_TextStyleBox*)s;
        e = gf_isom_box_write_header(s, bs);
+       assert(e == GF_OK);
 
        gf_bs_write_u16(bs, ptr->entry_count);
        for (i=0; i<ptr->entry_count; i++) gpp_write_style(bs, &ptr->styles[i]);
index 89fb162854872bccb9abf66a68f32b4ab4679ffe..46a260321502c3b381b8cfb64ac513039171c5b3 100644 (file)
@@ -3448,6 +3448,7 @@ GF_Err mp4a_AddBox(GF_Box *s, GF_Box *a)
                                GF_Err e;
                                GF_BitStream *bs = gf_bs_new(wave->data+offset, wave->dataSize-offset, GF_BITSTREAM_READ);
                                e = gf_isom_parse_box(&a, bs);
+                               assert(e == GF_OK);
                                gf_bs_del(bs);
                                ptr->esd = (GF_ESDBox *)a;
                        }
@@ -4495,6 +4496,8 @@ void stbl_del(GF_Box *s)
        if (ptr->PaddingBits) gf_isom_box_del((GF_Box *) ptr->PaddingBits);
        if (ptr->Fragments) gf_isom_box_del((GF_Box *) ptr->Fragments);
        if (ptr->SubSamples) gf_isom_box_del((GF_Box *) ptr->SubSamples);
+       if (ptr->sampleGroups) gf_isom_box_array_del(ptr->sampleGroups);
+       if (ptr->sampleGroupsDescription) gf_isom_box_array_del(ptr->sampleGroupsDescription);
 
        gf_free(ptr);
 }
@@ -4564,6 +4567,15 @@ GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a)
                ptr->SubSamples = (GF_SubSampleInformationBox *)a;
                break;
 
+       case GF_ISOM_BOX_TYPE_SBGP:
+               if (!ptr->sampleGroups) ptr->sampleGroups = gf_list_new();
+               gf_list_add(ptr->sampleGroups, a);
+               break;
+       case GF_ISOM_BOX_TYPE_SGPD:
+               if (!ptr->sampleGroupsDescription) ptr->sampleGroupsDescription = gf_list_new();
+               gf_list_add(ptr->sampleGroupsDescription, a);
+               break;
+
        default:
                GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type)));
                gf_isom_box_del(a);
@@ -4691,6 +4703,14 @@ GF_Err stbl_Write(GF_Box *s, GF_BitStream *bs)
                e = gf_isom_box_write((GF_Box *) ptr->SubSamples, bs);
                if (e) return e;
        }
+       if (ptr->sampleGroupsDescription) {
+               e = gf_isom_box_array_write(s, ptr->sampleGroupsDescription, bs);
+               if (e) return e;
+       }
+       if (ptr->sampleGroups) {
+               e = gf_isom_box_array_write(s, ptr->sampleGroups, bs);
+               if (e) return e;
+       }
 
 #if WRITE_SAMPLE_FRAGMENTS
        //sampleFragments
@@ -4782,7 +4802,14 @@ GF_Err stbl_Size(GF_Box *s)
                if (e) return e;
                ptr->size += ptr->SubSamples->size;
        }
-       
+       if (ptr->sampleGroups) {
+               e = gf_isom_box_array_size(s, ptr->sampleGroups);
+               if (e) return e;
+       }       
+       if (ptr->sampleGroupsDescription) {
+               e = gf_isom_box_array_size(s, ptr->sampleGroupsDescription);
+               if (e) return e;
+       }       
        return GF_OK;
 }
 
@@ -6004,6 +6031,8 @@ void traf_del(GF_Box *s)
        if (ptr->subs) gf_isom_box_del((GF_Box *) ptr->subs);
        if (ptr->tfdt) gf_isom_box_del((GF_Box *) ptr->tfdt);
        gf_isom_box_array_del(ptr->TrackRuns);
+       if (ptr->sampleGroups) gf_isom_box_array_del(ptr->sampleGroups);
+       if (ptr->sampleGroupsDescription) gf_isom_box_array_del(ptr->sampleGroupsDescription);
        gf_free(ptr);
 }
 
@@ -6030,11 +6059,20 @@ GF_Err traf_AddBox(GF_Box *s, GF_Box *a)
                if (ptr->subs) return GF_ISOM_INVALID_FILE;
                ptr->subs = (GF_SubSampleInformationBox *)a;
                return GF_OK;
+       case GF_ISOM_BOX_TYPE_SBGP:
+               if (!ptr->sampleGroups) ptr->sampleGroups = gf_list_new();
+               gf_list_add(ptr->sampleGroups, a);
+               return GF_OK;           
+       case GF_ISOM_BOX_TYPE_SGPD:
+               if (!ptr->sampleGroupsDescription) ptr->sampleGroupsDescription = gf_list_new();
+               gf_list_add(ptr->sampleGroupsDescription, a);
+               return GF_OK;           
        default:
                GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type)));
                gf_isom_box_del(a);
                return GF_OK;           
        }
+       return GF_OK;           
 }
 
 
@@ -6080,12 +6118,22 @@ GF_Err traf_Write(GF_Box *s, GF_BitStream *bs)
        if (ptr->tfdt) {
                e = gf_isom_box_write((GF_Box *) ptr->tfdt, bs);
                if (e) return e;
-       }
-       e = gf_isom_box_array_write(s, ptr->TrackRuns, bs);
-       if (e) return e;
+       }       
        if (ptr->sdtp) {
                e = gf_isom_box_write((GF_Box *) ptr->sdtp, bs);
+               if (e) return e;
+       }
+       if (ptr->sampleGroupsDescription) {
+               e = gf_isom_box_array_write(s, ptr->sampleGroupsDescription, bs);
+               if (e) return e;
+       }
+       if (ptr->sampleGroups) {
+               e = gf_isom_box_array_write(s, ptr->sampleGroups, bs);
+               if (e) return e;
        }
+       e = gf_isom_box_array_write(s, ptr->TrackRuns, bs);
+       if (e) return e;
+
        return e;
 }
 
@@ -6116,6 +6164,16 @@ GF_Err traf_Size(GF_Box *s)
                if (e) return e;
                ptr->size += ptr->tfdt->size;
        }
+
+       if (ptr->sampleGroups) {
+               e = gf_isom_box_array_size(s, ptr->sampleGroups);
+               if (e) return e;
+       }
+       if (ptr->sampleGroupsDescription) {
+               e = gf_isom_box_array_size(s, ptr->sampleGroupsDescription);
+               if (e) return e;
+       }
+
        return gf_isom_box_array_size(s, ptr->TrackRuns);
 }
 
@@ -6150,7 +6208,6 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak)
        GF_GenericSampleEntryBox *genm;
        GF_UnknownBox *a;
        u32 i;
-       u64 read;
 
        i=0;
        while ((a = (GF_UnknownBox*)gf_list_enum(trak->Media->information->sampleTable->SampleDescription->boxList, &i))) {
@@ -6229,7 +6286,6 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak)
                        genm = (GF_GenericSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRM);
                        genm->size = a->size;
                        bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ);
-                       read = 0;
                        gf_bs_read_data(bs, genm->reserved, 6);
                        genm->dataReferenceIndex = gf_bs_read_u16(bs);
                        genm->data_size = (u32) gf_bs_available(bs);
@@ -6752,7 +6808,6 @@ GF_Err trun_Size(GF_Box *s)
 {
        GF_Err e;
        u32 i, count;
-       GF_TrunEntry *p;
        GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s;
 
        e = gf_isom_full_box_get_size(s);
@@ -6766,7 +6821,6 @@ GF_Err trun_Size(GF_Box *s)
        //if nothing to do, this will be skipped automatically
        count = gf_list_count(ptr->entries);
        for (i=0; i<count; i++) {
-               p = (GF_TrunEntry*)gf_list_get(ptr->entries, i);
                if (ptr->flags & GF_ISOM_TRUN_DURATION) ptr->size += 4;
                if (ptr->flags & GF_ISOM_TRUN_SIZE) ptr->size += 4;
                //SHOULDN'T BE USED IF GF_ISOM_TRUN_FIRST_FLAG IS DEFINED
@@ -7737,8 +7791,9 @@ GF_Err sidx_Read(GF_Box *s,GF_BitStream *bs)
                ptr->refs[i].reference_type = gf_bs_read_int(bs, 1);
                ptr->refs[i].reference_size = gf_bs_read_int(bs, 31);
                ptr->refs[i].subsegment_duration = gf_bs_read_u32(bs);
-               ptr->refs[i].contains_RAP = gf_bs_read_int(bs, 1);
-               ptr->refs[i].RAP_delta_time = gf_bs_read_int(bs, 31);
+               ptr->refs[i].starts_with_SAP = gf_bs_read_int(bs, 1);
+               ptr->refs[i].SAP_type = gf_bs_read_int(bs, 3);
+               ptr->refs[i].SAP_delta_time = gf_bs_read_int(bs, 28);
                ptr->size -= 12;
        }
        return GF_OK;
@@ -7782,8 +7837,9 @@ GF_Err sidx_Write(GF_Box *s, GF_BitStream *bs)
                gf_bs_write_int(bs, ptr->refs[i].reference_type, 1);
                gf_bs_write_int(bs, ptr->refs[i].reference_size, 31);
                gf_bs_write_u32(bs, ptr->refs[i].subsegment_duration);
-               gf_bs_write_int(bs, ptr->refs[i].contains_RAP, 1);
-               gf_bs_write_int(bs, ptr->refs[i].RAP_delta_time, 31);
+               gf_bs_write_int(bs, ptr->refs[i].starts_with_SAP, 1);
+               gf_bs_write_int(bs, ptr->refs[i].SAP_type, 3);
+               gf_bs_write_int(bs, ptr->refs[i].SAP_delta_time, 28);
        }
        return GF_OK;
 }
@@ -8031,7 +8087,6 @@ void rvcc_del(GF_Box *s)
        gf_free(s);
 }
 
-/*this is using chpl format according to some NeroRecode samples*/
 GF_Err rvcc_Read(GF_Box *s,GF_BitStream *bs)
 {
        GF_RVCConfigurationBox *ptr = (GF_RVCConfigurationBox*)s;
@@ -8076,6 +8131,274 @@ GF_Err rvcc_Size(GF_Box *s)
 
 
 
+GF_Box *sbgp_New()
+{
+       GF_SampleGroupBox *p;
+       GF_SAFEALLOC(p, GF_SampleGroupBox);
+       p->type = GF_ISOM_BOX_TYPE_SBGP;
+       return (GF_Box *)p;
+}
+void sbgp_del(GF_Box *a)
+{
+       GF_SampleGroupBox *p = (GF_SampleGroupBox *)a;
+       if (p->sample_entries) gf_free(p->sample_entries);
+       gf_free(p);
+}
+
+GF_Err sbgp_Read(GF_Box *s, GF_BitStream *bs)
+{
+       u32 i;
+       GF_SampleGroupBox *p = (GF_SampleGroupBox *)s;
+       GF_Err e = gf_isom_full_box_read(s, bs);
+       if (e) return e;
+
+       p->grouping_type = gf_bs_read_u32(bs);
+       p->size -= 4;
+       if (p->version==1) {
+               p->grouping_type_parameter = gf_bs_read_u32(bs);
+               p->size -= 4;
+       }
+       p->entry_count = gf_bs_read_u32(bs);
+       p->size -= 4;
+       p->sample_entries = gf_malloc(sizeof(GF_SampleGroupEntry)*p->entry_count);
+       if (!p->sample_entries) return GF_IO_ERR;
+       for (i=0; i<p->entry_count; i++) {
+               p->sample_entries[i].sample_count = gf_bs_read_u32(bs);
+               p->sample_entries[i].group_description_index = gf_bs_read_u32(bs);
+               p->size -= 8;
+       }
+       return GF_OK;
+}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+GF_Err sbgp_Write(GF_Box *s, GF_BitStream *bs)
+{
+       u32 i;
+       GF_Err e;
+       GF_SampleGroupBox *p = (GF_SampleGroupBox*)s;
+       
+       e = gf_isom_full_box_write(s, bs);
+       if (e) return e;
+       gf_bs_write_u32(bs, p->grouping_type);
+       if (p->version==1) 
+               gf_bs_write_u32(bs, p->grouping_type_parameter);
+
+       gf_bs_write_u32(bs, p->entry_count);
+       for (i = 0; i<p->entry_count; i++ ) {
+               gf_bs_write_u32(bs, p->sample_entries[i].sample_count);
+               gf_bs_write_u32(bs, p->sample_entries[i].group_description_index);
+       }
+       return GF_OK;
+}
+
+GF_Err sbgp_Size(GF_Box *s)
+{
+       GF_Err e;
+       GF_SampleGroupBox *p = (GF_SampleGroupBox*)s;
+       e = gf_isom_full_box_get_size(s);
+       if (e) return e;
+       p->size += 8;
+       if (p->version==1) p->size += 4;
+       p->size += 8*p->entry_count;
+       return GF_OK;
+}
+
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
+
+static void *sgpd_parse_entry(u32 grouping_type, GF_BitStream *bs, u32 entry_size, u32 *total_bytes)
+{
+       switch (grouping_type) {
+       case GF_4CC( 'r', 'o', 'l', 'l' ):
+       {
+               GF_RollRecoveryEntry *ptr;
+               GF_SAFEALLOC(ptr, GF_RollRecoveryEntry);
+               ptr->roll_distance = gf_bs_read_int(bs, 16);
+               *total_bytes = 2;
+               return ptr;
+       }
+       case GF_4CC( 'r', 'a', 'p', ' ' ):
+       {
+               GF_VisualRandomAccessEntry *ptr;
+               GF_SAFEALLOC(ptr, GF_VisualRandomAccessEntry);
+               ptr->num_leading_samples_known = gf_bs_read_int(bs, 1);
+               ptr->num_leading_samples = gf_bs_read_int(bs, 7);
+               *total_bytes = 1;
+               return ptr;
+       }
+       default:
+       {
+               GF_DefaultSampleGroupDescriptionEntry *ptr;
+               if (!entry_size) return NULL;
+               GF_SAFEALLOC(ptr, GF_DefaultSampleGroupDescriptionEntry);
+               ptr->length = entry_size;
+               ptr->data = (u8 *) gf_malloc(sizeof(u8)*ptr->length);
+               gf_bs_read_data(bs, ptr->data, ptr->length);
+               *total_bytes = entry_size;
+               return ptr;
+       }
+       }
+       return NULL;
+}
+
+static void    sgpd_del_entry(u32 grouping_type, void *entry)
+{
+       switch (grouping_type) {
+       case GF_4CC( 'r', 'o', 'l', 'l' ):
+       case GF_4CC( 'r', 'a', 'p', ' ' ):
+               gf_free(entry);
+               return;
+
+       default:
+       {
+               GF_DefaultSampleGroupDescriptionEntry *ptr = (GF_DefaultSampleGroupDescriptionEntry *)entry;
+               if (ptr->data) gf_free(ptr->data);
+               gf_free(ptr->data);
+       }
+
+       }
+}
+
+static void    sgpd_write_entry(u32 grouping_type, void *entry, GF_BitStream *bs)
+{
+       switch (grouping_type) {
+       case GF_4CC( 'r', 'o', 'l', 'l' ):
+               gf_bs_write_int(bs, ((GF_RollRecoveryEntry*)entry)->roll_distance, 16);
+               return;
+       case GF_4CC( 'r', 'a', 'p', ' ' ):
+               gf_bs_write_int(bs, ((GF_VisualRandomAccessEntry*)entry)->num_leading_samples_known, 1);
+               gf_bs_write_int(bs, ((GF_VisualRandomAccessEntry*)entry)->num_leading_samples, 7);
+               return;
+       default:
+               {
+               GF_DefaultSampleGroupDescriptionEntry *ptr = (GF_DefaultSampleGroupDescriptionEntry *)entry;
+               gf_bs_write_data(bs, ptr->data, ptr->length);
+               }
+       }
+}
+static u32 sgpd_size_entry(u32 grouping_type, void *entry)
+{
+       switch (grouping_type) {
+       case GF_4CC( 'r', 'o', 'l', 'l' ):
+               return 2;
+       case GF_4CC( 'r', 'a', 'p', ' ' ):
+               return 1;
+       default:
+               return ((GF_DefaultSampleGroupDescriptionEntry *)entry)->length;
+       }
+}
+
+
+GF_Box *sgpd_New()
+{
+       GF_SampleGroupDescriptionBox *p;
+       GF_SAFEALLOC(p, GF_SampleGroupDescriptionBox);
+       p->type = GF_ISOM_BOX_TYPE_SGPD;
+       /*version 0 is deprecated, use v1 by default*/
+       p->version = 1;
+       p->group_descriptions = gf_list_new();
+
+       return (GF_Box *)p;
+}
+
+void sgpd_del(GF_Box *a)
+{
+       GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)a;
+       while (gf_list_count(p->group_descriptions)) {
+               void *ptr = gf_list_last(p->group_descriptions);
+               sgpd_del_entry(p->grouping_type, ptr);
+               gf_list_rem_last(p->group_descriptions);
+       }
+       gf_list_del(p->group_descriptions);
+       gf_free(p);
+}
+
+GF_Err sgpd_Read(GF_Box *s, GF_BitStream *bs)
+{
+       u32 entry_count;
+       GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)s;
+       GF_Err e = gf_isom_full_box_read(s, bs);
+       if (e) return e;
+
+       p->grouping_type = gf_bs_read_u32(bs);
+       p->size -= 4;
+       
+       if (p->version==1) {
+               p->default_length = gf_bs_read_u32(bs);
+               p->size -= 4;
+       }
+       entry_count = gf_bs_read_u32(bs);
+       p->size -= 4;
+
+       while (entry_count) {
+               void *ptr;
+               u32 parsed_bytes;
+               u32 size = p->default_length;
+               if ((p->version==1) && !size) {
+                       size = gf_bs_read_u32(bs);
+                       p->size -= 4;
+               }
+               ptr = sgpd_parse_entry(p->grouping_type, bs, size, &parsed_bytes);
+               if (!ptr) return GF_ISOM_INVALID_FILE;
+               if (p->size < parsed_bytes) return GF_ISOM_INVALID_FILE;
+               p->size -= parsed_bytes;
+               gf_list_add(p->group_descriptions, ptr);
+               entry_count--;
+       }
+       return GF_OK;
+}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+GF_Err sgpd_Write(GF_Box *s, GF_BitStream *bs)
+{
+       u32 i;
+       GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)s;
+       GF_Err e;
+       e = gf_isom_full_box_write(s, bs);
+       if (e) return e;
+
+       gf_bs_write_u32(bs, p->grouping_type);
+       if (p->version==1) gf_bs_write_u32(bs, p->default_length);
+       gf_bs_write_u32(bs, gf_list_count(p->group_descriptions) );
+
+       for (i=0; i<gf_list_count(p->group_descriptions); i++) {
+               void *ptr = gf_list_get(p->group_descriptions, i);
+               if ((p->version == 1) && !p->default_length) {
+                       u32 size = sgpd_size_entry(p->grouping_type, ptr);
+                       gf_bs_write_u32(bs, size);
+               }
+               sgpd_write_entry(p->grouping_type, ptr, bs);
+       }
+       return GF_OK;
+}
+
+GF_Err sgpd_Size(GF_Box *s)
+{
+       u32 i;
+       GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)s;
+       GF_Err e;
+       e = gf_isom_full_box_get_size(s);
+       if (e) return e;
+       p->size += 8;
+       if (p->version==1) p->size += 4;
+       p->default_length = 0;
+
+       for (i=0; i<gf_list_count(p->group_descriptions); i++) {
+               void *ptr = gf_list_get(p->group_descriptions, i);
+               u32 size = sgpd_size_entry(p->grouping_type, ptr);
+               p->size += size;
+               if (!p->default_length) {
+                       p->default_length = size;
+               } else if (p->default_length != size) {
+                       p->default_length = 0;
+               }
+       }
+       if (p->version==1) {
+               if (!p->default_length) p->size += gf_list_count(p->group_descriptions)*4;
+       }
+       return GF_OK;
+}
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
+
 
 
 #endif /*GPAC_DISABLE_ISOM*/
index 3b0ca624b70a8af18518f8c30865b96df52bb3d4..b059065c3678a31c28be4a57f0a2007db3a733f2 100644 (file)
@@ -206,6 +206,7 @@ GF_Err schm_Write(GF_Box *s, GF_BitStream *bs)
        GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *) s;
        if (!s) return GF_BAD_PARAM;
        e = gf_isom_full_box_write(s, bs);
+       assert(e == GF_OK);
        gf_bs_write_u32(bs, ptr->scheme_type);
        gf_bs_write_u32(bs, ptr->scheme_version);
        if (ptr->flags & 0x000001) gf_bs_write_data(bs, ptr->URI, strlen(ptr->URI)+1);
index 6e4cf18e3e0c5f88318a7088b8e8f3c490ac718c..4af3783634a3a170f09cda7f1c582f4d14ceb9d5 100644 (file)
@@ -179,6 +179,11 @@ GF_Err gf_box_dump(void *ptr, FILE * trace)
                return chpl_dump(a, trace);
        case GF_ISOM_BOX_TYPE_PDIN:
                return dpin_dump(a, trace);
+       case GF_ISOM_BOX_TYPE_SBGP: 
+               return sbgp_dump(a, trace);
+       case GF_ISOM_BOX_TYPE_SGPD: 
+               return sgpd_dump(a, trace);
+
 
        case GF_ISOM_BOX_TYPE_RTP_STSD:
                return ghnt_dump(a, trace);
@@ -674,6 +679,8 @@ GF_Err stbl_dump(GF_Box *a, FILE * trace)
        if (p->PaddingBits) gf_box_dump(p->PaddingBits, trace);
        if (p->SubSamples) gf_box_dump(p->SubSamples, trace);
        if (p->Fragments) gf_box_dump(p->Fragments, trace);
+       if (p->sampleGroupsDescription) gf_box_array_dump(p->sampleGroupsDescription, trace);
+       if (p->sampleGroups) gf_box_array_dump(p->sampleGroups, trace);
 
        fprintf(trace, "</SampleTableBox>\n");
        return GF_OK;
@@ -1789,7 +1796,7 @@ GF_Err xml_dump(GF_Box *a, FILE * trace)
        DumpBox(a, trace);
        gf_full_box_dump(a, trace);
        fprintf(trace, "<![CDATA[\n");
-       fwrite(p->xml, p->xml_length, 1, trace);
+       gf_fwrite(p->xml, p->xml_length, 1, trace);
        fprintf(trace, "]]>\n");
        fprintf(trace, "</XMLBox>\n");
        return GF_OK;
@@ -2248,6 +2255,8 @@ GF_Err traf_dump(GF_Box *a, FILE * trace)
        if (p->subs) gf_box_dump(p->subs, trace);
        if (p->sdtp) gf_box_dump(p->sdtp, trace);
        if (p->tfdt) gf_box_dump(p->tfdt, trace);
+       if (p->sampleGroupsDescription) gf_box_array_dump(p->sampleGroupsDescription, trace);
+       if (p->sampleGroups) gf_box_array_dump(p->sampleGroups, trace);
        gf_box_array_dump(p->TrackRuns, trace);
        fprintf(trace, "</TrackFragmentBox>\n");
        return GF_OK;
@@ -2264,7 +2273,7 @@ GF_Err tfhd_dump(GF_Box *a, FILE * trace)
                fprintf(trace, " BaseDataOffset=\""LLD"\"", LLD_CAST p->base_data_offset);
        }
        if (p->flags & GF_ISOM_TRAF_SAMPLE_DESC)
-               fprintf(trace, "SampleDescriptionIndex=\"%d\"", p->sample_desc_index);
+               fprintf(trace, " SampleDescriptionIndex=\"%d\"", p->sample_desc_index);
        if (p->flags & GF_ISOM_TRAF_SAMPLE_DUR)
                fprintf(trace, " SampleDuration=\"%d\"", p->def_sample_duration);
        if (p->flags & GF_ISOM_TRAF_SAMPLE_SIZE)
@@ -3265,9 +3274,6 @@ GF_Err ilst_dump(GF_Box *a, FILE * trace)
 
 GF_Err ListEntry_dump(GF_Box *a, FILE * trace)
 {
-       GF_ItemListBox *p;
-
-       p = (GF_ItemListBox *)a;
        fprintf(trace, "<ListEntry>\n");
        DumpBox(a, trace);
        gf_box_dump(a, trace);
@@ -3277,9 +3283,6 @@ GF_Err ListEntry_dump(GF_Box *a, FILE * trace)
 
 GF_Err data_dump(GF_Box *a, FILE * trace)
 {
-       GF_ItemListBox *p;
-
-       p = (GF_ItemListBox *)a;
        fprintf(trace, "<data>\n");
        DumpBox(a, trace);
        gf_full_box_dump(a, trace);
@@ -3506,7 +3509,7 @@ GF_Err sidx_dump(GF_Box *a, FILE * trace)
        gf_full_box_dump(a, trace);
        
        for (i=0; i<p->nb_refs; i++) {
-               fprintf(trace, "<Reference type=\"%d\" size=\"%d\" duration=\"%d\" hasRAP=\"%d\" RAPDeltaTime=\"%d\"/>\n", p->refs[i].reference_type, p->refs[i].reference_size, p->refs[i].subsegment_duration, p->refs[i].contains_RAP, p->refs[i].RAP_delta_time);
+               fprintf(trace, "<Reference type=\"%d\" size=\"%d\" duration=\"%d\" startsWithSAP=\"%d\" SAP_type=\"%d\" SAPDeltaTime=\"%d\"/>\n", p->refs[i].reference_type, p->refs[i].reference_size, p->refs[i].subsegment_duration, p->refs[i].starts_with_SAP, p->refs[i].SAP_type, p->refs[i].SAP_delta_time);
        }
        fprintf(trace, "</SegmentIndexBox>\n");
        return GF_OK;
@@ -3570,4 +3573,54 @@ GF_Err rvcc_dump(GF_Box *a, FILE * trace)
        return GF_OK;
 }
 
+GF_Err sbgp_dump(GF_Box *a, FILE * trace)
+{
+       u32 i;
+       GF_SampleGroupBox *ptr = (GF_SampleGroupBox*) a;
+       if (!a) return GF_BAD_PARAM;
+
+       fprintf(trace, "<SampleGroupBox grouping_type=\"%s\"", gf_4cc_to_str(ptr->grouping_type) );
+       if (ptr->version==1) fprintf(trace, " grouping_type_parameter=\"%d\"", ptr->grouping_type_parameter);
+       fprintf(trace, ">\n");
+       DumpBox(a, trace);
+       gf_full_box_dump((GF_Box *)a, trace);
+       for (i=0; i<ptr->entry_count; i++) {
+               fprintf(trace, "<SampleGroupBoxEntry sample_count=\"%d\" group_description_index=\"%d\"/>\n", ptr->sample_entries[i].sample_count, ptr->sample_entries[i].group_description_index );
+       }
+       fprintf(trace, "</SampleGroupBox>\n");
+       return GF_OK;
+}
+
+GF_Err sgpd_dump(GF_Box *a, FILE * trace)
+{
+       u32 i;
+       GF_SampleGroupDescriptionBox *ptr = (GF_SampleGroupDescriptionBox*) a;
+       if (!a) return GF_BAD_PARAM;
+
+       fprintf(trace, "<SampleGroupDescriptionBox grouping_type=\"%s\"", gf_4cc_to_str(ptr->grouping_type) );
+       if (ptr->version==1) fprintf(trace, " default_length=\"%d\"", ptr->default_length);
+       fprintf(trace, ">\n");
+       DumpBox(a, trace);
+       gf_full_box_dump((GF_Box *)a, trace);
+       for (i=0; i<gf_list_count(ptr->group_descriptions); i++) {
+               void *entry = gf_list_get(ptr->group_descriptions, i);
+               switch (ptr->grouping_type) {
+               case GF_4CC( 'r', 'o', 'l', 'l' ):
+                       fprintf(trace, "<RollRecoveryEntry roll_distance=\"%d\" />\n", ((GF_RollRecoveryEntry*)entry)->roll_distance );
+                       break;
+               case GF_4CC( 'r', 'a', 'p', ' ' ):
+                       fprintf(trace, "<VisualRandomAccessEntry num_leading_samples_known=\"%s\"", ((GF_VisualRandomAccessEntry*)entry)->num_leading_samples_known ? "yes" : "no");
+                       if (((GF_VisualRandomAccessEntry*)entry)->num_leading_samples_known) fprintf(trace, " num_leading_samples=\"%d\" />", ((GF_VisualRandomAccessEntry*)entry)->num_leading_samples);
+                       fprintf(trace, "/>\n");
+                       break;
+               default:
+                       fprintf(trace, "<DefaultSampleGroupDescriptionEntry size=\"%d\" data=\"", ((GF_DefaultSampleGroupDescriptionEntry*)entry)->length);
+                       DumpData(trace, ((GF_DefaultSampleGroupDescriptionEntry*)entry)->data,  ((GF_DefaultSampleGroupDescriptionEntry*)entry)->length);
+                       fprintf(trace, "\"/>\n");
+               }
+       }
+       fprintf(trace, "</SampleGroupDescriptionBox>\n");
+       return GF_OK;
+}
+
 #endif /*GPAC_DISABLE_ISOM_DUMP*/
index 1ffd065c16484e28db3f26bedd0b436230ca5b64..d17a27c0b77032610868b0a2294ca4678515cd59 100644 (file)
@@ -29,7 +29,7 @@
 //Add this funct to handle incomplete files...
 //bytesExpected is 0 most of the time. If the file is incomplete, bytesExpected
 //is the number of bytes missing to parse the box...
-GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpected)
+GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpected, Bool progressive_mode)
 {
        GF_Err ret;
        u64 start;
@@ -43,6 +43,7 @@ GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpec
        ret = gf_isom_parse_box(outBox, bs);
        if (ret == GF_ISOM_INCOMPLETE_FILE) {
                *bytesExpected = (*outBox)->size;
+               GF_LOG(progressive_mode ? GF_LOG_DEBUG : GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Incomplete box %s\n", gf_4cc_to_str( (*outBox)->type) ));
                gf_bs_seek(bs, start);
                gf_isom_box_del(*outBox);
                *outBox = NULL;
@@ -131,7 +132,6 @@ proceed_box:
        if (size - hdr_size > end ) {
                newBox->size = size - hdr_size - end;
                *outBox = newBox;
-               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Incomplete box %s\n", gf_4cc_to_str(newBox->type) ));
                return GF_ISOM_INCOMPLETE_FILE;
        }
        //we need a special reading for these boxes...
@@ -398,6 +398,8 @@ GF_Box *gf_isom_box_new(u32 boxType)
        case GF_ISOM_BOX_TYPE_VOID: return void_New();
        case GF_ISOM_BOX_TYPE_STSF: return stsf_New();
        case GF_ISOM_BOX_TYPE_PDIN: return pdin_New();
+       case GF_ISOM_BOX_TYPE_SBGP: return sbgp_New();
+       case GF_ISOM_BOX_TYPE_SGPD: return sgpd_New();
 
 #ifndef GPAC_DISABLE_ISOM_HINTING
        case GF_ISOM_BOX_TYPE_RTP_STSD:
@@ -649,6 +651,9 @@ void gf_isom_box_del(GF_Box *a)
        case GF_ISOM_BOX_TYPE_VOID: void_del(a); return;
        case GF_ISOM_BOX_TYPE_STSF: stsf_del(a); return;
        case GF_ISOM_BOX_TYPE_PDIN: pdin_del(a); return;
+       case GF_ISOM_BOX_TYPE_SBGP: sbgp_del(a); return;
+       case GF_ISOM_BOX_TYPE_SGPD: sgpd_del(a); return;
+
 
 #ifndef GPAC_DISABLE_ISOM_HINTING
        case GF_ISOM_BOX_TYPE_RTP_STSD: ghnt_del(a); return;
@@ -888,7 +893,9 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs)
        case GF_ISOM_BOX_TYPE_VOID: return void_Read(a, bs);
        case GF_ISOM_BOX_TYPE_STSF: return stsf_Read(a, bs);
        case GF_ISOM_BOX_TYPE_PDIN: return pdin_Read(a, bs);
-       
+       case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Read(a, bs);
+       case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Read(a, bs);
+
 #ifndef GPAC_DISABLE_ISOM_HINTING
        case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Read(a, bs);
        case GF_ISOM_BOX_TYPE_RTPO: return rtpo_Read(a, bs);
@@ -1120,6 +1127,8 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs)
        case GF_ISOM_BOX_TYPE_VOID: return void_Write(a, bs);
        case GF_ISOM_BOX_TYPE_STSF: return stsf_Write(a, bs);
        case GF_ISOM_BOX_TYPE_PDIN: return pdin_Write(a, bs);
+       case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Write(a, bs);
+       case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Write(a, bs);
 
 #ifndef GPAC_DISABLE_ISOM_HINTING
        case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Write(a, bs);
@@ -1350,7 +1359,9 @@ GF_Err gf_isom_box_size(GF_Box *a)
        case GF_ISOM_BOX_TYPE_VOID: return void_Size(a);
        case GF_ISOM_BOX_TYPE_STSF: return stsf_Size(a);
        case GF_ISOM_BOX_TYPE_PDIN: return pdin_Size(a);
-       
+       case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Size(a);
+       case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Size(a);
+
 #ifndef GPAC_DISABLE_ISOM_HINTING
        case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Size(a);
        case GF_ISOM_BOX_TYPE_RTPO: return rtpo_Size(a);
index ed99b23be84475920f6ab6c278451a318a18dfd4..e24ee8142d5608317843fd98f226d081b31c9204 100644 (file)
@@ -30,7 +30,7 @@
 /**************************************************************
                Some Local functions for movie creation
 **************************************************************/
-GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpected);
+GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpected, Bool progressive_mode);
 
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
 GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset, Bool is_first_merge);
@@ -82,7 +82,7 @@ GF_Err MergeFragment(GF_MovieFragmentBox *moof, GF_ISOFile *mov)
 #endif
 
 
-GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing)
+GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progressive_mode)
 {
        GF_Box *a;
        u64 totSize;
@@ -105,7 +105,7 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing)
                mov->current_top_box_start = gf_bs_get_position(mov->movieFileMap->bs);
 #endif
 
-               e = gf_isom_parse_root_box(&a, mov->movieFileMap->bs, bytesMissing);
+               e = gf_isom_parse_root_box(&a, mov->movieFileMap->bs, bytesMissing, progressive_mode);
 
                if (e >= 0) {
                        e = GF_OK;
@@ -194,8 +194,19 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing)
 
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
                case GF_ISOM_BOX_TYPE_STYP:
-                       if (((GF_SegmentTypeBox *)a)->majorBrand == GF_4CC('i', 's', 's', 's') ||
-                               ((GF_SegmentTypeBox *)a)->majorBrand == GF_4CC('i', 'm', 's', 's')) mov->is_index_segment = 1;
+               {
+                       u32 brand = ((GF_SegmentTypeBox *)a)->majorBrand;
+                       switch (brand) {
+                       case GF_4CC('s', 'i', 's', 'x'):
+                       case GF_4CC('r', 'i', 's', 'x'):
+                       case GF_4CC('s', 's', 's', 's'):
+                               mov->is_index_segment = 1;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               /*fall-through*/
 
                case GF_ISOM_BOX_TYPE_SIDX:
                        totSize += a->size;
@@ -380,7 +391,7 @@ GF_ISOFile *gf_isom_open_file(const char *fileName, u32 OpenMode, const char *tm
        }
 
        //OK, let's parse the movie...
-       mov->LastError = gf_isom_parse_movie_boxes(mov, &bytes);
+       mov->LastError = gf_isom_parse_movie_boxes(mov, &bytes, 0);
        if (mov->LastError) {
                gf_isom_set_last_error(NULL, mov->LastError);
                gf_isom_delete_movie(mov);
@@ -451,7 +462,7 @@ GF_TrackBox *gf_isom_get_track_from_file(GF_ISOFile *movie, u32 trackNumber)
 
 
 //WARNING: MOVIETIME IS EXPRESSED IN MEDIA TS
-GF_Err GetMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit)
+GF_Err GetMediaTime(GF_TrackBox *trak, Bool force_non_empty, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit)
 {
 #if 0
        GF_Err e;
@@ -459,7 +470,7 @@ GF_Err GetMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *MediaTime, s64 *Segme
        u64 firstDTS;
 #endif
        u32 i;
-       u64 time, lastSampleTime, m_time;
+       u64 time, lastSampleTime;
        s64 mtime;
        GF_EdtsEntry *ent;
        Double scale_ts;
@@ -485,22 +496,21 @@ GF_Err GetMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *MediaTime, s64 *Segme
        if (! trak->editBox || !trak->editBox->editList) {
                *MediaTime = movieTime;
                //check this is in our media time line
-               if (*MediaTime > lastSampleTime) *MediaTime = lastSampleTime;
+               if (!trak->moov->mov->use_segments && (*MediaTime > lastSampleTime)) *MediaTime = lastSampleTime;
                *useEdit = 0;
                return GF_OK;
        }
        //browse the edit list and get the time
-       scale_ts = trak->moov->mvhd->timeScale;
-       scale_ts /= trak->Media->mediaHeader->timeScale;
-       scale_ts *= ((s64)movieTime );
-       m_time = (u64) (scale_ts);
+       scale_ts = trak->Media->mediaHeader->timeScale;
+       scale_ts /= trak->moov->mvhd->timeScale;
 
        time = 0;
        ent = NULL;
        i=0;
        while ((ent = (GF_EdtsEntry *)gf_list_enum(trak->editBox->editList->entryList, &i))) {
-               if (time + ent->segmentDuration > m_time) {
-                       goto ent_found;
+               if ( (time + ent->segmentDuration) * scale_ts > movieTime) {
+                       if (!force_non_empty || (ent->mediaTime >= 0)) 
+                               goto ent_found;
                }
                time += ent->segmentDuration;
        }
index 0eaac6807cd00b3f3200d863f00816ca1baa5b6f..261304cdbe3370e816ad9146cdad1f55ba46dc4c 100644 (file)
@@ -125,7 +125,7 @@ Bool gf_isom_probe_file(const char *fileName)
                        the file map is regular (through FILE handles)
 **************************************************************/
 GF_EXPORT
-GF_Err gf_isom_open_progressive(const char *fileName, GF_ISOFile **the_file, u64 *BytesMissing)
+GF_Err gf_isom_open_progressive(const char *fileName, u64 start_range, u64 end_range, GF_ISOFile **the_file, u64 *BytesMissing)
 {
        GF_Err e;
        GF_ISOFile *movie;
@@ -150,7 +150,12 @@ GF_Err gf_isom_open_progressive(const char *fileName, GF_ISOFile **the_file, u64
        movie->finalName = NULL;
 #endif /*GPAC_DISABLE_ISOM_WRITE*/
 
-       e = gf_isom_parse_movie_boxes(movie, BytesMissing);
+       if (end_range>start_range) {
+               gf_bs_seek(movie->movieFileMap->bs, end_range+1);
+               gf_bs_truncate(movie->movieFileMap->bs);
+               gf_bs_seek(movie->movieFileMap->bs, start_range);
+       }
+       e = gf_isom_parse_movie_boxes(movie, BytesMissing, 1);
        if (e == GF_ISOM_INCOMPLETE_FILE) {
                //if we have a moov, we're fine
                if (movie->moov) {
@@ -641,7 +646,7 @@ GF_Err gf_isom_get_media_time(GF_ISOFile *the_file, u32 trackNumber, u32 movieTi
        if (!trak || !MediaTime) return GF_BAD_PARAM;;
 
        SegmentStartTime = 0;
-       return GetMediaTime(trak, movieTime, MediaTime, &SegmentStartTime, &mediaOffset, &useEdit);
+       return GetMediaTime(trak, 0, movieTime, MediaTime, &SegmentStartTime, &mediaOffset, &useEdit);
 }
 
 
@@ -1233,8 +1238,11 @@ GF_Err gf_isom_get_sample_for_media_time(GF_ISOFile *the_file, u32 trackNumber,
        stbl = trak->Media->information->sampleTable;
 
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
-       if (desiredTime < trak->dts_at_seg_start) return GF_BAD_PARAM;
-       desiredTime -= trak->dts_at_seg_start;
+       if (desiredTime < trak->dts_at_seg_start) {
+               desiredTime = 0;
+       } else {
+               desiredTime -= trak->dts_at_seg_start;
+       }
 #endif
 
        e = findEntryForTime(stbl, desiredTime, 0, &sampleNumber, &prevSampleNumber);
@@ -1366,6 +1374,7 @@ GF_Err gf_isom_get_sample_for_media_time(GF_ISOFile *the_file, u32 trackNumber,
 GF_EXPORT
 GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber, u64 movieTime, u32 *StreamDescriptionIndex, u8 SearchMode, GF_ISOSample **sample, u32 *sampleNumber)
 {
+       Double tsscale;
        GF_Err e;
        GF_TrackBox *trak;
        u64 mediaTime;
@@ -1386,7 +1395,7 @@ GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber,
                        return GF_EOS;
                }
        }
-       else if (movieTime * trak->moov->mvhd->timeScale > trak->Header->duration * trak->Media->mediaHeader->timeScale) {
+       else if (!trak->dts_at_seg_start && (movieTime * trak->moov->mvhd->timeScale > trak->Header->duration * trak->Media->mediaHeader->timeScale)) {
                *sample = NULL;
                if (sampleNumber) *sampleNumber = 0;
                *StreamDescriptionIndex = 0;
@@ -1397,7 +1406,7 @@ GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber,
        mediaTime = segStartTime = 0;
        *StreamDescriptionIndex = 0;
 
-       e = GetMediaTime(trak, movieTime, &mediaTime, &segStartTime, &mediaOffset, &useEdit);
+       e = GetMediaTime(trak, (SearchMode==GF_ISOM_SEARCH_SYNC_FORWARD) ? 1 : 0, movieTime, &mediaTime, &segStartTime, &mediaOffset, &useEdit);
        if (e) return e;
 
        /*here we check if we were playing or not and return no sample in normal search modes*/
@@ -1430,6 +1439,9 @@ GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber,
                }
        }
 
+       tsscale = trak->Media->mediaHeader->timeScale;
+       tsscale /= trak->moov->mvhd->timeScale;
+
        //OK, we have a sample so fetch it
        e = gf_isom_get_sample_for_media_time(the_file, trackNumber, mediaTime, StreamDescriptionIndex, SearchMode, sample, &sampNum);
        if (e) return e;
@@ -1438,9 +1450,8 @@ GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber,
        //to the media time scale (used by SLConfig) - add the edit start time but stay in
        //the track TS
        if (useEdit) {
-               u64 _ts = segStartTime;
-               _ts *= trak->Media->mediaHeader->timeScale;
-               _ts /= trak->moov->mvhd->timeScale;
+               u64 _ts = (u64)(segStartTime * tsscale);
+
                (*sample)->DTS += _ts;
                /*watchout, the sample fetched may be before the first sample in the edit list (when seeking)*/
                if ( (*sample)->DTS > (u64) mediaOffset) {
@@ -1450,6 +1461,10 @@ GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber,
                }
        }
        if (sampleNumber) *sampleNumber = sampNum;
+#ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
+       if ( (*sample) ) (*sample)->DTS += trak->dts_at_seg_start;
+#endif
+
        return GF_OK;
 }
 
@@ -1704,31 +1719,64 @@ void gf_isom_delete(GF_ISOFile *movie)
 }
 
 GF_EXPORT
-u32 gf_isom_get_max_chunk_duration(GF_ISOFile *movie, u32 trackNumber)
+GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min, u32 *dur_avg, u32 *dur_max, u32 *size_min, u32 *size_avg, u32 *size_max)
 {
        GF_TrackBox *trak;
-       u32 i, sample_per_chunk, sample_dur;
+       u32 i, k, sample_idx, dmin, dmax, smin, smax, tot_chunks;
+       u64 davg, savg;
        GF_SampleToChunkBox *stsc;
        GF_TimeToSampleBox *stts;
-       if (!movie || !trackNumber || !movie->moov) return 0;
+       if (!movie || !trackNumber || !movie->moov) return GF_BAD_PARAM;
        trak = gf_isom_get_track_from_file(movie, trackNumber);
-       if (!trak) return 0;
+       if (!trak) return GF_BAD_PARAM;
 
        stsc = trak->Media->information->sampleTable->SampleToChunk;
        stts = trak->Media->information->sampleTable->TimeToSample;
 
-       sample_per_chunk = 0;
+       dmin = smin = (u32) -1;
+       dmax = smax = 0;
+       davg = savg = 0;
+       sample_idx = 1;
+       tot_chunks = 0;
        for (i=0; i<stsc->nb_entries; i++) {
-               if (stsc->entries[i].samplesPerChunk > sample_per_chunk) sample_per_chunk = stsc->entries[i].samplesPerChunk;
-       }
-       sample_dur = 0;
-       for (i=0; i<stts->nb_entries; i++) {
-               if (stts->entries[i].sampleDelta > sample_dur) sample_dur = stts->entries[i].sampleDelta;
+               u32 nb_chunk = 0;
+               while (1) {
+                       u32 chunk_dur = 0;
+                       u32 chunk_size = 0;
+                       for (k=0; k<stsc->entries[i].samplesPerChunk; k++) {
+                               u64 dts;
+                               u32 dur;
+                               u32 size;
+                               stbl_GetSampleDTS_and_Duration(stts, k+sample_idx, &dts, &dur);
+                               chunk_dur += dur;
+                               stbl_GetSampleSize(trak->Media->information->sampleTable->SampleSize, k+sample_idx, &size);
+                               chunk_size += size;
+                               
+                       }
+                       if (dmin>chunk_dur) dmin = chunk_dur;
+                       if (dmax<chunk_dur) dmax = chunk_dur;
+                       davg += chunk_dur;
+                       if (smin>chunk_size) smin = chunk_size;
+                       if (smax<chunk_size) smax = chunk_size;
+                       savg += chunk_dur;
+                       
+                       tot_chunks ++;
+                       sample_idx += stsc->entries[i].samplesPerChunk;
+                       if (i+1==stsc->nb_entries) break;
+                       nb_chunk ++;
+                       if (stsc->entries[i].firstChunk + nb_chunk == stsc->entries[i+1].firstChunk) break;
+               }
        }
+       if (tot_chunks) davg /= tot_chunks;
+
+       if (dur_min) *dur_min = dmin;
+       if (dur_avg) *dur_avg = (u32) davg;
+       if (dur_max) *dur_max = dmax;
 
-       //rescale to ms
-       i = 1000 * sample_dur * sample_per_chunk / trak->Media->mediaHeader->timeScale;
-       return i;
+       if (size_min) *size_min = smin;
+       if (size_avg) *size_avg = (u32) savg;
+       if (size_max) *size_max = smax;
+       return GF_OK;
 }
 
 GF_EXPORT
@@ -1882,7 +1930,7 @@ GF_Err gf_isom_refresh_fragmented(GF_ISOFile *movie, u64 *MissingBytes)
        if (prevsize==size) return GF_OK;
 
        //ok parse root boxes
-       return gf_isom_parse_movie_boxes(movie, MissingBytes);
+       return gf_isom_parse_movie_boxes(movie, MissingBytes, 1);
 #endif
 }
 
@@ -1934,7 +1982,7 @@ GF_Err gf_isom_release_segment(GF_ISOFile *movie, Bool reset_tables)
        return GF_OK;
 }
 
-GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName)
+GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName, u64 start_range, u64 end_range)
 {
 #ifdef GPAC_DISABLE_ISOM_FRAGMENTS
        return GF_NOT_SUPPORTED;
@@ -1951,6 +1999,15 @@ GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName)
        e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_READ_ONLY, &movie->movieFileMap);
        if (e) return e;
 
+       movie->current_top_box_start = 0;
+
+       if (end_range > start_range) {
+               gf_bs_seek(movie->movieFileMap->bs, end_range+1);
+               gf_bs_truncate(movie->movieFileMap->bs);
+               gf_bs_seek(movie->movieFileMap->bs, start_range);       
+               movie->current_top_box_start = start_range;
+       }
+       
        for (i=0; i<gf_list_count(movie->moov->trackList); i++) {
                GF_TrackBox *trak = gf_list_get(movie->moov->trackList, i);
                if (trak->Media->information->dataHandler == NULL) {
@@ -1958,9 +2015,8 @@ GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName)
                }
        }
 
-       movie->current_top_box_start = 0;
        //ok parse root boxes
-       return gf_isom_parse_movie_boxes(movie, &MissingBytes);
+       return gf_isom_parse_movie_boxes(movie, &MissingBytes, 1);
 #endif
 }
 
@@ -2618,5 +2674,89 @@ GF_Err gf_isom_get_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio
        return GF_OK;
 }
 
+GF_EXPORT
+Bool gf_isom_moov_first(GF_ISOFile *movie)
+{
+       u32 i;
+       for (i=0; i<gf_list_count(movie->TopBoxes); i++) {
+               GF_Box *b = gf_list_get(movie->TopBoxes, i);
+               if (b->type == GF_ISOM_BOX_TYPE_MOOV) return 1;
+               if (b->type == GF_ISOM_BOX_TYPE_MDAT) return 0;
+       }
+       return 0;
+}
+
+void gf_isom_reset_fragment_info(GF_ISOFile *movie)
+{
+       u32 i;
+       if (!movie) return;
+       for (i=0; i<gf_list_count(movie->moov->trackList); i++) {
+               GF_TrackBox *trak = gf_list_get(movie->moov->trackList, i);
+               trak->dts_at_seg_start = 0;
+               trak->sample_count_at_seg_start = 0;
+               trak->Media->information->sampleTable->SampleSize->sampleCount = 0;
+       }
+       movie->NextMoofNumber = 0;
+}
+
+GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, Bool *is_rap, Bool *has_roll, s32 *roll_distance)
+{
+       GF_TrackBox *trak;
+       u32 i, count;
+
+       if (is_rap) *is_rap = 0;
+       if (has_roll) *has_roll = 0;
+       if (roll_distance) *roll_distance = 0;
+
+       trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak) return GF_BAD_PARAM;
+       if (!trak->Media->information->sampleTable->sampleGroups) return GF_OK;
+
+       count = gf_list_count(trak->Media->information->sampleTable->sampleGroups);
+       for (i=0; i<count; i++) {
+               GF_SampleGroupBox *sg;
+               u32 j, group_desc_index;
+               GF_SampleGroupDescriptionBox *sgdesc;
+               u32 first_sample_in_entry, last_sample_in_entry;
+               first_sample_in_entry = 1;
+               group_desc_index = 0;
+               sg = gf_list_get(trak->Media->information->sampleTable->sampleGroups, i);
+               for (j=0; j<sg->entry_count; j++) {
+                       last_sample_in_entry = first_sample_in_entry + sg->sample_entries[j].sample_count - 1;
+                       if ((sample_number<first_sample_in_entry) || (sample_number>last_sample_in_entry)) {
+                               first_sample_in_entry = last_sample_in_entry+1;
+                               continue;
+                       }
+                       /*we found our sample*/
+                       group_desc_index = sg->sample_entries[j].group_description_index;
+                       break;
+               }
+               /*no sampleGroup info associated*/
+               if (!group_desc_index) continue;
+
+               sgdesc = NULL;
+               for (j=0; j<gf_list_count(trak->Media->information->sampleTable->sampleGroupsDescription); j++) {
+                       sgdesc = gf_list_get(trak->Media->information->sampleTable->sampleGroupsDescription, j);
+                       if (sgdesc->grouping_type==sg->grouping_type) break;
+                       sgdesc = NULL;
+               }
+               /*no sampleGroup description found for this group (invalid file)*/
+               if (!sgdesc) continue;
+
+               switch (sgdesc->grouping_type) {
+               case GF_4CC('r','a','p',' '):
+                       if (is_rap) *is_rap = 1;
+                       break;
+               case GF_4CC('r','o','l','l'):
+                       if (has_roll) *has_roll = 1;
+                       if (roll_distance) {
+                               GF_RollRecoveryEntry *roll_entry = (GF_RollRecoveryEntry *) gf_list_get(sgdesc->group_descriptions, group_desc_index - 1);
+                               if (roll_entry) *roll_distance = roll_entry->roll_distance;
+                       }
+                       break;
+               }
+       }
+       return GF_OK;
+}
 
 #endif /*GPAC_DISABLE_ISOM*/
index 048ffcb3e5f90450ed22ad4f82d93f9af8d298f5..b898dc93ec103d6817063843168806ee67aca8cb 100644 (file)
@@ -545,7 +545,6 @@ GF_Err gf_isom_new_mpeg4_description(GF_ISOFile *movie,
        GF_Err e;
        u32 dataRefIndex;
        GF_ESD *new_esd;
-       GF_TrackReferenceBox *tref;
 
        e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
        if (e) return e;
@@ -555,8 +554,6 @@ GF_Err gf_isom_new_mpeg4_description(GF_ISOFile *movie,
                !esd || !esd->decoderConfig || 
                !esd->slConfig) return GF_BAD_PARAM;
 
-       tref = NULL;
-
        //get or create the data ref
        e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
        if (e) return e;
@@ -2416,7 +2413,10 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de
 
        stbl = trak->Media->information->sampleTable;
        stbl_temp = (GF_SampleTableBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STBL);
+       /*clone sampleDescription table*/
        stbl_temp->SampleDescription = stbl->SampleDescription;
+       /*also clone sampleGroups description tables if any*/
+       stbl_temp->sampleGroupsDescription = stbl->sampleGroupsDescription;
        trak->Media->information->sampleTable = stbl_temp;
 
        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
@@ -2432,6 +2432,7 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de
        trak->Media->information->sampleTable = stbl;
 
        stbl_temp->SampleDescription = NULL;
+       stbl_temp->sampleGroupsDescription = NULL;
        gf_isom_box_del((GF_Box *)stbl_temp);
        if (e) return e;
 
@@ -2488,6 +2489,30 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de
        return GF_OK;
 }
 
+GF_Err gf_isom_clone_sample_descriptions(GF_ISOFile *the_file, u32 trackNumber, GF_ISOFile *orig_file, u32 orig_track, Bool reset_existing)
+{
+       u32 i;
+       GF_TrackBox *dst_trak, *src_trak;
+       GF_Err e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
+       if (e) return e;
+
+       dst_trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!dst_trak || !dst_trak->Media) return GF_BAD_PARAM;
+       src_trak = gf_isom_get_track_from_file(orig_file, orig_track);
+       if (!src_trak || !src_trak->Media) return GF_BAD_PARAM;
+
+       if (reset_existing) {
+               gf_isom_box_array_del(dst_trak->Media->information->sampleTable->SampleDescription->boxList);
+               dst_trak->Media->information->sampleTable->SampleDescription->boxList = gf_list_new();
+       }
+
+       for (i=0; i<gf_list_count(src_trak->Media->information->sampleTable->SampleDescription->boxList); i++) {
+               u32 outDesc;
+               e = gf_isom_clone_sample_description(the_file, trackNumber, orig_file, orig_track, i+1, NULL, NULL, &outDesc);
+               if (e) break;
+       }
+       return e;
+}
 
 GF_Err gf_isom_clone_sample_description(GF_ISOFile *the_file, u32 trackNumber, GF_ISOFile *orig_file, u32 orig_track, u32 orig_desc_index, char *URLname, char *URNname, u32 *outDescriptionIndex)
 {
@@ -3102,7 +3127,7 @@ GF_Err gf_isom_set_media_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 ne
 
 
 
-Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, GF_ISOFile *f2, u32 tk2)
+Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, u32 sdesc_index1, GF_ISOFile *f2, u32 tk2, u32 sdesc_index2)
 {
        u32 i, count;
        GF_TrackBox *trak1, *trak2;
@@ -3121,12 +3146,19 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, GF_ISOFile *f2,
 
        if (trak1->Media->handler->handlerType != trak2->Media->handler->handlerType) return 0;
        count = gf_list_count(trak1->Media->information->sampleTable->SampleDescription->boxList);
-       if (count != gf_list_count(trak2->Media->information->sampleTable->SampleDescription->boxList)) return 0;
+       if (count != gf_list_count(trak2->Media->information->sampleTable->SampleDescription->boxList)) {
+               if (!sdesc_index1 && !sdesc_index2) return 0;
+       }
 
        need_memcmp = 1;
        for (i=0; i<count; i++) {
                GF_Box *ent1 = (GF_Box *)gf_list_get(trak1->Media->information->sampleTable->SampleDescription->boxList, i);
                GF_Box *ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->boxList, i);
+
+               if (sdesc_index1) ent1 = (GF_Box *)gf_list_get(trak1->Media->information->sampleTable->SampleDescription->boxList, sdesc_index1 - 1);
+               if (sdesc_index2) ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->boxList, sdesc_index2 - 1);
+
+               if (!ent1 || !ent2) return 0;
                if (ent1->type != ent2->type) return 0;
 
                switch (ent1->type) {
@@ -3137,8 +3169,8 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, GF_ISOFile *f2,
                case GF_ISOM_BOX_TYPE_ENCA:
                case GF_ISOM_BOX_TYPE_ENCV:
                case GF_ISOM_BOX_TYPE_ENCS:
-                       Media_GetESD(trak1->Media, i+1, &esd1, 1);
-                       Media_GetESD(trak2->Media, i+1, &esd2, 1);
+                       Media_GetESD(trak1->Media, sdesc_index1 , &esd1, 1);
+                       Media_GetESD(trak2->Media, sdesc_index2 , &esd2, 1);
                        if (!esd1 || !esd2) continue;
                        need_memcmp = 0;
                        if (esd1->decoderConfig->streamType != esd2->decoderConfig->streamType) return 0;
@@ -3194,6 +3226,8 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, GF_ISOFile *f2,
                }
                        break;
                }
+
+               if (sdesc_index1 && sdesc_index2) break;
        }
        if (!need_memcmp) return 1;
        ret = 0;
@@ -3243,6 +3277,7 @@ u64 gf_isom_estimate_size(GF_ISOFile *movie)
        i=0;
        while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) {
                e = gf_isom_box_size(a);
+               assert (e == GF_OK);
                mdat_size += a->size;
        }
        return mdat_size;
@@ -4008,6 +4043,188 @@ GF_Err gf_isom_set_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio
 }
 
 
+GF_Err gf_isom_add_sample_group_entry(GF_List *sampleGroups, u32 sample_number, u32 grouping_type, u32 sampleGroupDescriptionIndex)
+{
+       GF_SampleGroupBox *sgroup = NULL;
+       u32 i, count, last_sample_in_entry;
+
+       count = gf_list_count(sampleGroups);
+       for (i=0; i<count; i++) {
+               sgroup = gf_list_get(sampleGroups, i);
+               if (sgroup->grouping_type==grouping_type) break;
+               sgroup = NULL;
+       }
+       if (!sgroup) {
+               sgroup = (GF_SampleGroupBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SBGP);
+               sgroup->grouping_type = grouping_type;
+               gf_list_add(sampleGroups, sgroup);
+       }
+       /*used in fragments, means we are adding the last sample*/
+       if (!sample_number) {
+               sample_number = 1;
+               if (sgroup->entry_count) {
+                       for (i=0; i<sgroup->entry_count; i++) {
+                               sample_number += sgroup->sample_entries[i].sample_count;
+                       }
+               }
+       }
+
+       if (!sgroup->entry_count) {
+               u32 idx = 0;
+               sgroup->entry_count = (sample_number>1) ? 2 : 1;
+               sgroup->sample_entries = gf_malloc(sizeof(GF_SampleGroupEntry) * sgroup->entry_count );
+               if (sample_number>1) {
+                       sgroup->sample_entries[0].sample_count = sample_number-1;
+                       sgroup->sample_entries[0].group_description_index = 0;
+                       idx = 1;
+               }
+               sgroup->sample_entries[idx].sample_count = 1;
+               sgroup->sample_entries[idx].group_description_index = sampleGroupDescriptionIndex;
+               return GF_OK;
+       }
+       last_sample_in_entry = 0;
+       for (i=0; i<sgroup->entry_count; i++) {
+               /*TODO*/
+               if (last_sample_in_entry + sgroup->sample_entries[i].sample_count > sample_number) return GF_NOT_SUPPORTED;
+               last_sample_in_entry += sgroup->sample_entries[i].sample_count;
+       }
+
+       if ((sgroup->sample_entries[sgroup->entry_count-1].group_description_index==sampleGroupDescriptionIndex) && (last_sample_in_entry+1==sample_number)) {
+               sgroup->sample_entries[sgroup->entry_count-1].sample_count++;
+               return GF_OK;
+       }
+       /*last entry was an empty desc (no group associated), just add the number of samples missing until new one, then add new one*/
+       if (! sgroup->sample_entries[sgroup->entry_count-1].group_description_index) {
+               sgroup->sample_entries[sgroup->entry_count-1].sample_count += sample_number - 1 - last_sample_in_entry;
+               sgroup->sample_entries = gf_realloc(sgroup->sample_entries, sizeof(GF_SampleGroupEntry) * (sgroup->entry_count + 1) );
+               sgroup->sample_entries[sgroup->entry_count].sample_count = 1;
+               sgroup->sample_entries[sgroup->entry_count].group_description_index = sampleGroupDescriptionIndex;
+               sgroup->entry_count++;
+               return GF_OK;
+       }
+       /*we are adding a sample with no desc, add entry at the end*/
+       if (!sampleGroupDescriptionIndex) {
+               sgroup->sample_entries = gf_realloc(sgroup->sample_entries, sizeof(GF_SampleGroupEntry) * (sgroup->entry_count + 1) );
+               sgroup->sample_entries[sgroup->entry_count].sample_count = 1;
+               sgroup->sample_entries[sgroup->entry_count].group_description_index = 0;
+               sgroup->entry_count++;
+               return GF_OK;
+       }
+       /*need to insert two entries ...*/
+       sgroup->sample_entries = gf_realloc(sgroup->sample_entries, sizeof(GF_SampleGroupEntry) * (sgroup->entry_count + 2) );
+
+       sgroup->sample_entries[sgroup->entry_count].sample_count = sample_number - 1 - last_sample_in_entry;
+       sgroup->sample_entries[sgroup->entry_count].group_description_index = 0;
+
+       sgroup->sample_entries[sgroup->entry_count+1].sample_count = 1;
+       sgroup->sample_entries[sgroup->entry_count+1].group_description_index = sampleGroupDescriptionIndex;
+       sgroup->entry_count+=2;
+       return GF_OK;
+}
+
+/*for now not exported*/
+static GF_Err gf_isom_set_sample_group_info(GF_ISOFile *movie, u32 track, u32 sample_number, u32 grouping_type, void *udta, void *(*sg_create_entry)(void *udta), Bool (*sg_compare_entry)(void *udta, void *entry))
+{
+       GF_Err e;
+       GF_TrackBox *trak;
+       GF_List *groupList;
+       void *entry;
+       GF_SampleGroupDescriptionBox *sgdesc = NULL;
+       u32 i, count, entry_idx;
+
+       e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
+       if (e) return e;
+
+       trak = gf_isom_get_track_from_file(movie, track);
+       if (!trak) return GF_BAD_PARAM;
+
+       /*look in stbl for sample sampleGroupsDescription*/
+       if (!trak->Media->information->sampleTable->sampleGroupsDescription)
+               trak->Media->information->sampleTable->sampleGroupsDescription = gf_list_new();
+
+       groupList = trak->Media->information->sampleTable->sampleGroupsDescription;
+       count = gf_list_count(groupList);
+       for (i=0; i<count; i++) {
+               sgdesc = gf_list_get(groupList, i);
+               if (sgdesc->grouping_type==grouping_type) break;
+               sgdesc = NULL;
+       }
+       if (!sgdesc) {
+               sgdesc = (GF_SampleGroupDescriptionBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SGPD);
+               sgdesc->grouping_type = grouping_type;
+               gf_list_add(groupList, sgdesc);
+       }
+       entry = NULL;
+       for (i=0; i<gf_list_count(sgdesc->group_descriptions); i++) {
+               entry = gf_list_get(sgdesc->group_descriptions, i);
+               if (sg_compare_entry(udta, entry)) break;
+               entry = NULL;
+       }
+       if (!entry) {
+               entry = sg_create_entry(udta);
+               if (!entry) return GF_IO_ERR;
+               gf_list_add(sgdesc->group_descriptions, entry);
+       }
+
+       entry_idx = 1 + gf_list_find(sgdesc->group_descriptions, entry);
+
+       /*look in stbl for sample sampleGroups*/
+       if (!trak->Media->information->sampleTable->sampleGroups)
+               trak->Media->information->sampleTable->sampleGroups = gf_list_new();
+
+       groupList = trak->Media->information->sampleTable->sampleGroups;
+
+       return gf_isom_add_sample_group_entry(trak->Media->information->sampleTable->sampleGroups, sample_number, grouping_type, entry_idx);
+}
+
+void *sg_rap_create_entry(void *udta)
+{
+       GF_VisualRandomAccessEntry *entry;
+       u32 *num_leading_samples = (u32 *) udta;
+       assert(udta);
+       GF_SAFEALLOC(entry, GF_VisualRandomAccessEntry);
+       entry->num_leading_samples = *num_leading_samples;
+       entry->num_leading_samples_known = entry->num_leading_samples ? 1 : 0;
+       return entry;
+}
+
+Bool sg_rap_compare_entry(void *udta, void *entry)
+{
+       u32 *num_leading_samples = (u32 *) udta;
+       if (*num_leading_samples == ((GF_VisualRandomAccessEntry *)entry)->num_leading_samples) return 1;
+       return 0;
+}
+
+GF_Err gf_isom_set_sample_rap_group(GF_ISOFile *movie, u32 track, u32 sample_number, u32 num_leading_samples)
+{
+       return gf_isom_set_sample_group_info(movie, track, sample_number, GF_4CC( 'r', 'a', 'p', ' ' ), &num_leading_samples, sg_rap_create_entry, sg_rap_compare_entry);
+}
+
+
+
+void *sg_roll_create_entry(void *udta)
+{
+       GF_RollRecoveryEntry *entry;
+       s16 *roll_distance = (s16 *) udta;
+       GF_SAFEALLOC(entry, GF_RollRecoveryEntry);
+       entry->roll_distance = *roll_distance;
+       return entry;
+}
+
+Bool sg_roll_compare_entry(void *udta, void *entry)
+{
+       s16 *roll_distance = (s16 *) udta;
+       if (*roll_distance == ((GF_RollRecoveryEntry *)entry)->roll_distance) return 1;
+       return 0;
+}
+
+GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_number, s16 roll_distance)
+{
+       return gf_isom_set_sample_group_info(movie, track, sample_number, GF_4CC( 'r', 'o', 'l', 'l' ), &roll_distance, sg_roll_create_entry, sg_roll_compare_entry);
+}
+
+
+
 #endif /*!defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)*/
 
 
index 87977f06960e0e62fd1dca87882bde2e7eab5e3d..e8ab639cfb3ffd1a0a77a8f76fe7c2c350b689e7 100644 (file)
@@ -457,12 +457,21 @@ GF_Err Media_FindSyncSample(GF_SampleTableBox *stbl, u32 searchFromSample, u32 *
                (*sampleNumber) = searchFromSample;
                return GF_OK;
        }
+
+       /*check sample groups - prev & next are overwritten if RAP group is found, but are not re-initialized otherwise*/
+       stbl_SearchSAPs(stbl, searchFromSample, &isRAP, &prev, &next);
+       if (isRAP) {
+               (*sampleNumber) = searchFromSample;
+               return GF_OK;
+       }
+
        //nothing yet, go for next time...
        if (mode == GF_ISOM_SEARCH_SYNC_FORWARD) {
                if (next) *sampleNumber = next;
        } else {
                if (prev) *sampleNumber = prev;
        }
+
        return GF_OK;
 }
 
index 89ab53683fe2cf5e00171bcba823a8497b5de97e..6fb0a9d04aa223738a7049b1e68d48fe7f9cebd7 100644 (file)
@@ -83,9 +83,9 @@ GF_Err gf_isom_extract_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num,
        }
        if (!xml || !xml->xml || !xml->xml_length) return GF_BAD_PARAM;
        
-       didfile = gf_f64_open(outName, "wt");
+       didfile = gf_f64_open(outName, "wb");
        if (!didfile) return GF_IO_ERR;
-       fwrite(xml->xml, xml->xml_length, 1, didfile);
+       gf_fwrite(xml->xml, xml->xml_length, 1, didfile);
        fclose(didfile);
 
        if (is_binary) *is_binary = (xml->type==GF_ISOM_BOX_TYPE_BXML) ? 1 : 0;
index 096bb8613ec5e7072a0eec6c2d521b780e2aad5c..38f87cd53c25b2fe69fd0ce2a2274f4aec20101d 100644 (file)
@@ -129,6 +129,39 @@ GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, Bool use_segments)
        return GF_OK;
 }
 
+GF_Err gf_isom_change_track_fragment_defaults(GF_ISOFile *movie, u32 TrackID, 
+                                                        u32 DefaultSampleDescriptionIndex,
+                                                        u32 DefaultSampleDuration,
+                                                        u32 DefaultSampleSize,
+                                                        u8 DefaultSampleIsSync,
+                                                        u8 DefaultSamplePadding,
+                                                        u16 DefaultDegradationPriority)
+{
+       GF_MovieExtendsBox *mvex;
+       GF_TrackExtendsBox *trex;
+       GF_TrackBox *trak;
+
+       if (!movie || !movie->moov) return GF_BAD_PARAM;
+       //this is only allowed in write mode
+       if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;
+
+       trak = gf_isom_get_track_from_id(movie->moov, TrackID);
+       if (!trak) return GF_BAD_PARAM;
+
+       mvex = movie->moov->mvex;
+       if (!mvex) return GF_BAD_PARAM;
+
+       trex = GetTrex(movie->moov, TrackID);
+       if (!trex)  return GF_BAD_PARAM;
+
+       trex->def_sample_desc_index = DefaultSampleDescriptionIndex;
+       trex->def_sample_duration = DefaultSampleDuration;
+       trex->def_sample_size = DefaultSampleSize;
+       trex->def_sample_flags = GF_ISOM_FORMAT_FRAG_FLAGS(DefaultSamplePadding, DefaultSampleIsSync, DefaultDegradationPriority);
+
+       return GF_OK;
+}
+
 
 GF_Err gf_isom_setup_track_fragment(GF_ISOFile *movie, u32 TrackID, 
                                                         u32 DefaultSampleDescriptionIndex,
@@ -167,12 +200,7 @@ GF_Err gf_isom_setup_track_fragment(GF_ISOFile *movie, u32 TrackID,
                mvex_AddBox((GF_Box*)mvex, (GF_Box *) trex);
        }
        trex->track = trak;
-       trex->def_sample_desc_index = DefaultSampleDescriptionIndex;
-       trex->def_sample_duration = DefaultSampleDuration;
-       trex->def_sample_size = DefaultSampleSize;
-       trex->def_sample_flags = GF_ISOM_FORMAT_FRAG_FLAGS(DefaultSamplePadding, DefaultSampleIsSync, DefaultDegradationPriority);
-
-       return GF_OK;
+       return gf_isom_change_track_fragment_defaults(movie, TrackID, DefaultSampleDescriptionIndex, DefaultSampleDuration, DefaultSampleSize, DefaultSampleIsSync, DefaultSamplePadding, DefaultDegradationPriority);
 }
 
 
@@ -478,39 +506,98 @@ u32 UpdateRuns(GF_ISOFile *movie, GF_TrackFragmentBox *traf)
        return sampleCount;
 }
 
-Bool moof_get_rap_time_offset(GF_MovieFragmentBox *moof, u32 refTrackID, u32 *rap_delta)
+static u32 moof_get_sap_info(GF_MovieFragmentBox *moof, u32 refTrackID, u32 *sap_delta, Bool *starts_with_sap)
 {
-       u32 i, j, delta;
+       u32 i, j, count, delta, earliest_cts, sap_type, sap_sample_num, cur_sample;
+       Bool first = 1;
        GF_TrunEntry *ent;
-       GF_TrackFragmentBox *traf;
+       GF_TrackFragmentBox *traf=NULL;
        GF_TrackFragmentRunBox *trun;
-       *rap_delta = 0;
+       *sap_delta = 0;
+       *starts_with_sap = 0;
        for (i=0; i<gf_list_count(moof->TrackList); i++) {
                traf = gf_list_get(moof->TrackList, i);
                if (traf->tfhd->trackID==refTrackID) break;
                traf=NULL;
        }
        if (!traf) return 0;
+       earliest_cts = 0;
+
+
+       /*first check if we have a roll/rap sample in this traf, and mark its sample count*/
+       sap_type = 0;
+       sap_sample_num = 0;
+       /*check RAP and ROLL*/
+       count = traf->sampleGroups ? gf_list_count(traf->sampleGroups) : 0;
+       for (i=0; i<count; i++) {
+               GF_SampleGroupBox *sg;
+               u32 j, first_sample;
+               Bool rap_type = 0;
+               sg = gf_list_get(traf->sampleGroups, i);
+
+
+               switch (sg->grouping_type) {
+               case GF_4CC('r','a','p',' '):
+                       rap_type = 1;
+                       break;
+               case GF_4CC('r','o','l','l'):
+                       break;
+               default:
+                       continue;
+               }
+               /*first entry is SAP*/
+               first_sample = 1;
+               for (j=0; j<sg->entry_count; j++) {
+                       if (! sg->sample_entries[j].group_description_index) {
+                               first_sample += sg->sample_entries[j].sample_count;
+                               continue;
+                       }
+                       if (!j) {
+                               *starts_with_sap = 1;
+                               sap_sample_num = 0;
+                       }
+                       if (!sap_sample_num || (sap_sample_num>first_sample)) {
+                               sap_type = rap_type ? 3 : 4;
+                               sap_sample_num = first_sample;
+                       }
+                       break;
+               }
+       }
 
+       /*then browse all samples, looking for SYNC flag or sap_sample_num*/
+       cur_sample = 1;
        delta = 0;
        i=0;
        while ((trun = gf_list_enum(traf->TrackRuns, &i))) {
                if (trun->flags & GF_ISOM_TRUN_FIRST_FLAG) {
                        if (GF_ISOM_GET_FRAG_SYNC(trun->flags)) {
                                ent = gf_list_get(trun->entries, 0);
-                               *rap_delta = delta + ent->CTS_Offset;
+                               if (!delta) earliest_cts = ent->CTS_Offset;
+                               *sap_delta = delta + ent->CTS_Offset - ent->CTS_Offset;
+                               *starts_with_sap = first;
                                return 1;
                        }
                }
                j=0;
                while ((ent = gf_list_enum(trun->entries, &j))) {
+                       if (!delta) earliest_cts = ent->CTS_Offset;
+
                        if (GF_ISOM_GET_FRAG_SYNC(ent->flags)) {
-                               *rap_delta = delta + ent->CTS_Offset;
+                               *sap_delta = delta + ent->CTS_Offset - earliest_cts;
+                               *starts_with_sap = first;
                                return 1;
                        }
+                       /*we found our roll or rap sample*/
+                       if (cur_sample==sap_sample_num) {
+                               *sap_delta = delta + ent->CTS_Offset - earliest_cts;
+                               return sap_type;
+                       }
                        delta += ent->Duration;
+                       first = 0;
+                       cur_sample++;
                }
        }
+       /*not found*/
        return 0;
 }
 
@@ -518,7 +605,7 @@ u32 moof_get_duration(GF_MovieFragmentBox *moof, u32 refTrackID)
 {
        u32 i, j, duration;
        GF_TrunEntry *ent;
-       GF_TrackFragmentBox *traf;
+       GF_TrackFragmentBox *traf = NULL;
        GF_TrackFragmentRunBox *trun;
        for (i=0; i<gf_list_count(moof->TrackList); i++) {
                traf = gf_list_get(moof->TrackList, i);
@@ -542,7 +629,7 @@ u32 moof_get_earliest_cts(GF_MovieFragmentBox *moof, u32 refTrackID)
 {
        u32 i, j, cts, duration;
        GF_TrunEntry *ent;
-       GF_TrackFragmentBox *traf;
+       GF_TrackFragmentBox *traf=NULL;
        GF_TrackFragmentRunBox *trun;
        for (i=0; i<gf_list_count(moof->TrackList); i++) {
                traf = gf_list_get(moof->TrackList, i);
@@ -601,17 +688,23 @@ GF_Err StoreFragment(GF_ISOFile *movie, Bool load_mdat_only, s32 data_offset_dif
        }
 
        if (load_mdat_only) {
+               u64 offset;
                u64 pos = gf_bs_get_position(bs);
                //we assume we never write large MDATs in fragment mode which should always be true
                movie->moof->mdat_size = (u32) (pos - movie->moof->fragment_offset);
                movie->moof->mdat = gf_malloc(sizeof(char) * movie->moof->mdat_size);
                if (!movie->moof->mdat) return GF_OUT_OF_MEM;
-               gf_bs_seek(bs, movie->segment_start);
+
+               offset = movie->segment_start;
+
+               gf_bs_seek(bs, offset);
                /*write mdat size*/
                gf_bs_write_u32(bs, (u32) movie->moof->mdat_size);
-               gf_bs_seek(bs, movie->segment_start);
+
+               gf_bs_seek(bs, offset);
                gf_bs_read_data(bs, movie->moof->mdat, movie->moof->mdat_size);
-               gf_bs_seek(bs, movie->segment_start);
+
+               gf_bs_seek(bs, offset);
                gf_bs_truncate(bs);
                return GF_OK;
        }
@@ -727,20 +820,78 @@ static GF_Err sidx_rewrite(GF_SegmentIndexBox *sidx, GF_BitStream *bs, u64 start
        return e;
 }
 
+GF_Err gf_isom_allocate_sidx(GF_ISOFile *movie, s32 subsegs_per_sidx, Bool daisy_chain_sidx, u32 nb_segs, u32 *frags_per_segment, u32 *start_range, u32 *end_range)
+{
+       GF_BitStream *bs;
+       GF_Err e;
+
+       //and only at setup
+       if (!movie || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;
+       if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;
+       if (movie->root_sidx) return GF_BAD_PARAM;
+       if (movie->moof) return GF_BAD_PARAM;
+       if (gf_list_count(movie->moof_list)) return GF_BAD_PARAM;
+
+       movie->root_sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX);
+       /*we don't write anything between sidx and following moov*/
+       movie->root_sidx->first_offset = 0;
+
+       /*for now we only store one ref per subsegment*/
+       movie->root_sidx->nb_refs = nb_segs;
+
+       movie->root_sidx->refs = gf_malloc(sizeof(GF_SIDXReference) * movie->root_sidx->nb_refs);
+       memset(movie->root_sidx->refs, 0, sizeof(GF_SIDXReference) * movie->root_sidx->nb_refs);
+
+       movie->root_sidx_index = 0;
+
+       /*remember start of sidx*/
+       movie->root_sidx_offset = gf_bs_get_position(movie->editFileMap->bs);
+
+       bs = movie->editFileMap->bs;
+
+       e = gf_isom_box_size((GF_Box *) movie->root_sidx);
+       if (e) return e;
+       e = gf_isom_box_write((GF_Box *) movie->root_sidx, bs);
+       if (e) return e;
+
+       if (start_range) *start_range = (u32) movie->root_sidx_offset;
+       if (end_range) *end_range = (u32) gf_bs_get_position(bs);
+
+       return GF_OK;
+}
+
+typedef struct
+{
+       GF_SegmentIndexBox *sidx;
+       u64 start_offset, end_offset;
+} SIDXEntry;
 
-GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenceTrackID, u64 ref_track_decode_time, Bool daisy_chain_sidx, Bool last_segment)
+GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 subsegments_per_sidx, u32 referenceTrackID, u64 ref_track_decode_time, u64 ref_track_next_cts, Bool daisy_chain_sidx, Bool last_segment, u64 *index_start_range, u64 *index_end_range)
 {
        GF_SegmentIndexBox *sidx=NULL;
-       GF_SegmentIndexBox *prev_sidx=NULL;
        GF_SegmentIndexBox *root_sidx=NULL;
+       GF_List *daisy_sidx = NULL;
        u64 sidx_start, sidx_end;
-       Bool first_sidx = 0;
+       Bool first_frag_in_subseg;
        Bool no_sidx = 0;
-       u32 count, nb_subsegs=0, idx, cur_dur, sidx_dur, sidx_idx;
-       u64 last_top_box_pos, root_prev_offset, local_sidx_start, local_sidx_end;
+       u32 count, idx, cur_dur, sidx_dur, sidx_idx, idx_offset, frag_count;
+       u64 last_top_box_pos, root_prev_offset, local_sidx_start, local_sidx_end, prev_earliest_cts, prev_earliest_dts;
        GF_TrackBox *trak = NULL;
        GF_Err e;
+       /*number of subsegment in this segment (eg nb references in the first SIDX found)*/
+       u32 nb_subsegs=0; 
+       /*number of subsegment per sidx (eg number of references of any sub-SIDX*/
+       u32 subseg_per_sidx;
+       /*number of fragments per subsegment*/
+       u32 frags_per_subseg;
+       /*number of fragments per subsidx*/
+       u32 frags_per_subsidx;
+
        sidx_start = sidx_end = 0;
+
+       if (index_start_range) *index_start_range = 0;
+       if (index_end_range) *index_end_range = 0;
+
        //and only at setup
        if (!movie || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;
        if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;
@@ -758,8 +909,20 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenc
        gf_bs_seek(movie->editFileMap->bs, movie->segment_start);
        gf_bs_truncate(movie->editFileMap->bs);
 
+       idx_offset = 0;
+
        if (referenceTrackID) {
                trak = gf_isom_get_track_from_id(movie->moov, referenceTrackID);
+       }
+       
+       if (subsegments_per_sidx < 0) {
+               referenceTrackID = 0;
+               subsegments_per_sidx = 0;
+               no_sidx = 1;
+       }
+
+       /*write STYP if we write to a different file or if we write the last segment*/
+       if ((!movie->append_segment && !movie->segment_start) || last_segment) {
 
                /*modify brands STYP*/
 
@@ -769,108 +932,169 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenc
                        /*"lmsg" brand: this is the last DASH Segment*/
                        gf_isom_modify_alternate_brand(movie, GF_4CC('l','m','s','g'), 1);
                }
-       }
-       /*write STYP*/
-       movie->brand->type = GF_ISOM_BOX_TYPE_STYP;
-    e = gf_isom_box_size((GF_Box *) movie->brand);
-    if (e) return e;
-    e = gf_isom_box_write((GF_Box *) movie->brand, movie->editFileMap->bs);
-    if (e) return e;
-
-       if (frags_per_sidx < 0) {
-               referenceTrackID = 0;
-               frags_per_sidx = 0;
-               no_sidx = 1;
+
+               movie->brand->type = GF_ISOM_BOX_TYPE_STYP;
+               e = gf_isom_box_size((GF_Box *) movie->brand);
+               if (e) return e;
+               e = gf_isom_box_write((GF_Box *) movie->brand, movie->editFileMap->bs);
+               if (e) return e;
        }
 
+       frags_per_subseg = 0;
+       subseg_per_sidx = 0;
+       frags_per_subsidx = 0;
+       
+       prev_earliest_cts = 0;
+       prev_earliest_dts = ref_track_decode_time;
+
+       if (daisy_chain_sidx)
+               daisy_sidx = gf_list_new();
+
        /*prepare SIDX: we write a blank SIDX box with the right number of entries, and will rewrite it later on*/
        if (referenceTrackID) {
                Bool is_root_sidx=0;
-               sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX);
+
+               prev_earliest_cts = ref_track_decode_time + moof_get_earliest_cts(gf_list_get(movie->moof_list, 0), referenceTrackID);
+
+               if (movie->root_sidx) {
+                       sidx = movie->root_sidx;
+               } else {
+                       sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX);
+               }
                sidx->reference_ID = referenceTrackID;
                sidx->timescale = trak->Media->mediaHeader->timeScale;
                /*we don't write anything between sidx and following moov*/
                sidx->first_offset = 0;
-               sidx->earliest_presentation_time = ref_track_decode_time;
 
-               /*we consider that each fragment is a subsegment - this could be controled by another parameter*/
-               if (!frags_per_sidx) {
+               /*we allocated our sidx to have one ref per "segment" (eg per call to close_segment)*/
+               if (movie->root_sidx) {
+                       if (!movie->root_sidx_index) {
+                               sidx->earliest_presentation_time = prev_earliest_cts;
+                       }
                        nb_subsegs = 1;
-                       frags_per_sidx = count;
+                       frags_per_subseg = count;
+                       frags_per_subsidx = count;
+                       subseg_per_sidx = 1;
+
+                       idx_offset = movie->root_sidx_index;
+                       sidx_end = gf_bs_get_position(movie->editFileMap->bs);
                } else {
-                       nb_subsegs = count/frags_per_sidx;
-                       if (nb_subsegs*frags_per_sidx<count) nb_subsegs++;
-               }
+                       sidx->earliest_presentation_time = prev_earliest_cts;
+
+                       /*if more subsegments requested than fragments available, make a single sidx*/
+                       if ((s32) count <= subsegments_per_sidx) 
+                               subsegments_per_sidx = 0;
+                       
+                       if (daisy_chain_sidx && (subsegments_per_sidx<2))
+                               subsegments_per_sidx = 2;
+
+                       /*single SIDX, each fragment is a subsegment and we reference all subsegments*/
+                       if (!subsegments_per_sidx) {
+                               nb_subsegs = count;
+                               /*we consider that each fragment is a subsegment - this could be controled by another parameter*/
+                               frags_per_subseg = 1;
+                               frags_per_subsidx = count;
+                               subseg_per_sidx = count;
+
+                               sidx->nb_refs = nb_subsegs;
+                               daisy_chain_sidx = 0;
+                       }
+                       /*daisy-chain SIDX: each SIDX describes a subsegment made of frags_per_subseg fragments plus next */
+                       else if (daisy_chain_sidx) {
+                               frags_per_subsidx = count/subsegments_per_sidx;
+                               if (frags_per_subsidx * subsegments_per_sidx < count) frags_per_subsidx++;
+                               
+                               nb_subsegs = subsegments_per_sidx;
 
-               /*single SIDX, reference all fragments*/
-               if (nb_subsegs==1) {
-                       sidx->nb_refs = frags_per_sidx;
-                       daisy_chain_sidx = 0;
-               } 
-               /*daisy-chain SIDX, reference all fragments plus next */
-               else if (daisy_chain_sidx) {
-                       sidx->nb_refs = frags_per_sidx + 1;
-                       /*we will have to adjust earliest cpresentation time*/
-                       first_sidx = 1;
-               }
-               /*root SIDX referencing all subsegments*/
-               else {
-                       sidx->nb_refs = nb_subsegs;
-                       is_root_sidx = 1;
-               }
-               sidx->refs = gf_malloc(sizeof(GF_SIDXReference)*sidx->nb_refs);
-               memset(sidx->refs, 0, sizeof(GF_SIDXReference)*sidx->nb_refs);
+                               /*we consider that each fragment is a subsegment - this could be controled by another parameter*/
+                               frags_per_subseg = 1;
+                               subseg_per_sidx = frags_per_subsidx / frags_per_subseg;
+                               if (subseg_per_sidx * frags_per_subseg < frags_per_subsidx) subseg_per_sidx++;
 
-               /*remember start of sidx*/
-               sidx_start = gf_bs_get_position(movie->editFileMap->bs);
+                               sidx->nb_refs = subseg_per_sidx + 1;
+                       } 
+                       /*hierarchical SIDX*/
+                       else {
+                               frags_per_subsidx = count/subsegments_per_sidx;
+                               if (frags_per_subsidx * subsegments_per_sidx < count) frags_per_subsidx++;
+                               
+                               nb_subsegs = subsegments_per_sidx;
 
-               e = gf_isom_box_size((GF_Box *) sidx);
-               if (e) return e;
-               e = gf_isom_box_write((GF_Box *) sidx, movie->editFileMap->bs);
-               if (e) return e;
+                               /*we consider that each fragment is a subsegment - this could be controled by another parameter*/
+                               frags_per_subseg = 1;
+                               subseg_per_sidx = frags_per_subsidx / frags_per_subseg;
+                               if (subseg_per_sidx * frags_per_subseg < frags_per_subsidx) subseg_per_sidx++;
 
-               sidx_end = gf_bs_get_position(movie->editFileMap->bs);
-       
-               count = idx = 0;
+                               sidx->nb_refs = nb_subsegs;
+                               is_root_sidx = 1;
+                       }
+
+                       sidx->refs = gf_malloc(sizeof(GF_SIDXReference)*sidx->nb_refs);
+                       memset(sidx->refs, 0, sizeof(GF_SIDXReference)*sidx->nb_refs);
+
+                       /*remember start of sidx*/
+                       sidx_start = gf_bs_get_position(movie->editFileMap->bs);
+
+                       e = gf_isom_box_size((GF_Box *) sidx);
+                       if (e) return e;
+                       e = gf_isom_box_write((GF_Box *) sidx, movie->editFileMap->bs);
+                       if (e) return e;
+
+                       sidx_end = gf_bs_get_position(movie->editFileMap->bs);
+
+                       if (daisy_sidx) {
+                               SIDXEntry *entry;
+                               GF_SAFEALLOC(entry, SIDXEntry);
+                               entry->sidx = sidx;
+                               entry->start_offset = sidx_start;
+                               gf_list_add(daisy_sidx, entry);
+                       }
+               }
 
                if (is_root_sidx) {
                        root_sidx = sidx;
                        sidx = NULL;
                }
+               count = idx = 0;
        }
 
 
+       last_top_box_pos = root_prev_offset = sidx_end;
        sidx_idx = 0;
        sidx_dur = 0;
-       last_top_box_pos = root_prev_offset = sidx_end;
        local_sidx_start = local_sidx_end = 0;
 
        /*cumulated segments duration since start of the sidx */
+       frag_count = frags_per_subsidx;
        cur_dur = 0;
+       first_frag_in_subseg = 1;
        e = GF_OK;
        while (gf_list_count(movie->moof_list)) {
                s32 offset_diff;
                u32 moof_size;
-               u32 dur;
 
                movie->moof = gf_list_get(movie->moof_list, 0);
                gf_list_rem(movie->moof_list, 0);
 
-               if (!root_sidx && sidx && first_sidx) {
-                       first_sidx = 0;
-                       sidx->earliest_presentation_time = ref_track_decode_time + moof_get_earliest_cts(movie->moof, referenceTrackID);
-               }
-
                /*hierarchical or daisy-chain SIDXs*/
                if (!no_sidx && !sidx && (root_sidx || daisy_chain_sidx) ) {
+                       u32 subsegments_remaining;
                        sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX);
                        sidx->reference_ID = referenceTrackID;
                        sidx->timescale = trak->Media->mediaHeader->timeScale;
                        sidx->earliest_presentation_time = ref_track_decode_time + sidx_dur + moof_get_earliest_cts(movie->moof, referenceTrackID);
 
+                       frag_count = frags_per_subsidx;
+
+                       /*last segment, add only one ref*/
+                       subsegments_remaining = 1 + gf_list_count(movie->moof_list);
+                       if (subseg_per_sidx*frags_per_subseg > subsegments_remaining) {
+                               subseg_per_sidx = subsegments_remaining / frags_per_subseg;
+                               if (subseg_per_sidx * frags_per_subseg < subsegments_remaining) subseg_per_sidx++;
+                       }
                        /*we don't write anything between sidx and following moov*/
                        sidx->first_offset = 0;
-                       sidx->nb_refs = frags_per_sidx;
+                       sidx->nb_refs = subseg_per_sidx;
                        if (daisy_chain_sidx && (nb_subsegs>1)) {
                                sidx->nb_refs += 1;
                        }
@@ -893,6 +1117,14 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenc
 
                        /*adjust prev offset*/
                        last_top_box_pos = local_sidx_end;
+
+                       if (daisy_sidx) {
+                               SIDXEntry *entry;
+                               GF_SAFEALLOC(entry, SIDXEntry);
+                               entry->sidx = sidx;
+                               entry->start_offset = local_sidx_start;
+                               gf_list_add(daisy_sidx, entry);
+                       }
                }
 
                offset_diff = (s32) (gf_bs_get_position(movie->editFileMap->bs) - movie->moof->fragment_offset);
@@ -901,90 +1133,160 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenc
                if (!e) {
                        e = StoreFragment(movie, 0, offset_diff, &moof_size);
 
+
                        if (sidx) {
-                               /*we refer to next moof*/
-                               sidx->refs[idx].reference_type = 0;
-                               sidx->refs[idx].contains_RAP = moof_get_rap_time_offset(movie->moof, referenceTrackID, & sidx->refs[idx].RAP_delta_time);
-                               if (sidx->refs[idx].contains_RAP) {
-                                       sidx->refs[idx].RAP_delta_time += cur_dur;
-
-                                       if (root_sidx && !root_sidx->refs[sidx_idx].contains_RAP) {
-                                               root_sidx->refs[sidx_idx].contains_RAP = 1;
-                                               root_sidx->refs[sidx_idx].RAP_delta_time = sidx->refs[idx].RAP_delta_time + sidx_dur;
-                                       }
-                                       else if (prev_sidx && !prev_sidx->refs[prev_sidx->nb_refs - 1].contains_RAP) {
-                                               prev_sidx->refs[prev_sidx->nb_refs - 1].contains_RAP = 1;
-                                               prev_sidx->refs[prev_sidx->nb_refs - 1].RAP_delta_time = sidx->refs[idx].RAP_delta_time;
+                               u32 cur_index = idx_offset + idx;
+
+                               /*do not compute earliest CTS if single segment sidx since we only have set the info for one subsegment*/
+                               if (!movie->root_sidx && first_frag_in_subseg) {
+                                       u64 first_cts = ref_track_decode_time + sidx_dur + cur_dur +  moof_get_earliest_cts(movie->moof, referenceTrackID);
+                                       u32 subseg_dur = (u32) (first_cts - prev_earliest_cts);
+                                       if (cur_index) {
+                                               sidx->refs[cur_index-1].subsegment_duration = subseg_dur;
+                                               if (root_sidx) root_sidx->refs[sidx_idx].subsegment_duration += subseg_dur;
                                        }
+                                       prev_earliest_cts = first_cts;
+                                       first_frag_in_subseg = 0;
+                               }
+
 
+                               /*we refer to next moof*/
+                               sidx->refs[cur_index].reference_type = 0;
+                               if (!sidx->refs[cur_index].SAP_type) {
+                                       sidx->refs[cur_index].SAP_type = moof_get_sap_info(movie->moof, referenceTrackID, & sidx->refs[cur_index].SAP_delta_time, & sidx->refs[cur_index].starts_with_SAP);
+                                       if (sidx->refs[cur_index].SAP_type) {
+                                               if (root_sidx && !root_sidx->refs[sidx_idx].SAP_type) {
+                                                       root_sidx->refs[sidx_idx].SAP_type = sidx->refs[cur_index].SAP_type;
+                                                       root_sidx->refs[sidx_idx].SAP_delta_time = sidx->refs[cur_index].SAP_delta_time;
+                                                       root_sidx->refs[sidx_idx].starts_with_SAP = sidx->refs[cur_index].starts_with_SAP;
+                                               }
+                                       }
                                }
-                               
-                               dur = moof_get_duration(movie->moof, referenceTrackID);
-                               sidx->refs[idx].subsegment_duration += dur;
-                               cur_dur += dur;
+                               cur_dur += moof_get_duration(movie->moof, referenceTrackID);
+
                                /*reference size is end of the moof we just wrote minus last_box_pos*/
-                               sidx->refs[idx].reference_size = (u32) ( gf_bs_get_position(movie->editFileMap->bs) - last_top_box_pos) ;
+                               sidx->refs[cur_index].reference_size += (u32) ( gf_bs_get_position(movie->editFileMap->bs) - last_top_box_pos) ;
                                last_top_box_pos = gf_bs_get_position(movie->editFileMap->bs);
-                               idx++;
 
                                count++;
+
+                               /*we are switching subsegment*/
+                               frag_count--;
+
+                               if (count==frags_per_subseg) {                                  
+                                       count = 0;
+                                       first_frag_in_subseg = 1;
+                                       idx++;
+                               }
+
                                /*switching to next SIDX*/
-                               if (count==frags_per_sidx) {
+                               if ((idx==subseg_per_sidx) || !frag_count) {
+                                       u32 subseg_dur;
+                                       u64 next_cts;
+                                       /*update last ref duration*/
+                                       if (gf_list_count(movie->moof_list)) {
+                                               next_cts = ref_track_decode_time + sidx_dur + cur_dur + moof_get_earliest_cts(gf_list_get(movie->moof_list, 0), referenceTrackID);
+                                       } else {
+                                               next_cts = ref_track_next_cts;
+                                       }
+                                       subseg_dur = (u32) (next_cts - prev_earliest_cts);
+                                       if (movie->root_sidx) {
+                                               sidx->refs[idx_offset].subsegment_duration = subseg_dur;
+                                       }
+                                       /*if daisy chain and not the last sidx, we have an extra entry at the end*/
+                                       else if (daisy_chain_sidx && (nb_subsegs>1)) {
+                                               sidx->refs[sidx->nb_refs - 2].subsegment_duration = subseg_dur;
+                                       } else {
+                                               sidx->refs[sidx->nb_refs-1].subsegment_duration = subseg_dur;
+                                       }
+                                       if (root_sidx) root_sidx->refs[sidx_idx].subsegment_duration += subseg_dur;
 
                                        if (root_sidx) {
                                                root_sidx->refs[sidx_idx].reference_size = (u32) (gf_bs_get_position(movie->editFileMap->bs) - local_sidx_start);
-                                               root_sidx->refs[sidx_idx].subsegment_duration = cur_dur;
                                                if (!sidx_idx) {
                                                        root_sidx->earliest_presentation_time = sidx->earliest_presentation_time;
                                                }
-
                                                sidx_rewrite(sidx, movie->editFileMap->bs, local_sidx_start);
                                                gf_isom_box_del((GF_Box*)sidx);
                                                sidx = NULL;
                                        } else if (daisy_chain_sidx) {
-                                               if (prev_sidx) {
-                                                       if (prev_sidx->refs[prev_sidx->nb_refs - 1].contains_RAP) {
-                                                               prev_sidx->refs[prev_sidx->nb_refs - 1].contains_RAP = 1;
-                                                               prev_sidx->refs[prev_sidx->nb_refs - 1].RAP_delta_time += sidx_dur;
-                                                       }
-                                                       prev_sidx->refs[prev_sidx->nb_refs - 1].subsegment_duration = sidx_dur;
-                                                       prev_sidx->refs[prev_sidx->nb_refs - 1].reference_size = (u32) (gf_bs_get_position(movie->editFileMap->bs) - local_sidx_start);
-                                                       prev_sidx->refs[prev_sidx->nb_refs - 1].reference_type = 1;
-                                                       sidx_rewrite(prev_sidx, movie->editFileMap->bs, sidx_start);
-                                                       gf_isom_box_del((GF_Box*)prev_sidx);
-
-                                                       sidx_start = local_sidx_start;
-                                                       sidx_end = local_sidx_end;
-                                               }
+                                               SIDXEntry *entry = gf_list_last(daisy_sidx);
+                                               entry->end_offset = gf_bs_get_position(movie->editFileMap->bs);
                                                nb_subsegs--;
-                                               prev_sidx = sidx;
                                                sidx = NULL;
                                        }
                                        sidx_dur += cur_dur;
                                        cur_dur = 0;
                                        count = 0;
                                        idx=0;
+                                       if (movie->root_sidx) 
+                                               movie->root_sidx_index++;
                                        sidx_idx++;
                                }
                        }
                } 
-               gf_isom_box_del((GF_Box *) movie->moof);        
+               gf_isom_box_del((GF_Box *) movie->moof);
                movie->moof = NULL;
        }
 
+       if (movie->root_sidx) {
+               if (last_segment) {
+                       assert(movie->root_sidx_index == movie->root_sidx->nb_refs);
+
+                       sidx_rewrite(movie->root_sidx, movie->editFileMap->bs, movie->root_sidx_offset);
+                       gf_isom_box_del((GF_Box*) movie->root_sidx);
+                       movie->root_sidx = NULL;
+               }
+               return GF_OK;
+       } 
+
        if (sidx) {
+               assert(!root_sidx);
                sidx_rewrite(sidx, movie->editFileMap->bs, sidx_start);
                gf_isom_box_del((GF_Box*)sidx);
        }
-       if (prev_sidx) {
-               sidx_rewrite(prev_sidx, movie->editFileMap->bs, sidx_start);
-               gf_isom_box_del((GF_Box*)prev_sidx);
+       if (daisy_sidx) {
+               u32 i, j;
+               u64 last_entry_end_offset = 0;
+               u32 count = gf_list_count(daisy_sidx);
+               for (i=count; i>1; i--) {
+                       SIDXEntry *entry = gf_list_get(daisy_sidx, i-2);
+                       SIDXEntry *next_entry = gf_list_get(daisy_sidx, i-1);
+
+                       if (!last_entry_end_offset) {
+                               last_entry_end_offset = next_entry->end_offset;
+                               /*rewrite last sidx*/
+                               sidx_rewrite(next_entry->sidx, movie->editFileMap->bs, next_entry->start_offset);
+                       }
+                       /*copy over SAP info for last item (which points to next item !)*/
+                       entry->sidx->refs[entry->sidx->nb_refs-1] = next_entry->sidx->refs[0];
+                       /*and rewrite reference type, size and dur*/
+                       entry->sidx->refs[entry->sidx->nb_refs-1].reference_type = 1;
+                       entry->sidx->refs[entry->sidx->nb_refs-1].reference_size = (u32) (last_entry_end_offset - next_entry->start_offset);
+                       entry->sidx->refs[entry->sidx->nb_refs-1].subsegment_duration = 0;
+                       for (j=0; j<next_entry->sidx->nb_refs; j++) {
+                               entry->sidx->refs[entry->sidx->nb_refs-1].subsegment_duration += next_entry->sidx->refs[j].subsegment_duration;
+                       }
+                       sidx_rewrite(entry->sidx, movie->editFileMap->bs, entry->start_offset);
+               }
+               while (gf_list_count(daisy_sidx)) {
+                       SIDXEntry *entry = gf_list_last(daisy_sidx);
+                       gf_isom_box_del((GF_Box*)entry->sidx);
+                       gf_free(entry);
+                       gf_list_rem_last(daisy_sidx);
+               }
+               gf_list_del(daisy_sidx);
        }
        if (root_sidx) {
                sidx_rewrite(root_sidx, movie->editFileMap->bs, sidx_start);
                gf_isom_box_del((GF_Box*)root_sidx);
        }
 
+       if ((root_sidx || sidx) && !daisy_chain_sidx) {
+               if (index_start_range) *index_start_range = sidx_start;
+               if (index_end_range) *index_end_range = sidx_end;
+       }
+
        if (movie->append_segment) {
                char bloc[1024];
                u32 seg_size = (u32) gf_bs_get_size(movie->editFileMap->bs);
@@ -1004,7 +1306,7 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 frags_per_sidx, u32 referenc
 GF_Err gf_isom_close_fragments(GF_ISOFile *movie)
 {
        if (movie->use_segments) {
-               return gf_isom_close_segment(movie, 0, 0, 0, 0, 1);
+               return gf_isom_close_segment(movie, 0, 0, 0, 0, 0, 1, NULL, NULL);
        } else {
                return StoreFragment(movie, 0, 0, NULL);
        }
@@ -1026,13 +1328,14 @@ GF_Err gf_isom_start_segment(GF_ISOFile *movie, char *SegName)
                gf_isom_datamap_del(movie->editFileMap);
                e = gf_isom_datamap_new(SegName, NULL, GF_ISOM_DATA_MAP_WRITE, & movie->editFileMap);
                movie->segment_start = 0;
-               return e;
-       }       
-       assert(gf_list_count(movie->moof_list) == 0);
-       movie->segment_start = gf_bs_get_position(movie->editFileMap->bs);
-       /*if movieFileMap is not null, we are concatenating segments to the original move, force a copy*/
-       if (movie->movieFileMap)
-               movie->append_segment = 1;
+               if (e) return e;
+       } else {
+               assert(gf_list_count(movie->moof_list) == 0);
+               movie->segment_start = gf_bs_get_position(movie->editFileMap->bs);
+               /*if movieFileMap is not null, we are concatenating segments to the original move, force a copy*/
+               if (movie->movieFileMap)
+                       movie->append_segment = 1;
+       }
        return GF_OK;
 }
 
@@ -1062,20 +1365,6 @@ GF_Err gf_isom_start_fragment(GF_ISOFile *movie, Bool moof_first)
                if (e) return e;
        }
        
-    /* Inserting free data for testing HTTP streaming */
-#if 0
-       if (0) {
-        GF_FreeSpaceBox *fb = (GF_FreeSpaceBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_FREE);
-        fb->dataSize = free_data_insert_size;
-        //gf_list_add(movie->TopBoxes, fb);
-           e = gf_isom_box_size((GF_Box *) fb);
-           if (e) return e;
-           e = gf_isom_box_write((GF_Box *) fb, movie->editFileMap->bs);
-           if (e) return e;
-        gf_isom_box_del((GF_Box *)fb);
-    }
-#endif
-
        //create new fragment
        movie->moof = (GF_MovieFragmentBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MOOF);
        movie->moof->mfhd = (GF_MovieFragmentHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MFHD);
@@ -1310,34 +1599,66 @@ GF_Err gf_isom_fragment_copy_subsample(GF_ISOFile *dest, u32 TrackID, GF_ISOFile
        u32 i, count, last_sample;
        GF_SampleEntry *sub_sample;
        GF_Err e;
+       GF_TrackBox *trak;
        GF_TrackFragmentBox *traf;
        if (!dest->moof || !(dest->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;
 
-       if (! gf_isom_sample_get_subsample_entry(orig, track, sampleNumber, &sub_sample)) return GF_OK;
-
        traf = GetTraf(dest, TrackID);
        if (!traf || !traf->tfhd->sample_desc_index) return GF_BAD_PARAM;
 
-       /*compute last sample number in traf*/
-       last_sample = 0;
-       count = gf_list_count(traf->TrackRuns);
-       for (i=0; i<count; i++) {
-               GF_TrackFragmentRunBox *trun = gf_list_get(traf->TrackRuns, i);
-               last_sample += trun->sample_count;
-       }
+       trak = gf_isom_get_track_from_file(orig, track);
+       if (!trak) return GF_BAD_PARAM;
 
-       /*create subsample if needed*/
-       if (!traf->subs) {
-               traf->subs = (GF_SubSampleInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SUBS);
-               traf->subs->version = 0;
+       /*copy subsample info if any*/
+       if ( gf_isom_sample_get_subsample_entry(orig, track, sampleNumber, &sub_sample)) {
+               if (!traf || !traf->tfhd->sample_desc_index) return GF_BAD_PARAM;
+
+               /*compute last sample number in traf*/
+               last_sample = 0;
+               count = gf_list_count(traf->TrackRuns);
+               for (i=0; i<count; i++) {
+                       GF_TrackFragmentRunBox *trun = gf_list_get(traf->TrackRuns, i);
+                       last_sample += trun->sample_count;
+               }
+
+               /*create subsample if needed*/
+               if (!traf->subs) {
+                       traf->subs = (GF_SubSampleInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SUBS);
+                       traf->subs->version = 0;
+               }
+               
+
+               count = gf_list_count(sub_sample->SubSamples);
+               for (i=0; i<count; i++) {
+                       GF_SubSampleEntry *entry = gf_list_get(sub_sample->SubSamples, i);
+                       e = gf_isom_add_subsample_info(traf->subs, last_sample, entry->subsample_size, entry->subsample_priority, entry->reserved, entry->discardable);
+                       if (e) return e;
+               }
        }
-       
+       /*copy sampleToGroup info if any*/
+       if (trak->Media->information->sampleTable->sampleGroups) {
+               count = gf_list_count(trak->Media->information->sampleTable->sampleGroups);
+               for (i=0; i<count; i++) {
+                       GF_SampleGroupBox *sg;
+                       u32 j;
+                       u32 first_sample_in_entry, last_sample_in_entry;
+                       first_sample_in_entry = 1;
+                       
+                       sg = gf_list_get(trak->Media->information->sampleTable->sampleGroups, i);
+                       for (j=0; j<sg->entry_count; j++) {
+                               last_sample_in_entry = first_sample_in_entry + sg->sample_entries[j].sample_count - 1;
+                               if ((sampleNumber<first_sample_in_entry) || (sampleNumber>last_sample_in_entry)) {
+                                       first_sample_in_entry = last_sample_in_entry+1;
+                                       continue;
+                               }
+                               /*found our sample, add it to trak->sampleGroups*/
+                               if (!traf->sampleGroups)
+                                       traf->sampleGroups = gf_list_new();
 
-       count = gf_list_count(sub_sample->SubSamples);
-       for (i=0; i<count; i++) {
-               GF_SubSampleEntry *entry = gf_list_get(sub_sample->SubSamples, i);
-               e = gf_isom_add_subsample_info(traf->subs, last_sample, entry->subsample_size, entry->subsample_priority, entry->reserved, entry->discardable);
-               if (e) return e;
+                               e = gf_isom_add_sample_group_entry(traf->sampleGroups, 0, sg->grouping_type, sg->sample_entries[j].group_description_index);
+                               break;
+                       }
+               }
        }
        return GF_OK;
 }
index 51f8e258501d3eb5524307ea2df8782c06eecdee..49a239d35f8430d0dd114f5e1eb5cbc78378e9f2 100644 (file)
@@ -223,11 +223,10 @@ GF_Err stbl_GetSampleDTS(GF_TimeToSampleBox *stts, u32 SampleNumber, u64 *DTS)
 {
        return stbl_GetSampleDTS_and_Duration(stts, SampleNumber, DTS, NULL);
 }
-//Set the RAP flag of a sample
+//Retrieve closes RAP for a given sample - if sample is RAP, sets the RAP flag
 GF_Err stbl_GetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 *IsRAP, u32 *prevRAP, u32 *nextRAP)
 {
        u32 i;
-
        if (prevRAP) *prevRAP = 0;
        if (nextRAP) *nextRAP = 0;
 
@@ -256,6 +255,99 @@ GF_Err stbl_GetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 *IsRAP, u3
        return GF_OK;
 }
 
+GF_Err stbl_SearchSAPs(GF_SampleTableBox *stbl, u32 SampleNumber, u8 *IsRAP, u32 *prevRAP, u32 *nextRAP)
+{
+       u32 i, j, count, count2;
+       assert(prevRAP);
+       assert(nextRAP);
+       (*IsRAP) = 0;
+
+       if (!stbl->sampleGroups || !stbl->sampleGroupsDescription) return GF_OK;
+
+       count = gf_list_count(stbl->sampleGroups);
+       count2 = gf_list_count(stbl->sampleGroupsDescription);
+       for (i=0; i<count; i++) {
+               GF_SampleGroupDescriptionBox *sgdp = NULL;
+               Bool is_rap_group = 0;
+               s32 roll_distance = 0;
+               u32 first_sample_in_entry, last_sample_in_entry;
+               GF_SampleGroupBox *sg = gf_list_get(stbl->sampleGroups, i);
+               switch (sg->grouping_type) {
+               case GF_4CC('r','a','p',' '):
+                       is_rap_group = 1;
+                       break;
+               case GF_4CC('r','o','l','l'):
+                       break;
+               default:
+                       continue;
+               }
+               for (j=0; j<count2; j++) {
+                       sgdp = gf_list_get(stbl->sampleGroupsDescription, j);
+                       if (sgdp->grouping_type==sg->grouping_type) break;
+                       sgdp = NULL;
+               }
+               if (! sgdp) continue;
+                       
+               first_sample_in_entry=1;
+               for (j=0; j<sg->entry_count; j++) {
+                       u32 first_rap_in_entry, last_rap_in_entry;
+                       last_sample_in_entry = first_sample_in_entry + sg->sample_entries[j].sample_count - 1;
+
+                       /*samples in this entry are not RAPs, continue*/
+                       if (! sg->sample_entries[j].group_description_index) {
+                               first_sample_in_entry += sg->sample_entries[j].sample_count;
+                               continue;
+                       }
+                       if (!is_rap_group) {
+                               GF_RollRecoveryEntry *entry = gf_list_get(sgdp->group_descriptions, sg->sample_entries[j].group_description_index - 1);
+                               roll_distance = entry ? entry->roll_distance : 0;
+                       }
+
+                       /*we consider the first sample in a roll or rap group entry to be the RAP (eg, we have to decode from this sample anyway)
+                       except if roll_distance is strictly negative in which case we have to rewind our sample numbers from roll_distance*/
+                       if (roll_distance < 0) {
+                               if ((s32) first_sample_in_entry + roll_distance>=0) first_rap_in_entry = first_sample_in_entry + roll_distance;
+                               else first_rap_in_entry = 0;
+
+                               if ((s32) last_sample_in_entry + roll_distance>=0) last_rap_in_entry = last_sample_in_entry + roll_distance;
+                               else last_rap_in_entry = 0;
+                       } else {
+                               first_rap_in_entry = first_sample_in_entry;
+                               last_rap_in_entry = last_sample_in_entry;
+                       }
+
+                       /*store previous & next sample RAP - note that we do not store the closest previous RAP, only the first of the previous RAP group
+                       as RAPs are usually isolated this should not be an issue*/
+                       if (prevRAP && (first_rap_in_entry <= SampleNumber)) {
+                               *prevRAP = first_rap_in_entry;
+                       }
+                       if (nextRAP) {
+                               *nextRAP = last_rap_in_entry;
+                       }
+                       
+                       /*sample lies in this (rap) group, it is rap*/
+                       if (is_rap_group) {
+                               if ((first_rap_in_entry <= SampleNumber) && (SampleNumber <= last_rap_in_entry)) {
+                                       (*IsRAP) = 1;
+                                       return GF_OK;
+                               }
+                       } else {
+                               /*prevRAP or nextRAP matches SampleNumber, sample is RAP*/
+                               if ((*prevRAP == SampleNumber) || (*nextRAP == SampleNumber)) {
+                                       (*IsRAP) = 1;
+                                       return GF_OK;
+                               }
+                       }
+
+                       /*first sample in entry is after our target sample, abort*/
+                       if (first_rap_in_entry > SampleNumber) {
+                               break;
+                       }
+               }
+       }
+       return GF_OK;
+}
+
 //get the number of "ghost chunk" (implicit chunks described by an entry)
 void GetGhostNum(GF_StscEntry *ent, u32 EntryIndex, u32 count, GF_SampleTableBox *stbl)
 {
index c4b6e1b79a277e9d97ee0a7b1d23d8c37019bd17..9ed4a7672ba5f48e80ee5597549253bdce35dd9a 100644 (file)
@@ -731,9 +731,8 @@ GF_Err stbl_SetSampleSize(GF_SampleSizeBox *stsz, u32 SampleNumber, u32 size)
 
 GF_Err stbl_SetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 isRAP)
 {
-       u32 i, nextSamp;
+       u32 i;
 
-       nextSamp = 0;
        //check if we have already a sync sample
        for (i = 0; i < stss->nb_entries; i++) {
 
index ef03064d521f92f4cf7921d27b88bd5b44160305..3534b8013e938f1bef8a630490b4d4e8b51b8f36 100644 (file)
@@ -358,19 +358,27 @@ GF_Err SetTrackDuration(GF_TrackBox *trak)
        e = Media_SetDuration(trak);
        if (e) return e;
 
+       //assert the timeScales are non-NULL
+       if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE;
+       trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale;
+
        //if we have an edit list, the duration is the sum of all the editList 
        //entries' duration (always expressed in MovieTimeScale)
-       if (trak->editBox && trak->editBox->editList) {
+       if (trak->editBox && !trak->editBox->last_is_empty && trak->editBox->editList) {
                trackDuration = 0;
                elst = trak->editBox->editList;
                i=0;
                while ((ent = (GF_EdtsEntry*)gf_list_enum(elst->entryList, &i))) {
                        trackDuration += ent->segmentDuration;
+                       if (ent->mediaRate && !ent->segmentDuration) {
+                               trak->editBox->last_is_empty = 1;
+                       }
+               }
+
+               if (trak->editBox->last_is_empty) {
+                       ent = (GF_EdtsEntry*) gf_list_last(elst->entryList);
+                       ent->segmentDuration = trackDuration;
                }
-       } else {
-               //assert the timeScales are non-NULL
-               if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE;
-               trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale;
        }
        trak->Header->duration = trackDuration;
        trak->Header->modificationTime = gf_isom_get_mp4time();
@@ -483,6 +491,80 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset,
                        if (degr) stbl_AppendDegradation(trak->Media->information->sampleTable, degr);
                }
        }
+       /*merge sample groups*/
+       if (traf->sampleGroups) {
+               GF_List *groups;
+               GF_List *groupDescs;
+               if (!trak->Media->information->sampleTable->sampleGroups)
+                       trak->Media->information->sampleTable->sampleGroups = gf_list_new();
+
+               if (!trak->Media->information->sampleTable->sampleGroupsDescription)
+                       trak->Media->information->sampleTable->sampleGroupsDescription = gf_list_new();
+
+               groupDescs = trak->Media->information->sampleTable->sampleGroupsDescription;
+               for (i=0; i<gf_list_count(traf->sampleGroupsDescription); i++) {
+                       GF_SampleGroupDescriptionBox *new_sgdesc = NULL;
+                       GF_SampleGroupDescriptionBox *sgdesc = gf_list_get(traf->sampleGroupsDescription, i);
+                       for (j=0; j<gf_list_count(groupDescs); j++) {
+                               new_sgdesc = gf_list_get(groupDescs, j);
+                               if (new_sgdesc->grouping_type==sgdesc->grouping_type) break;
+                               new_sgdesc = NULL;
+                       }
+                       /*new description, move it to our sample table*/
+                       if (!new_sgdesc) {
+                               gf_list_add(groupDescs, sgdesc);
+                               gf_list_rem(traf->sampleGroupsDescription, i);
+                               i--;
+                       }
+                       /*merge descriptions*/
+                       else {
+                               u32 idx = gf_list_count(new_sgdesc->group_descriptions);
+                               for (j=idx; j<gf_list_count(sgdesc->group_descriptions); j++) {
+                                       void *ptr = gf_list_get(sgdesc->group_descriptions, j);
+                                       if (ptr) {
+                                               gf_list_add(new_sgdesc->group_descriptions, ptr);
+                                               gf_list_rem(sgdesc->group_descriptions, j);
+                                               j--;
+                                       }
+                               }
+                       }
+               }
+
+               groups = trak->Media->information->sampleTable->sampleGroups;
+               for (i=0; i<gf_list_count(traf->sampleGroups); i++) {
+                       GF_SampleGroupBox *stbl_group = NULL; 
+                       GF_SampleGroupBox *frag_group = gf_list_get(traf->sampleGroups, i);
+
+
+                       for (j=0; j<gf_list_count(groups); j++) {
+                               stbl_group = gf_list_get(groups, j);
+                               if ((frag_group->grouping_type==stbl_group->grouping_type) && (frag_group->grouping_type_parameter==stbl_group->grouping_type_parameter))
+                                       break;
+                               stbl_group = NULL;
+                       }
+                       if (!stbl_group) {
+                               stbl_group = (GF_SampleGroupBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SBGP);
+                               stbl_group->grouping_type = frag_group->grouping_type;
+                               stbl_group->grouping_type_parameter = frag_group->grouping_type_parameter;
+                               stbl_group->version = frag_group->version;
+                               gf_list_add(groups, stbl_group);
+                       }
+                       if (frag_group->entry_count && stbl_group->entry_count && 
+                               (frag_group->sample_entries[0].group_description_index==stbl_group->sample_entries[stbl_group->entry_count-1].group_description_index) 
+                       ) {
+                               stbl_group->sample_entries[stbl_group->entry_count - 1].sample_count += frag_group->sample_entries[0].sample_count;
+                               if (frag_group->entry_count>1) {
+                                       stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count - 1));
+                                       memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[1], sizeof(GF_SampleGroupEntry) * (frag_group->entry_count - 1));
+                                       stbl_group->entry_count += frag_group->entry_count - 1;
+                               }
+                       } else {
+                               stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count));
+                               memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[0], sizeof(GF_SampleGroupEntry) * frag_group->entry_count);
+                               stbl_group->entry_count += frag_group->entry_count;
+                       }
+               }
+       }
        return GF_OK;
 }
 
@@ -534,7 +616,6 @@ GF_Err NewMedia(GF_MediaBox **mdia, u32 MediaType, u32 TimeScale)
        GF_MediaInformationBox *minf;
        GF_DataInformationBox *dinf;
        GF_SampleTableBox *stbl;
-       GF_SampleDescriptionBox *stsd;
        GF_DataReferenceBox *dref;
        char *str;
 
@@ -548,7 +629,6 @@ GF_Err NewMedia(GF_MediaBox **mdia, u32 MediaType, u32 TimeScale)
        hdlr = NULL;
        dinf = NULL;
        stbl = NULL;
-       stsd = NULL;
        dref = NULL;
        mediaInfo = NULL;
 
index 86bc80359260c60e219453124705d7bd61ec1077..7b5dd8db8d233f3918bc8f49309eed0d80c0cc26 100644 (file)
@@ -4075,7 +4075,6 @@ static void *lsr_read_update_value_indexed(GF_LASeRCodec *lsr, GF_Node*node, u32
 static void lsr_read_update_value(GF_LASeRCodec *lsr, GF_Node *node, u32 att_tag, u32 fieldType, void *val, u32 node_tag)
 {
        u32 is_default, has_escape, escape_val = 0;
-       SVG_Paint *paint;
        SVG_Number num, *n;
        is_default = has_escape = 0;
 
@@ -4084,7 +4083,6 @@ static void lsr_read_update_value(GF_LASeRCodec *lsr, GF_Node *node, u32 att_tag
                GF_LSR_READ_INT(lsr, *(SVG_Boolean*)val, 1, "val");
                break;
        case SVG_Paint_datatype:
-               paint = (SVG_Paint *)val;
                lsr_read_paint(lsr, (SVG_Paint*)val, "val");
                break;
 /*
@@ -4951,7 +4949,6 @@ static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_E
 {
        GF_Node *n;
        GF_Command *com;
-       GF_Err e;
        u32 i, type, count;
 
        if (cond) {
@@ -4984,10 +4981,10 @@ static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_E
                case LSR_UPDATE_ADD:
                case LSR_UPDATE_INSERT:
                case LSR_UPDATE_REPLACE:
-                       e = lsr_read_add_replace_insert(lsr, com_list, type);
+                       lsr_read_add_replace_insert(lsr, com_list, type);
                        break;
                case LSR_UPDATE_DELETE:
-                       e = lsr_read_delete(lsr, com_list);
+                       lsr_read_delete(lsr, com_list);
                        break;
                case LSR_UPDATE_NEW_SCENE:
                case LSR_UPDATE_REFRESH_SCENE: /*TODO FIXME, depends on decoder state*/
@@ -5013,24 +5010,24 @@ static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_E
                        lsr_read_byte_align_string(lsr, NULL, "textContent");
                        break;
                case LSR_UPDATE_SEND_EVENT:
-                       e = lsr_read_send_event(lsr, com_list);
+                       lsr_read_send_event(lsr, com_list);
                        break;
                case LSR_UPDATE_RESTORE:
-                       e = lsr_read_restore(lsr, com_list);
+                       lsr_read_restore(lsr, com_list);
                        break;
                case LSR_UPDATE_SAVE:
-                       e = lsr_read_save(lsr, com_list);
+                       lsr_read_save(lsr, com_list);
                        break;
                case LSR_UPDATE_EXTEND:
                {
-                       u32 extID, len;
+                       u32 extID;
                        GF_Node *n;
                        GF_LSR_READ_INT(lsr, extID, lsr->info->cfg.extensionIDBits, "extensionID");
-                       len = lsr_read_vluimsbf5(lsr, "len");
+                       /*len = */lsr_read_vluimsbf5(lsr, "len");
                        if (extID==2) {
-                               u32 j, sub_count;
+                               u32 j;
                                lsr_read_vluimsbf5(lsr, "reserved");
-                               sub_count = lsr_read_vluimsbf5(lsr, "occ2");
+                               /*sub_count = */lsr_read_vluimsbf5(lsr, "occ2");
                                for (j=0; j<count; j++) {
                                        u32 k, occ3;
                                        GF_LSR_READ_INT(lsr, k, 2, "reserved");
index dc17e9451319c24fcc9baa3be5c4bd8dbf5e03a2..11981da1932a401c542393228923ff1e3bb45ac0 100644 (file)
@@ -1580,12 +1580,11 @@ static void lsr_write_an_anim_value(GF_LASeRCodec *lsr, void *val, u32 lsr_type,
                                lsr_write_fixed_16_8(lsr, v->value, "val");
                        }
                } else if (svg_type==SVG_Transform_Rotate_datatype) {
-                       Fixed angle;
                        SVG_Point_Angle *p = (SVG_Point_Angle *)val;
+                       Fixed angle = gf_muldiv(p->angle, INT2FIX(180), GF_PI);
                        count = (p->x || p->y) ? 3 : 1;
                        lsr_write_vluimsbf5(lsr, count, "count");
-                       angle = gf_muldiv(p->angle, INT2FIX(180), GF_PI);
-                       lsr_write_fixed_16_8(lsr, p->angle, "val");
+                       lsr_write_fixed_16_8(lsr, angle, "val");
                        if (count==3) {
                                lsr_write_fixed_16_8(lsr, p->x, "val");
                                lsr_write_fixed_16_8(lsr, p->y, "val");
@@ -3481,9 +3480,7 @@ static GF_Err lsr_write_add_replace_insert(GF_LASeRCodec *lsr, GF_Command *com)
        }
        if (type!=LSR_UPDATE_INSERT) {
                if (com->fromNodeID) {
-                       GF_Node *opNode;
                        u8 opAttType;
-                       opNode = gf_sg_find_node(lsr->sg, com->fromNodeID);
                        opAttType = gf_lsr_anim_type_from_attribute(com->fromFieldIndex);
                        GF_LSR_WRITE_INT(lsr, 1, 1, "has_operandAttribute");
                        GF_LSR_WRITE_INT(lsr, opAttType, 8, "operandAttribute");
diff --git a/src/media_tools/ait.c b/src/media_tools/ait.c
new file mode 100644 (file)
index 0000000..8adb546
--- /dev/null
@@ -0,0 +1,774 @@
+/* \r
+ * Copyright (c) TELECOM ParisTech 2011\r
+ */\r
+\r
+#include <gpac/ait.h>\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
+/* static functions */\r
+static Bool check_ait_already_received(GF_List* ChannelAppList,u32 pid,char* data);\r
+static void gf_ait_application_decode_destroy(GF_M2TS_AIT_APPLICATION_DECODE* application_decode);\r
+static GF_Err gf_m2ts_decode_ait(GF_M2TS_AIT *ait, char  *data, u32 data_size, u32 table_id);\r
+static Bool gf_m2ts_is_dmscc_app(GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo);\r
+static void gf_m2ts_free_ait_application(GF_M2TS_AIT_APPLICATION* application);\r
+static void gf_ait_destroy(GF_M2TS_AIT* ait);\r
+static void gf_m2ts_process_ait(GF_M2TS_Demuxer *ts, GF_M2TS_AIT* ait);\r
+\r
+GF_M2TS_ES *gf_ait_section_new(u32 service_id)\r
+{\r
+       GF_M2TS_ES *es;\r
+       GF_M2TS_AIT_CARRY *ses;\r
+       GF_SAFEALLOC(ses, GF_M2TS_AIT_CARRY);\r
+       es = (GF_M2TS_ES *)ses;\r
+       es->flags = GF_M2TS_ES_IS_SECTION;\r
+       ses->service_id = service_id;\r
+       return es;\r
+}\r
+\r
+\r
+void on_ait_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) \r
+{\r
+       GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)par;\r
+       char *data;\r
+       u32 u32_data_size;\r
+       u32 u32_table_id;\r
+\r
+       \r
+\r
+       if (evt_type == GF_M2TS_EVT_AIT_FOUND) {\r
+               GF_M2TS_AIT* ait;\r
+               GF_M2TS_AIT_CARRY* ait_carry = (GF_M2TS_AIT_CARRY*)pck->stream;\r
+               data = pck->data;\r
+\r
+               if(!check_ait_already_received(ts->ChannelAppList,ait_carry->pid,data)){\r
+                       GF_SAFEALLOC(ait, GF_M2TS_AIT);                 \r
+                       u32_data_size = pck->data_len;\r
+                       u32_table_id = data[0];         \r
+                       ait->pid = ait_carry->pid;\r
+                       ait->service_id = ait_carry->service_id;\r
+                       gf_m2ts_decode_ait(ait, data, u32_data_size, u32_table_id);\r
+                       gf_m2ts_process_ait(ts,ait);\r
+                       gf_ait_destroy(ait);\r
+                       if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_AIT_FOUND, pck->stream);\r
+               }\r
+               \r
+       }\r
+}\r
+\r
+static GF_Err gf_m2ts_decode_ait(GF_M2TS_AIT *ait, char  *data, u32 data_size, u32 table_id)\r
+{\r
+\r
+       GF_BitStream *bs;\r
+       u8 temp_descriptor_tag;\r
+       u32 data_shift, app_desc_data_shift, ait_app_data_shift;\r
+       u32 nb_of_protocol;\r
+\r
+       data_shift = 0;\r
+       temp_descriptor_tag = 0;\r
+       ait_app_data_shift = 0;\r
+       bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ);\r
+\r
+       ait->common_descriptors = gf_list_new();\r
+       if(ait->common_descriptors == NULL){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Error during common_descriptors list initialization, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       ait->application_decoded = gf_list_new();\r
+       if(ait->application_decoded == NULL){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Error during application list initialization, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+\r
+       ait->table_id = gf_bs_read_int(bs,8);   \r
+       ait->section_syntax_indicator = gf_bs_read_int(bs,1);\r
+       gf_bs_read_int(bs,3);\r
+       ait->section_length = gf_bs_read_int(bs,12);    \r
+       if( (data[1] & 0x0C) != 0){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length is not correct abroding \n"));\r
+       }else if( ait->section_length > AIT_SECTION_LENGTH_MAX){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length should not exceed 1021. Wrong section, abording processing \n"));\r
+       }\r
+       ait->test_application_flag = gf_bs_read_int(bs,1);\r
+       if(ait->test_application_flag == 1){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] test application flag is at 1. API transmitted for testing, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       ait->application_type = gf_bs_read_int(bs,15);  \r
+       if(ait->application_type != APPLICATION_TYPE_HTTP_APPLICATION){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] application type should 0x10. Wrong section, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       gf_bs_read_int(bs,2);\r
+       ait->version_number = gf_bs_read_int(bs,5);\r
+\r
+       ait->current_next_indicator = gf_bs_read_int(bs,1);     \r
+       if(!ait->current_next_indicator){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] current next indicator should be at 1 \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       ait->section_number = gf_bs_read_int(bs,8);\r
+       ait->last_section_number = gf_bs_read_int(bs,8);        \r
+       gf_bs_read_int(bs,4);/* bit shifting */\r
+       ait->common_descriptors_length = gf_bs_read_int(bs,12); \r
+       gf_bs_read_int(bs,(unsigned int)ait->common_descriptors_length/8);\r
+       gf_bs_read_int(bs,4);/* bit shifting */ \r
+       ait->application_loop_length = gf_bs_read_int(bs,12);\r
+\r
+       data_shift = (u32)(gf_bs_get_position(bs)) + ait->common_descriptors_length/8;\r
+\r
+       while (ait_app_data_shift < ait->application_loop_length) {\r
+\r
+               GF_M2TS_AIT_APPLICATION_DECODE* application;\r
+               GF_SAFEALLOC(application,GF_M2TS_AIT_APPLICATION_DECODE);\r
+               application->application_descriptors = gf_list_new();\r
+               application->index_app_desc_id = 0;\r
+\r
+               /* application loop */\r
+               application->organisation_id = gf_bs_read_int(bs,32);   \r
+               application->application_id= gf_bs_read_int(bs,16);\r
+               application->application_control_code= gf_bs_read_int(bs,8);\r
+               gf_bs_read_int(bs,4);/* bit shifting */\r
+               application->application_descriptors_loop_length= gf_bs_read_int(bs,12);                \r
+\r
+               ait_app_data_shift += 9;\r
+               app_desc_data_shift = 0;\r
+               nb_of_protocol = 0;\r
+\r
+               while (app_desc_data_shift< application->application_descriptors_loop_length) {\r
+                       temp_descriptor_tag = gf_bs_read_int(bs,8);\r
+                       switch (temp_descriptor_tag) {\r
+                               case APPLICATION_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;\r
+                                               u8 i;\r
+                                               GF_M2TS_APPLICATION_DESCRIPTOR *application_descriptor;\r
+                                               GF_SAFEALLOC(application_descriptor, GF_M2TS_APPLICATION_DESCRIPTOR);\r
+                                               application_descriptor->descriptor_tag = temp_descriptor_tag;\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               application_descriptor->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               application_descriptor->application_profiles_length = gf_bs_read_int(bs,8);\r
+                                               application_descriptor->application_profile = gf_bs_read_int(bs,16);\r
+                                               application_descriptor->version_major = gf_bs_read_int(bs,8);\r
+                                               application_descriptor->version_minor = gf_bs_read_int(bs,8);\r
+                                               application_descriptor->version_micro = gf_bs_read_int(bs,8);\r
+                                               application_descriptor->service_bound_flag = gf_bs_read_int(bs,1);\r
+                                               application_descriptor->visibility = gf_bs_read_int(bs,2);\r
+                                               gf_bs_read_int(bs,5); /*bit shift*/\r
+                                               application_descriptor->application_priority = gf_bs_read_int(bs,8);\r
+                                               if (nb_of_protocol > 0) {\r
+                                                       for (i=0; i<nb_of_protocol; i++) {                                              \r
+                                                               application_descriptor->transport_protocol_label[i] = gf_bs_read_int(bs,8);\r
+                                                       }\r
+                                               } else {\r
+                                                       application_descriptor->transport_protocol_label[0] = gf_bs_read_int(bs,8);\r
+                                               }\r
+                                               if (pre_processing_pos+application_descriptor->descriptor_length != gf_bs_get_position(bs) || application_descriptor->application_profile == 2 /* PVR feature */) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),application_descriptor->descriptor_length));\r
+                                                       gf_free(application_descriptor);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,application_descriptor);\r
+                                               app_desc_data_shift += (2+ application_descriptor->descriptor_length);\r
+                                               break;\r
+                                       }\r
+                               case APPLICATION_NAME_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;\r
+                                               GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor;\r
+                                               GF_SAFEALLOC(name_descriptor, GF_M2TS_APPLICATION_NAME_DESCRIPTOR);\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               name_descriptor->descriptor_tag = temp_descriptor_tag;\r
+                                               name_descriptor->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               name_descriptor->ISO_639_language_code = gf_bs_read_int(bs,24);\r
+                                               name_descriptor->application_name_length = gf_bs_read_int(bs,8);\r
+                                               name_descriptor->application_name_char = (char*) gf_calloc(name_descriptor->application_name_length+1,sizeof(char));\r
+                                               gf_bs_read_data(bs,name_descriptor->application_name_char,name_descriptor->application_name_length);\r
+                                               name_descriptor->application_name_char[name_descriptor->application_name_length] = 0 ;\r
+                                               if (pre_processing_pos+name_descriptor->descriptor_length != gf_bs_get_position(bs)) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),name_descriptor->descriptor_length));\r
+                                                       gf_free(name_descriptor->application_name_char);\r
+                                                       gf_free(name_descriptor);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,name_descriptor);\r
+                                               app_desc_data_shift += (2+ name_descriptor->descriptor_length);\r
+                                               break;\r
+                                       }\r
+                               case TRANSPORT_PROTOCOL_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;\r
+                                               GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor;\r
+                                               GF_SAFEALLOC(protocol_descriptor, GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR);\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               nb_of_protocol++;\r
+                                               protocol_descriptor->descriptor_tag = temp_descriptor_tag;\r
+                                               protocol_descriptor->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               protocol_descriptor->protocol_id = gf_bs_read_int(bs,16);\r
+                                               protocol_descriptor->transport_protocol_label = gf_bs_read_int(bs,8);\r
+                                               switch (protocol_descriptor->protocol_id) {\r
+                               case CAROUSEL:\r
+                                       {\r
+                                               GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte;\r
+                                               GF_SAFEALLOC(Carousel_selector_byte, GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE);\r
+                                               Carousel_selector_byte->remote_connection = gf_bs_read_int(bs,1);\r
+                                               gf_bs_read_int(bs,7); /* bit shifting */\r
+                                               if (Carousel_selector_byte->remote_connection) {\r
+                                                       Carousel_selector_byte->original_network_id = gf_bs_read_int(bs,16);\r
+                                                       Carousel_selector_byte->transport_stream_id = gf_bs_read_int(bs,16);\r
+                                                       Carousel_selector_byte->service_id = gf_bs_read_int(bs,16);\r
+                                               }\r
+                                               Carousel_selector_byte->component_tag = gf_bs_read_int(bs,8);\r
+                                               protocol_descriptor->selector_byte = Carousel_selector_byte;\r
+                                               break;\r
+                                       }\r
+                               case TRANSPORT_HTTP:\r
+                                       {                                       \r
+                                               u32 i;                                                          \r
+                                               GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte;\r
+                                               GF_SAFEALLOC(Transport_http_selector_byte, GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE);                                       \r
+                                               Transport_http_selector_byte->URL_base_length = gf_bs_read_int(bs,8);\r
+                                               //printf("Transport_http_selector_byte->URL_base_length %d \n",Transport_http_selector_byte->URL_base_length);\r
+                                               Transport_http_selector_byte->URL_base_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_base_length+1,sizeof(char));\r
+                                               gf_bs_read_data(bs,Transport_http_selector_byte->URL_base_byte ,(u32)(Transport_http_selector_byte->URL_base_length));\r
+                                               Transport_http_selector_byte->URL_base_byte[Transport_http_selector_byte->URL_base_length] = 0;\r
+                                               Transport_http_selector_byte->URL_extension_count = gf_bs_read_int(bs,8);\r
+                                               if (Transport_http_selector_byte->URL_extension_count) {\r
+                                                       Transport_http_selector_byte->URL_extentions = (GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION*) gf_calloc(Transport_http_selector_byte->URL_extension_count,sizeof(GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION));\r
+                                                       for (i=0; i < Transport_http_selector_byte->URL_extension_count;i++) {\r
+                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_length = gf_bs_read_int(bs,8);\r
+                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_extentions[i].URL_extension_length+1,sizeof(char));\r
+                                                               gf_bs_read_data(bs,Transport_http_selector_byte->URL_extentions[i].URL_extension_byte,(u32)(Transport_http_selector_byte->URL_extentions[i].URL_extension_length));\r
+                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_byte[Transport_http_selector_byte->URL_extentions[i].URL_extension_length] = 0;\r
+                                                       }\r
+                                               }\r
+                                               protocol_descriptor->selector_byte = Transport_http_selector_byte;\r
+                                               break;\r
+                                       }\r
+                               default:\r
+                                       {\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Protocol ID %d unsupported, ignoring the selector byte \n",protocol_descriptor->protocol_id));\r
+                                       }\r
+                                               }\r
+                                               if (pre_processing_pos+protocol_descriptor->descriptor_length != gf_bs_get_position(bs)) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),protocol_descriptor->descriptor_length));\r
+                                                       if (protocol_descriptor->protocol_id == CAROUSEL) {                                             \r
+                                                               GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte = (GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE*) protocol_descriptor->selector_byte;                                                            \r
+                                                               gf_free(Carousel_selector_byte);                                                                \r
+                                                       } else if(protocol_descriptor->protocol_id ==TRANSPORT_HTTP) {\r
+                                                               u32 i;\r
+                                                               GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte = (GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE*) protocol_descriptor->selector_byte;                                                                \r
+                                                               gf_free(Transport_http_selector_byte->URL_base_byte);\r
+                                                               for(i = 0; i < Transport_http_selector_byte->URL_extension_count;i++){                                                                          \r
+                                                                       gf_free(Transport_http_selector_byte->URL_extentions[i].URL_extension_byte);\r
+                                                               }\r
+                                                               gf_free(Transport_http_selector_byte);                                          \r
+                                                       }\r
+                                                       gf_free(protocol_descriptor);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,protocol_descriptor);                                  \r
+                                               app_desc_data_shift += (2+ protocol_descriptor->descriptor_length);\r
+                                               break;\r
+                                       }\r
+                               case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;                                 \r
+                                               GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location;\r
+                                               GF_SAFEALLOC(Simple_application_location, GF_M2TS_SIMPLE_APPLICATION_LOCATION);\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               Simple_application_location->descriptor_tag = temp_descriptor_tag;\r
+                                               Simple_application_location->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               Simple_application_location->initial_path_bytes = (char*)gf_calloc(Simple_application_location->descriptor_length+1,sizeof(char));\r
+                                               gf_bs_read_data(bs,Simple_application_location->initial_path_bytes ,(u32)(Simple_application_location->descriptor_length));\r
+                                               Simple_application_location->initial_path_bytes[Simple_application_location->descriptor_length] = 0;\r
+                                               if (pre_processing_pos+Simple_application_location->descriptor_length != gf_bs_get_position(bs)) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),Simple_application_location->descriptor_length));\r
+                                                       gf_free(Simple_application_location->initial_path_bytes);\r
+                                                       gf_free(Simple_application_location);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,Simple_application_location);\r
+                                               app_desc_data_shift += (2+ Simple_application_location->descriptor_length);\r
+                                               break;\r
+                                       }\r
+                               case APPLICATION_USAGE_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;\r
+                                               GF_M2TS_APPLICATION_USAGE* Application_usage;\r
+                                               GF_SAFEALLOC(Application_usage, GF_M2TS_APPLICATION_USAGE);\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               Application_usage->descriptor_tag = temp_descriptor_tag;\r
+                                               Application_usage->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               Application_usage->usage_type = gf_bs_read_int(bs,8);\r
+                                               if (pre_processing_pos+Application_usage->descriptor_length != gf_bs_get_position(bs)) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),Application_usage->descriptor_length));\r
+                                                       gf_free(Application_usage);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,Application_usage);\r
+                                               app_desc_data_shift += (2+ Application_usage->descriptor_length);\r
+                                               break;\r
+                                       }\r
+                               case APPLICATION_BOUNDARY_DESCRIPTOR:\r
+                                       {\r
+                                               u64 pre_processing_pos;\r
+                                               u32 i;\r
+                                               GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR* boundary_descriptor;\r
+                                               GF_SAFEALLOC(boundary_descriptor, GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR);\r
+                                               application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;\r
+                                               application->index_app_desc_id++;\r
+                                               boundary_descriptor->descriptor_tag = temp_descriptor_tag;\r
+                                               boundary_descriptor->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               pre_processing_pos = gf_bs_get_position(bs);\r
+                                               boundary_descriptor->boundary_extension_count = gf_bs_read_int(bs,8);\r
+                                               if (boundary_descriptor->boundary_extension_count > 0) {\r
+                                                       boundary_descriptor->boundary_extension_info = (GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO*)gf_calloc(boundary_descriptor->boundary_extension_count,sizeof(GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO));\r
+                                                       for (i=0;i<boundary_descriptor->boundary_extension_count;i++) {\r
+                                                               boundary_descriptor->boundary_extension_info[i].boundary_extension_length = gf_bs_read_int(bs,8);\r
+                                                               if (boundary_descriptor->boundary_extension_info[i].boundary_extension_length > 0) {\r
+                                                                       boundary_descriptor->boundary_extension_info[i].boundary_extension_byte = (char*)gf_calloc(boundary_descriptor->boundary_extension_info[i].boundary_extension_length+1,sizeof(char));\r
+                                                                       gf_bs_read_data(bs,boundary_descriptor->boundary_extension_info[i].boundary_extension_byte ,(u32)(boundary_descriptor->boundary_extension_info[i].boundary_extension_length));\r
+                                                                       boundary_descriptor->boundary_extension_info[i].boundary_extension_byte[boundary_descriptor->boundary_extension_info[i].boundary_extension_length] = 0;\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                               if (pre_processing_pos+boundary_descriptor->descriptor_length != gf_bs_get_position(bs)) {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),boundary_descriptor->descriptor_length));\r
+                                                       if (boundary_descriptor->boundary_extension_count > 0) {\r
+                                                               u32 i;\r
+                                                               for (i=0;i<boundary_descriptor->boundary_extension_count;i++) {\r
+                                                                       if (boundary_descriptor->boundary_extension_info[i].boundary_extension_length > 0) {\r
+                                                                               gf_free(boundary_descriptor->boundary_extension_info[i].boundary_extension_byte);\r
+                                                                       }\r
+                                                               }\r
+                                                               gf_free(boundary_descriptor->boundary_extension_info);\r
+                                                       }\r
+                                                       gf_free(boundary_descriptor);\r
+                                                       return GF_CORRUPTED_DATA;\r
+                                               }\r
+                                               gf_list_add(application->application_descriptors,boundary_descriptor);\r
+                                               app_desc_data_shift += (2+ boundary_descriptor->descriptor_length);\r
+                                               break;                                  \r
+                                       }\r
+                               default:\r
+                                       {\r
+                                               u8 length;\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor tag %d unknown, ignoring the descriptor \n",temp_descriptor_tag));\r
+                                               /* get descriptor's length */\r
+                                               length = gf_bs_read_int(bs,8);\r
+                                               /* bit shifting (eq descriptor's length)*/\r
+                                               gf_bs_read_int(bs,8*length);                                    \r
+                                       }\r
+\r
+                       }\r
+\r
+               }\r
+               ait_app_data_shift += application->application_descriptors_loop_length; \r
+               gf_list_add(ait->application_decoded,application);              \r
+       }\r
+\r
+       data_shift +=ait->application_loop_length;\r
+       ait->CRC_32 = gf_bs_read_int(bs,32);\r
+       data_shift += 4;\r
+\r
+\r
+       if (data_shift != data_size) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] AIT processed length error. Difference between byte shifting %d and data size %d \n",data_shift,data_size));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static void gf_m2ts_process_ait(GF_M2TS_Demuxer *ts, GF_M2TS_AIT* ait){\r
+\r
+       u32 nb_app_desc,k,desc_id;\r
+\r
+       u32 nb_of_app,j,i;\r
+       GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo;\r
+       char* url_base;\r
+       char* url_appli_path;\r
+\r
+       nb_of_app = gf_list_count(ait->application_decoded);\r
+       url_base = NULL;\r
+       url_appli_path = NULL;\r
+       j=0;    \r
+       i=0;\r
+\r
+       /* Link the AIT and the channel */\r
+       ChanAppInfo = gf_m2ts_get_channel_application_info(ts->ChannelAppList,ait->service_id); \r
+\r
+       if(!ChanAppInfo){\r
+               GF_SAFEALLOC(ChanAppInfo,GF_M2TS_CHANNEL_APPLICATION_INFO);\r
+               ChanAppInfo->service_id = ait->service_id;\r
+               ChanAppInfo->Application = gf_list_new();\r
+               ChanAppInfo->ait_pid = ait->pid;\r
+               gf_list_add(ts->ChannelAppList,ChanAppInfo);\r
+       }\r
+\r
+       ChanAppInfo->nb_application = nb_of_app;\r
+\r
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[DSMCC] ChanAppInfo->nb_application %d \n",ChanAppInfo->nb_application));\r
+       \r
+       for(j=0 ; j<nb_of_app ; j++){\r
+               GF_M2TS_AIT_APPLICATION* Application;\r
+               GF_M2TS_AIT_APPLICATION_DECODE* application_decoded;\r
+               GF_SAFEALLOC(Application,GF_M2TS_AIT_APPLICATION);\r
+               gf_list_add(ChanAppInfo->Application,Application);                      \r
+               Application->http_url = NULL;\r
+               Application->carousel_url = NULL;\r
+\r
+               application_decoded = (GF_M2TS_AIT_APPLICATION_DECODE*)gf_list_get(ait->application_decoded,j);\r
+               nb_app_desc = gf_list_count(application_decoded->application_descriptors);\r
+               Application->application_control_code = application_decoded->application_control_code;\r
+               Application->application_id = application_decoded->application_id;\r
+               Application->broadband = 0;\r
+               Application->broadcast = 0;\r
+               ChanAppInfo->version_number = ait->version_number;\r
+               \r
+               k=0;\r
+               for(k=0 ; k<nb_app_desc ; k++){\r
+                       desc_id = application_decoded->application_descriptors_id[k];\r
+                       switch(desc_id){\r
+                                                       case APPLICATION_DESCRIPTOR:\r
+                                                               {\r
+                                                                       GF_M2TS_APPLICATION_DESCRIPTOR* application_descriptor = (GF_M2TS_APPLICATION_DESCRIPTOR*)gf_list_get(application_decoded->application_descriptors,k);\r
+                                                                       Application->priority = application_descriptor->application_priority;\r
+                                                                       Application->application_profile = application_descriptor->application_profile;\r
+\r
+                                                                       break;\r
+                                                               }\r
+                                                       case APPLICATION_NAME_DESCRIPTOR:\r
+                                                               {\r
+                                                                       GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor = (GF_M2TS_APPLICATION_NAME_DESCRIPTOR*)gf_list_get(application_decoded->application_descriptors,k);\r
+                                                                       Application->appli_name = gf_strdup(name_descriptor->application_name_char);\r
+                                                                       break;\r
+                                                               }\r
+                                                       case TRANSPORT_PROTOCOL_DESCRIPTOR:\r
+                                                               {\r
+                                                                       GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor = (GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR*)gf_list_get(application_decoded->application_descriptors,k);\r
+\r
+                                                                       switch(protocol_descriptor->protocol_id){\r
+                                                                               case CAROUSEL:\r
+                                                                                       {                                                                       \r
+                                                                                               GF_Err e;                                                                                               \r
+                                                                                               GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte = (GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE*)protocol_descriptor->selector_byte;\r
+                                                                                               if(ts->process_dmscc){\r
+                                                                                                       GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = gf_m2ts_get_dmscc_overlord(ts->dsmcc_controler,ait->service_id);\r
+                                                                                                       Application->broadcast = 1;\r
+                                                                                                       if(!dsmcc_overlord){\r
+                                                                                                               char app_url[1024], char_service_id[128];\r
+                                                                                                               \r
+                                                                                                               memset(&app_url,0,1024*sizeof(char));\r
+                                                                                                               memset(&char_service_id,0,128*sizeof(char));\r
+\r
+                                                                                                               dsmcc_overlord = gf_m2ts_init_dsmcc_overlord(ait->service_id);\r
+                                                                                                               dsmcc_overlord->application_id = Application->application_id;\r
+                                                                                                               sprintf(char_service_id,"%d",dsmcc_overlord->service_id);\r
+                                                                                                               dsmcc_overlord->root_dir = (char*)gf_calloc(strlen(ts->dsmcc_root_dir)+2+strlen(char_service_id),sizeof(char));\r
+                                                                                                               sprintf(dsmcc_overlord->root_dir,"%s%c%s",ts->dsmcc_root_dir,GF_PATH_SEPARATOR,char_service_id);\r
+                                                                                                               e = gf_mkdir(dsmcc_overlord->root_dir);\r
+                                                                                                               if(e){                                                                                                                  \r
+                                                                                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the creation of the directory %s \n",dsmcc_overlord->root_dir));\r
+                                                                                                                       if(e == GF_BAD_PARAM){\r
+                                                                                                                               gf_cleanup_dir(dsmcc_overlord->root_dir);\r
+                                                                                                                       }\r
+                                                                                                               }\r
+                                                                                                               sprintf(app_url,"%s%cindex.html",dsmcc_overlord->root_dir,GF_PATH_SEPARATOR);\r
+                                                                                                               Application->carousel_url = gf_strdup(app_url);                                                                                 \r
+                                                                                                               gf_list_add(ts->dsmcc_controler,dsmcc_overlord);\r
+                                                                                                       }\r
+                                                                                               }\r
+                                                                                               if(Carousel_selector_byte->remote_connection){\r
+                                                                                                       Application->carousel_pid = Carousel_selector_byte->service_id;\r
+                                                                                               }\r
+                                                                                               Application->component_tag = Carousel_selector_byte->component_tag;\r
+\r
+                                                                                               break;\r
+                                                                                       }\r
+                                                                               case TRANSPORT_HTTP:\r
+                                                                                       {\r
+                                                                                               GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte = (GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE*)protocol_descriptor->selector_byte;\r
+                                                                                               url_base = Transport_http_selector_byte->URL_base_byte;\r
+                                                                                               Application->broadband = 1;\r
+                                                                                       }\r
+                                                                               default:\r
+                                                                                       {\r
+                                                                                       }\r
+                                                                       }\r
+                                                                       break;\r
+                                                               }\r
+                                                       case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR:\r
+                                                               {\r
+                                                                       GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location = (GF_M2TS_SIMPLE_APPLICATION_LOCATION*)gf_list_get(application_decoded->application_descriptors,k);\r
+                                                                       url_appli_path = Simple_application_location->initial_path_bytes;\r
+                                                                       break;\r
+                                                               }\r
+                                                       case APPLICATION_USAGE_DESCRIPTOR:\r
+                                                               {\r
+                                                                       break;\r
+                                                               }\r
+                                                       default:\r
+                                                               {\r
+                                                                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Process AIT] Descriptor tag %d unknown, ignoring the descriptor \n",desc_id));\r
+                                                               }\r
+                       }\r
+\r
+                       if((url_base != NULL) && ( url_appli_path != NULL)){\r
+                               u32 url_length = (strlen(url_base)+strlen(url_appli_path));\r
+                               Application->http_url = (char*)gf_calloc(url_length + 1,sizeof(char));\r
+                               sprintf(Application->http_url,"%s%s",url_base,url_appli_path);\r
+                               Application->http_url[url_length]=0;\r
+                               Application->url_received = 1;\r
+                               url_base = NULL;\r
+                               url_appli_path = NULL;\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Process AIT] SERVICE ID %d  URL %s  \n",ChanAppInfo->service_id,Application->http_url));\r
+                       }\r
+\r
+               }\r
+       }\r
+       if(ts->process_dmscc){\r
+               GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = gf_m2ts_get_dmscc_overlord(ts->dsmcc_controler,ait->service_id);\r
+\r
+               if(dsmcc_overlord && !gf_m2ts_is_dmscc_app(ChanAppInfo)){                       \r
+                       gf_cleanup_dir(dsmcc_overlord->root_dir);\r
+                       gf_rmdir(dsmcc_overlord->root_dir);     \r
+                       gf_m2ts_delete_dsmcc_overlord(dsmcc_overlord);\r
+\r
+               }\r
+       }\r
+}\r
+\r
+static Bool gf_m2ts_is_dmscc_app(GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo){\r
+       \r
+       u32 nb_app,i;\r
+\r
+       nb_app = gf_list_count(ChanAppInfo->Application);\r
+       for(i=0;i<nb_app;i++){\r
+               GF_M2TS_AIT_APPLICATION* Application = (GF_M2TS_AIT_APPLICATION*)gf_list_get(ChanAppInfo->Application,i);\r
+               if(Application->broadband){\r
+                       return 1;\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+GF_M2TS_CHANNEL_APPLICATION_INFO* gf_m2ts_get_channel_application_info(GF_List* ChannelAppList, u32 ait_service_id){\r
+       u32 i,nb_chanapp;\r
+\r
+       nb_chanapp = gf_list_count(ChannelAppList);\r
+\r
+       for(i = 0; i < nb_chanapp; i++){        \r
+               GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo = (GF_M2TS_CHANNEL_APPLICATION_INFO*)gf_list_get(ChannelAppList,i);\r
+               if(ChanAppInfo->service_id == ait_service_id){\r
+                       return ChanAppInfo;\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+\r
+}\r
+\r
+static Bool check_ait_already_received(GF_List* ChannelAppList,u32 pid,char* data)\r
+{\r
+    u32 nb_of_ait;\r
+       u32 version_number;\r
+\r
+       nb_of_ait = 0;\r
+\r
+       nb_of_ait = gf_list_count(ChannelAppList);\r
+\r
+       if(nb_of_ait){\r
+               u32 i;\r
+               for(i = 0;i < nb_of_ait;i++){\r
+                       GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo = (GF_M2TS_CHANNEL_APPLICATION_INFO*) gf_list_get(ChannelAppList,i);\r
+                       if(ChanAppInfo->ait_pid == pid){\r
+                               version_number = (data[5] &0x3E)>>1;\r
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Process AIT] AIT ait_list_version number %d, ait->version_number %d \n",ChanAppInfo->version_number,version_number));\r
+                               if(ChanAppInfo->version_number >= version_number){\r
+                                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Process AIT] AIT already received, abording processing \n"));    \r
+                                       return 1;\r
+                               }else{                          \r
+                                       while(ChanAppInfo->nb_application != 0){\r
+                                               GF_M2TS_AIT_APPLICATION* Application = gf_list_get(ChanAppInfo->Application,0);\r
+                                               gf_m2ts_free_ait_application(Application);\r
+                                               gf_list_rem(ChanAppInfo->Application,0);\r
+                                               ChanAppInfo->nb_application = gf_list_count(ChanAppInfo->Application);\r
+                                       }\r
+                                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Process AIT] Discard old applications - New AIT received \n"));\r
+                                       return 0;\r
+                               }\r
+                       }\r
+               }\r
+       }else{\r
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Process AIT] No AIT received \n"));\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static void gf_ait_destroy(GF_M2TS_AIT* ait)\r
+{\r
+       u32 common_descr_numb, app_numb;\r
+\r
+       /* delete de Elementary Stream part of the AIT structure */     \r
+       common_descr_numb = 0;\r
+       app_numb = 0;\r
+\r
+       /* delete the common descriptors */ \r
+       common_descr_numb = gf_list_count(ait->common_descriptors);\r
+       while(common_descr_numb != 0){\r
+               //TODO\r
+       };\r
+       gf_list_del(ait->common_descriptors);\r
+\r
+       /* delete the applications and their descriptors */\r
+       app_numb = gf_list_count(ait->application_decoded);\r
+       while(app_numb != 0){\r
+               GF_M2TS_AIT_APPLICATION_DECODE* application = gf_list_get(ait->application_decoded,0);\r
+               gf_ait_application_decode_destroy(application);\r
+               gf_list_rem(ait->application_decoded,0);\r
+               app_numb = gf_list_count(ait->application_decoded);\r
+       }\r
+       gf_list_del(ait->application_decoded);\r
+       gf_free(ait);\r
+}\r
+\r
+static void gf_ait_application_decode_destroy(GF_M2TS_AIT_APPLICATION_DECODE* application_decode)\r
+{\r
+\r
+       u32 app_desc_num,i,app_descr_index;\r
+\r
+       app_desc_num = app_descr_index = i = 0; \r
+       app_desc_num = gf_list_count(application_decode->application_descriptors);\r
+\r
+       while (app_desc_num != 0) {\r
+               u32 descr_tag;\r
+               descr_tag = application_decode->application_descriptors_id[i];\r
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[DSMCC] descr_tag %d\n", descr_tag));\r
+               switch(descr_tag) {\r
+                       case APPLICATION_DESCRIPTOR:\r
+                               {\r
+                                       GF_M2TS_APPLICATION_DESCRIPTOR* application_descriptor = (GF_M2TS_APPLICATION_DESCRIPTOR*)gf_list_get(application_decode->application_descriptors,0);\r
+                                       gf_free(application_descriptor);  \r
+                                       break;\r
+                               }\r
+                       case APPLICATION_NAME_DESCRIPTOR:\r
+                               {\r
+                                       GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor = (GF_M2TS_APPLICATION_NAME_DESCRIPTOR*)gf_list_get(application_decode->application_descriptors,0);\r
+                                       gf_free(name_descriptor->application_name_char);\r
+                                       gf_free(name_descriptor);\r
+                                       break;\r
+                               }\r
+                       case TRANSPORT_PROTOCOL_DESCRIPTOR:\r
+                               {\r
+                                       GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor = (GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR*)gf_list_get(application_decode->application_descriptors,0);                                        \r
+                                       switch (protocol_descriptor->protocol_id) {\r
+                       case CAROUSEL:\r
+                               {\r
+                                       GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte = (GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE*)protocol_descriptor->selector_byte;\r
+                                       gf_free(Carousel_selector_byte);\r
+                                       break;\r
+                               }\r
+                       case TRANSPORT_HTTP:\r
+                               {                                       \r
+                                       u32 i;                                                          \r
+                                       GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte = (GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE*)protocol_descriptor->selector_byte;\r
+                                       gf_free(Transport_http_selector_byte->URL_base_byte);\r
+                                       if (Transport_http_selector_byte->URL_extension_count) {\r
+                                               for (i=0; i < Transport_http_selector_byte->URL_extension_count;i++) {                                                                          \r
+                                                       gf_free(Transport_http_selector_byte->URL_extentions[i].URL_extension_byte);\r
+                                               }\r
+                                               gf_free(Transport_http_selector_byte->URL_extentions);\r
+                                       }\r
+                                       gf_free(Transport_http_selector_byte);\r
+                                       break;\r
+                               }\r
+                       default:\r
+                               {\r
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Protocol ID %d unsupported, ignoring the selector byte \n",protocol_descriptor->protocol_id));\r
+                               }\r
+                                       }                                       \r
+                                       gf_free(protocol_descriptor);                                   \r
+                                       break;\r
+                               }\r
+                       case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR:\r
+                               {                       \r
+                                       GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location = (GF_M2TS_SIMPLE_APPLICATION_LOCATION*)gf_list_get(application_decode->application_descriptors,0);\r
+                                       gf_free(Simple_application_location->initial_path_bytes);\r
+                                       gf_free(Simple_application_location);\r
+                                       break;\r
+                               }\r
+                       case APPLICATION_USAGE_DESCRIPTOR:\r
+                               {\r
+                                       GF_M2TS_APPLICATION_USAGE* Application_usage = (GF_M2TS_APPLICATION_USAGE*)gf_list_get(application_decode->application_descriptors,0);\r
+                                       gf_free(Application_usage);\r
+                                       break;\r
+                               }\r
+                       case APPLICATION_BOUNDARY_DESCRIPTOR:\r
+                               {\r
+                                       u32 i;\r
+                                       GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR* boundary_descriptor = (GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR*)gf_list_get(application_decode->application_descriptors, 0);\r
+                                       if (boundary_descriptor->boundary_extension_count > 0) {\r
+                                               for (i=0; i<boundary_descriptor->boundary_extension_count; i++) {\r
+                                                       if (boundary_descriptor->boundary_extension_info[i].boundary_extension_length > 0) {\r
+                                                               gf_free(boundary_descriptor->boundary_extension_info[i].boundary_extension_byte);\r
+                                                       }                                                       \r
+                                               }\r
+                                               gf_free(boundary_descriptor->boundary_extension_info);\r
+                                       }\r
+                                       gf_free(boundary_descriptor);\r
+                                       break;                                  \r
+                               }\r
+                       default:\r
+                               {\r
+                               }\r
+               }\r
+               gf_list_rem(application_decode->application_descriptors,0);\r
+               app_desc_num = gf_list_count(application_decode->application_descriptors);\r
+               i++;\r
+       }\r
+       gf_list_del(application_decode->application_descriptors);\r
+       gf_free(application_decode);\r
+}\r
+\r
+static void gf_m2ts_free_ait_application(GF_M2TS_AIT_APPLICATION* Application){\r
+\r
+       if(Application->http_url){\r
+               gf_free(Application->http_url);\r
+       }\r
+       if(Application->carousel_url){\r
+               gf_free(Application->carousel_url);\r
+       }\r
+\r
+       if(Application->appli_name){\r
+               gf_free(Application->appli_name);\r
+       }\r
+       gf_free(Application);\r
+}\r
+\r
+void  gf_m2ts_delete_channel_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO* ChannelApp){\r
+\r
+       while(gf_list_count(ChannelApp->Application)){\r
+               GF_M2TS_AIT_APPLICATION* Application = (GF_M2TS_AIT_APPLICATION*)gf_list_get(ChannelApp->Application,0);\r
+               gf_m2ts_free_ait_application(Application);\r
+               gf_list_rem(ChannelApp->Application,0);\r
+       }\r
+\r
+       gf_list_del(ChannelApp->Application);\r
+       gf_free(ChannelApp);\r
+}\r
+#endif //GPAC_DISABLE_MPEG2TS\r
+\r
+\r
index 154563de63d7d515627a33f856d7844dcbc1fd06..fa6f6c72fd8831c3e9f200afcdc17c8a3023e706 100644 (file)
@@ -280,7 +280,7 @@ static GF_Err M4V_Reset(GF_M4VParser *m4v, u64 start)
 
 static GF_Err gf_m4v_parse_config_mpeg12(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi)
 {
-       char p[4];
+       unsigned char p[4];
        u32 ext_type;
        s32 o_type;
        u8 go, par;
@@ -909,14 +909,12 @@ GF_Err gf_m4a_parse_config(GF_BitStream *bs, GF_M4ADecSpecInfo *cfg, Bool size_k
        case 22:
        case 23:
        {
-               Bool fl_flag, ext_flag;
-               u32 delay;
+               Bool ext_flag;
                /*frame length flag*/
-               fl_flag = gf_bs_read_int(bs, 1);
+               /*fl_flag = */gf_bs_read_int(bs, 1);
                /*depends on core coder*/
-               delay = 0;
                if (gf_bs_read_int(bs, 1))
-                       delay = gf_bs_read_int(bs, 14);
+                       /*delay = */gf_bs_read_int(bs, 14);
                ext_flag = gf_bs_read_int(bs, 1);
                if (!cfg->nb_chan) {
                }
@@ -1133,11 +1131,6 @@ const char *gf_mp3_version_name(u32 hdr)
 #ifndef GPAC_DISABLE_AV_PARSERS
 
 
-static u8 MP3_GetLayerV(u32 hdr)
-{
-       return ((hdr >> 17) & 0x3); 
-}
-
 GF_EXPORT
 u8 gf_mp3_layer(u32 hdr)
 {
@@ -1151,56 +1144,45 @@ u8 gf_mp3_num_channels(u32 hdr)
        return 2;
 }
 
-
-static GFINLINE u32 get_MP3SamplingRates(u32 version, u32 idx) 
-{
-       switch (version) {
-       case 0:
-               switch (idx) {
-               case 0: return 11025;
-               case 1: return 12000;
-               case 2: return 8000;
-               default: return 0;
-               }
-               break;
-       case 1:
-               return 0;
-       case 2:
-               switch (idx) {
-               case 0: return 22050;
-               case 1: return 24000;
-               case 2: return 16000;
-               default: return 0;
-               }
-               break;
-       case 3:
-               switch (idx) {
-               case 0: return 44100;
-               case 1: return 48000;
-               case 2: return 32000;
-               default: return 0;
-               }
-               break;
-       }
-       return 0;
-}
-
 GF_EXPORT
 u16 gf_mp3_sampling_rate(u32 hdr)
 {
+       u16 res;
        /* extract the necessary fields from the MP3 header */
        u8 version = gf_mp3_version(hdr);
        u8 sampleRateIndex = (hdr >> 10) & 0x3;
-       return get_MP3SamplingRates(version, sampleRateIndex);
+
+       switch (sampleRateIndex) {
+       case 0: 
+               res = 44100; 
+               break;
+       case 1: 
+               res = 48000; 
+               break;
+       case 2: 
+               res = 32000; 
+               break;
+       default: 
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[MPEG-1/2 Audio] Samplerate index not valid\n"));
+               return 0;
+       }
+       /*reserved or MPEG-1*/
+       if (version & 1) return res;
+
+       /*MPEG-2*/
+       res /= 2;
+       /*MPEG-2.5*/
+       if (version == 0) res /= 2;
+       return res;
 }
 
 GF_EXPORT
 u16 gf_mp3_window_size(u32 hdr)
 {
        u8 version = gf_mp3_version(hdr);
-       u8 layer = MP3_GetLayerV(hdr);
+       u8 layer = gf_mp3_layer(hdr);
 
-       if (layer == 1) {
+       if (layer == 3) {
                if (version == 3) return 1152;
                return 576;
        }
@@ -1222,175 +1204,67 @@ u8 gf_mp3_object_type_indication(u32 hdr)
        }
 }
 
+/*aligned bitrate parsing with libMAD*/
 
-static GFINLINE u32 get_MP3BitRates(u32 idx1, u32 idx2) 
-{
-       switch (idx1) {
-       /* MPEG-1, Layer III */
-       case 0:
-               switch (idx2) {
-               case 0: return 32;
-               case 1: return 40;
-               case 2: return 48;
-               case 3: return 56;
-               case 4: return 64;
-               case 5: return 80;
-               case 6: return 96;
-               case 7: return 112;
-               case 8: return 128;
-               case 9: return 160;
-               case 10: return 192;
-               case 11: return 224;
-               case 12: return 256;
-               case 13: return 320;
-               default: return 0;
-               }
-               break;
-       /* MPEG-1, Layer II */
-       case 1:
-               switch (idx2) {
-               case 0: return 32;
-               case 1: return 48;
-               case 2: return 56;
-               case 3: return 64;
-               case 4: return 80;
-               case 5: return 96;
-               case 6: return 112;
-               case 7: return 128;
-               case 8: return 160;
-               case 9: return 192;
-               case 10: return 224;
-               case 11: return 256;
-               case 12: return 320;
-               case 13: return 384;
-               default: return 0;
-               }
-               break;
-       /* MPEG-1, Layer I */
-       case 2:
-               switch (idx2) {
-               case 0: return 32;
-               case 1: return 64;
-               case 2: return 96;
-               case 3: return 128;
-               case 4: return 160;
-               case 5: return 192;
-               case 6: return 224;
-               case 7: return 256;
-               case 8: return 288;
-               case 9: return 320;
-               case 10: return 352;
-               case 11: return 384;
-               case 12: return 416;
-               case 13: return 448;
-               default: return 0;
-               }
-               break;
-       /* MPEG-2 or 2.5, Layer II or III */
-       case 3:
-               switch (idx2) {
-               case 0: return 8;
-               case 1: return 16;
-               case 2: return 24;
-               case 3: return 32;
-               case 4: return 40;
-               case 5: return 48;
-               case 6: return 56;
-               case 7: return 64;
-               case 8: return 80;
-               case 9: return 96;
-               case 10: return 112;
-               case 11: return 128;
-               case 12: return 144;
-               case 13: return 160;
-               default: return 0;
-               }
-               break;
-       /* MPEG-2 or 2.5, Layer I */
-       case 4:
-               switch (idx2) {
-               case 0: return 32;
-               case 1: return 48;
-               case 2: return 56;
-               case 3: return 64;
-               case 4: return 80;
-               case 5: return 96;
-               case 6: return 112;
-               case 7: return 128;
-               case 8: return 144;
-               case 9: return 160;
-               case 10: return 176;
-               case 11: return 192;
-               case 12: return 224;
-               case 13: return 256;
-               default: return 0;
-               }
-               break;
-       default:
-               return 0;
-       }
-       return 0;
-}
+static
+u32 const bitrate_table[5][15] = {
+  /* MPEG-1 */
+  { 0,  32000,  64000,  96000, 128000, 160000, 192000, 224000,  /* Layer I   */
+       256000, 288000, 320000, 352000, 384000, 416000, 448000 },
+  { 0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,  /* Layer II  */
+       128000, 160000, 192000, 224000, 256000, 320000, 384000 },
+  { 0,  32000,  40000,  48000,  56000,  64000,  80000,  96000,  /* Layer III */
+       112000, 128000, 160000, 192000, 224000, 256000, 320000 },
+
+  /* MPEG-2 LSF */
+  { 0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,  /* Layer I   */
+       128000, 144000, 160000, 176000, 192000, 224000, 256000 },
+  { 0,   8000,  16000,  24000,  32000,  40000,  48000,  56000,  /* Layers    */
+        64000,  80000,  96000, 112000, 128000, 144000, 160000 } /* II & III  */
+};
 
 
-GF_EXPORT
-u16 gf_mp3_frame_size(u32 hdr)
+u32 gf_mp3_bit_rate(u32 hdr)
 {
-       u32 val;
-       u8 bitRateIndex1;
        u8 version = gf_mp3_version(hdr);
-       u8 layer = MP3_GetLayerV(hdr);
-       u8 bitRateIndex2 = (hdr >> 12) & 0xF;
-       u8 sampleRateIndex = (hdr >> 10) & 0x3;
-       Bool isPadded = (hdr >> 9) & 0x1;
-       u32 frameSize = 0;
+       u8 layer = gf_mp3_layer(hdr);
+       u8 bitRateIndex = (hdr >> 12) & 0xF;
 
-       if (version == 3) {
-               bitRateIndex1 = layer - 1;
-       } else {
-               if (layer == 3) {
-                       bitRateIndex1 = 4;
-               } else {
-                       bitRateIndex1 = 3;
-               }
+       if (bitRateIndex == 15) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[MPEG-1/2 Audio] Bitrate index not valid\n"));
+           return 0;
        }
 
-       /* compute frame size */
-       val = get_MP3SamplingRates(version, sampleRateIndex);
-       if (!(version & 1)) val <<= 1;
-       if (!val) return 0;
-       frameSize = 144 * 1000 * get_MP3BitRates(bitRateIndex1, bitRateIndex2-1);
-       frameSize /= val;
-
-       if (isPadded) {
-               if (layer == 3) {
-                       frameSize += 4;
-               } else {
-                       frameSize++;
-               }
-       }
-       return (u16) frameSize;
+       /*MPEG-1*/
+       if (version & 1)
+           return bitrate_table[layer - 1][bitRateIndex];
+       /*MPEG-2/2.5*/
+       else
+           return bitrate_table[3 + (layer >> 1)][bitRateIndex];
 }
 
 
-u16 gf_mp3_bit_rate(u32 hdr)
+
+GF_EXPORT
+u16 gf_mp3_frame_size(u32 hdr)
 {
-       u8 bitRateIndex1;
        u8 version = gf_mp3_version(hdr);
-       u8 layer = MP3_GetLayerV(hdr);
-       u8 bitRateIndex2 = (hdr >> 12) & 0xF;
-       if (version == 3) {
-               bitRateIndex1 = layer - 1;
+       u8 layer = gf_mp3_layer(hdr);
+       u32 pad = ( (hdr >> 9) & 0x1) ? 1 : 0;
+       u32 bitrate = gf_mp3_bit_rate(hdr);
+       u32 samplerate = gf_mp3_sampling_rate(hdr);
+
+       u32 frameSize = 0;
+       if (!samplerate || !bitrate) return 0;
+
+       if (layer==1) {
+               frameSize = (( 12 * bitrate / samplerate) + pad) * 4;
        } else {
-               if (layer == 3) {
-                       bitRateIndex1 = 4;
-               } else {
-                       bitRateIndex1 = 3;
-               }
+               u32 slots_per_frame = 144;
+           if ((layer == 3) && !(version & 1)) slots_per_frame = 72;
+               frameSize = (slots_per_frame * bitrate / samplerate) + pad;
        }
-
-       /* compute frame size */
-       return get_MP3BitRates(bitRateIndex1, bitRateIndex2-1);
+       return (u16) frameSize;
 }
 
 
@@ -1829,7 +1703,10 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        sps_data_without_emulation_bytes = gf_malloc(sps_size*sizeof(char));
        sps_data_without_emulation_bytes_size = avc_remove_emulation_bytes(sps_data, sps_data_without_emulation_bytes, sps_size);
        bs = gf_bs_new(sps_data_without_emulation_bytes, sps_data_without_emulation_bytes_size, GF_BITSTREAM_READ);
-       
+       if (!bs) {
+               sps_id = -1;
+               goto exit;
+       }
        if (vui_flag_pos) *vui_flag_pos = 0;
 
        profile_idc = gf_bs_read_int(bs, 8);
@@ -1845,6 +1722,10 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        by subset SPS. According to the SVC standard, subset SPS can have the same sps_id 
        than its base layer, but it does not refer to the same SPS. */
        sps_id = avc_get_ue(bs) + GF_SVC_SSPS_ID_SHIFT * subseq_sps;
+       if (sps_id >=32) {
+               sps_id = -1;
+               goto exit;
+       }
 
        sps = &avc->sps[sps_id];
        sps->state |= subseq_sps ? AVC_SUBSPS_PARSED : AVC_SPS_PARSED;
@@ -2084,11 +1965,24 @@ s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc)
        pps_data_without_emulation_bytes = gf_malloc(pps_size*sizeof(char));
        pps_data_without_emulation_bytes_size = avc_remove_emulation_bytes(pps_data, pps_data_without_emulation_bytes, pps_size);
        bs = gf_bs_new(pps_data_without_emulation_bytes, pps_data_without_emulation_bytes_size, GF_BITSTREAM_READ);
+       if (!bs) {
+               pps_id = -1;
+               goto exit;
+       }
        pps_id = avc_get_ue(bs);
+       if (pps_id>=255) {
+               pps_id = -1;
+               goto exit;
+       }
        pps = &avc->pps[pps_id];
    
        if (!pps->status) pps->status = 1;
        pps->sps_id = avc_get_ue(bs);
+       if (pps->sps_id >= 32) {
+               pps->sps_id = 0;
+               pps_id = -1;
+               goto exit;
+       }
        /*sps_id may be refer to regular SPS or subseq sps, depending on the coded slice refering to the pps*/
        if (!avc->sps[pps->sps_id].state && !avc->sps[pps->sps_id + GF_SVC_SSPS_ID_SHIFT].state) {
                pps_id = -1;
@@ -2138,10 +2032,10 @@ static s32 SVC_ReadNal_header_extension(GF_BitStream *bs, SVC_NALUHeader *NalHea
 
 static s32 avc_parse_slice(GF_BitStream *bs, AVCState *avc, Bool svc_idr_flag, AVCSliceInfo *si) 
 {
-       s32 first_mb_in_slice, pps_id;
+       s32 pps_id;
 
        /*s->current_picture.reference= h->nal_ref_idc != 0;*/
-       first_mb_in_slice = avc_get_ue(bs);
+       /*first_mb_in_slice = */avc_get_ue(bs);
        si->slice_type = avc_get_ue(bs);
        if (si->slice_type > 9) return -1;
 
@@ -2183,10 +2077,10 @@ static s32 avc_parse_slice(GF_BitStream *bs, AVCState *avc, Bool svc_idr_flag, A
 
 static s32 svc_parse_slice(GF_BitStream *bs, AVCState *avc, AVCSliceInfo *si) 
 {
-       s32 first_mb_in_slice, pps_id;
+       s32 pps_id;
 
        /*s->current_picture.reference= h->nal_ref_idc != 0;*/
-       first_mb_in_slice = avc_get_ue(bs);
+       /*first_mb_in_slice = */avc_get_ue(bs);
        si->slice_type = avc_get_ue(bs);
        if (si->slice_type > 9) return -1;
 
@@ -2561,7 +2455,7 @@ u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc)
        if ((hdr & 0x1F) != GF_AVC_NALU_SEI) return 0;
 
        /*PPS still contains emulation bytes*/
-       sei_without_emulation_bytes = gf_malloc(nal_size*sizeof(char));
+       sei_without_emulation_bytes = gf_malloc(nal_size + 1/*for SEI null string termination*/);
        sei_without_emulation_bytes_size = avc_remove_emulation_bytes(buffer, sei_without_emulation_bytes, nal_size);
 
        bs = gf_bs_new(sei_without_emulation_bytes, sei_without_emulation_bytes_size, GF_BITSTREAM_READ);
@@ -2599,10 +2493,12 @@ u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc)
                        break;
                case 5: /*user unregistered */
                {
-                       u8 prev = sei_without_emulation_bytes[start+2+psize];
-                       sei_without_emulation_bytes[start+2+psize] = 0;
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[avc-h264] SEI user message %s\n", sei_without_emulation_bytes+start+2)); 
-                       sei_without_emulation_bytes[start+2+psize] = prev;
+                       char prev;
+                       assert(start+psize+1 < nal_size+1);
+                       prev = sei_without_emulation_bytes[start+psize+1];
+                       sei_without_emulation_bytes[start+psize+1] = 0;
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[avc-h264] SEI user message %s\n", sei_without_emulation_bytes+start+16)); 
+                       sei_without_emulation_bytes[start+psize+1] = prev;
                }
                        break;
                
index f220bddaf7ea8a03288cf767d4c0102b09798cd9..8ac5b65ca4008c768a1b1226d1113057b6354c51 100644 (file)
@@ -43,7 +43,7 @@
 //#define NEW_RIFF_THRES (10*1024*1024)
 
 // Maximum number of indices per stream
-#define NR_IXNN_CHUNKS 32
+#define NR_IXNN_CHUNKS 96
 
 
 #define DEBUG_ODML
@@ -85,7 +85,7 @@ static u32 avi_write (FILE *fd, char *buf, u32 len)
    u32 r = 0;
 
    while (r < len) {
-      n = fwrite (buf + r, 1, len - r, fd);
+      n = gf_fwrite (buf + r, 1, len - r, fd);
       if (n < 0)
          return n;
 
diff --git a/src/media_tools/carousel.c b/src/media_tools/carousel.c
deleted file mode 100644 (file)
index 99cc818..0000000
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
-*                      GPAC - Multimedia Framework C SDK
-*
-*                      Authors: Telecom Paristech
-*    Copyright (c)2006-200X ENST - All rights reserved
-*
-*  This file is part of GPAC / MPEG2-TS sub-project
-*
-*  GPAC is gf_free software; you can redistribute it and/or modify
-*  it under the terms of the GNU Lesser General Public License as published by
-*  the gf_free Software Foundation; either version 2, or (at your option)
-*  any later version.
-*   
-*  GPAC 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 Lesser General Public License for more details.
-*   
-*  You should have received a copy of the GNU Lesser General Public
-*  License along with this library; see the file COPYING.  If not, write to
-*  the gf_free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
-*
-*/
-
-#include <gpac/carousel.h>
-
-
-GF_M2TS_ES *gf_ait_section_new(u32 service_id)
-{
-       GF_M2TS_ES *es;
-
-       GF_M2TS_AIT *ses;
-       GF_SAFEALLOC(ses, GF_M2TS_AIT);
-       es = (GF_M2TS_ES *)ses;
-       es->flags = GF_M2TS_ES_IS_SECTION;
-       ses->service_id = service_id;
-       return es;
-}
-
-
-void on_ait_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) 
-{
-       GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)par;
-       char *data;
-       u32 u32_data_size;
-       u32 u32_table_id;
-
-       if (evt_type == GF_M2TS_EVT_AIT_FOUND) {
-               data = pck->data;
-               u32_data_size = pck->data_len;
-               u32_table_id = data[0];
-
-               gf_m2ts_process_ait((GF_M2TS_AIT*)pck->stream, data, u32_data_size, u32_table_id);
-
-       }
-}
-
-GF_Err gf_m2ts_process_ait(GF_M2TS_AIT *ait, char  *data, u32 data_size, u32 table_id)
-{
-
-       GF_BitStream *bs;
-       u8 temp_descriptor_tag;
-       u32 data_shift, app_desc_data_shift, ait_app_data_shift;
-       u32 nb_of_ait;
-
-       data_shift = 0;
-       temp_descriptor_tag = 0;
-       nb_of_ait = 0;
-       ait_app_data_shift = 0;
-       bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ);
-
-       ait->common_descriptors = gf_list_new();
-       ait->application = gf_list_new();
-
-       ait->table_id = gf_bs_read_int(bs,8);   
-       ait->section_syntax_indicator = gf_bs_read_int(bs,1);
-       gf_bs_read_int(bs,3);
-       ait->section_length = gf_bs_read_int(bs,12);    
-       if( (data[1] & 0x0C) != 0){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length is not correct abroding \n"));
-       }else if( ait->section_length > AIT_SECTION_LENGTH_MAX){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length should not exceed 1021. Wrong section, abording processing \n"));
-       }
-       ait->test_application_flag = gf_bs_read_int(bs,1);
-       ait->application_type = gf_bs_read_int(bs,15);  
-       if(ait->application_type != APPLICATION_TYPE_HTTP_APPLICATION){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] application type should 0x10. Wrong section, abording processing \n"));
-       }
-       gf_bs_read_int(bs,2);
-       ait->version_number = gf_bs_read_int(bs,5);
-
-       ait->current_next_indicator = gf_bs_read_int(bs,1);     
-       if(!ait->current_next_indicator){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] current next indicator should be at 1 \n"));
-       }
-       ait->section_number = gf_bs_read_int(bs,8);
-       ait->last_section_number = gf_bs_read_int(bs,8);        
-       gf_bs_read_int(bs,4);/* bit shifting */
-       ait->common_descriptors_length = gf_bs_read_int(bs,12); 
-       gf_bs_read_int(bs,(unsigned int)ait->common_descriptors_length/8);
-       gf_bs_read_int(bs,4);/* bit shifting */ 
-       ait->application_loop_length = gf_bs_read_int(bs,12);
-
-       data_shift = (u32)(gf_bs_get_position(bs)) + ait->common_descriptors_length/8;
-
-       while(ait_app_data_shift<ait->application_loop_length){
-
-               GF_M2TS_AIT_APPLICATION* application;
-               GF_SAFEALLOC(application,GF_M2TS_AIT_APPLICATION);
-               application->application_descriptors = gf_list_new();
-               application->index_app_desc_id = 0;
-
-               /* application loop */
-               application->organisation_id = gf_bs_read_int(bs,32);   
-               application->application_id= gf_bs_read_int(bs,16);
-               application->application_control_code= gf_bs_read_int(bs,8);
-               gf_bs_read_int(bs,4);/* bit shifting */
-               application->application_descriptors_loop_length= gf_bs_read_int(bs,12);                
-
-               ait_app_data_shift += 9;
-               app_desc_data_shift = 0;
-
-               while(app_desc_data_shift< application->application_descriptors_loop_length){
-                       temp_descriptor_tag = gf_bs_read_int(bs,8);
-                       switch(temp_descriptor_tag){
-                       case APPLICATION_DESCRIPTOR:
-                               {
-                                       u64 pre_processing_pos;
-                                       GF_M2TS_APPLICATION_DESCRIPTOR* application_descriptor;
-                                       GF_SAFEALLOC(application_descriptor, GF_M2TS_APPLICATION_DESCRIPTOR);
-                                       application_descriptor->descriptor_tag = temp_descriptor_tag;
-                                       application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;
-                                       application->index_app_desc_id++;
-                                       application_descriptor->descriptor_length = gf_bs_read_int(bs,8);
-                                       pre_processing_pos = gf_bs_get_position(bs);
-                                       application_descriptor->application_profiles_length = gf_bs_read_int(bs,8);
-                                       application_descriptor->application_profile = gf_bs_read_int(bs,16);
-                                       application_descriptor->version_major = gf_bs_read_int(bs,8);
-                                       application_descriptor->version_minor = gf_bs_read_int(bs,8);
-                                       application_descriptor->version_micro = gf_bs_read_int(bs,8);
-                                       application_descriptor->service_bound_flag = gf_bs_read_int(bs,1);
-                                       application_descriptor->visibility = gf_bs_read_int(bs,2);
-                                       gf_bs_read_int(bs,5); /*bit shift*/
-                                       application_descriptor->application_priority = gf_bs_read_int(bs,8);
-                                       application_descriptor->transport_protocol_label = gf_bs_read_int(bs,8);
-                                       if(pre_processing_pos+application_descriptor->descriptor_length != gf_bs_get_position(bs)){
-                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),application_descriptor->descriptor_length));
-                                       }
-                                       gf_list_add(application->application_descriptors,application_descriptor);
-                                       app_desc_data_shift += (2+ application_descriptor->descriptor_length);
-                                       break;
-                               }
-                       case APPLICATION_NAME_DESCRIPTOR:
-                               {
-                                       u64 pre_processing_pos;
-                                       GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor;
-                                       GF_SAFEALLOC(name_descriptor, GF_M2TS_APPLICATION_NAME_DESCRIPTOR);
-                                       application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;
-                                       application->index_app_desc_id++;
-                                       name_descriptor->descriptor_tag = temp_descriptor_tag;
-                                       name_descriptor->descriptor_length = gf_bs_read_int(bs,8);
-                                       pre_processing_pos = gf_bs_get_position(bs);
-                                       name_descriptor->ISO_639_language_code = gf_bs_read_int(bs,24);
-                                       name_descriptor->application_name_length = gf_bs_read_int(bs,8);
-                                       name_descriptor->application_name_char = (char*) gf_calloc(name_descriptor->application_name_length+1,sizeof(char));
-                                       gf_bs_read_data(bs,name_descriptor->application_name_char,name_descriptor->application_name_length);
-                                       name_descriptor->application_name_char[name_descriptor->application_name_length] = 0 ;
-                                       if(pre_processing_pos+name_descriptor->descriptor_length != gf_bs_get_position(bs)){
-                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),name_descriptor->descriptor_length));
-                                       }
-                                       gf_list_add(application->application_descriptors,name_descriptor);
-                                       app_desc_data_shift += (2+ name_descriptor->descriptor_length);
-                                       break;
-                               }
-                       case TRANSPORT_PROTOCOL_DESCRIPTOR:
-                               {
-                                       u64 pre_processing_pos;
-                                       GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor;
-                                       GF_SAFEALLOC(protocol_descriptor, GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR);
-                                       application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;
-                                       application->index_app_desc_id++;
-                                       protocol_descriptor->descriptor_tag = temp_descriptor_tag;
-                                       protocol_descriptor->descriptor_length = gf_bs_read_int(bs,8);
-                                       pre_processing_pos = gf_bs_get_position(bs);
-                                       protocol_descriptor->protocol_id = gf_bs_read_int(bs,16);
-                                       protocol_descriptor->transport_protocol_label = gf_bs_read_int(bs,8);
-                                       switch(protocol_descriptor->protocol_id){
-                                               case CAROUSEL:
-                                                       {
-                                                               GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte;
-                                                               GF_SAFEALLOC(Carousel_selector_byte, GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE);
-                                                               Carousel_selector_byte->remote_connection = gf_bs_read_int(bs,1);
-                                                               gf_bs_read_int(bs,7); /* bit shifting */
-                                                               if(Carousel_selector_byte->remote_connection){
-                                                                       Carousel_selector_byte->original_network_id = gf_bs_read_int(bs,16);
-                                                                       Carousel_selector_byte->transport_stream_id = gf_bs_read_int(bs,16);
-                                                                       Carousel_selector_byte->service_id = gf_bs_read_int(bs,16);
-                                                               }
-                                                               Carousel_selector_byte->component_tag = gf_bs_read_int(bs,8);
-                                                               protocol_descriptor->selector_byte = Carousel_selector_byte;
-                                                               break;
-                                                       }
-                                               case TRANSPORT_HTTP:
-                                                       {                                       
-                                                               u32 i;                                                          
-                                                               GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte;
-                                                               GF_SAFEALLOC(Transport_http_selector_byte, GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE);                                       
-                                                               Transport_http_selector_byte->URL_base_length = gf_bs_read_int(bs,8);
-                                                               //printf("Transport_http_selector_byte->URL_base_length %d \n",Transport_http_selector_byte->URL_base_length);
-                                                               Transport_http_selector_byte->URL_base_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_base_length,sizeof(char));
-                                                               gf_bs_read_data(bs,Transport_http_selector_byte->URL_base_byte ,(u32)(Transport_http_selector_byte->URL_base_length));
-                                                               Transport_http_selector_byte->URL_base_byte[Transport_http_selector_byte->URL_base_length] = 0;
-                                                               Transport_http_selector_byte->URL_extension_count = gf_bs_read_int(bs,8);
-                                                               if(Transport_http_selector_byte->URL_extension_count){
-                                                                       Transport_http_selector_byte->URL_extentions = (GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION*) gf_calloc(Transport_http_selector_byte->URL_extension_count,sizeof(GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION));
-                                                                       for(i = 0; i < Transport_http_selector_byte->URL_extension_count;i++){
-                                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_length = gf_bs_read_int(bs,8);
-                                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_extentions[i].URL_extension_length,sizeof(char));
-                                                                               gf_bs_read_data(bs,Transport_http_selector_byte->URL_extentions[i].URL_extension_byte,(u32)(Transport_http_selector_byte->URL_extentions[i].URL_extension_length));
-                                                                               Transport_http_selector_byte->URL_extentions[i].URL_extension_byte[Transport_http_selector_byte->URL_extentions[i].URL_extension_length] = 0;
-                                                                       }
-                                                               }
-                                                               protocol_descriptor->selector_byte = Transport_http_selector_byte;
-                                                               break;
-                                                       }
-                                               default:
-                                                       {
-                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Protocol ID %d unsupported, ignoring the selector byte \n",protocol_descriptor->protocol_id));
-                                                       }
-                                       }
-                                       if(pre_processing_pos+protocol_descriptor->descriptor_length != gf_bs_get_position(bs)){
-                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),protocol_descriptor->descriptor_length));
-                                       }
-                                       gf_list_add(application->application_descriptors,protocol_descriptor);
-                                       app_desc_data_shift += (2+ protocol_descriptor->descriptor_length);
-                                       break;
-                               }
-                       case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR:
-                               {
-                                       u64 pre_processing_pos;
-                                       GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location;
-                                       GF_SAFEALLOC(Simple_application_location, GF_M2TS_SIMPLE_APPLICATION_LOCATION);
-                                       application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;
-                                       application->index_app_desc_id++;
-                                       Simple_application_location->descriptor_tag = temp_descriptor_tag;
-                                       Simple_application_location->descriptor_length = gf_bs_read_int(bs,8);
-                                       pre_processing_pos = gf_bs_get_position(bs);
-                                       Simple_application_location->initial_path_bytes = (char*)gf_calloc(Simple_application_location->descriptor_length,sizeof(char));
-                                       gf_bs_read_data(bs,Simple_application_location->initial_path_bytes ,(u32)(Simple_application_location->descriptor_length));
-                                       Simple_application_location->initial_path_bytes[Simple_application_location->descriptor_length] = 0;
-                                       if(pre_processing_pos+Simple_application_location->descriptor_length != gf_bs_get_position(bs)){
-                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),Simple_application_location->descriptor_length));
-                                       }
-                                       gf_list_add(application->application_descriptors,Simple_application_location);
-                                       app_desc_data_shift += (2+ Simple_application_location->descriptor_length);
-                                       break;
-                               }
-                       case APPLICATION_USAGE_DESCRIPTOR:
-                               {
-                                       u64 pre_processing_pos;
-                                       GF_M2TS_APPLICATION_USAGE* Application_usage;
-                                       GF_SAFEALLOC(Application_usage, GF_M2TS_APPLICATION_USAGE);
-                                       application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag;
-                                       application->index_app_desc_id++;
-                                       Application_usage->descriptor_tag = temp_descriptor_tag;
-                                       Application_usage->descriptor_length = gf_bs_read_int(bs,8);
-                                       pre_processing_pos = gf_bs_get_position(bs);
-                                       Application_usage->usage_type = gf_bs_read_int(bs,8);
-                                       if(pre_processing_pos+Application_usage->descriptor_length != gf_bs_get_position(bs)){
-                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) -  pre_processing_pos),Application_usage->descriptor_length));
-                                       }
-                                       gf_list_add(application->application_descriptors,Application_usage);
-                                       app_desc_data_shift += (2+ Application_usage->descriptor_length);
-                                       break;
-                               }
-                       default:
-                               {
-                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor tag %d unknown, ignoring the descriptor \n",temp_descriptor_tag));
-                               }
-
-                       }
-
-               }
-               ait_app_data_shift += application->application_descriptors_loop_length; 
-               gf_list_add(ait->application,application);
-       }
-
-       data_shift +=ait->application_loop_length;
-       ait->CRC_32 = gf_bs_read_int(bs,32);
-       data_shift += 4;
-
-       if(data_shift != data_size){
-               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] AIT processed length error. Difference between byte shifting %d and data size %d \n",data_shift,data_size));
-       }
-
-       return GF_OK;
-}
-
-void gf_ait_destroy(GF_M2TS_AIT* ait)
-{
-//     u32 common_descr_numb, app_numb;
-//     GF_M2TS_ES *es = (GF_M2TS_ES *)ait;
-//     
-//     /* delete de Elementary Stream part of the AIT structure */
-//     gf_m2ts_es_del(es);
-//     
-//     common_descr_numb = 0;
-//     app_numb = 0;
-//     
-//     /* delete the common descriptors */ 
-//     common_descr_numb = gf_list_count(ait->common_descriptors);
-// //  while(common_app_numb != 0){
-// //    
-// //  };
-// 
-//     /* delete the applications and their descriptors */
-//     app_numb = gf_list_count(ait->application);
-//     while(app_numb != 0){
-//       u32 app_desc_num;
-//       u32 app_descr_index;
-//       
-//       app_desc_num = 0;
-//       app_descr_index = 0;
-//       app_desc_num = gf_list_count(ait->application->application_descriptors);
-//       while(app_desc_num != 0){
-//         u32 descr_tag;
-//         ait->application->index_app_desc_id--;
-//         descr_tag = ait->application->application_descriptors_id[ait->application->index_app_desc_id];
-//         
-//         switch(descr_tag){
-//                     case APPLICATION_DESCRIPTOR:
-//                             {
-//                                     GF_M2TS_APPLICATION_DESCRIPTOR* application_descriptor = (GF_M2TS_APPLICATION_DESCRIPTOR*)gf_list_get(ait->application->application_descriptors,ait->application->index_app_desc_id);
-//                                     gf_free(application_descriptor);  
-//                                     break;
-//                             }
-//                     case APPLICATION_NAME_DESCRIPTOR:
-//                             {
-//                                     u64 pre_processing_pos;
-//                                     GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor = (GF_M2TS_APPLICATION_NAME_DESCRIPTOR*)gf_list_get(ait->application->application_descriptors,ait->application->index_app_desc_id);
-//                                     gf_free(name_descriptor->application_name_char);
-//                                     gf_free(name_descriptor);
-//                                     break;
-//                             }
-//                     case TRANSPORT_PROTOCOL_DESCRIPTOR:
-//                             {
-//                                     u64 pre_processing_pos;
-//                                     GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor = (GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR*)gf_list_get(ait->application->application_descriptors,ait->application->index_app_desc_id);
-//                                     
-// 
-//                                     switch(protocol_descriptor->protocol_id){
-//                                             case CAROUSEL:
-//                                                     {
-//                                                             GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte = (GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE*)protocol_descriptor->selector_byte;
-//                                                             gf_free(Carousel_selector_byte);
-//                                                             break;
-//                                                     }
-//                                             case TRANSPORT_HTTP:
-//                                                     {                                       
-//                                                             u32 i;                                                          
-//                                                             GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte = (GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE*)protocol_descriptor->selector_byte;
-//                                                             gf_free(Transport_http_selector_byte->URL_base_byte);
-//                                                             if(Transport_http_selector_byte->URL_extension_count){
-//                                                                     for(i = 0; i < Transport_http_selector_byte->URL_extension_count;i++){
-//                                                                             Transport_http_selector_byte->URL_extentions[i].URL_extension_length = gf_bs_read_int(bs,8);
-//                                                                             gf_free(Transport_http_selector_byte->URL_extentions[i].URL_extension_byte)
-//                                                                     }
-//                                                                     gf_free(Transport_http_selector_byte->URL_extentions);
-//                                                             }
-//                                                             gf_free(Transport_http_selector_byte);
-//                                                             break;
-//                                                     }
-//                                             default:
-//                                                     {
-//                                                             GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Protocol ID %d unsupported, ignoring the selector byte \n",protocol_descriptor->protocol_id));
-//                                                     }
-//                                     }                                       
-//                                     gf_free(protocol_descriptor);                                   
-//                                     break;
-//                             }
-//                     case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR:
-//                             {                       
-//                                     GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location = (GF_M2TS_SIMPLE_APPLICATION_LOCATION*)gf_list_get(ait->application->application_descriptors,ait->application->index_app_desc_id);
-//                                     gf_free(Simple_application_location->initial_path_bytes);
-//                                     gf_free(Simple_application_location);
-//                                     break;
-//                             }
-//                     case APPLICATION_USAGE_DESCRIPTOR:
-//                             {
-//                                     GF_M2TS_APPLICATION_USAGE* Application_usage = (GF_M2TS_SIMPLE_APPLICATION_LOCATION*)gf_list_get(ait->application->application_descriptors,ait->application->index_app_desc_id);
-//                                     gf_free(Application_usage);
-//                                     break;
-//                             }
-//                     default:
-//                             {
-//                                     GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor tag %d unknown, ignoring the descriptor \n",temp_descriptor_tag));
-//                             }
-// 
-//                     }
-//                      gf_list_rem(ait->application->application_descriptors,ait->application->index_app_desc_id);
-// 
-//             }
-//             gf_list_del(ait->application->application_descriptors);
-//       }
-//       gf_list_del(ait->application);
-//       
-//     };
-       
-}
\ No newline at end of file
diff --git a/src/media_tools/dsmcc.c b/src/media_tools/dsmcc.c
new file mode 100644 (file)
index 0000000..6b3e02c
--- /dev/null
@@ -0,0 +1,1938 @@
+/* \r
+ * Copyright (c) TELECOM ParisTech 2011\r
+ */\r
+\r
+#include <gpac/dsmcc.h>\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+/* DSMCC */\r
+\r
+\r
+\r
+/* static functions */\r
+static GF_Err dsmcc_download_data_validation(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 downloadId);\r
+static GF_Err gf_m2ts_dsmcc_process_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc, char* data,GF_BitStream *bs,u32* data_shift);\r
+static GF_Err gf_m2ts_dsmcc_process_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader, char* data,GF_BitStream *bs,u32* data_shift,u32 mode);\r
+static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char  *data, GF_BitStream *bs,u32* data_shift);\r
+static GF_Err gf_m2ts_dsmcc_section_delete(GF_M2TS_DSMCC_SECTION *dsmcc);\r
+static GF_Err gf_m2ts_dsmcc_delete_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader);\r
+static GF_Err gf_m2ts_dsmcc_delete_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc);\r
+\r
+\r
+static GF_Err dsmcc_module_delete(GF_M2TS_DSMCC_MODULE* dsmcc_module);\r
+//static GF_Err dsmcc_module_state(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 moduleId,u32 moduleVersion);\r
+static GF_Err dsmcc_create_module_validation(GF_M2TS_DSMCC_INFO_MODULES* InfoModules, u32 downloadId, GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 nb_module);\r
+static GF_Err dsmcc_module_complete(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 moduleIndex);\r
+static GF_Err dsmcc_get_biop_module_info(GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u8 data_size);\r
+static GF_M2TS_DSMCC_MODULE* dsmcc_create_module(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord, GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication);\r
+\r
+/* BIOP */\r
+static GF_Err dsmcc_process_biop_data(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u32 data_size);\r
+static GF_M2TS_DSMCC_BIOP_HEADER* dsmcc_process_biop_header(GF_BitStream* bs);\r
+static GF_Err dsmcc_process_biop_file(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,u16 moduleId,u32 downloadId);\r
+static GF_Err dsmcc_process_biop_directory(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,Bool IsServiceGateway);\r
+static GF_Err dsmcc_process_biop_stream_event(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway);\r
+static GF_Err dsmcc_process_biop_stream_message(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway);\r
+\r
+/* Tools */\r
+static void dsmcc_biop_get_context(GF_BitStream* bs,GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count);\r
+static void dsmcc_biop_descriptor(GF_BitStream* bs,GF_List* list,u32 size);\r
+static GF_Err dsmcc_biop_get_ior(GF_BitStream* bs,GF_M2TS_DSMCC_IOR* IOR);\r
+static GF_M2TS_DSMCC_DIR* dsmcc_get_directory(GF_List* List, u32 objectKey_data);\r
+static GF_M2TS_DSMCC_FILE* dsmcc_get_file(GF_List* ServiceGatewayList,u16 moduleId,u32 downloadId,u32 objectKey_data);\r
+static GF_Err dsmcc_check_element_validation(GF_List* List,char* Parent_name,GF_M2TS_DSMCC_BIOP_NAME Name);\r
+static char* dsmcc_get_file_namepath(GF_M2TS_DSMCC_DIR* Dir,char* name);\r
+\r
+/* Free */\r
+static void dsmcc_free_biop_context(GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count);\r
+static void dsmcc_free_biop_name(GF_M2TS_DSMCC_BIOP_NAME* Name, u32 nb_name);\r
+static void dsmcc_free_biop_descriptor(GF_List* list);\r
+static void dsmcc_free_biop_ior(GF_M2TS_DSMCC_IOR* IOR);\r
+static void dsmcc_free_biop_header(GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header);\r
+static void dsmcc_free_biop_directory(GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory);\r
+static void dsmcc_free_biop_file(GF_M2TS_DSMCC_BIOP_FILE* BIOP_File);\r
+static void dsmcc_free_biop_stream_event(GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent);\r
+static void dsmcc_free_biop_stream_message(GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage);\r
+\r
+GF_M2TS_DSMCC_OVERLORD* gf_m2ts_init_dsmcc_overlord(u32 service_id) {\r
+       GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord;\r
+       GF_SAFEALLOC(dsmcc_overlord,GF_M2TS_DSMCC_OVERLORD);    \r
+       dsmcc_overlord->dsmcc_modules = gf_list_new();\r
+       dsmcc_overlord->service_id = service_id;\r
+       return dsmcc_overlord;\r
+}\r
+\r
+GF_M2TS_DSMCC_OVERLORD* gf_m2ts_get_dmscc_overlord(GF_List* Dsmcc_controller,u32 service_id) \r
+{\r
+       u16 nb_dsmcc,i;\r
+\r
+       nb_dsmcc = gf_list_count(Dsmcc_controller);\r
+\r
+       if(!nb_dsmcc){\r
+               return NULL;\r
+       }else{\r
+               for(i =0;i<nb_dsmcc;i++){\r
+                       GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = (GF_M2TS_DSMCC_OVERLORD*)gf_list_get(Dsmcc_controller,i);\r
+                       if(dsmcc_overlord->service_id == service_id){\r
+                               return dsmcc_overlord;\r
+                       }\r
+               }\r
+       }\r
+       return NULL;\r
+}\r
+\r
+void on_dsmcc_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) \r
+{\r
+       GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)par;\r
+       char *data;\r
+       u32 u32_data_size;\r
+       u32 u32_table_id;\r
+       GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord;\r
+\r
+       dsmcc_overlord = gf_m2ts_get_dmscc_overlord(ts->dsmcc_controler,pck->stream->service_id);\r
+\r
+       if (dsmcc_overlord && evt_type == GF_M2TS_EVT_DSMCC_FOUND) {\r
+               GF_Err e;\r
+               GF_M2TS_DSMCC_SECTION* dsmcc;\r
+               data = pck->data;\r
+               u32_data_size = pck->data_len;\r
+               u32_table_id = data[0]; \r
+               GF_SAFEALLOC(dsmcc,GF_M2TS_DSMCC_SECTION);\r
+\r
+               e = gf_m2ts_process_dsmcc(dsmcc_overlord,dsmcc,data,u32_data_size,u32_table_id);\r
+               if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_DSMCC_FOUND, pck);\r
+               assert(e == GF_OK);\r
+       }\r
+}\r
+\r
+GF_Err gf_m2ts_process_dsmcc(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char  *data, u32 data_size, u32 table_id)\r
+{\r
+       GF_BitStream *bs;       \r
+       u32 data_shift,reserved_test;\r
+\r
+       data_shift = 0;\r
+       //first_section = *first_section_received;\r
+       bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ);\r
+\r
+       dsmcc->table_id = gf_bs_read_int(bs,8); \r
+       dsmcc->section_syntax_indicator = gf_bs_read_int(bs,1);\r
+       dsmcc->private_indicator = gf_bs_read_int(bs,1);\r
+       reserved_test = gf_bs_read_int(bs,2);\r
+       if (reserved_test != 3) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] test reserved flag is not at 3. Corrupted section, abording processing\n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       dsmcc->dsmcc_section_length = gf_bs_read_int(bs,12);\r
+       if (dsmcc->dsmcc_section_length > DSMCC_SECTION_LENGTH_MAX) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] section length should not exceed 4096. Wrong section, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       dsmcc->table_id_extension = gf_bs_read_int(bs,16);\r
+\r
+       /*bit shifting */\r
+       gf_bs_read_int(bs,2);\r
+\r
+       dsmcc->version_number = gf_bs_read_int(bs,5);\r
+       if(dsmcc->version_number != 0 &&(dsmcc->table_id == GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA || dsmcc->table_id == GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE)){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Version number should be 0 for Encapsulated Data or UN Message, abording processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+\r
+       dsmcc->current_next_indicator = gf_bs_read_int(bs,1);   \r
+       if (!dsmcc->current_next_indicator) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] current next indicator should be at 1 \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       dsmcc->section_number = gf_bs_read_int(bs,8);\r
+       /*if(dsmcc->section_number >0 && ((*first_section_received) == 0)){\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Wainting for the first section \n"));\r
+       return GF_CORRUPTED_DATA;\r
+       }\r
+       *first_section_received = 1;*/\r
+       dsmcc->last_section_number = gf_bs_read_int(bs,8);      \r
+       //printf("\nsection_number %d last_section_number %d\n",dsmcc->section_number,dsmcc->last_section_number);\r
+       //printf("dsmcc->table_id %d \n",dsmcc->table_id);\r
+       switch (dsmcc->table_id) {\r
+               case GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA:\r
+                       {\r
+                               data_shift = (u32)(gf_bs_get_position(bs));\r
+                               break;\r
+                       }\r
+               case GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE:                        \r
+               case GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE:\r
+                       {\r
+                               data_shift = (u32)(gf_bs_get_position(bs));                             \r
+                               gf_m2ts_dsmcc_download_data(dsmcc_overlord,dsmcc,data,bs,&data_shift);                          \r
+                               break;\r
+                       }\r
+               case GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION:\r
+                       {\r
+                               data_shift = (u32)(gf_bs_get_position(bs));\r
+                               break;\r
+                       }\r
+               default:\r
+                       {\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown DSMCC Section Type \n"));               \r
+                               break;\r
+                       }\r
+       }\r
+\r
+       if (dsmcc->section_syntax_indicator == 0) {\r
+               dsmcc->checksum = gf_bs_read_int(bs,32);        \r
+       } else {\r
+               dsmcc->CRC_32= gf_bs_read_int(bs,32);\r
+       }\r
+\r
+       data_shift = (u32)(gf_bs_get_position(bs));\r
+\r
+       /*if(data_shift != dsmcc->dsmcc_section_length){.\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] AIT processed length error. Difference between byte shifting %d and data size %d \n",data_shift,data_size));\r
+       return GF_CORRUPTED_DATA;\r
+       }*/\r
+\r
+       //gf_m2ts_dsmcc_extract_info(ts,dsmcc);\r
+       gf_m2ts_dsmcc_section_delete(dsmcc);\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char  *data, GF_BitStream *bs,u32* data_shift)\r
+{\r
+       GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE* DataMessage;\r
+       GF_SAFEALLOC(DataMessage,GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE);\r
+\r
+       /* Header */\r
+       gf_m2ts_dsmcc_process_message_header(&DataMessage->DownloadDataHeader,data,bs,data_shift,1);\r
+       dsmcc->DSMCC_Extension = DataMessage;\r
+\r
+       //printf("DataMessage->DownloadDataHeader.messageId %d \n",DataMessage->DownloadDataHeader.messageId);\r
+\r
+       switch (DataMessage->DownloadDataHeader.messageId)\r
+       {\r
+       case DOWNLOAD_INFO_REQUEST:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST*  DownloadInfoRequest;\r
+                       GF_SAFEALLOC(DownloadInfoRequest,GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST);\r
+                       DataMessage->dataMessagePayload = DownloadInfoRequest;\r
+\r
+                       /* Payload */\r
+                       DownloadInfoRequest->bufferSize = gf_bs_read_int(bs,32);\r
+                       DownloadInfoRequest->maximumBlockSize = gf_bs_read_int(bs,16);\r
+                       gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadInfoRequest->CompatibilityDescr,data,bs,data_shift);\r
+                       DownloadInfoRequest->privateDataLength = gf_bs_read_int(bs,16);\r
+                       DownloadInfoRequest->privateDataByte = (char*)gf_calloc(DownloadInfoRequest->privateDataLength,sizeof(char));\r
+                       gf_bs_read_data(bs,DownloadInfoRequest->privateDataByte,(u32)(DownloadInfoRequest->privateDataLength));\r
+                       break;\r
+               }\r
+       case DOWNLOAD_INFO_REPONSE_INDICATION:          \r
+               {\r
+                       u32 i,nb_modules;\r
+                       GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication;\r
+                       GF_SAFEALLOC(DownloadInfoIndication,GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC);\r
+                       DataMessage->dataMessagePayload = DownloadInfoIndication;\r
+\r
+                       /* Payload */\r
+                       DownloadInfoIndication->downloadId = gf_bs_read_int(bs,32);\r
+                       DownloadInfoIndication->blockSize = gf_bs_read_int(bs,16);\r
+                       DownloadInfoIndication->windowSize = gf_bs_read_int(bs,8);\r
+                       DownloadInfoIndication->ackPeriod = gf_bs_read_int(bs,8);\r
+                       DownloadInfoIndication->tCDownloadWindow = gf_bs_read_int(bs,32);\r
+                       DownloadInfoIndication->tCDownloadScenario = gf_bs_read_int(bs,32);\r
+\r
+                       /* Compatibility Descr */\r
+                       gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadInfoIndication->CompatibilityDescr,data,bs,data_shift);\r
+                       DownloadInfoIndication->numberOfModules = gf_bs_read_int(bs,16);\r
+                       /* Versioning of the DownloadInfoIndication is made by the field transactionId (here known as downloadId) */\r
+                       if(DataMessage->DownloadDataHeader.downloadId > dsmcc_overlord->transactionId){\r
+                               dsmcc_overlord->transactionId = DataMessage->DownloadDataHeader.downloadId;\r
+                               nb_modules = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+                               for(i = 0;i<DownloadInfoIndication->numberOfModules;i++){\r
+                                       DownloadInfoIndication->Modules.moduleId = gf_bs_read_int(bs,16);\r
+                                       DownloadInfoIndication->Modules.moduleSize = gf_bs_read_int(bs,32);\r
+                                       DownloadInfoIndication->Modules.moduleVersion = gf_bs_read_int(bs,8);\r
+                                       DownloadInfoIndication->Modules.moduleInfoLength = gf_bs_read_int(bs,8);                                \r
+                                       DownloadInfoIndication->Modules.moduleInfoByte = (char*)gf_calloc(DownloadInfoIndication->Modules.moduleInfoLength,sizeof(char));\r
+                                       gf_bs_read_data(bs,DownloadInfoIndication->Modules.moduleInfoByte,(u32)(DownloadInfoIndication->Modules.moduleInfoLength));\r
+                                       if(!dsmcc_create_module_validation(&DownloadInfoIndication->Modules,DownloadInfoIndication->downloadId,dsmcc_overlord,nb_modules)){\r
+                                               /* Creation of the module */\r
+                                               GF_M2TS_DSMCC_MODULE*dsmcc_module = dsmcc_create_module(dsmcc_overlord,DownloadInfoIndication);\r
+                                               if(DownloadInfoIndication->Modules.moduleInfoLength){\r
+                                                       GF_Err e;\r
+                                                       e = dsmcc_get_biop_module_info(dsmcc_module,DownloadInfoIndication->Modules.moduleInfoByte,DownloadInfoIndication->Modules.moduleInfoLength);\r
+                                                       if(e){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in BIOP Module Info for module %d, abording the processing \n",dsmcc_module->moduleId));\r
+                                                               gf_free(DownloadInfoIndication->Modules.moduleInfoByte);\r
+                                                               DownloadInfoIndication->Modules.moduleInfoByte = NULL;\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }                                               \r
+                                               }\r
+                                       }\r
+                                       gf_free(DownloadInfoIndication->Modules.moduleInfoByte);\r
+                                       DownloadInfoIndication->Modules.moduleInfoByte = NULL;\r
+                               }\r
+                               DownloadInfoIndication->privateDataLength = gf_bs_read_int(bs,16);    \r
+                               DownloadInfoIndication->privateDataByte = (char*)gf_calloc(DownloadInfoIndication->privateDataLength,sizeof(char));\r
+                               gf_bs_read_data(bs,DownloadInfoIndication->privateDataByte,(u32)(DownloadInfoIndication->privateDataLength));\r
+                       }\r
+                       break;\r
+               }\r
+       case DOWNLOAD_DATA_BLOCK:\r
+               {                               \r
+                       u32 data_shift,modules_count,i;\r
+                       GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock;\r
+                       GF_SAFEALLOC(DownloadDataBlock,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK);\r
+                       DataMessage->dataMessagePayload = DownloadDataBlock;\r
+                       modules_count = 0;\r
+                       modules_count = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+\r
+                       if(!modules_count){\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Download Information Indicator has not been received yet, waiting before processing data block \n"));\r
+                               break;\r
+                       }\r
+\r
+\r
+                       DownloadDataBlock->moduleId = gf_bs_read_int(bs,16);\r
+                       //printf("DownloadDataBlock->moduleId %d \n",DownloadDataBlock->moduleId);\r
+                       DownloadDataBlock->moduleVersion = gf_bs_read_int(bs,8); \r
+                       DownloadDataBlock->reserved = gf_bs_read_int(bs,8);\r
+                       if(DownloadDataBlock->reserved != 0xFF){\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader reserved slot does not have the correct value, abording the processing \n"));\r
+                               return GF_CORRUPTED_DATA;\r
+                       }\r
+                       DownloadDataBlock->blockNumber = gf_bs_read_int(bs,16);\r
+                               \r
+                       for(i=0;i<modules_count;i++){\r
+                               GF_M2TS_DSMCC_MODULE* dsmcc_module = gf_list_get(dsmcc_overlord->dsmcc_modules,i);\r
+                               /* Test if the data are compatible with the module configuration */\r
+                               if(!dsmcc_download_data_validation(dsmcc_overlord,DownloadDataBlock,dsmcc_module,DataMessage->DownloadDataHeader.downloadId)){\r
+                                       //printf("DownloadDataBlock->blockNumber %d \n\n",DownloadDataBlock->blockNumber);\r
+                                       DownloadDataBlock->dataBlocksize = (DataMessage->DownloadDataHeader.messageLength - 6);                                 \r
+                                       if(dsmcc_module->block_size < DownloadDataBlock->dataBlocksize){\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error block_size should be >= to DownloadDataBlock->dataBlocksize , abording the processing \n"));\r
+                                               return GF_CORRUPTED_DATA;\r
+                                       }\r
+                                       DownloadDataBlock->blockDataByte = (char*)gf_calloc(DownloadDataBlock->dataBlocksize,sizeof(char));\r
+                                       data_shift = (u32)(gf_bs_get_position(bs));\r
+                                       gf_bs_read_data(bs,DownloadDataBlock->blockDataByte,DownloadDataBlock->dataBlocksize);\r
+                                       memcpy(dsmcc_module->buffer+dsmcc_module->byte_sift,DownloadDataBlock->blockDataByte,DownloadDataBlock->dataBlocksize*sizeof(char));\r
+                                       dsmcc_module->byte_sift += DownloadDataBlock->dataBlocksize;                                                                    \r
+                                       dsmcc_module->last_section_number = dsmcc->last_section_number;\r
+                                       dsmcc_module->section_number++;\r
+                                       if(dsmcc_module->section_number == (dsmcc_module->last_section_number+1)){                                              \r
+                                               dsmcc_module_complete(dsmcc_overlord,dsmcc_module,i);                                           \r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }                               \r
+                       \r
+                       break;                  \r
+               }               \r
+       case DOWNLOAD_DATA_REQUEST:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE* DownloadDataRequest;\r
+                       GF_SAFEALLOC(DownloadDataRequest,GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE);\r
+                       DataMessage->dataMessagePayload = DownloadDataRequest;  \r
+                       DownloadDataRequest->moduleId = gf_bs_read_int(bs,16);\r
+                       DownloadDataRequest->blockNumber = gf_bs_read_int(bs,16);\r
+                       DownloadDataRequest->downloadReason  = gf_bs_read_int(bs,8);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_DATA_CANCEL:\r
+\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_CANCEL* DownloadCancel;\r
+                       GF_SAFEALLOC(DownloadCancel,GF_M2TS_DSMCC_DOWNLOAD_CANCEL);\r
+                       DataMessage->dataMessagePayload = DownloadCancel;       \r
+                       DownloadCancel->downloadId = gf_bs_read_int(bs,32);\r
+                       DownloadCancel->moduleId = gf_bs_read_int(bs,16);\r
+                       DownloadCancel->blockNumber = gf_bs_read_int(bs,16);\r
+                       DownloadCancel->downloadCancelReason = gf_bs_read_int(bs,8);\r
+                       DownloadCancel->reserved = gf_bs_read_int(bs,8);\r
+                       DownloadCancel->privateDataLength = gf_bs_read_int(bs,16);\r
+                       if(DownloadCancel->privateDataLength){\r
+                               DownloadCancel->privateDataByte = (char*)gf_calloc(DownloadCancel->privateDataLength,sizeof(char));\r
+                               gf_bs_read_data(bs,DownloadCancel->privateDataByte,(u32)(DownloadCancel->privateDataLength));\r
+                       }\r
+                       break;\r
+\r
+               }\r
+       case DOWNLOAD_SERVER_INITIATE:\r
+\r
+               {\r
+                       u32 localbyteshift;\r
+                       GF_Err e;\r
+                       GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT* DownloadServerInit;\r
+                       GF_SAFEALLOC(DownloadServerInit,GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT);\r
+                       DataMessage->dataMessagePayload = DownloadServerInit;\r
+                       localbyteshift = (u32)(gf_bs_get_position(bs));\r
+                       gf_bs_read_data(bs,DownloadServerInit->serverId,20);                    \r
+                       gf_m2ts_dsmcc_process_compatibility_descriptor(&DownloadServerInit->CompatibilityDescr,data,bs,data_shift);\r
+                       DownloadServerInit->privateDataLength = gf_bs_read_int(bs,16);\r
+                       if(DownloadServerInit->privateDataLength){\r
+\r
+                               u32 i;\r
+\r
+                               GF_M2TS_DSMCC_SERVICE_GATEWAY_INFO* ServiceGateWayInfo;\r
+                               GF_SAFEALLOC(ServiceGateWayInfo,GF_M2TS_DSMCC_SERVICE_GATEWAY_INFO);\r
+\r
+                               /* IOR */\r
+                               e = dsmcc_biop_get_ior(bs,&ServiceGateWayInfo->IOR);\r
+                               if(e){\r
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted IOR, abording the processing \n"));\r
+                                       gf_free(ServiceGateWayInfo);\r
+                                       return GF_CORRUPTED_DATA;       \r
+                               }\r
+                               ServiceGateWayInfo->downloadTaps_count = gf_bs_read_int(bs,8);\r
+                               ServiceGateWayInfo->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(ServiceGateWayInfo->downloadTaps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS));\r
+                               for(i=0;i<ServiceGateWayInfo->downloadTaps_count;i++){\r
+                                       ServiceGateWayInfo->Taps[i].id = gf_bs_read_int(bs,16);                                 \r
+                                       ServiceGateWayInfo->Taps[i].use = gf_bs_read_int(bs,16);                                        \r
+                                       ServiceGateWayInfo->Taps[i].assocTag = gf_bs_read_int(bs,16);\r
+                                       ServiceGateWayInfo->Taps[i].selector_length = gf_bs_read_int(bs,8);                                     \r
+                                       ServiceGateWayInfo->Taps[i].selector_type = gf_bs_read_int(bs,16);                                      \r
+                                       ServiceGateWayInfo->Taps[i].transactionId = gf_bs_read_int(bs,32);\r
+                                       ServiceGateWayInfo->Taps[i].timeout = gf_bs_read_int(bs,32);\r
+                               }\r
+                               ServiceGateWayInfo->serviceContextList_count = gf_bs_read_int(bs,8);\r
+                               ServiceGateWayInfo->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(ServiceGateWayInfo->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT));\r
+                               dsmcc_biop_get_context(bs,ServiceGateWayInfo->ServiceContext,ServiceGateWayInfo->serviceContextList_count);\r
+                               ServiceGateWayInfo->userInfoLength = gf_bs_read_int(bs,16);\r
+                               if(ServiceGateWayInfo->userInfoLength != 0){\r
+                                       ServiceGateWayInfo->userInfo_data = (char*)gf_calloc(ServiceGateWayInfo->userInfoLength,sizeof(char));\r
+                                       gf_bs_read_data(bs,ServiceGateWayInfo->userInfo_data,(u32)(ServiceGateWayInfo->userInfoLength));\r
+                               }\r
+\r
+                               if(!dsmcc_overlord->ServiceGateway && gf_list_count(ServiceGateWayInfo->IOR.taggedProfile)){\r
+                                       GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(ServiceGateWayInfo->IOR.taggedProfile,0);\r
+                                       dsmcc_overlord->ServiceGateway = (GF_M2TS_DSMCC_SERVICE_GATEWAY*)gf_calloc(1,sizeof(GF_M2TS_DSMCC_SERVICE_GATEWAY));\r
+                                       dsmcc_overlord->ServiceGateway->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId;\r
+                                       dsmcc_overlord->ServiceGateway->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId;\r
+                                       dsmcc_overlord->ServiceGateway->service_id = dsmcc_overlord->service_id;\r
+                                       dsmcc_overlord->ServiceGateway->File = gf_list_new();\r
+                                       dsmcc_overlord->ServiceGateway->Dir = gf_list_new();\r
+                               }\r
+                       }\r
+\r
+                       break;\r
+               }\r
+\r
+       default:\r
+               {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown dataMessagePayload Type \n"));\r
+                       break;\r
+               }\r
+       }\r
+\r
+       //dsmcc->DSMCC_Extension = DataMessage;\r
+\r
+       return GF_OK;\r
+}\r
+\r
+\r
+\r
+\r
+static GF_Err gf_m2ts_dsmcc_process_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader, char* data,GF_BitStream *bs,u32* data_shift,u32 mode)\r
+{\r
+       u32 byte_shift;\r
+\r
+       byte_shift = *data_shift;\r
+\r
+       MessageHeader->protocolDiscriminator = gf_bs_read_int(bs,8);\r
+       if (MessageHeader->protocolDiscriminator != 0x11) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader Protocol Discriminator slot does not have the correct value, abording the processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       MessageHeader->dsmccType = gf_bs_read_int(bs,8);\r
+       MessageHeader->messageId = gf_bs_read_int(bs,16);\r
+       /* mode 0 for Message Header - 1 for Download Data header */\r
+       if (mode == 0) {\r
+               MessageHeader->transactionId = gf_bs_read_int(bs,32);\r
+       } else if (mode == 1) {\r
+               MessageHeader->downloadId = gf_bs_read_int(bs,32);\r
+       }\r
+       //printf("MessageHeader->downloadId %d \n",MessageHeader->downloadId);\r
+       MessageHeader->reserved = gf_bs_read_int(bs,8);\r
+       if (MessageHeader->reserved != 0xFF) {\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader reserved slot does not have the correct value, abording the processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       MessageHeader->adaptationLength = gf_bs_read_int(bs,8);\r
+       MessageHeader->header_length = ((u32)(gf_bs_get_position(bs)) - byte_shift);\r
+       MessageHeader->messageLength = gf_bs_read_int(bs,16);\r
+\r
+       if (MessageHeader->adaptationLength > 0) {\r
+               MessageHeader->DsmccAdaptationHeader = (GF_M2TS_DSMCC_ADAPTATION_HEADER*)gf_calloc(1, sizeof(GF_M2TS_DSMCC_ADAPTATION_HEADER));\r
+               MessageHeader->DsmccAdaptationHeader->adaptationType = gf_bs_read_int(bs,8);\r
+\r
+               MessageHeader->DsmccAdaptationHeader->adaptationDataByte = (char*)gf_calloc(MessageHeader->adaptationLength-1,sizeof(char));\r
+               gf_bs_read_data(bs,MessageHeader->DsmccAdaptationHeader->adaptationDataByte,(u32)(MessageHeader->adaptationLength));\r
+\r
+       }\r
+\r
+       *data_shift = (u32)(gf_bs_get_position(bs));\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err gf_m2ts_dsmcc_process_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc, char* data,GF_BitStream *bs,u32* data_shift)\r
+{\r
+       u32 i,j,byte_shift;\r
+\r
+       byte_shift = (u32)(gf_bs_get_position(bs));\r
+\r
+       CompatibilityDesc->compatibilityDescriptorLength = gf_bs_read_int(bs,16);\r
+\r
+       if(CompatibilityDesc->compatibilityDescriptorLength){\r
+               CompatibilityDesc->descriptorCount = gf_bs_read_int(bs,16);\r
+               if(CompatibilityDesc->descriptorCount){\r
+                       CompatibilityDesc->Descriptor = (GF_M2TS_DSMCC_DESCRIPTOR*)gf_calloc(CompatibilityDesc->descriptorCount,sizeof(GF_M2TS_DSMCC_DESCRIPTOR));\r
+                       for(i=0;i<CompatibilityDesc->descriptorCount;i++){\r
+                               CompatibilityDesc->Descriptor[i].descriptorType = gf_bs_read_int(bs,8);\r
+                               CompatibilityDesc->Descriptor[i].descriptorLength = gf_bs_read_int(bs,8);\r
+                               CompatibilityDesc->Descriptor[i].specifierType = gf_bs_read_int(bs,8);\r
+                               CompatibilityDesc->Descriptor[i].specifierData = gf_bs_read_int(bs,21);\r
+                               CompatibilityDesc->Descriptor[i].model = gf_bs_read_int(bs,16);\r
+                               CompatibilityDesc->Descriptor[i].version = gf_bs_read_int(bs,16);\r
+                               CompatibilityDesc->Descriptor[i].subDescriptorCount = gf_bs_read_int(bs,8);\r
+                               if(CompatibilityDesc->Descriptor[i].subDescriptorCount){\r
+                                       CompatibilityDesc->Descriptor[i].SubDescriptor  = (GF_M2TS_DSMCC_SUBDESCRIPTOR*)gf_calloc(CompatibilityDesc->Descriptor[i].subDescriptorCount,sizeof(GF_M2TS_DSMCC_SUBDESCRIPTOR));\r
+                                       for(j=0;j>CompatibilityDesc->Descriptor[i].subDescriptorCount;j++){\r
+                                               CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorType = gf_bs_read_int(bs,8);\r
+                                               CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength = gf_bs_read_int(bs,8);\r
+                                               if(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength){\r
+                                                       CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation = (char*)gf_calloc(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength,sizeof(char));\r
+                                                       gf_bs_read_data(bs,CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation,(u32)(CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength));\r
+                                               }\r
+\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       *data_shift = (u32)(gf_bs_get_position(bs));\r
+       if(*data_shift != byte_shift+2+CompatibilityDesc->compatibilityDescriptorLength){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Descriptor length not respected, difference between %d and %d \n",(*data_shift - byte_shift),2+CompatibilityDesc->compatibilityDescriptorLength));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_create_module_validation(GF_M2TS_DSMCC_INFO_MODULES* InfoModules, u32 downloadId, GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 nb_module){\r
+\r
+       u32 i;\r
+       for (i=0; i<nb_module; i++) {\r
+               GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i];\r
+               if ((InfoModules->moduleId == dsmcc_process.moduleId) && (downloadId == dsmcc_process.downloadId)) {\r
+                       if (InfoModules->moduleVersion <= dsmcc_process.version_number) {\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Module already intialized \n"));\r
+                               return GF_CORRUPTED_DATA;\r
+                       } else if (InfoModules->moduleVersion > dsmcc_process.version_number) {\r
+                               GF_M2TS_DSMCC_MODULE* dsmcc_module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->dsmcc_modules,i);\r
+                               dsmcc_module_delete(dsmcc_module);\r
+                               gf_list_rem(dsmcc_overlord->dsmcc_modules,i);\r
+                               dsmcc_process.version_number = InfoModules->moduleVersion;\r
+                               dsmcc_process.done = 0;\r
+                               return GF_OK;\r
+                       }\r
+               }\r
+       }\r
+       return  GF_OK;\r
+}\r
+\r
+//static GF_Err dsmcc_module_state(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,u32 moduleId,u32 moduleVersion){\r
+//\r
+//     u32 i,nb_module;\r
+//     nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+//     /* This test comes from the fact that the moduleVersion only borrow the least 5 significant bits of the moduleVersion conveys in DownloadDataBlock */\r
+//     /* If the moduleVersion is eq to 0x1F, it does not tell if it is clearly 0x1F or a superior value. So in this case it is better to process the data */\r
+//     /* If the moduleVersion is eq to 0x0, it means that the data conveys a DownloadDataResponse, so it has to be processed */\r
+//     if (moduleVersion != 0 || moduleVersion < 0x1F) {\r
+//             for (i=0; i<nb_module; i++) {\r
+//                     GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i];\r
+//                     if ((moduleId == dsmcc_process.moduleId) && (moduleVersion <= dsmcc_process.version_number)) {\r
+//                             if (dsmcc_process.done) {\r
+//                                     GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Module already processed \n"));\r
+//                                     return GF_CORRUPTED_DATA;\r
+//                             } else {\r
+//                                     return GF_OK;   \r
+//                             }\r
+//                     }\r
+//             }\r
+//     }\r
+//     return  GF_OK;\r
+//}\r
+\r
+static GF_Err dsmcc_download_data_validation(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 downloadId)\r
+{\r
+       /* It checks if the module Id is eq to the SGW's module Id if Got_ServiceGateway is null (means that the SWG has not been processed yet \r
+               If then Got_ServiceGateway = 1, all the module are processed */\r
+       if(dsmcc_overlord->ServiceGateway){\r
+               if ((dsmcc_overlord->Got_ServiceGateway || dsmcc_module->moduleId == dsmcc_overlord->ServiceGateway->moduleId)&&\r
+                       ((dsmcc_module->moduleId == DownloadDataBlock->moduleId) && (dsmcc_module->section_number == DownloadDataBlock->blockNumber) &&\r
+                       (dsmcc_module->downloadId == downloadId) && (dsmcc_module->version_number == DownloadDataBlock->moduleVersion))){                       \r
+                               return GF_OK;\r
+               }\r
+       }\r
+       \r
+       return GF_CORRUPTED_DATA;\r
+}\r
+\r
+static GF_Err dsmcc_module_complete(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,u32 moduleIndex)\r
+{\r
+       u32 i,nb_module;\r
+       GF_Err e;\r
+       e = GF_OK;\r
+       nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+       for (i=0; i<nb_module; i++) {\r
+               GF_M2TS_DSMCC_PROCESSED dsmcc_process = dsmcc_overlord->processed[i];\r
+               if ((dsmcc_module->moduleId == dsmcc_process.moduleId) && dsmcc_module->version_number == dsmcc_process.version_number && dsmcc_module->downloadId == dsmcc_process.downloadId) {\r
+                       /*process buffer*/\r
+                       if(dsmcc_module->Gzip){\r
+                               u32 uncomp_size;\r
+                               char* uncompressed_data;\r
+\r
+                               gf_gz_decompress_payload(dsmcc_module->buffer,dsmcc_module->byte_sift,&uncompressed_data, &uncomp_size);\r
+                               //dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,uncompressed_data,dsmcc_module->original_size);\r
+                               \r
+                               if(dsmcc_module->original_size == uncomp_size){\r
+                                       e = dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,uncompressed_data,dsmcc_module->original_size);\r
+                               }else{\r
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Buffer size is not equal to the module size. Flushing the data \n"));\r
+                                       gf_free(dsmcc_module->buffer);\r
+                                       dsmcc_module->buffer = NULL;\r
+                                       dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char));\r
+                                       dsmcc_module->section_number = 0;\r
+                                       return GF_CORRUPTED_DATA;\r
+                               }\r
+                       }else{\r
+                               e = dsmcc_process_biop_data(dsmcc_overlord,dsmcc_module,dsmcc_module->buffer,dsmcc_module->size);                               \r
+                       }\r
+                       if(e){\r
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the processing of the module data. Flushing the data \n"));\r
+                                       gf_free(dsmcc_module->buffer);\r
+                                       dsmcc_module->buffer = NULL;\r
+                                       dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char));\r
+                                       dsmcc_module->section_number = 0;\r
+                                       return GF_CORRUPTED_DATA;\r
+                       }else{\r
+                               dsmcc_process.done = 1;                 \r
+                               dsmcc_module_delete(dsmcc_module);\r
+                               gf_list_rem(dsmcc_overlord->dsmcc_modules,moduleIndex);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return  GF_OK;\r
+}\r
+\r
+/* Delete structure of the DSMCC data processing */\r
+\r
+static GF_Err gf_m2ts_dsmcc_delete_compatibility_descriptor(GF_M2TS_DSMCC_COMPATIBILITY_DESCRIPTOR *CompatibilityDesc)\r
+{\r
+       u32 i,j;        \r
+       if (CompatibilityDesc->compatibilityDescriptorLength) {\r
+               if (CompatibilityDesc->descriptorCount) {\r
+                       for (i=0; i<CompatibilityDesc->descriptorCount; i++) {\r
+                               if (CompatibilityDesc->Descriptor[i].subDescriptorCount) {\r
+                                       for (j=0; j>CompatibilityDesc->Descriptor[i].subDescriptorCount; j++) {\r
+                                               if (CompatibilityDesc->Descriptor[i].SubDescriptor[j].subDescriptorLength) {\r
+                                                       gf_free(CompatibilityDesc->Descriptor[i].SubDescriptor[j].additionalInformation);\r
+                                               }\r
+                                       }\r
+                                       gf_free(CompatibilityDesc->Descriptor[i].SubDescriptor);\r
+                               }\r
+                       }\r
+                       gf_free(CompatibilityDesc->Descriptor);\r
+               }\r
+       }\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err gf_m2ts_dsmcc_delete_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HEADER *MessageHeader)\r
+{      \r
+       if (MessageHeader->adaptationLength > 0) {              \r
+               gf_free(MessageHeader->DsmccAdaptationHeader->adaptationDataByte);\r
+               gf_free(MessageHeader->DsmccAdaptationHeader);\r
+       }\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err gf_m2ts_dsmcc_section_delete(GF_M2TS_DSMCC_SECTION *dsmcc)\r
+{\r
+       GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE* DataMessage = (GF_M2TS_DSMCC_DOWNLOAD_DATA_MESSAGE*)dsmcc->DSMCC_Extension;        \r
+\r
+       if(!DataMessage){\r
+               return GF_OK;\r
+       }\r
+\r
+       switch (DataMessage->DownloadDataHeader.messageId)\r
+       {\r
+       case DOWNLOAD_INFO_REQUEST:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST*  DownloadInfoRequest = (GF_M2TS_DSMCC_DOWNLOAD_INFO_REQUEST*)DataMessage->dataMessagePayload;\r
+                       if(DownloadInfoRequest->privateDataLength){\r
+                               gf_free(DownloadInfoRequest->privateDataByte);\r
+                       }\r
+                       gf_free(DownloadInfoRequest);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_INFO_REPONSE_INDICATION:\r
+               {                       \r
+                       GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication = (GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC*)DataMessage->dataMessagePayload;\r
+\r
+                       /* Compatibility Descr */\r
+                       gf_m2ts_dsmcc_delete_compatibility_descriptor(&DownloadInfoIndication->CompatibilityDescr);\r
+                       \r
+                       if (DownloadInfoIndication->privateDataLength) {\r
+                               gf_free(DownloadInfoIndication->privateDataByte);\r
+                       }\r
+                       gf_free(DownloadInfoIndication);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_DATA_BLOCK:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK* DownloadDataBlock = (GF_M2TS_DSMCC_DOWNLOAD_DATA_BLOCK*)DataMessage->dataMessagePayload;\r
+                       if (DownloadDataBlock->dataBlocksize) {\r
+                               gf_free(DownloadDataBlock->blockDataByte);\r
+                       }\r
+                       gf_free(DownloadDataBlock);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_DATA_REQUEST:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE* DownloadDataRequest = (GF_M2TS_DSMCC_DOWNLOAD_DATA_REQUEST_MESSAGE*)DataMessage->dataMessagePayload;\r
+                       gf_free(DownloadDataRequest);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_DATA_CANCEL:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_CANCEL* DownloadCancel = (GF_M2TS_DSMCC_DOWNLOAD_CANCEL*)DataMessage->dataMessagePayload;                        \r
+                       if (DownloadCancel->privateDataLength) {\r
+                               gf_free(DownloadCancel->privateDataByte);\r
+                       }\r
+                       gf_free(DownloadCancel);\r
+                       break;\r
+               }\r
+       case DOWNLOAD_SERVER_INITIATE:\r
+               {\r
+                       GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT* DownloadServerInit = (GF_M2TS_DSMCC_DOWNLOAD_SERVER_INIT*)DataMessage->dataMessagePayload;\r
+                       gf_m2ts_dsmcc_delete_compatibility_descriptor(&DownloadServerInit->CompatibilityDescr);\r
+                       if (DownloadServerInit->privateDataLength) {\r
+                               gf_free(DownloadServerInit->privateDataByte);\r
+                       }\r
+                       gf_free(DownloadServerInit);\r
+                       break;\r
+               }\r
+       default:\r
+               {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unknown dataMessagePayload Type \n"));\r
+                       break;\r
+               }\r
+       } \r
+\r
+       /* Header */\r
+       gf_m2ts_dsmcc_delete_message_header(&DataMessage->DownloadDataHeader);\r
+       gf_free(DataMessage);\r
+       gf_free(dsmcc);\r
+       dsmcc = NULL;\r
+       return GF_OK;\r
+}\r
+\r
+\r
+static GF_Err dsmcc_module_delete(GF_M2TS_DSMCC_MODULE* dsmcc_module){\r
+\r
+       gf_free(dsmcc_module->buffer);\r
+       gf_free(dsmcc_module);\r
+       dsmcc_module = NULL;\r
+       return  GF_OK;\r
+}\r
+\r
+/* BIOP MESSAGE */\r
+\r
+static GF_Err dsmcc_get_biop_module_info(GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u8 data_size){\r
+\r
+       GF_M2TS_DSMCC_BIOP_MODULE_INFO* BIOP_ModuleInfo;\r
+       GF_BitStream *bs;\r
+       u8 i;\r
+\r
+\r
+       bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ);\r
+       GF_SAFEALLOC(BIOP_ModuleInfo,GF_M2TS_DSMCC_BIOP_MODULE_INFO);\r
+       BIOP_ModuleInfo->descriptor = gf_list_new();\r
+\r
+       BIOP_ModuleInfo->moduleTimeOut = gf_bs_read_int(bs,32);\r
+       BIOP_ModuleInfo->blockTimeOut = gf_bs_read_int(bs,32);\r
+       BIOP_ModuleInfo->minBlockTime = gf_bs_read_int(bs,32);\r
+       BIOP_ModuleInfo->taps_count = gf_bs_read_int(bs,8);\r
+       if(!BIOP_ModuleInfo->taps_count){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted payload for BIOP Module Info \n"));\r
+               gf_list_del(BIOP_ModuleInfo->descriptor);       \r
+               gf_free(BIOP_ModuleInfo);\r
+               return GF_CORRUPTED_DATA;       \r
+       }\r
+\r
+       BIOP_ModuleInfo->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_ModuleInfo->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS));\r
+       for(i = 0; i < BIOP_ModuleInfo->taps_count; i++){\r
+               BIOP_ModuleInfo->Taps[i].id = gf_bs_read_int(bs,16);\r
+               BIOP_ModuleInfo->Taps[i].use = gf_bs_read_int(bs,16);\r
+               BIOP_ModuleInfo->Taps[i].assocTag = gf_bs_read_int(bs,16);\r
+               BIOP_ModuleInfo->Taps[i].selector_length = gf_bs_read_int(bs,8);\r
+               if(BIOP_ModuleInfo->Taps[i].selector_length){\r
+                       BIOP_ModuleInfo->Taps[i].selector_data = (char*)gf_calloc(BIOP_ModuleInfo->Taps[i].selector_length,sizeof(char));\r
+                       gf_bs_read_data(bs,BIOP_ModuleInfo->Taps[i].selector_data,(u8)(BIOP_ModuleInfo->Taps[i].selector_length));\r
+               }\r
+               if(i == 0 && (BIOP_ModuleInfo->Taps[i].id != 0x00 || BIOP_ModuleInfo->Taps[i].use != 0x17 || BIOP_ModuleInfo->Taps[i].selector_length != 0x00)){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Corrupted payload for BIOP Module Info \n"));\r
+                       gf_free(BIOP_ModuleInfo->Taps);\r
+                       gf_list_del(BIOP_ModuleInfo->descriptor);\r
+                       gf_free(BIOP_ModuleInfo);\r
+                       return GF_CORRUPTED_DATA;       \r
+               }\r
+       }\r
+       BIOP_ModuleInfo->userInfoLength = gf_bs_read_int(bs,8);\r
+       if(BIOP_ModuleInfo->userInfoLength){\r
+\r
+               u32 nb_desc,j;\r
+               u8* descr_tag;\r
+\r
+               dsmcc_biop_descriptor(bs,BIOP_ModuleInfo->descriptor,(u32)(BIOP_ModuleInfo->userInfoLength));           \r
+\r
+               nb_desc = gf_list_count(BIOP_ModuleInfo->descriptor);\r
+               j = 0;\r
+               while(j<nb_desc){\r
+\r
+                       /* get the descriptor tag */\r
+                       descr_tag = (u8*)gf_list_get(BIOP_ModuleInfo->descriptor,j);\r
+                       \r
+                       switch(*descr_tag){\r
+\r
+                               case CACHING_PRIORITY_DESCRIPTOR:\r
+                                       {\r
+                                               //GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr = (GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR*)gf_list_get(BIOP_ModuleInfo->descriptor,j);                                           \r
+                                               break;                                  \r
+                                       }\r
+                               case COMPRESSED_MODULE_DESCRIPTOR:\r
+                                       {\r
+                                               u8 comp_meth;\r
+                                               GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr = (GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR*)gf_list_get(BIOP_ModuleInfo->descriptor,j);                                        \r
+                                               /*if CompModuleDescr->compression_method least significant nibble is eq to 0x08, the terminal shall support the Deflate compression algorithm (GZIP)*/\r
+                                               comp_meth = (CompModuleDescr->compression_method &0x0F);\r
+                                               if(comp_meth == 0x08){\r
+                                                       dsmcc_module->Gzip = 1;\r
+                                               }                                               \r
+                                               dsmcc_module->original_size = CompModuleDescr->original_size;                                           \r
+                                               break;  \r
+\r
+                                       }\r
+                               default:\r
+                                       {\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n"));\r
+                                               break;\r
+                                       }\r
+                       }                       \r
+                       j++;\r
+               }\r
+       }\r
+               \r
+       dsmcc_free_biop_descriptor(BIOP_ModuleInfo->descriptor);\r
+\r
+       for(i = 0; i < BIOP_ModuleInfo->taps_count; i++){\r
+               if(BIOP_ModuleInfo->Taps[i].selector_length){\r
+                       gf_free(BIOP_ModuleInfo->Taps[i].selector_data);\r
+               }               \r
+       }\r
+       gf_free(BIOP_ModuleInfo->Taps);\r
+       gf_free(BIOP_ModuleInfo);       \r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_process_biop_data(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_MODULE* dsmcc_module,char* data,u32 data_size){\r
+\r
+       GF_BitStream *bs;\r
+       GF_Err e;\r
+       Bool Error;\r
+       u32 byte_shift;\r
+       GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header;\r
+       GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway = dsmcc_overlord->ServiceGateway;\r
+\r
+       e = GF_OK;\r
+       Error = 0;\r
+\r
+       bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ);\r
+\r
+       byte_shift = (u32)(gf_bs_get_position(bs));\r
+\r
+       while(byte_shift < data_size){\r
+\r
+               BIOP_Header = dsmcc_process_biop_header(bs);\r
+\r
+               if(BIOP_Header){\r
+                       if(!strcmp(BIOP_Header->objectKind_data,"fil")){\r
+                               e = dsmcc_process_biop_file(bs,BIOP_Header,dsmcc_overlord,dsmcc_module->moduleId,dsmcc_module->downloadId);\r
+                       }else if(!strcmp(BIOP_Header->objectKind_data,"dir")){\r
+                               e = dsmcc_process_biop_directory(bs,BIOP_Header,dsmcc_overlord,0);\r
+                       }else if(!strcmp(BIOP_Header->objectKind_data,"srg")){\r
+                               e = dsmcc_process_biop_directory(bs,BIOP_Header,dsmcc_overlord,1);\r
+                               if(e == GF_OK){\r
+                                       dsmcc_overlord->Got_ServiceGateway = 1;\r
+                               }\r
+                       }else if(!strcmp(BIOP_Header->objectKind_data,"str")){\r
+                               dsmcc_process_biop_stream_message(bs,BIOP_Header,ServiceGateway);\r
+                       }else if(!strcmp(BIOP_Header->objectKind_data,"ste")){\r
+                               dsmcc_process_biop_stream_event(bs,BIOP_Header,ServiceGateway);\r
+                       }else{\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported BIOP Message, abording process \n"));                               \r
+                       }\r
+               }\r
+               byte_shift = (u32)(gf_bs_get_position(bs));\r
+               if((e || !BIOP_Header) && (byte_shift < data_size)){\r
+                       /* Error inside the data. Read next byte until a new "BIOP" is found or data_size is reached */\r
+                       gf_bs_read_int(bs,8);\r
+                       Error = 1;\r
+               }\r
+               if(BIOP_Header){\r
+                       dsmcc_free_biop_header(BIOP_Header);\r
+               }\r
+               \r
+       }\r
+\r
+       if(Error){\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_M2TS_DSMCC_BIOP_HEADER* dsmcc_process_biop_header(GF_BitStream* bs){\r
+       \r
+       GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header;\r
+       GF_SAFEALLOC(BIOP_Header,GF_M2TS_DSMCC_BIOP_HEADER);\r
+\r
+       BIOP_Header->magic = gf_bs_read_int(bs,32);\r
+       if(BIOP_Header->magic != 0x42494F50){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Wrong BIOP Header, abording process \n"));\r
+               return NULL;\r
+       }\r
+       BIOP_Header->biop_version_major = gf_bs_read_int(bs,8);\r
+       BIOP_Header->biop_version_minor = gf_bs_read_int(bs,8);\r
+       BIOP_Header->byte_order = gf_bs_read_int(bs,8);\r
+       BIOP_Header->message_type = gf_bs_read_int(bs,8);\r
+       BIOP_Header->message_size = gf_bs_read_int(bs,32);\r
+       BIOP_Header->objectKey_length = gf_bs_read_int(bs,8);\r
+       if(BIOP_Header->objectKey_length){\r
+               BIOP_Header->objectKey_data = gf_bs_read_int(bs,BIOP_Header->objectKey_length*8);\r
+       }\r
+       BIOP_Header->objectKind_length = gf_bs_read_int(bs,32);\r
+       if(BIOP_Header->objectKind_length){\r
+               BIOP_Header->objectKind_data = (char*)gf_calloc(BIOP_Header->objectKind_length,sizeof(char));\r
+               gf_bs_read_data(bs,BIOP_Header->objectKind_data,(u32)(BIOP_Header->objectKind_length));\r
+       }\r
+       BIOP_Header->objectInfo_length = gf_bs_read_int(bs,16);\r
+\r
+       return BIOP_Header;\r
+}\r
+\r
+static GF_Err dsmcc_process_biop_file(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,u16 moduleId,u32 downloadId){\r
+\r
+       u32 nb_desc,descr_size;         \r
+       GF_M2TS_DSMCC_BIOP_FILE* BIOP_File;\r
+       GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway;\r
+       GF_M2TS_DSMCC_FILE* File;\r
+       FILE* pFile;\r
+       char* FileType;\r
+       u8* descr_tag;\r
+\r
+       GF_SAFEALLOC(BIOP_File,GF_M2TS_DSMCC_BIOP_FILE);\r
+\r
+       ServiceGateway = dsmcc_overlord->ServiceGateway;\r
+\r
+       BIOP_File->Header = BIOP_Header;        \r
+       BIOP_File->ContentSize = gf_bs_read_int(bs,64); \r
+\r
+       descr_size = BIOP_File->Header->objectInfo_length-8;\r
+\r
+       if(descr_size){\r
+               dsmcc_biop_descriptor(bs,BIOP_File->descriptor,descr_size);\r
+       }\r
+\r
+        gf_bs_read_int(bs,(u32)(descr_size));\r
+\r
+       nb_desc = gf_list_count(BIOP_File->descriptor);\r
+\r
+       while(nb_desc){\r
+\r
+               /* get the descriptor tag */\r
+               descr_tag = (u8*)gf_list_get(BIOP_File->descriptor,0);                          \r
+\r
+               switch(*descr_tag){\r
+                               case CONTENT_TYPE_DESCRIPTOR:\r
+                                       {\r
+                                               GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(BIOP_File->descriptor,0);                                         \r
+                                               FileType = strdup(ContentTypeDescr->content_type_data_byte);                                            \r
+                                       }\r
+                               default:\r
+                                       {\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n"));\r
+                                               break;\r
+                                       }\r
+               }               \r
+               nb_desc--;\r
+       }\r
+\r
+       BIOP_File->serviceContextList_count = gf_bs_read_int(bs,8);\r
+       if(BIOP_File->serviceContextList_count){\r
+               BIOP_File->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_File->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT));\r
+               dsmcc_biop_get_context(bs,BIOP_File->ServiceContext,BIOP_File->serviceContextList_count);\r
+       }\r
+       BIOP_File->messageBody_length = gf_bs_read_int(bs,32);\r
+       BIOP_File->content_length = gf_bs_read_int(bs,32);\r
+       if(BIOP_File->content_length){\r
+               BIOP_File->content_byte = (char*)gf_calloc(BIOP_File->content_length,sizeof(char));\r
+               gf_bs_read_data(bs,BIOP_File->content_byte,(u32)(BIOP_File->content_length));\r
+\r
+       }\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("module_Id %d \n",moduleId));\r
+       File = dsmcc_get_file(ServiceGateway->File,moduleId,downloadId,BIOP_File->Header->objectKey_data);      \r
+       if(File){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Fichier: %s module_Id %d place :%d \n",File->Path,moduleId,File->objectKey_data));\r
+               pFile = fopen(File->Path,"wb");\r
+               if (pFile!=NULL){\r
+                       gf_fwrite(BIOP_File->content_byte,1,BIOP_File->content_length ,pFile);                  \r
+                       fclose(pFile);\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Fichier créé \n\n"));\r
+                       if(!strcmp(File->name,"index.html")){\r
+                               dsmcc_overlord->get_index = 1;\r
+                       }\r
+               }\r
+       }else{\r
+               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[DSMCC] File vould not be created\n"));\r
+       }\r
+\r
+       dsmcc_free_biop_file(BIOP_File);        \r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_process_biop_directory(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_OVERLORD*dsmcc_overlord,Bool IsServiceGateway){\r
+\r
+       GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory;\r
+       GF_M2TS_DSMCC_DIR* Dir;\r
+       char* ParentName;\r
+       char* FileType;\r
+       u32 i;\r
+       GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway;\r
+\r
+       GF_SAFEALLOC(BIOP_Directory,GF_M2TS_DSMCC_BIOP_DIRECTORY);\r
+\r
+       ServiceGateway = dsmcc_overlord->ServiceGateway;\r
+\r
+       /* Get the Header */\r
+       BIOP_Directory->Header = BIOP_Header;\r
+       \r
+       if(BIOP_Directory->Header->objectInfo_length != 0x0){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] ObjectInfo_length value is not correct \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }\r
+       \r
+       if(IsServiceGateway){\r
+               /* create a "dir" struct with no parent */                      \r
+               Dir = (GF_M2TS_DSMCC_DIR*)ServiceGateway;\r
+               ServiceGateway->objectKey_data = BIOP_Directory->Header->objectKey_data;\r
+               ServiceGateway->parent = NULL;                  \r
+               ServiceGateway->name = (char*)gf_strdup(dsmcc_overlord->root_dir);\r
+               ParentName = ServiceGateway->name;                      \r
+       }else{\r
+               /* get the dir related to the payload */\r
+               Dir = dsmcc_get_directory(ServiceGateway->Dir,BIOP_Directory->Header->objectKey_data);          \r
+       }\r
+\r
+       BIOP_Directory->serviceContextList_count = gf_bs_read_int(bs,8);\r
+       if(BIOP_Directory->serviceContextList_count){\r
+               BIOP_Directory->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_Directory->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT));\r
+               dsmcc_biop_get_context(bs,BIOP_Directory->ServiceContext,BIOP_Directory->serviceContextList_count);\r
+       }\r
+       BIOP_Directory->messageBody_length = gf_bs_read_int(bs,32);\r
+       BIOP_Directory->bindings_count = gf_bs_read_int(bs,16);\r
+       BIOP_Directory->Name = (GF_M2TS_DSMCC_BIOP_NAME*)gf_calloc(BIOP_Directory->bindings_count,sizeof(GF_M2TS_DSMCC_BIOP_NAME));\r
+\r
+       /* Get the linked files */\r
+       for(i = 0; i<BIOP_Directory->bindings_count;i++){\r
+               u32 descr_length,nb_desc,j;\r
+               u8* descr_tag;\r
+               GF_Err e;\r
+\r
+               BIOP_Directory->Name[i].nameComponents_count = gf_bs_read_int(bs,8);\r
+               BIOP_Directory->Name[i].id_length = gf_bs_read_int(bs,8);\r
+               if(BIOP_Directory->Name[i].id_length){\r
+                       BIOP_Directory->Name[i].id_data = (char*)gf_calloc(BIOP_Directory->Name[i].id_length,sizeof(char));\r
+                       gf_bs_read_data(bs,BIOP_Directory->Name[i].id_data,(u32)(BIOP_Directory->Name[i].id_length));\r
+               }\r
+               BIOP_Directory->Name[i].kind_length = gf_bs_read_int(bs,8);\r
+               if(BIOP_Directory->Name[i].kind_length > 0x04){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] kind_length value is not valid\n"));\r
+                       return GF_CORRUPTED_DATA;\r
+               }\r
+               if(BIOP_Directory->Name[i].kind_length){\r
+                       BIOP_Directory->Name[i].kind_data = (char*)gf_calloc(BIOP_Directory->Name[i].kind_length,sizeof(char));\r
+                       gf_bs_read_data(bs,BIOP_Directory->Name[i].kind_data,(u32)(BIOP_Directory->Name[i].kind_length));\r
+               }\r
+       \r
+               BIOP_Directory->Name[i].BindingType = gf_bs_read_int(bs,8);\r
+               /* IOR */\r
+               e = dsmcc_biop_get_ior(bs,&BIOP_Directory->Name[i].IOR);\r
+               if(e){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in IOR processing\n"));\r
+                       return GF_CORRUPTED_DATA;\r
+               }\r
+\r
+               BIOP_Directory->Name[i].objectInfo_length = gf_bs_read_int(bs,16);\r
+               if(!strcmp(BIOP_Directory->Name[i].kind_data,"fil")){\r
+                       BIOP_Directory->Name[i].ContentSize = gf_bs_read_int(bs,64);\r
+                       descr_length = BIOP_Directory->Name[i].objectInfo_length - 8;\r
+               }else{\r
+                       descr_length = BIOP_Directory->Name[i].objectInfo_length;\r
+               }\r
+\r
+               if(descr_length){\r
+                       BIOP_Directory->Name[i].descriptor = gf_list_new();\r
+                       dsmcc_biop_descriptor(bs,BIOP_Directory->Name[i].descriptor,descr_length);\r
+               }\r
+\r
+               gf_bs_read_int(bs,(u32)(descr_length));\r
+\r
+               nb_desc = gf_list_count(BIOP_Directory->Name[i].descriptor);\r
+               j = 0;\r
+               while(j<nb_desc){\r
+                       /* get the descriptor tag */\r
+                       descr_tag = (u8*)gf_list_get(BIOP_Directory->Name[i].descriptor ,0);            \r
+\r
+                       switch(*descr_tag){\r
+                                       case CONTENT_TYPE_DESCRIPTOR:\r
+                                               {\r
+                                                       GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(BIOP_Directory->Name[i].descriptor ,j);                                           \r
+                                                       FileType = strdup(ContentTypeDescr->content_type_data_byte);                                            \r
+                                               }\r
+                                       default:\r
+                                               {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported descriptor Type \n"));\r
+                                                       break;\r
+                                               }\r
+                       }                               \r
+                       j++;\r
+               }\r
+                       \r
+               if(!strcmp(BIOP_Directory->Name[i].kind_data,"dir")){\r
+                       if(!dsmcc_check_element_validation(ServiceGateway->Dir,ServiceGateway->name,BIOP_Directory->Name[i])){\r
+                               GF_Err e;\r
+                               GF_M2TS_DSMCC_DIR* Directory;\r
+                               GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(BIOP_Directory->Name[i].IOR.taggedProfile,0);                                        \r
+                               GF_SAFEALLOC(Directory,GF_M2TS_DSMCC_DIR);\r
+                               Directory->name = (char*)gf_strdup(BIOP_Directory->Name[i].id_data);\r
+                               Directory->File = gf_list_new();\r
+                               Directory->objectKey_data = taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data;\r
+                               Directory->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId;\r
+                               Directory->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId;                  \r
+                               Directory->parent = Dir;\r
+                               Directory->Path = dsmcc_get_file_namepath(Dir,Directory->name);\r
+                               e = gf_mkdir(Directory->Path);\r
+                               if(e){\r
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the creation of the directory %s \n",Directory->Path));\r
+                               }\r
+                               gf_list_add(ServiceGateway->Dir,Directory);\r
+                       }\r
+               }else if(!strcmp(BIOP_Directory->Name[i].kind_data,"fil")){\r
+                       if(!dsmcc_check_element_validation(ServiceGateway->File,ServiceGateway->name,BIOP_Directory->Name[i])){\r
+                               GF_M2TS_DSMCC_FILE* File;\r
+                               GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(BIOP_Directory->Name[i].IOR.taggedProfile,0);                                        \r
+                               GF_SAFEALLOC(File,GF_M2TS_DSMCC_FILE);\r
+                               File->name = (char*)gf_strdup(BIOP_Directory->Name[i].id_data);                                 \r
+                               File->objectKey_data = taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data;\r
+                               File->downloadId = taggedProfile->BIOPProfileBody->ObjectLocation.carouselId;\r
+                               File->moduleId = taggedProfile->BIOPProfileBody->ObjectLocation.moduleId;                                               \r
+                               File->parent = Dir;\r
+                               File->Path = dsmcc_get_file_namepath(Dir,File->name);\r
+                               gf_list_add(ServiceGateway->File,File);\r
+                       }\r
+               }               \r
+       }\r
+       dsmcc_free_biop_directory(BIOP_Directory);\r
+       \r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_process_biop_stream_event(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway){\r
+\r
+       u32 i;          \r
+       GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent;\r
+       //GF_M2TS_DSMCC_FILE* File;     \r
+       u32 eventdata,Info_length;\r
+\r
+       GF_SAFEALLOC(BIOP_StreamEvent,GF_M2TS_DSMCC_BIOP_STREAM_EVENT);\r
+\r
+       eventdata = 0;\r
+\r
+       BIOP_StreamEvent->Header = BIOP_Header;\r
+       /* Get Info */\r
+       BIOP_StreamEvent->Info.aDescription_length = gf_bs_read_int(bs,8);\r
+       if(BIOP_StreamEvent->Info.aDescription_length){\r
+               BIOP_StreamEvent->Info.aDescription_bytes = (char*)gf_calloc(BIOP_StreamEvent->Info.aDescription_length,sizeof(char));\r
+               gf_bs_read_data(bs,BIOP_StreamEvent->Info.aDescription_bytes,(u8)(BIOP_StreamEvent->Info.aDescription_length));\r
+       }\r
+       BIOP_StreamEvent->Info.duration_aSeconds = gf_bs_read_int(bs,32);\r
+       BIOP_StreamEvent->Info.duration_aMicroseconds = gf_bs_read_int(bs,32);\r
+       BIOP_StreamEvent->Info.audio = gf_bs_read_int(bs,8);\r
+       BIOP_StreamEvent->Info.video = gf_bs_read_int(bs,8);\r
+       BIOP_StreamEvent->Info.data = gf_bs_read_int(bs,8);\r
+\r
+       /* Event List */\r
+       BIOP_StreamEvent->eventNames_count = gf_bs_read_int(bs,16);\r
+       if(BIOP_StreamEvent->eventNames_count){\r
+               BIOP_StreamEvent->EventList = (GF_M2TS_DSMCC_BIOP_EVENT_LIST*)gf_calloc(BIOP_StreamEvent->eventNames_count,sizeof(GF_M2TS_DSMCC_BIOP_EVENT_LIST));\r
+               for(i=0;i<BIOP_StreamEvent->eventNames_count;i++){\r
+                       BIOP_StreamEvent->EventList[i].eventName_length = gf_bs_read_int(bs,8);\r
+                       eventdata += BIOP_StreamEvent->EventList[i].eventName_length;\r
+                       if(BIOP_StreamEvent->EventList[i].eventName_length){\r
+                               BIOP_StreamEvent->EventList[i].eventName_data_byte = (char*)gf_calloc(BIOP_StreamEvent->EventList[i].eventName_length,sizeof(char));\r
+                               gf_bs_read_data(bs,BIOP_StreamEvent->EventList[i].eventName_data_byte,(u8)(BIOP_StreamEvent->EventList[i].eventName_length));\r
+                       }\r
+               }\r
+       }\r
+\r
+       Info_length = BIOP_StreamEvent->Header->objectInfo_length - (BIOP_StreamEvent->Info.aDescription_length + 14 + BIOP_StreamEvent->eventNames_count + eventdata);\r
+\r
+       BIOP_StreamEvent->serviceContextList_count = gf_bs_read_int(bs,8);\r
+       if(BIOP_StreamEvent->serviceContextList_count){\r
+               BIOP_StreamEvent->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_StreamEvent->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT));\r
+               dsmcc_biop_get_context(bs,BIOP_StreamEvent->ServiceContext,BIOP_StreamEvent->serviceContextList_count);\r
+       }       \r
+                       \r
+       BIOP_StreamEvent->messageBody_length = gf_bs_read_int(bs,32);\r
+       BIOP_StreamEvent->taps_count = gf_bs_read_int(bs,8);\r
+       BIOP_StreamEvent->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_StreamEvent->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS));\r
+       for(i=0;i<BIOP_StreamEvent->taps_count;i++){\r
+               BIOP_StreamEvent->Taps[i].id = gf_bs_read_int(bs,16);           \r
+               BIOP_StreamEvent->Taps[i].use = gf_bs_read_int(bs,16);          \r
+               BIOP_StreamEvent->Taps[i].assocTag = gf_bs_read_int(bs,16);\r
+               BIOP_StreamEvent->Taps[i].selector_length = gf_bs_read_int(bs,8);\r
+               if(BIOP_StreamEvent->Taps[i].selector_length != 0x00){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : selector_length has a wrong value, abording the processing \n"));\r
+                       return GF_CORRUPTED_DATA;\r
+               }               \r
+       }\r
+       BIOP_StreamEvent->eventIds_count = gf_bs_read_int(bs,8);\r
+       if(BIOP_StreamEvent->eventIds_count != BIOP_StreamEvent->eventNames_count){\r
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : eventIds_count has a wrong value, abording the processing \n"));\r
+               return GF_CORRUPTED_DATA;\r
+       }else if(BIOP_StreamEvent->eventIds_count){\r
+               BIOP_StreamEvent->eventId = (u16*)gf_calloc(BIOP_StreamEvent->eventIds_count,sizeof(u16));\r
+               for(i =0;i<BIOP_StreamEvent->eventIds_count;i++){\r
+                       BIOP_StreamEvent->eventId[i] = gf_bs_read_int(bs,16);\r
+               }\r
+       }\r
+\r
+       dsmcc_free_biop_stream_event(BIOP_StreamEvent);\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_process_biop_stream_message(GF_BitStream* bs,GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header,GF_M2TS_DSMCC_SERVICE_GATEWAY* ServiceGateway){\r
+\r
+       u32 i;          \r
+       GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage;  \r
+       u32 eventdata,Info_length;\r
+\r
+       GF_SAFEALLOC(BIOP_StreamMessage,GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE);\r
+\r
+       eventdata = 0;\r
+\r
+       BIOP_StreamMessage->Header = BIOP_Header;\r
+       /* Get Info */\r
+       BIOP_StreamMessage->Info.aDescription_length = gf_bs_read_int(bs,8);\r
+       if(BIOP_StreamMessage->Info.aDescription_length){\r
+               BIOP_StreamMessage->Info.aDescription_bytes = (char*)gf_calloc(BIOP_StreamMessage->Info.aDescription_length,sizeof(char));\r
+               gf_bs_read_data(bs,BIOP_StreamMessage->Info.aDescription_bytes,(u8)(BIOP_StreamMessage->Info.aDescription_length));\r
+       }\r
+       BIOP_StreamMessage->Info.duration_aSeconds = gf_bs_read_int(bs,32);\r
+       BIOP_StreamMessage->Info.duration_aMicroseconds = gf_bs_read_int(bs,32);\r
+       BIOP_StreamMessage->Info.audio = gf_bs_read_int(bs,8);\r
+       BIOP_StreamMessage->Info.video = gf_bs_read_int(bs,8);\r
+       BIOP_StreamMessage->Info.data = gf_bs_read_int(bs,8);\r
+       \r
+\r
+       Info_length = BIOP_StreamMessage->Header->objectInfo_length - (BIOP_StreamMessage->Info.aDescription_length + 10);\r
+\r
+       BIOP_StreamMessage->serviceContextList_count = gf_bs_read_int(bs,8);\r
+       if(BIOP_StreamMessage->serviceContextList_count){\r
+               BIOP_StreamMessage->ServiceContext = (GF_M2TS_DSMCC_SERVICE_CONTEXT*)gf_calloc(BIOP_StreamMessage->serviceContextList_count,sizeof(GF_M2TS_DSMCC_SERVICE_CONTEXT));\r
+               dsmcc_biop_get_context(bs,BIOP_StreamMessage->ServiceContext,BIOP_StreamMessage->serviceContextList_count);\r
+       }\r
+                               \r
+       BIOP_StreamMessage->messageBody_length = gf_bs_read_int(bs,32);\r
+       BIOP_StreamMessage->taps_count = gf_bs_read_int(bs,8);\r
+       BIOP_StreamMessage->Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(BIOP_StreamMessage->taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS));\r
+       for(i=0;i<BIOP_StreamMessage->taps_count;i++){\r
+               BIOP_StreamMessage->Taps[i].id = gf_bs_read_int(bs,16);         \r
+               BIOP_StreamMessage->Taps[i].use = gf_bs_read_int(bs,16);                \r
+               BIOP_StreamMessage->Taps[i].assocTag = gf_bs_read_int(bs,16);\r
+               BIOP_StreamMessage->Taps[i].selector_length = gf_bs_read_int(bs,8);\r
+               if(BIOP_StreamMessage->Taps[i].selector_length != 0x00){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Stream Event : selector_length has a wrong value, abording the processing \n"));\r
+                       return GF_CORRUPTED_DATA;\r
+               }               \r
+       }\r
+\r
+       dsmcc_free_biop_stream_message(BIOP_StreamMessage);\r
+\r
+       return GF_OK;\r
+}\r
+\r
+\r
+/* Tools */\r
+\r
+static GF_M2TS_DSMCC_MODULE* dsmcc_create_module(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord, GF_M2TS_DSMCC_DOWNLOAD_INFO_RESP_INDIC* DownloadInfoIndication)\r
+{\r
+       u32 module_index;\r
+       GF_M2TS_DSMCC_MODULE* dsmcc_module;\r
+       GF_SAFEALLOC(dsmcc_module,GF_M2TS_DSMCC_MODULE);\r
+       dsmcc_module->downloadId = DownloadInfoIndication->downloadId;\r
+       dsmcc_module->moduleId = DownloadInfoIndication->Modules.moduleId;\r
+       dsmcc_module->size = DownloadInfoIndication->Modules.moduleSize;\r
+       dsmcc_module->version_number = DownloadInfoIndication->Modules.moduleVersion;\r
+       dsmcc_module->block_size = DownloadInfoIndication->blockSize;\r
+       dsmcc_module->buffer = (char*)gf_calloc(dsmcc_module->size,sizeof(char));\r
+       module_index = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+       dsmcc_overlord->processed[module_index].moduleId = dsmcc_module->moduleId;\r
+       dsmcc_overlord->processed[module_index].downloadId = dsmcc_module->downloadId;\r
+       dsmcc_overlord->processed[module_index].version_number = dsmcc_module->version_number;\r
+       gf_list_add(dsmcc_overlord->dsmcc_modules,dsmcc_module);\r
+\r
+       return dsmcc_module;\r
+}\r
+\r
+static void dsmcc_biop_descriptor(GF_BitStream* bs,GF_List* list,u32 size){\r
+       u8 descr_tag;\r
+       u32 data_shift,start_pos;\r
+\r
+       start_pos = (u32)(gf_bs_get_position(bs));\r
+               data_shift = 0;\r
+\r
+       while(size > data_shift){\r
+       descr_tag = gf_bs_read_int(bs,8);                       \r
+\r
+                       switch(descr_tag){\r
+\r
+                               case CACHING_PRIORITY_DESCRIPTOR:\r
+                                       {\r
+                                               GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr;\r
+                                               GF_SAFEALLOC(CachingPriorityDescr,GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR);\r
+                                               CachingPriorityDescr->descriptor_tag = descr_tag;\r
+                                               CachingPriorityDescr->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               CachingPriorityDescr->priority_value = gf_bs_read_int(bs,8);\r
+                                               CachingPriorityDescr->transparency_level = gf_bs_read_int(bs,8);\r
+                                               gf_list_add(list,CachingPriorityDescr);\r
+                                               break;                                  \r
+                                       }\r
+                               case COMPRESSED_MODULE_DESCRIPTOR:\r
+                                       {\r
+                                               GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr;\r
+                                               GF_SAFEALLOC(CompModuleDescr,GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR);\r
+                                               CompModuleDescr->descriptor_tag = descr_tag;\r
+                                               CompModuleDescr->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               CompModuleDescr->compression_method = gf_bs_read_int(bs,8);\r
+                                               /* if CompModuleDescr->compression_method least significant nibble is eq to 0x08, the terminal shall support the Deflate compression algorithm (GZIP) */\r
+                                               CompModuleDescr->original_size = gf_bs_read_int(bs,32);                         \r
+                                               gf_list_add(list,CompModuleDescr);\r
+                                               break;  \r
+\r
+                                       }\r
+                               case CONTENT_TYPE_DESCRIPTOR:\r
+                                       {\r
+                                               GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr;\r
+                                               GF_SAFEALLOC(ContentTypeDescr,GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR);\r
+                                               ContentTypeDescr->descriptor_tag = descr_tag;\r
+                                               ContentTypeDescr->descriptor_length = gf_bs_read_int(bs,8);\r
+                                               ContentTypeDescr->content_type_data_byte = (char*)gf_calloc(ContentTypeDescr->descriptor_length,sizeof(char));\r
+                                               gf_bs_read_data(bs,ContentTypeDescr->content_type_data_byte,(u32)(ContentTypeDescr->descriptor_length));\r
+                                               gf_list_add(list,ContentTypeDescr);\r
+                                       }\r
+                               default:\r
+                                       {\r
+                                               u32 size;\r
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported Descriptor Type \n"));\r
+                                               /* byte shift - in descriptors length is on thr second byte*/\r
+                                               size = gf_bs_read_int(bs,8);\r
+                                               gf_bs_read_int(bs,8*size);\r
+                                               break;\r
+                                       }\r
+                       }                       \r
+                       data_shift = (u32)(gf_bs_get_position(bs)) - start_pos;\r
+       }\r
+}\r
+\r
+static void dsmcc_biop_get_context(GF_BitStream* bs,GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count)\r
+{\r
+       u32 i;\r
+\r
+       for(i=0;i<serviceContextList_count;i++){\r
+               Context[i].context_id = gf_bs_read_int(bs,32);                                  \r
+               Context[i].context_data_length = gf_bs_read_int(bs,16); \r
+               if(Context[i].context_data_length != 0){\r
+                       Context[i].context_data_byte = (char*)gf_calloc(Context[i].context_data_length ,sizeof(char));\r
+                       gf_bs_read_data(bs,Context[i].context_data_byte,(u32)(Context[i].context_data_length ));\r
+               }\r
+       }\r
+}\r
+\r
+static GF_Err dsmcc_biop_get_ior(GF_BitStream* bs,GF_M2TS_DSMCC_IOR* IOR)\r
+{\r
+       u32 i,left_lite_component;\r
+       /* IOR */\r
+       left_lite_component = 0;\r
+       IOR->type_id_length = gf_bs_read_int(bs,32);\r
+       if(IOR->type_id_length > 0xA){          \r
+               //return GF_CORRUPTED_DATA;\r
+       }\r
+       IOR->type_id_byte = (char*)gf_calloc(IOR->type_id_length,sizeof(char));\r
+       gf_bs_read_data(bs,IOR->type_id_byte,(u32)(IOR->type_id_length));\r
+       IOR->taggedProfiles_count = gf_bs_read_int(bs,32);\r
+       IOR->taggedProfile = gf_list_new();\r
+       for(i = 0; i < IOR->taggedProfiles_count;i++){\r
+               GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile;\r
+               GF_SAFEALLOC(taggedProfile,GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE);\r
+               gf_list_add(IOR->taggedProfile,taggedProfile);\r
+               taggedProfile->profileId_tag = gf_bs_read_int(bs,32);\r
+               taggedProfile->profile_data_length = gf_bs_read_int(bs,32);\r
+               taggedProfile->profile_data_byte_order = gf_bs_read_int(bs,8);\r
+               if(taggedProfile->profile_data_byte_order != 0x00){\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in IOR processing : profile data byte order has a wrong value, abording the processing \n"));\r
+                       return GF_CORRUPTED_DATA;\r
+               }\r
+               taggedProfile->lite_component_count = gf_bs_read_int(bs,8);\r
+               left_lite_component = taggedProfile->lite_component_count;\r
+               switch(taggedProfile->profileId_tag){\r
+                                       case TAG_BIOP:\r
+                                               {\r
+                                                       /* Object Location */\r
+                                                       u32 j;\r
+                                                       GF_SAFEALLOC(taggedProfile->BIOPProfileBody,GF_M2TS_DSMCC_BIOP_PROFILE_BODY);\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.componentId_tag = gf_bs_read_int(bs,32);\r
+                                                       if(taggedProfile->BIOPProfileBody->ObjectLocation.componentId_tag != 0x49534F50){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : component tag has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.component_data_length = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.carouselId = gf_bs_read_int(bs,32);\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.moduleId = gf_bs_read_int(bs,16);\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.version_major = gf_bs_read_int(bs,8);\r
+                                                       if(taggedProfile->BIOPProfileBody->ObjectLocation.version_major != 0x01){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : version major has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.version_minor = gf_bs_read_int(bs,8);\r
+                                                       if(taggedProfile->BIOPProfileBody->ObjectLocation.version_minor != 0x00){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Profile Body : version minor has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length = gf_bs_read_int(bs,8);\r
+                                                       if(taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length){\r
+                                                               taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data = gf_bs_read_int(bs,taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_length*8);\r
+                                                       }\r
+                                                       /* ConnBinder */\r
+\r
+                                                       taggedProfile->BIOPProfileBody->ConnBinder.componentId_tag = gf_bs_read_int(bs,32);\r
+                                                       if(taggedProfile->BIOPProfileBody->ConnBinder.componentId_tag != 0x49534F40){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : componentId tag has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->BIOPProfileBody->ConnBinder.component_data_length = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->BIOPProfileBody->ConnBinder.taps_count = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->BIOPProfileBody->ConnBinder.Taps = (GF_M2TS_DSMCC_BIOP_TAPS*)gf_calloc(taggedProfile->BIOPProfileBody->ConnBinder.taps_count,sizeof(GF_M2TS_DSMCC_BIOP_TAPS));\r
+                                                       for(j=0;j<taggedProfile->BIOPProfileBody->ConnBinder.taps_count;j++){\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].id = gf_bs_read_int(bs,16);\r
+                                                               if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].id != 0x00){\r
+                                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : id has a wrong value, abording the processing \n"));\r
+                                                                       return GF_CORRUPTED_DATA;\r
+                                                               }\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].use = gf_bs_read_int(bs,16);\r
+                                                               if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].use != 0x016){\r
+                                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : use has a wrong value, abording the processing \n"));\r
+                                                                       return GF_CORRUPTED_DATA;\r
+                                                               }\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].assocTag = gf_bs_read_int(bs,16);\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_length = gf_bs_read_int(bs,8);\r
+                                                               if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_length != 0x0A){\r
+                                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : selector_length has a wrong value, abording the processing \n"));\r
+                                                                       return GF_CORRUPTED_DATA;\r
+                                                               }\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_type = gf_bs_read_int(bs,16);\r
+                                                               if(taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].selector_type != 0x001){\r
+                                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in ConnBinder : selector_type has a wrong value, abording the processing \n"));\r
+                                                                       return GF_CORRUPTED_DATA;\r
+                                                               }\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].transactionId = gf_bs_read_int(bs,32);\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.Taps[i].timeout = gf_bs_read_int(bs,32);\r
+                                                       }\r
+                                                       if(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18 != 0){\r
+                                                               taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte = (char*)gf_calloc(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18,sizeof(char));\r
+                                                               gf_bs_read_data(bs,taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte,(u32)(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18));\r
+                                                       }\r
+                                                       left_lite_component = left_lite_component - 2; \r
+                                                       break;\r
+                                               }\r
+                                       case TAG_LITE_OPTIONS:\r
+                                               {\r
+                                                       /* Service Location */\r
+                                                       u32 j;\r
+                                                       GF_SAFEALLOC(taggedProfile->ServiceLocation,GF_M2TS_DSMCC_BIOP_SERVICE_LOCATION);\r
+                                                       taggedProfile->ServiceLocation->componentId_tag = gf_bs_read_int(bs,32);\r
+                                                       if(taggedProfile->ServiceLocation->componentId_tag != 0x49534F46){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Location : component tag has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->ServiceLocation->component_data_length = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_length = gf_bs_read_int(bs,8);\r
+                                                       if(taggedProfile->ServiceLocation->serviceDomain_length != 0x14){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Location : Service Domain Length tag has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.AFI = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.type = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.carouselId = gf_bs_read_int(bs,32);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.specifierType = gf_bs_read_int(bs,8);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.specifierData = gf_bs_read_int(bs,24);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.transport_stream_id = gf_bs_read_int(bs,16);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.original_network_id = gf_bs_read_int(bs,16);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.service_id = gf_bs_read_int(bs,16);\r
+                                                       taggedProfile->ServiceLocation->serviceDomain_data.reserved = gf_bs_read_int(bs,32);\r
+                                                       if(taggedProfile->ServiceLocation->serviceDomain_data.reserved != 0xFFFFFFFF){\r
+                                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error in Service Domain Data : reserved has a wrong value, abording the processing \n"));\r
+                                                               return GF_CORRUPTED_DATA;\r
+                                                       }\r
+                                                       taggedProfile->ServiceLocation->nameComponents_count = gf_bs_read_int(bs,32);\r
+                                                       taggedProfile->ServiceLocation->NameComponent = (GF_M2TS_DSMCC_BIOP_NAME_COMPONENT*)gf_calloc(taggedProfile->ServiceLocation->nameComponents_count,sizeof(GF_M2TS_DSMCC_BIOP_NAME_COMPONENT));\r
+                                                       for(j = 0; j < taggedProfile->ServiceLocation->nameComponents_count; j++){\r
+                                                               taggedProfile->ServiceLocation->NameComponent[j].id_length = gf_bs_read_int(bs,32);\r
+                                                               if(taggedProfile->ServiceLocation->NameComponent[j].id_length != 0){\r
+                                                                       taggedProfile->ServiceLocation->NameComponent[j].id_data = (char*)gf_calloc(taggedProfile->ServiceLocation->NameComponent[j].id_length,sizeof(char));\r
+                                                                       gf_bs_read_data(bs,taggedProfile->ServiceLocation->NameComponent[i].id_data,(u32)(taggedProfile->ServiceLocation->NameComponent[j].id_length));                                                 \r
+                                                               }\r
+                                                               taggedProfile->ServiceLocation->NameComponent[j].kind_length = gf_bs_read_int(bs,32);\r
+                                                               if(taggedProfile->ServiceLocation->NameComponent[j].kind_length != 0){\r
+                                                                       taggedProfile->ServiceLocation->NameComponent[j].kind_data = (char*)gf_calloc(taggedProfile->ServiceLocation->NameComponent[j].kind_length,sizeof(char));\r
+                                                                       gf_bs_read_data(bs,taggedProfile->ServiceLocation->NameComponent[j].kind_data,(u32)(taggedProfile->ServiceLocation->NameComponent[j].kind_length));\r
+                                                               }\r
+                                                       }\r
+                                                       taggedProfile->ServiceLocation->initialContext_length = gf_bs_read_int(bs,8);\r
+                                                       if(taggedProfile->ServiceLocation->initialContext_length != 0){\r
+                                                               taggedProfile->ServiceLocation->InitialContext_data_byte = (char*)gf_calloc(taggedProfile->ServiceLocation->initialContext_length,sizeof(char));\r
+                                                               gf_bs_read_data(bs,taggedProfile->ServiceLocation->InitialContext_data_byte,(u32)(taggedProfile->ServiceLocation->initialContext_length));\r
+                                                       }\r
+                                                       left_lite_component = left_lite_component - 1; \r
+                                                       break;\r
+                                               }\r
+                                       default:\r
+                                               {\r
+                                                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Unsupported Service gateway profile tag \n"));\r
+                                                       break;\r
+                                               }\r
+               }\r
+               taggedProfile->LiteComponent = (GF_M2TS_DSMCC_BIOP_LITE_COMPONENT*)gf_calloc(left_lite_component,sizeof(GF_M2TS_DSMCC_BIOP_LITE_COMPONENT));\r
+               for(i = 0; i<left_lite_component ; i++){\r
+                       taggedProfile->LiteComponent[i].componentId_tag = gf_bs_read_int(bs,32);                                                \r
+                       taggedProfile->LiteComponent[i].component_data_length = gf_bs_read_int(bs,8);\r
+                       if(taggedProfile->LiteComponent[i].component_data_length != 0){\r
+                               taggedProfile->LiteComponent[i].component_data_byte = (char*)gf_calloc(taggedProfile->ServiceLocation->initialContext_length,sizeof(char));\r
+                               gf_bs_read_data(bs,taggedProfile->LiteComponent[i].component_data_byte,(u32)(taggedProfile->LiteComponent[i].component_data_length));\r
+                       }\r
+\r
+               }\r
+\r
+       }\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err dsmcc_check_element_validation(GF_List* List,char* Parent_name,GF_M2TS_DSMCC_BIOP_NAME Name)\r
+{\r
+       u32 nb_elt,i;\r
+\r
+       GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = (GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE*)gf_list_get(Name.IOR.taggedProfile,0);   \r
+       nb_elt = gf_list_count(List);\r
+                       \r
+       for(i = 0; i < nb_elt;i++){\r
+               GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(List,i);\r
+               if(!strcmp(File->name,Name.id_data) && !strcmp(File->parent,Parent_name) &&\r
+                       (File->objectKey_data == taggedProfile->BIOPProfileBody->ObjectLocation.objectKey_data) && File->moduleId == taggedProfile->BIOPProfileBody->ObjectLocation.moduleId){\r
+                       /* File or Dir already received */\r
+                               return GF_BAD_PARAM;\r
+               }\r
+       }\r
+\r
+       return GF_OK;\r
+}\r
+\r
+static GF_M2TS_DSMCC_DIR* dsmcc_get_directory(GF_List* List, u32 objectKey_data){\r
+       u32 nb_elt,i;\r
+\r
+       nb_elt = gf_list_count(List);\r
+\r
+       for(i = 0;i<nb_elt;i++){\r
+               GF_M2TS_DSMCC_DIR* TmpDir;\r
+               GF_M2TS_DSMCC_DIR* Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(List,i);\r
+               if(Dir->objectKey_data == objectKey_data){\r
+                       return Dir;\r
+               }\r
+               if(gf_list_count(Dir->Dir)){\r
+                       TmpDir = dsmcc_get_directory(Dir->Dir,objectKey_data);\r
+                       if(TmpDir){\r
+                               return TmpDir;\r
+                       }\r
+               }\r
+       }\r
+       return NULL;\r
+}\r
+\r
+static GF_M2TS_DSMCC_FILE* dsmcc_get_file(GF_List* ServiceGateway_List, u16 moduleId,u32 downloadId,u32 objectKey_data){\r
+       u32 nb_elt,i;\r
+       nb_elt = gf_list_count(ServiceGateway_List);\r
+       for(i = 0;i<nb_elt;i++){                \r
+               GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(ServiceGateway_List,i);\r
+               if((File->objectKey_data == objectKey_data) && File->moduleId == moduleId && File->downloadId == downloadId){\r
+                       return File;\r
+               }               \r
+       }\r
+       return NULL;\r
+}\r
+\r
+static char* dsmcc_get_file_namepath(GF_M2TS_DSMCC_DIR* Dir,char* name){\r
+       char* Path;\r
+       GF_M2TS_DSMCC_DIR* directory = Dir;\r
+\r
+       Path = gf_calloc(512,sizeof(char));\r
+       sprintf(Path,"%s%c%s",directory->name,GF_PATH_SEPARATOR,name);\r
+       while(directory->parent != NULL){\r
+               GF_M2TS_DSMCC_DIR* tempdir;\r
+               char* tempPath = gf_strdup(Path);\r
+               tempdir = (GF_M2TS_DSMCC_DIR*)directory->parent;\r
+               sprintf(Path,"%s%c%s",tempdir->name,GF_PATH_SEPARATOR,tempPath);\r
+               gf_free(tempPath);\r
+               directory = tempdir;\r
+       }\r
+       return Path;\r
+}\r
+\r
+\r
+/* Free struct */\r
+\r
+static void dsmcc_delete_module(GF_M2TS_DSMCC_MODULE* module)\r
+{\r
+       if(module->buffer){\r
+               gf_free(module->buffer);\r
+       }\r
+\r
+       gf_free(module);\r
+}\r
+\r
+static void dmscc_delete_file(GF_M2TS_DSMCC_FILE* File){\r
+\r
+       if(File->name){\r
+               gf_free(File->name);\r
+       }\r
+       if(File->Path){\r
+               gf_free(File->Path);\r
+       }\r
+}\r
+\r
+static void dmscc_delete_dir(GF_M2TS_DSMCC_DIR* Dir){\r
+\r
+       u32 nb_file, nb_dir,i;\r
+\r
+       if(Dir->name){\r
+               gf_free(Dir->name);\r
+       }\r
+       if(Dir->Path){\r
+               gf_free(Dir->Path);\r
+       }\r
+\r
+       nb_file = gf_list_count(Dir->File);\r
+       for(i=0;i<nb_file;i++){\r
+               GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(Dir->File,i);\r
+               dmscc_delete_file(File);\r
+       }\r
+       gf_list_del(Dir->File);\r
+\r
+       nb_dir = gf_list_count(Dir->Dir);\r
+       for(i=0;i<nb_dir;i++){\r
+               GF_M2TS_DSMCC_DIR* Sub_Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(Dir->Dir,i);\r
+               dmscc_delete_dir(Sub_Dir);\r
+       }\r
+       gf_list_del(Dir->Dir);\r
+       gf_free(Dir);\r
+}\r
+\r
+static void dmscc_delete_servicegateway(GF_M2TS_DSMCC_SERVICE_GATEWAY* Servicegateway){\r
+\r
+       u32 nb_file, nb_dir,i;\r
+\r
+       if(Servicegateway->name){\r
+               gf_free(Servicegateway->name);\r
+       }\r
+       nb_file = gf_list_count(Servicegateway->File);\r
+       for(i=0;i<nb_file;i++){\r
+               GF_M2TS_DSMCC_FILE* File = (GF_M2TS_DSMCC_FILE*)gf_list_get(Servicegateway->File,i);\r
+               dmscc_delete_file(File);\r
+       }\r
+       gf_list_del(Servicegateway->File);\r
+\r
+       nb_dir = gf_list_count(Servicegateway->Dir);\r
+       for(i=0;i<nb_dir;i++){\r
+               GF_M2TS_DSMCC_DIR* Dir = (GF_M2TS_DSMCC_DIR*)gf_list_get(Servicegateway->Dir,i);\r
+               dmscc_delete_dir(Dir);\r
+       }\r
+       gf_list_del(Servicegateway->Dir);\r
+       gf_free(Servicegateway);\r
+}\r
+\r
+void gf_m2ts_delete_dsmcc_overlord(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord) \r
+{\r
+       u16 nb_module,i;\r
+\r
+       nb_module = gf_list_count(dsmcc_overlord->dsmcc_modules);\r
+       for(i=0;i<nb_module;i++){\r
+               GF_M2TS_DSMCC_MODULE* module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->dsmcc_modules,i);\r
+               dsmcc_delete_module(module);\r
+       }\r
+       gf_list_del(dsmcc_overlord->dsmcc_modules);\r
+\r
+       nb_module = gf_list_count(dsmcc_overlord->Unprocessed_module);\r
+       for(i=0;i<nb_module;i++){\r
+               GF_M2TS_DSMCC_MODULE* module = (GF_M2TS_DSMCC_MODULE*)gf_list_get(dsmcc_overlord->Unprocessed_module,i);\r
+               dsmcc_delete_module(module);\r
+       }\r
+       gf_list_del(dsmcc_overlord->dsmcc_modules);\r
+       dmscc_delete_servicegateway(dsmcc_overlord->ServiceGateway);\r
+\r
+       if(dsmcc_overlord->root_dir){\r
+               gf_free(dsmcc_overlord->root_dir);\r
+       }\r
+\r
+       gf_free(dsmcc_overlord);\r
+}\r
+\r
+static void dsmcc_free_biop_header(GF_M2TS_DSMCC_BIOP_HEADER* BIOP_Header){    \r
+\r
+       gf_free(BIOP_Header->objectKind_data);  \r
+       gf_free(BIOP_Header);\r
+}\r
+\r
+static void dsmcc_free_biop_directory(GF_M2TS_DSMCC_BIOP_DIRECTORY* BIOP_Directory){\r
+\r
+       gf_free(BIOP_Directory->objectInfo_data);\r
+       dsmcc_free_biop_context(BIOP_Directory->ServiceContext,BIOP_Directory->serviceContextList_count);\r
+       dsmcc_free_biop_name(BIOP_Directory->Name,BIOP_Directory->bindings_count);\r
+       gf_free(BIOP_Directory);\r
+}\r
+\r
+static void dsmcc_free_biop_file(GF_M2TS_DSMCC_BIOP_FILE* BIOP_File){\r
+\r
+       dsmcc_free_biop_descriptor(BIOP_File->descriptor);\r
+       dsmcc_free_biop_context(BIOP_File->ServiceContext,BIOP_File->serviceContextList_count); \r
+       if(BIOP_File->content_length){\r
+               gf_free(BIOP_File->content_byte);\r
+       }\r
+       gf_free(BIOP_File);\r
+}\r
+\r
+static void dsmcc_free_biop_stream_event(GF_M2TS_DSMCC_BIOP_STREAM_EVENT* BIOP_StreamEvent){\r
+\r
+       u32 i;\r
+\r
+       if(BIOP_StreamEvent->Info.aDescription_length){\r
+               gf_free(BIOP_StreamEvent->Info.aDescription_bytes);\r
+       }\r
+\r
+       if(BIOP_StreamEvent->objectInfo_byte){\r
+               gf_free(BIOP_StreamEvent->objectInfo_byte);\r
+       }\r
+       \r
+       if(BIOP_StreamEvent->eventNames_count){ \r
+               for(i=0;i<BIOP_StreamEvent->eventNames_count;i++){                      \r
+                       if(BIOP_StreamEvent->EventList[i].eventName_length){\r
+                               gf_free(BIOP_StreamEvent->EventList[i].eventName_data_byte);\r
+                       }\r
+               }\r
+               gf_free(BIOP_StreamEvent->EventList);\r
+       }\r
+       \r
+       if(BIOP_StreamEvent->taps_count){       \r
+               gf_free(BIOP_StreamEvent->Taps);\r
+       }\r
+\r
+       dsmcc_free_biop_context(BIOP_StreamEvent->ServiceContext,BIOP_StreamEvent->serviceContextList_count);\r
+       \r
+       if(BIOP_StreamEvent->eventId){  \r
+               gf_free(BIOP_StreamEvent->eventId);\r
+       }\r
+}\r
+\r
+static void dsmcc_free_biop_stream_message(GF_M2TS_DSMCC_BIOP_STREAM_MESSAGE* BIOP_StreamMessage){\r
+\r
+       if(BIOP_StreamMessage->Info.aDescription_length){\r
+               gf_free(BIOP_StreamMessage->Info.aDescription_bytes);\r
+       }\r
+       \r
+       if(BIOP_StreamMessage->objectInfo_byte){\r
+               gf_free(BIOP_StreamMessage->objectInfo_byte);\r
+       }       \r
+       \r
+       if(BIOP_StreamMessage->taps_count){     \r
+               gf_free(BIOP_StreamMessage->Taps);\r
+       }\r
+\r
+       dsmcc_free_biop_context(BIOP_StreamMessage->ServiceContext,BIOP_StreamMessage->serviceContextList_count);       \r
+}\r
+\r
+static void dsmcc_free_biop_ior(GF_M2TS_DSMCC_IOR* IOR)\r
+{\r
+       u32 i,left_lite_component;\r
+       \r
+       if(IOR->type_id_length){                \r
+               gf_free(IOR->type_id_byte);\r
+       }       \r
+       for(i = 0; i < IOR->taggedProfiles_count;i++){\r
+               GF_M2TS_DSMCC_BIOP_TAGGED_PROFILE* taggedProfile = gf_list_get(IOR->taggedProfile,0);\r
+               left_lite_component = taggedProfile->lite_component_count;\r
+\r
+               switch(taggedProfile->profileId_tag){                           \r
+       \r
+                                       case TAG_BIOP:\r
+                                               {\r
+                                                       /* Object Location */                                           \r
+                                                       GF_SAFEALLOC(taggedProfile->BIOPProfileBody,GF_M2TS_DSMCC_BIOP_PROFILE_BODY);\r
+                                                       \r
+                                                       gf_free(taggedProfile->BIOPProfileBody->ConnBinder.Taps); \r
+                                                       if(taggedProfile->BIOPProfileBody->ConnBinder.component_data_length-18 != 0){\r
+                                                               gf_free(taggedProfile->BIOPProfileBody->ConnBinder.additional_tap_byte);\r
+                                                       }\r
+                                                       gf_free(taggedProfile->BIOPProfileBody);\r
+                                                       left_lite_component = left_lite_component - 2; \r
+                                                       break;\r
+                                               }\r
+                                       case TAG_LITE_OPTIONS:\r
+                                               {\r
+                                                       /* Service Location */\r
+                                                       u32 j;          \r
+                                                       \r
+                                                       for(j = 0; j < taggedProfile->ServiceLocation->nameComponents_count; j++){\r
+\r
+                                                               if(taggedProfile->ServiceLocation->NameComponent[j].id_length != 0){\r
+                                                                       gf_free(taggedProfile->ServiceLocation->NameComponent[j].id_data); \r
+                                                               }                                                               \r
+                                                               if(taggedProfile->ServiceLocation->NameComponent[j].kind_length != 0){\r
+                                                                       gf_free(taggedProfile->ServiceLocation->NameComponent[j].kind_data);\r
+                                                               }\r
+                                                       }\r
+                                                       gf_free(taggedProfile->ServiceLocation->NameComponent);\r
+                               \r
+                                                       if(taggedProfile->ServiceLocation->initialContext_length != 0){\r
+                                                               gf_free(taggedProfile->ServiceLocation->InitialContext_data_byte);\r
+                                                       }\r
+                                                       left_lite_component = left_lite_component - 1; \r
+                                                       break;\r
+                                               }                                       \r
+               }\r
+\r
+               for(i = 0; i<left_lite_component ; i++){                        \r
+                       if(taggedProfile->LiteComponent[i].component_data_length != 0){\r
+                               gf_free(taggedProfile->LiteComponent[i].component_data_byte);\r
+                       }\r
+\r
+               }\r
+               gf_free(taggedProfile->LiteComponent);\r
+               gf_list_rem(IOR->taggedProfile,0);\r
+               gf_free(taggedProfile);\r
+       }\r
+       gf_list_del(IOR->taggedProfile);\r
+}\r
+\r
+static void dsmcc_free_biop_descriptor(GF_List* list){\r
+       u8* descr_tag;\r
+       u32 descr_count;\r
+\r
+       descr_count = gf_list_count(list);\r
+\r
+\r
+       while(gf_list_count(list)){\r
+\r
+               descr_tag = (u8*)gf_list_get(list,0);           \r
+\r
+               switch(*descr_tag){\r
+\r
+                               case CACHING_PRIORITY_DESCRIPTOR:\r
+                                       {\r
+                                               GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR* CachingPriorityDescr = (GF_M2TS_DSMCC_BIOP_CACHING_PRIORITY_DESCRIPTOR*)gf_list_get(list,0);\r
+                                               gf_list_rem(list,0);\r
+                                               gf_free(CachingPriorityDescr);\r
+                                               break;                                  \r
+                                       }\r
+                               case COMPRESSED_MODULE_DESCRIPTOR:\r
+                                       {                                               \r
+                                               GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR* CompModuleDescr = (GF_M2TS_DSMCC_BIOP_COMPRESSED_MODULE_DESCRIPTOR*)gf_list_get(list,0);\r
+                                               gf_list_rem(list,0);\r
+                                               gf_free(CompModuleDescr);\r
+                                               break;  \r
+\r
+                                       }\r
+                               case CONTENT_TYPE_DESCRIPTOR:\r
+                                       {                       \r
+                                               GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR* ContentTypeDescr = (GF_M2TS_DSMCC_BIOP_CONTENT_TYPE_DESRIPTOR*)gf_list_get(list,0);\r
+                                               gf_list_rem(list,0);\r
+                                               if(ContentTypeDescr->descriptor_length){\r
+                                                       gf_free(ContentTypeDescr->content_type_data_byte);\r
+                                               }\r
+                                               gf_free(ContentTypeDescr);\r
+                                               break;\r
+                                       }\r
+                               default:\r
+                                       {\r
+\r
+                                               break;\r
+                                       }                               \r
+               }                       \r
+\r
+       }\r
+       gf_list_del(list);\r
+}\r
+\r
+\r
+static void dsmcc_free_biop_name(GF_M2TS_DSMCC_BIOP_NAME* Name, u32 nb_name){\r
+       u32 i;\r
+\r
+       for(i =0;i<nb_name;i++){\r
+\r
+               if(Name[i].id_length){\r
+                       gf_free(Name[i].id_data);                       \r
+               }               \r
+               if(Name[i].kind_length){\r
+                       gf_free(Name[i].kind_data);\r
+               }                       \r
+               /* IOR */\r
+               dsmcc_free_biop_ior(&Name[i].IOR);              \r
+               dsmcc_free_biop_descriptor(Name[i].descriptor);         \r
+       }\r
+}\r
+\r
+static void dsmcc_free_biop_context(GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 serviceContextList_count){\r
+       u32 i;\r
+\r
+       for(i=0;i<serviceContextList_count;i++){                \r
+               if(Context[i].context_data_length != 0){\r
+                       gf_free(Context[i].context_data_byte);                  \r
+               }\r
+       }\r
+       gf_free(Context);\r
+}\r
+\r
+#endif //GPAC_DISABLE_MPEG2TS
\ No newline at end of file
index 0ce63687fde20bf3ecc33f217e4f6f31d7e5f467..9abf791d14582021cc8315eb7542ffedaa5a5a11 100644 (file)
@@ -38,7 +38,7 @@ void dvb_decode_mjd_date(u32 date, u16 *year, u8 *month, u8 *day)
     else k = 0;
     *year = yp + k + 1900;
     *month = mp - 1 - k*12;
-       assert(*year>=1900 && *year<=2100 && *month && *month<12 && *day && *day<=31);
+       assert(*year>=1900 && *year<=2100 && *month && *month<=12 && *day && *day<=31);
 }
 
 #if 0 /*disabled since mktime doesn't exist on Windows Mobile*/
index 9562f81518bf007c4cb2d5afd2ac03570cd72f82..0349a32ac93871d530aa17b341ade74724757fc8 100644 (file)
@@ -2,16 +2,16 @@
 #include <gpac/network.h>
 #include <string.h>
 
+
+#ifndef GPAC_DISABLE_MPEG2TS
+
+
 static void gf_m2ts_Delete_IpPacket(GF_M2TS_IP_Packet *ip_packet);
 
 
 static void empty_list(GF_List * list)
 {
        void *obj;
-       u32 nb;
-
-       nb = gf_list_count(list);
-
        while(gf_list_count(list)){
                obj = gf_list_get(list,0);
                gf_list_rem(list,0);
@@ -40,11 +40,13 @@ static void on_dvb_mpe_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
 
                case GF_M2TS_TABLE_ID_MPE_FEC:
                case GF_M2TS_TABLE_ID_DSM_CC_PRIVATE:
-                       if(ts->ip_platform != NULL) {
-                               gf_m2ts_process_mpe(ts, (GF_M2TS_SECTION_MPE*)pck->stream, data, u32_data_size, u32_table_id);
-                       } else {
+                       if ((ts->ip_platform != NULL) || ts->direct_mpe) {
+                               GF_M2TS_SECTION_MPE* mpe = (GF_M2TS_SECTION_MPE*)pck->stream;
+                               gf_m2ts_process_mpe(ts, mpe, data, u32_data_size, u32_table_id);
+                       }
+                       else {
                                //printf("Time Slice Parameters for MPE-FEC have not been found yet \n");
-                       }                                               
+                       }
                        break;                          
                default:
                        return;
@@ -70,7 +72,6 @@ void gf_dvb_mpe_init(GF_M2TS_Demuxer *ts)
 
 void gf_dvb_mpe_shutdown(GF_M2TS_Demuxer *ts)
 {
-       u32 i_streams, i_targets;
        GF_M2TS_IP_Stream *ip_stream_buff;
 
        GF_M2TS_IP_PLATFORM * ip_platform;
@@ -80,8 +81,6 @@ void gf_dvb_mpe_shutdown(GF_M2TS_Demuxer *ts)
 
        if (!ip_platform) return;
 
-       i_streams = 0;
-       i_targets = 0;
        if (ip_platform->ip_streams){
                while(gf_list_count(ip_platform->ip_streams)){
                        ip_stream_buff=gf_list_get(ip_platform->ip_streams, 0); 
@@ -117,6 +116,7 @@ GF_M2TS_ES *gf_dvb_mpe_section_new()
 
        GF_M2TS_SECTION_MPE *ses;
        GF_SAFEALLOC(ses, GF_M2TS_SECTION_MPE);
+       ses->mff = NULL;
        es = (GF_M2TS_ES *)ses;
        es->flags = GF_M2TS_ES_IS_SECTION | GF_M2TS_ES_IS_MPE;
        return es;
@@ -159,12 +159,11 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned
 {
        GF_M2TS_IP_Stream *ip_stream_buff;
        GF_M2TS_IP_PLATFORM * ip_platform = ts->ip_platform;
-       u32 delta_t;
        u32 table_boundry_flag;
        u32 frame_boundry_flag; 
        u32 offset; 
        u32 i_streams,j;
-       u32 id,section_length, section_number, last_section_number;
+       u32 section_number, last_section_number;
        s32 len_left = data_size;
        assert( ts );
 
@@ -178,11 +177,9 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned
        }
        
        /*get number of rows of mpe_fec_frame from descriptor*/
-       id = data[0];
-       section_length = (data[1] & 0xF)<<8|data[2];
        section_number = data[6];               
        last_section_number = data[7];
-       //printf( "table_id: %x section_length: %d section_number: %d last : %d \n",id, section_length, section_number, last_section_number);   
+       //printf( "table_id: %x section_length: %d section_number: %d last : %d \n", data[0], (data[1] & 0xF)<<8|data[2], section_number, last_section_number); 
        
        if (ts->direct_mpe) {
                if (table_id != GF_M2TS_TABLE_ID_DSM_CC_PRIVATE) return;
@@ -201,7 +198,7 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned
 
        /*get number of rows of mpe_fec_frame from descriptor*/
        /* Real-Time Parameters */      
-       delta_t = (data[8]<<4)|(data[9]>>4);
+       //delta_t = (data[8]<<4)|(data[9]>>4);
        table_boundry_flag = (data[9] >> 3 )& 0x1;
        frame_boundry_flag = (data[9] >> 2 )& 0x1; 
                
@@ -422,8 +419,7 @@ void gf_m2ts_mpe_send_datagram(GF_M2TS_Demuxer *ts, u32 mpe_pid, unsigned char *
 
        socket_simu(&ip_pck, ts, 0);
 
-       fprintf(stdout, "MPE PID %d - send datagram %d bytes to %d.%d.%d.%d port:%d\n", mpe_pid, ip_pck.u32_udp_data_size-8, ip_pck.u8_rx_adr[0], ip_pck.u8_rx_adr[1], ip_pck.u8_rx_adr[2], ip_pck.u8_rx_adr[3], ip_pck.u32_rx_udp_port);
-
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("MPE PID %d - send datagram %d bytes to %d.%d.%d.%d port:%d\n", mpe_pid, ip_pck.u32_udp_data_size-8, ip_pck.u8_rx_adr[0], ip_pck.u8_rx_adr[1], ip_pck.u8_rx_adr[2], ip_pck.u8_rx_adr[3], ip_pck.u32_rx_udp_port));
 }
 
 
@@ -1079,6 +1075,7 @@ void socket_simu(GF_M2TS_IP_Packet *ip_packet, GF_M2TS_Demuxer *ts, Bool yield)
 
                if (gf_sk_is_multicast_address(name) ) {
                        e = gf_sk_setup_multicast(Sock_Struct->sock, name, ip_packet->u32_rx_udp_port, 1/*TTL - FIXME this should be in a cfg file*/, 0, NULL/*FIXME this should be in a cfg file*/);
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Setting up multicast socket for MPE on %s:%d\n", name, ip_packet->u32_rx_udp_port ));
                } else {
                        /* 
                                binding of the socket to send data to port 4600 on the local machine 
@@ -1086,6 +1083,7 @@ void socket_simu(GF_M2TS_IP_Packet *ip_packet, GF_M2TS_Demuxer *ts, Bool yield)
                                the second adress is "localhost" and the port is the destination port on localhost
                        */
                        e = gf_sk_bind(Sock_Struct->sock, "127.0.0.1", ip_packet->u32_rx_udp_port,/*name*/"127.0.0.1", ip_packet->u32_rx_udp_port, 0); 
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Setting up socket for MPE on 127.0.0.1:%d\n", ip_packet->u32_rx_udp_port ));
                }
 
                if (e != GF_OK) {
@@ -1259,10 +1257,10 @@ void setColRS( MPE_FEC_FRAME * mff, u32 offset, u8 * pds, u32 length )
 {
        if ( mff->current_offset_rs != offset)  {
                printf ("there is an error hole in the RS from %d to %d \n", mff->current_offset_rs, offset );
-               mff->current_offset_rs = offset;
-               setErrorIndicator( mff->p_error_rs , mff->current_offset_rs , (offset - mff->current_offset_rs)*sizeof(u32));            
+               setErrorIndicator( mff->p_error_rs , mff->current_offset_rs , (offset - mff->current_offset_rs)*sizeof(u32));
+               mff->current_offset_rs = offset;        
        } 
-  assert(mff->rows == length);
+       assert(mff->rows == length);
        memcpy(mff->p_rs + mff->current_offset_rs , pds, length*sizeof(u8) );
        mff->current_offset_rs = offset + length ; 
        
@@ -1270,9 +1268,7 @@ void setColRS( MPE_FEC_FRAME * mff, u32 offset, u8 * pds, u32 length )
 
 void getColRS(MPE_FEC_FRAME * mff, u32 offset, u8 * pds, u32 length)
 {
-       
        memcpy(pds,mff->p_rs + offset, length);
-
 }
 
 void getErrorPositions(MPE_FEC_FRAME *mff, u32 row, u32 * errPositions)
@@ -1310,7 +1306,7 @@ u32  getErrasurePositions( MPE_FEC_FRAME *mff , u32 row, u32 *errasures)
        return nb;
 }
 
-void setErrorIndicator(u32 * data , u32 offset,u32 length)
+void setErrorIndicator(u32 * data , u32 offset, u32 length)
 {
 //     printf("setting the error indication \n");
        memset(data+offset, 1, length);
@@ -1321,3 +1317,6 @@ void setErrorIndicator(u32 * data , u32 offset,u32 length)
        printf ("private descriptor \n");
        return ;
 }*/
+
+
+#endif //GPAC_DISABLE_MPEG2TS
index a12f1268293b3ddd1cef2022ad75cd5a91ceebf7..feaf651dc6a25cfc028b60e61bfb710ff96102d8 100644 (file)
@@ -335,7 +335,6 @@ GF_ISOMRTPStreamer *gf_isom_streamer_new(const char *file_name, const char *ip_d
        GF_ISOMRTPStreamer *streamer;
        GF_Err e = GF_OK;
        const char *opt = NULL;
-       const char *dest_ip;
        /*GF_Config *configFile = NULL; */
        u32 i, max_ptime, au_sn_len;    
        u8 payt;                        
@@ -352,7 +351,6 @@ GF_ISOMRTPStreamer *gf_isom_streamer_new(const char *file_name, const char *ip_d
        GF_SAFEALLOC(streamer, GF_ISOMRTPStreamer);
        streamer->dest_ip = gf_strdup(ip_dest);
 
-       dest_ip = ip_dest;
        payt = 96;
        max_ptime = au_sn_len = 0;
 
index 0f5d39c994ef2eba386c3a0c6c127406e5981a69..ade42edeff9a967f121c387ee85df60e9c0dcf9a 100644 (file)
@@ -319,6 +319,7 @@ GF_Err gf_img_jpeg_dec(char *jpg, u32 jpg_size, u32 *width, u32 *height, u32 *pi
                jpeg_destroy_decompress(&jpx.cinfo);
                return GF_BUFFER_TOO_SMALL;
        }
+       if (!dst_nb_comp) dst_nb_comp = jpx.cinfo.num_components;
 
        scan_line = NULL;
        /*decode*/
@@ -411,35 +412,6 @@ static void gf_png_user_error_fn(png_structp png_ptr,png_const_charp error_msg)
        longjmp(png_jmpbuf(png_ptr), 1);
 }
 
-GF_Err gf_img_png_file_dec(char *png_filename, u32 *width, u32 *height, u32 *pixel_format, char **dst, u32 *dst_size)
-{
-    u32 fsize, readen;
-    FILE *f;
-    char *data;
-    GF_Err e;
-    f = gf_f64_open(png_filename, "rb");
-    if (!f) return GF_URL_ERROR;
-
-    gf_f64_seek(f, 0, SEEK_END);
-    fsize = (u32)gf_f64_tell(f);
-    gf_f64_seek(f, 0, SEEK_SET);
-    data = gf_malloc(fsize);
-    readen = fread(data, sizeof(char), fsize, f);
-    if (readen != fsize){
-       fclose( f );
-       return GF_IO_ERR;
-    }
-    *dst_size = 0;
-    e = gf_img_png_dec(data, fsize, width, height, pixel_format, NULL, dst_size);    
-    if (*dst_size) {
-        *dst = gf_malloc(*dst_size);
-       fclose( f );
-        return gf_img_png_dec(data, fsize, width, height, pixel_format, *dst, dst_size);    
-    } else {
-       fclose( f );
-        return e;
-    }
-}
 
 GF_EXPORT
 GF_Err gf_img_png_dec(char *png, u32 png_size, u32 *width, u32 *height, u32 *pixel_format, char *dst, u32 *dst_size)
@@ -694,3 +666,49 @@ GF_Err gf_img_png_enc(char *data, u32 width, u32 height, s32 stride, u32 pixel_f
 #endif /*GPAC_HAS_PNG*/
 
 
+GF_Err gf_img_file_dec(char *png_filename, u32 *hint_oti, u32 *width, u32 *height, u32 *pixel_format, char **dst, u32 *dst_size)
+{
+    u32 fsize, read, oti;
+    FILE *f;
+    char *data;
+    GF_Err e;
+    f = gf_f64_open(png_filename, "rb");
+    if (!f) return GF_URL_ERROR;
+
+       oti = 0;
+       if (!hint_oti || ! *hint_oti) {
+               char *ext = strrchr(png_filename, '.');
+               if (!ext) return GF_NOT_SUPPORTED;
+               if (!stricmp(ext, ".png")) oti = GPAC_OTI_IMAGE_PNG;
+               else if (!stricmp(ext, ".jpg") || !stricmp(ext, ".jpeg")) oti = GPAC_OTI_IMAGE_JPEG;
+       }
+    gf_f64_seek(f, 0, SEEK_END);
+    fsize = (u32)gf_f64_tell(f);
+    gf_f64_seek(f, 0, SEEK_SET);
+    data = gf_malloc(fsize);
+    read = fread(data, sizeof(char), fsize, f);
+       fclose( f );
+    if (read != fsize) return GF_IO_ERR;
+
+       e = GF_NOT_SUPPORTED;
+       *dst_size = 0;
+       if (oti == GPAC_OTI_IMAGE_JPEG) {
+#ifdef GPAC_HAS_JPEG
+               e = gf_img_jpeg_dec(data, fsize, width, height, pixel_format, NULL, dst_size, 0);    
+               if (*dst_size) {
+                       *dst = gf_malloc(*dst_size);
+                       return gf_img_jpeg_dec(data, fsize, width, height, pixel_format, NULL, dst_size, 0);    
+               }
+#endif
+       } else if (oti == GPAC_OTI_IMAGE_PNG) {
+#ifdef GPAC_HAS_PNG
+               e = gf_img_png_dec(data, fsize, width, height, pixel_format, NULL, dst_size);    
+               if (*dst_size) {
+                       *dst = gf_malloc(*dst_size);
+                       return gf_img_png_dec(data, fsize, width, height, pixel_format, *dst, dst_size);    
+               }
+#endif
+       }
+       return e;
+}
+
index e6e5dc5f7fe3f1d29eed2215049e542855e39419..aec2100297d14043dc80f303e7d8ae42cef33ce2 100644 (file)
@@ -436,7 +436,7 @@ GF_EXPORT
 GF_Err gf_ismacryp_decrypt_file(GF_ISOFile *mp4, const char *drm_file)
 {
        GF_Err e;
-       u32 i, idx, count, common_idx, nb_tracks, scheme_type, cur_tk;
+       u32 i, idx, count, common_idx, nb_tracks, scheme_type;
        const char *scheme_URI, *KMS_URI;
        ISMACrypInfo *info;
        Bool is_oma;
@@ -463,7 +463,6 @@ GF_Err gf_ismacryp_decrypt_file(GF_ISOFile *mp4, const char *drm_file)
        }
        
        nb_tracks = gf_isom_get_track_count(mp4);
-       cur_tk = 1;
        e = GF_OK;
        for (i=0; i<nb_tracks; i++) {
                u32 trackID = gf_isom_get_track_id(mp4, i+1);
index ccdc84dacc2efc1f52cc63fab73ed2cb2f1ff709..7ce1c691d975c92ddbcb7ee34548efd4c8081aa5 100644 (file)
@@ -34,7 +34,7 @@
 void gf_media_get_sample_average_infos(GF_ISOFile *file, u32 Track, u32 *avgSize, u32 *MaxSize, u32 *TimeDelta, u32 *maxCTSDelta, u32 *const_duration, u32 *bandwidth)
 {
        u32 i, count, ts_diff;
-       u64 prevTS, DTS, tdelta;
+       u64 prevTS, tdelta;
        Double bw;
        GF_ISOSample *samp;
 
@@ -43,7 +43,6 @@ void gf_media_get_sample_average_infos(GF_ISOFile *file, u32 Track, u32 *avgSize
        *maxCTSDelta = 0;
        bw = 0;
        prevTS = 0;
-       DTS = 0;
        tdelta = 0;
 
        count = gf_isom_get_sample_count(file, Track);
@@ -132,14 +131,14 @@ void MP4T_DumpSDP(GF_ISOFile *file, const char *name)
        f = gf_f64_open(name, "wt");
        //get the movie SDP
        gf_isom_sdp_get(file, &sdp, &size);
-       fwrite(sdp, size, 1, f);
+       gf_fwrite(sdp, size, 1, f);
        fprintf(f, "\r\n");
 
        //then tracks
        for (i=0; i<gf_isom_get_track_count(file); i++) {
                if (gf_isom_get_media_type(file, i+1) != GF_ISOM_MEDIA_HINT) continue;
                gf_isom_sdp_track_get(file, i+1, &sdp, &size);
-               fwrite(sdp, size, 1, f);
+               gf_fwrite(sdp, size, 1, f);
        }
        fclose(f);
 }
index 0b22a3669c58ab9be3849bed78121919d075dd82..9f3939b282a23169861432e1f013ef0fa9d9b761 100644 (file)
 
 #ifndef GPAC_DISABLE_ISOM
 
+GF_Err gf_media_get_rfc_6381_codec_name(GF_ISOFile *movie, u32 track, char *szCodec)
+{
+       GF_ESD *esd;
+       GF_AVCConfig *avcc;
+       GF_AVCConfigSlot *sps;
+       u32 subtype = gf_isom_get_media_subtype(movie, track, 1);
+
+       switch (subtype) {
+       case GF_ISOM_SUBTYPE_MPEG4:
+               esd = gf_isom_get_esd(movie, track, 1);
+               switch (esd->decoderConfig->streamType) {
+               case GF_STREAM_AUDIO:
+                       if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
+                               /*5 first bits of AAC config*/
+                               u8 audio_object_type = (esd->decoderConfig->decoderSpecificInfo->data[0] & 0xF8) >> 3;
+                               sprintf(szCodec, "mp4a.%02x.%02x", esd->decoderConfig->objectTypeIndication, audio_object_type);
+                       } else {
+                               sprintf(szCodec, "mp4a.%02x", esd->decoderConfig->objectTypeIndication);
+                       }
+                       break;
+               case GF_STREAM_VISUAL:
+                       if (esd->decoderConfig->decoderSpecificInfo) {
+                               GF_M4VDecSpecInfo dsi;
+                               gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
+                               sprintf(szCodec, "mp4v.%02x.%02x", esd->decoderConfig->objectTypeIndication, dsi.VideoPL);
+                       } else {
+                               sprintf(szCodec, "mp4v.%02x", esd->decoderConfig->objectTypeIndication);
+                       }
+                       break;
+               default:
+                       sprintf(szCodec, "mp4s.%02x", esd->decoderConfig->objectTypeIndication);
+                       break;
+               }
+               gf_odf_desc_del((GF_Descriptor *)esd);
+               return GF_OK;
+
+       case GF_ISOM_SUBTYPE_AVC_H264:
+       case GF_ISOM_SUBTYPE_AVC2_H264:
+       case GF_ISOM_SUBTYPE_SVC_H264:
+               avcc = gf_isom_avc_config_get(movie, track, 1);
+               sps = gf_list_get(avcc->sequenceParameterSets, 0);
+               sprintf(szCodec, "%s.%02x%02x%02x", gf_4cc_to_str(subtype), (u8) sps->data[1], (u8) sps->data[2], (u8) sps->data[3]);
+               gf_odf_avc_cfg_del(avcc);
+               return GF_OK;
+
+       default:
+               GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISOM Tools] codec parameters not known - setting codecs string to default value \"%s\"\n", gf_4cc_to_str(subtype) ));
+               sprintf(szCodec, "%s", gf_4cc_to_str(subtype));
+               return GF_OK;
+       }
+       return GF_OK;
+}
+
 #ifndef GPAC_DISABLE_ISOM_WRITE
 
 static const u32 ISMA_VIDEO_OD_ID = 20;
@@ -76,11 +129,10 @@ static const u8 ISMA_BIFS_AI[] =
 GF_EXPORT
 GF_Err gf_media_make_isma(GF_ISOFile *mp4file, Bool keepESIDs, Bool keepImage, Bool no_ocr)
 {
-       u32 AudioTrack, VideoTrack, Tracks, i, mType, bifsT, odT, descIndex, VideoType, VID, AID, bifsID, odID;
+       u32 AudioTrack, VideoTrack, Tracks, i, mType, bifsT, odT, descIndex, VID, AID, bifsID, odID;
        u32 bifs, w, h;
        Bool is_image, image_track;
        GF_ESD *a_esd, *v_esd, *_esd;
-       Bool update_vid_esd;
        GF_ObjectDescriptor *od;
        GF_ODUpdate *odU;
        GF_ODCodec *codec;
@@ -174,7 +226,6 @@ GF_Err gf_media_make_isma(GF_ISOFile *mp4file, Bool keepESIDs, Bool keepImage, B
        odU = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
 
        a_esd = v_esd = NULL;
-       update_vid_esd = 0;
 
        gf_isom_set_root_od_id(mp4file, 1);
 
@@ -194,7 +245,6 @@ GF_Err gf_media_make_isma(GF_ISOFile *mp4file, Bool keepESIDs, Bool keepImage, B
        w = h = 0;
        if (VideoTrack) {
                bifs = 1;
-               VideoType = 0;
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
                od->objectDescriptorID = ISMA_VIDEO_OD_ID;
 
@@ -610,27 +660,57 @@ GF_Err gf_media_make_psp(GF_ISOFile *mp4)
 
 typedef struct
 {
+       Bool is_ref_track;
        Bool done;
        u32 TrackID;
        u32 SampleNum, SampleCount;
        u32 FragmentLength;
        u32 OriginalTrack;
+       u32 finalSampleDescriptionIndex;
        u32 TimeScale, MediaType, DefaultDuration, InitialTSOffset;
        u64 last_sample_cts, next_sample_dts;
+       Bool all_sample_raps;
 } TrackFragmenter;
 
+static u64 get_next_sap_time(GF_ISOFile *input, u32 track, u32 sample_count, u32 sample_num)
+{
+       GF_ISOSample *samp;
+       u64 time;
+       Bool is_rap, has_roll;
+       u32 i, found_sample = 0;
+       for (i=sample_num; i<=sample_count; i++) {
+               if (gf_isom_get_sample_sync(input, track, i)) {
+                       found_sample = i;
+                       break;
+               }
+               gf_isom_get_sample_rap_roll_info(input, track, i, &is_rap, &has_roll, NULL);
+               if (is_rap || has_roll) {
+                       found_sample = i;
+                       break;
+               }
+       }
+       if (!found_sample) return 0;
+       samp = gf_isom_get_sample_info(input, track, found_sample, NULL, NULL);
+       time = samp->DTS;
+       gf_isom_sample_del(&samp);
+       return time;
+}
+
 
 GF_EXPORT
-GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 fragments_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, const char *dash_ctx_file)
+GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool single_segment_mode, const char *dash_ctx_file, GF_ISOFile *sample_descs, u32 rep_idx)
 {
        u8 NbBits;
        u32 i, TrackNum, descIndex, j, count, nb_sync, ref_track_id, nb_tracks_done;
        u32 defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, nb_samp, nb_done;
+       u32 nb_video, nb_audio, nb_text, nb_scene;
        u8 defaultPadding;
        u16 defaultDegradationPriority;
        GF_Err e;
        char sOpt[100], sKey[100];
-       u32 cur_seg, fragment_index;
+       char szCodecs[200], szCodec[100];
+       char szComponents[1000];
+       u32 cur_seg, fragment_index, nb_fragments, max_sap_type;
        GF_ISOFile *output;
        GF_ISOSample *sample, *next;
        GF_List *fragmenters;
@@ -638,14 +718,17 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
        Double average_duration, file_duration, period_duration, max_segment_duration;
        u32 nb_segments, width, height, sample_rate, nb_channels;
        char langCode[5];
+       u32 index_start_range, index_end_range;
+       Bool force_switch_segment = 0;
        Bool switch_segment = 0;
        Bool split_seg_at_rap = (dash_mode==2) ? 1 : 0;
        Bool split_at_rap = 0;
        Bool has_rap = 0;
        Bool next_sample_rap = 0;
        Bool flush_all_samples = 0;
+       Bool simulation_pass = 0;
        u64 last_ref_cts = 0;
-       u64 start_range, end_range, file_size, init_seg_size, ref_track_cur_dur;
+       u64 start_range, end_range, file_size, init_seg_size, ref_track_first_dts, ref_track_next_cts;
        u32 tfref_timescale = 0;
        u32 bandwidth = 0;
        TrackFragmenter *tf, *tfref;
@@ -656,8 +739,13 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
        GF_Config *dash_ctx = NULL;
        Bool store_dash_params = 0;
        Bool dash_moov_setup = 0;
-       Bool segments_start_with_rap = 1;
+       Bool segments_start_with_sap = 1;
        Bool first_sample_in_segment = 0;
+       u32 *segments_info = NULL;
+       u32 nb_segments_info = 0;
+       Bool audio_only = 1;
+
+
        SegmentDuration = 0;
        nb_samp = 0;
        fragmenters = NULL;
@@ -699,11 +787,7 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                if (store_dash_params) {
                        gf_cfg_set_key(dash_ctx, "DASH", "InitializationSegment", SegName);
                }
-
-
-               strcpy(SegName, output_file);
-               strcat(SegName, ".mpd");
-               mpd = gf_f64_open(SegName, "wt");
+               mpd = gf_f64_open(mpd_name, "a+t");
                mpd_segs = gf_temp_file_new();
        } else {
                output = gf_isom_open(output_file, GF_ISOM_OPEN_WRITE, NULL);
@@ -719,14 +803,23 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                if (e) goto err_exit;
        }
 
-       MaxFragmentDuration = (u32) (max_duration_sec * 1000);
+       MaxFragmentDuration = (u32) (max_duration_sec * 1000);  
        MaxSegmentDuration = (u32) (dash_duration_sec * 1000);
+
+       /*in single segment mode, only one big SIDX is written between the end of the moov and the first fragment. 
+       To speed-up writing, we do a first fragmentation pass without writing any sample to compute the number of segments and fragments per segment
+       in order to allocate / write to file the sidx before the fragmentation. The sidx will then be rewritten when closing the last segment*/
+       if (single_segment_mode) simulation_pass = 1;
+       index_start_range = index_end_range = 0;        
+
        tfref = NULL;
        file_duration = 0;
        width = height = sample_rate = nb_channels = 0;
        langCode[0]=0;
        langCode[4]=0;
+       szCodecs[0] = 0;
 
+       nb_video = nb_audio = nb_text = nb_scene = 0;
        //duplicates all tracks
        for (i=0; i<gf_isom_get_track_count(input); i++) {
                u32 _w, _h, _sr, _nb_ch;
@@ -755,8 +848,15 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        count = gf_isom_get_sample_count(input, i+1);
                }
 
-               //setup fragmenters
+               if (mtype == GF_ISOM_MEDIA_VISUAL) nb_video++;
+               else if (mtype == GF_ISOM_MEDIA_AUDIO) nb_audio++;
+               else if (mtype == GF_ISOM_MEDIA_TEXT) nb_text++;
+               else if (mtype == GF_ISOM_MEDIA_SCENE) nb_scene++;
+               else if (mtype == GF_ISOM_MEDIA_DIMS) nb_scene++;
+
+               if (mtype != GF_ISOM_MEDIA_AUDIO) audio_only = 0;
 
+               //setup fragmenters
                if (! dash_moov_setup) {
                        gf_isom_get_fragment_defaults(input, i+1,
                                                                         &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority);
@@ -773,6 +873,10 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                                                         &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority);
                }
 
+               gf_media_get_rfc_6381_codec_name(output, TrackNum, szCodec);
+               if (strlen(szCodecs)) strcat(szCodecs, ",");
+               strcat(szCodecs, szCodec);
+
                GF_SAFEALLOC(tf, TrackFragmenter);
                tf->TrackID = gf_isom_get_track_id(output, TrackNum);
                tf->SampleCount = gf_isom_get_sample_count(input, i+1);
@@ -784,9 +888,13 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                if (gf_isom_get_sync_point_count(input, i+1)>nb_sync) { 
                        tfref = tf;
                        nb_sync = gf_isom_get_sync_point_count(input, i+1);
+               } else if (!gf_isom_has_sync_points(input, i+1)) {
+                       tf->all_sample_raps = 1;
                }
 
-                       /*figure out if we have an initial TS*/
+               tf->finalSampleDescriptionIndex = 1;
+
+               /*figure out if we have an initial TS*/
                if (!dash_moov_setup) {
                        if (gf_isom_get_edit_segment_count(input, i+1)) {
                                u64 EditTime, SegmentDuration, MediaTime;
@@ -798,6 +906,53 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                /*and remove edit segments*/
                                gf_isom_remove_edit_segments(output, TrackNum);
                        }
+                       /*locate sample description in list if given*/
+                       if (sample_descs) {
+                               u32 s_count;
+                               u32 sample_descs_track = gf_isom_get_track_by_id(sample_descs, tf->TrackID);
+                               if (!sample_descs_track) {
+                                       e = GF_BAD_PARAM;
+                                       goto err_exit;
+
+                               }
+
+                               //the initialization segment is not yet setup for fragmentation
+                               if (! gf_isom_is_track_fragmented(sample_descs, tf->TrackID)) {
+                                       e = gf_isom_setup_track_fragment(sample_descs, sample_descs_track,
+                                                               defaultDescriptionIndex, defaultDuration,
+                                                               defaultSize, (u8) defaultRandomAccess,
+                                                               defaultPadding, defaultDegradationPriority);
+                                       if (e) goto err_exit;
+                               }
+                               /*otherwise override the fragment defauls so that we are consistent with the shared init segment*/
+                               else {
+                                       e = gf_isom_get_fragment_defaults(sample_descs, sample_descs_track,
+                                                                                        &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority);
+                                       if (e) goto err_exit;
+
+                                       e = gf_isom_change_track_fragment_defaults(output, TrackNum,
+                                                                                        defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, defaultPadding, defaultDegradationPriority);
+                                       if (e) goto err_exit;
+
+
+                               }
+
+                               /*reset all sample desc and clone with new ones*/
+                               gf_isom_clone_sample_descriptions(output, TrackNum, sample_descs, sample_descs_track, 1);
+
+                               /*and search in new ones the new index*/
+                               s_count = gf_isom_get_sample_description_count(sample_descs, sample_descs_track); 
+                               if (s_count>1) {
+                                       u32 k;
+                                       /*remove all sample descs*/
+                                       for (k=0; k<s_count; k++) {
+                                               /*search in original file if we have the sample desc*/
+                                               if (gf_isom_is_same_sample_description(input, TrackNum, 1, sample_descs, sample_descs_track, k+1)) {
+                                                       tf->finalSampleDescriptionIndex = k+1;
+                                               }
+                                       }
+                               }
+                       }
                }
                /*restore track decode times*/
                else {
@@ -806,7 +961,7 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        opt = (char *)gf_cfg_get_key(dash_ctx, sKey, "NextDecodingTime");
                        if (opt) tf->InitialTSOffset = atoi(opt);
                }
-
+       
                switch (mtype) {
                case GF_ISOM_MEDIA_TEXT:
                        gf_isom_get_media_language(input, i+1, langCode);
@@ -832,21 +987,48 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        file_duration = ((Double) gf_isom_get_media_duration(input, i+1)) / tf->TimeScale;
                }
                gf_list_add(fragmenters, tf);
+
                nb_samp += count;
        }
 
+       /*format component info*/
+       szComponents[0] = 0;
+       for (i=0; i<gf_list_count(fragmenters); i++) {
+               char szComponent[100];
+               tf = gf_list_get(fragmenters, i);
+               switch (tf->MediaType) {
+               case GF_ISOM_MEDIA_TEXT:
+                       gf_isom_get_media_language(input, i+1, langCode);
+                       sprintf(szComponent, "    <ContentComponent id=\"%d\" contentType=\"text\" lang=\"%s\"/>\n", tf->TrackID, langCode);
+                       break;
+               case GF_ISOM_MEDIA_VISUAL:
+                       sprintf(szComponent, "    <ContentComponent id=\"%d\" contentType=\"video\"/>\n", tf->TrackID);
+                       break;
+               case GF_ISOM_MEDIA_SCENE:
+               case GF_ISOM_MEDIA_DIMS:
+                       sprintf(szComponent, "    <ContentComponent id=\"%d\" contentType=\"application\" lang=\"%s\"/>\n", tf->TrackID, langCode);
+                       break;
+               case GF_ISOM_MEDIA_AUDIO:
+                       sprintf(szComponent, "    <ContentComponent id=\"%d\" contentType=\"audio\" lang=\"%s\"/>\n", tf->TrackID, langCode);
+                       break;
+               }
+               strcat(szComponents, szComponent);
+       }
+
        if (!tfref) tfref = gf_list_get(fragmenters, 0);
+       tfref->is_ref_track = 1;
        tfref_timescale = tfref->TimeScale;
        ref_track_id = tfref->TrackID;
+       if (tfref->all_sample_raps) split_seg_at_rap = 1;
 
        //flush movie
        e = gf_isom_finalize_for_fragment(output, dash_mode ? 1 : 0);
        if (e) goto err_exit;
 
        start_range = 0;
-       end_range = gf_isom_get_file_size(output);
-       file_size = end_range;
-       init_seg_size = end_range;
+       file_size = gf_isom_get_file_size(output);
+       end_range = file_size - 1;
+       init_seg_size = file_size;
 
        if (dash_ctx) {
                if (store_dash_params) {
@@ -859,11 +1041,13 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                }
        }
 
+restart_fragmentation_pass:
+
        average_duration = 0;
        nb_segments = 0;
 
        nb_tracks_done = 0;
-       ref_track_cur_dur = tfref ? tfref->InitialTSOffset : 0;
+       ref_track_first_dts = (u64) -1;
        nb_done = 0;
 
        maxFragDurationOverSegment=0;
@@ -874,6 +1058,13 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
        cur_seg=1;
        fragment_index=1;
        period_duration = 0;
+       split_at_rap = 0;
+       has_rap = 0;
+       next_sample_rap = 0;
+       flush_all_samples = 0;
+       force_switch_segment = 0;
+       max_sap_type = 0;
+       ref_track_next_cts = 0;
 
        /*setup previous URL list*/
        if (dash_ctx) {
@@ -893,7 +1084,10 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                if (opt) period_duration = atof(opt);
        }
        gf_isom_set_next_moof_number(output, fragment_index);
+
+
        max_segment_duration = 0;
+       nb_fragments=0;
 
        while ( (count = gf_list_count(fragmenters)) ) {
 
@@ -901,39 +1095,60 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        SegmentDuration = 0;
                        switch_segment = 0;
                        first_sample_in_segment = 1;
-                       start_range = gf_isom_get_file_size(output);
-                       if (seg_rad_name) {
-                               sprintf(SegName, "%s%d.%s", seg_rad_name, cur_seg, seg_ext);
-                               e = gf_isom_start_segment(output, SegName);
-                               if (!use_url_template) {
-                                       fprintf(mpd_segs, "    <Url sourceURL=\"%s\"/>\n", SegName);    
-                                       if (dash_ctx) {
-                                               char szKey[100], szVal[4046];
-                                               sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
-                                               sprintf(szVal, "<Url sourceURL=\"%s\"/>", SegName);
-                                               gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
+
+                       if (simulation_pass) {
+                               segments_info = gf_realloc(segments_info, sizeof(u32) * (nb_segments_info+1) );
+                               segments_info[nb_segments_info] = 0;
+                               nb_segments_info++;
+                               e = GF_OK;
+                       } else {
+                               start_range = gf_isom_get_file_size(output);
+                               if (seg_rad_name) {
+                                       sprintf(SegName, "%s%d.%s", seg_rad_name, cur_seg, seg_ext);
+                                       e = gf_isom_start_segment(output, SegName);
+                                       if (!use_url_template) {
+                                               fprintf(mpd_segs, "     <SegmentURL media=\"%s\"/>\n", SegName);        
+                                               if (dash_ctx) {
+                                                       char szKey[100], szVal[4046];
+                                                       sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
+                                                       sprintf(szVal, "<SegmentURL sourceURL=\"%s\"/>", SegName);
+                                                       gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
+                                               }
                                        }
+                               } else {
+                                       e = gf_isom_start_segment(output, NULL);
                                }
-                       } else {
-                               e = gf_isom_start_segment(output, NULL);
                        }
+
                        cur_seg++;
                        if (e) goto err_exit;
                } 
 
                maxFragDurationOverSegment=0;
-               e = gf_isom_start_fragment(output, 1);
-               if (e) goto err_exit;
+
                sample = NULL;
 
-               for (i=0; i<count; i++) {
-                       tf = (TrackFragmenter *)gf_list_get(fragmenters, i);
-                       if (tf->done) continue;
-                       gf_isom_set_traf_base_media_decode_time(output, tf->TrackID, tf->InitialTSOffset + tf->next_sample_dts);
+               if (simulation_pass) {
+                       segments_info[nb_segments_info-1] ++;
+                       e = GF_OK;
+               } else {
+                       e = gf_isom_start_fragment(output, 1);
+                       if (e) goto err_exit;
+       
+
+                       for (i=0; i<count; i++) {
+                               tf = (TrackFragmenter *)gf_list_get(fragmenters, i);
+                               if (tf->done) continue;
+                               gf_isom_set_traf_base_media_decode_time(output, tf->TrackID, tf->InitialTSOffset + tf->next_sample_dts);
+                       }
+               
                }
 
                //process track by track
                for (i=0; i<count; i++) {
+                       Bool has_roll, is_rap;
+                       s32 roll_distance;
+                       u32 SAP_type = 0;
                        /*start with ref*/
                        if (tfref && split_seg_at_rap ) {
                                if (i==0) {
@@ -955,8 +1170,26 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        //ok write samples
                        while (1) {
                                Bool stop_frag = 0;
+
+                               /*first sample*/
                                if (!sample) {
                                        sample = gf_isom_get_sample(input, tf->OriginalTrack, tf->SampleNum + 1, &descIndex);
+                                       if (!sample) {
+                                               e = gf_isom_last_error(input);
+                                               goto err_exit;
+                                       }
+
+                                       /*also get SAP type - this is not needed if sample is not NULL as SAP tye was computed for "next sample" in previous loop*/
+                                       if (sample->IsRAP) {
+                                               SAP_type = 1;
+                                       } else {
+                                               SAP_type = 0;
+                                               e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, &roll_distance);
+                                               if (e==GF_OK) {
+                                                       if (is_rap) SAP_type = 3;
+                                                       else if (has_roll && (roll_distance>=0) ) SAP_type = 4;
+                                               }
+                                       }
                                }
                                gf_isom_get_sample_padding_bits(input, tf->OriginalTrack, tf->SampleNum+1, &NbBits);
 
@@ -967,24 +1200,46 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                        defaultDuration = tf->DefaultDuration;
                                }
 
-                               if (segments_start_with_rap && first_sample_in_segment && (tf==tfref)) {
-                                       first_sample_in_segment = 0;
-                                       if (!sample->IsRAP) segments_start_with_rap = 0;
-                               }
-
+                               if (tf==tfref) {
+                                       if (segments_start_with_sap && first_sample_in_segment ) {
+                                               first_sample_in_segment = 0;
+                                               if (! SAP_type) segments_start_with_sap = 0;
+                                       }
+                                       if (ref_track_first_dts > sample->DTS) 
+                                               ref_track_first_dts = sample->DTS;
 
-                               e = gf_isom_fragment_add_sample(output, tf->TrackID, sample, descIndex,
-                                                                defaultDuration, NbBits, 0);
-                               if (e) 
-                                       goto err_exit;
+                                       if (next) {
+                                               u64 next_cts = next->DTS + next->CTS_Offset;
+                                               if (ref_track_next_cts<next_cts) {
+                                                       ref_track_next_cts = next_cts;
+                                               }
+                                       } else {
+                                               u64 cts = gf_isom_get_media_duration(input, tf->OriginalTrack);
+                                               if (cts>ref_track_next_cts) ref_track_next_cts = cts;
+                                               else ref_track_next_cts += defaultDuration;
+                                       }
+                               }
 
-                               /*copy subsample information*/
-                               e = gf_isom_fragment_copy_subsample(output, tf->TrackID, input, tf->OriginalTrack, tf->SampleNum + 1);
-                               if (e) 
-                                       goto err_exit;
+                               if (SAP_type > max_sap_type) max_sap_type = SAP_type;
 
-                               gf_set_progress("ISO File Fragmenting", nb_done, nb_samp);
-                               nb_done++;
+                               if (simulation_pass) {
+                                       e = GF_OK;
+                               } else {
+                                       /*override descIndex with final index used in file*/
+                                       descIndex = tf->finalSampleDescriptionIndex;
+                                       e = gf_isom_fragment_add_sample(output, tf->TrackID, sample, descIndex,
+                                                                        defaultDuration, NbBits, 0);
+                                       if (e) 
+                                               goto err_exit;
+
+                                       /*copy subsample information*/
+                                       e = gf_isom_fragment_copy_subsample(output, tf->TrackID, input, tf->OriginalTrack, tf->SampleNum + 1);
+                                       if (e) 
+                                               goto err_exit;
+
+                                       gf_set_progress("ISO File Fragmenting", nb_done, nb_samp);
+                                       nb_done++;
+                               }
 
                                tf->last_sample_cts = sample->DTS + sample->CTS_Offset;
                                tf->next_sample_dts = sample->DTS + defaultDuration;
@@ -994,20 +1249,54 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                tf->FragmentLength += defaultDuration;
                                tf->SampleNum += 1;
 
-                               if (next && next->IsRAP) {
+                               /*compute SAP type*/
+                               if (sample) {
+                                       if (sample->IsRAP) {
+                                               SAP_type = 1;
+                                       } else {
+                                               SAP_type = 0;
+                                               e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, NULL);
+                                               if (e==GF_OK) {
+                                                       if (is_rap)
+                                                               SAP_type = 3;
+                                                       else if (has_roll && (roll_distance>=0) )
+                                                               SAP_type = 4;
+                                               }
+                                       }
+                               }
+
+                               if (next && SAP_type) {
                                        if (tf==tfref) {
                                                if (split_seg_at_rap) {
-                                                       u32 frag_dur = tf->FragmentLength*1000/tf->TimeScale;
+                                                       u64 next_sap_time;
+                                                       /*duration of fragment if we add this rap*/
+                                                       u32 frag_dur = (tf->FragmentLength+defaultDuration)*1000/tf->TimeScale;
                                                        next_sample_rap = 1;
-                                                       /*if media segment about to be produced is longer than max segment length, force split*/
-                                                       if (SegmentDuration + frag_dur > MaxSegmentDuration) {
-                                                               split_at_rap = 1;
+                                                       next_sap_time = get_next_sap_time(input, tf->OriginalTrack, tf->SampleCount, tf->SampleNum + 2);
+                                                       /*if no more SAP after this one, do not switch segment*/
+                                                       if (next_sap_time) {
+                                                               u32 scaler;
+                                                               /*this is the fragment duration from last sample added to next SAP*/
+                                                               frag_dur += (u32) (next_sap_time - tf->next_sample_dts - defaultDuration)*1000/tf->TimeScale;
+                                                               /*if media segment about to be produced is longer than max segment length, force segment split*/
+                                                               if (SegmentDuration + frag_dur > MaxSegmentDuration) {
+                                                                       split_at_rap = 1;
+                                                                       /*force new segment*/
+                                                                       force_switch_segment = 1;
+                                                               }
+
+                                                               /*if adding this SAP will result in stoping the fragment "soon" after it, stop now and start with SAP
+                                                               if all samples are RAPs, just stop fragment if we exceed the requested duration by adding the next sample
+                                                               otherwise, take 3 samples (should be refined of course)*/
+                                                               scaler = 3;
+                                                               if (tf->all_sample_raps) scaler = 1;
+                                                               if ( (tf->FragmentLength + scaler*defaultDuration)*1000 >= MaxFragmentDuration * tf->TimeScale)
+                                                                       stop_frag = 1;
                                                        }
-
-                                                       if (split_at_rap) {
+                                                       if (split_at_rap && !tf->all_sample_raps) {
                                                                stop_frag = 1;
                                                                /*override fragment duration for the rest of this fragment*/
-                                                               MaxFragmentDuration = frag_dur;
+                                                               MaxFragmentDuration = tf->FragmentLength*1000/tf->TimeScale;
                                                        }
                                                } else if (!has_rap) {
                                                        if (tf->FragmentLength == defaultDuration) has_rap = 2;
@@ -1061,7 +1350,12 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        SegmentDuration += maxFragDurationOverSegment;
                        maxFragDurationOverSegment=0;
 
-                       if ((SegmentDuration >= MaxSegmentDuration) && (!split_seg_at_rap || next_sample_rap)) {
+                       /*next fragment will exceed segment length, abort fragment now (all samples RAPs)*/
+                       if (tfref && tfref->all_sample_raps && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) {
+                               force_switch_segment = 1;
+                       }
+
+                       if (force_switch_segment || ((SegmentDuration >= MaxSegmentDuration) && (!split_seg_at_rap || next_sample_rap))) {
                                average_duration += SegmentDuration;
                                nb_segments++;
                                if (max_segment_duration * 1000 <= SegmentDuration) {
@@ -1079,6 +1373,7 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                }
                                fprintf(stdout, "\n ");
 #endif
+                               force_switch_segment=0;
                                switch_segment=1;
                                SegmentDuration=0;
                                split_at_rap = 0;
@@ -1086,26 +1381,31 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                                /*restore fragment duration*/
                                MaxFragmentDuration = (u32) (max_duration_sec * 1000);
 
-                               gf_isom_close_segment(output, fragments_per_sidx, ref_track_id, ref_track_cur_dur, daisy_chain_sidx, flush_all_samples ? 1 : 0);
-                               if (tfref) ref_track_cur_dur = tfref->InitialTSOffset + tfref->next_sample_dts;
-
-                               if (!seg_rad_name) {
-                                       file_size = end_range = gf_isom_get_file_size(output);
-                                       fprintf(mpd_segs, "    <Url range=\""LLD"-"LLD"\"/>\n", start_range, end_range);        
-                                       if (dash_ctx) {
-                                               char szKey[100], szVal[4046];
-                                               sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
-                                               sprintf(szVal, "<Url range=\""LLD"-"LLD"\"/>", start_range, end_range);
-                                               gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
-
+                               if (!simulation_pass) {
+                                       u64 idx_start_range, idx_end_range;
+                                       
+                                       gf_isom_close_segment(output, subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, daisy_chain_sidx, flush_all_samples ? 1 : 0, &idx_start_range, &idx_end_range);
+                                       ref_track_first_dts = (u64) -1;
+
+                                       if (!seg_rad_name) {
+                                               file_size = gf_isom_get_file_size(output);
+                                               end_range = file_size - 1;
+                                               if (!single_segment_mode) {
+                                                       fprintf(mpd_segs, "     <SegmentURL mediaRange=\""LLD"-"LLD"\" indexRange=\""LLD"-"LLD"\"/>\n", start_range, end_range, idx_start_range, idx_end_range);        
+                                                       if (dash_ctx) {
+                                                               char szKey[100], szVal[4046];
+                                                               sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
+                                                               sprintf(szVal, "<SegmentURL mediaRange=\""LLD"-"LLD"\" indexRange=\""LLD"-"LLD"\"/>", start_range, end_range, idx_start_range, idx_end_range);
+                                                               gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
+                                                       }
+                                               }
+                                       } else {
+                                               file_size += gf_isom_get_file_size(output);
                                        }
-                               } else {
-                                       file_size += gf_isom_get_file_size(output);
                                }
-
                        } 
-                       /*next fragment will exceed segment length, abort fragment at next rap*/
-                       if (split_seg_at_rap && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) {
+                       /*next fragment will exceed segment length, abort fragment at next rap (possibly after MaxSegmentDuration)*/
+                       if (split_seg_at_rap && SegmentDuration && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) {
                                split_at_rap = 1;
                        }
                }
@@ -1113,65 +1413,79 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                if (nb_tracks_done==count) break;
        }
 
+       if (simulation_pass) {
+               /*OK, we have all segments and frags per segments*/
+               gf_isom_allocate_sidx(output, subsegs_per_sidx, daisy_chain_sidx, nb_segments_info, segments_info, &index_start_range, &index_end_range );
+               gf_free(segments_info);
+               segments_info = NULL;
+               simulation_pass = 0;
+               /*reset fragmenters*/
+               for (i=0; i<gf_list_count(fragmenters); i++) {
+                       tf = gf_list_get(fragmenters, i);
+                       tf->done = 0;
+                       tf->last_sample_cts = 0;
+                       tf->next_sample_dts = 0;
+                       tf->FragmentLength = 0;
+                       tf->SampleNum = 0;
+                       if (tf->is_ref_track) tfref = tf;
+               }
+               goto restart_fragmentation_pass;
+       }
 
        if (dash_mode) {
                char buffer[1000];
-               u32 size;
                u32 h, m;
                Double s;
 
                /*flush last segment*/
                if (!switch_segment) {
+                       u64 idx_start_range, idx_end_range;
+
                        if (max_segment_duration * 1000 <= SegmentDuration) {
                                max_segment_duration = SegmentDuration;
                                max_segment_duration /= 1000;
                        }
-                       if (!split_at_rap) {
-                               assert(max_segment_duration <= dash_duration_sec);
-                       }
 
-                       gf_isom_close_segment(output, fragments_per_sidx, ref_track_id, ref_track_cur_dur, daisy_chain_sidx, 1);
+                       gf_isom_close_segment(output, subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, daisy_chain_sidx, 1, &idx_start_range, &idx_end_range);
                        nb_segments++;
+
                        if (!seg_rad_name) {
-                               file_size = end_range = gf_isom_get_file_size(output);
-                               fprintf(mpd_segs, "    <Url range=\""LLD"-"LLD"\"/>\n", start_range, end_range);        
-
-                               if (dash_ctx) {
-                                       char szKey[100], szVal[4046];
-                                       sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
-                                       sprintf(szVal, "<Url range=\""LLD"-"LLD"\"/>", start_range, end_range);
-                                       gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
+                               file_size = gf_isom_get_file_size(output);
+                               end_range = file_size - 1;
+                               if (!single_segment_mode) {
+                                       fprintf(mpd_segs, "     <SegmentURL mediaRange=\""LLD"-"LLD"\" indexRange=\""LLD"-"LLD"\"/>\n", start_range, end_range, idx_start_range, idx_end_range);        
+                                       if (dash_ctx) {
+                                               char szKey[100], szVal[4046];
+                                               sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 );
+                                               sprintf(szVal, "<SegmentURL mediaRange=\""LLD"-"LLD"\" indexRange=\""LLD"-"LLD"\"/>", start_range, end_range, idx_start_range, idx_end_range);
+                                               gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal);
+                                       }
                                }
                        } else {
                                file_size += gf_isom_get_file_size(output);
                        }
                }
 
-               if (use_url_template) {
-                       sprintf(SegName, "%s_seg$Index$.%s", seg_rad_name, seg_ext);
-                       fprintf(mpd_segs, "    <UrlTemplate sourceURL=\"%s\" startIndex=\"1\" endIndex=\"%d\" />\n", SegName, cur_seg-1);       
-               }
                period_duration += file_duration;
                h = (u32) (period_duration/3600);
                m = (u32) (period_duration-h*60)/60;
                s = period_duration - h*3600 - m*60;
                bandwidth = (u32) (file_size * 8 / file_duration);
 
-               fprintf(mpd, "<MPD type=\"OnDemand\" xmlns=\"urn:3GPP:ns:PSS:AdaptiveHTTPStreamingMPD:2009\">\n");
-           fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
-               fprintf(mpd, "  <Title>Media Presentation Description for file %s generated with GPAC </Title>\n", gf_isom_get_filename(input));
-        fprintf(mpd, " </ProgramInformation>\n");
-        fprintf(mpd, " <Period start=\"PT0S\" duration=\"PT%dH%dM%.2fS\">\n", h, m, s);        
-               fprintf(mpd, "  <Representation mimeType=\"video/mp4\"");
+               fprintf(mpd, "   <Representation id=\"%d\" mimeType=\"%s/mp4\" codecs=\"%s\"", rep_idx ? rep_idx : 1, audio_only ? "audio" : "video", szCodecs);
                if (width && height) fprintf(mpd, " width=\"%d\" height=\"%d\"", width, height);
                if (sample_rate && nb_channels) fprintf(mpd, " sampleRate=\"%d\" numChannels=\"%d\"", sample_rate, nb_channels);
                if (langCode[0]) fprintf(mpd, " lang=\"%s\"", langCode);
-               fprintf(mpd, " startWithRAP=\"%s\"", (segments_start_with_rap || split_seg_at_rap) ? "true" : "false");
-               fprintf(mpd, " bandwidth=\"%d\"", bandwidth);
-               /*what should we put here ?? */
-               fprintf(mpd, " minBufferTime=\"%d\"", MaxFragmentDuration);
+               if (segments_start_with_sap || split_seg_at_rap) {
+                       fprintf(mpd, " startWithSAP=\"%d\"", max_sap_type);
+               } else {
+                       fprintf(mpd, " startWithSAP=\"false\"");
+               }
+               if (single_segment_mode && segments_start_with_sap) fprintf(mpd, " subsegmentStartsWithSAP=\"true\"");
                
+               fprintf(mpd, " bandwidth=\"%d\"", bandwidth);           
                fprintf(mpd, ">\n");
+               if (strlen(szComponents)) fprintf(mpd, "%s", szComponents);
 
                if (dash_ctx) {
                        Double seg_dur;
@@ -1191,34 +1505,43 @@ GF_Err gf_media_fragment_file(GF_ISOFile *input, char *output_file, Double max_d
                        }
                }
 
-               h = (u32) (max_segment_duration / 3600);
-               m = (u32) (max_segment_duration - h*60)/60;
-               s = max_segment_duration - h*3600 - m*60;
-               if (m) {
-                       fprintf(mpd, "   <SegmentInfo duration=\"PT%dM%.2fS\"", m, s);  
+               if (use_url_template) {
+                       sprintf(SegName, "%s$Number$.%s", seg_rad_name, seg_ext);
+                       fprintf(mpd, "    <SegmentTemplate timescale=\"1000\" duration=\"%d\" media=\"%s\" startNumber=\"1\"", (u32) (max_segment_duration*1000), SegName);     
+                       if (!sample_descs) fprintf(mpd, " initialization=\"%s.mp4\"", output_file);     
+                       fprintf(mpd, "/>\n");
+               } else if (single_segment_mode) {
+                       fprintf(mpd, "    <BaseURL>%s</BaseURL>\n", gf_isom_get_filename(output) );     
+                       fprintf(mpd, "    <SegmentBase indexRangeExact=\"true\" indexRange=\"%d-%d\"/>\n", index_start_range, index_end_range); 
                } else {
-                       fprintf(mpd, "   <SegmentInfo duration=\"PT%.2fS\"", s);        
+                       if (!seg_rad_name) {
+                               fprintf(mpd, "    <BaseURL>%s.mp4</BaseURL>\n", output_file );  
+                       }
+                       fprintf(mpd, "    <SegmentList timescale=\"1000\" duration=\"%d\">\n", (u32) (max_segment_duration*1000));      
+                       //if (!sample_descs) 
+                       {
+                               fprintf(mpd, "     <Initialization");   
+                               if (!seg_rad_name) {
+                                       fprintf(mpd, " range=\"0-"LLD"\"", init_seg_size-1);
+                               } else {
+                                       fprintf(mpd, " sourceURL=\"%s.mp4\"", output_file);
+                               }
+                               fprintf(mpd, "/>\n");
+                       }
                }
-               fprintf(mpd, ">\n");
 
-               fprintf(mpd, "    <InitialisationSegmentURL sourceURL=\"%s.mp4\"", output_file);        
-               if (!seg_rad_name) {
-                       fprintf(mpd, " range=\"0-"LLD"\"", init_seg_size);
-               }
-               fprintf(mpd, "/>\n");
 
-               gf_f64_seek(mpd_segs, 0, SEEK_END);
-               size = (u32) gf_f64_tell(mpd_segs);
                gf_f64_seek(mpd_segs, 0, SEEK_SET);
                while (!feof(mpd_segs)) {
                        u32 r = fread(buffer, 1, 100, mpd_segs);
-                       fwrite(buffer, 1, r, mpd);
+                       gf_fwrite(buffer, 1, r, mpd);
                }
 
-               fprintf(mpd, "   </SegmentInfo>\n");
-        fprintf(mpd, "  </Representation>\n");
-        fprintf(mpd, " </Period>\n");
-        fprintf(mpd, "</MPD>");
+               if (!use_url_template && !single_segment_mode) {
+                       fprintf(mpd, "    </SegmentList>\n");
+               }
+
+               fprintf(mpd, "   </Representation>\n");
        }
 
        /*store context*/
@@ -1259,12 +1582,62 @@ err_exit:
        return e;
 }
 
+
+GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, char *init_segment, Double period_duration)
+{
+       u32 h, m;
+       Double s;
+       FILE *mpd = fopen(mpd_name, "wt");
+       if (!mpd) return GF_IO_ERR;
+
+       h = (u32) (period_duration/3600);
+       m = (u32) (period_duration-h*60)/60;
+       s = period_duration - h*3600 - m*60;
+
+       /*TODO what should we put for minBufferTime */
+       fprintf(mpd, "<MPD type=\"static\" xmlns=\"urn:mpeg:DASH:schema:MPD:2011\" profiles=\"%s\" minBufferTime=\"PT1.5S\" mediaPresentationDuration=\"PT%dH%dM%.2fS\">\n", 
+               single_segment ? "urn:mpeg:dash:profile:isoff-on-demand:2011" : "urn:mpeg:dash:profile:full:2011",
+               h, m, s);
+    fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
+       if (title)
+               fprintf(mpd, "  <Title>Media Presentation Description for file %s generated with GPAC </Title>\n", title);
+    fprintf(mpd, " </ProgramInformation>\n");
+    fprintf(mpd, " <Period start=\"PT0S\" duration=\"PT%dH%dM%.2fS\">\n", h, m, s);    
+       fprintf(mpd, "  <AdaptationSet>\n");
+
+       if (init_segment) {
+               if (use_url_template) {
+                       fprintf(mpd, "   <SegmentTemplate initialization=\"%s\"/>\n", init_segment);    
+               } else if (0 && !single_segment) {
+                       fprintf(mpd, "   <SegmentList>\n");     
+                       fprintf(mpd, "    <Initialization sourceURL=\"%s\"/>\n", init_segment); 
+                       fprintf(mpd, "   </SegmentList>\n");    
+               }
+       }
+
+       fclose(mpd);
+       return GF_OK;
+}
+
+GF_Err gf_media_mpd_end(char *mpd_name)
+{
+       FILE *mpd = fopen(mpd_name, "a+t");
+       if (!mpd_name) return GF_IO_ERR;
+
+    fprintf(mpd, "  </AdaptationSet>\n");
+    fprintf(mpd, " </Period>\n");
+    fprintf(mpd, "</MPD>");
+
+       fclose(mpd);
+       return GF_OK;
+}
+
 GF_EXPORT
 GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import_fps)
 {
        int readen=0;
        GF_Err e;
-       u32 state, unicode_type, offset;
+       u32 state, offset;
        u32 cur_chap;
        u64 ts;
        u32 i, h, m, s, ms, fr, fps;
@@ -1284,21 +1657,17 @@ GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import
                        e = GF_NOT_SUPPORTED;
                        goto err_exit;
                }
-               unicode_type = 2;
                offset = 2;
        } else if ((line[0]==(char)(0xFE)) && (line[1]==(char)(0xFF))) {
                if (!line[2] && !line[3]){
                        e = GF_NOT_SUPPORTED;
                        goto err_exit;
                }
-               unicode_type = 1;
                offset = 2;
        } else if ((line[0]==(char)(0xEF)) && (line[1]==(char)(0xBB)) && (line[2]==(char)(0xBF))) {
                /*we handle UTF8 as asci*/
-               unicode_type = 0;
                offset = 3;
        } else {
-               unicode_type = 0;
                offset = 0;
        }
        gf_f64_seek(f, offset, SEEK_SET);
index f60671e1bd9e19a700b49c14a75c14b4d7053dce..2c82391e0e3b6b98ed98649f41bef9ea67929a14 100644 (file)
@@ -1015,7 +1015,9 @@ static GFINLINE u64 gf_m2ts_get_pcr(GF_M2TS_Mux_Program *program)
 
 void gf_m2ts_stream_update_data_following(GF_M2TS_Mux_Stream *stream)
 {
+       Bool ignore_next=0;
        stream->next_payload_size = 0;
+       stream->next_pck_flags = 0;
        stream->copy_from_next_packets = 0;
        
        if (stream->program->mux->one_au_per_pes) return;
@@ -1050,6 +1052,24 @@ void gf_m2ts_stream_update_data_following(GF_M2TS_Mux_Stream *stream)
                        stream->next_pck_flags = stream->pck_first->flags;
                }
        }
+       /*consider we don't have the next AU if:
+       1- we are asked to start new PES at RAP, just consider we don't have the next AU*/
+       if (stream->start_pes_at_rap && (stream->next_pck_flags & GF_ESI_DATA_AU_RAP) ) {
+               ignore_next=1;
+               stream->program->force_pat_pmt_state = 1;
+       }
+       /*if we have a RAP about to start on a stream in this program, force all other streams to stop merging cuming data in their current PES*/
+       else if (stream->program->force_pat_pmt_state) {
+               ignore_next=1;
+       }
+
+       if (ignore_next) {
+               stream->next_payload_size = 0;
+               stream->next_pck_cts = 0;
+               stream->next_pck_dts = 0;
+               stream->next_pck_flags = 0;
+       } 
+
        if (stream->next_payload_size) {
                stream->next_payload_size += stream->reframe_overhead;
 
@@ -1060,36 +1080,80 @@ void gf_m2ts_stream_update_data_following(GF_M2TS_Mux_Stream *stream)
 
 Bool gf_m2ts_stream_compute_pes_length(GF_M2TS_Mux_Stream *stream, u32 payload_length)
 {
-       stream->copy_from_next_packets = 0;
-       stream->next_payload_size = 0;
-
-       gf_m2ts_stream_update_data_following(stream);
-               
        assert(stream->pes_data_remain==0);
        stream->pes_data_len = stream->curr_pck.data_len - stream->pck_offset;
 
-//     stream->next_payload_size = 0;
+       stream->copy_from_next_packets = 0;
        /*if we have next payload ready, compute transmitted size*/
        if (stream->next_payload_size) {
                u32 pck_size = stream->curr_pck.data_len - stream->pck_offset;
                u32 ts_bytes = payload_length;  
 
-               /*flushing end of previous PES, let's put the entire next AU in it*/
-               if (pck_size<=ts_bytes) {
+               /*finish this AU*/
+               while (ts_bytes < pck_size) {
+                       ts_bytes += 184;
+               }
+
+               /*current AU started in PES, don't start new AU - if enough data
+               still to be sent from current AU, don't send the complete AU
+               in order to avoid padding*/
+               if (stream->prevent_two_au_start_in_pes && !stream->pck_offset) {
+                       if (ts_bytes>184)
+                               ts_bytes -= 184;
+                       else
+                               ts_bytes = pck_size;
+               }
+               /*try to fit in part of the next AU*/
+               else if (stream->next_payload_size) {
+                       /*how much more TS packets do we need to send next AU ?*/
                        while (ts_bytes < pck_size + stream->next_payload_size) {
                                ts_bytes += 184;
                        }
-               } 
-               /*needs several TS packets to send the PES, don't attempt to stick in the entire next AU*/
-               else {
-                       while (ts_bytes < pck_size) {
-                               ts_bytes += 184;
+                       /*don't end next AU in next PES if we don't want to start 2 AUs in one PES*/
+                       if (stream->prevent_two_au_start_in_pes && (ts_bytes>pck_size + stream->next_payload_size)) {
+                               if (ts_bytes>184)
+                                       ts_bytes -= 184;
+                               else
+                                       ts_bytes = pck_size + stream->next_payload_size;
                        }
                }
+
                /*that's how much bytes we copy from the following AUs*/
-               stream->copy_from_next_packets = ts_bytes - pck_size;
+               if (ts_bytes >= pck_size) {
+                       stream->copy_from_next_packets = ts_bytes - pck_size;
+               } else {
+                       u32 skipped = pck_size-ts_bytes;
+                       if (stream->pes_data_len > skipped)
+                               stream->pes_data_len -= skipped;
+               }
+
+               if (stream->min_bytes_copy_from_next && stream->copy_from_next_packets) {
+                       /*if we don't have enough space in the PES to store begining of new AU, don't copy it and ask
+                       to recompute header (we might no longer have DTS/CTS signaled)*/
+                       if (stream->copy_from_next_packets < stream->min_bytes_copy_from_next) {
+                               stream->copy_from_next_packets = 0;
+                               stream->next_payload_size = 0;
+                               stream->next_pck_flags = 0;
+                               return 0;
+                       }
+                       /*if what will remain after copying next AU is less than the minimum safety copy only copy next AU and
+                       realign n+2 AU start with PES*/
+                       if ((stream->copy_from_next_packets > stream->next_payload_size)
+                               && (stream->copy_from_next_packets - stream->next_payload_size < stream->min_bytes_copy_from_next)
+                       ) {
+                               stream->copy_from_next_packets = stream->next_payload_size;
+                       }
+               }
+
+               if (stream->pck_offset && !stream->copy_from_next_packets && stream->next_payload_size) {
+                       stream->copy_from_next_packets = 0;
+                       stream->next_payload_size = 0;
+                       stream->next_pck_flags = 0;
+                       return 0;
+               }
 
                if (stream->ifce->caps & GF_ESI_STREAM_IS_OVER) {
+#if 0
                        while (stream->copy_from_next_packets > stream->next_payload_size) {
                                if (stream->copy_from_next_packets < 184) {
                                        stream->copy_from_next_packets = 0;
@@ -1097,8 +1161,11 @@ Bool gf_m2ts_stream_compute_pes_length(GF_M2TS_Mux_Stream *stream, u32 payload_l
                                }
                                stream->copy_from_next_packets -= 184;
                        }
+#endif
+                       stream->pes_data_len += stream->next_payload_size;
+               } else {
+                       stream->pes_data_len += stream->copy_from_next_packets;
                }
-               stream->pes_data_len += stream->copy_from_next_packets;
        }
        stream->pes_data_remain = stream->pes_data_len;
        return 1;
@@ -1110,14 +1177,16 @@ static u32 gf_m2ts_stream_get_pes_header_length(GF_M2TS_Mux_Stream *stream)
        u32 hdr_len, flags;
        flags = stream->pck_offset ? stream->next_pck_flags : stream->curr_pck.flags;
 
+       /*not done with the current pes*/
        if (stream->pes_data_remain) return 0;
-       /*not the AU start*/
-       if ( !(flags & GF_ESI_DATA_AU_START) ) 
-               return 0;
-
        hdr_len = 9;
-       if (flags & GF_ESI_DATA_HAS_CTS) hdr_len += 5;
-       if (flags & GF_ESI_DATA_HAS_DTS) hdr_len += 5;
+       /*signal timing only if AU start in the PES*/
+       if ( flags & GF_ESI_DATA_AU_START) {
+               if (flags & GF_ESI_DATA_HAS_CTS) hdr_len += 5;
+               if (flags & GF_ESI_DATA_HAS_DTS) hdr_len += 5;
+       } else {
+               hdr_len = hdr_len;
+       }
        return hdr_len;
 }
 
@@ -1136,6 +1205,11 @@ u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream,
                use_dts = (stream->next_pck_flags & GF_ESI_DATA_HAS_DTS) ? 1 : 0;
                dts = stream->next_pck_dts;
                cts = stream->next_pck_cts;
+       }
+       /*we already sent the begining of the AU*/
+       else if (stream->pck_offset) {
+               use_pts = use_dts = 0;
+               dts = cts = 0;
        } else {
                use_pts = (stream->curr_pck.flags & GF_ESI_DATA_HAS_CTS) ? 1 : 0;
                use_dts = (stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? 1 : 0;
@@ -1143,6 +1217,7 @@ u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream,
                cts = stream->curr_pck.cts;
        }
 
+       /*PES packet length: number of bytes in the PES packet following the last byte of the field "pes packet length"*/
        assert(stream->pes_data_len);
        pes_len = stream->pes_data_len + 3; // 3 = header size
        if (use_pts) pes_len += 5;
@@ -1198,35 +1273,60 @@ u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream,
 void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
 {
        GF_BitStream *bs;
-       Bool needs_pcr;
+       Bool needs_pcr, first_pass;
        u32 adaptation_field_control, payload_length, payload_to_copy, padding_length, hdr_len, pos, copy_next;
 
        assert(stream->pid);
        bs = gf_bs_new(packet, 188, GF_BITSTREAM_WRITE);
 
        hdr_len = gf_m2ts_stream_get_pes_header_length(stream);
-       
-       adaptation_field_control = GF_M2TS_ADAPTATION_NONE;
-       payload_length = 184 - hdr_len;
-       payload_to_copy = padding_length = 0;
-       needs_pcr = (hdr_len && stream->pcr_priority ) ? 1 : 0;
-
-       if (needs_pcr) {
-               /*AF headers + PCR*/
-               payload_length -= 8;
-               adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
-       }
-       
-       if (hdr_len) {
-               assert(!stream->pes_data_remain);
-               gf_m2ts_stream_compute_pes_length(stream, payload_length);
-               assert(stream->pes_data_remain==stream->pes_data_len);
+
+       /*we may need two pass in case we first compute hdr len and TS payload size by considering
+       we concatenate next au start in this PES but finally couldn't do it when computing PES len
+       and AU alignment constraint of the stream*/
+       first_pass = 1;
+       while (1) {
+               if (hdr_len) {
+                       if (first_pass)
+                               gf_m2ts_stream_update_data_following(stream);
+                       hdr_len = gf_m2ts_stream_get_pes_header_length(stream);
+               }
+               
+               adaptation_field_control = GF_M2TS_ADAPTATION_NONE;
+               payload_length = 184 - hdr_len;
+               payload_to_copy = padding_length = 0;
+               needs_pcr = (hdr_len && stream->pcr_priority ) ? 1 : 0;
+
+               /*if we forced inserting PAT/PMT before new RAP, also insert PCR here*/
+               if (stream->program->force_pat_pmt_state == 3) {
+                       if( stream == stream->program->pcr) {
+                               stream->program->force_pat_pmt_state = 0;
+                               needs_pcr = 1;
+                       }
+               }
+
+               if (needs_pcr) {
+                       /*AF headers + PCR*/
+                       payload_length -= 8;
+                       adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
+               }
+               
+               if (hdr_len) {
+                       assert(!stream->pes_data_remain);
+                       if (! gf_m2ts_stream_compute_pes_length(stream, payload_length)) {
+                               first_pass = 0;
+                               continue;
+                       }
+
+                       assert(stream->pes_data_remain==stream->pes_data_len);
+               }
+               break;
        }
 
        copy_next = stream->copy_from_next_packets;
        payload_to_copy = stream->curr_pck.data_len - stream->pck_offset;
        /*end of PES packet*/
-       if (payload_to_copy > stream->pes_data_remain) {
+       if (payload_to_copy >= stream->pes_data_remain) {
                payload_to_copy = stream->pes_data_remain;
                copy_next = 0;
        }
@@ -1252,7 +1352,8 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
                if (payload_length < payload_to_copy + copy_next) {
                        padding_length = 10;
                        payload_length -= padding_length;
-                       payload_to_copy = payload_length;
+                       if (payload_to_copy > payload_length)
+                               payload_to_copy = payload_length;
                } else {
                        padding_length = payload_length - payload_to_copy - copy_next; 
                        payload_length -= padding_length;
@@ -1293,6 +1394,10 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
                }
                is_rap = (hdr_len && (stream->curr_pck.flags & GF_ESI_DATA_AU_RAP) ) ? 1 : 0;
                gf_m2ts_add_adaptation(bs, stream->pid, needs_pcr, pcr, is_rap, padding_length);
+       
+               if (padding_length) 
+                       stream->program->mux->tot_pes_pad_bytes += padding_length;
+
        }
 
        if (hdr_len) gf_m2ts_stream_add_pes_header(bs, stream, payload_length);
@@ -1300,6 +1405,7 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
        pos = (u32) gf_bs_get_position(bs);
        gf_bs_del(bs);
 
+       assert(stream->curr_pck.data_len - stream->pck_offset >= payload_to_copy);
        memcpy(packet+pos, stream->curr_pck.data + stream->pck_offset, payload_to_copy);
        stream->pck_offset += payload_to_copy;
        assert(stream->pes_data_remain >= payload_to_copy);
@@ -1313,12 +1419,12 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
                if (stream->discard_data) gf_free(stream->curr_pck.data);
                stream->curr_pck.data = NULL;
                stream->curr_pck.data_len = 0;
+               stream->pck_offset = 0;
 
                GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Done sending PES (%d bytes) from PID %d at stream time %d:%d (DTS "LLD" - PCR "LLD")\n", stream->curr_pck.data_len, stream->pid, stream->time.sec, stream->time.nanosec, stream->curr_pck.dts, gf_m2ts_get_pcr(stream->program)/300));
 
 #ifndef GPAC_DISABLE_LOG
-               if ((gf_log_get_level() >= GF_LOG_INFO) 
-                       && (gf_log_get_tools() & GF_LOG_CONTAINER) 
+               if (gf_log_tool_level_on(GF_LOG_CONTAINER, GF_LOG_INFO)
                        && gf_m2ts_time_less(&stream->program->mux->time, &stream->time)
                ) {
                        s32 drift;
@@ -1342,7 +1448,17 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
                        while (1) {
                                u32 remain = 0;
                                Bool res = stream->process(stream->program->mux, stream);
-                               assert(res);
+                               if (!res) {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Not enough data to fill current PES (PID %d) - filling with 0xFF\n", stream->pid) );
+                                       memset(packet+pos, 0xFF, copy_next);
+                                       
+                                       if (stream->copy_from_next_packets > copy_next) {
+                                               stream->copy_from_next_packets -= copy_next;
+                                       } else {
+                                               stream->copy_from_next_packets = 0;
+                                       }
+                                       break;
+                               }
                                if (copy_next > stream->curr_pck.data_len) {
                                        remain = copy_next - stream->curr_pck.data_len;
                                        copy_next = stream->curr_pck.data_len;
@@ -1360,16 +1476,22 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet)
                                }
 
                                if (stream->pck_offset == stream->curr_pck.data_len) {
+                                       assert(!remain || (remain>=stream->min_bytes_copy_from_next));
                                        /*PES has been sent, discard internal buffer*/
                                        if (stream->discard_data) gf_free(stream->curr_pck.data);
                                        stream->curr_pck.data = NULL;
                                        stream->curr_pck.data_len = 0;
+                                       stream->pck_offset = 0;
                                }
                                if (!remain) break;
                                pos += copy_next;
                                copy_next = remain;
                        }
                }
+               else if (stream->program->force_pat_pmt_state==1) {
+                       stream->program->force_pat_pmt_state = 2;
+                       stream->program->mux->force_pat = 1;
+               }
        }
        stream->bytes_since_last_time += 188;
 }
@@ -1478,12 +1600,18 @@ GF_M2TS_Mux_Stream *gf_m2ts_program_stream_add(GF_M2TS_Mux_Program *program, str
        case GF_STREAM_VISUAL:
                /*just pick first valid stream_id in visual range*/
                stream->mpeg2_stream_id = 0xE0;
+               /*for video streams, prevent sending two frames start in one PES. This will
+               introduce more overhead at very low bitrates where such cases happen, but will ensure proper timing
+               of each frame*/
+               stream->prevent_two_au_start_in_pes = 1;
                switch (ifce->object_type_indication) {
                case GPAC_OTI_VIDEO_MPEG4_PART2:
                        stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG4;
                        break;
                case GPAC_OTI_VIDEO_AVC:
                        stream->mpeg2_stream_type = GF_M2TS_VIDEO_H264;
+                       /*make sure we send AU delim NALU in same PES as first VCL NAL: 6 bytes (AU delim) + 4 byte start code + first nal header*/
+                       stream->min_bytes_copy_from_next = 11;
                        break;
                case GPAC_OTI_VIDEO_MPEG1:
                        stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG1;
@@ -1600,7 +1728,7 @@ GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_num
        program->pmt->program = program;
        muxer->pat->table_needs_update = 1;
        program->pmt->process = gf_m2ts_stream_process_pmt;
-       program->pmt->refresh_rate_ms = pmt_refresh_rate;
+       program->pmt->refresh_rate_ms = pmt_refresh_rate ? pmt_refresh_rate : (u32) -1;
        return program;
 }
 
@@ -1611,7 +1739,7 @@ GF_M2TS_Mux *gf_m2ts_mux_new(u32 mux_rate, u32 pat_refresh_rate, Bool real_time)
        GF_SAFEALLOC(muxer, GF_M2TS_Mux);
        muxer->pat = gf_m2ts_stream_new(GF_M2TS_PID_PAT);
        muxer->pat->process = gf_m2ts_stream_process_pat;
-       muxer->pat->refresh_rate_ms = pat_refresh_rate;
+       muxer->pat->refresh_rate_ms = pat_refresh_rate ? pat_refresh_rate : (u32) -1;
        muxer->real_time = real_time;
        muxer->bit_rate = mux_rate;
        muxer->init_pcr_value = 0;
@@ -1816,9 +1944,10 @@ const char *gf_m2ts_mux_process(GF_M2TS_Mux *muxer, u32 *status)
 
        /*PAT*/
        res = muxer->pat->process(muxer, muxer->pat);
-       if (res && gf_m2ts_time_less_or_equal(&muxer->pat->time, &time) ) {
+       if ((res && gf_m2ts_time_less_or_equal(&muxer->pat->time, &time)) || muxer->force_pat) {
                time = muxer->pat->time;
                stream_to_process = muxer->pat;
+               muxer->force_pat = 0;
                /*force sending the PAT regardless of other streams*/
                goto send_pck;
        }
@@ -1827,9 +1956,11 @@ const char *gf_m2ts_mux_process(GF_M2TS_Mux *muxer, u32 *status)
        program = muxer->programs;
        while (program) {
                res = program->pmt->process(muxer, program->pmt);
-               if (res && gf_m2ts_time_less_or_equal(&program->pmt->time, &time) ) {
+               if ((res && gf_m2ts_time_less_or_equal(&program->pmt->time, &time)) || (program->force_pat_pmt_state==2)) {
                        time = program->pmt->time;
                        stream_to_process = program->pmt;
+                       if (program->force_pat_pmt_state==2) 
+                               program->force_pat_pmt_state = 3;
                        /*force sending the PMT regardless of other streams*/
                        goto send_pck;
                }
@@ -1918,8 +2049,7 @@ send_pck:
                *status = GF_M2TS_STATE_DATA;
 
 #ifndef GPAC_DISABLE_LOG
-               if ((gf_log_get_level() >= GF_LOG_DEBUG) 
-                       && (gf_log_get_tools() & GF_LOG_CONTAINER) 
+               if (gf_log_tool_level_on(GF_LOG_CONTAINER, GF_LOG_DEBUG) 
                        && muxer->fixed_rate 
                ) {
                        s32 drift;
index 3916a464f79497810bb4d541f0a1f0ee1f1d251a..17ce1290780fe7dab20d3d7c6c939793a10a38a5 100644 (file)
@@ -30,7 +30,7 @@
 #include <stdio.h>
 #include <gpac/network.h>
 
-/*#define MYLOG(xx) GF_LOG( GF_LOG_INFO, GF_LOG_CONTAINER, xx )*/
+/*#define MYLOG(xx) GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, xx )*/
 //#define MYLOG(xx) printf xx
 #define MYLOG(xx)
 
@@ -128,13 +128,16 @@ gf_free(pl);
 return result;
 }*/
 
-PlaylistElement * playlist_element_new(PlaylistElementType elementType, const char * url, const char * title, const char *codecs, int durationInfo) {
+PlaylistElement * playlist_element_new(PlaylistElementType elementType, const char * url, const char * title, const char *codecs, int durationInfo, u64 byteRangeStart, u64 byteRangeEnd) {
        PlaylistElement * e = gf_malloc(sizeof(PlaylistElement));
        bzero(e, sizeof(PlaylistElement));
        assert( url );
        if (e == NULL)
                return NULL;
        e->durationInfo = durationInfo;
+       e->byteRangeStart = byteRangeStart;
+       e->byteRangeEnd = byteRangeEnd;
+
        e->title = (title ? gf_strdup(title) : NULL);
        e->codecs = (codecs ? gf_strdup(codecs) : NULL);
        assert( url);
@@ -320,6 +323,7 @@ typedef struct _s_accumulated_attributes {
        int currentMediaSequence;
        Bool isVariantPlaylist;
        Bool isPlaylistEnded;
+       u64 byteRangeStart, byteRangeEnd;
 } s_accumulated_attributes;
 
 static Bool safe_start_equals(const char * attribute, const char * line) {
@@ -336,6 +340,7 @@ static Bool safe_start_equals(const char * attribute, const char * line) {
 static char ** extractAttributes(const char * name, const char * line, const int numberOfAttributes) {
        int sz, i, currentAttribute, start;
        char ** ret;
+       u8 quote=0;
        int len = strlen(line);
        start = strlen(name);
        if (len <= start)
@@ -345,7 +350,7 @@ static char ** extractAttributes(const char * name, const char * line, const int
        ret = gf_calloc((numberOfAttributes + 1 ), sizeof(char*));
        currentAttribute = 0;
        for (i = start ; i <= len ; i++) {
-               if (line[i] == '\0' || line[i] == ',') {
+               if (line[i] == '\0' || (!quote && line[i] == ',')  || (line[i] == quote) ) {
                        u32 spaces = 0;
                        sz = 1 + i - start;
                        while (line[start+spaces] == ' ') spaces++;
@@ -357,6 +362,10 @@ static char ** extractAttributes(const char * name, const char * line, const int
                                return ret;
                        }
                }
+               if ((line[i] == '\'') || (line[i] == '"'))  {
+                       if (quote) quote = 0;
+                       else quote = line[i];
+               }
        }
        if (currentAttribute == 0) {
                gf_free(ret);
@@ -450,6 +459,22 @@ static char ** parseAttributes(const char * line, s_accumulated_attributes * att
                }
                return ret;
        }
+       ret = extractAttributes("#EXT-X-BYTERANGE:", line, 1);
+       if (ret) {
+               /* #EXT-X-BYTERANGE:<begin@end> */
+               if (ret[0]) {
+                       u64 begin, size;
+                       if (sscanf(ret[0], LLU"@"LLU, &size, &begin) == 2) {
+                               if (size) {
+                                       attributes->byteRangeStart = begin;
+                                       attributes->byteRangeEnd = begin + size - 1;
+                               } else {
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[M3U8] Invalid byte range %s\n", ret[0]));
+                               }
+                       }
+               }
+               return ret;
+       }
        return NULL;
 }
 
@@ -462,7 +487,7 @@ GF_Err parse_root_playlist(const char * file, VariantPlaylist ** playlist, const
 
 GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const char * baseURL, Program * in_program, PlaylistElement *sub_playlist)
 {
-       int readen, readPointer, len, i, currentLineNumber;
+       int len, i, currentLineNumber;
        FILE * f;
        VariantPlaylist * pl;
        char currentLine[M3U8_BUF_SIZE];
@@ -470,7 +495,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
        s_accumulated_attributes attribs;
        f = gf_f64_open(file, "rt");
        if (!f) {
-               GF_LOG( GF_LOG_ERROR, GF_LOG_CONTAINER,("[M3U8] Cannot Open m3u8 file %s for reading\n", file));
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[M3U8] Cannot Open m3u8 file %s for reading\n", file));
                return GF_SERVICE_ERROR;
        }
        if (*playlist == NULL) {
@@ -481,8 +506,6 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                }
        }
        pl = *playlist;
-       readen=0;
-       readPointer = 0;
        currentLineNumber = 0;
        bzero(&attribs, sizeof(s_accumulated_attributes));
        attribs.bandwidth = 0;
@@ -509,7 +532,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                        if (len < 7 || strncmp("#EXTM3U", currentLine, 7)!=0) {
                                fclose(f);
                                variant_playlist_del(pl);
-                               GF_LOG( GF_LOG_ERROR, GF_LOG_CONTAINER, ("Failed to parse M3U8 File, it should start with #EXTM3U, but was : %s\n", currentLine));
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Failed to parse M3U8 File, it should start with #EXTM3U, but was : %s\n", currentLine));
                                return GF_STREAM_NOT_FOUND;
                        }
                        continue;
@@ -609,7 +632,8 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                fullURL,
                                                attribs.title,
                                                attribs.codecs,
-                                               attribs.durationInSeconds);
+                                               attribs.durationInSeconds,
+                                               attribs.byteRangeStart, attribs.byteRangeEnd);
                                        if (currentPlayList == NULL) {
                                                /* OUT of memory */
                                                variant_playlist_del(*playlist);
@@ -634,7 +658,8 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        baseURL,
                                                        attribs.title,
                                                        attribs.codecs,
-                                                       attribs.durationInSeconds);
+                                                       attribs.durationInSeconds, 
+                                                       attribs.byteRangeStart, attribs.byteRangeEnd);
                                                if (currentPlayList == NULL) {
                                                        /* OUT of memory */
                                                        variant_playlist_del(*playlist);
@@ -652,7 +677,8 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        fullURL,
                                                        attribs.title,
                                                        attribs.codecs,
-                                                       attribs.durationInSeconds);
+                                                       attribs.durationInSeconds,
+                                                       attribs.byteRangeStart, attribs.byteRangeEnd);
                                                if (subElement == NULL) {
                                                        variant_playlist_del(*playlist);
                                                        playlist_element_del(currentPlayList);
@@ -662,6 +688,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                }
                                                gf_list_add(currentPlayList->element.playlist.elements, subElement);
                                                gf_list_add(program->bitrates, currentPlayList);
+                                               currentPlayList->element.playlist.computed_duration += subElement->durationInfo; 
                                                assert( program );
                                                assert( program->bitrates);
                                                assert( currentPlayList);
@@ -672,7 +699,8 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        fullURL,
                                                        attribs.title,
                                                        attribs.codecs,
-                                                       attribs.durationInSeconds);
+                                                       attribs.durationInSeconds,
+                                                       attribs.byteRangeStart, attribs.byteRangeEnd);
                                                if (currentPlayList->elementType != TYPE_PLAYLIST) {
                                                        currentPlayList->elementType = TYPE_PLAYLIST;
                                                        if (!currentPlayList->element.playlist.elements)
@@ -686,6 +714,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        return GF_OUT_OF_MEM;
                                                }
                                                gf_list_add(currentPlayList->element.playlist.elements, subElement);
+                                               currentPlayList->element.playlist.computed_duration += subElement->durationInfo; 
                                        }
                                }
 
@@ -695,8 +724,13 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                        currentPlayList->element.playlist.target_duration = attribs.targetDurationInSeconds;
                                        currentPlayList->durationInfo = attribs.targetDurationInSeconds;
                                }
-                               if (attribs.durationInSeconds) {
-                                       currentPlayList->durationInfo = attribs.durationInSeconds;
+                               if (attribs.durationInSeconds) {                                        
+                                       if (currentPlayList->durationInfo == 0) {
+                                               /* we set the playlist duration info as the duration of a segment, only if it's not set
+                                                  There are cases of playlist with the last segment with a duration different from the others 
+                                                  (example: Apple bipbop test)*/                                 
+                                               currentPlayList->durationInfo = attribs.durationInSeconds;
+                                       }
                                }
                                currentPlayList->element.playlist.mediaSequenceMin = attribs.minMediaSequence;
                                currentPlayList->element.playlist.mediaSequenceMax = attribs.currentMediaSequence++;
@@ -723,5 +757,18 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                }
        }
        fclose(f);
+
+       for (i=0; i < (int) gf_list_count(pl->programs); i++) {
+               u32 j;
+               Program *prog = gf_list_get(pl->programs, i);
+               prog->computed_duration = 0;
+               for (j=0; j<gf_list_count(prog->bitrates); j++) {
+                       PlaylistElement *ple = gf_list_get(prog->bitrates, j);
+                       if (ple->elementType==TYPE_PLAYLIST) {
+                               if (ple->element.playlist.computed_duration > prog->computed_duration) 
+                                       prog->computed_duration = ple->element.playlist.computed_duration;
+                       }
+               }
+       }
        return GF_OK;
 }
index c907da873bf6b2e0df93f614a4c99abad3e08087..f1374a0bf93f7c344e944cbbc49394bb9a98585b 100644 (file)
@@ -41,7 +41,7 @@ static GF_Err gf_export_message(GF_MediaExporter *dumper, GF_Err e, char *format
        if (dumper->flags & GF_EXPORT_PROBE_ONLY) return e;
 
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_AUTHOR)) {
+       if (gf_log_tool_level_on(GF_LOG_AUTHOR, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                va_list args;
                char szMsg[1024];
                va_start(args, format);
@@ -89,8 +89,8 @@ static GF_Err gf_dump_to_ogg(GF_MediaExporter *dumper, char *szName, u32 track)
 
                if (op.b_o_s) {
                        ogg_stream_pageout(&os, &og);
-                       fwrite(og.header, 1, og.header_len, out);
-                       fwrite(og.body, 1, og.body_len, out);
+                       gf_fwrite(og.header, 1, og.header_len, out);
+                       gf_fwrite(og.body, 1, og.body_len, out);
                        op.b_o_s = 0;
 
                        if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_MEDIA_THEORA) {
@@ -116,8 +116,8 @@ static GF_Err gf_dump_to_ogg(GF_MediaExporter *dumper, char *szName, u32 track)
        gf_odf_desc_del((GF_Descriptor *)esd);
 
        while (ogg_stream_pageout(&os, &og)>0) {
-               fwrite(og.header, 1, og.header_len, out);
-               fwrite(og.body, 1, og.body_len, out);
+               gf_fwrite(og.header, 1, og.header_len, out);
+               gf_fwrite(og.body, 1, og.body_len, out);
        }
        
        op.granulepos = -1;
@@ -157,15 +157,15 @@ static GF_Err gf_dump_to_ogg(GF_MediaExporter *dumper, char *szName, u32 track)
                if (dumper->flags & GF_EXPORT_DO_ABORT) break;
 
                while (ogg_stream_pageout(&os, &og)>0) {
-                       fwrite(og.header, 1, og.header_len, out);
-                       fwrite(og.body, 1, og.body_len, out);
+                       gf_fwrite(og.header, 1, og.header_len, out);
+                       gf_fwrite(og.body, 1, og.body_len, out);
                }
        }
        if (samp) gf_isom_sample_del(&samp);
 
        while (ogg_stream_flush(&os, &og)>0) {
-               fwrite(og.header, 1, og.header_len, out);
-               fwrite(og.body, 1, og.body_len, out);
+               gf_fwrite(og.header, 1, og.header_len, out);
+               gf_fwrite(og.body, 1, og.body_len, out);
        }
     ogg_stream_clear(&os);
        fclose(out);
@@ -182,7 +182,10 @@ GF_Err gf_export_hint(GF_MediaExporter *dumper)
        FILE *out;
        u32 track, i, size, m_stype, sn, count;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        m_stype = gf_isom_get_media_subtype(dumper->file, track, 1);
 
        e = gf_isom_reset_hint_reader(dumper->file, track, dumper->sample_num ? dumper->sample_num : 1, 0, 0, 0);
@@ -204,7 +207,7 @@ GF_Err gf_export_hint(GF_MediaExporter *dumper)
                if (e) return gf_export_message(dumper, e, "Error fetching hint packet %d", i);
                sprintf(szName, "%s_pck_%04d.%s", dumper->out_name, i, gf_4cc_to_str(m_stype));
                out = gf_f64_open(szName, "wb");
-               fwrite(pck, size, 1, out);
+               gf_fwrite(pck, size, 1, out);
                fclose(out);
                gf_free(pck);
                i++;
@@ -243,7 +246,10 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper)
        GF_BitStream *bs;
        u32 track, i, di, count, m_type, m_stype, dsi_size, is_mj2k;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        m_type = gf_isom_get_media_type(dumper->file, track);
        m_stype = gf_isom_get_media_subtype(dumper->file, track, 1);
        dsi_size = 0;
@@ -382,7 +388,7 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper)
                        gf_export_message(dumper, GF_OK, "Extracting \'%s\' Track (type '%s') - Compressor %s sample%s", szEXT, gf_4cc_to_str(m_type), udesc ? udesc->compressor_name : "Unknown", szNum);
                        break;
                }
-               if (udesc->extension_buf) gf_free(udesc->extension_buf);
+               if (udesc && udesc->extension_buf) gf_free(udesc->extension_buf);
                if (udesc) gf_free(udesc);
        }
        if (dumper->flags & GF_EXPORT_PROBE_ONLY) return GF_OK;
@@ -566,7 +572,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
        GF_GenericSampleDescription *udesc;
        char szName[1000], szEXT[5], GUID[16];
        FILE *out;
-       u32 *qcp_rates;
+       unsigned int *qcp_rates, rt_cnt;        /*contains constants*/
        GF_AVCConfig *avccfg;
        GF_M4ADecSpecInfo a_cfg;
        GF_BitStream *bs;
@@ -575,12 +581,16 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
        u32 aac_type, is_aac;
        char *dsi;
        QCPRateTable rtable[8];
-       u32 rt_cnt;
 
        dsi_size = 0;
        dsi = NULL;
        avccfg = NULL;
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
+
        m_type = gf_isom_get_media_type(dumper->file, track);
        m_stype = gf_isom_get_media_subtype(dumper->file, track, 1);
        has_qcp_pad = 0;
@@ -869,10 +879,10 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                }
 
                if (qcp_type==1) {
-                       qcp_rates = (u32 *)GF_QCELP_RATE_TO_SIZE;
+                       qcp_rates = (unsigned int*)GF_QCELP_RATE_TO_SIZE;
                        rt_cnt = GF_QCELP_RATE_TO_SIZE_NB;
                } else {
-                       qcp_rates = (u32 *)GF_SMV_EVRC_RATE_TO_SIZE;
+                       qcp_rates = (unsigned int*)GF_SMV_EVRC_RATE_TO_SIZE;
                        rt_cnt = GF_SMV_EVRC_RATE_TO_SIZE_NB;
                }
 
@@ -961,7 +971,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                        while (remain) {
                                nal_size = 0;
                                if (remain<avccfg->nal_unit_size){
-                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Corrupted NAL Unit: header size %d - bytes left %d\n", avccfg->nal_unit_size, remain) );
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Sample %d (size %d): Corrupted NAL Unit: header size %d - bytes left %d\n", i+1, samp->dataLength, avccfg->nal_unit_size, remain) );
                                        break;
                                }
                                for (j=0; j<avccfg->nal_unit_size; j++) {
@@ -972,7 +982,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                                }
                                gf_bs_write_u32(bs, 1);
                                if (remain < nal_size) {
-                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Corrupted NAL Unit: size %d - bytes left %d\n", nal_size, remain) );
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Sample %d (size %d): Corrupted NAL Unit: size %d - bytes left %d\n", i+1, samp->dataLength, nal_size, remain) );
                                        nal_size = remain;
                                }
                                gf_bs_write_data(bs, ptr, nal_size);
@@ -1073,7 +1083,7 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper)
                                max_size = size;
                        }
                        AVI_read_frame(in, frame, (int*)&key);
-                       if ((u32) size>4) fwrite(frame, 1, size, fout);
+                       if ((u32) size>4) gf_fwrite(frame, 1, size, fout);
                        gf_set_progress("AVI Extract", i+1, num_samples);
                }
                gf_free(frame);
@@ -1119,7 +1129,7 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper)
                size = AVI_read_audio(in, frame, max_size, (int*)&continuous);
                if (!size) break;
                num_samples += size;
-               fwrite(frame, 1, size, fout);
+               gf_fwrite(frame, 1, size, fout);
                gf_set_progress("AVI Extract", num_samples, tot_size);
 
        }
@@ -1141,7 +1151,10 @@ GF_Err gf_media_export_nhnt(GF_MediaExporter *dumper)
        Bool has_b_frames;
        u32 track, i, di, count, pos;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        esd = gf_isom_get_esd(dumper->file, track, 1);
        if (!esd) return gf_export_message(dumper, GF_NON_COMPLIANT_BITSTREAM, "Invalid MPEG-4 stream in track ID %d", dumper->trackID);
 
@@ -1171,7 +1184,7 @@ GF_Err gf_media_export_nhnt(GF_MediaExporter *dumper)
        if (esd->decoderConfig->decoderSpecificInfo  && esd->decoderConfig->decoderSpecificInfo->data) {
                sprintf(szName, "%s.info", dumper->out_name);
                out_inf = gf_f64_open(szName, "wb");
-               if (out_inf) fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, out_inf);
+               if (out_inf) gf_fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, out_inf);
                fclose(out_inf);
        }
 
@@ -1204,7 +1217,7 @@ GF_Err gf_media_export_nhnt(GF_MediaExporter *dumper)
        for (i=0; i<count; i++) {
                GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di);
                if (!samp) break;
-               fwrite(samp->data, samp->dataLength, 1, out_med);
+               gf_fwrite(samp->data, samp->dataLength, 1, out_med);
                
                /*dump nhnt info*/
                gf_bs_write_u24(bs, samp->dataLength);
@@ -1402,7 +1415,10 @@ GF_Err gf_media_export_isom(GF_MediaExporter *dumper)
        u32 track;
        u8 mode;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        if (gf_isom_get_media_type(dumper->file, dumper->trackID)==GF_ISOM_MEDIA_OD) {
                return gf_export_message(dumper, GF_BAD_PARAM, "Cannot extract OD track, result is  meaningless");
        }
@@ -1465,7 +1481,10 @@ GF_Err gf_media_export_avi(GF_MediaExporter *dumper)
        GF_M4VDecSpecInfo dsi;
        Double FPS;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        esd = gf_isom_get_esd(dumper->file, track, 1);
        if (!esd) return gf_export_message(dumper, GF_NON_COMPLIANT_BITSTREAM, "Invalid MPEG-4 stream in track ID %d", dumper->trackID);
 
@@ -1575,9 +1594,12 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
        u32 w, h;
        Bool uncompress;
        u32 track, i, di, count, pos, mstype;
-       const char *szRootName, *szSampleName;
+       const char *szRootName;
 
-       track = gf_isom_get_track_by_id(dumper->file, dumper->trackID);
+       if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
+               return GF_BAD_PARAM;
+       }
        if (!track) return gf_export_message(dumper, GF_BAD_PARAM, "Invalid track ID %d", dumper->trackID);
 
        if (dumper->flags & GF_EXPORT_PROBE_ONLY) {
@@ -1590,7 +1612,6 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
        if (dims_doc) {
                sprintf(szName, "%s.dml", dumper->out_name);
                szRootName = "DIMSStream";
-               szSampleName = "DIMSUnit";
        } else {
                sprintf(szMedia, "%s.media", dumper->out_name);
                med = gf_f64_open(szMedia, "wb");
@@ -1601,7 +1622,6 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
 
                sprintf(szName, "%s.nhml", dumper->out_name);
                szRootName = "NHNTStream";
-               szSampleName = "NHNTSample";
        }
        nhml = gf_f64_open(szName, "wt");
        if (!nhml) {
@@ -1620,7 +1640,7 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                if (esd->decoderConfig->decoderSpecificInfo  && esd->decoderConfig->decoderSpecificInfo->data) {
                        sprintf(szName, "%s.info", dumper->out_name);
                        inf = gf_f64_open(szName, "wb");
-                       if (inf) fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, inf);
+                       if (inf) gf_fwrite(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, 1, inf);
                        fclose(inf);
                        fprintf(nhml, "specificInfoFile=\"%s\" ", szName);
                }
@@ -1653,7 +1673,7 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                        if (sdesc->extension_buf) {
                                sprintf(szName, "%s.info", dumper->out_name);
                                inf = gf_f64_open(szName, "wb");
-                               if (inf) fwrite(sdesc->extension_buf, sdesc->extension_buf_size, 1, inf);
+                               if (inf) gf_fwrite(sdesc->extension_buf, sdesc->extension_buf_size, 1, inf);
                                fclose(inf);
                                fprintf(nhml, "specificInfoFile=\"%s\" ", szName);
                                gf_free(sdesc->extension_buf);
@@ -1699,7 +1719,7 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                if (!samp) break;
 
                if (med)
-                       fwrite(samp->data, samp->dataLength, 1, med);
+                       gf_fwrite(samp->data, samp->dataLength, 1, med);
 
                if (dims_doc) {
                        GF_BitStream *bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
@@ -1754,7 +1774,7 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                                                inflateEnd(&d_stream);
                                        }
                                } else {
-                                       fwrite(samp->data+pos+3, size-1, 1, nhml);
+                                       gf_fwrite(samp->data+pos+3, size-1, 1, nhml);
                                }
                                fprintf(nhml, "</DIMSUnit>\n");
                                
@@ -1877,7 +1897,7 @@ GF_Err gf_media_export_saf(GF_MediaExporter *dumper)
                while (1) {
                        gf_saf_mux_for_time(mux, (u32) -1, 0, &data, &size);
                        if (!data) break;
-                       fwrite(data, size, 1, saf_f);
+                       gf_fwrite(data, size, 1, saf_f);
                        gf_free(data);
                }
                gf_set_progress("SAF Export", samp_done, tot_samp);
@@ -1885,7 +1905,7 @@ GF_Err gf_media_export_saf(GF_MediaExporter *dumper)
        }       
        gf_saf_mux_for_time(mux, (u32) -1, 1, &data, &size);
        if (data) {
-               fwrite(data, size, 1, saf_f);
+               gf_fwrite(data, size, 1, saf_f);
                gf_free(data);
        }
        fclose(saf_f);
@@ -1905,12 +1925,12 @@ void m2ts_export_dump(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
        if (evt_type == GF_M2TS_EVT_PES_PCK) {
                FILE *dst = (FILE*)ts->user;
                GF_M2TS_PES_PCK *pck = (GF_M2TS_PES_PCK *)par;
-               fwrite(pck->data, pck->data_len, 1, dst);
+               gf_fwrite(pck->data, pck->data_len, 1, dst);
        }
        else if (evt_type == GF_M2TS_EVT_SL_PCK) {
                FILE *dst = (FILE*)ts->user;
                GF_M2TS_SL_PCK *pck = (GF_M2TS_SL_PCK *)par;
-               fwrite(pck->data + 5, pck->data_len - 5, 1, dst);
+               gf_fwrite(pck->data + 5, pck->data_len - 5, 1, dst);
        }
 }
 
index b76406ed03a192871b4a01ec8e0653fc610abcbb..ca904df9d5c1e7f7995f079b4d175675aa610994 100644 (file)
@@ -41,7 +41,7 @@
 GF_Err gf_import_message(GF_MediaImporter *import, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_AUTHOR)) {
+       if (gf_log_tool_level_on(GF_LOG_AUTHOR, e ? GF_LOG_ERROR : GF_LOG_INFO)) {
                va_list args;
                char szMsg[1024];
                va_start(args, format);
@@ -301,8 +301,8 @@ GF_Err gf_import_mp3(GF_MediaImporter *import)
        u16 sr;
        u32 nb_chan;
        FILE *in;
-       u32 hdr, size, max_size, track, di, duration;
-       u64 done, tot_size, offset;
+       u32 hdr, size, max_size, track, di;
+       u64 done, tot_size, offset, duration;
        GF_ISOSample *samp;
 
        in = gf_f64_open(import->in_name, "rb");
@@ -371,7 +371,8 @@ GF_Err gf_import_mp3(GF_MediaImporter *import)
        samp = gf_isom_sample_new();
        samp->IsRAP = 1;
 
-       duration = import->duration*sr;
+       duration = import->duration;
+       duration *= sr;
        duration /= 1000;
 
        max_size = 0;
@@ -499,8 +500,8 @@ GF_Err gf_import_aac_adts(GF_MediaImporter *import)
        ADTSHeader hdr;
        GF_M4ADecSpecInfo acfg;
        FILE *in;
-       u64 offset, tot_size, done;
-       u32 max_size, track, di, duration, prof, i;
+       u64 offset, tot_size, done, duration;
+       u32 max_size, track, di, i;
        GF_ISOSample *samp;
 
        in = gf_f64_open(import->in_name, "rb");
@@ -630,7 +631,6 @@ GF_Err gf_import_aac_adts(GF_MediaImporter *import)
        if (0 && hdr.is_mp2) acfg.audioPL = 0xFE;
 
        gf_bs_align(dsi);
-       prof = hdr.profile;
 
        e = GF_OK;
        destroy_esd = 0;
@@ -687,7 +687,8 @@ GF_Err gf_import_aac_adts(GF_MediaImporter *import)
        if (e) goto exit;
        samp->DTS+=dts_inc;
 
-       duration = import->duration*sr;
+       duration = import->duration;
+       duration *= sr;
        duration /= 1000;
 
        tot_size = gf_bs_get_size(bs);
@@ -742,9 +743,9 @@ static GF_Err gf_import_cmp(GF_MediaImporter *import, Bool mpeg12)
        Double FPS;
        FILE *mdia;
        GF_ISOSample *samp;
-       Bool is_vfr, enable_vfr, erase_pl, has_cts_offset, is_packed, destroy_esd, do_vfr, forced_packed;
-       u32 nb_samp, i, timescale, max_size, track, di, PL, max_b, nbI, nbP, nbB, nbNotCoded, dts_inc, ref_frame, b_frames, duration;
-       u64 pos, tot_size, done_size, samp_offset;
+       Bool is_vfr, erase_pl, has_cts_offset, is_packed, destroy_esd, do_vfr, forced_packed;
+       u32 nb_samp, i, timescale, max_size, track, di, PL, max_b, nbI, nbP, nbB, nbNotCoded, dts_inc, ref_frame, b_frames;
+       u64 pos, tot_size, done_size, samp_offset, duration;
        GF_M4VDecSpecInfo dsi;
        GF_M4VParser *vparse;
        GF_BitStream *bs;
@@ -769,11 +770,11 @@ static GF_Err gf_import_cmp(GF_MediaImporter *import, Bool mpeg12)
        if (import->video_fps) FPS = (Double) import->video_fps;
        get_video_timing(FPS, &timescale, &dts_inc);
 
-       duration = (u32) (import->duration*FPS);
+       duration = (u64) (import->duration*FPS);
 
        is_packed = 0;
        nbNotCoded = nbI = nbP = nbB = max_b = 0;
-       enable_vfr = is_vfr = erase_pl = 0;
+       is_vfr = erase_pl = 0;
 
        if (import->flags & GF_IMPORT_PROBE_ONLY) {
                import->tk_info[0].track_num = 1;
@@ -1022,11 +1023,11 @@ static GF_Err gf_import_avi_video(GF_MediaImporter *import)
        u32 i, num_samples, timescale, track, di, PL, max_b, nb_f, ref_frame, b_frames;
        u64 samp_offset, size, max_size;
        u32 nbI, nbP, nbB, nbDummy, nbNotCoded, dts_inc, cur_samp;
-       Bool is_vfr, enable_vfr, erase_pl;
+       Bool is_vfr, erase_pl;
        GF_M4VDecSpecInfo dsi;
        GF_M4VParser *vparse;
        s32 key;
-       u32 duration;
+       u64 duration;
        Bool destroy_esd, is_packed, is_init, has_cts_offset;
        char *comp, *frame;
        avi_t *in;
@@ -1110,7 +1111,7 @@ static GF_Err gf_import_avi_video(GF_MediaImporter *import)
        FPS = AVI_frame_rate(in);
        if (import->video_fps) FPS = (Double) import->video_fps;
        get_video_timing(FPS, &timescale, &dts_inc);
-       duration = (u32) (import->duration*FPS);
+       duration = (u64) (import->duration*FPS);
 
        e = GF_OK;
        max_size = 0;
@@ -1124,7 +1125,6 @@ static GF_Err gf_import_avi_video(GF_MediaImporter *import)
 
        is_packed = 0;
        nbDummy = nbNotCoded = nbI = nbP = nbB = max_b = 0;
-       enable_vfr = 0;
        has_cts_offset = 0;
        cur_samp = b_frames = ref_frame = 0;
 
@@ -1378,7 +1378,8 @@ GF_Err gf_import_avi_audio(GF_MediaImporter *import)
 {
        GF_Err e;
        FILE *test;
-       u32 hdr, di, track, i, tot_size, duration;
+       u64 duration;
+       u32 hdr, di, track, i, tot_size;
        s64 offset;
        s32 size, max_size, done;
        u16 sampleRate;
@@ -1535,8 +1536,8 @@ exit:
 GF_Err gf_import_isomedia(GF_MediaImporter *import)
 {
        GF_Err e;
-       u64 offset, sampDTS;
-       u32 track, di, trackID, track_in, i, num_samples, mtype, stype, w, h, duration, sr, sbr_sr, ch, mstype;
+       u64 offset, sampDTS, duration;
+       u32 track, di, trackID, track_in, i, num_samples, mtype, stype, w, h, sr, sbr_sr, ch, mstype;
        s32 trans_x, trans_y;
        s16 layer;
        u8 bps;
@@ -1746,7 +1747,7 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
                break;
        }
 
-       duration = (u32) (((Double)import->duration * gf_isom_get_media_timescale(import->orig, track_in)) / 1000);
+       duration = (u64) (((Double)import->duration * gf_isom_get_media_timescale(import->orig, track_in)) / 1000);
 
        num_samples = gf_isom_get_sample_count(import->orig, track_in);
        for (i=0; i<num_samples; i++) {
@@ -1806,8 +1807,8 @@ GF_Err gf_import_mpeg_ps_video(GF_MediaImporter *import)
        Double FPS;
        char *buf;
        u8 ftype;
-       u32 track, di, streamID, mtype, w, h, ar, nb_streams, buf_len, frames, ref_frame, timescale, duration, dts_inc, last_pos;
-       u64 file_size;
+       u32 track, di, streamID, mtype, w, h, ar, nb_streams, buf_len, frames, ref_frame, timescale, dts_inc, last_pos;
+       u64 file_size, duration;
        Bool destroy_esd;
 
        if (import->flags & GF_IMPORT_USE_DATAREF)
@@ -1883,7 +1884,8 @@ GF_Err gf_import_mpeg_ps_video(GF_MediaImporter *import)
        if (import->video_fps) FPS = (Double) import->video_fps;
        get_video_timing(FPS, &timescale, &dts_inc);
 
-       duration = import->duration*timescale;
+       duration = import->duration;
+       duration *= timescale;
        duration /= 1000;
 
        destroy_esd = 0;
@@ -1963,8 +1965,8 @@ GF_Err gf_import_mpeg_ps_audio(GF_MediaImporter *import)
        GF_Err e;
        mpeg2ps_t *ps;
        char *buf;
-       u32 track, di, streamID, mtype, sr, nb_ch, nb_streams, buf_len, frames, hdr, duration, last_pos;
-       u64 file_size;
+       u32 track, di, streamID, mtype, sr, nb_ch, nb_streams, buf_len, frames, hdr, last_pos;
+       u64 file_size, duration;
        Bool destroy_esd;
        GF_ISOSample *samp;
 
@@ -2041,7 +2043,7 @@ GF_Err gf_import_mpeg_ps_audio(GF_MediaImporter *import)
        gf_import_message(import, GF_OK, "%s Audio import - sample rate %d - %d channel%s", (mtype==GPAC_OTI_AUDIO_MPEG1) ? "MPEG-1" : "MPEG-2", sr, nb_ch, (nb_ch>1) ? "s" : "");
 
 
-       duration = (u32) ((Double)import->duration/1000.0 * sr);
+       duration = (u64) ((Double)import->duration/1000.0 * sr);
 
        samp = gf_isom_sample_new();
        samp->IsRAP = 1;
@@ -2083,10 +2085,10 @@ GF_Err gf_import_nhnt(GF_MediaImporter *import)
 {
        GF_Err e;
        Bool destroy_esd, next_is_start;
-       u32 track, di, mtype, max_size, duration, count, w, h, sig;
+       u32 track, di, mtype, max_size, count, w, h, sig;
        GF_ISOSample *samp;
        s64 media_size, media_done;
-       u64 offset;
+       u64 offset, duration;
        GF_BitStream *bs;
        FILE *nhnt, *mdia, *info;
        char *ext, szName[1000], szMedia[1000], szNhnt[1000];
@@ -2234,7 +2236,7 @@ GF_Err gf_import_nhnt(GF_MediaImporter *import)
 
        gf_import_message(import, GF_OK, "NHNT import - Stream Type %s - ObjectTypeIndication 0x%02x", gf_odf_stream_type_name(import->esd->decoderConfig->streamType), import->esd->decoderConfig->objectTypeIndication);
 
-       duration = (u32) ( ((Double) import->duration)/ 1000 * import->esd->slConfig->timestampResolution);
+       duration = (u64) ( ((Double) import->duration)/ 1000 * import->esd->slConfig->timestampResolution);
 
        samp = gf_isom_sample_new();
        samp->data = (char*)gf_malloc(sizeof(char) * 1024);
@@ -2528,10 +2530,11 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc)
        GF_Err e;
        GF_DIMSDescription dims;
        Bool destroy_esd, inRootOD, do_compress, use_dict, is_dims;
-       u32 i, track, tkID, di, mtype, max_size, duration, count, streamType, oti, timescale, specInfoSize, dts_inc, par_den, par_num;
+       u32 i, track, tkID, di, mtype, max_size, count, streamType, oti, timescale, specInfoSize, dts_inc, par_den, par_num;
        GF_ISOSample *samp;
        GF_XMLAttribute *att;
        s64 media_size, media_done, offset;
+       u64 duration;
        FILE *nhml, *mdia, *info;
        char *dictionary;
        char *ext, szName[1000], szMedia[1000], szMediaTemp[1000], szInfo[1000], szXmlFrom[1000], szXmlTo[1000], *specInfo;
@@ -2803,7 +2806,7 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc)
                gf_isom_set_audio_info(import->dest, track, di, sdesc.samplerate, sdesc.nb_channels, (u8) sdesc.bits_per_sample);
        }
 
-       duration = (u32) ( ((Double) import->duration)/ 1000 * timescale);
+       duration = (u64) ( ((Double) import->duration)/ 1000 * timescale);
 
        samp = gf_isom_sample_new();
        samp->data = (char*)gf_malloc(sizeof(char) * 1024);
@@ -3029,12 +3032,12 @@ exit:
 GF_Err gf_import_amr_evrc_smv(GF_MediaImporter *import)
 {
        GF_Err e;
-       u32 track, trackID, di, max_size, duration, sample_rate, block_size, i, readen;
+       u32 track, trackID, di, sample_rate, block_size, i, readen;
        GF_ISOSample *samp;
        char magic[20], *msg;
        Bool delete_esd, update_gpp_cfg;
        u32 media_done, mtype, oti, nb_frames;
-       u64 offset, media_size;
+       u64 offset, media_size, duration;
        GF_3GPConfig gpp_cfg;
        FILE *mdia;
        msg = NULL;
@@ -3151,13 +3154,13 @@ GF_Err gf_import_amr_evrc_smv(GF_MediaImporter *import)
                if (e) goto exit;
        }
        gf_isom_set_audio_info(import->dest, track, di, sample_rate, 1, 16);
-       duration = import->duration * sample_rate;
+       duration = import->duration;
+       duration *= sample_rate;
        duration /= 1000;
 
        samp = gf_isom_sample_new();
        samp->data = (char*)gf_malloc(sizeof(char) * 200);
        samp->IsRAP = 1;
-       max_size = 200;
        offset = gf_f64_tell(mdia);
        gf_f64_seek(mdia, 0, SEEK_END);
        media_size = gf_f64_tell(mdia) - offset;
@@ -3178,9 +3181,9 @@ GF_Err gf_import_amr_evrc_smv(GF_MediaImporter *import)
                        /*update mode set (same mechanism for both AMR and AMR-WB*/
                        gpp_cfg.AMR_mode_set |= (1<<ft);
                        if (gpp_cfg.type==GF_ISOM_SUBTYPE_3GP_AMR_WB) {
-                               samp->dataLength = GF_AMR_WB_FRAME_SIZE[ft];
+                               samp->dataLength = (u32)GF_AMR_WB_FRAME_SIZE[ft];
                        } else {
-                               samp->dataLength = GF_AMR_FRAME_SIZE[ft];
+                               samp->dataLength = (u32)GF_AMR_FRAME_SIZE[ft];
                        }
                        samp->data[0] = toc;
                        break;
@@ -3189,7 +3192,7 @@ GF_Err gf_import_amr_evrc_smv(GF_MediaImporter *import)
                        for (i=0; i<GF_SMV_EVRC_RATE_TO_SIZE_NB; i++) {
                                if (GF_SMV_EVRC_RATE_TO_SIZE[2*i]==toc) {
                                        /*remove rate_type byte*/
-                                       samp->dataLength = GF_SMV_EVRC_RATE_TO_SIZE[2*i+1] - 1;
+                                       samp->dataLength = (u32)GF_SMV_EVRC_RATE_TO_SIZE[2*i+1] - 1;
                                        break;
                                }
                        }
@@ -3254,8 +3257,8 @@ static const char *QCP_SMV_GUID = "\x75\x2B\x7C\x8D\x97\xA7\x46\xED\x98\x5E\xD5\
 GF_Err gf_import_qcp(GF_MediaImporter *import)
 {
        GF_Err e;
-       u32 track, trackID, di, i, nb_pck, duration, riff_size, chunk_size, major, minor, version, avg_bps, pck_size, block_size, bps, samplerate, vrat_rate_flag, size_in_packets, nb_frames;
-       u64 max_size;
+       u32 track, trackID, di, i, nb_pck, riff_size, chunk_size, pck_size, block_size, bps, samplerate, vrat_rate_flag, size_in_packets, nb_frames;
+       u64 max_size, duration;
        GF_BitStream *bs;
        GF_ISOSample *samp;
        char magic[12], GUID[16], name[81], fmt[162];
@@ -3308,17 +3311,17 @@ GF_Err gf_import_qcp(GF_MediaImporter *import)
        }
        chunk_size = gf_bs_read_u32_le(bs);
        has_pad = (chunk_size%2) ? 1 : 0;
-       major = gf_bs_read_u8(bs);
-       minor = gf_bs_read_u8(bs);
+       /*major = */gf_bs_read_u8(bs);
+       /*minor = */gf_bs_read_u8(bs);
        chunk_size -= 2;
        /*codec info*/
        gf_bs_read_data(bs, GUID, 16);
-       version = gf_bs_read_u16_le(bs);
+       /*version = */gf_bs_read_u16_le(bs);
        chunk_size -= 18;
        gf_bs_read_data(bs, name, 80);
        name[80]=0;
        chunk_size -= 80;
-       avg_bps = gf_bs_read_u16_le(bs);
+       /*avg_bps = */gf_bs_read_u16_le(bs);
        pck_size = gf_bs_read_u16_le(bs);
        block_size = gf_bs_read_u16_le(bs);
        samplerate = gf_bs_read_u16_le(bs);
@@ -3417,7 +3420,8 @@ GF_Err gf_import_qcp(GF_MediaImporter *import)
        }
        gf_isom_set_audio_info(import->dest, track, di, samplerate, 1, (u8) bps);
 
-       duration = import->duration * samplerate;
+       duration = import->duration;
+       duration *= samplerate;
        duration /= 1000;
 
        samp = gf_isom_sample_new();
@@ -3571,8 +3575,8 @@ static void h263_get_pic_size(GF_BitStream *bs, u32 fmt, u32 *w, u32 *h)
 GF_Err gf_import_h263(GF_MediaImporter *import)
 {
        GF_Err e;
-       u32 track, trackID, di, max_size, timescale, duration, w, h, fmt, nb_samp, dts_inc;
-       u64 offset, media_size, media_done;
+       u32 track, trackID, di, max_size, timescale, w, h, fmt, nb_samp, dts_inc;
+       u64 offset, media_size, media_done, duration;
        GF_ISOSample *samp;
        char *samp_data;
        GF_3GPConfig gpp_cfg;
@@ -3648,7 +3652,7 @@ GF_Err gf_import_h263(GF_MediaImporter *import)
 
        samp = gf_isom_sample_new();
 
-       duration = (u32) ( ((Double)import->duration) * timescale / 1000.0);
+       duration = (u64) ( ((Double)import->duration) * timescale / 1000.0);
        media_size = gf_bs_get_size(bs);
        nb_samp = 0;
        media_done = 0;
@@ -3739,8 +3743,9 @@ GF_Err gf_media_avc_rewrite_samples(GF_ISOFile *file, u32 track, u32 prev_size,
 GF_Err gf_import_h264(GF_MediaImporter *import)
 {
        u64 nal_start, nal_end, total_size;
-       u32 nal_size, track, trackID, di, cur_samp, nb_i, nb_idr, nb_p, nb_b, nb_sp, nb_si, nb_sei, max_w, max_h, duration, max_total_delay;
-       s32 idx;
+       u32 nal_size, track, trackID, di, cur_samp, nb_i, nb_idr, nb_p, nb_b, nb_sp, nb_si, nb_sei, max_w, max_h, max_total_delay;
+       s32 idx, sei_recovery_frame_count;
+       u64 duration;
        u8 nal_type;
        GF_Err e;
        FILE *mdia;
@@ -3749,10 +3754,11 @@ GF_Err gf_import_h264(GF_MediaImporter *import)
        GF_AVCConfig *avccfg, *svccfg, *dstcfg;
        GF_BitStream *bs;
        GF_BitStream *sample_data;
-       Bool flush_sample, sample_is_rap, first_nal, slice_is_ref, has_cts_offset, detect_fps, is_paff, set_subsamples;
-       u32 ref_frame, pred_frame, timescale, copy_size, size_length, dts_inc;
+       Bool flush_sample, sample_is_rap, sample_has_islice, first_nal, slice_is_ref, has_cts_offset, detect_fps, is_paff, set_subsamples, slice_force_ref;
+       u32 ref_frame, timescale, copy_size, size_length, dts_inc;
        s32 last_poc, max_last_poc, max_last_b_poc, poc_diff, prev_last_poc, min_poc, poc_shift;
        Bool first_avc;
+       Bool use_opengop_gdr = 0;
        u32 last_svc_sps;
        u32 prev_nalu_prefix_size, res_prev_nalu_prefix;
        u8 priority_prev_nalu_prefix;
@@ -3787,6 +3793,7 @@ GF_Err gf_import_h264(GF_MediaImporter *import)
 
        poc_diff = 0;
 
+
 restart_import:
 
        memset(&avc, 0, sizeof(AVCState));
@@ -3798,7 +3805,8 @@ restart_import:
        buffer = (char*)gf_malloc(sizeof(char) * max_size);
        sample_data = NULL;
        first_avc = 1;
-       last_svc_sps = 0,
+       last_svc_sps = 0;
+       sei_recovery_frame_count = -1;
 
        bs = gf_bs_from_file(mdia, GF_BITSTREAM_READ);
        if (!AVC_IsStartCode(bs)) {
@@ -3833,16 +3841,17 @@ restart_import:
 
        sample_data = NULL;
        sample_is_rap = 0;
+       sample_has_islice = 0;
        cur_samp = 0;
        is_paff = 0;
        total_size = gf_bs_get_size(bs);
        nal_start = gf_bs_get_position(bs);
-       duration = (u32) ( ((Double)import->duration) * timescale / 1000.0);
+       duration = (u64) ( ((Double)import->duration) * timescale / 1000.0);
 
        nb_i = nb_idr = nb_p = nb_b = nb_sp = nb_si = nb_sei = 0;
        max_w = max_h = 0;
        first_nal = 1;
-       ref_frame = pred_frame = 0;
+       ref_frame = 0;
        last_poc = max_last_poc = max_last_b_poc = prev_last_poc = 0;
        max_total_delay = 0;
 
@@ -4047,7 +4056,9 @@ restart_import:
                                copy_size = nal_size;
                                switch (avc.s_info.slice_type) {
                                case GF_AVC_TYPE_P: case GF_AVC_TYPE2_P: nb_p++; break;
-                               case GF_AVC_TYPE_I: case GF_AVC_TYPE2_I: nb_i++; break;
+                               case GF_AVC_TYPE_I: case GF_AVC_TYPE2_I: nb_i++; 
+                                       sample_has_islice = 1;
+                                       break;
                                case GF_AVC_TYPE_B: case GF_AVC_TYPE2_B: nb_b++; break;
                                case GF_AVC_TYPE_SP: case GF_AVC_TYPE2_SP: nb_sp++; break;
                                case GF_AVC_TYPE_SI: case GF_AVC_TYPE2_SI: nb_si++; break;
@@ -4106,6 +4117,15 @@ restart_import:
                        GF_ISOSample *samp = gf_isom_sample_new();
                        samp->DTS = (u64)dts_inc*cur_samp;
                        samp->IsRAP = sample_is_rap;
+                       if (!sample_is_rap) {
+                               if (sample_has_islice && (import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) {
+                                       samp->IsRAP = 1;
+                                       if (!use_opengop_gdr) {
+                                               use_opengop_gdr = 1;
+                                               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[AVC Import] Forcing non-IDR samples with I slices to be marked as sync points - resulting file will not be ISO conformant\n"));
+                                       }
+                               }
+                       }
                        gf_bs_get_content(sample_data, &samp->data, &samp->dataLength);
                        gf_bs_del(sample_data);
                        sample_data = NULL;
@@ -4147,13 +4167,32 @@ restart_import:
                        e = gf_isom_add_sample(import->dest, track, di, samp);
                        if (e) goto exit;
 
-                       gf_isom_sample_del(&samp);
                        cur_samp++;
+
+                       /*write sampleGroups info*/
+                       if (!samp->IsRAP && (sei_recovery_frame_count>=0)) {
+                               /*generic GDR*/
+                               if (sei_recovery_frame_count) {
+                                       if (!use_opengop_gdr) use_opengop_gdr = 1;
+                                       e = gf_isom_set_sample_roll_group(import->dest, track, cur_samp, (s16) sei_recovery_frame_count);
+                               } 
+                               /*open-GOP*/
+                               else if (sample_has_islice) {
+                                       if (!use_opengop_gdr) use_opengop_gdr = 2;
+                                       e = gf_isom_set_sample_rap_group(import->dest, track, cur_samp, 0);
+                               }
+                               if (e) goto exit;
+                       }
+
+                       gf_isom_sample_del(&samp);
                        gf_set_progress("Importing AVC-H264", (u32) (nal_start/1024), (u32) (total_size/1024) );
                        first_nal = 1;
 
                        if (min_poc > last_poc)
                                min_poc = last_poc;
+
+                       sample_has_islice = 0;
+                       sei_recovery_frame_count = -1;
                }
 
                if (copy_size) {
@@ -4246,16 +4285,22 @@ restart_import:
                                if (!is_paff && avc.s_info.bottom_field_flag)
                                        is_paff = 1;
 
+                               slice_is_ref = (avc.s_info.nal_unit_type==GF_AVC_NALU_IDR_SLICE);
+                               if (slice_is_ref) nb_idr++;
+                               slice_force_ref = 0;
+
+                               /*we only indicate TRUE IDRs for sync samples (cf AVC file format spec).
+                               SEI recovery should be used to build sampleToGroup & RollRecovery tables*/
                                if (first_nal) {
                                        first_nal = 0;
-                                       /*we only indicate TRUE IDRs for sync samples (cf AVC file format spec).
-                                       SEI recovery should be used to build sampleToGroup & RollRecovery tables*/
-                                       avc.sei.recovery_point.valid = 0;
-
+                                       if (avc.sei.recovery_point.valid) {
+                                               sei_recovery_frame_count = avc.sei.recovery_point.frame_cnt;
+                                               avc.sei.recovery_point.valid = 0;
+                                               if ((import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) 
+                                                       slice_force_ref = 1;
+                                       }
                                        sample_is_rap = AVC_SliceIsIDR(&avc);
                                }
-                               slice_is_ref = (avc.s_info.nal_unit_type==GF_AVC_NALU_IDR_SLICE);
-                               if (slice_is_ref) nb_idr++;
 
                                if (avc.s_info.poc<poc_shift) {
                                        u32 j;
@@ -4279,13 +4324,19 @@ restart_import:
                                        }
                                        last_poc = avc.s_info.poc;
                                }
+
                                /*ref slice, reset poc*/
                                if (slice_is_ref) {
                                        ref_frame = cur_samp+1;
                                        max_last_poc = last_poc = max_last_b_poc = 0;
-                                       pred_frame = 0;
                                        poc_shift = 0;
                                }
+                               /*forced ref slice*/
+                               else if (slice_force_ref) {
+                                       ref_frame = cur_samp+1; 
+                                       /*adjust POC shift as sample will now be marked as sync, so wo must store poc as if IDR (eg POC=0) for our CTS offset computing to be correct*/
+                                       poc_shift = avc.s_info.poc;
+                               }
                                /*strictly less - this is a new P slice*/
                                else if (max_last_poc<last_poc) {
                                        max_last_b_poc = 0;
@@ -4349,6 +4400,9 @@ restart_import:
                GF_ISOSample *samp = gf_isom_sample_new();
                samp->DTS = (u64)dts_inc*cur_samp;
                samp->IsRAP = sample_is_rap;
+               if (!sample_is_rap && sample_has_islice && (import->flags & GF_IMPORT_FORCE_SYNC)) {
+                       samp->IsRAP = 1;
+               }
                /*we store the frame order (based on the POC) as the CTS offset and update the whole table at the end*/
                samp->CTS_Offset = last_poc - poc_shift;
                gf_bs_get_content(sample_data, &samp->data, &samp->dataLength);
@@ -4361,6 +4415,7 @@ restart_import:
                cur_samp++;
        }
 
+
        /*recompute all CTS offsets*/
        if (has_cts_offset) {
                u32 i, last_cts_samp;
@@ -4483,6 +4538,11 @@ restart_import:
                }
        }
 
+       if (use_opengop_gdr==2) {
+               gf_import_message(import, GF_OK, "OpenGOP detected - adjusting file brand");
+               gf_isom_modify_alternate_brand(import->dest, GF_4CC('i', 's', 'o', '6'), 1);
+       }
+
        /*rewrite ESD*/
        if (import->esd) {
                if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG);
@@ -4570,8 +4630,8 @@ GF_Err gf_import_ogg_video(GF_MediaImporter *import)
 {
        GF_Err e;
        ogg_sync_state oy;
-       u32 di, track, duration;
-       u64 tot_size, done;
+       u32 di, track;
+       u64 tot_size, done, duration;
        u32 w, h, fps_num, fps_den, keyframe_freq_force, theora_kgs, flag, dts_inc, timescale;
        Double FPS;
        Bool destroy_esd, go;
@@ -4761,7 +4821,7 @@ GF_Err gf_import_ogg_video(GF_MediaImporter *import)
                                                Double d = import->duration;
                                                d *= import->esd->slConfig->timestampResolution;
                                                d /= 1000;
-                                               duration = (u32) d;
+                                               duration = (u64) d;
                                        }
                                }
 
@@ -4822,8 +4882,8 @@ GF_Err gf_import_ogg_audio(GF_MediaImporter *import)
 
        GF_Err e;
        ogg_sync_state oy;
-       u32 di, track, duration;
-       u64 done, tot_size;
+       u32 di, track;
+       u64 done, tot_size, duration;
        s32 block_size;
        GF_ISOSample *samp;
        Bool destroy_esd, go;
@@ -4856,7 +4916,8 @@ GF_Err gf_import_ogg_audio(GF_MediaImporter *import)
        destroy_esd = 0;
        samp = gf_isom_sample_new();
        /*avoids gcc warnings*/
-       track = num_headers = duration = 0;
+       track = num_headers = 0;
+       duration = 0;
 
        ogg_sync_init(&oy);
 
@@ -4945,7 +5006,7 @@ GF_Err gf_import_ogg_audio(GF_MediaImporter *import)
                                                Double d = import->duration;
                                                d *= vp.sample_rate;
                                                d /= 1000;
-                                               duration = (u32) d;
+                                               duration = (u64) d;
                                        }
                                }
                                continue;
@@ -5253,6 +5314,9 @@ typedef struct
 #endif
        Bool force_next_au_start;
        Bool stream_setup;
+       u32 nb_video, nb_video_configured;
+       u32 nb_audio, nb_audio_configured;
+
 } GF_TSImport;
 
 #ifndef GPAC_DISABLE_MPEG2TS
@@ -5295,7 +5359,6 @@ static void m2ts_set_track_mpeg4_probe_info(GF_M2TS_ES *es, GF_ESD *esd,
                        tk_info->type = GF_ISOM_MEDIA_ESM;
                        break;
                }
-               if (es) tk_info->mpeg4_es_id = es->mpeg4_es_id;
        }
 }
 
@@ -5373,13 +5436,16 @@ static void m2ts_set_track_mpeg4_creation_info(GF_MediaImporter *import, u32 *mt
 
 }
 
-static void m2ts_create_track(GF_TSImport *tsimp, u32 mtype, u32 stype, u32 oti, Bool is_in_iod)
+static void m2ts_create_track(GF_TSImport *tsimp, u32 mtype, u32 stype, u32 oti, u32 mpeg4_es_id, Bool is_in_iod)
 {
        GF_MediaImporter *import= (GF_MediaImporter *)tsimp->import;
        if (mtype != GF_ISOM_MEDIA_ESM) {
                u32 di;
                Bool destroy_esd = 0;
-               tsimp->track = gf_isom_new_track(import->dest, (import->esd?import->esd->ESID:import->trackID), mtype, 90000);
+               if (import->esd) mpeg4_es_id = import->esd->ESID;
+               else if (!mpeg4_es_id) mpeg4_es_id = import->trackID;
+
+               tsimp->track = gf_isom_new_track(import->dest, mpeg4_es_id, mtype, 90000);
                if (!tsimp->track) {
                        tsimp->track = gf_isom_new_track(import->dest, 0, mtype, 90000);
                        if (!tsimp->track) {
@@ -5412,6 +5478,43 @@ static void m2ts_create_track(GF_TSImport *tsimp, u32 mtype, u32 stype, u32 oti,
        }
 }
 
+/*rewrite last AVC sample currently stored in Annex-B format to ISO format (rewrite start code)*/
+void m2ts_rewrite_avc_sample(GF_MediaImporter *import, GF_TSImport *tsimp)
+{
+       GF_Err e;
+       u32 sc_pos, start;
+       char *data;
+       GF_BitStream *bs;
+       GF_ISOSample *samp;
+       u32 count = gf_isom_get_sample_count(import->dest, tsimp->track);
+       if (!count || !tsimp->avccfg) return;
+
+       samp = gf_isom_get_sample(import->dest, tsimp->track, count, NULL);
+       sc_pos = 1;
+       start = 0;
+       bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_WRITE);
+       data = samp->data;
+       while (1) {
+               if (!samp->data[start+sc_pos] && !samp->data[start+sc_pos+1] && !samp->data[start+sc_pos+2] && (samp->data[start+sc_pos+3]==1)) {
+                       gf_bs_seek(bs, start);
+                       gf_bs_write_u32(bs, (u32) sc_pos-start-4);
+                       start = sc_pos;
+               }
+               sc_pos++;
+               if (start+sc_pos>=samp->dataLength) break;
+       }
+       gf_bs_seek(bs, start);
+       gf_bs_write_u32(bs, samp->dataLength-start-4);
+       
+       gf_bs_del(bs);
+       
+       e = gf_isom_update_sample(import->dest, tsimp->track, count, samp, 1);
+       if (e) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error rewriting AVC NALUs: %s\n", gf_error_to_string(e) ));
+       }
+       gf_isom_sample_del(&samp);
+}
+
 void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
 {
        GF_Err e;
@@ -5423,7 +5526,6 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
        GF_MediaImporter *import= (GF_MediaImporter *)tsimp->import;
        GF_M2TS_ES *es = NULL;
        GF_M2TS_PES *pes = NULL;
-       GF_M2TS_SECTION_ES *ses = NULL;
 
        switch (evt_type) {
        case GF_M2TS_EVT_PAT_FOUND:
@@ -5465,13 +5567,15 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
                                if (es->pid == prog->pmt_pid) continue;
                                if (es->flags & GF_M2TS_ES_IS_SECTION) {
-                                       ses = (GF_M2TS_SECTION_ES *)es;
+                                       //ses = (GF_M2TS_SECTION_ES *)es;
                                } else {
                                        pes = (GF_M2TS_PES *)es;
+                                       gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
                                }
                                idx = import->nb_tracks;
                                import->tk_info[idx].track_num = es->pid;
                                import->tk_info[idx].prog_num = prog->number;
+                               import->tk_info[idx].mpeg4_es_id = es->mpeg4_es_id;
 
                                switch (es->stream_type) {
                                case GF_M2TS_VIDEO_MPEG1:
@@ -5479,36 +5583,42 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_video++;
                                        break;
                                case GF_M2TS_VIDEO_MPEG2:
                                        import->tk_info[idx].media_type = GF_4CC('M','P','G','2');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_video++;
                                        break;
                                case GF_M2TS_VIDEO_MPEG4:
                                        import->tk_info[idx].media_type = GF_4CC('M','P','4','V');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_video++;
                                        break;
                                case GF_M2TS_VIDEO_H264:
                                        import->tk_info[idx].media_type = GF_4CC('H','2','6','4');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_video++;
                                        break;
                                case GF_M2TS_AUDIO_MPEG1:
                                        import->tk_info[idx].media_type = GF_4CC('M','P','G','1');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_audio++;
                                        break;
                                case GF_M2TS_AUDIO_MPEG2:
                                        import->tk_info[idx].media_type = GF_4CC('M','P','G','2');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_audio++;
                                        break;
                                case GF_M2TS_AUDIO_AAC:
                                case GF_M2TS_AUDIO_LATM_AAC:
@@ -5516,18 +5626,21 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_audio++;
                                        break;
                                case GF_M2TS_AUDIO_AC3:
                                        import->tk_info[idx].media_type = GF_4CC('D','A','C','3');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_audio++;
                                        break;
                                case GF_M2TS_AUDIO_EC3:
                                        import->tk_info[idx].media_type = GF_4CC('D','E','C','3');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
                                        import->tk_info[idx].lang = pes->lang;
                                        import->nb_tracks++;
+                                       tsimp->nb_audio++;
                                        break;
                                case GF_M2TS_SYSTEMS_MPEG4_PES:
                                case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
@@ -5564,7 +5677,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                if (es->pid == prog->pmt_pid) continue;
                                if (es->pid == import->trackID) found = 1;
                                if (es->flags & GF_M2TS_ES_IS_SECTION) {
-                                       ses = (GF_M2TS_SECTION_ES *)es;
+                                       //ses = (GF_M2TS_SECTION_ES *)es;
                                } else {
                                        pes = (GF_M2TS_PES *)es;
                                }
@@ -5588,7 +5701,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        es = ts->ess[import->trackID]; /* import->trackID == pid */
 
                        if (es->flags & GF_M2TS_ES_IS_SECTION) {
-                               ses = (GF_M2TS_SECTION_ES *)es;
+                               //ses = (GF_M2TS_SECTION_ES *)es;
                        } else {
                                pes = (GF_M2TS_PES *)es;
                                gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
@@ -5643,7 +5756,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                }
                                break;
                        }
-                       m2ts_create_track(tsimp, mtype, stype, oti, is_in_iod);
+                       m2ts_create_track(tsimp, mtype, stype, oti, es->mpeg4_es_id, is_in_iod);
                }
                break;
        case GF_M2TS_EVT_AAC_CFG:
@@ -5666,16 +5779,39 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                {
                        GF_M2TS_PES_PCK *pck = (GF_M2TS_PES_PCK *)par;
                        is_au_start = (pck->flags & GF_M2TS_PES_PCK_AU_START);
-
+                       
                        if (import->flags & GF_IMPORT_PROBE_ONLY) {
                                for (i=0; i<import->nb_tracks; i++) {
                                        if (import->tk_info[i].track_num == pck->stream->pid) {
-                                               if (pck->stream->aud_sr) {
+                                               if (pck->stream->aud_sr && ! import->tk_info[i].audio_info.sample_rate) {
+                                                       import->tk_info[i].audio_info.sample_rate = pck->stream->aud_sr;
+                                                       import->tk_info[i].audio_info.nb_channels = pck->stream->aud_nb_ch;
+                                                       if ((pck->stream->stream_type==GF_M2TS_AUDIO_AAC) || (pck->stream->stream_type==GF_M2TS_AUDIO_LATM_AAC)) {
+                                                               sprintf(import->tk_info[i].szCodecProfile, "mp4a.40.%02x", (u8) pck->stream->aud_obj_type);
+                                                       }
                                                        import->tk_info[i].audio_info.sample_rate = pck->stream->aud_sr;
                                                        import->tk_info[i].audio_info.nb_channels = pck->stream->aud_nb_ch;
+                                                       tsimp->nb_audio_configured++;
                                                } else {
-                                                       import->tk_info[i].video_info.width = pck->stream->vid_w;
-                                                       import->tk_info[i].video_info.height = pck->stream->vid_h;
+                                                       /*unpack AVC config*/
+                                                       if ((pck->stream->stream_type==GF_M2TS_VIDEO_H264) && !pck->data[0] && !pck->data[1]) {
+                                                               u32 nal_type = pck->data[4] & 0x1F;
+                                                               if (nal_type == GF_AVC_NALU_SEQ_PARAM) {
+                                                                       sprintf(import->tk_info[i].szCodecProfile, "avc1.%02x%02x%02x", (u8) pck->data[5], (u8) pck->data[6], (u8) pck->data[7]);
+                                                               }
+                                                       }
+                                                       if (pck->stream->vid_w && ! import->tk_info[i].video_info.width ) {
+                                                               import->tk_info[i].video_info.width = pck->stream->vid_w;
+                                                               import->tk_info[i].video_info.height = pck->stream->vid_h;
+                                                               tsimp->nb_video_configured++;
+                                                       }
+                                               }
+                                               /*consider we are done if not using 4 on 2*/
+                                               if (!ts->has_4on2 
+                                                       && (tsimp->nb_video_configured == tsimp->nb_video)
+                                                       && (tsimp->nb_audio_configured == tsimp->nb_audio)
+                                                       ) {
+                                                       import->flags |= GF_IMPORT_DO_ABORT;
                                                }
                                                break;
                                        }
@@ -5699,9 +5835,10 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        } 
                        if (pck->stream->pid != import->trackID) return;
 
-                       if (tsimp->avccfg) {
+                       /*avc data for the current sample is stored in annex-B, as we don't know the size of each nal
+                       when called back (depending on PES packetization, the end of the nal could be in following pes)*/
+                       if (tsimp->avccfg && !pck->data[0] && !pck->data[1]) {
                                GF_AVCConfigSlot *slc;
-                               GF_BitStream *bs;
                                s32 idx;
                                Bool add_sps, is_subseq = 0;
                                u32 nal_type = pck->data[4] & 0x1F;
@@ -5774,11 +5911,6 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        break;
                                }
 
-                               /*rewrite nalu header*/
-                               bs = gf_bs_new(pck->data, pck->data_len, GF_BITSTREAM_WRITE);
-                               gf_bs_write_u32(bs, pck->data_len - 4);
-                               gf_bs_del(bs);
-
                                if (tsimp->force_next_au_start) {
                                        is_au_start = 1;
                                        tsimp->force_next_au_start = 0;
@@ -5787,7 +5919,12 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        if (!is_au_start) {
                                e = gf_isom_append_sample_data(import->dest, tsimp->track, (char*)pck->data, pck->data_len);
                                if (e) {
-                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error appending sample data\n"));
+                                       if (!gf_isom_get_sample_count(import->dest, tsimp->track)) {
+                                               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] missed begining of sample data\n"));
+                                               e = GF_OK;
+                                       } else {
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error appending sample data\n"));
+                                       }
                                }
                                if (pck->flags & GF_M2TS_PES_PCK_I_FRAME) tsimp->nb_i++;
                                if (pck->flags & GF_M2TS_PES_PCK_P_FRAME) tsimp->nb_p++;
@@ -5838,9 +5975,16 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                samp->IsRAP = (pck->flags & GF_M2TS_PES_PCK_RAP) ? 1 : 0;
                                samp->data = pck->data;
                                samp->dataLength = pck->data_len;
-                               e = gf_isom_add_sample(import->dest, tsimp->track, 1, samp);
+
+                               if (samp->DTS && (samp->DTS==tsimp->last_dts)) {
+                                       e = gf_isom_append_sample_data(import->dest, tsimp->track, (char*)pck->data, pck->data_len);
+                               } else {
+
+                                       if (tsimp->avccfg) m2ts_rewrite_avc_sample(import, tsimp);
+                                       e = gf_isom_add_sample(import->dest, tsimp->track, 1, samp);
+                               }
                                if (e) {
-                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error adding sample: %s\n", gf_error_to_string(e)));
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d: Error adding sample: %s\n", pck->stream->pid, gf_error_to_string(e)));
                                        //import->flags |= GF_IMPORT_DO_ABORT;
                                        import->last_error = e;
                                }
@@ -5850,6 +5994,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                if (pck->flags & GF_M2TS_PES_PCK_I_FRAME) tsimp->nb_i++;
                                if (pck->flags & GF_M2TS_PES_PCK_P_FRAME) tsimp->nb_p++;
                                if (pck->flags & GF_M2TS_PES_PCK_B_FRAME) tsimp->nb_b++;
+                               tsimp->last_dts = samp->DTS;
                        } else {
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] negative time sample - skipping\n"));
                        }
@@ -5865,7 +6010,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                        if (!sl_pck->stream->program->pmt_iod) return;
 
                        if (sl_pck->stream->flags & GF_M2TS_ES_IS_SECTION) {
-                               ses = (GF_M2TS_SECTION_ES *)sl_pck->stream;
+                               //ses = (GF_M2TS_SECTION_ES *)sl_pck->stream;
                        } else {
                                pes = (GF_M2TS_PES *)sl_pck->stream;
                        }
@@ -5933,7 +6078,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                mtype = stype = oti = 0;
                                import->esd = gf_m2ts_get_esd(sl_pck->stream);
                                m2ts_set_track_mpeg4_creation_info(import, &mtype, &stype, &oti);
-                               m2ts_create_track(tsimp, mtype, stype, oti, 0);
+                               m2ts_create_track(tsimp, mtype, stype, oti, sl_pck->stream->mpeg4_es_id, 0);
                        }
 
                        if (import->esd) {
@@ -5949,11 +6094,21 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                } else {
                                        if (!(sl_pck->stream->flags & GF_M2TS_ES_FIRST_DTS)) {
                                                sl_pck->stream->flags |= GF_M2TS_ES_FIRST_DTS;
+
+                                               if (!hdr.compositionTimeStampFlag) {
+                                                       hdr.compositionTimeStamp = sl_pck->stream->program->first_dts;
+                                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d First SL Access unit start flag set without any composition time stamp - defaulting to last CTS seen on program\n", sl_pck->stream->pid));
+                                               } 
                                                sl_pck->stream->first_dts = (hdr.decodingTimeStamp?hdr.decodingTimeStamp:hdr.compositionTimeStamp);
                                                if (!sl_pck->stream->program->first_dts ||
                                                        sl_pck->stream->program->first_dts > sl_pck->stream->first_dts) {
                                                        sl_pck->stream->program->first_dts = sl_pck->stream->first_dts;
                                                }
+                                       } else {
+                                               if (!hdr.compositionTimeStampFlag) {
+                                                       hdr.compositionTimeStamp = sl_pck->stream->first_dts + tsimp->last_dts+1;
+                                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d SL Access unit start flag set without any composition time stamp - defaulting to last CTS seen on stream + 1\n", sl_pck->stream->pid));
+                                               } 
                                        }
 
                                        samp = gf_isom_sample_new();
@@ -5971,8 +6126,9 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                                samp->dataLength = sl_pck->data_len - hdr_len;
 
                                                e = gf_isom_add_sample(import->dest, tsimp->track, 1, samp);
+                                               /*if CTS was not specified, samples will simply be skipped*/
                                                if (e) {
-                                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error adding sample\n"));
+                                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d Error adding sample\n", sl_pck->stream->pid));
                                                }
                                                if (import->duration && (import->duration<=(samp->DTS+samp->CTS_Offset)/90)) {
                                                        //import->flags |= GF_IMPORT_DO_ABORT;
@@ -6074,32 +6230,37 @@ GF_Err gf_import_mpeg_ts(GF_MediaImporter *import)
                        gf_isom_avc_config_update(import->dest, tsimp.track, 1, tsimp.avccfg);
                        gf_isom_set_visual_info(import->dest, tsimp.track, 1, w, h);
                        gf_isom_set_track_layout_info(import->dest, tsimp.track, w<<16, h<<16, 0, 0, 0);
+
+
+                       m2ts_rewrite_avc_sample(import, &tsimp);
+
                        gf_odf_avc_cfg_del(tsimp.avccfg);
                }
 
 
+               if (tsimp.track) {
+                       MP4T_RecomputeBitRate(import->dest, tsimp.track);
+                       /* creation of the edit lists */
+                       if (es->first_dts != es->program->first_dts) {
+                               u32 media_ts, moov_ts, offset;
+                               u64 dur;
+                               media_ts = gf_isom_get_media_timescale(import->dest, tsimp.track);
+                               moov_ts = gf_isom_get_timescale(import->dest);
+                               assert(es->program->first_dts <= es->first_dts);
+                               offset = (u32)(es->first_dts - es->program->first_dts) * moov_ts / media_ts;
+                               dur = gf_isom_get_media_duration(import->dest, tsimp.track) * moov_ts / media_ts;
+                               gf_isom_set_edit_segment(import->dest, tsimp.track, 0, offset, 0, GF_ISOM_EDIT_EMPTY);
+                               gf_isom_set_edit_segment(import->dest, tsimp.track, offset, dur, 0, GF_ISOM_EDIT_NORMAL);
+                               gf_import_message(import, GF_OK, "Timeline offset: %d ms", offset);
+                       }
 
-               MP4T_RecomputeBitRate(import->dest, tsimp.track);
-               /* creation of the edit lists */
-               if (es->first_dts != es->program->first_dts) {
-                       u32 media_ts, moov_ts, offset;
-                       u64 dur;
-                       media_ts = gf_isom_get_media_timescale(import->dest, tsimp.track);
-                       moov_ts = gf_isom_get_timescale(import->dest);
-                       assert(es->program->first_dts < es->first_dts);
-                       offset = (u32)(es->first_dts - es->program->first_dts) * moov_ts / media_ts;
-                       dur = gf_isom_get_media_duration(import->dest, tsimp.track) * moov_ts / media_ts;
-                       gf_isom_set_edit_segment(import->dest, tsimp.track, 0, offset, 0, GF_ISOM_EDIT_EMPTY);
-                       gf_isom_set_edit_segment(import->dest, tsimp.track, offset, dur, 0, GF_ISOM_EDIT_NORMAL);
-                       gf_import_message(import, GF_OK, "Timeline offset: %d ms", offset);
-               }
+                       if (tsimp.nb_p) {
+                               gf_import_message(import, GF_OK, "Import results: %d VOPs (%d Is - %d Ps - %d Bs)", gf_isom_get_sample_count(import->dest, tsimp.track), tsimp.nb_i, tsimp.nb_p, tsimp.nb_b);
+                       }
 
-               if (tsimp.nb_p) {
-                       gf_import_message(import, GF_OK, "Import results: %d VOPs (%d Is - %d Ps - %d Bs)", gf_isom_get_sample_count(import->dest, tsimp.track), tsimp.nb_i, tsimp.nb_p, tsimp.nb_b);
+                       if (es->program->pmt_iod)
+                               gf_isom_set_brand_info(import->dest, GF_ISOM_BRAND_MP42, 1);
                }
-
-               if (es->program->pmt_iod)
-                       gf_isom_set_brand_info(import->dest, GF_ISOM_BRAND_MP42, 1);
        }
 
        gf_m2ts_demux_del(ts);
@@ -6111,7 +6272,7 @@ GF_Err gf_import_mpeg_ts(GF_MediaImporter *import)
 
 GF_Err gf_import_vobsub(GF_MediaImporter *import)
 {
-       static u8 null_subpic[] = { 0x00, 0x09, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0xFF };
+       static const u8 null_subpic[] = { 0x00, 0x09, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0xFF };
        char              filename[GF_MAX_PATH];
        FILE             *file = NULL;
        int               version;
@@ -6376,8 +6537,8 @@ GF_Err gf_import_ac3(GF_MediaImporter *import)
        u32 nb_chan;
        FILE *in;
        GF_BitStream *bs;
-       u32 max_size, track, di, duration;
-       u64 tot_size, done;
+       u32 max_size, track, di;
+       u64 tot_size, done, duration;
        GF_ISOSample *samp;
 
        in = gf_f64_open(import->in_name, "rb");
@@ -6450,7 +6611,8 @@ GF_Err gf_import_ac3(GF_MediaImporter *import)
        samp = gf_isom_sample_new();
        samp->IsRAP = 1;
 
-       duration = import->duration*sr;
+       duration = import->duration;
+       duration *= sr;
        duration /= 1000;
 
        max_size = 0;
@@ -6728,6 +6890,7 @@ GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level)
                if (level) slc->data[3] = level;
        }
        e = gf_isom_avc_config_update(file, track, 1, avcc);
+       assert (e == GF_OK);
        gf_odf_avc_cfg_del(avcc);
        return GF_OK;
 }
index 61abb0bda934cb3f1713b70edbfa2b1e422e2698..c9b36b094ff8db031c494a6b8118bf299266fd88 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *                      GPAC - Multimedia Framework C SDK
 *
-*                      Authors: Cyril Concolato
+*                      Authors: Cyril Concolato - Jean Le Feuvre
 *                      Copyright (c) Telecom ParisTech 2010-
 *                                      All rights reserved
 *
 #include <gpac/internal/m3u8.h>
 #include <gpac/network.h>
 
+
+static Bool gf_mpd_parse_bool(char *attr)
+{
+       if (!strcmp(attr, "true")) return 1;
+       return 0;
+}
+
+static char *gf_mpd_parse_string(char *attr)
+{
+       return gf_strdup(attr);
+}
+
+static char *gf_mpd_parse_text_content(GF_XMLNode *child)
+{
+       u32 child_index = 0;
+       while (1) {
+               child = gf_list_get(child->content, child_index);
+               if (!child) {
+                       break;
+               } else if (child->type == GF_XML_TEXT_TYPE) {
+                       return gf_mpd_parse_string(child->name);
+               }
+               child_index++;
+       }
+       return NULL;
+}
+
+static u32 gf_mpd_parse_int(char *attr)
+{
+       return atoi(attr);
+}
+
+static Double gf_mpd_parse_double(char *attr)
+{
+       return atof(attr);
+}
+
+static GF_MPD_Fractional *gf_mpd_parse_frac(char *attr)
+{
+       GF_MPD_Fractional *res;
+       GF_SAFEALLOC(res, GF_MPD_Fractional);
+       sscanf(attr, "%d:%d", &res->num, &res->den);
+       return res;
+}
+
+static u64 gf_mpd_parse_date(char *attr)
+{
+       fprintf(stdout, "error: mpd parse date not implemented\n");
+       return 0;
+}
+
 static u32 gf_mpd_parse_duration(char *duration) {
        u32 i;
        if (!duration) return 0;
@@ -76,373 +127,533 @@ static u32 gf_mpd_parse_duration(char *duration) {
        }
 }
 
-static GF_Err gf_mpd_parse_rep_cp(GF_XMLNode *root, GF_MPD_Representation *rep)
-{
-       u32 att_index;
-       GF_XMLAttribute *att;
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "SchemeInformation")) {
-                       rep->content_protection_type = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "schemeIdUri")) {
-                       rep->content_protection_uri = gf_strdup(att->value);
-               }
-               att_index++;
-       }
 
-       return GF_OK;
-}
 
-static GF_Err gf_mpd_parse_rep_trickmode(GF_XMLNode *root, GF_MPD_Representation *rep)
+static GF_MPD_ByteRange *gf_mpd_parse_byte_range(char *attr)
 {
-       u32 att_index;
-       GF_XMLAttribute *att;
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "alternatePlayoutRate")) {
-                       rep->alternatePlayoutRate = atof(att->value);
-               }
-               att_index++;
-       }
-
-       return GF_OK;
+       GF_MPD_ByteRange *br;
+       GF_SAFEALLOC(br, GF_MPD_ByteRange);
+       sscanf(attr, LLD"-"LLD, &br->start_range, &br->end_range);
+       return br;
 }
 
-static GF_Err gf_mpd_parse_rep_initseg(GF_XMLNode *root, GF_MPD_Representation *rep, const char * baseURL)
+static GF_Err gf_mpd_parse_location(GF_MPD *mpd, GF_XMLNode *child)
 {
-       u32 att_index;
-       GF_XMLAttribute *att;
-
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "sourceURL")) {
-                       GF_URL_Info info;
-                       GF_Err e;
-                       gf_dm_url_info_init(&info);
-                       e = gf_dm_get_url_info(att->value, &info, baseURL);
-                       assert( e == GF_OK );
-                       assert( info.canonicalRepresentation);
-                       rep->init_url = gf_strdup(info.canonicalRepresentation);
-                       gf_dm_url_info_del(&info);
-               } else if (!strcmp(att->name, "range")) {
-                       rep->init_use_range = 1;
-                       sscanf(att->value, "%d-%d", &rep->init_byterange_start, &rep->init_byterange_end);
-               }
-               att_index++;
-       }
+       char *str = gf_mpd_parse_text_content(child);
+       if (str) return gf_list_add(mpd->locations, str);
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_rep_urltemplate(GF_XMLNode *root, GF_MPD_Representation *rep)
+static GF_Err gf_mpd_parse_metrics(GF_MPD *mpd, GF_XMLNode *child)
 {
-       u32 att_index;
-       GF_XMLAttribute *att;
-
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "sourceURL")) {
-                       rep->url_template = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "id")) {
-                       rep->id = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "startIndex")) {
-                       rep->startIndex = atoi(att->value)-1;
-               } else if (!strcmp(att->name, "endIndex")) {
-                       rep->endIndex = atoi(att->value)-1;
-               }
-               att_index++;
-       }
+       fprintf(stdout, "mpd metrics not implemented yet\n");
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_rep_urlelt(GF_XMLNode *root, GF_MPD_SegmentInfo *seg, const char * baseURL)
+GF_Err gf_mpd_parse_base_url(GF_List *container, GF_XMLNode *node)
 {
-       u32 att_index;
+       u32 i;
+       GF_Err e;
        GF_XMLAttribute *att;
+       GF_MPD_BaseURL *url; 
+       GF_SAFEALLOC(url, GF_MPD_BaseURL);
+       if (! url) return GF_OUT_OF_MEM;
+       e = gf_list_add(container, url);
 
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "sourceURL")) {
-                       GF_URL_Info info;
-                       GF_Err e;
-                       gf_dm_url_info_init(&info);
-                       e = gf_dm_get_url_info(att->value, &info, baseURL);
-                       assert( e == GF_OK );
-                       assert( info.canonicalRepresentation);
-                       seg->url = gf_strdup(info.canonicalRepresentation);
-                       gf_dm_url_info_del(&info);
-               } else if (!strcmp(att->name, "range")) {
-                       seg->use_byterange = 1;
-                       sscanf(att->value, "%d-%d", &seg->byterange_start, &seg->byterange_end);
-               }
-               att_index++;
+       i = 0;
+       while ( (att = gf_list_enum(node->attributes, &i))) {
+               if (!strcmp(att->name, "serviceLocation")) url->service_location = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "byteRange")) url->byte_range = gf_mpd_parse_byte_range(att->value);
        }
+       url->URL = gf_mpd_parse_text_content(node);
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_rep_segmentinfo(GF_XMLNode *root, GF_MPD_Representation *rep)
+static GF_Err gf_mpd_parse_program_info(GF_MPD *mpd, GF_XMLNode *root)
 {
+       GF_MPD_ProgramInfo *info;
        u32 att_index, child_index;
-       u32 nb_urlelements;
        GF_XMLAttribute *att;
        GF_XMLNode *child;
 
+       GF_SAFEALLOC(info, GF_MPD_ProgramInfo);
+       if (!info) return GF_OUT_OF_MEM;
+
        att_index = 0;
        while (1) {
                att = gf_list_get(root->attributes, att_index);
                if (!att) {
                        break;
-               } else if (!strcmp(att->name, "duration")) {
-                       rep->default_segment_duration = gf_mpd_parse_duration(att->value);
-               } else if (!strcmp(att->name, "baseURL")) {
-                       rep->default_base_url = gf_strdup(att->value);
+               } else if (!strcmp(att->name, "moreInformationURL")) {
+                       info->more_info_url = gf_mpd_parse_string(att->value);
+               } else if (!strcmp(att->name, "lang")) {
+                       info->lang = gf_mpd_parse_string(att->value);
                }
                att_index++;
        }
 
        child_index = 0;
-       nb_urlelements = 0;
        while (1) {
                child = gf_list_get(root->content, child_index);
                if (!child) {
                        break;
                } else if (child->type == GF_XML_NODE_TYPE) {
-                       if (!strcmp(child->name, "InitialisationSegmentURL")) {
-                               gf_mpd_parse_rep_initseg(child, rep, rep->default_base_url);
-                       } else if (!strcmp(child->name, "BaseURL")) {
-                               /*ISO/IEC 23001-6 (19/07/2011), 5.5.11.2: "If [InitialisationSegmentURL@sourceURL]
-                                 not present, then any BaseURL element is mapped to the sourceURL"*/
-                               att_index = 0;
-                               while (att = gf_list_get(child->content, att_index)) {
-                                       if (att->value) {
-                                               rep->init_url = strdup(att->value);
-                                       }
-                                       att_index++;
+                       if (!strcmp(child->name, "Title")) {
+                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
+                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
+                                       info->title = gf_strdup(data_node->name);
+                               }
+                       } else if (!strcmp(child->name, "Source")) {
+                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
+                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
+                                       info->source = gf_strdup(data_node->name);
+                               }
+                       } else if (!strcmp(child->name, "Copyright")) {
+                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
+                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
+                                       info->copyright = gf_strdup(data_node->name);
                                }
-                       } else if (!strcmp(child->name, "UrlTemplate")) {
-                               gf_mpd_parse_rep_urltemplate(child, rep);
-                       } else if (!strcmp(child->name, "Url")) {
-                               nb_urlelements++;
                        }
                }
                child_index++;
        }
+       return gf_list_add(mpd->program_infos, info);
+}
 
-       /* We assume that URL Template has precedence over URL elements */
-       if (rep->url_template) {
-               /* TODO: expand the template to create segment urls*/
-       } else if (nb_urlelements) {
-               u32 urlelt_index = 0;
-               assert( !rep->segments );
-               rep->segments = gf_list_new();
-
-               child_index = 0;
-               while (1) {
-                       child = gf_list_get(root->content, child_index);
-                       if (!child) {
-                               break;
-                       } else if (child->type == GF_XML_NODE_TYPE) {
-                               if (!strcmp(child->name, "Url")) {
-                                       GF_MPD_SegmentInfo *seg_info;
-                                       GF_SAFEALLOC(seg_info, GF_MPD_SegmentInfo);
-                                       if (!seg_info) return GF_OUT_OF_MEM;
-                                       seg_info->byterange_end = 0;
-                                       seg_info->byterange_start = 0;
-                                       seg_info->use_byterange = 0;
-                                       seg_info->url = NULL;
-                                       gf_mpd_parse_rep_urlelt(child, seg_info, rep->default_base_url);
-                                       gf_list_add(rep->segments, seg_info);
-                                       urlelt_index++;
-                               }
+static GF_MPD_URL *gf_mpd_parse_url(GF_XMLNode *root)
+{
+       u32 i;
+       GF_MPD_URL *url;
+       GF_XMLAttribute *att;
+
+       GF_SAFEALLOC(url, GF_MPD_URL);
+       if (!url) return NULL;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "sourceURL")) url->sourceURL = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "range")) url->byte_range = gf_mpd_parse_byte_range(att->value);
+       }
+       return url;
+}
+
+static void gf_mpd_parse_segment_base_generic(GF_MPD_SegmentBase *seg, GF_XMLNode *root)
+{
+       GF_XMLAttribute *att;
+       GF_XMLNode *child;
+       u32 i = 0;
+
+       /*setup some defaults*/
+       seg->timescale = 1;
+
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "timescale")) seg->timescale = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "presentationTimeOffset")) seg->presentation_time_offset = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "indexRange")) seg->index_range = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "indexRangeExact")) seg->index_range_exact = gf_mpd_parse_bool(att->value);
+       }
+
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "Initialization")) seg->initialization_segment = gf_mpd_parse_url(child);
+               else if (!strcmp(child->name, "RepresentationIndex")) seg->representation_index = gf_mpd_parse_url(child);
+       }
+}
+
+static GF_MPD_SegmentTimeline *gf_mpd_parse_segment_timeline(GF_XMLNode *root)
+{
+       u32 i, j;
+       GF_XMLAttribute *att;
+       GF_XMLNode *child;
+       GF_MPD_SegmentTimeline *seg;
+       GF_SAFEALLOC(seg, GF_MPD_SegmentTimeline);
+       if (!seg) return NULL;
+       seg->entries = gf_list_new();
+
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "S")) {
+                       GF_MPD_SegmentTimelineEntry *segent;
+                       GF_SAFEALLOC(segent, GF_MPD_SegmentTimelineEntry);
+                       gf_list_add(seg->entries, segent);
+
+                       j = 0;
+                       while ( (att = gf_list_enum(child->attributes, &j)) ) {
+                               if (!strcmp(att->name, "t")) segent->start_time = gf_mpd_parse_int(att->value);
+                               else if (!strcmp(att->name, "d")) segent->duration = gf_mpd_parse_int(att->value);
+                               else if (!strcmp(att->name, "r")) segent->repeat_count = gf_mpd_parse_int(att->value);
                        }
-                       child_index++;
                }
        }
+       return seg;
+}
+
+static GF_MPD_SegmentBase *gf_mpd_parse_segment_base(GF_XMLNode *root)
+{
+       GF_MPD_SegmentBase *seg;
+       GF_SAFEALLOC(seg, GF_MPD_SegmentBase);
+       if (!seg) return NULL;
+       gf_mpd_parse_segment_base_generic(seg, root);
+       return seg;
+}
+
+void gf_mpd_parse_multiple_segment_base(GF_MPD_MultipleSegmentBase *seg, GF_XMLNode *root)
+{
+       u32 i;
+       GF_XMLAttribute *att;
+       GF_XMLNode *child;
+
+       gf_mpd_parse_segment_base_generic((GF_MPD_SegmentBase*)seg, root);
+       seg->start_number = (u32) -1;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "duration")) seg->duration = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "startNumber")) seg->start_number = gf_mpd_parse_int(att->value);
+       }
+
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "SegmentTimeline")) seg->segment_timeline = gf_mpd_parse_segment_timeline(child);
+               else if (!strcmp(child->name, "BitstreamSwitching")) seg->bitstream_switching_url = gf_mpd_parse_url(child);
+       }
+}
+
+static void gf_mpd_parse_segment_url(GF_List *container, GF_XMLNode *root)
+{
+       u32 i;
+       GF_MPD_SegmentURL *seg;
+       GF_XMLAttribute *att;
+
+       GF_SAFEALLOC(seg, GF_MPD_SegmentURL);
+       if (!seg) return;
+       gf_list_add(container, seg);
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "media")) seg->media = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "index")) seg->index = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "mediaRange")) seg->media_range = gf_mpd_parse_byte_range(att->value);
+               else if (!strcmp(att->name, "indexRange")) seg->index_range = gf_mpd_parse_byte_range(att->value);
+       }
+}
+
+static GF_MPD_SegmentList *gf_mpd_parse_segment_list(GF_XMLNode *root)
+{
+       u32 i;
+       GF_MPD_SegmentList *seg;
+       GF_XMLAttribute *att;
+       GF_XMLNode *child;
+
+       GF_SAFEALLOC(seg, GF_MPD_SegmentList);
+       if (!seg) return NULL;
+       seg->segment_URLs = gf_list_new();
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (strstr(att->name, "href") || strstr(att->name, "actuate")) {
+               } 
+       }
+       gf_mpd_parse_multiple_segment_base((GF_MPD_MultipleSegmentBase *)seg, root);
+
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "SegmentURL")) gf_mpd_parse_segment_url(seg->segment_URLs, child);
+       }
+       if (!gf_list_count(seg->segment_URLs)) {
+               gf_list_del(seg->segment_URLs);
+               seg->segment_URLs = NULL;
+       }
+       return seg;
+}
+
+static GF_MPD_SegmentTemplate *gf_mpd_parse_segment_template(GF_XMLNode *root)
+{
+       u32 i;
+       GF_MPD_SegmentTemplate *seg;
+       GF_XMLAttribute *att;
+
+       GF_SAFEALLOC(seg, GF_MPD_SegmentTemplate);
+       if (!seg) return NULL;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "media")) seg->media = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "index")) seg->index = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "initialization")) seg->initialization = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "bitstreamSwitching")) seg->bitstream_switching = gf_mpd_parse_string(att->value);
+       }
+       gf_mpd_parse_multiple_segment_base((GF_MPD_MultipleSegmentBase *)seg, root);
+       return seg;
+}
+
+static GF_Err gf_mpd_parse_content_component(GF_List *container, GF_XMLNode *root)
+{
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_representation(GF_XMLNode *root, GF_MPD_Representation *rep)
+static GF_Err gf_mpd_parse_descriptor(GF_List *container, GF_XMLNode *root)
+{
+       return GF_OK;
+}
+
+static void gf_mpd_parse_common_representation(GF_MPD_CommonAttributes *com, GF_XMLNode *root)
 {
-       u32 att_index, child_index;
        GF_XMLAttribute *att;
        GF_XMLNode *child;
+       u32 i = 0;
 
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "bandwidth")) {
-                       rep->bandwidth = atoi(att->value);
-               } else if (!strcmp(att->name, "width")) {
-                       rep->width = atoi(att->value);
-               } else if (!strcmp(att->name, "height")) {
-                       rep->height = atoi(att->value);
-               } else if (!strcmp(att->name, "lang")) {
-                       rep->lang = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "mimeType")) {
-                       rep->mime = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "group")) {
-                       rep->groupID = atoi(att->value);
-               } else if (!strcmp(att->name, "startWithRAP")) {
-                       if (!strcmp(att->value, "true")) rep->startWithRap = 1;
-               } else if (!strcmp(att->name, "qualityRanking")) {
-                       rep->qualityRanking = atoi(att->value);
+       /*setup some default*/  
+       com->max_playout_rate = 1.0;
+
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "profiles")) com->profiles = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "width")) com->width = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "height")) com->height = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "sar")) com->sar = gf_mpd_parse_frac(att->value);
+               else if (!strcmp(att->name, "frameRate")) com->framerate = gf_mpd_parse_frac(att->value);
+               else if (!strcmp(att->name, "audioSamplingRate")) com->samplerate = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "mimeType")) com->mime_type = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "segmentProfiles")) com->segmentProfiles = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "codecs")) com->codecs = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "maximumSAPPeriod")) com->maximum_sap_period = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "startWithSAP")) {
+                       if (!strcmp(att->value, "false")) com->starts_with_sap = 0;
+                       else com->starts_with_sap = gf_mpd_parse_int(att->value);
+               }
+               else if (!strcmp(att->name, "maxPlayoutRate")) com->max_playout_rate = gf_mpd_parse_double(att->value);
+               else if (!strcmp(att->name, "codingDependency")) com->coding_dependency = gf_mpd_parse_bool(att->value);
+               else if (!strcmp(att->name, "scanType")) {
+                       if (!strcmp(att->value, "progressive")) com->scan_type = GF_MPD_SCANTYPE_PROGRESSIVE;
+                       else if (!strcmp(att->value, "interlaced")) com->scan_type = GF_MPD_SCANTYPE_INTERLACED;
                }
-               att_index++;
        }
 
-       child_index = 0;
-       while (1) {
-               child = gf_list_get(root->content, child_index);
-               if (!child) {
-                       break;
-               } else if (child->type == GF_XML_NODE_TYPE) {
-                       if (!strcmp(child->name, "ContentProtection")) {
-                               gf_mpd_parse_rep_cp(child, rep);
-                       } else if (!strcmp(child->name, "TrickMode")) {
-                               gf_mpd_parse_rep_trickmode(child, rep);
-                       } else if (!strcmp(child->name, "SegmentInfo")) {
-                               gf_mpd_parse_rep_segmentinfo(child, rep);
-                       }
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "FramePacking")) {
+                       gf_mpd_parse_content_component(com->frame_packing, child);
+               }
+               else if (!strcmp(child->name, "AudioChannelConfiguration")) {
+                       gf_mpd_parse_content_component(com->audio_channels, child);
+               }
+               else if (!strcmp(child->name, "ContentProtection")) {
+                       gf_mpd_parse_content_component(com->content_protection, child);
                }
-               child_index++;
        }
-       return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_segment_info_default(GF_XMLNode *root, GF_MPD_Period *period)
+static void gf_mpd_init_common_attributes(GF_MPD_CommonAttributes *com)
 {
-       u32 att_index;
+       com->audio_channels = gf_list_new();
+       com->content_protection = gf_list_new();
+       com->frame_packing = gf_list_new();
+}
+static GF_Err gf_mpd_parse_representation(GF_List *container, GF_XMLNode *root)
+{
+       u32 i;
+       GF_MPD_Representation *rep;
        GF_XMLAttribute *att;
+       GF_XMLNode *child;
+       GF_Err e;
 
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "duration")) {
-                       period->default_segment_duration = gf_mpd_parse_duration(att->value);
-               } else if (!strcmp(att->name, "baseURL")) {
-                       period->default_base_url = gf_strdup(att->value);
-               } else if (!strcmp(att->name, "sourceUrlTemplatePeriod")) {
-                       period->url_template = gf_strdup(att->value);
-               }
-               att_index++;
+       GF_SAFEALLOC(rep, GF_MPD_Representation);
+       if (!rep) return GF_OUT_OF_MEM;
+       gf_mpd_init_common_attributes((GF_MPD_CommonAttributes *)rep);
+       rep->base_URLs = gf_list_new();
+       rep->sub_representations = gf_list_new();
+       e = gf_list_add(container, rep);
+       if (e) return e;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (!strcmp(att->name, "id")) rep->id = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "bandwidth")) rep->bandwidth = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "qualityRanking")) rep->quality_ranking = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "dependencyId")) rep->dependency_id = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "mediaStreamStructureId")) rep->media_stream_structure_id = gf_mpd_parse_string(att->value);
        }
+       gf_mpd_parse_common_representation((GF_MPD_CommonAttributes*)rep, root);
 
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "BaseURL")) {
+                       e = gf_mpd_parse_base_url(rep->base_URLs, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "SegmentBase")) {
+                       rep->segment_base = gf_mpd_parse_segment_base(child);
+               }
+               else if (!strcmp(child->name, "SegmentList")) {
+                       rep->segment_list = gf_mpd_parse_segment_list(child);
+               }
+               else if (!strcmp(child->name, "SegmentTemplate")) {
+                       rep->segment_template = gf_mpd_parse_segment_template(child);
+               }
+               else if (!strcmp(child->name, "SubRepresentation")) {
+/*TODO
+                       e = gf_mpd_parse_subrepresentation(rep->sub_representations, child);
+                       if (e) return e;
+*/
+               }
+       }
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_period(GF_XMLNode *root, GF_MPD_Period *period, const char *default_base_url)
+static GF_Err gf_mpd_parse_adaptation_set(GF_List *container, GF_XMLNode *root)
 {
-       u32 att_index, child_index;
+       u32 i;
+       GF_MPD_AdaptationSet *set;
        GF_XMLAttribute *att;
        GF_XMLNode *child;
+       GF_Err e;
 
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "start")) {
-               } else if (!strcmp(att->name, "segmentAlignmentFlag")) {
-                       if (!strcmp(att->value, "true")) {
-                               period->segment_alignment_flag = 1;
-                       }
-               } else if (!strcmp(att->name, "bitstreamSwitchingFlag")) {
-                       if (!strcmp(att->value, "true")) {
-                               period->segment_alignment_flag = 1;
-                       }
+       GF_SAFEALLOC(set, GF_MPD_AdaptationSet);
+       if (!set) return GF_OUT_OF_MEM;
+       gf_mpd_init_common_attributes((GF_MPD_CommonAttributes *)set);
+       set->accessibility = gf_list_new();
+       set->role = gf_list_new();
+       set->rating = gf_list_new();
+       set->viewpoint = gf_list_new();
+       set->content_component = gf_list_new();
+       set->base_URLs = gf_list_new();
+       set->representations = gf_list_new();
+       /*assign default ID and group*/
+       set->group = -1;
+
+       e = gf_list_add(container, set);
+       if (e) return e;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (strstr(att->name, "href") || strstr(att->name, "actuate")) {
+               } 
+               else if (!strcmp(att->name, "id")) set->id = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "group")) set->group = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "lang")) set->lang = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "contentType")) set->content_type = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "par")) set->par = gf_mpd_parse_frac(att->value);
+               else if (!strcmp(att->name, "minBandwidth")) set->min_bandwidth = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "maxBandwidth")) set->max_bandwidth = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "minWidth")) set->min_width = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "maxWidth")) set->max_width = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "minHeight")) set->min_height = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "maxHeight")) set->max_height = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "minFrameRate")) set->min_framerate = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "maxFrameRate")) set->max_framerate = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "segmentAlignment")) set->segment_alignment = gf_mpd_parse_bool(att->value);
+               else if (!strcmp(att->name, "bitstreamSwitching")) set->bitstream_switching = gf_mpd_parse_bool(att->value);
+               else if (!strcmp(att->name, "subsegmentAlignment")) set->subsegment_alignment = gf_mpd_parse_bool(att->value);
+               else if (!strcmp(att->name, "subsegmentStartsWithSAP")) {
+                       if (!strcmp(att->value, "false")) set->subsegment_starts_with_sap  = 0;
+                       else set->subsegment_starts_with_sap = gf_mpd_parse_int(att->value);
                }
-               att_index++;
        }
+       gf_mpd_parse_common_representation((GF_MPD_CommonAttributes*)set, root);
 
-       child_index = 0;
-       while (1) {
-               child = gf_list_get(root->content, child_index);
-               if (!child) {
-                       break;
-               } else if (child->type == GF_XML_NODE_TYPE) {
-                       if (!strcmp(child->name, "SegmentInfoDefault")) {
-                               gf_mpd_parse_segment_info_default(child, period);
-                       } else if (!strcmp(child->name, "Representation")) {
-                               GF_MPD_Representation *rep;
-                               GF_SAFEALLOC(rep, GF_MPD_Representation);
-                               if (!rep)
-                                       return GF_OUT_OF_MEM;
-                               if (default_base_url) {
-                                       rep->default_base_url = gf_strdup(default_base_url);
-                               }
-                               gf_mpd_parse_representation(child, rep);
-                               gf_list_add(period->representations, rep);
-                       }
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "Accessibility")) {
+                       e = gf_mpd_parse_descriptor(set->accessibility, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "Role")) {
+                       e = gf_mpd_parse_descriptor(set->role, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "Rating")) {
+                       e = gf_mpd_parse_descriptor(set->rating, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "Viewpoint")) {
+                       e = gf_mpd_parse_descriptor(set->viewpoint, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "BaseURL")) {
+                       e = gf_mpd_parse_base_url(set->base_URLs, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "ContentComponent")) {
+                       e = gf_mpd_parse_content_component(set->content_component, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "SegmentBase")) {
+                       set->segment_base = gf_mpd_parse_segment_base(child);
+               }
+               else if (!strcmp(child->name, "SegmentList")) {
+                       set->segment_list = gf_mpd_parse_segment_list(child);
+               }
+               else if (!strcmp(child->name, "SegmentTemplate")) {
+                       set->segment_template = gf_mpd_parse_segment_template(child);
+               }
+               else if (!strcmp(child->name, "Representation")) {
+                       e = gf_mpd_parse_representation(set->representations, child);
+                       if (e) return e;
                }
-               child_index++;
        }
-
        return GF_OK;
 }
 
-static GF_Err gf_mpd_parse_program_info(GF_XMLNode *root, GF_MPD *mpd)
+static GF_Err gf_mpd_parse_period(GF_MPD *mpd, GF_XMLNode *root)
 {
-       u32 att_index, child_index;
+       u32 i;
+       GF_MPD_Period *period;
        GF_XMLAttribute *att;
        GF_XMLNode *child;
+       GF_Err e;
 
-       att_index = 0;
-       while (1) {
-               att = gf_list_get(root->attributes, att_index);
-               if (!att) {
-                       break;
-               } else if (!strcmp(att->name, "moreInformationURL")) {
-                       mpd->more_info_url = gf_strdup(att->value);
-               }
-               att_index++;
+       GF_SAFEALLOC(period, GF_MPD_Period);
+       if (!period) return GF_OUT_OF_MEM;
+       period->adaptation_sets = gf_list_new();
+       period->base_URLs = gf_list_new();
+       period->subsets = gf_list_new();
+       e = gf_list_add(mpd->periods, period);
+       if (e) return e;
+
+       i = 0;
+       while ( (att = gf_list_enum(root->attributes, &i)) ) {
+               if (strstr(att->name, "href") || strstr(att->name, "actuate")) {
+               } 
+               else if (!strcmp(att->name, "id")) period->ID = gf_mpd_parse_string(att->value);
+               else if (!strcmp(att->name, "start")) period->start = gf_mpd_parse_duration(att->value);
+               else if (!strcmp(att->name, "duration")) period->duration = gf_mpd_parse_duration(att->value);
+               else if (!strcmp(att->name, "bitstreamSwitching")) period->bitstream_switching = gf_mpd_parse_bool(att->value);
        }
 
-       child_index = 0;
-       while (1) {
-               child = gf_list_get(root->content, child_index);
-               if (!child) {
-                       break;
-               } else if (child->type == GF_XML_NODE_TYPE) {
-                       if (!strcmp(child->name, "Title")) {
-                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
-                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
-                                       mpd->title = gf_strdup(data_node->name);
-                               }
-                       } else if (!strcmp(child->name, "Source")) {
-                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
-                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
-                                       mpd->source = gf_strdup(data_node->name);
-                               }
-                       } else if (!strcmp(child->name, "Copyright")) {
-                               GF_XMLNode *data_node = gf_list_get(child->content, 0);
-                               if (data_node && data_node->type == GF_XML_TEXT_TYPE) {
-                                       mpd->copyright = gf_strdup(data_node->name);
-                               }
-                       }
+       i = 0;
+       while ( (child = gf_list_enum(root->content, &i))) {
+               if (child->type != GF_XML_NODE_TYPE) continue;
+               if (!strcmp(child->name, "BaseURL")) {
+                       e = gf_mpd_parse_base_url(period->base_URLs, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "SegmentBase")) {
+                       period->segment_base = gf_mpd_parse_segment_base(child);
+               }
+               else if (!strcmp(child->name, "SegmentList")) {
+                       period->segment_list = gf_mpd_parse_segment_list(child);
+               }
+               else if (!strcmp(child->name, "SegmentTemplate")) {
+                       period->segment_template = gf_mpd_parse_segment_template(child);
+               }
+               else if (!strcmp(child->name, "AdaptationSet")) {
+                       e = gf_mpd_parse_adaptation_set(period->adaptation_sets, child);
+                       if (e) return e;
+               }
+               else if (!strcmp(child->name, "SubSet")) {
                }
-               child_index++;
        }
        return GF_OK;
 }
 
+
 GF_MPD *gf_mpd_new()
 {
        GF_MPD *mpd;
@@ -450,65 +661,186 @@ GF_MPD *gf_mpd_new()
        return mpd;
 }
 
+static void gf_mpd_del_list(GF_List *list, void (*__destructor)(void *), Bool reset_only)
+{
+       if (!list) return;
+       while (gf_list_count(list)) {
+               void *item = gf_list_last(list);
+               gf_list_rem_last(list);
+               if (item && __destructor) __destructor(item);
+       }
+       if (!reset_only) gf_list_del(list);
+}
+
+void gf_mpd_base_url_free(void *_item)
+{
+       GF_MPD_BaseURL *base_url = (GF_MPD_BaseURL *)_item;
+       if (base_url->service_location) gf_free(base_url->service_location);
+       if (base_url->URL) gf_free(base_url->URL);
+       gf_free(base_url);
+}
+
+void gf_mpd_url_free(void *_item)
+{
+       GF_MPD_URL *ptr = (GF_MPD_URL*)_item;
+       if (ptr->sourceURL) gf_free(ptr->sourceURL);
+       gf_free(ptr);
+}
+void gf_mpd_string_free(void *_item)
+{
+       gf_free( (char *) _item );
+}
+
+void gf_mpd_prog_info_free(void *_item)
+{
+       GF_MPD_ProgramInfo *ptr = (GF_MPD_ProgramInfo *)_item;
+       if (ptr->lang) gf_free(ptr->lang);
+       if (ptr->title) gf_free(ptr->title);
+       if (ptr->source) gf_free(ptr->source);
+       if (ptr->copyright) gf_free(ptr->copyright);
+       if (ptr->more_info_url) gf_free(ptr->more_info_url);
+       gf_free(ptr);
+}
+void gf_mpd_segment_url_free(void *_item)
+{
+       GF_MPD_SegmentURL *ptr = (GF_MPD_SegmentURL*)_item;
+       if (ptr->index) gf_free(ptr->index);
+       if (ptr->index_range) gf_free(ptr->index_range);
+       if (ptr->media) gf_free(ptr->media);
+       if (ptr->media_range) gf_free(ptr->media_range);
+       gf_free(ptr);
+}
+void gf_mpd_segment_base_free(void *_item)
+{
+       GF_MPD_SegmentBase *ptr = (GF_MPD_SegmentBase *)_item;
+       if (ptr->initialization_segment) gf_mpd_url_free(ptr->initialization_segment);
+       if (ptr->representation_index) gf_mpd_url_free(ptr->representation_index);
+       gf_free(ptr);
+}
+
+void gf_mpd_segment_entry_free(void *_item)
+{
+       gf_free(_item);
+}
+void gf_mpd_segment_timeline_free(void *_item)
+{
+       GF_MPD_SegmentTimeline *ptr = (GF_MPD_SegmentTimeline *)_item;
+       gf_mpd_del_list(ptr->entries, gf_mpd_segment_entry_free, 0);
+       gf_free(ptr);
+}
+
+void gf_mpd_segment_list_free(void *_item)
+{
+       GF_MPD_SegmentList *ptr = (GF_MPD_SegmentList *)_item;
+       if (ptr->initialization_segment) gf_mpd_url_free(ptr->initialization_segment);
+       if (ptr->bitstream_switching_url) gf_mpd_url_free(ptr->bitstream_switching_url);
+       if (ptr->representation_index) gf_mpd_url_free(ptr->representation_index);
+       if (ptr->segment_timeline) gf_mpd_segment_timeline_free(ptr->segment_timeline);
+       gf_mpd_del_list(ptr->segment_URLs, gf_mpd_segment_url_free, 0);
+       gf_free(ptr);
+}
+void gf_mpd_segment_template_free(void *_item)
+{
+       GF_MPD_SegmentTemplate *ptr = (GF_MPD_SegmentTemplate *)_item;
+       if (ptr->initialization_segment) gf_mpd_url_free(ptr->initialization_segment);
+       if (ptr->bitstream_switching_url) gf_mpd_url_free(ptr->bitstream_switching_url);
+       if (ptr->representation_index) gf_mpd_url_free(ptr->representation_index);
+       if (ptr->segment_timeline) gf_mpd_segment_timeline_free(ptr->segment_timeline);
+       if (ptr->index) gf_free(ptr->index);
+       if (ptr->media) gf_free(ptr->media);
+       if (ptr->initialization) gf_free(ptr->initialization);
+       if (ptr->bitstream_switching) gf_free(ptr->bitstream_switching);
+       gf_free(ptr);
+}
+void gf_mpd_descriptor_free(void *item)
+{
+       fprintf(stdout, "error: descriptor not implemented\n");
+       gf_free(item);
+}
+
+void gf_mpd_content_component_free(void *item)
+{
+       fprintf(stdout, "error: content component not implemented\n");
+       gf_free(item);
+}
+
+void gf_mpd_common_attributes_free(GF_MPD_CommonAttributes *ptr)
+{
+       if (ptr->profiles) gf_free(ptr->profiles);
+       if (ptr->sar) gf_free(ptr->sar);
+       if (ptr->framerate) gf_free(ptr->framerate);
+       if (ptr->mime_type) gf_free(ptr->mime_type);
+       if (ptr->segmentProfiles) gf_free(ptr->segmentProfiles);
+       if (ptr->codecs) gf_free(ptr->codecs);
+       gf_mpd_del_list(ptr->frame_packing, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->audio_channels, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->content_protection, gf_mpd_descriptor_free, 0);
+}
+
+void gf_mpd_representation_free(void *_item)
+{
+       GF_MPD_Representation *ptr = (GF_MPD_Representation *)_item;
+       gf_mpd_common_attributes_free((GF_MPD_CommonAttributes *)ptr);
+       if (ptr->id) gf_free(ptr->id);
+       if (ptr->dependency_id) gf_free(ptr->dependency_id);
+       if (ptr->media_stream_structure_id) gf_free(ptr->media_stream_structure_id);
+
+       gf_mpd_del_list(ptr->base_URLs, gf_mpd_base_url_free, 0);
+       gf_mpd_del_list(ptr->sub_representations, NULL/*TODO*/, 0);
+       if (ptr->segment_base) gf_mpd_segment_base_free(ptr->segment_base);
+       if (ptr->segment_list) gf_mpd_segment_list_free(ptr->segment_list);
+       if (ptr->segment_template) gf_mpd_segment_template_free(ptr->segment_template);
+       gf_free(ptr);
+}
+
+void gf_mpd_adaptation_set_free(void *_item)
+{
+       GF_MPD_AdaptationSet *ptr = (GF_MPD_AdaptationSet *)_item;
+       gf_mpd_common_attributes_free((GF_MPD_CommonAttributes *)ptr);
+       if (ptr->lang) gf_free(ptr->lang);
+       if (ptr->content_type) gf_free(ptr->content_type);
+       if (ptr->par) gf_free(ptr->par);
+       gf_mpd_del_list(ptr->accessibility, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->role, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->rating, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->viewpoint, gf_mpd_descriptor_free, 0);
+       gf_mpd_del_list(ptr->content_component, gf_mpd_content_component_free, 0);
+       if (ptr->segment_base) gf_mpd_segment_base_free(ptr->segment_base);
+       if (ptr->segment_list) gf_mpd_segment_list_free(ptr->segment_list);
+       if (ptr->segment_template) gf_mpd_segment_template_free(ptr->segment_template);
+       gf_mpd_del_list(ptr->base_URLs, gf_mpd_base_url_free, 0);
+       gf_mpd_del_list(ptr->representations, gf_mpd_representation_free, 0);
+       gf_free(ptr);
+}
+void gf_mpd_period_free(void *_item)
+{
+       GF_MPD_Period *ptr = (GF_MPD_Period *)_item;
+       if (ptr->ID) gf_free(ptr->ID);
+       if (ptr->segment_base) gf_mpd_segment_base_free(ptr->segment_base);
+       if (ptr->segment_list) gf_mpd_segment_list_free(ptr->segment_list);
+       if (ptr->segment_template) gf_mpd_segment_template_free(ptr->segment_template);
+
+       gf_mpd_del_list(ptr->base_URLs, gf_mpd_base_url_free, 0);
+       gf_mpd_del_list(ptr->adaptation_sets, gf_mpd_adaptation_set_free, 0);
+       gf_mpd_del_list(ptr->subsets, NULL/*TODO*/, 0);
+       gf_free(ptr);
+}
+
 void gf_mpd_del(GF_MPD *mpd)
 {
-       while (gf_list_count(mpd->periods)) {
-               GF_MPD_Period *period = gf_list_get(mpd->periods, 0);
-               gf_list_rem(mpd->periods, 0);
-               while (gf_list_count(period->representations)) {
-                       GF_MPD_Representation *rep = gf_list_get(period->representations, 0);
-                       gf_list_rem(period->representations, 0);
-
-                       while (gf_list_count(rep->segments)) {
-                               GF_MPD_SegmentInfo *seg = gf_list_get(rep->segments, 0);
-                               gf_list_rem(rep->segments, 0);
-                               if (seg->url) gf_free(seg->url);
-                               gf_free(seg);
-                       }
-                       if (rep->content_protection_type) gf_free(rep->content_protection_type);
-                       rep->content_protection_type = NULL;
-                       if (rep->content_protection_uri) gf_free(rep->content_protection_uri);
-                       rep->content_protection_uri = NULL;
-                       if (rep->default_base_url) gf_free(rep->default_base_url);
-                       rep->default_base_url = NULL;
-                       if (rep->id) gf_free(rep->id);
-                       rep->id = NULL;
-                       if (rep->init_url) gf_free(rep->init_url);
-                       rep->init_url = NULL;
-                       if (rep->lang) gf_free(rep->lang);
-                       rep->lang = NULL;
-                       if (rep->mime) gf_free(rep->mime);
-                       rep->mime = NULL;
-                       if (rep->url_template) gf_free(rep->url_template);
-                       rep->url_template = NULL;
-                       if (rep->segments) gf_list_del(rep->segments);
-                       rep->segments = NULL;
-                       gf_free(rep);
-               }
-               gf_list_del(period->representations);
-               period->representations = NULL;
-               if (period->default_base_url) gf_free(period->default_base_url);
-               if (period->url_template) gf_free(period->url_template);
-
-               gf_free(period);
-       }
-       gf_list_del(mpd->periods);
-       mpd->periods = NULL;
-       if (mpd->base_url) gf_free(mpd->base_url);
-       mpd->base_url = NULL;
-       if (mpd->title) gf_free(mpd->title);
-       mpd->title = NULL;
-       if (mpd->source) gf_free(mpd->source);
-       mpd->source = NULL;
-       if (mpd->copyright) gf_free(mpd->copyright);
-       mpd->copyright = NULL;
-       if (mpd->more_info_url) gf_free(mpd->more_info_url);
-       mpd->more_info_url = NULL;
+       gf_mpd_del_list(mpd->program_infos, gf_mpd_prog_info_free, 0);
+       gf_mpd_del_list(mpd->base_URLs, gf_mpd_base_url_free, 0);
+       gf_mpd_del_list(mpd->locations, gf_mpd_string_free, 0);
+       gf_mpd_del_list(mpd->metrics, NULL/*TODO*/, 0);
+       gf_mpd_del_list(mpd->periods, gf_mpd_period_free, 0);
+       if (mpd->profiles) gf_free(mpd->profiles);
+       if (mpd->ID) gf_free(mpd->ID);
        gf_free(mpd);
 }
 
 GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_base_url)
 {
+       GF_Err e;
        u32 att_index, child_index;
        GF_XMLAttribute *att;
        GF_XMLNode *child;
@@ -517,6 +849,12 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b
 
        assert( !mpd->periods );
        mpd->periods = gf_list_new();
+       mpd->program_infos = gf_list_new();
+       mpd->base_URLs = gf_list_new();
+       mpd->locations = gf_list_new();
+       mpd->metrics = gf_list_new();
+       /*setup some defaults*/
+       mpd->type = GF_MPD_TYPE_STATIC;
 
        att_index = 0;
        child_index = gf_list_count(root->attributes);
@@ -524,20 +862,33 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b
                att = gf_list_get(root->attributes, att_index);
                if (!att) {
                        continue;
+               } 
+               
+               if (!strcmp(att->name, "id")) {
+                       mpd->ID = gf_mpd_parse_string(att->value);
+               } else if (!strcmp(att->name, "profiles")) {
+                       mpd->profiles = gf_mpd_parse_string(att->value);
                } else if (!strcmp(att->name, "type")) {
-                       if (!strcmp(att->value, "OnDemand")) mpd->type = GF_MPD_TYPE_ON_DEMAND;
-                       else if (!strcmp(att->value, "Live")) mpd->type = GF_MPD_TYPE_LIVE;
+                       if (!strcmp(att->value, "static")) mpd->type = GF_MPD_TYPE_STATIC;
+                       else if (!strcmp(att->value, "dynamic")) mpd->type = GF_MPD_TYPE_DYNAMIC;
                } else if (!strcmp(att->name, "availabilityStartTime")) {
+                       mpd->availabilityStartTime = gf_mpd_parse_date(att->value);
                } else if (!strcmp(att->name, "availabilityEndTime")) {
+                       mpd->availabilityEndTime = gf_mpd_parse_date(att->value);
                } else if (!strcmp(att->name, "mediaPresentationDuration")) {
-                       mpd->duration = gf_mpd_parse_duration(att->value);
-               } else if (!strcmp(att->name, "minimumUpdatePeriodMPD")) {
-                       mpd->min_update_time = gf_mpd_parse_duration(att->value);
+                       mpd->media_presentation_duration = gf_mpd_parse_duration(att->value);
+               } else if (!strcmp(att->name, "minimumUpdatePeriod")) {
+                       mpd->minimum_update_period = gf_mpd_parse_duration(att->value);
                } else if (!strcmp(att->name, "minBufferTime")) {
                        mpd->min_buffer_time = gf_mpd_parse_duration(att->value);
                } else if (!strcmp(att->name, "timeShiftBufferDepth")) {
                        mpd->time_shift_buffer_depth = gf_mpd_parse_duration(att->value);
-               } else if (!strcmp(att->name, "baseURL")) {
+               } else if (!strcmp(att->name, "suggestedPresentationDelay")) {
+                       mpd->suggested_presentaton_delay = gf_mpd_parse_duration(att->value);
+               } else if (!strcmp(att->name, "maxSegmentDuration")) {
+                       mpd->max_segment_duration = gf_mpd_parse_duration(att->value);
+               } else if (!strcmp(att->name, "maxSubsegmentDuration")) {
+                       mpd->max_subsegment_duration = gf_mpd_parse_duration(att->value);
                }
        }
 
@@ -548,15 +899,20 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b
                        break;
                } else if (child->type == GF_XML_NODE_TYPE) {
                        if (!strcmp(child->name, "ProgramInformation")) {
-                               gf_mpd_parse_program_info(child, mpd);
+                               e = gf_mpd_parse_program_info(mpd, child);
+                               if (e) return e;
+                       } else if (!strcmp(child->name, "Location")) {
+                               e = gf_mpd_parse_location(mpd, child);
+                               if (e) return e;
                        } else if (!strcmp(child->name, "Period")) {
-                               GF_MPD_Period *period;
-                               GF_SAFEALLOC(period, GF_MPD_Period);
-                               if (!period)
-                                       return GF_OUT_OF_MEM;
-                               period->representations = gf_list_new();
-                               gf_mpd_parse_period(child, period, default_base_url);
-                               gf_list_add(mpd->periods, period);
+                               e = gf_mpd_parse_period(mpd, child);
+                               if (e) return e;
+                       } else if (!strcmp(child->name, "Metrics")) {
+                               e = gf_mpd_parse_metrics(mpd, child);
+                               if (e) return e;
+                       } else if (!strcmp(child->name, "BaseURL")) {
+                               e = gf_mpd_parse_base_url(mpd->base_URLs, child);
+                               if (e) return e;
                        }
                }
                child_index++;
@@ -564,18 +920,21 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b
        return GF_OK;
 }
 
-GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const char *base_url,
+GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url,
                                          const char *mpd_file,
-                                         u32 reload_count, char *mimeTypeForM3U8Segments)
+                                         u32 reload_count, char *mimeTypeForM3U8Segments, GF_ClientService *service, Bool do_import, Bool use_mpd_templates)
 {
        GF_Err e;
-       u32 i, count;
+       char *sep, *template_base, *template_ext;
+       u32 i, count, j, count2, k, count3, template_width, template_idx_start;
        Double update_interval;
        VariantPlaylist * pl = NULL;
+       Bool use_template;
        Program *prog;
-       PlaylistElement *pe, *the_pe;
+       PlaylistElement *pe, *the_pe, *elt;
        FILE *fmpd;
        Bool is_end;
+       u32 max_dur = 0;
 
        e = parse_root_playlist(m3u8_file, &pl, base_url);
        if (e) {
@@ -589,12 +948,13 @@ GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const ch
                mpd_file = m3u8_file;
        }
        the_pe = NULL;
-       is_end = !pl->playlistNeedsRefresh;
+       pe = NULL;
        i=0;
        assert( pl );
        assert( pl->programs );
        while ((prog = gf_list_enum(pl->programs, &i))) {
                u32 j=0;
+
                while (NULL != (pe = gf_list_enum(prog->bitrates, &j))) {
                        Bool found = 0;
                        u32 k;
@@ -614,10 +974,13 @@ GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const ch
                        if (found) continue;
 
                        the_pe = pe;
-                       suburl = gf_url_concatenate(base_url, pe->url);
-                       if (!strcmp(base_url, suburl)) {
-                               gf_free(suburl);
-                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD Generator] Not downloading, programs are identical for %s...\n", pe->url));
+                       suburl = NULL;
+                       if (strcmp(base_url, pe->url))
+                               suburl = gf_url_concatenate(base_url, pe->url);
+
+                       if (!suburl || !strcmp(base_url, suburl)) {
+                               if (suburl) gf_free(suburl);
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD Generator] Not downloading, programs are identical for %s...\n", pe->url));
                                continue;
                        }
                        if (service) {
@@ -633,16 +996,22 @@ GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const ch
                                gf_term_download_del(sess);
                                gf_free(suburl);
                        } else { /* for use in MP4Box */
-                               extern GF_Err gf_dm_wget(const char *url, const char *filename);
-                               e = gf_dm_wget(suburl, "tmp.m3u8");
-                               if (e==GF_OK) {
-                                       e = parse_sub_playlist("tmp.m3u8", &pl, suburl, prog, pe);
+                               if (strstr(suburl, "://") && !strstr(suburl, "://") ) {
+                                       e = gf_dm_wget(suburl, "tmp.m3u8");
+                                       if (e==GF_OK) {
+                                               e = parse_sub_playlist("tmp.m3u8", &pl, suburl, prog, pe);
+                                       }
+                                       gf_delete_file("tmp.m3u8");
+                               } else {
+                                       e = parse_sub_playlist(suburl, &pl, suburl, prog, pe);
                                }
-                               gf_delete_file("tmp.m3u8");
                        }
                }
+               if (max_dur < (u32) prog->computed_duration)
+                       max_dur = (u32) prog->computed_duration;
        }
 
+       is_end = !pl->playlistNeedsRefresh;
        assert(the_pe);
 
        update_interval = 0;
@@ -675,8 +1044,16 @@ GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const ch
                variant_playlist_del(pl);
                return GF_IO_ERR;
        }
-       fprintf(fmpd, "<MPD type=\"Live\" xmlns=\"urn:mpeg:mpegB:schema:DASH:MPD:DIS2011\" profiles=\"urn:mpeg:mpegB:profile:dash:full:2011\"");
-       if (update_interval) fprintf(fmpd, " minimumUpdatePeriodMPD=\"PT%02.2gS\"", update_interval);
+       fprintf(fmpd, "<MPD type=\"%s\" xmlns=\"urn:mpeg:DASH:schema:MPD:2011\" profiles=\"urn:mpeg:dash:profile:full:2011\"", is_end ? "static" : "dynamic" );
+       sep = strrchr(m3u8_file, '/');
+       if (!sep) sep = strrchr(m3u8_file, '\\');
+       if (sep) sep = sep + 1;
+       else sep = (char *)m3u8_file;
+       fprintf(fmpd, " id=\"%s\"", sep);
+
+       if (update_interval) fprintf(fmpd, " minimumUpdatePeriod=\"PT%02.2gS\"", update_interval);
+       if (is_end) fprintf(fmpd, " mediaPresentationDuration=\"PT%dS\"", max_dur);
+       fprintf(fmpd, " minBufferTime=\"PT1.5S\"");
        fprintf(fmpd, ">\n");
 
        fprintf(fmpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
@@ -686,67 +1063,334 @@ GF_Err gf_m3u8_to_mpd(GF_ClientService *service, const char *m3u8_file, const ch
                        title = the_pe->url;
                fprintf(fmpd, "  <Title>%s</Title>\n", title );
        }
-       fprintf(fmpd, "  <Copyright>Generated from URL %s</Copyright>\n", base_url );
-       fprintf(fmpd, "  <Source>Generated by GPAC %s from %s</Source>\n", GPAC_FULL_VERSION, base_url);
+       fprintf(fmpd, "  <Source>Generated from URL %s</Source>\n", base_url );
+       fprintf(fmpd, "  <Copyright>Generated by GPAC %s from %s</Copyright>\n", GPAC_FULL_VERSION, base_url);
 
        fprintf(fmpd, " </ProgramInformation>\n");
-       fprintf(fmpd, " <Period start=\"PT0S\">\n");
+       fprintf(fmpd, " <Period start=\"PT0S\"");
+       if (is_end) fprintf(fmpd, " duration=\"PT%dS\"", max_dur);
+       fprintf(fmpd, " >\n");
+
 
        count = gf_list_count(pl->programs);
+       /*check if we use templates*/
+       template_base = NULL;
+       template_ext = NULL;
+       use_template = use_mpd_templates;
+       template_width = 0;
+       template_idx_start = 0;
        for (i=0; i<count; i++) {
-               u32 j, count2;
-               Program *prog = gf_list_get(pl->programs, i);
+               prog = gf_list_get(pl->programs, i);
                count2 = gf_list_count(prog->bitrates);
                for (j = 0; j<count2; j++) {
-                       PlaylistElement *pe = gf_list_get(prog->bitrates, j);
-                       if (pe->elementType == TYPE_PLAYLIST) {
-                               u32 k, count3;
-                               char *base_url = gf_strdup(pe->url);
-                               char *sep = strrchr(base_url, '/');
-                               if (sep) *(sep+1) = 0;
-                               if (pe->codecs && (pe->codecs[0] = '\"')) {
-                                       u32 len = strlen(pe->codecs);
-                                       strncpy(pe->codecs, pe->codecs+1, len-1);
-                                       pe->codecs[len-2] = 0;
-                               }
-                               /* SOUCHAY : if mime-type is still unknown, do not try to add codec information since it would be wrong */
-                               if (!strcmp(M3U8_UNKOWN_MIME_TYPE, mimeTypeForM3U8Segments)){
-                                       fprintf(fmpd, "  <Representation mimeType=\"%s\" bandwidth=\"%d\">\n", mimeTypeForM3U8Segments, pe->bandwidth);
+                       pe = gf_list_get(prog->bitrates, j);
+                       if (pe->elementType != TYPE_PLAYLIST) 
+                               continue;
+
+                       count3 = gf_list_count(pe->element.playlist.elements);
+                       if (!count3) continue;
+
+                       if (!template_base && use_template) {
+                               char *sub_url;
+                               elt = gf_list_get(pe->element.playlist.elements, 0);
+                               sub_url = strrchr(elt->url, '/');
+                               if (!sub_url) {
+                                       sub_url = elt->url;
                                } else {
-                                       fprintf(fmpd, "  <Representation mimeType=\"%s%s%s\" bandwidth=\"%d\">\n", mimeTypeForM3U8Segments, (pe->codecs ? ";codecs=":""), (pe->codecs ? pe->codecs:""), pe->bandwidth);
+                                       sub_url ++;
+                               }
+                               template_base = gf_strdup(sub_url);
+                               template_ext = strrchr(template_base, '.');
+                               k=0;
+                               while (1) {
+                                       if (strchr("0123456789", template_base[k])) {
+                                               if (template_ext) {
+                                                       template_ext[0] = 0;
+                                                       template_width = strlen(template_base + k);
+                                                       template_idx_start = atoi(template_base + k);
+                                                       template_ext[0] = '.';
+                                               }
+                                               template_base[k] = 0;
+                                               break;
+                                       }
+                                       k++;
+                                       if (!template_base[k]) {
+                                               use_template = 0;
+                                               break;
+                                       }
                                }
-                               fprintf(fmpd, "\n   <SegmentInfo duration=\"PT%dS\" baseURL=\"%s\">\n", pe->durationInfo, base_url);
-                               count3 = gf_list_count(pe->element.playlist.elements);
-                               update_interval = (count3 - 1) * pe->durationInfo * 1000;
+                       }
+                       if (!template_ext) template_ext="";
+
+                       if (use_template) {
                                for (k=0; k<count3; k++) {
-                                       u32 cmp = 0;
-                                       char *src_url, *seg_url;
-                                       PlaylistElement *elt = gf_list_get(pe->element.playlist.elements, k);
+                                       char szURL[GF_MAX_PATH], *sub_url;
+                                       elt = gf_list_get(pe->element.playlist.elements, k);
+                                       
+                                       if (template_width==2) sprintf(szURL, "%s%02d%s", template_base, template_idx_start + k, template_ext);
+                                       else if (template_width==3) sprintf(szURL, "%s%03d%s", template_base, template_idx_start + k, template_ext);
+                                       else if (template_width==4) sprintf(szURL, "%s%04d%s", template_base, template_idx_start + k, template_ext);
+                                       else if (template_width==5) sprintf(szURL, "%s%05d%s", template_base, template_idx_start + k, template_ext);
+                                       else if (template_width==6) sprintf(szURL, "%s%06d%s", template_base, template_idx_start + k, template_ext);
+                                       else sprintf(szURL, "%s%d%s", template_base, template_idx_start + k, template_ext);
 
-                                       /*remove protocol scheme and try to find the common part in baseURL and segment URL - this avoids copying the entire url*/
-                                       src_url = strstr(base_url, "://");
-                                       if (src_url) src_url += 3;
-                                       else src_url = base_url;
+                                       sub_url = strrchr(elt->url, '/');
+                                       if (!sub_url) sub_url = elt->url;
+                                       else sub_url ++;
+                                       if (strcmp(szURL, sub_url)) {
+                                               use_template = 0;
+                                               break;
+                                       }
+                               }
+                       }
 
-                                       seg_url = strstr(elt->url, "://");
-                                       if (seg_url) seg_url += 3;
-                                       else seg_url = elt->url;
+               }
+       }
+
+       fprintf(fmpd, "  <AdaptationSet>\n");
+
+       /*if we use templates, put the SegmentTemplate element at the adaptationSet level*/
+       if (use_template) {
+               fprintf(fmpd, "   <SegmentTemplate");
+
+               fprintf(fmpd, " duration=\"%d\"", pe->durationInfo);
+               if (template_width>1) {
+                       fprintf(fmpd, " media=\"%s$%%0%ddNumber$%s\"", template_base, template_width, template_ext);
+               } else {
+                       fprintf(fmpd, " media=\"%s$Number$%s\"", template_base, template_ext);
+               }
+               fprintf(fmpd, " startNumber=\"%d\"", template_idx_start);
+               fprintf(fmpd, "/>\n");
+       }
 
-                                       while (src_url[cmp] == seg_url[cmp]) cmp++;
-                                       fprintf(fmpd, "    <Url sourceURL=\"%s\"/>\n", cmp ? (seg_url + cmp) : elt->url);
+       if (do_import) {
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+               GF_Err e;
+               GF_MediaImporter import;
+               char *tmp_file = NULL;
+               elt = gf_list_get(pe->element.playlist.elements, 0);
+               memset(&import, 0, sizeof(GF_MediaImporter));
+               import.trackID = 0;
+               import.flags = GF_IMPORT_PROBE_ONLY;
+
+               if (strstr(elt->url, "://") && !strstr(elt->url, "file://")) {
+                       tmp_file = strrchr(elt->url, '/');
+                       if (!tmp_file) tmp_file = strrchr(elt->url, '\\');
+                       if (tmp_file) {
+                               e = gf_dm_wget(elt->url, tmp_file);
+                               if (e==GF_OK) {
+                                       import.in_name = tmp_file;
+                                       e = gf_media_import(&import);
                                }
-                               fprintf(fmpd, "   </SegmentInfo>\n");
-                               fprintf(fmpd, "  </Representation>\n");
-                               gf_free(base_url);
-                       } else if (pe->elementType == TYPE_STREAM) {
+                       }
+               } else {
+                       import.in_name = elt->url;
+                       e = gf_media_import(&import);
+               }
+
+               if (import.nb_tracks>1) {
+                       for (k=0; k<import.nb_tracks; k++) {
+                               fprintf(fmpd, "   <ContentComponent id=\"%d\"", import.tk_info[k].track_num);
+                               if (import.tk_info[k].lang) 
+                                       fprintf(fmpd, " lang=\"%s\"", gf_4cc_to_str(import.tk_info[k].lang));
+                               switch (import.tk_info[k].type) {
+                               case GF_ISOM_MEDIA_VISUAL:
+                                       fprintf(fmpd, " contentType=\"video\"");
+                                       break;
+                               case GF_ISOM_MEDIA_AUDIO:
+                                       fprintf(fmpd, " contentType=\"audio\"");
+                                       break;
+                               default:
+                                       fprintf(fmpd, " contentType=\"application\"");
+                                       break;
+                               }
+                               fprintf(fmpd, "/>\n");
+                       }
+               }
+               if (tmp_file)
+                       gf_delete_file(tmp_file);
+#endif
+       }
+
+       /*check if we use templates*/
+       count = gf_list_count(pl->programs);
+       for (i=0; i<count; i++) {
+               u32 width, height, samplerate, num_channels;
+               prog = gf_list_get(pl->programs, i);
+               count2 = gf_list_count(prog->bitrates);
+               for (j = 0; j<count2; j++) {
+                       char *base_url;
+                       char *byte_range_media_file = NULL;
+                       pe = gf_list_get(prog->bitrates, j);
+                       
+                       if (pe->elementType == TYPE_STREAM) {
                                fprintf(stdout, "NOT SUPPORTED: M3U8 Stream\n");
+                       } else if (pe->elementType != TYPE_PLAYLIST) {
+                               fprintf(stdout, "NOT SUPPORTED: M3U8 unknown type\n");
+                       }
+
+                       count3 = gf_list_count(pe->element.playlist.elements);
+                       if (!count3) continue;
+
+                       base_url = gf_strdup(pe->url);
+                       sep = strrchr(base_url, '/');
+
+                       if (pe->codecs && (pe->codecs[0] = '\"')) {
+                               u32 len = strlen(pe->codecs);
+                               strncpy(pe->codecs, pe->codecs+1, len-1);
+                               pe->codecs[len-2] = 0;
+                       }
+
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+                       width = height = samplerate = num_channels = 0;
+                       if (do_import) {
+                               GF_Err e;
+                               GF_MediaImporter import;
+                               char *tmp_file = NULL;
+                               elt = gf_list_get(pe->element.playlist.elements, 0);
+                               memset(&import, 0, sizeof(GF_MediaImporter));
+                               import.trackID = 0;
+                               import.flags = GF_IMPORT_PROBE_ONLY;
+
+                               if (strstr(elt->url, "://") && !strstr(elt->url, "file://")) {
+                                       tmp_file = strrchr(elt->url, '/');
+                                       if (!tmp_file) tmp_file = strrchr(elt->url, '\\');
+                                       if (tmp_file) {
+                                               e = gf_dm_wget(elt->url, tmp_file);
+                                               if (e==GF_OK) {
+                                                       import.in_name = tmp_file;
+                                               }
+                                       }
+                               } else {
+                                       import.in_name = elt->url;
+                               }
+                               e = gf_media_import(&import);
+
+                               if (!pe->bandwidth && pe->durationInfo) {
+                                       u64 pos = 0;
+                                       Double bw;
+                                       FILE *t = gf_f64_open(import.in_name, "rb");
+                                       if (t) {
+                                               gf_f64_seek(t, 0, SEEK_END);
+                                               pos = gf_f64_tell(t);
+                                               fclose(t);
+                                       }
+                                       bw = (Double) pos;
+                                       bw *= 8;
+                                       bw /= pe->durationInfo;
+                                       pe->bandwidth = (u32) bw;
+                               }
+
+                               if (tmp_file)
+                                       gf_delete_file(tmp_file);
+
+                               if (!pe->codecs) {
+                                       char szCodecs[1024];
+                                       szCodecs[0] = 0;
+                                       for (k=0; k<import.nb_tracks; k++) {
+                                               if (strlen(import.tk_info[k].szCodecProfile)) {
+                                                       if (strlen(szCodecs)) strcat(szCodecs, ",");
+                                                       strcat(szCodecs, import.tk_info[k].szCodecProfile);
+                                               }
+                                       }
+                                       pe->codecs = gf_strdup(szCodecs);
+                               }
+                               for (k=0; k<import.nb_tracks; k++) {
+                                       switch (import.tk_info[k].type) {
+                                       case GF_ISOM_MEDIA_VISUAL:
+                                               width = import.tk_info[k].video_info.width;
+                                               height = import.tk_info[k].video_info.height;
+                                               break;
+                                       case GF_ISOM_MEDIA_AUDIO:
+                                               samplerate = import.tk_info[k].audio_info.sample_rate;
+                                               num_channels = import.tk_info[k].audio_info.nb_channels;
+                                               break;
+                                       }
+                               }
+
+                       }
+#endif
+
+                       fprintf(fmpd, "   <Representation id=\"%s\" bandwidth=\"%d\"", sep ? sep+1 : base_url, pe->bandwidth);
+                       /* SOUCHAY : if mime-type is still unknown, do not try to add codec information since it would be wrong */
+                       if (!strcmp(M3U8_UNKOWN_MIME_TYPE, mimeTypeForM3U8Segments)){
+                               fprintf(fmpd, " mimeType=\"%s\"", mimeTypeForM3U8Segments);
+                       } else {
+                               fprintf(fmpd, " mimeType=\"%s\"", mimeTypeForM3U8Segments);
                        }
+                       if (pe->codecs)
+                               fprintf(fmpd, " codecs=\"%s\"", pe->codecs);
+                       if (width && height) {
+                               fprintf(fmpd, " width=\"%d\" height=\"%d\"", width, height);
+                       }
+                       if (samplerate)
+                               fprintf(fmpd, " audioSamplingRate=\"%d\"", samplerate);
+                       
+
+                       if (use_template) {
+                               if (sep) {
+                                       /*keep final '/' */
+                                       sep[1] = 0;
+                                       fprintf(fmpd, ">\n    <BaseURL>%s</BaseURL>\n   </Representation>\n", base_url);
+                               } else
+                                       fprintf(fmpd, "/>\n");
+
+                               continue;
+                       }
+
+                       fprintf(fmpd, ">\n");
+
+                       byte_range_media_file = NULL;
+                       elt = gf_list_get(pe->element.playlist.elements, 0);
+                       if (elt && (elt->byteRangeEnd || elt->byteRangeStart)) {
+                               byte_range_media_file = elt->url;
+                               fprintf(fmpd, "    <BaseURL>%s</BaseURL>\n", byte_range_media_file);
+                       } else if (sep) {
+                               sep[1] = 0;
+                               fprintf(fmpd, "    <BaseURL>%s</BaseURL>\n", base_url);
+                       }
+
+                       fprintf(fmpd, "    <SegmentList duration=\"%d\">\n", pe->durationInfo);
+                       update_interval = (count3 - 1) * pe->durationInfo * 1000;
+                       for (k=0; k<count3; k++) {
+                               u32 cmp = 0;
+                               char *src_url, *seg_url;
+                               elt = gf_list_get(pe->element.playlist.elements, k);
+
+                               /*remove protocol scheme and try to find the common part in baseURL and segment URL - this avoids copying the entire url*/
+                               src_url = strstr(base_url, "://");
+                               if (src_url) src_url += 3;
+                               else src_url = base_url;
+
+                               seg_url = strstr(elt->url, "://");
+                               if (seg_url) seg_url += 3;
+                               else seg_url = elt->url;
+
+                               while (src_url[cmp] == seg_url[cmp]) cmp++;
+
+                               if (byte_range_media_file) {
+                                       fprintf(fmpd, "     <SegmentURL mediaRange=\""LLU"-"LLU"\"", elt->byteRangeStart, elt->byteRangeEnd);
+                                       if (strcmp(elt->url, byte_range_media_file) )fprintf(fmpd, " media=\"%s\"", elt->url);
+                                       fprintf(fmpd, "/>\n");
+                               } else {
+                                       fprintf(fmpd, "     <SegmentURL media=\"%s\"/>\n", cmp ? (seg_url + cmp) : elt->url);
+                               }
+                       }
+                       fprintf(fmpd, "    </SegmentList>\n");
+                       fprintf(fmpd, "   </Representation>\n");
+                       gf_free(base_url);
                }
        }
+
+       if (template_base) {
+               gf_free(template_base);
+               template_base = NULL;
+       }
+
+       fprintf(fmpd, "  </AdaptationSet>\n");
        fprintf(fmpd, " </Period>\n");
        fprintf(fmpd, "</MPD>");
        fclose(fmpd);
        variant_playlist_del(pl);
        return GF_OK;
 }
-
index eb052cdfe1c3e93857b68090511956244a353a9c..22b243c5844d096120e99b7125478400662e1d60 100644 (file)
@@ -24,8 +24,6 @@
 
 #include <gpac/mpegts.h>
 
-#include <gpac/carousel.h>
-
 
 #ifndef GPAC_DISABLE_MPEG2TS
 
 #include <gpac/internal/media_dev.h>
 #include <gpac/math.h>
 #include <string.h>
-#include <gpac/carousel.h>
 #include <gpac/download.h>
 
+#ifdef GPAC_CONFIG_LINUX
+#include <unistd.h>
+#endif
+
 #define DUMP_MPE_IP_DATAGRAMS
 //#define FORCE_DISABLE_MPEG4SL_OVER_MPEG2TS
 
@@ -69,20 +70,12 @@ const char *gf_m2ts_get_stream_name(u32 streamType)
        }
 }
 
-static u32 gf_m2ts_reframe_default(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_default(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        GF_M2TS_PES_PCK pck;
        pck.flags = 0;
        if (pes->rap) pck.flags |= GF_M2TS_PES_PCK_RAP;
-
-       if (PTS) {
-               pes->PTS = PTS;
-               /*backup DTS for start detection*/
-               PTS = pes->DTS;
-               if (DTS) pes->DTS = DTS;
-               else pes->DTS = PTS;
-               if (!PTS || (PTS != pes->DTS)) pck.flags = GF_M2TS_PES_PCK_AU_START;
-       }
+       if (!same_pts) pck.flags |= GF_M2TS_PES_PCK_AU_START;
        pck.DTS = pes->DTS;
        pck.PTS = pes->PTS;
        pck.data = data;
@@ -93,8 +86,28 @@ static u32 gf_m2ts_reframe_default(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DT
        return 0;
 }
 
-static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_reset(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
+       if (pes->data) {
+               gf_free(pes->data);
+               pes->data = NULL;
+       }
+       pes->data_len = 0;
+       if (pes->prev_data) {
+               gf_free(pes->prev_data);
+               pes->prev_data = NULL;
+       }
+       pes->prev_data_len = 0;
+       pes->pes_len = 0;
+       pes->prev_PTS = 0;
+       pes->reframe = NULL;
+       pes->cc = -1;
+       return 0;
+}
+
+static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
+{
+       Bool au_start_in_pes=0;
        Bool force_new_au=0;
        Bool start_code_found = 0;
        Bool short_start_code = 0;
@@ -103,12 +116,8 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
 
        GF_M2TS_PES_PCK pck;
 
-       if (PTS) {
-               if (pes->PTS != PTS) force_new_au = 1;
-               pes->PTS = PTS;
-               if (DTS) pes->DTS = DTS;
-               else pes->DTS = PTS;
-       }
+       if (!same_pts) 
+               force_new_au = 1;
 
        /*dispatch frame*/
        pck.stream = pes;
@@ -191,8 +200,15 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
 #endif
                        /*check AU start type*/
                        if (nal_type==GF_AVC_NALU_ACCESS_UNIT) {
+                               if (au_start_in_pes) {
+                                       /*FIXME - we should check the AVC framerate to update the timing ...*/
+                                       pck.DTS += 3000;
+                                       pck.PTS += 3000;
+//                                     GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID%d: Two AVC AUs start in this PES packet - cannot recompute non-first AU timing\n", pes->pid));
+                               }
                                pck.flags = GF_M2TS_PES_PCK_AU_START;
                                force_new_au = 0;
+                               au_start_in_pes = 1;
                        } else if (nal_type==GF_AVC_NALU_IDR_SLICE) {
                                pck.flags = GF_M2TS_PES_PCK_RAP;
                        } 
@@ -237,7 +253,7 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                }
                if (force_new_au) {
                        pck.flags |= GF_M2TS_PES_PCK_AU_START;
-                       force_new_au = 0;
+                       //force_new_au = 0;
                }
                ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
        }
@@ -245,17 +261,12 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
        return 0;
 }
 
-static u32 gf_m2ts_reframe_mpeg_video(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_mpeg_video(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        u32 sc_pos = 0;
        u32 to_send = data_len;
        GF_M2TS_PES_PCK pck;
 
-       if (PTS) {
-               pes->PTS = PTS;
-               if (DTS) pes->DTS = DTS;
-               else pes->DTS = PTS;
-       }
        /*dispatch frame*/
        pck.stream = pes;
        pck.DTS = pes->DTS;
@@ -350,27 +361,37 @@ typedef struct
        u32 profile, sr_idx, nb_ch, frame_size;
 } ADTSHeader;
 
-static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        ADTSHeader hdr;
        u32 sc_pos = 0;
        u32 start = 0;
+
        u32 hdr_size = 0;
+       u64 PTS;
        Bool first = 1;
-       u32 remain;
        GF_M2TS_PES_PCK pck;
 
-       if (PTS) {
-               pes->PTS = PTS;
-               if (DTS) pes->DTS = DTS;
-               else pes->DTS = PTS;
-       }
        /*dispatch frame*/
+       PTS = pes->PTS;
        pck.stream = pes;
        pck.DTS = pes->DTS;
-       pck.PTS = pes->PTS;
+       pck.PTS = PTS;
        pck.flags = 0;
-       remain = pes->frame_state;
+
+       if (pes->frame_state && (data[pes->frame_state]==0xFF) && ((data[pes->frame_state+1] & 0xF0) == 0xF0)) {
+               assert(pes->frame_state<=data_len);
+               /*dispatch frame*/
+               pck.stream = pes;
+               pck.DTS = PTS;
+               pck.PTS = PTS;
+               pck.flags = 0;
+               pck.data = data;
+               pck.data_len = pes->frame_state;
+               ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+               first = 0;
+               start = sc_pos = pes->frame_state;
+       }
        pes->frame_state = 0;
 
        /*fixme - we need to test this with more ADTS sources were PES framing is on any boundaries*/
@@ -387,13 +408,25 @@ static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                if (start < sc_pos) {
                        /*dispatch frame*/
                        pck.stream = pes;
-                       pck.DTS = pes->PTS;
-                       pck.PTS = pes->PTS;
+                       pck.DTS = PTS;
+                       pck.PTS = PTS;
                        pck.flags = 0;
                        pck.data = data+start;
                        pck.data_len = sc_pos-start;
                        ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
-                       remain = 0;
+                       if (pes->frame_state == pck.data_len) {
+                               /*consider we are sync*/
+                               first = 0;
+                       } else {
+                               first = 1;
+                       }
+                       pes->frame_state = 0;
+               }
+               /*not enough data to parse the frame header*/
+               if (sc_pos + 7 >= data_len) {
+                       pes->frame_state = 0;
+                       pes->prev_PTS = PTS;
+                       return data_len-sc_pos;
                }
 
                bs = gf_bs_new(data + sc_pos + 1, 9, GF_BITSTREAM_READ);
@@ -417,7 +450,7 @@ static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
 
                /*make sure we are sync if we have more data following*/
                if (sc_pos + hdr.frame_size < data_len) {
-                       if ((data[sc_pos + hdr.frame_size]!=0xFF) || ((data[sc_pos+hdr.frame_size+1] & 0xF0) != 0xF0)) {
+                       if ((hdr.frame_size < hdr_size) || (data[sc_pos + hdr.frame_size]!=0xFF) || ((data[sc_pos+hdr.frame_size+1] & 0xF0) != 0xF0)) {
                                sc_pos++;
                                continue;
                        }
@@ -439,19 +472,25 @@ static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                        gf_free(pck.data);
                        pes->aud_sr = cfg.base_sr;
                        pes->aud_nb_ch = cfg.nb_chan;
+                       pes->aud_obj_type = hdr.profile;
                }
 
                /*dispatch frame*/
                pck.stream = pes;
-               pck.DTS = pes->PTS;
-               pck.PTS = pes->PTS;
+               if (first && pes->prev_PTS) {
+                       pck.DTS = pck.PTS = pes->prev_PTS;
+               } else {
+                       pck.DTS = pck.PTS = PTS;
+               }
                pck.flags = GF_M2TS_PES_PCK_AU_START | GF_M2TS_PES_PCK_RAP;
                pck.data = data + sc_pos + hdr_size;
                pck.data_len = hdr.frame_size - hdr_size;
 
                if (pck.data_len > data_len - sc_pos - hdr_size) {
+                       assert(pck.data_len - (data_len - sc_pos - hdr_size) > 0);
                        /*remember how much we have to send*/
                        pes->frame_state = pck.data_len - (data_len - sc_pos - hdr_size);
+                       assert((s32) pes->frame_state > 0);
                        pck.data_len = data_len - sc_pos - hdr_size;
                }
 
@@ -459,10 +498,13 @@ static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                sc_pos += pck.data_len + hdr_size;
                start = sc_pos;
 
-               /*update PTS in case we don't get any update*/
-               if (pes->aud_sr) {
+               if (first && pes->prev_PTS) {
+                       pes->prev_PTS = 0;
+               } 
+               /*update PTS in case we don't get any update*/                  
+               else if (pes->aud_sr) {
                        size = 1024*90000/pes->aud_sr;
-                       pes->PTS += size;
+                       PTS += size;
                }
                first = 0;
        }
@@ -470,21 +512,16 @@ static u32 gf_m2ts_reframe_aac_adts(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
        return 0;
 }
 
-static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        u32 sc_pos = 0;
        u32 start = 0;
        GF_M2TS_PES_PCK pck;
 
-       if (PTS) {
-               pes->PTS = PTS;
-               if (DTS) pes->DTS = DTS;
-               else pes->DTS = PTS;
-       }
        /*dispatch frame*/
        pck.stream = pes;
        pck.DTS = pes->DTS;
-       pck.PTS = pes->PTS;
+       pck.PTS = pes->PTS;     
        pck.flags = 0;
 
        /*fixme - we need to test this with more LATM sources were PES framing is on any boundaries*/
@@ -519,18 +556,18 @@ static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                        amux_versionA = 0;
                        if (amux_version) amux_versionA = gf_bs_read_int(bs, 1);
                        if (!amux_versionA) {
-                               u32 i, allStreamsSameTimeFraming, numSubFrames, numProgram;
+                               u32 i, allStreamsSameTimeFraming, numProgram;
                                if (amux_version) latm_get_value(bs);
 
                                allStreamsSameTimeFraming = gf_bs_read_int(bs, 1);
-                               numSubFrames = gf_bs_read_int(bs, 6);
+                               /*numSubFrames = */gf_bs_read_int(bs, 6);
                                numProgram = gf_bs_read_int(bs, 4);
                                for (i=0; i<=numProgram; i++) {
                                        u32 j, num_lay;
                                        num_lay = gf_bs_read_int(bs, 3);
                                        for (j=0;j<=num_lay; j++) {
                                                GF_M4ADecSpecInfo cfg;
-                                               u32 frameLengthType, latmBufferFullness;
+                                               u32 frameLengthType;
                                                Bool same_cfg = 0;
                                                if (i || j) same_cfg = gf_bs_read_int(bs, 1);
 
@@ -542,6 +579,8 @@ static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                                                                pck.stream = pes;
                                                                pes->aud_sr = cfg.base_sr;
                                                                pes->aud_nb_ch = cfg.nb_chan;
+                                                               pes->aud_obj_type = cfg.base_object_type;
+
                                                                gf_m4a_write_config(&cfg, &pck.data, &pck.data_len);
                                                                ts->on_event(ts, GF_M2TS_EVT_AAC_CFG, &pck);
                                                                gf_free(pck.data);
@@ -549,7 +588,7 @@ static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
                                                }
                                                frameLengthType = gf_bs_read_int(bs, 3);
                                                if (!frameLengthType) {
-                                                       latmBufferFullness = gf_bs_read_int(bs, 8);
+                                                       /*latmBufferFullness = */gf_bs_read_int(bs, 8);
                                                        if (!allStreamsSameTimeFraming) {
                                                        }
                                                } else {
@@ -612,18 +651,20 @@ static u32 gf_m2ts_reframe_aac_latm(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 D
 
 
 #ifndef GPAC_DISABLE_AV_PARSERS
-static u32 gf_m2ts_reframe_mpeg_audio(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64 DTS, u64 PTS, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_mpeg_audio(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        GF_M2TS_PES_PCK pck;
        u32 pos, frame_size, remain;
+       u64 PTS;
 
        pck.flags = GF_M2TS_PES_PCK_RAP;
        pck.stream = pes;
        remain = pes->frame_state;
+       PTS = pes->PTS;
 
        if (remain) {
                /*dispatch end of prev frame*/
-               pck.DTS = pck.PTS = pes->PTS;
+               pck.DTS = pck.PTS = PTS;
                pck.data = data;
                pck.data_len = (remain>data_len) ? data_len : remain;
                ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
@@ -644,23 +685,21 @@ static u32 gf_m2ts_reframe_mpeg_audio(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64
        }
        assert((pes->frame_state & 0xffe00000) == 0xffe00000);
 
-       if (!pes->PTS) {
+       if (!pes->aud_sr || !pes->aud_nb_ch) {
                pes->aud_sr = gf_mp3_sampling_rate(pes->frame_state);
                pes->aud_nb_ch = gf_mp3_num_channels(pes->frame_state);
        }
-       /*we may get a PTS for either the previous or the current frame*/
-       if (PTS>=pes->PTS) pes->PTS = PTS;
        pck.flags = GF_M2TS_PES_PCK_RAP | GF_M2TS_PES_PCK_AU_START;
 
        frame_size = gf_mp3_frame_size(pes->frame_state);
        while (frame_size <= data_len) {
                /*dispatch frame*/
-               pck.DTS = pck.PTS = pes->PTS;
+               pck.DTS = pck.PTS = PTS;
                pck.data = data;
                pck.data_len = frame_size;
                ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
 
-               pes->PTS += gf_mp3_window_size(pes->frame_state)*90000/gf_mp3_sampling_rate(pes->frame_state);
+               PTS += gf_mp3_window_size(pes->frame_state)*90000/gf_mp3_sampling_rate(pes->frame_state);
                /*move frame*/
                data += frame_size;
                data_len -= frame_size;
@@ -679,12 +718,12 @@ static u32 gf_m2ts_reframe_mpeg_audio(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, u64
                frame_size = gf_mp3_frame_size(pes->frame_state);
        }
        if (data_len) {
-               pck.DTS = pck.PTS = pes->PTS;
+               pck.DTS = pck.PTS = PTS;
                pck.data = data;
                pck.data_len = data_len;
                ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
                /*update PTS in case we don't get any update*/
-               pes->PTS += gf_mp3_window_size(pes->frame_state)*90000/gf_mp3_sampling_rate(pes->frame_state);
+               PTS += gf_mp3_window_size(pes->frame_state)*90000/gf_mp3_sampling_rate(pes->frame_state);
                pes->frame_state = frame_size - data_len;
        } else  {
                pes->frame_state = 0;
@@ -804,14 +843,27 @@ static void gf_m2ts_section_complete(GF_M2TS_Demuxer *ts, GF_M2TS_SectionFilter
                        pck.data_len = sec->length;
                        pck.data = sec->section;
                        pck.stream = (GF_M2TS_ES *)ses;
-                       ts->on_event(ts, GF_M2TS_EVT_AIT_FOUND, &pck);
-               } else if (ts->on_mpe_event && ((ses && (ses->flags & GF_M2TS_EVT_DVB_MPE)) || (sec->section[0]==GF_M2TS_TABLE_ID_INT)) ) {
+                       //ts->on_event(ts, GF_M2TS_EVT_AIT_FOUND, &pck);
+                       on_ait_section(ts, GF_M2TS_EVT_AIT_FOUND, &pck);
+               } else if ((ts->on_event && (sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE ||
+                       sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_PRIVATE)) ) {                         
+                       GF_M2TS_SL_PCK pck;
+                       pck.data_len = sec->length;
+                       pck.data = sec->section;
+                       pck.stream = (GF_M2TS_ES *)ses;
+                       on_dsmcc_section(ts,GF_M2TS_EVT_DSMCC_FOUND,&pck); 
+                       //ts->on_event(ts, GF_M2TS_EVT_DSMCC_FOUND, &pck);
+               }
+#ifdef DUMP_MPE_IP_DATAGRAMS
+               else if (ts->on_mpe_event && ((ses && (ses->flags & GF_M2TS_EVT_DVB_MPE)) || (sec->section[0]==GF_M2TS_TABLE_ID_INT)) ) {
                        GF_M2TS_SL_PCK pck;
                        pck.data_len = sec->length;
                        pck.data = sec->section;
                        pck.stream = (GF_M2TS_ES *)ses;
                        ts->on_mpe_event(ts, GF_M2TS_EVT_DVB_MPE, &pck);
-               } else if (ts->on_event) {
+               } 
+#endif
+               else if (ts->on_event) {
                        GF_M2TS_SL_PCK pck;
                        pck.data_len = sec->length;
                        pck.data = sec->section;
@@ -988,6 +1040,8 @@ static Bool gf_m2ts_is_long_section(u8 table_id)
        case GF_M2TS_TABLE_ID_SIT:
        case GF_M2TS_TABLE_ID_DSM_CC_PRIVATE:
        case GF_M2TS_TABLE_ID_MPE_FEC:
+       case GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE:
+       case GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE:
                return 1;
        default:
                if (table_id >= GF_M2TS_TABLE_ID_EIT_SCHEDULE_MIN && table_id <= GF_M2TS_TABLE_ID_EIT_SCHEDULE_MAX)
@@ -1103,7 +1157,7 @@ aggregated_section:
 
 static void gf_m2ts_process_sdt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, GF_List *sections, u8 table_id, u16 ex_table_id, u8 version_number, u8 last_section_number, u32 status)
 {
-        u32 orig_net_id, pos, evt_type;
+        u32 pos, evt_type;
         u32 nb_sections;
         u32 data_size;
         unsigned char *data;
@@ -1134,7 +1188,7 @@ static void gf_m2ts_process_sdt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, GF
         data = section->data;
         data_size = section->data_size;
 
-        orig_net_id = (data[0] << 8) | data[1];
+        //orig_net_id = (data[0] << 8) | data[1];
         pos = 3;
         while (pos < data_size) {
                 GF_M2TS_SDT *sdt;
@@ -1377,17 +1431,19 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                while (info_length > first_loop_len) {
 #ifndef FORCE_DISABLE_MPEG4SL_OVER_MPEG2TS
                        if (tag == GF_M2TS_MPEG4_IOD_DESCRIPTOR) {
-                               u8 scope, label;
                                u32 size;
                                GF_BitStream *iod_bs;
-                               scope = data[6];
-                               label = data[7];
                                iod_bs = gf_bs_new(data+8, len-2, GF_BITSTREAM_READ);
                                if (pmt->program->pmt_iod) gf_odf_desc_del((GF_Descriptor *)pmt->program->pmt_iod);
                                gf_odf_parse_descriptor(iod_bs , (GF_Descriptor **) &pmt->program->pmt_iod, &size);
                                /*remember program number for service/program selection*/
                                if (pmt->program->pmt_iod) pmt->program->pmt_iod->ServiceID = pmt->program->number;
                                gf_bs_del(iod_bs );
+                               /*if empty IOD (freebox case), discard it and use dynamic declaration of object*/
+                               if (!gf_list_count(pmt->program->pmt_iod->ESDescriptors)) {
+                                       gf_odf_desc_del((GF_Descriptor *)pmt->program->pmt_iod);
+                                       pmt->program->pmt_iod = NULL;
+                               }
                        } else {
 #else
                        {
@@ -1405,8 +1461,7 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
        /* count de number of program related PMT received */
        for(i=0;i<gf_list_count(ts->programs);i++){
          GF_M2TS_Program *prog = (GF_M2TS_Program *)gf_list_get(ts->programs,i);
-         if(prog->pmt_pid == pmt->pid){
-               ts->nb_prog_pmt_received++;
+         if(prog->pmt_pid == pmt->pid){                
                break;
          }
        }
@@ -1424,7 +1479,7 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                reg_desc_format = 0;
 
                switch (stream_type) {
-                 printf("stream_type :%d \n",stream_type);
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("stream_type :%d \n",stream_type));
                /* PES */
                case GF_M2TS_VIDEO_MPEG1:
                case GF_M2TS_VIDEO_MPEG2:
@@ -1466,24 +1521,34 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                        break;
 
                
-               case GF_M2TS_PRIVATE_SECTION:
-                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("AIT section found on pid %d\n", pid));
+               
                        /*to refine with generic private section redispatching to AIT or other afterwards*/
                        es = gf_ait_section_new(pmt->program->number);
                        ses = (GF_M2TS_SECTION_ES *)es;
                        ses->sec = gf_m2ts_section_filter_new(NULL, 0);
                        break;
+               case GF_M2TS_13818_6_ANNEX_A:
+               case GF_M2TS_13818_6_ANNEX_B:
+               case GF_M2TS_13818_6_ANNEX_C:
                case GF_M2TS_13818_6_ANNEX_D:
+               case GF_M2TS_PRIVATE_SECTION:                   
                        GF_SAFEALLOC(ses, GF_M2TS_SECTION_ES);
                        es = (GF_M2TS_ES *)ses;
-                       es->flags |= GF_M2TS_ES_IS_SECTION;             
-                       printf("stream type DSM CC user private section: pid = %d \n", pid);            
+                       es->flags |= GF_M2TS_ES_IS_SECTION;
+                       es->pid = pid;
+                       es->service_id = pmt->program->number;
+                       if(stream_type == GF_M2TS_PRIVATE_SECTION){
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("AIT section found on pid %d\n", pid));
+                       }else{
+                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("stream type DSM CC user private section: pid = %d \n", pid));           
+                       }
                        /* NULL means: trigger the call to on_event with DVB_GENERAL type and the raw section as payload */
                        ses->sec = gf_m2ts_section_filter_new(NULL, 1);
+                       //ses->sec->service_id = pmt->program->number;
                        break;
 
                case GF_M2TS_MPE_SECTIONS:
-                       printf("stream type MPE found : pid = %d \n", pid);
+                       GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("stream type MPE found : pid = %d \n", pid));
 #ifdef DUMP_MPE_IP_DATAGRAMS
                        es = gf_dvb_mpe_section_new();
                        if (es->flags & GF_M2TS_ES_IS_SECTION) {
@@ -1561,7 +1626,7 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                                case GF_M2TS_DVB_STREAM_IDENTIFIER_DESCRIPTOR:
                                        {
                                                es->component_tag = data[2];
-                                               printf("Component Tag: %d on Program %d\n", es->component_tag, es->program->number);
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Component Tag: %d on Program %d\n", es->component_tag, es->program->number));
                                        }
                                        break;
                                case GF_M2TS_DVB_TELETEXT_DESCRIPTOR:
@@ -1620,11 +1685,9 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                        nb_es++;
                }
        }
+
        
-       if (nb_es) {
-               if(ts->nb_prog_pmt_received == gf_list_count(ts->programs)){
-                   ts->all_prog_pmt_received = 1;
-               }
+       if (nb_es) {            
                evt_type = (status&GF_M2TS_TABLE_FOUND) ? GF_M2TS_EVT_PMT_FOUND : GF_M2TS_EVT_PMT_UPDATE;
                if (ts->on_event) ts->on_event(ts, evt_type, pmt->program);
        } else {
@@ -1770,7 +1833,7 @@ static GFINLINE u64 gf_m2ts_get_pts(unsigned char *data)
 
 static void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_size, GF_M2TS_PESHeader *pesh)
 {
-       u32 has_pts, has_dts, te;
+       u32 has_pts, has_dts;
        u32 len_check;
        memset(pesh, 0, sizeof(GF_M2TS_PESHeader));
 
@@ -1788,7 +1851,6 @@ static void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_s
        copyright                               = gf_bs_read_int(bs,1);
        original                                = gf_bs_read_int(bs,1);
 */
-       te = data[4];
        has_pts = (data[4]&0x80);
        has_dts = has_pts ? (data[4]&0x40) : 0;
 /*
@@ -1830,10 +1892,16 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea
         u32 stream_id = pes->data[3] | 0x100;
         if ((stream_id >= 0x1c0 && stream_id <= 0x1df) ||
               (stream_id >= 0x1e0 && stream_id <= 0x1ef) ||
-              (stream_id == 0x1bd)) {
+              (stream_id == 0x1bd) ||
+                         /*SL-packetized*/
+                         ((u8) pes->data[3]==0xfa) 
+               ) {
+                       Bool same_pts = 0;
 
                        /*OK read header*/
                        gf_m2ts_pes_header(pes, pes->data+3, pes->data_len-3, &pesh);
+                       
+                       /*send PES timing*/
                        {
                                GF_M2TS_PES_PCK pck;
                                memset(&pck, 0, sizeof(GF_M2TS_PES_PCK));
@@ -1844,20 +1912,69 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea
                                pes->pes_end_packet_number = ts->pck_number;
                                if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PES_TIMING, &pck);
                        }
-
                        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d Got PES header PTS %d\n", pes->pid, pesh.PTS));
+
+                       if (pesh.PTS) {
+
+                               if (pesh.PTS==pes->PTS) {
+                                       same_pts = 1;
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - same PTS "LLU" for two consecutive PES packets \n", pes->pid, pes->PTS) );
+                               }
+#ifndef GPAC_DISABLE_LOG
+                               /*FIXME - this test should only be done for non bi-directionnally coded media
+                               else if (pesh.PTS < pes->PTS) {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - PTS "LLU" less than previous packet PTS "LLU"\n", pes->pid, pesh.PTS, pes->PTS) );
+                               }
+                               */
+#endif
+
+                               pes->PTS = pesh.PTS;
+                               if (!pesh.DTS) pesh.DTS = pesh.PTS;
+
+#ifndef GPAC_DISABLE_LOG
+                               if (pesh.DTS==pes->DTS) {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - same DTS "LLU" for two consecutive PES packets \n", pes->pid, pes->DTS) );
+                               } if (pesh.DTS<pes->DTS) {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - DTS "LLU" less than previous DTS "LLU"\n", pes->pid, pesh.DTS, pes->DTS) );
+                               }
+#endif
+                               pes->DTS = pesh.DTS;
+                       }
+                       /*no PTSs were coded, same time*/
+                       else if (!pesh.hdr_data_len)
+                               same_pts = 1;
+
+
                        /*3-byte start-code + 6 bytes header + hdr extensions*/
                        len = 9 + pesh.hdr_data_len;
-                       if (pes->reframe) {
+
+                       if ((u8) pes->data[3]==0xfa) {
+                               GF_M2TS_SL_PCK sl_pck;
+
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] SL Packet in PES for %d - ES ID %d\n", pes->pid, pes->mpeg4_es_id));
+
+                               if (pes->data_len > len) {
+                                       sl_pck.data = pes->data + len;
+                                       sl_pck.data_len = pes->data_len - len;
+                                       sl_pck.stream = (GF_M2TS_ES *)pes;
+                                       if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SL_PCK, &sl_pck);
+                               } else {
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] Bad SL Packet size: (%d indicated < %d header)\n", pes->pid, pes->data_len, len));
+                               }
+                       } else if (pes->reframe) {
                                u32 remain;
                                u32 offset = len;
 
+                               if (pesh.pck_len && (pesh.pck_len-3-pesh.hdr_data_len != pes->data_len-len)) {
+                                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES payload size %d but received %d bytes\n", (u32) ( pesh.pck_len-3-pesh.hdr_data_len), pes->data_len-len));
+                               }
+
                                if (pes->prev_data_len) {
                                        assert(pes->prev_data_len < len);
                                        offset = len - pes->prev_data_len;
                                        memcpy(pes->data + offset, pes->prev_data, pes->prev_data_len);
                                }
-                               remain = pes->reframe(ts, pes, pesh.DTS, pesh.PTS, pes->data+offset, pes->data_len-offset);
+                               remain = pes->reframe(ts, pes, same_pts, pes->data+offset, pes->data_len-offset);
 
                                if (pes->prev_data) gf_free(pes->prev_data);
                                pes->prev_data = NULL;
@@ -1868,25 +1985,6 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea
                                        pes->prev_data_len = remain;
                                }
                        }
-               }
-               /*SL-packetized stream*/
-               else if ((u8) pes->data[3]==0xfa) {
-                       GF_M2TS_SL_PCK sl_pck;
-                       /*read header*/
-                       gf_m2ts_pes_header(pes, pes->data+3, pes->data_len-3, &pesh);
-
-                       /*3-byte start-code + 6 bytes header + hdr extensions*/
-                       len = 9 + pesh.hdr_data_len;
-
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] SL Packet in PES for %d - ES ID %d\n", pes->pid, pes->mpeg4_es_id));
-                       if (pes->data_len > len) {
-                               sl_pck.data = pes->data + len;
-                               sl_pck.data_len = pes->data_len - len;
-                               sl_pck.stream = (GF_M2TS_ES *)pes;
-                               if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SL_PCK, &sl_pck);
-                       } else {
-                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] Bad SL Packet size: (%d indicated < %d header)\n", pes->pid, pes->data_len, len));
-                       }
                } else {
                        GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: unknown stream ID %08X\n", pes->pid, stream_id));
                }
@@ -1914,15 +2012,21 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H
        pes->cc = hdr->continuity_counter;
 
        if (disc) {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Packet discontinuity (%d expected - got %d- - trashing PES packet\n", pes->pid, expect_cc, hdr->continuity_counter));
-               if (pes->data) {
-                       gf_free(pes->data);
-                       pes->data = NULL;
+               if (pes->flags & GF_M2TS_ES_IGNORE_NEXT_DISCONTINUITY) {
+                       pes->flags &= ~GF_M2TS_ES_IGNORE_NEXT_DISCONTINUITY;
+                       disc = 0;
+               }
+               if (disc) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Packet discontinuity (%d expected - got %d- - trashing PES packet\n", pes->pid, expect_cc, hdr->continuity_counter));
+                       if (pes->data) {
+                               gf_free(pes->data);
+                               pes->data = NULL;
+                       }
+                       pes->data_len = 0;
+                       pes->pes_len = 0;
+                       pes->cc = -1;
+                       return;
                }
-               pes->data_len = 0;
-               pes->pes_len = 0;
-               pes->cc = -1;
-               return;
        }
 
        if (!pes->reframe) return;
@@ -2029,7 +2133,7 @@ static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data)
        hdr.continuity_counter = data[3] & 0xf;
 
        if (hdr.error) {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] TS Packet has error (PID could be %d)\n", hdr.pid));
+               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] TS Packet has error (PID could be %d)\n", hdr.pid));
                return;
        }
 //#if DEBUG_TS_PACKET
@@ -2049,15 +2153,16 @@ static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data)
                }
                paf = &af;
                memset(paf, 0, sizeof(GF_M2TS_AdaptationField));
-               gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size, hdr.pid);
+               assert(af_size>=0 && af_size<=182);
+               if (af_size) gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size, hdr.pid);
                pos += 1+af_size;
                payload_size = 183 - af_size;
                break;
        /*adaptation only - still process in cas of PCR*/
        case 2:
                af_size = data[4];
-               if (af_size>183) {
-                       //error
+               if (af_size != 183) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] Non conformant bitstream: AF size is %d when it must be 183 for AF type 2\n", af_size));
                        return;
                }
                paf = &af;
@@ -2214,6 +2319,16 @@ GF_ESD *gf_m2ts_get_esd(GF_M2TS_ES *es)
        return esd;
 }
 
+void gf_m2ts_set_segment_switch(GF_M2TS_Demuxer *ts)
+{
+       u32 i;
+       for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {
+               GF_M2TS_ES *es = (GF_M2TS_ES *) ts->ess[i];
+               if (!es) continue;
+               es->flags |= GF_M2TS_ES_IGNORE_NEXT_DISCONTINUITY;
+       }
+}
+
 void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts)
 {
        u32 i;
@@ -2274,8 +2389,6 @@ void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts)
 
 static void gf_m2ts_process_section_discard(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *es, GF_List *sections, u8 table_id, u16 ex_table_id, u8 version_number, u8 last_section_number, u32 status)
 {
-       u32 res;
-       res = 0;
 }
 
 GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode)
@@ -2300,18 +2413,7 @@ GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode)
                pes->reframe = gf_m2ts_reframe_default;
                break;
        case GF_M2TS_PES_FRAMING_SKIP:
-               if (pes->data) {
-                       gf_free(pes->data);
-                       pes->data = NULL;
-               }
-               pes->data_len = 0;
-               if (pes->prev_data) {
-                       gf_free(pes->prev_data);
-                       pes->prev_data = NULL;
-               }
-               pes->prev_data_len = 0;
-               pes->pes_len = 0;
-               pes->reframe = NULL;
+               pes->reframe = gf_m2ts_reframe_reset;
                break;
        case GF_M2TS_PES_FRAMING_SKIP_NO_RESET:
                pes->reframe = NULL;
@@ -2353,6 +2455,7 @@ GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode)
 GF_M2TS_Demuxer *gf_m2ts_demux_new()
 {
        GF_M2TS_Demuxer *ts;
+
        GF_SAFEALLOC(ts, GF_M2TS_Demuxer);
        ts->programs = gf_list_new();
        ts->SDTs = gf_list_new();
@@ -2372,10 +2475,35 @@ GF_M2TS_Demuxer *gf_m2ts_demux_new()
        ts->requested_pids = gf_list_new();     
        ts->demux_and_play = 0;
        ts->nb_prog_pmt_received = 0;
+       ts->ChannelAppList = gf_list_new();
 
        return ts;
 }
 
+void gf_m2ts_demux_dmscc_init(GF_M2TS_Demuxer *ts){
+
+       char* temp_dir;
+       u32 length;
+       GF_Err e;
+
+       ts->dsmcc_controler = gf_list_new();
+       ts->process_dmscc = 1;
+       
+       temp_dir = gf_get_default_cache_directory();                                                                                                            
+       length = strlen(temp_dir);
+       if(temp_dir[length-1] == GF_PATH_SEPARATOR){
+               temp_dir[length-1] = 0;
+       }
+
+       ts->dsmcc_root_dir = (char*)gf_calloc(strlen(temp_dir)+strlen("CarouselData")+2,sizeof(char));
+       sprintf(ts->dsmcc_root_dir,"%s%cCarouselData",temp_dir,GF_PATH_SEPARATOR);
+       e = gf_mkdir(ts->dsmcc_root_dir);
+       if(e){
+               GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error during the creation of the directory %s \n",ts->dsmcc_root_dir));
+       }
+
+}
+
 void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts)
 {
        u32 i;
@@ -2413,6 +2541,23 @@ void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts)
        gf_dvb_mpe_shutdown(ts);
 #endif
 
+       if(gf_list_count(ts->dsmcc_controler)){
+               GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = (GF_M2TS_DSMCC_OVERLORD*)gf_list_get(ts->dsmcc_controler,0);   
+               gf_cleanup_dir(dsmcc_overlord->root_dir);
+               gf_rmdir(dsmcc_overlord->root_dir);     
+               gf_m2ts_delete_dsmcc_overlord(dsmcc_overlord);
+               if(ts->dsmcc_root_dir){
+                       gf_free(ts->dsmcc_root_dir);
+               }
+       }
+
+       while(gf_list_count(ts->ChannelAppList)){
+               GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo = (GF_M2TS_CHANNEL_APPLICATION_INFO*)gf_list_get(ts->ChannelAppList,0);
+               gf_m2ts_delete_channel_application_info(ChanAppInfo);
+               gf_list_rem(ts->ChannelAppList,0);
+       }
+       gf_list_del(ts->ChannelAppList);
+
        gf_free(ts);
 }
 
@@ -2437,8 +2582,6 @@ static u32 TSDemux_DemuxRun(void *_p)
        //u32 i;
        GF_M2TS_Demuxer *ts = _p;
 
-       ts->run_state = 1;
-
        gf_m2ts_reset_parsers(ts);
        
 #ifdef GPAC_HAS_LINUX_DVB
@@ -2483,6 +2626,11 @@ static u32 TSDemux_DemuxRun(void *_p)
                 }
         } else if (ts->file) {
                u32 pos = 0;
+
+               if (ts->segment_switch) {
+                       ts->segment_switch = 0;
+                       goto next_segment_setup;
+               } 
                if (ts->start_range && ts->duration) {
                        Double perc = ts->start_range / (1000 * ts->duration);
                        pos = (u32) (s64) (perc * ts->file_size);
@@ -2496,6 +2644,7 @@ static u32 TSDemux_DemuxRun(void *_p)
                gf_f64_seek(ts->file, pos, SEEK_SET);
 
 restart_file:
+               gf_f64_seek(ts->file, ts->start_byterange, SEEK_SET);
 
                while (ts->run_state && !feof(ts->file)) {
                        /*m2ts chunks by chunks*/
@@ -2516,9 +2665,12 @@ restart_file:
                        ts->nb_pck++;
                        //fprintf(stderr, "TS packet #%d\r", ts->nb_pck);
 
+                       if (ts->end_byterange && (gf_f64_tell(ts->file)>=ts->end_byterange))
+                               break;
+
                        //gf_sleep(0);
                        /*if asked to regulate, wait until we get a play request*/
-                       while (ts->run_state && !ts->nb_playing && ts->file_regulate) {
+                       while (ts->run_state && !ts->nb_playing && (ts->file_regulate==1)) {
                                gf_sleep(50);
                                continue;
                        }
@@ -2531,11 +2683,15 @@ restart_file:
                }
                if (feof(ts->file)) GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSDemux] EOS reached\n"));
 
+next_segment_setup:
                if (ts->run_state && ts->query_next) {
-                       const char *next_url = ts->query_next(ts->udta_query);
+                       const char *next_url = NULL;
+                       ts->query_next(ts->query_udta, 0, &next_url, &ts->start_byterange, &ts->end_byterange);
                        if (next_url) {
                                fclose(ts->file);
                                ts->file = gf_f64_open(next_url, "rb");
+                               gf_m2ts_set_segment_switch(ts);
+
                                if (ts->file) goto restart_file;
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDemux] Cannot open next file %s\n", next_url));
                        }
@@ -2837,6 +2993,12 @@ static GF_Err TSDemux_SetupFile(GF_M2TS_Demuxer *ts, char *url)
        ts->end_range = ts->start_range = 0;
        ts->nb_playing = 0;     
 
+       ts->start_byterange = ts->end_byterange = 0;
+       if (ts->query_next) {
+               ts->query_next(ts->query_udta, 1, NULL, &ts->start_byterange, &ts->end_byterange);
+       }
+
+
        return  TSDemux_DemuxPlay(ts);
 
 }
@@ -2858,7 +3020,7 @@ GF_Err TSDemux_Demux_Setup(GF_M2TS_Demuxer *ts, const char *url, Bool loop)
 
     if(loop == 1){
       ts->loop_demux = 1;
-      printf("Loop Mode activated \n");
+      GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Loop Mode activated \n"));
     }
 
        if (!strnicmp(url, "udp://", 6)
@@ -2900,6 +3062,9 @@ GF_Err TSDemux_CloseDemux(GF_M2TS_Demuxer *ts)
 
 GF_Err TSDemux_DemuxPlay(GF_M2TS_Demuxer *ts){
 
+       /*set the state variable outside the TS thread. If inside, we may get called for shutdown before the TS thread has started
+       and we would overwrite the run_state when entering the TS thread, which would make the thread run forever and the stop() wait forever*/
+       ts->run_state = 1;
        if(ts->th){
                /*start playing for tune-in*/
                return gf_th_run(ts->th, TSDemux_DemuxRun, ts);
index 00d4ce36ad8e122b3fea794ba746f30ed33f2250..3d4801f0698f0b9d0358957e313d85903410bd8a 100644 (file)
@@ -1472,7 +1472,6 @@ static GF_Err gf_text_import_texml(GF_MediaImporter *import)
                                                }
                                        }
                                        else if (!strcmp(sub->name, "sharedStyles")) {
-                                               u32 idx = 0;
                                                GF_XMLNode *style, *ftable;
                                                u32 m=0;
                                                while ((style=(GF_XMLNode*)gf_list_enum(sub->content, &m))) {
@@ -1503,7 +1502,10 @@ static GF_Err gf_text_import_texml(GF_MediaImporter *import)
                                                                if (!strcmp(css_style, "font-table")) {
                                                                        u32 z;
                                                                        styles[nb_styles].fontID = atoi(css_val);
-                                                                       for (z=0; z<td.font_count; z++) { if (td.fonts[z].fontID == styles[nb_styles].fontID) { idx = z; break; } }
+                                                                       for (z=0; z<td.font_count; z++) {
+                                                                               if (td.fonts[z].fontID == styles[nb_styles].fontID)
+                                                                                       break;
+                                                                       }
                                                                }
                                                                else if (!strcmp(css_style, "font-size")) styles[nb_styles].font_size = atoi(css_val);
                                                                else if (!strcmp(css_style, "font-style") && !strcmp(css_val, "italic")) styles[nb_styles].style_flags |= GF_TXT_STYLE_ITALIC;
@@ -1539,7 +1541,6 @@ static GF_Err gf_text_import_texml(GF_MediaImporter *import)
                                nb_descs ++;
                        } 
                        else if (!strcmp(desc->name, "sampleData")) {
-                               Bool is_utf16 = 0;
                                GF_XMLNode *sub;
                                u16 start, end;
                                u32 styleID;
@@ -1550,7 +1551,7 @@ static GF_Err gf_text_import_texml(GF_MediaImporter *import)
 
                                k=0;
                                while ((att=(GF_XMLAttribute *)gf_list_enum(desc->attributes, &k))) {
-                                       if (!strcmp(att->name, "targetEncoding") && !strcmp(att->value, "utf16")) is_utf16 = 1;
+                                       if (!strcmp(att->name, "targetEncoding") && !strcmp(att->value, "utf16")) ;//is_utf16 = 1;
                                        else if (!strcmp(att->name, "scrollDelay")) gf_isom_text_set_scroll_delay(samp, atoi(att->value) );
                                        else if (!strcmp(att->name, "highlightColor")) gf_isom_text_set_highlight_color_argb(samp, tx3g_get_color(import, att->value));
                                }
index b215c1bdc7b15568cac0b80dab8ffa86ef63d9ef..f24cca955ec120ee0a77e66940ee6cbb65c34f6b 100644 (file)
@@ -633,7 +633,7 @@ GF_Err vobsub_packetize_subpicture(FILE *fsub, u64 pts, char *data, u32 dataSize
                }
 
                /* Write packet into file */
-               if (fwrite(buf, sizeof(buf), 1, fsub) != 1) {
+               if (gf_fwrite(buf, sizeof(buf), 1, fsub) != 1) {
                        return GF_IO_ERR;
                }
 
index 85aef081e2e56e203ef79d5bc78932aac14b8032..cb3059b88d499adf546c0d17af358b6dbc861aff 100644 (file)
@@ -451,6 +451,11 @@ GF_Err gf_odf_size_descriptor(GF_Descriptor *desc, u32 *outSize)
 
 #endif /*GPAC_MINIMAL_ODF*/
        default:
+               /*don't write out l descriptors*/
+               if ((desc->tag>=GF_ODF_MUXINFO_TAG) && (desc->tag<=GF_ODF_LASER_CFG_TAG)) {
+                       *outSize = 0;
+                       return GF_OK;
+               }
                return gf_odf_size_default((GF_DefaultDescriptor *)desc, outSize);
        }
        return GF_OK;
@@ -544,6 +549,9 @@ GF_Err gf_odf_write_descriptor(GF_BitStream *bs, GF_Descriptor *desc)
                return gf_odf_write_ipmp_tool(bs, (GF_IPMP_Tool *)desc);
 #endif /*GPAC_MINIMAL_ODF*/
        default:
+               /*don't write out internal descriptors*/
+               if ((desc->tag>=GF_ODF_MUXINFO_TAG) && (desc->tag<=GF_ODF_LASER_CFG_TAG))
+                       return GF_OK;
                return gf_odf_write_default(bs, (GF_DefaultDescriptor *)desc);
        }
        return GF_OK;
index 1c7968a1fc3d4e4e7df4c93426fa5cada81fb420..16cbcbd1aaf05685dcafb1f0f08b8e3e7b47d0cf 100644 (file)
@@ -325,7 +325,6 @@ GF_EXPORT
 GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti)
 {
        Bool hasSize, cmd_stream;
-       GF_Err e;
        GF_BitStream *bs;
        GF_BIFSConfig *cfg;
 
@@ -341,7 +340,6 @@ GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti)
        bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ);
        
        cfg = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG);   
-       e = GF_OK;
        if (oti==2) {
                /*3D Mesh Coding*/
                gf_bs_read_int(bs, 1);
@@ -363,7 +361,9 @@ GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti)
                        if (gf_bs_read_int(bs, 1) == 0) break;
                }
                gf_bs_align(bs);
-               if (gf_bs_get_size(bs) != gf_bs_get_position(bs))  e = GF_NOT_SUPPORTED;
+               if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (not supported)\n"));
+               }
        } else {
                cfg->pixelMetrics = gf_bs_read_int(bs, 1);
                hasSize = gf_bs_read_int(bs, 1);
@@ -372,7 +372,8 @@ GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti)
                        cfg->pixelHeight = gf_bs_read_int(bs, 16);
                }
                gf_bs_align(bs);
-               if (gf_bs_get_size(bs) != gf_bs_get_position(bs))  e = GF_ODF_INVALID_DESCRIPTOR;
+               if (gf_bs_get_size(bs) != gf_bs_get_position(bs))
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (invalid descriptor)\n"));
        }
        gf_bs_del(bs);
        return cfg;
index 9ffd54797318f6a4d2d56a785055d5a4fd1876a7..059079b6540a8b92d4207de5f197d69fc0690873 100644 (file)
@@ -472,14 +472,14 @@ GF_Err AddDescriptorToIOD(GF_InitialObjectDescriptor *iod, GF_Descriptor *desc)
 GF_Err gf_odf_read_iod(GF_BitStream *bs, GF_InitialObjectDescriptor *iod, u32 DescSize)
 {
        GF_Err e;
-       u32 reserved, urlflag, read;
+       u32 urlflag, read;
        u32 tmp_size, nbBytes = 0;
        if (! iod) return GF_BAD_PARAM;
 
        iod->objectDescriptorID = gf_bs_read_int(bs, 10);
        urlflag = gf_bs_read_int(bs, 1);
        iod->inlineProfileFlag = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 4);
+       /*reserved = */gf_bs_read_int(bs, 4);
        nbBytes += 2;
        
        if (urlflag) {
@@ -649,13 +649,13 @@ GF_Err AddDescriptorToOD(GF_ObjectDescriptor *od, GF_Descriptor *desc)
 GF_Err gf_odf_read_od(GF_BitStream *bs, GF_ObjectDescriptor *od, u32 DescSize)
 {
        GF_Err e;
-       u32 reserved, urlflag;
+       u32 urlflag;
        u32 tmpSize, nbBytes = 0;
        if (! od) return GF_BAD_PARAM;
 
        od->objectDescriptorID = gf_bs_read_int(bs, 10);
        urlflag = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 5);
+       /*reserved = */gf_bs_read_int(bs, 5);
        nbBytes += 2;
        
        if (urlflag) {
@@ -812,14 +812,14 @@ GF_Err AddDescriptorToIsomIOD(GF_IsomInitialObjectDescriptor *iod, GF_Descriptor
 GF_Err gf_odf_read_isom_iod(GF_BitStream *bs, GF_IsomInitialObjectDescriptor *iod, u32 DescSize)
 {
        u32 nbBytes = 0, tmpSize;
-       u32 reserved, urlflag;
+       u32 urlflag;
        GF_Err e;
        if (! iod) return GF_BAD_PARAM;
 
        iod->objectDescriptorID = gf_bs_read_int(bs, 10);
        urlflag = gf_bs_read_int(bs, 1);
        iod->inlineProfileFlag = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 4);
+       /*reserved = */gf_bs_read_int(bs, 4);
        nbBytes += 2;
        
        if (urlflag) {
@@ -1000,13 +1000,13 @@ GF_Err AddDescriptorToIsomOD(GF_IsomObjectDescriptor *od, GF_Descriptor *desc)
 GF_Err gf_odf_read_isom_od(GF_BitStream *bs, GF_IsomObjectDescriptor *od, u32 DescSize)
 {
        GF_Err e;
-       u32 reserved, urlflag;
+       u32 urlflag;
        u32 tmpSize, nbBytes = 0;
        if (! od) return GF_BAD_PARAM;
 
        od->objectDescriptorID = gf_bs_read_int(bs, 10);
        urlflag = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 5);
+       /*reserved = */gf_bs_read_int(bs, 5);
        nbBytes += 2;
        
        if (urlflag) {
@@ -1119,13 +1119,13 @@ GF_Err gf_odf_del_dcd(GF_DecoderConfig *dcd)
 GF_Err gf_odf_read_dcd(GF_BitStream *bs, GF_DecoderConfig *dcd, u32 DescSize)
 {
        GF_Err e;
-       u32 reserved, tmp_size, nbBytes = 0;
+       u32 /*reserved, */tmp_size, nbBytes = 0;
        if (! dcd) return GF_BAD_PARAM;
 
        dcd->objectTypeIndication = gf_bs_read_int(bs, 8);
        dcd->streamType = gf_bs_read_int(bs, 6);
        dcd->upstream = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 1);
+       /*reserved = */gf_bs_read_int(bs, 1);
        dcd->bufferSizeDB = gf_bs_read_int(bs, 24);
        dcd->maxBitrate = gf_bs_read_int(bs, 32);
        dcd->avgBitrate = gf_bs_read_int(bs, 32);
@@ -1189,7 +1189,6 @@ GF_Err gf_odf_size_dcd(GF_DecoderConfig *dcd, u32 *outSize)
        e = gf_odf_size_descriptor_list(dcd->profileLevelIndicationIndexDescriptor, outSize);
        if (e) return e;
        return GF_OK;
-
 }
 
 GF_Err gf_odf_write_dcd(GF_BitStream *bs, GF_DecoderConfig *dcd)
@@ -1885,7 +1884,7 @@ GF_Err gf_odf_del_cc_name(GF_CC_Name *cnd)
 GF_Err gf_odf_read_cc_name(GF_BitStream *bs, GF_CC_Name *cnd, u32 DescSize)
 {
        GF_Err e;
-       u32 i, aligned, count, len, nbBytes = 0;
+       u32 i, count, len, nbBytes = 0;
        if (!cnd) return GF_BAD_PARAM;
 
        count = gf_bs_read_int(bs, 8);
@@ -1896,7 +1895,7 @@ GF_Err gf_odf_read_cc_name(GF_BitStream *bs, GF_CC_Name *cnd, u32 DescSize)
                memset(tmp , 0, sizeof(GF_ContentCreatorInfo));
                tmp->langCode = gf_bs_read_int(bs, 24);
                tmp->isUTF8 = gf_bs_read_int(bs, 1);
-               aligned = gf_bs_read_int(bs, 7);
+               /*aligned = */gf_bs_read_int(bs, 7);
                nbBytes += 4;
 
                e = OD_ReadUTF8String(bs, & tmp->contentCreatorName, tmp->isUTF8, &len);
@@ -1975,7 +1974,7 @@ GF_Err gf_odf_del_ci(GF_CIDesc *cid)
 
 GF_Err gf_odf_read_ci(GF_BitStream *bs, GF_CIDesc *cid, u32 DescSize)
 {
-       u32 reserved, nbBytes = 0;
+       u32 nbBytes = 0;
        if (! cid) return GF_BAD_PARAM;
 
        cid->compatibility = gf_bs_read_int(bs, 2);     //MUST BE NULL
@@ -1984,7 +1983,7 @@ GF_Err gf_odf_read_ci(GF_BitStream *bs, GF_CIDesc *cid, u32 DescSize)
        cid->contentTypeFlag = gf_bs_read_int(bs, 1);
        cid->contentIdentifierFlag = gf_bs_read_int(bs, 1);
        cid->protectedContent = gf_bs_read_int(bs, 1);
-       reserved = gf_bs_read_int(bs, 3);
+       /*reserved = */gf_bs_read_int(bs, 3);
        nbBytes += 1;
 
        if (cid->contentTypeFlag) {
@@ -2099,12 +2098,12 @@ GF_Err gf_odf_read_exp_text(GF_BitStream *bs, GF_ExpandedTextual *etd, u32 DescS
 {
        GF_Err e;
        u32 nbBytes = 0;
-       u32 i, aligned, len, nonLen, count;
+       u32 i, len, nonLen, count;
        if (!etd) return GF_BAD_PARAM;
 
        etd->langCode = gf_bs_read_int(bs, 24);
        etd->isUTF8 = gf_bs_read_int(bs, 1);
-       aligned = gf_bs_read_int(bs, 7);
+       /*aligned = */gf_bs_read_int(bs, 7);
        count = gf_bs_read_int(bs, 8);
        nbBytes += 5;
 
@@ -2588,12 +2587,12 @@ GF_Err gf_odf_del_kw(GF_KeyWord *kwd)
 GF_Err gf_odf_read_kw(GF_BitStream *bs, GF_KeyWord *kwd, u32 DescSize)
 {
        GF_Err e;
-       u32 nbBytes = 0, aligned, i, kwcount, len;
+       u32 nbBytes = 0, i, kwcount, len;
        if (!kwd) return GF_BAD_PARAM;
 
        kwd->languageCode = gf_bs_read_int(bs, 24);
        kwd->isUTF8 = gf_bs_read_int(bs, 1);
-       aligned = gf_bs_read_int(bs, 7);
+       /*aligned = */gf_bs_read_int(bs, 7);
        kwcount = gf_bs_read_int(bs, 8);
        nbBytes += 5;
 
@@ -2632,7 +2631,9 @@ GF_Err gf_odf_write_kw(GF_BitStream *bs, GF_KeyWord *kwd)
        if (!kwd) return GF_BAD_PARAM;
 
        e = gf_odf_size_descriptor((GF_Descriptor *)kwd, &size);
+       assert(e == GF_OK);
        e = gf_odf_write_base_descriptor(bs, kwd->tag, size);
+       assert(e == GF_OK);
 
        gf_bs_write_int(bs, kwd->languageCode, 24);
        gf_bs_write_int(bs, kwd->isUTF8, 1);
@@ -2727,7 +2728,7 @@ GF_Err gf_odf_read_oci_name(GF_BitStream *bs, GF_OCICreators *ocn, u32 DescSize)
 {
        GF_Err e;
        u32 nbBytes = 0;
-       u32 i, aligned, count, len;
+       u32 i, count, len;
        if (!ocn) return GF_BAD_PARAM;
 
        count = gf_bs_read_int(bs, 8);
@@ -2737,7 +2738,7 @@ GF_Err gf_odf_read_oci_name(GF_BitStream *bs, GF_OCICreators *ocn, u32 DescSize)
                if (! tmp) return GF_OUT_OF_MEM;
                tmp->langCode = gf_bs_read_int(bs, 24);
                tmp->isUTF8 = gf_bs_read_int(bs, 1);
-               aligned = gf_bs_read_int(bs, 7);
+               /*aligned = */gf_bs_read_int(bs, 7);
                nbBytes += 4;
                e = OD_ReadUTF8String(bs, & tmp->OCICreatorName, tmp->isUTF8, &len);
                if (e) return e;
@@ -2986,12 +2987,11 @@ GF_Err gf_odf_read_short_text(GF_BitStream *bs, GF_ShortTextual *std, u32 DescSi
 {
        GF_Err e;
        u32 nbBytes = 0, len;
-       u8 aligned;
        if (!std) return GF_BAD_PARAM;
 
        std->langCode = gf_bs_read_int(bs, 24);
        std->isUTF8 = gf_bs_read_int(bs, 1);
-       aligned = gf_bs_read_int(bs, 7);
+       /*aligned = */gf_bs_read_int(bs, 7);
        nbBytes += 4;
 
        e = OD_ReadUTF8String(bs, & std->eventName, std->isUTF8, &len);
index 2b62167f65bb343f4cc84d6c70bc94b931bd872b..a24d02b123145e7e6481826a1ca00d9d076f8393 100644 (file)
@@ -172,7 +172,9 @@ GF_Err gf_odf_write_od_remove(GF_BitStream *bs, GF_ODRemove *odRem)
        if (! odRem) return GF_BAD_PARAM;
 
        e = gf_odf_size_od_remove(odRem, &size);
+       assert(e == GF_OK);
        e = gf_odf_write_base_descriptor(bs, odRem->tag, size);
+       assert(e == GF_OK);
 
        for (i = 0; i < odRem->NbODs; i++) {
                gf_bs_write_int(bs, odRem->OD_ID[i], 10);
@@ -431,11 +433,11 @@ GF_Err gf_odf_del_esd_remove(GF_ESDRemove *ESDRemove)
 
 GF_Err gf_odf_read_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem, u32 gf_odf_size_command)
 {
-       u32 i = 0, aligned, nbBits;
+       u32 i = 0;
        if (! esdRem) return GF_BAD_PARAM;
 
        esdRem->ODID = gf_bs_read_int(bs, 10);
-       aligned = gf_bs_read_int(bs, 6);                //aligned
+       /*aligned = */gf_bs_read_int(bs, 6);            //aligned
 
        //we have gf_odf_size_command - 2 bytes left, and this is our ES_ID[1...255]
        //this works because OD commands are aligned
@@ -452,7 +454,7 @@ GF_Err gf_odf_read_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem, u32 gf_odf
                esdRem->ES_ID[i] = gf_bs_read_int(bs, 16);
        }
        //OD commands are aligned (but we should already be aligned....
-       nbBits = gf_bs_align(bs);
+       /*nbBits = */gf_bs_align(bs);
        return GF_OK;
 }
 
@@ -569,7 +571,9 @@ GF_Err gf_odf_del_ipmp_update(GF_IPMPUpdate *IPMPDUpdate)
        while (gf_list_count(IPMPDUpdate->IPMPDescList)) {
                GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(IPMPDUpdate->IPMPDescList, 0);
                e = gf_odf_delete_descriptor(tmp);
+               assert(e == GF_OK);
                e = gf_list_rem(IPMPDUpdate->IPMPDescList, 0);
+               assert(e == GF_OK);
        }
        gf_list_del(IPMPDUpdate->IPMPDescList);
        gf_free(IPMPDUpdate);
index 43634041db124f97f55865a23294e5388484c873..2050b0d2191a470a419b28d187a110a004f38e68 100644 (file)
@@ -374,7 +374,6 @@ GF_Err gf_odf_set_field(GF_Descriptor *desc, char *fieldName, char *val)
                break;
        case GF_ODF_BIFS_CFG_TAG:
        {
-               s32 notused;
                GF_BIFSConfig *bcd = (GF_BIFSConfig*)desc;
                if (!stricmp(val, "auto")) return GF_OK;
                if (!stricmp(fieldName, "nodeIDbits")) ret += sscanf(val, "%hu", &bcd->nodeIDbits);
@@ -385,8 +384,8 @@ GF_Err gf_odf_set_field(GF_Descriptor *desc, char *fieldName, char *val)
                else if (!stricmp(fieldName, "pixelMetric") || !stricmp(fieldName, "pixelMetrics")) GET_BOOL(bcd->pixelMetrics)
                else if (!stricmp(fieldName, "pixelWidth")) ret += sscanf(val, "%hu", &bcd->pixelWidth);
                else if (!stricmp(fieldName, "pixelHeight")) ret += sscanf(val, "%hu", &bcd->pixelHeight);
-               else if (!stricmp(fieldName, "use3DMeshCoding")) GET_BOOL(notused)
-               else if (!stricmp(fieldName, "usePredictiveMFField")) GET_BOOL(notused)
+               else if (!stricmp(fieldName, "use3DMeshCoding")) ret = 1;
+               else if (!stricmp(fieldName, "usePredictiveMFField")) ret = 1;
                else if (!stricmp(fieldName, "randomAccess")) GET_BOOL(bcd->randomAccess)
                else if (!stricmp(fieldName, "useNames")) GET_BOOL(bcd->useNames)
        }
@@ -397,7 +396,7 @@ GF_Err gf_odf_set_field(GF_Descriptor *desc, char *fieldName, char *val)
                if (!stricmp(fieldName, "fileName") || !stricmp(fieldName, "url")) GET_STRING(mi->file_name)
                else if (!stricmp(fieldName, "streamFormat")) GET_STRING(mi->streamFormat)
                else if (!stricmp(fieldName, "GroupID")) ret += sscanf(val, "%u", &mi->GroupID);
-               else if (!stricmp(fieldName, "startTime")) ret += sscanf(val, "%u", &mi->startTime);
+               else if (!stricmp(fieldName, "startTime")) ret += sscanf(val, "%d", &mi->startTime);
                else if (!stricmp(fieldName, "duration")) ret += sscanf(val, "%u", &mi->duration);
                else if (!stricmp(fieldName, "carouselPeriod")) {
                        ret += sscanf(val, "%u", &mi->carousel_period_plus_one);
index 3bae3d17a37be5471378b048b9f0c444f3214649..b0bd1e63be65c438c7ce71f5c07e608b643177fe 100644 (file)
@@ -165,7 +165,7 @@ static u32 GetTSbytesLen(GF_SLConfig *sl)
 GF_Err gf_odf_read_slc(GF_BitStream *bs, GF_SLConfig *sl, u32 DescSize)
 {
        GF_Err e;
-       u32 reserved, nbBytes = 0;
+       u32 nbBytes = 0;
        
        if (!sl) return GF_BAD_PARAM;
 
@@ -217,7 +217,7 @@ GF_Err gf_odf_read_slc(GF_BitStream *bs, GF_SLConfig *sl, u32 DescSize)
                sl->packetSeqNumLength = gf_bs_read_int(bs, 5);
                if (sl->packetSeqNumLength > 16) return GF_ODF_INVALID_DESCRIPTOR;
        
-               reserved = gf_bs_read_int(bs, 2);
+               /*reserved = */gf_bs_read_int(bs, 2);
                nbBytes += 15;
        }
 
@@ -262,7 +262,9 @@ GF_Err gf_odf_write_slc(GF_BitStream *bs, GF_SLConfig *sl)
        if (! sl) return GF_BAD_PARAM;
 
        e = gf_odf_size_descriptor((GF_Descriptor *)sl, &size);
+       assert(e == GF_OK);
        e = gf_odf_write_base_descriptor(bs, sl->tag, size);
+       assert(e == GF_OK);
 
        gf_bs_write_int(bs, sl->predefined, 8);
        if (! sl->predefined) {
index ab80aada9992bdb5c91fd1b1652d873b1bb35658..306eba28a551c5d1bd2d4a496278d1e27d4910f1 100644 (file)
@@ -297,14 +297,12 @@ static GF_Err gf_sm_import_specials(GF_SceneManager *ctx)
 {
        GF_Err e;
        u32 i, j, n, m, k;
-       GF_ESD *esd;
        GF_AUContext *au;
        GF_StreamContext *sc;
 
        i=0;
        while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {
                if (sc->streamType != GF_STREAM_OD) continue;
-               esd = NULL;
                j=0;
                while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) {
                        GF_ODCom *com;
@@ -348,7 +346,6 @@ static GF_Err gf_sm_import_specials(GF_SceneManager *ctx)
 static GF_ESD *gf_sm_locate_esd(GF_SceneManager *ctx, u16 ES_ID)
 {
        u32 i, j, n, m, k;
-       GF_ESD *esd;
        GF_AUContext *au;
        GF_StreamContext *sc;
        if (!ES_ID) return NULL;
@@ -356,7 +353,6 @@ static GF_ESD *gf_sm_locate_esd(GF_SceneManager *ctx, u16 ES_ID)
        i=0;
        while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {
                if (sc->streamType != GF_STREAM_OD) continue;
-               esd = NULL;
                j=0;
                while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) {
                        GF_ODCom *com;
@@ -397,7 +393,7 @@ static GF_ESD *gf_sm_locate_esd(GF_SceneManager *ctx, u16 ES_ID)
 static GF_Err gf_sm_encode_scene(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, u32 scene_type)
 {
        char *data;
-       Bool is_in_iod, delete_desc, first_scene_id;
+       Bool is_in_iod, delete_desc;
        u32 i, j, di, rate, init_offset, data_len, count, track, rap_delay, flags, rap_mode;
        u64 last_rap, dur, time_slice, avg_rate, prev_dts;
        GF_Err e;
@@ -438,7 +434,6 @@ static GF_Err gf_sm_encode_scene(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_SMEnc
 
        flags = opts ? opts->flags : 0;
        delete_desc = 0;
-       first_scene_id = 0;
        esd = NULL;
 
 
@@ -585,15 +580,6 @@ force_scene_rap:
                if (sc && sc->timeScale) esd->slConfig->timestampResolution = sc->timeScale;
                if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = 1000;
 
-               /*force scene dependencies (we cannot encode in 2 different scene contexts)*/
-               if (!esd->dependsOnESID) {
-                       if (!first_scene_id) {
-                               esd->dependsOnESID = 0;
-                               first_scene_id = esd->ESID;
-                       } else {
-                               esd->dependsOnESID = first_scene_id;
-                       }
-               }
                if (!esd->decoderConfig) esd->decoderConfig = (GF_DecoderConfig*)gf_odf_desc_new(GF_ODF_DCD_TAG);
                esd->decoderConfig->streamType = GF_STREAM_SCENE;
 
@@ -1046,6 +1032,21 @@ static GF_Err gf_sm_encode_od(GF_SceneManager *ctx, GF_ISOFile *mp4, char *media
                                                GF_ESD *imp_esd;
                                                m=0;
                                                while ((imp_esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &m))) {
+                                                       /*do not import scene and OD streams*/
+                                                       if (imp_esd->decoderConfig) {
+                                                               switch (imp_esd->decoderConfig->streamType) {
+                                                               case GF_STREAM_SCENE:
+                                                                       /*import AFX streams, but not others*/
+                                                                       if (imp_esd->decoderConfig->objectTypeIndication==GPAC_OTI_SCENE_AFX) 
+                                                                               break;
+                                                                       continue;
+                                                               case GF_STREAM_OD:
+                                                                       continue;
+                                                               default:
+                                                                       break;
+                                                               }
+                                                       }
+
                                                        switch (imp_esd->tag) {
                                                        case GF_ODF_ESD_TAG:
                                                                e = gf_sm_import_stream(ctx, mp4, imp_esd, au->timing_sec, mediaSource, au->flags & GF_SM_AU_RAP);
index d991a14fd1d6b3185bc8e6c17acafa075eb243e0..de85f89d0b516f6772bd504eefffc301874fc851 100644 (file)
 #include <gpac/nodes_x3d.h>
 /*for key codes...*/
 #include <gpac/user.h>
+#include <gpac/base_coding.h>
+#include <gpac/network.h>
+
+
+void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName)
+{
+       u32 data_size = 0;
+       char *data = NULL;
+       char *buffer; 
+       M_BitWrapper *bw = (M_BitWrapper *)node;
+
+       if (!bw->buffer.buffer) return;
+       buffer = bw->buffer.buffer;
+       if (!strnicmp(buffer, "file://", 7)) {
+               char *url = gf_url_concatenate(fileName, buffer+7);
+               if (url) {
+                       FILE *f = fopen(url, "rb");
+                       if (f) {
+                               fseek(f, 0, SEEK_END);
+                               data_size = ftell(f);
+                               fseek(f, 0, SEEK_SET);
+                               data = gf_malloc(sizeof(char)*data_size);
+                               if (data) {
+                                       size_t s = fread(data, 1, data_size, f);
+                                       assert(s == data_size);
+                               }
+                               fclose(f);
+                       }
+                       gf_free(url);
+               }
+       } else {
+               Bool base_64 = 0;
+               if (!strnicmp(buffer, "data:application/octet-string", 29)) {
+                       char *sep = strchr(bw->buffer.buffer, ',');
+                       base_64 = strstr(bw->buffer.buffer, ";base64") ? 1 : 0;
+                       if (sep) buffer = sep+1;
+               }
+                       
+               if (base_64) {
+                       data_size = 2*strlen(buffer);
+                       data = (char*)gf_malloc(sizeof(char)*data_size);
+                       if (data) 
+                               data_size = gf_base64_decode(buffer, strlen(buffer), data, data_size);
+               } else {
+                       u32 i, c;
+                       char s[3];
+                       data_size = strlen(buffer) / 3;
+                       data = (char*)gf_malloc(sizeof(char) * data_size);
+                       if (data) {
+                               s[2] = 0;
+                               for (i=0; i<data_size; i++) {
+                                       s[0] = buffer[3*i+1];
+                                       s[1] = buffer[3*i+2];
+                                       sscanf(s, "%02X", &c);
+                                       data[i] = (unsigned char) c;
+                               }
+                       }
+               }
+       }
+       gf_free(bw->buffer.buffer);
+       bw->buffer.buffer = NULL;
+       bw->buffer_len = 0;
+       if (data) {
+               bw->buffer.buffer = data;
+               bw->buffer_len = data_size;
+       }
+
+}
+
 
 #ifndef GPAC_DISABLE_LOADER_BT
 
@@ -63,7 +132,7 @@ typedef struct
        GF_Err last_error;
        u32 line;
 
-       Bool done;
+       Bool done, in_com;
        u32 is_wrl;
        /*0: no unicode, 1: UTF-16BE, 2: UTF-16LE*/
        u32 unicode_type;
@@ -112,7 +181,7 @@ GF_Node *gf_bt_peek_node(GF_BTParser *parser, char *defID);
 static GF_Err gf_bt_report(GF_BTParser *parser, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[2048];
                va_list args;
                va_start(args, format);
@@ -454,7 +523,7 @@ char *gf_bt_get_next(GF_BTParser *parser, Bool point_break)
        return parser->cur_buffer;
 }
 
-char *gf_bt_get_string(GF_BTParser *parser)
+char *gf_bt_get_string(GF_BTParser *parser, u8 string_delim)
 {
        char *res;
        s32 i, size;
@@ -473,22 +542,23 @@ char *gf_bt_get_string(GF_BTParser *parser)
                if (gzeof(parser->gz_in)) return NULL;
                gf_bt_check_line(parser);
        }
+       if (!string_delim) string_delim = '"';
 
        i=0;
        while (1) {
-               if (parser->line_buffer[parser->line_pos] == '\"')
+               if (parser->line_buffer[parser->line_pos] == string_delim)
                        if ( !parser->line_pos || (parser->line_buffer[parser->line_pos-1] != '\\') ) break;
 
                BT_STR_CHECK_ALLOC
 
                if ((parser->line_buffer[parser->line_pos]=='/') && (parser->line_buffer[parser->line_pos+1]=='/') && (parser->line_buffer[parser->line_pos-1]!=':') ) {
                        /*this looks like a comment*/
-                       if (!strstr(&parser->line_buffer[parser->line_pos], "\"")) {
+                       if (!strchr(&parser->line_buffer[parser->line_pos], string_delim)) {
                                gf_bt_check_line(parser);
                                continue;
                        }
                }
-               if ((parser->line_buffer[parser->line_pos] != '\\') || (parser->line_buffer[parser->line_pos+1] != '"')) {
+               if ((parser->line_buffer[parser->line_pos] != '\\') || (parser->line_buffer[parser->line_pos+1] != string_delim)) {
                        /*handle UTF-8 - WARNING: if parser is in unicode string is already utf8 multibyte chars*/
                        if (!parser->unicode_type && parser->line_buffer[parser->line_pos] & 0x80) {
                                char c = parser->line_buffer[parser->line_pos];
@@ -773,6 +843,7 @@ static void gf_bt_update_timenode(GF_BTParser *parser, GF_Node *node)
        }
 }
 
+
 void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
 {
        switch (info->fieldType) {
@@ -854,8 +925,12 @@ void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
                if (parser->last_error) return;
                break;
        case GF_SG_VRML_SFSTRING:
-               if (gf_bt_check_code(parser, '\"') || gf_bt_check_code(parser, '\'')) {
-                       char *str = gf_bt_get_string(parser);
+       {
+               u8 delim = 0;
+               if (gf_bt_check_code(parser, '\"')) delim = '\"';
+               else if (gf_bt_check_code(parser, '\'')) delim = '\'';
+               if (delim) {
+                       char *str = gf_bt_get_string(parser, delim);
                        if (!str)
                                goto err;
                        if (((SFString *)info->far_ptr)->buffer) gf_free(((SFString *)info->far_ptr)->buffer);
@@ -864,14 +939,23 @@ void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
                                ((SFString *)info->far_ptr)->buffer = str;
                        else
                                gf_free(str);
+
+                       if (n && (n->sgprivate->tag==TAG_MPEG4_BitWrapper)) {
+                               gf_sm_update_bitwrapper_buffer(n, parser->load->fileName);
+                       }
                } else {
                        goto err;
                }
+       }
                break;
        case GF_SG_VRML_SFURL:
-               if (gf_bt_check_code(parser, '\"') || gf_bt_check_code(parser, '\'')) {
+       {
+               u8 delim = 0;
+               if (gf_bt_check_code(parser, '\"')) delim = '\"';
+               else if (gf_bt_check_code(parser, '\'')) delim = '\'';
+               if (delim) {
                        SFURL *url = (SFURL *)info->far_ptr;
-                       char *str = gf_bt_get_string(parser);
+                       char *str = gf_bt_get_string(parser, delim);
                        if (!str) goto err;
                        if (url->url) gf_free(url->url);
                        url->url = NULL;
@@ -902,6 +986,7 @@ void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
                        if (parser->last_error) return;
                        ((SFURL *)info->far_ptr)->OD_ID = val;
                }
+       }
                break;
        case GF_SG_VRML_SFCOMMANDBUFFER:
        {
@@ -967,7 +1052,7 @@ void gf_bt_sffield(GF_BTParser *parser, GF_FieldInfo *info, GF_Node *n)
                if (!gf_bt_check_code(parser, '\"')) {
                        gf_bt_report(parser, GF_BAD_PARAM, "\" expected in Script");
                }
-               sc->script_text = (unsigned char*)gf_bt_get_string(parser);
+               sc->script_text = (unsigned char*)gf_bt_get_string(parser, '\"');
        }
                break;
        case GF_SG_VRML_SFATTRREF:
@@ -1336,7 +1421,7 @@ GF_Node *gf_bt_sf_node(GF_BTParser *parser, char *node_name, GF_Node *parent, ch
                                        }
                                        /*we ignore 'description' for MPEG4 sensors*/
                                        else if (!strcmp(str, "description")) {
-                                               char *str = gf_bt_get_string(parser);
+                                               char *str = gf_bt_get_string(parser, 0);
                                                gf_free(str);
                                                parser->last_error = GF_OK;
                                                continue;
@@ -1380,7 +1465,6 @@ GF_Node *gf_bt_sf_node(GF_BTParser *parser, char *node_name, GF_Node *parent, ch
 
                        if (is_script && parser->last_error) {
                                u32 eType, fType;
-                               GF_ScriptField *sf;
                                eType = 0;
                                if (!strcmp(str, "eventIn") || !strcmp(str, "inputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_IN;
                                else if (!strcmp(str, "eventOut") || !strcmp(str, "outputOnly")) eType = GF_SG_SCRIPT_TYPE_EVENT_OUT;
@@ -1397,7 +1481,7 @@ GF_Node *gf_bt_sf_node(GF_BTParser *parser, char *node_name, GF_Node *parent, ch
                                }
                                parser->last_error = GF_OK;
                                str = gf_bt_get_next(parser, 0);
-                               sf = gf_sg_script_field_new(node, eType, fType, str);
+                               gf_sg_script_field_new(node, eType, fType, str);
                                parser->last_error = gf_node_get_field_by_name(node, str, &info);
 
                                if (parser->parsing_proto && gf_bt_set_field_is(parser, &info, node)) continue;
@@ -1768,12 +1852,10 @@ next_field:
 
        if (externProto) {
                SFURL *url;
-               u32 nb_urls;
                Bool has_urls = 0;
                if (gf_bt_check_code(parser, '[')) has_urls = 1;
 
                gf_sg_vrml_mf_reset(&proto->ExternProto, GF_SG_VRML_MFURL);
-               nb_urls = 0;
                do {
                        str = gf_bt_get_next(parser, 0);
                        gf_sg_vrml_mf_append(&proto->ExternProto, GF_SG_VRML_MFURL, (void **) &url);
@@ -3173,14 +3255,17 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
 {
        char *str;
        GF_Node *node, *vrml_root_node;
-       Bool in_com, force_new_com;
+       Bool force_new_com;
        GF_Route *r;
        Bool has_id;
        char szDEFName[1000];
 
        vrml_root_node = NULL;
        has_id = 0;
-       in_com = init_com ? 0 : 1;
+       
+       if (init_com)
+               parser->in_com = 0 ;
+
        parser->cur_com = init_com;
 
        force_new_com = (parser->load->flags & GF_SM_LOAD_CONTEXT_READY) ? 1 : 0;
@@ -3202,7 +3287,8 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
                }
        }
 
-       parser->stream_id = parser->load->force_es_id;
+       if (!parser->in_com)
+               parser->stream_id = parser->load->force_es_id;
 
        /*parse all top-level items*/
        while (!parser->last_error) {
@@ -3257,7 +3343,7 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
                        is always RAP*/
                        if (!parser->au_time) parser->au_is_rap = 1;
 
-                       in_com = 1;
+                       parser->in_com = 1;
 
                        if (!gf_bt_check_code(parser, '{')) {
                                str = gf_bt_get_next(parser, 0);
@@ -3316,7 +3402,10 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
                                GF_StreamContext *prev = parser->od_es;
                                parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) parser->stream_id, GF_STREAM_OD, 0);
                                /*force new AU if stream changed*/
-                               if (parser->od_es != prev) parser->bifs_au = NULL;
+                               if (parser->od_es != prev) {
+                                       parser->bifs_au = NULL;
+                                       parser->od_au = NULL;
+                               }
                        }
                        if (!parser->od_es) parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) parser->stream_id, GF_STREAM_OD, 0);
                        if (!parser->od_au) parser->od_au = gf_sm_stream_au_new(parser->od_es, parser->au_time, 0, parser->au_is_rap);
@@ -3394,7 +3483,7 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
                /*if in command, check command end*/
                else {
                        /*check command end*/
-                       if (/*in_com && */gf_bt_check_code(parser, '}')) in_com = 0;
+                       if (/*in_com && */gf_bt_check_code(parser, '}')) parser->in_com = 0;
                        else if (strlen(str)) {
                                gf_bt_report(parser, GF_BAD_PARAM, "%s: Unknown top-level element", str);
                        }
@@ -3416,6 +3505,7 @@ GF_Err gf_bt_loader_run_intern(GF_BTParser *parser, GF_Command *init_com, Bool i
 static GF_Err gf_sm_load_bt_initialize(GF_SceneLoader *load, const char *str, Bool input_only)
 {
        u32 size;
+       char *sep;
        gzFile gzInput;
        GF_Err e;
        unsigned char BOM[5];
@@ -3474,7 +3564,13 @@ static GF_Err gf_sm_load_bt_initialize(GF_SceneLoader *load, const char *str, Bo
                if (parser->gz_in) gzseek(parser->gz_in, 3, SEEK_CUR);
        }
        parser->initialized = 1;
-
+       
+       if ( load->fileName )
+       {
+               sep = strrchr(load->fileName, '.');
+               if (sep && !strnicmp(sep, ".wrl", 4)) parser->is_wrl = 1;
+       }
+       
        if (input_only) return GF_OK;
 
        /*initalize default streams in the context*/
index 6461a1b51eb90422af0a5871999e5e79ada7a6c2..1d0c77c382b4b334253b04abfe6d71231978cb6d 100644 (file)
@@ -139,7 +139,7 @@ static void UpdateODCommand(GF_ISOFile *mp4, GF_ODCom *com)
 static void mp4_report(GF_SceneLoader *load, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[1024];
                va_list args;
                va_start(args, format);
@@ -333,7 +333,7 @@ static GF_Err gf_sm_isom_suspend(GF_SceneLoader *loader, Bool suspend)
 
 GF_Err gf_sm_load_init_isom(GF_SceneLoader *load)
 {
-       u32 i, track;
+       u32 i;
        GF_BIFSConfig *bc;
        GF_ESD *esd;
        GF_Err e;
@@ -382,8 +382,6 @@ GF_Err gf_sm_load_init_isom(GF_SceneLoader *load)
        e = GF_OK;
        GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("%s\n", scene_msg));
 
-       track = i+1;
-
        /*BIFS: update size & pixel metrics info*/
        if (esd->decoderConfig->objectTypeIndication<=2) {
                bc = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication);
index c7dd13bc4c858d9a9fe3e721887c1e32ef724a62..b84ac02b06a2bf30793bd447b76423dd5e841c7e 100644 (file)
@@ -35,7 +35,7 @@
 static GF_Err gf_qt_report(GF_SceneLoader *load, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[1024];
                va_list args;
                va_start(args, format);
@@ -51,7 +51,7 @@ static GF_Err gf_qt_report(GF_SceneLoader *load, GF_Err e, char *format, ...)
 /*import cubic QTVR to mp4*/
 GF_Err gf_sm_load_init_qt(GF_SceneLoader *load)
 {
-       u32 i, di, w, h, tk, pano_t, nb_samp;
+       u32 i, di, w, h, tk, nb_samp;
        Bool has_qtvr;
        GF_ISOSample *samp;
        GF_ISOFile *src;
@@ -72,7 +72,6 @@ GF_Err gf_sm_load_init_qt(GF_SceneLoader *load)
        if (!src) return gf_qt_report(load, GF_URL_ERROR, "Opening file %s failed", load->fileName);
 
        w = h = tk = 0;
-       pano_t = 0;
        nb_samp = 0;
 
        has_qtvr = 0;
@@ -172,7 +171,7 @@ GF_Err gf_sm_load_init_qt(GF_SceneLoader *load)
 
                samp = gf_isom_get_sample(src, tk, i+1, &di);
                img = gf_f64_open(mi->file_name, "wb");
-               fwrite(samp->data, samp->dataLength, 1, img);
+               gf_fwrite(samp->data, samp->dataLength, 1, img);
                fclose(img);
                gf_isom_sample_del(&samp);
        }
index 889b0bf8f0ba83531b5278c5ec4c814e4d13cfc3..cedbab8ac26ab63abd43f54368561dbf4a02531a 100644 (file)
@@ -129,7 +129,7 @@ typedef struct
 static GF_Err svg_report(GF_SVG_Parser *parser, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[2048];
                va_list args;
                va_start(args, format);
@@ -151,9 +151,9 @@ static void svg_progress(void *cbk, u64 done, u64 total)
 
        /*notify MediaEvent*/
        if (parser->load && parser->load->is) {
-               parser->load->is->on_media_event(parser->load->is, GF_EVENT_MEDIA_DATA_PROGRESS); 
+               parser->load->is->on_media_event(parser->load->is, GF_EVENT_MEDIA_PROGRESS); 
                if (done == total) {
-                       parser->load->is->on_media_event(parser->load->is, GF_EVENT_MEDIA_END_OF_DATA); 
+                       parser->load->is->on_media_event(parser->load->is, GF_EVENT_MEDIA_LOAD_DONE); 
                }
        }
        gf_set_progress("SVG (Dynamic Attribute List) Parsing", done, total);
@@ -357,9 +357,12 @@ static Bool svg_parse_animation(GF_SVG_Parser *parser, GF_SceneGraph *sg, SVG_De
        if (anim->resolve_stage==0) {
                /* Stage 0: parsing the animation attribute values 
                                        for that we need to resolve the target first */
+
+               /* if we don't have a target, try to get it */
                if (!anim->target) 
                        anim->target = (SVG_Element *) gf_sg_find_node_by_name(sg, anim->target_id + 1);
 
+               /* if now we have a target, create the xlink:href attribute on the animation element and set it to the found target */
                if (anim->target) {
                        XMLRI *iri;
                        gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_XLINK_ATT_href, 1, 0, &info);
@@ -444,24 +447,28 @@ static Bool svg_parse_animation(GF_SVG_Parser *parser, GF_SceneGraph *sg, SVG_De
                if (!anim->target) return 0;
 
                if (anim->to) {
+                       /* now that we have a target, if there is a to value to parse, create the attribute and parse it */
                        gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_to, 1, 0, &info);
                        gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->to, anim_value_type);
                        if (anim_value_type==XMLRI_datatype) 
                                svg_post_process_href(parser, (XMLRI*)((SMIL_AnimateValue *)info.far_ptr)->value);
                } 
                if (anim->from) {
+                       /* now that we have a target, if there is a from value to parse, create the attribute and parse it */
                        gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_from, 1, 0, &info);
                        gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->from, anim_value_type);
                        if (anim_value_type==XMLRI_datatype) 
                                svg_post_process_href(parser, (XMLRI*)((SMIL_AnimateValue *)info.far_ptr)->value);
                } 
                if (anim->by) {
+                       /* now that we have a target, if there is a by value to parse, create the attribute and parse it */
                        gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_by, 1, 0, &info);
                        gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->by, anim_value_type);
                        if (anim_value_type==XMLRI_datatype) 
                                svg_post_process_href(parser, (XMLRI*)((SMIL_AnimateValue *)info.far_ptr)->value);
                } 
                if (anim->values) {
+                       /* now that we have a target, if there is a 'values' value to parse, create the attribute and parse it */
                        gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_values, 1, 0, &info);
                        gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->values, anim_value_type);
                        if (anim_value_type==XMLRI_datatype) {
@@ -621,26 +628,36 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
        GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[SVG Parsing] Parsing node %s\n", name));
 
        *has_ns = 0;
-       /*parse all att for namespace*/
+       /*parse all att to check for namespaces, to:
+          - add the prefixed namespaces (xmlns:xxxx='...')
+          - change the namespace for this element if no prefix (xmlns='...')*/
        for (i=0; i<nb_attributes; i++) {
                GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
                if (!att->value || !strlen(att->value)) continue;
                if (!strncmp(att->name, "xmlns", 5)) {
+                       /* check if we have a prefix for this namespace */
                        char *qname = strchr(att->name, ':');
-                       if (qname) 
+                       if (qname) {
                                qname++;
-                       
+                       }
+                       /* Adds the namespace to the scene graph, either with a prefix or with NULL */
                        gf_sg_add_namespace(parser->load->scene_graph, att->value, qname);
-                       if (!qname) 
-                               parser->current_ns = gf_sg_get_namespace_code_from_name(parser->load->scene_graph, att->value);
 
+                       if (!qname) {
+                               /* Only if there was no prefix, we change the namespace for the current element */
+                               parser->current_ns = gf_sg_get_namespace_code_from_name(parser->load->scene_graph, att->value);
+                       }
+                       /* Signal that when ending this element, namespaces will have to be removed */
                        *has_ns = 1;
                }
+               /* FIXME: This should be changed to reflect that xml:id has precedence over id if both are specified with different values */
                else if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) {
                        if (!ID) ID = att->value;
                }
        }
 
+       /* CHECK: overriding the element namespace with the parent one, if given ???
+          This is wrong ??*/
        xmlns = parser->current_ns;
        if (name_space) {
                xmlns = gf_sg_get_namespace_code(parser->load->scene_graph, (char *) name_space);
@@ -661,6 +678,8 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
 #endif
        }
 
+       /* If this element has an ID, we look in the list of elements already created in advance (in case of reference) to see if it is there,
+          in which case we will reuse it*/
        has_id = 0;
        count = gf_list_count(parser->peeked_nodes);
        if (count && ID) {
@@ -676,6 +695,8 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                }
        }
 
+       /* If the element was found in the list of elements already created, we do not need to create it, we reuse it.
+          Otherwise, we create it based on the tag */
        if (!has_id) {
                /* Creates a node in the current scene graph */
                elt = (SVG_Element*)gf_node_new(parser->load->scene_graph, tag);
@@ -683,6 +704,7 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                        parser->last_error = GF_SG_UNKNOWN_NODE;
                        return NULL;
                }
+               /* CHECK: Why isn't this code in the gf_node_new call ?? */
                if (tag == TAG_DOMFullNode) {
                        GF_DOMFullNode *d = (GF_DOMFullNode *)elt;
                        d->name = gf_strdup(name);
@@ -690,10 +712,12 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                }
        }
 
+       /* We indicate that the element is used by its parent (reference counting for safe deleting) */
        gf_node_register((GF_Node *)elt, (parent ? (GF_Node *)parent->node : NULL));
+       /* We attach this element as the last child of its parent */
        if (parent && elt) gf_node_list_add_child_last( & parent->node->children, (GF_Node*)elt, & parent->last_child);
 
-
+       /* By default, all elements will need initialization for rendering, except some that will explicitly set it to 0 */
        needs_init = 1;
 
        if (gf_svg_is_animation_tag(tag)) {
@@ -722,6 +746,7 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                }
                anim->resolve_stage = 1;
        } else if ((tag == TAG_SVG_script) || (tag==TAG_SVG_handler)) {
+               /* Scripts and handlers don't render and have no initialization phase */
                needs_init = 0;
        }
 
@@ -737,6 +762,8 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                char *att_name = NULL;
                if (!att->value || !strlen(att->value)) continue;
 
+               /* first determine in which namespace is the attribute and store the result in ns, 
+               then shift the char buffer to point to the local name of the attribute*/
                ns = xmlns;
                att_name = strchr(att->name, ':');
                if (att_name) {
@@ -753,10 +780,16 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                        att_name = att->name;
                }
 
+               /* Begin of special cases of attributes */
+
+               /* CHECK: Shouldn't namespaces be checked here ? */
                if (!stricmp(att_name, "style")) {
                        gf_svg_parse_style((GF_Node *)elt, att->value);
                        continue;
                } 
+
+               /* Some attributes of the animation elements cannot be parsed (into typed values) until the type of value is known,
+                  we defer the parsing and store them temporarily as strings */
                if (anim) {
                        if (!stricmp(att_name, "to")) {
                                anim->to = gf_strdup(att->value);
@@ -780,27 +813,36 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                        }
                }
 
+               /* Special case for xlink:href attributes */
                if ((ns == GF_XMLNS_XLINK) && !stricmp(att_name, "href") ) {
+                       
                        if (gf_svg_is_animation_tag(tag)) {
+                               /* For xlink:href in animation elements, 
+                               we try to locate the target of the xlink:href to determine the type of values to be animated */
                                assert(anim);
                                anim->target_id = gf_strdup(att->value);
-                               /*may be NULL*/
+                               /*The target may be NULL, if it has not yet been parsed, we will try to resolve it later on */
                                anim->target = (SVG_Element *) gf_sg_find_node_by_name(parser->load->scene_graph, anim->target_id + 1);
                                continue;
                        } else {
+                               /* For xlink:href attribute on elements other than animation elements,
+                                  we create the attribute, parse it and try to do some special process it */
                                GF_FieldInfo info;
                                XMLRI *iri = NULL;
                                if (gf_node_get_attribute_by_tag((GF_Node *)elt, TAG_XLINK_ATT_href, 1, 0, &info)==GF_OK) {
                                        gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0);
                                        iri = info.far_ptr;
 
+                                       /* Embed script if needed or clean data URL with proper mime type */
                                        svg_process_media_href(parser, (GF_Node *)elt, iri);
-                                       
+                                       /* extract data URL and store as file */
                                        svg_post_process_href(parser, iri);
                                        continue;
                                } 
                        }
                } 
+
+               /* For the XML Event handler element, we need to defer the parsing of some attributes */
                if ((tag == TAG_SVG_handler) && (ns == GF_XMLNS_XMLEV)) {
                        if (!stricmp(att_name, "event") ) {
                                ev_event = att->value;
@@ -814,6 +856,7 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
 
                /*laser specific stuff*/
                if (ns == GF_XMLNS_LASER) { 
+                       /* CHECK: we should probably check the namespace of the attribute here */
                        if (!stricmp(att_name, "scale") ) {
                                if (gf_node_get_attribute_by_tag((GF_Node *)elt, TAG_SVG_ATT_transform, 1, 1, &info)==GF_OK) {
                                        SVG_Point pt;
@@ -834,6 +877,9 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                        } 
                }
 
+               /* For all attributes of the form 'on...', like 'onclick' we create a listener for the event on the current element, 
+                  we connect the listener to a handler that contains the code in the 'on...' attribute. */
+               /* CHECK: we should probably check the namespace of the attribute and of the element here */
                if (!strncmp(att_name, "on", 2)) {
                        u32 evtType = gf_dom_event_type_by_name(att_name + 2);
                        if (evtType != GF_EVENT_UNKNOWN) {
@@ -844,6 +890,9 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                        svg_report(parser, GF_OK, "Skipping unknown event handler %s on node %s", att->name, name);
                } 
 
+               /* end of special cases of attributes */
+
+               /* General attribute creation and parsing */
                if (gf_node_get_attribute_by_name((GF_Node *)elt, att_name, ns, 1, 0, &info)==GF_OK) {
 #ifndef SKIP_ATTS_PARSING
                        GF_Err e = gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0);
@@ -857,6 +906,7 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                                the 'xml:id'  attribute."*/
                                if (!node_name || (info.fieldIndex == TAG_XML_ATT_id)) {
                                        node_name = *(SVG_ID *)info.far_ptr;
+                                       /* Check if ID start with a digit, which is not a valid ID for a node according to XML (see http://www.w3.org/TR/xml/#id) */
                                        if (isdigit(node_name[0])) {
                                                svg_report(parser, GF_BAD_PARAM, "Invalid value %s for node %s %s", node_name, name, att->name);
                                                node_name = NULL;
@@ -869,7 +919,7 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                                case TAG_SVG_ATT_initialVisibility: 
                                case TAG_SVG_ATT_fullscreen: 
                                case TAG_SVG_ATT_requiredFonts: 
-                                       /*switch to v2*/
+                                       /*switch LASeR Configuration to v2 because these attributes are not part of v1*/
                                        svg_lsr_set_v2(parser);
                                        break;
                                }
@@ -877,15 +927,18 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
 #endif
                        continue;
                } 
+
+               /* all other attributes (??? failed to be created) should fall in this category */
                svg_report(parser, GF_OK, "Skipping attribute %s on node %s", att->name, name);
        }
 
-       /*set root BEFORE processing events in order to have it setup for script init*/
-       if ((tag == TAG_SVG_svg) && !parser->has_root)
+       /*set the root of the SVG tree BEFORE processing events in order to have it setup for script init (e.g. load events)*/
+       if ((tag == TAG_SVG_svg) && !parser->has_root) {
                svg_init_root_element(parser, elt);
+       }
 
+       /* When a handler element specifies the event attribute, an implicit listener is defined */
        if (ev_event) {
-               /* When the handler element specifies the event attribute, an implicit listener is defined */
                GF_Node *node = (GF_Node *)elt;
                SVG_Element *listener;
                u32 type;
@@ -906,22 +959,28 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
                ((XMLRI *)info.far_ptr)->target = node;
 
                if (ev_observer) {
+                       /* An observer was specified, so it needs to be used */
                        gf_node_get_attribute_by_tag((GF_Node *)listener, TAG_XMLEV_ATT_observer, 1, 0, &info);
                        gf_svg_parse_attribute((GF_Node *)elt, &info, (char*)ev_observer, 0);
                } else {
-                       /* this listener listens with the parent of the handler as the event target */
+                       /* No observer specified, this listener listens with the parent of the handler as the event target */
                        gf_node_get_attribute_by_tag((GF_Node *)listener, TAG_XMLEV_ATT_target, 1, 0, &info);
                        ((XMLRI *)info.far_ptr)->target = parent->node;
                }
+               /* if the target was found (already parsed), we are fine, otherwise we need to try to find it again, 
+                  we place the listener in the defered listener list */
                if ( ((XMLRI *)info.far_ptr)->target) 
                        gf_node_dom_listener_add(((XMLRI *)info.far_ptr)->target, (GF_Node *) listener);
                else
                        gf_list_add(parser->defered_listeners, listener);
        }
 
-       /* if the new element has an id, we try to resolve defered references */
+       /* if the new element has an id, we try to resolve defered references (including animations, href and listeners (just above)*/
        if (node_name) {
-               if (!has_id) gf_svg_parse_element_id((GF_Node *)elt, node_name, parser->command_depth ? 1 : 0);
+               if (!has_id) {
+                       /* if the element was already created before this call, we don't need to get a numerical id, we have it already */
+                       gf_svg_parse_element_id((GF_Node *)elt, node_name, parser->command_depth ? 1 : 0);
+               }
                svg_resolved_refs(parser, parser->load->scene_graph, node_name);
        }
 
@@ -942,18 +1001,22 @@ static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, c
        }
 
 #ifndef SKIP_INIT
-       if (needs_init) gf_node_init((GF_Node *)elt);
+       if (needs_init) {
+               /* For elements that need it, we initialize the rendering stack */
+               gf_node_init((GF_Node *)elt);
+       }
 #endif
 
        if (parent && elt) {
                /*mark parent element as dirty (new child added) and invalidate parent graph for progressive rendering*/
                gf_node_dirty_set((GF_Node *)parent->node, GF_SG_CHILD_DIRTY, 1);
                /*request scene redraw*/
-               if (parser->load->scene_graph->NodeCallback) 
+               if (parser->load->scene_graph->NodeCallback) {
                        parser->load->scene_graph->NodeCallback(parser->load->scene_graph->userpriv, GF_SG_CALLBACK_MODIFIED, NULL, NULL);
+               }
        }
 
-       /*register listener element*/
+       /*If we are in playback mode, we register (reference counting for safe deleting) the listener element with the element that uses it */
        if ((parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) && elt && (tag==TAG_SVG_listener)) {
                GF_FieldInfo info;
                Bool post_pone = 0;
@@ -1334,7 +1397,6 @@ static void svg_node_start(void *sax_cbck, const char *name, const char *name_sp
                        u32 time, OTI, ST, i, ts_res;
                        GF_ODUpdate *odU;
                        GF_ObjectDescriptor *od;
-                       Bool rap;
                        SVG_SAFExternalStream*st;
                        /*create a SAF stream*/
                        if (!parser->saf_es) {
@@ -1348,13 +1410,12 @@ static void svg_node_start(void *sax_cbck, const char *name, const char *name_sp
                                gf_list_add(parser->load->ctx->root_od->ESDescriptors, esd);
                        }
                        time = 0;
-                       rap = 0;
                        ts_res = 1000;
                        OTI = ST = 0;
                        for (i=0; i<nb_attributes;i++) {
                                GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
                                if (!strcmp(att->name, "time")) time = atoi(att->value);
-                               else if (!strcmp(att->name, "rap")) rap = !strcmp(att->value, "yes") ? 1 : 0;
+                               else if (!strcmp(att->name, "rap")) ;//rap = !strcmp(att->value, "yes") ? 1 : 0;
                                else if (!strcmp(att->name, "url")) url = gf_strdup(att->value); 
                                else if (!strcmp(att->name, "streamID")) ID = att->value;
                                else if (!strcmp(att->name, "objectTypeIndication")) OTI = atoi(att->value);
@@ -1592,7 +1653,9 @@ static void svg_node_start(void *sax_cbck, const char *name, const char *name_sp
 
 static void svg_node_end(void *sax_cbck, const char *name, const char *name_space)
 {
+#ifdef SKIP_UNKNOWN_NODES
        u32 ns;
+#endif
        GF_SVG_Parser *parser = (GF_SVG_Parser *)sax_cbck;
        SVG_NodeStack *top = (SVG_NodeStack *)gf_list_last(parser->node_stack);
 
@@ -1620,12 +1683,12 @@ static void svg_node_end(void *sax_cbck, const char *name, const char *name_spac
                return;
        }
        
+#ifdef SKIP_UNKNOWN_NODES
        ns = parser->current_ns;
        if (name_space) 
                ns = gf_sg_get_namespace_code(parser->load->scene_graph, (char *) name_space);  
 
        /*only remove created nodes ... */
-#ifdef SKIP_UNKNOWN_NODES
        if (gf_xml_get_element_tag(name, ns) != TAG_UndefinedNode) 
 #endif
        {
index 4275e0141d95bb8d1ab75472d6d1f37c78abc3e2..86c336bcf6b093a81c7cf37d4e793c997d97c059 100644 (file)
@@ -30,6 +30,8 @@
 #include <gpac/internal/scenegraph_dev.h>
 #include <gpac/nodes_x3d.h>
 
+void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName);
+
 #ifndef GPAC_DISABLE_LOADER_XMT
 
 
@@ -110,7 +112,7 @@ typedef struct
        u32 stream_id;
        Double au_time;
        Bool au_is_rap;
-
+       Bool in_com;
        GF_List *script_to_load;
 } GF_XMTParser;
 
@@ -137,7 +139,7 @@ typedef struct
 static GF_Err xmt_report(GF_XMTParser *parser, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[2048];
                va_list args;
                va_start(args, format);
@@ -159,7 +161,7 @@ static Bool xmt_esid_available(GF_XMTParser *parser, u16 ESID)
        XMT_ESDLink *esdl;
        i=0;
        while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
-               if (esdl->esd->ESID == ESID) return 0;
+               if (esdl->ESID == ESID) return 0;
        }
        return 1;
 }
@@ -170,7 +172,7 @@ static char *xmt_get_es_name(GF_XMTParser *parser, u16 ESID)
        XMT_ESDLink *esdl;
        i=0;
        while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
-               if (esdl->esd->ESID == ESID) return esdl->desc_name;
+               if (esdl->ESID == ESID) return esdl->desc_name;
        }
        return NULL;
 }
@@ -904,6 +906,9 @@ static u32 xmt_parse_sf_field(GF_XMTParser *parser, GF_FieldInfo *info, GF_Node
                break;
        case GF_SG_VRML_SFSTRING:
                res = xmt_parse_string(parser, info->name, (SFString*)info->far_ptr, 0, a_value); 
+               if (n && (n->sgprivate->tag==TAG_MPEG4_BitWrapper)) {
+                       gf_sm_update_bitwrapper_buffer(n, parser->load->fileName);
+               }
                break;
        case GF_SG_VRML_SFSCRIPT:
                res = xmt_parse_script(parser, info->name, (SFScript *)info->far_ptr, 0, a_value); 
@@ -1400,7 +1405,7 @@ static GF_Node *xmt_parse_element(GF_XMTParser *parser, char *name, const char *
 {
        GF_Err e;
        GF_FieldInfo info;
-       u32     tag, i, count, ID;
+       u32     tag, i, ID;
        Bool register_def = 0;
        Bool is_script = 0;
        GF_Node *node;
@@ -1642,7 +1647,6 @@ static GF_Node *xmt_parse_element(GF_XMTParser *parser, char *name, const char *
                                ID = 0;
                                register_def = 0;
                                tag = 0;
-                               count = 0;
                        }
                }
        } else {
@@ -1971,10 +1975,11 @@ static void xmt_parse_command(GF_XMTParser *parser, const char *name, const GF_X
                parser->state = XMT_STATE_ELEMENTS;
                return;
        }
-
-       parser->stream_id = parser->load->force_es_id;
+       if (!parser->in_com)
+               parser->stream_id = parser->load->force_es_id;
 
        if (!strcmp(name, "par")) {
+               parser->in_com = 1;
                for (i=0; i<nb_attributes; i++) {
                        GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
                        if (!att->value || !strlen(att->value)) continue;
@@ -2416,7 +2421,7 @@ static void xmt_parse_command(GF_XMTParser *parser, const char *name, const GF_X
                else if (!strcmp(name, "IPMP_DescriptorRemove")) tag = GF_ODF_IPMP_REMOVE_TAG;
 
                stream = gf_sm_stream_find(parser->load->ctx, (u16) stream_id);
-               if (!stream || (stream->streamType!=GF_STREAM_OD)) stream_id = parser->base_od_id;
+               if (stream && (stream->streamType!=GF_STREAM_OD)) stream_id = parser->base_od_id;
                parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) stream_id, GF_STREAM_OD, 0);
                parser->od_au = gf_sm_stream_au_new(parser->od_es, 0, au_time, au_is_rap);
                parser->od_command = gf_odf_com_new(tag);
@@ -2682,6 +2687,10 @@ static void xmt_node_end(void *sax_cbck, const char *name, const char *name_spac
                                parser->od_command = NULL;
                        }
 
+                       else if (!strcmp(name, "par"))
+                               parser->in_com = 1;
+
+
                }
                else if (parser->state == XMT_STATE_BODY_END) {
                        /*end XMT-A*/
@@ -2964,9 +2973,15 @@ static GF_Err xmt_restore_context(GF_SceneLoader *load)
                switch (sc->streamType) {
                case GF_STREAM_SCENE:
                case GF_STREAM_PRIVATE_SCENE:
-                       if (!parser->scene_es) parser->scene_es = sc; break;
-               case GF_STREAM_OD: if (!parser->od_es) parser->od_es = sc; break;
-               default: break;
+                       if (!parser->scene_es) 
+                               parser->scene_es = sc; 
+                       break;
+               case GF_STREAM_OD: 
+                       if (!parser->od_es) 
+                               parser->od_es = sc; 
+                       break;
+               default: 
+                       break;
                }
        }
        /*scene creation - pick up a size*/
index 37a41d78efe44d012c0584085c4adf7be43d1314..4f69376d735baa9dfa7d146649c29d441c0df317 100644 (file)
@@ -29,6 +29,7 @@
 #include <gpac/nodes_x3d.h>
 #include <gpac/nodes_svg.h>
 #include <gpac/events.h>
+#include <gpac/base_coding.h>
 
 #ifndef __SYMBIAN32__
 #include <wchar.h>
@@ -491,7 +492,7 @@ static void scene_dump_vrml_route_id(GF_SceneDumper *sdump, u32 routeID, char *r
 }
 
 
-static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Bool is_mf)
+static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Bool is_mf, GF_Node *node)
 {
        switch (type) {
        case GF_SG_VRML_SFBOOL:
@@ -601,6 +602,22 @@ static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Boo
                }
                /*dump in unicode*/
                str = ((SFString *)ptr)->buffer;
+
+               if (node && (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper)) {
+                       u32 bufsize = 50+ ((M_BitWrapper*)node)->buffer_len * 2;
+                       str = gf_malloc(sizeof(char)* bufsize);
+                       if (str) {
+                               s32 res;
+                               strcpy(str, "data:application/octet-string;base64,");
+                               res = gf_base64_encode(((M_BitWrapper*)node)->buffer.buffer, ((M_BitWrapper*)node)->buffer_len, str+37, bufsize-37);
+                               if (res<0) {
+                                       gf_free(str);
+                                       str = NULL;
+                               } else {
+                                       str[res+37] = 0;
+                               }
+                       }
+               }
                if (str && str[0]) {
                        if (sdump->XMLDump) {
                                scene_dump_utf_string(sdump, 1, str);
@@ -614,6 +631,9 @@ static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Boo
                                }
                        }
                }
+               if (node && (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper)) {
+                       if (str) gf_free(str);
+               }
 
                if (sdump->XMLDump) {
                        if (is_mf) fprintf(sdump->trace, sdump->X3DDump ? "\"" : "&quot;");
@@ -681,7 +701,7 @@ static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Boo
 }
 
 
-static void gf_dump_vrml_simple_field(GF_SceneDumper *sdump, GF_FieldInfo field)
+static void gf_dump_vrml_simple_field(GF_SceneDumper *sdump, GF_FieldInfo field, GF_Node *parent)
 {
        GenMFField *mffield;
        u32 i, sf_type;
@@ -710,7 +730,7 @@ static void gf_dump_vrml_simple_field(GF_SceneDumper *sdump, GF_FieldInfo field)
        }
        if (gf_sg_vrml_is_sf_field(field.fieldType)) {
                if (sdump->XMLDump) StartAttribute(sdump, "value");
-               gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0);
+               gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, parent);
                if (sdump->XMLDump) EndAttribute(sdump);
        } else {
                mffield = (GenMFField *) field.far_ptr;
@@ -726,7 +746,7 @@ static void gf_dump_vrml_simple_field(GF_SceneDumper *sdump, GF_FieldInfo field)
                        if (i) fprintf(sdump->trace, " ");
                        gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
                        /*this is to cope with single MFString which shall appear as SF in XMT*/
-                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1);
+                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1, parent);
                }
                if (!sdump->XMLDump) {
                        fprintf(sdump->trace, "]");
@@ -851,7 +871,7 @@ static void gf_dump_vrml_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInf
 
        if (gf_sg_vrml_is_sf_field(field.fieldType)) {
                StartAttribute(sdump, field.name);
-               gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0);
+               gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
                EndAttribute(sdump);
        } else {
                mffield = (GenMFField *) field.far_ptr;
@@ -876,7 +896,7 @@ static void gf_dump_vrml_field(GF_SceneDumper *sdump, GF_Node *node, GF_FieldInf
                for (i=0; i<mffield->count; i++) {
                        if (i) fprintf(sdump->trace, " ");
                        gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
-                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1);
+                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, 1, node);
                }
                if (!sdump->XMLDump) fprintf(sdump->trace, "]");
                
@@ -1020,7 +1040,7 @@ static void gf_dump_vrml_dyn_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fiel
                                        } else {
                                                fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
                                        }
-                                       gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0);
+                                       gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
                                        if (has_sublist)
                                                fprintf(sdump->trace, "\">\n");
                                        else
@@ -1036,7 +1056,7 @@ static void gf_dump_vrml_dyn_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fiel
                                if (field.fieldType == GF_SG_VRML_SFNODE) {
                                        gf_dump_vrml_node(sdump, field.far_ptr ? *(GF_Node **)field.far_ptr : NULL, 0, NULL);
                                } else {
-                                       gf_dump_vrml_simple_field(sdump, field);
+                                       gf_dump_vrml_simple_field(sdump, field, node);
                                }
                        }
                        fprintf(sdump->trace, "\n");
@@ -1066,7 +1086,7 @@ static void gf_dump_vrml_dyn_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fiel
                                                if (i) fprintf(sdump->trace, " ");
                                                if (field.fieldType != GF_SG_VRML_MFNODE) {
                                                        gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
-                                                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0);
+                                                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
                                                }
                                        }
                                }
@@ -1107,7 +1127,7 @@ static void gf_dump_vrml_dyn_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fiel
                                                if (i) fprintf(sdump->trace, " ");
                                                if (field.fieldType != GF_SG_VRML_MFNODE) {
                                                        gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
-                                                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0);
+                                                       gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
                                                }
                                        }
                                        if (has_sublist)
@@ -1148,7 +1168,7 @@ static void gf_dump_vrml_proto_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fi
                        } else {
                                fprintf(sdump->trace, " %s=\"", GetXMTFieldTypeValueName(field.fieldType));
                        }
-                       gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0);
+                       gf_dump_vrml_sffield(sdump, field.fieldType, field.far_ptr, 0, node);
                        fprintf(sdump->trace, "\"/>\n");
                }
        } else {
@@ -1179,7 +1199,7 @@ static void gf_dump_vrml_proto_field(GF_SceneDumper *sdump, GF_Node *node, GF_Fi
                                        if (i) fprintf(sdump->trace, " ");
                                        if (field.fieldType != GF_SG_VRML_MFNODE) {
                                                gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, &slot_ptr, i);
-                                               gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0);
+                                               gf_dump_vrml_sffield(sdump, sf_type, slot_ptr, (mffield->count>1) ? 1 : 0, node);
                                        }
                                }
                                fprintf(sdump->trace, "\"/>\n");
@@ -1630,7 +1650,7 @@ static GF_Err DumpMultipleIndexedReplace(GF_SceneDumper *sdump, GF_Command *com)
                } else {
                        fprintf(sdump->trace, "%d BY ", inf->pos);
                }
-               gf_dump_vrml_simple_field(sdump, field);
+               gf_dump_vrml_simple_field(sdump, field, com->node);
                if (sdump->XMLDump) {
                        fprintf(sdump->trace, "/>");
                } else {
@@ -1669,7 +1689,7 @@ static GF_Err DumpMultipleReplace(GF_SceneDumper *sdump, GF_Command *com)
                        DUMP_IND(sdump);
                        if (gf_sg_vrml_get_sf_type(info.fieldType) != GF_SG_VRML_SFNODE) {
                                fprintf(sdump->trace, "<repField atField=\"%s\" ", info.name);
-                               gf_dump_vrml_simple_field(sdump, info);
+                               gf_dump_vrml_simple_field(sdump, info, com->node);
                                fprintf(sdump->trace, "/>\n");
                        } else {
                                fprintf(sdump->trace, "<repField>");
@@ -1834,7 +1854,7 @@ static GF_Err DumpIndexInsert(GF_SceneDumper *sdump, GF_Command *com)
                fprintf(sdump->trace, "\n");
        } else {
                sffield.far_ptr = inf->field_ptr;
-               gf_dump_vrml_simple_field(sdump, sffield);
+               gf_dump_vrml_simple_field(sdump, sffield, com->node);
                if (sdump->XMLDump) fprintf(sdump->trace, "/>");
                fprintf(sdump->trace, "\n");
        }
@@ -2006,7 +2026,7 @@ static GF_Err DumpFieldReplace(GF_SceneDumper *sdump, GF_Command *com)
                break;
        default:
                field.far_ptr = inf->field_ptr;
-               gf_dump_vrml_simple_field(sdump, field);
+               gf_dump_vrml_simple_field(sdump, field, com->node);
                if (sdump->XMLDump) fprintf(sdump->trace, "/>");
                fprintf(sdump->trace, "\n");
        }
@@ -2060,7 +2080,7 @@ static GF_Err DumpIndexReplace(GF_SceneDumper *sdump, GF_Command *com)
        } else {
                field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
                field.far_ptr = inf->field_ptr;
-               gf_dump_vrml_simple_field(sdump, field);
+               gf_dump_vrml_simple_field(sdump, field, com->node);
                fprintf(sdump->trace, sdump->XMLDump ? "/>\n" : "\n");
        }
        return GF_OK;
@@ -2189,7 +2209,7 @@ static GF_Err DumpXReplace(GF_SceneDumper *sdump, GF_Command *com)
                gf_dump_vrml_node(sdump, inf->new_node, 0, NULL);
                fprintf(sdump->trace, (sdump->XMLDump) ? "</Replace>\n" : "\n");
        } else {
-               gf_dump_vrml_simple_field(sdump, field);
+               gf_dump_vrml_simple_field(sdump, field, com->node);
                fprintf(sdump->trace, sdump->XMLDump ? "/>\n" : "\n");
        }
        return GF_OK;
@@ -2297,7 +2317,7 @@ static GF_Err DumpProtos(GF_SceneDumper *sdump, GF_List *protoList)
                        fprintf(sdump->trace, "<ProtoDeclare name=\"%s\" protoID=\"%d\"", proto->Name, proto->ID);
                        if (proto->ExternProto.count) {
                                fprintf(sdump->trace, " locations=\"");
-                               gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0);
+                               gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0, NULL);
                                fprintf(sdump->trace, "\"");
                        }
                        fprintf(sdump->trace, ">\n");
@@ -2369,7 +2389,7 @@ static GF_Err DumpProtos(GF_SceneDumper *sdump, GF_List *protoList)
                if (proto->ExternProto.count) {
                        if (!sdump->XMLDump) {
                                fprintf(sdump->trace, " \"");
-                               gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0);
+                               gf_dump_vrml_sffield(sdump, GF_SG_VRML_SFURL, &proto->ExternProto.vals[0], 0, NULL);
                                fprintf(sdump->trace, "\"\n\n");
                        } else {
                                fprintf(sdump->trace, "</ProtoDeclare>\n");
@@ -2710,6 +2730,10 @@ GF_Err gf_sm_dump_command_list(GF_SceneDumper *sdump, GF_List *comList, u32 inde
                                EndElement(sdump, "Scene", 1);
                                sdump->indent--;
                                EndElement(sdump, "Replace", 1);
+                       } else {
+                               DUMP_IND(sdump);
+                               fprintf(sdump->trace, "\nAT 0 {\n");
+                               sdump->indent++;
                        }
                }
 #endif
@@ -2813,6 +2837,7 @@ GF_Err gf_sm_dump_command_list(GF_SceneDumper *sdump, GF_List *comList, u32 inde
        }
 
        if (remain && !sdump->XMLDump) {
+               sdump->indent--;
                DUMP_IND(sdump);
                fprintf(sdump->trace, "}\n");
        }
@@ -2836,7 +2861,6 @@ void gf_dump_svg_element(GF_SceneDumper *sdump, GF_Node *n, GF_Node *parent, Boo
        GF_ChildNodeItem *list;
        char attName[100], *attValue, attID[100];
        u32 i, count, nID;
-       Bool needs_cr;
        SVG_Element *svg = (SVG_Element *)n;
        GF_FieldInfo info;
        SVGAttribute *att;
@@ -2994,7 +3018,6 @@ void gf_dump_svg_element(GF_SceneDumper *sdump, GF_Node *n, GF_Node *parent, Boo
        }
 
        if (tag==TAG_SVG_text || tag==TAG_SVG_textArea) sdump->in_text = 1;
-       needs_cr = 1;
        sdump->indent++;
        list = svg->children;
        while (list) {
@@ -3281,6 +3304,7 @@ GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, u32 dump_mode)
                }
                if (dumper->dump_mode==GF_SM_DUMP_SVG) break;
        }
+       first_bifs = (num_scene==1) ? 1 : 0;
        num_scene = (num_scene>1) ? 1 : 0;
        num_od = (num_od>1) ? 1 : 0;
 
@@ -3307,7 +3331,6 @@ GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, u32 dump_mode)
 
        time = dumper->LSRDump ? -1 : 0;
        first_par = 0;
-       first_bifs = 1;
 
        while (gf_list_count(sample_list)) {
                GF_AUContext *au = (GF_AUContext*)gf_list_get(sample_list, 0);
@@ -3361,7 +3384,7 @@ GF_Err gf_sm_dump(GF_SceneManager *ctx, char *rad_name, u32 dump_mode)
                                } else {
                                        fprintf(dumper->trace, " </par>\n");
                                }
-                               fprintf(dumper->trace, " <par begin=\"%g\" atES_ID=\"es%d\">\n", au->timing_sec, au->owner->ESID);
+                               fprintf(dumper->trace, " <par begin=\"%g\" atES_ID=\"es%d\" isRAP=\"%s\">\n", au->timing_sec, au->owner->ESID, (au->flags & GF_SM_AU_RAP) ? "yes" : "no");
                        } else if (au->timing_sec>time) {
                                if (!first_par) {
                                        first_par = 1;
index 30b4d237fe8b46edf47ccca6ff81ef009f0a4701..3147182c245b9b5563e6ca85f6fda2ddfed5517c 100644 (file)
@@ -72,7 +72,6 @@ struct __tag_scene_engine
 #ifndef GPAC_DISABLE_BIFS_ENC
 static GF_Err gf_sm_setup_bifsenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF_ESD *esd)
 {
-       GF_Err e;
        char *data;
        u32 data_len;
        u32     nbb;
@@ -81,7 +80,6 @@ static GF_Err gf_sm_setup_bifsenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF
 
        if (!esd->decoderConfig || (esd->decoderConfig->streamType != GF_STREAM_SCENE)) return GF_BAD_PARAM;
 
-       e = GF_OK;
        if (!seng->bifsenc)
                seng->bifsenc = gf_bifs_encoder_new(seng->ctx->scene_graph);
 
@@ -149,17 +147,14 @@ static GF_Err gf_sm_setup_bifsenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF
 #ifndef GPAC_DISABLE_LASER
 static GF_Err gf_sm_setup_lsrenc(GF_SceneEngine *seng, GF_StreamContext *sc, GF_ESD *esd)
 {
-       GF_Err e;
        char *data;
        u32 data_len;
        GF_LASERConfig lsr_cfg;
 
        if (!esd->decoderConfig || (esd->decoderConfig->streamType != GF_STREAM_SCENE)) return GF_BAD_PARAM;
 
-       e = GF_OK;
        seng->lsrenc = gf_laser_encoder_new(seng->ctx->scene_graph);
 
-
        /*inputctx is not properly setup, do it*/
        if (!esd->decoderConfig->decoderSpecificInfo) {
                memset(&lsr_cfg, 0, sizeof(GF_LASERConfig));
@@ -195,7 +190,7 @@ static GF_Err gf_sm_live_setup(GF_SceneEngine *seng)
        GF_StreamContext *sc;
        GF_InitialObjectDescriptor *iod;
        GF_ESD *esd;
-       u32     i, j, count;
+       u32     i, j;
 
        e = GF_OK;
 
@@ -225,7 +220,6 @@ static GF_Err gf_sm_live_setup(GF_SceneEngine *seng)
                }
        }
 
-       count = gf_list_count(seng->ctx->streams);
        i=0;
        while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) {
 
@@ -302,23 +296,22 @@ static GF_Err gf_seng_encode_dims_au(GF_SceneEngine *seng, u16 ESID, GF_List *co
        u64 fsize;
        char *buffer = NULL;
        GF_BitStream *bs = NULL;
-       u32 offset;
        u8 dims_header;
-    Bool compress_dims;
+       Bool compress_dims;
 #ifdef DUMP_DIMS_LOG_WITH_TIME
-    u32 do_dump_with_time = 1;
+       u32 do_dump_with_time = 1;
 #endif
        u32 buffer_len;
-    char *cache_dir, *dump_name;
+       char *cache_dir, *dump_name;
 
-    if (!data) return GF_BAD_PARAM;
+       if (!data) return GF_BAD_PARAM;
 
        e = GF_OK;
 
-    if (!seng->dump_path) cache_dir = "C:\\Windows\\Temp";
-    else cache_dir = seng->dump_path;
+       if (!seng->dump_path) cache_dir = gf_get_default_cache_directory();
+       else cache_dir = seng->dump_path;
 
-    dump_name = "gpac_scene_engine_dump";
+       dump_name = "gpac_scene_engine_dump";
        compress_dims = 1;
 
 #ifdef DUMP_DIMS_LOG_WITH_TIME
@@ -341,6 +334,7 @@ start:
         sprintf(rad_name, "%s%c%s-%s-%s%s", cache_dir, GF_PATH_SEPARATOR, date_str, time_str, "rap_", dump_name);
 #endif
        }
+
        dumper = gf_sm_dumper_new(seng->ctx->scene_graph, rad_name, ' ', GF_SM_DUMP_SVG);
        if (!dumper) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot create SVG dumper for %s.svg\n", rad_name)); 
@@ -436,23 +430,22 @@ start:
                GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[SceneEngine] Warning: DIMS Unit size too big !!!\n")); 
                gf_bs_write_u16(bs, 0); /* internal GPAC hack to indicate that the size is larger than 65535 */
                gf_bs_write_u32(bs, buffer_len+1);
-               offset = 6;
        } else {
                gf_bs_write_u16(bs, buffer_len+1);
-               offset = 2;
        }
        gf_bs_write_u8(bs, dims_header);
        gf_bs_write_data(bs, buffer, buffer_len);
 
        gf_free(buffer);
-    buffer = NULL;
+       buffer = NULL;
 
-    gf_bs_get_content(bs, data, size);
+       gf_bs_get_content(bs, data, size);
        gf_bs_del(bs);
 
 exit:
-    if (buffer) gf_free(buffer);
-    if (file) fclose(file);
+       if (!seng->dump_path) gf_free(cache_dir);
+       if (buffer) gf_free(buffer);
+       if (file) fclose(file);
        return e;
 }
 
@@ -642,10 +635,9 @@ GF_EXPORT
 GF_Err gf_seng_encode_from_string(GF_SceneEngine *seng, u16 ESID, Bool disable_aggregation, char *auString, gf_seng_callback callback)
 {
        GF_StreamContext *sc;
-       u32 i, count;
+       u32 i;
        GF_Err e;
        
-       count = gf_list_count(seng->ctx->streams);
        i = 0;
        while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) {
                sc->current_au_count = gf_list_count(sc->AUs);
@@ -654,11 +646,11 @@ GF_Err gf_seng_encode_from_string(GF_SceneEngine *seng, u16 ESID, Bool disable_a
        seng->loader.flags |= GF_SM_LOAD_CONTEXT_READY;
        seng->loader.force_es_id = ESID;
     
-    /* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */
-    sc = gf_list_get(seng->ctx->streams, 0);
-    if (sc->objectType == GPAC_OTI_SCENE_DIMS) {
-        gf_seng_create_new_au(sc, 0);
-    }
+       /* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */
+       sc = gf_list_get(seng->ctx->streams, 0);
+       if (sc->objectType == GPAC_OTI_SCENE_DIMS) {
+               gf_seng_create_new_au(sc, 0);
+       }
 
        e = gf_sm_load_string(&seng->loader, auString, 0);
        if (e) goto exit;
@@ -753,7 +745,7 @@ GF_Err gf_seng_encode_from_file(GF_SceneEngine *seng, u16 ESID, Bool disable_agg
 {
        GF_Err e;
        GF_StreamContext *sc;
-       u32 i, count;
+       u32 i;
        Bool dims = 0;
 
        seng->loader.fileName = auFile;
@@ -761,18 +753,17 @@ GF_Err gf_seng_encode_from_file(GF_SceneEngine *seng, u16 ESID, Bool disable_agg
        seng->loader.force_es_id = ESID;
 
        sc = NULL;
-       count = gf_list_count(seng->ctx->streams);
        i=0;
        while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) {
                sc->current_au_count = gf_list_count(sc->AUs);
                sc->disable_aggregation = disable_aggregation;
        }
-    /* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */
-    sc = gf_list_get(seng->ctx->streams, 0);
-    if (sc->objectType == GPAC_OTI_SCENE_DIMS) {
+       /* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */
+       sc = gf_list_get(seng->ctx->streams, 0);
+       if (sc->objectType == GPAC_OTI_SCENE_DIMS) {
                dims = 1;
-        gf_seng_create_new_au(sc, 0);
-    }
+               gf_seng_create_new_au(sc, 0);
+       }
        seng->loader.flags |= GF_SM_LOAD_CONTEXT_READY;
 
        if (dims) {
index 2f041e0d9f1282fc6b5bfcccd71ebd06532232cf..9cc2752e0a4e61dd09c65c9334f0af174b375272 100644 (file)
@@ -388,7 +388,6 @@ GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID)
        for (i=0; i<stream_count; i++) {
                GF_AUContext *carousel_au;
                GF_List *carousel_commands;
-               Bool self_carousel;
                GF_StreamContext *aggregate_on_stream;
                GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i);
                if (ESID && (sc->ESID!=ESID)) continue;
@@ -396,11 +395,9 @@ GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID)
                /*locate the AU in which our commands will be aggregated*/
                carousel_au = NULL;
                carousel_commands = NULL;
-               self_carousel = 0;
                aggregate_on_stream = sc->aggregate_on_esid ? gf_sm_get_stream(ctx, sc->aggregate_on_esid) : NULL;
                if (aggregate_on_stream==sc) {
                        carousel_commands = gf_list_new();
-                       self_carousel = 1;
                } else if (aggregate_on_stream) {
                        if (!gf_list_count(aggregate_on_stream->AUs)) {
                                carousel_au = gf_sm_stream_au_new(aggregate_on_stream, 0, 0, 1);
@@ -415,17 +412,14 @@ GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID)
 #ifndef GPAC_DISABLE_VRML
                if (sc->streamType == GF_STREAM_SCENE) {
                        Bool has_modif = 0;
-                       Bool first_au=1;
                        /*we check for each stream if it is a base stream (SceneReplace ...) - several streams may carry RAPs if inline nodes are used*/
                        Bool base_stream_found = 0;
-                       u32 first_au_com_count = 0;
 
                        /*in DIMS we use an empty initial AU with no commands to signal the RAP*/
             if (sc->objectType == GPAC_OTI_SCENE_DIMS) base_stream_found = 1;
 
                        /*apply all commands - this will also apply the SceneReplace*/
                        while (gf_list_count(sc->AUs)) {
-                               Bool first_com=1;
                                u32 count;
                                au = (GF_AUContext *) gf_list_get(sc->AUs, 0);
                                gf_list_rem(sc->AUs, 0);
@@ -433,12 +427,10 @@ GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID)
                                /*AU not aggregated*/
                                if (au->flags & GF_SM_AU_NOT_AGGREGATED) {
                                        gf_sm_au_del(sc, au);
-                                       first_au=0;
                                        continue;
                                }
 
                                count = gf_list_count(au->commands);
-                               if (first_au && (au->flags & GF_SM_AU_CAROUSEL) ) first_au_com_count = count;
 
                                for (j=0; j<count; j++) {
                                        u32 store=0;
@@ -516,10 +508,8 @@ GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID)
                                                e = gf_sg_command_apply(ctx->scene_graph, com, 0);
                                                break;
                                        }
-                                       first_com=0;
                                }
                                gf_sm_au_del(sc, au);
-                               first_au=0;
                        }
 
                        /*and recreate scene replace*/
index a939f423f3954b0ef4d4c3a1c5fa5c44c96154f0..da983b8148fd6d0f9d334e967471878c42dec1cd 100644 (file)
@@ -1994,8 +1994,6 @@ Bool swf_bifs_action(SWFReader *read, SWFAction *act)
        GF_List *dst;
        MFURL url;
        SFURL sfurl;
-       MFString str;
-       SFString sfstr;
        Bool bval;
        GF_Node *n;
        Double time;
@@ -2026,11 +2024,7 @@ Bool swf_bifs_action(SWFReader *read, SWFAction *act)
                sfurl.OD_ID = 0; sfurl.url = act->url;
                url.count = 1; url.vals = &sfurl;
                s2b_set_field(read, dst, n, "url", -1, GF_SG_VRML_MFURL, &url, 0);
-
-               sfstr.buffer = act->target;
-               str.count = 1; str.vals = &act->target;
                s2b_set_field(read, dst, n, "parameter", -1, GF_SG_VRML_MFSTRING, &url, 0);
-               
                bval = 1;
                s2b_set_field(read, dst, n, "activate", -1, GF_SG_VRML_SFBOOL, &bval, 0);
                break;
index ce9e9727a47d50e88839cae590b8317ab32e0e49..8bebbb7232fe7eae0472ec079fea4c03460b3677 100644 (file)
@@ -1228,7 +1228,7 @@ static GF_Err swf_place_obj(SWFReader *read, u32 revision)
 {
        GF_Err e;
        u32 shape_id;
-       u32 ID, bitsize, ratio;
+       u32 ID, bitsize;
        u32 clip_depth;
        GF_Matrix2D mat;
        GF_ColorMatrix cmat;
@@ -1289,7 +1289,7 @@ static GF_Err swf_place_obj(SWFReader *read, u32 revision)
                        swf_get_colormatrix(read, &cmat);
                        swf_align(read);
                }
-               if (has_ratio) ratio = swf_get_16(read);
+               if (has_ratio) /*ratio = */swf_get_16(read);
                if (has_clip) clip_depth = swf_get_16(read);
 
                if (has_name) {
@@ -1816,7 +1816,7 @@ static GF_Err swf_def_sound(SWFReader *read)
                        u32 toread = read->size - tot_size;
                        if (toread>alloc_size) toread = alloc_size;
                        swf_read_data(read, frame, toread);
-                       fwrite(frame, sizeof(char)*toread, 1, snd->output);
+                       gf_fwrite(frame, sizeof(char)*toread, 1, snd->output);
                        tot_size += toread;
                }
 
@@ -1900,8 +1900,6 @@ static GF_Err swf_start_sound(SWFReader *read)
 static GF_Err swf_soundstream_hdr(SWFReader *read)
 {
        char szName[1024];
-       u8 rec_mix;
-       u32 samplesperframe;
        SWFSound *snd;
 
        if (read->sound_stream) {
@@ -1911,7 +1909,7 @@ static GF_Err swf_soundstream_hdr(SWFReader *read)
        
        GF_SAFEALLOC(snd, SWFSound);
 
-       rec_mix = swf_read_int(read, 8);
+       /*rec_mix = */swf_read_int(read, 8);
        /*0: uncompressed, 1: ADPCM, 2: MP3*/
        snd->format = swf_read_int(read, 4);
        /*0: 5.5k, 1: 11k, 2: 2: 22k, 3: 44k*/
@@ -1921,7 +1919,7 @@ static GF_Err swf_soundstream_hdr(SWFReader *read)
        /*0: mono, 8 1: stereo*/
        snd->stereo = swf_read_int(read, 1);
        /*samplesperframe hint*/
-       samplesperframe = swf_read_int(read, 16);
+       swf_read_int(read, 16);
 
        switch (snd->format) {
        /*raw PCM*/
@@ -1959,14 +1957,14 @@ static GF_Err swf_soundstream_block(SWFReader *read)
        return swf_func_skip(read);
 #else
        unsigned char bytes[4];
-       u32 hdr, alloc_size, size, tot_size, samplesPerFrame, delay;
+       u32 hdr, alloc_size, size, tot_size, samplesPerFrame;
        char *frame;
 
        /*note we're doing only MP3*/
        if (!read->sound_stream) return swf_func_skip(read);
 
        samplesPerFrame = swf_get_16(read);
-       delay = swf_get_16(read);
+       /*delay = */swf_get_16(read);
 
        if (!read->sound_stream->is_setup) {
 
@@ -2004,8 +2002,8 @@ static GF_Err swf_soundstream_block(SWFReader *read)
                if (tot_size + size >= read->size) size = read->size - tot_size;
 
                swf_read_data(read, frame, size-4);
-               fwrite(bytes, sizeof(char)*4, 1, read->sound_stream->output);
-               fwrite(frame, sizeof(char)*(size-4), 1, read->sound_stream->output);
+               gf_fwrite(bytes, sizeof(char)*4, 1, read->sound_stream->output);
+               gf_fwrite(frame, sizeof(char)*(size-4), 1, read->sound_stream->output);
                if (tot_size + size >= read->size) break;
                tot_size += size;
        }
@@ -2061,7 +2059,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
 
        if (version==1 && read->jpeg_hdr_size) {
                /*remove JPEG EOI*/
-               fwrite(read->jpeg_hdr, 1, read->jpeg_hdr_size-2, file);
+               gf_fwrite(read->jpeg_hdr, 1, read->jpeg_hdr_size-2, file);
                /*remove JPEG SOI*/
                swf_get_16(read);
                size-=2;
@@ -2069,7 +2067,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
        buf = gf_malloc(sizeof(u8)*size);
        swf_read_data(read, buf, size);
        if (version==1) {
-               fwrite(buf, 1, size, file);
+               gf_fwrite(buf, 1, size, file);
        } else {
                u32 i;
                for (i=0; i<size; i++) {
@@ -2086,7 +2084,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
                        skip = 2;
                }
                if (version==2)
-                       fwrite(buf+skip, 1, size-skip, file);
+                       gf_fwrite(buf+skip, 1, size-skip, file);
        }
        if (version!=3)
                fclose(file);
@@ -2106,6 +2104,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
                raw = gf_malloc(sizeof(char)*osize);
                memset(raw, 0, sizeof(char)*osize);
                e = gf_img_jpeg_dec(buf+skip, size-skip, &w, &h, &pf, raw, &osize, 4);
+               assert(e == GF_OK);
 
                /*read alpha map and decompress it*/
                if (size<AlphaPlaneSize) buf = gf_realloc(buf, sizeof(u8)*AlphaPlaneSize);
@@ -2132,14 +2131,13 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
                gf_img_png_enc(raw, w, h, h*4, GF_PIXEL_RGBA, buf, &osize);
                
                file = gf_f64_open(szName, "wb");
-               fwrite(buf, 1, osize, file);
+               gf_fwrite(buf, 1, osize, file);
                fclose(file);
                
                gf_free(raw);
        }
        gf_free(buf);
 
-
        return read->setup_image(read, ID, szName);
 }
 
@@ -2319,7 +2317,7 @@ GF_Err swf_parse_sprite(SWFReader *read)
 void swf_report(SWFReader *read, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[2048];
                va_list args;
                va_start(args, format);
@@ -2416,7 +2414,6 @@ GF_Err gf_sm_load_init_swf(GF_SceneLoader *load)
        GF_Err e;
        FILE *input;
        u8 sig[3];
-       u8 version;
 
        if (!load->ctx || !load->scene_graph || !load->fileName) return GF_BAD_PARAM;
        input = gf_f64_open(load->fileName, "rb");
@@ -2460,7 +2457,7 @@ GF_Err gf_sm_load_init_swf(GF_SceneLoader *load)
                e = GF_URL_ERROR;
                goto exit;
        }
-       version = gf_bs_read_u8(read->bs);
+       /*version = */gf_bs_read_u8(read->bs);
        read->length = swf_get_32(read);
 
        /*if compressed decompress the whole file*/
index 365ef1dc5835cf99fd839195c7ffa91aa3970169..1e70c4e4edc2648a7597e0166436cea1d1485ddf 100644 (file)
@@ -350,7 +350,6 @@ static GF_Err gf_text_import_sub_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxI
        SFString *sfstr;
        GF_CommandField *inf;
        Bool first_samp;
-       Double fps;
        char szLine[2048], szTime[30], szText[2048];
        GF_StreamContext *sc = NULL;
 
@@ -416,9 +415,6 @@ static GF_Err gf_text_import_sub_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxI
        com = NULL;
        inf = NULL;
 
-       fps = GF_IMPORT_DEFAULT_FPS;
-       if (mux->frame_rate) fps = mux->frame_rate;
-
        line = 0;
        first_samp = 1;
        while (1) {
index 6205318cea7239a9082828a03e02a5c6d8c63ae7..a435a53ecad2dc0fcf525f7da367dbac24270ee1 100644 (file)
@@ -48,7 +48,7 @@ static void gf_dom_refresh_event_filter(GF_SceneGraph *sg)
        if (sg->nb_evts_smil) sg->dom_evt_filter |= GF_DOM_EVENT_SMIL;
        if (sg->nb_evts_laser) sg->dom_evt_filter |= GF_DOM_EVENT_LASER;
        if (sg->nb_evts_svg) sg->dom_evt_filter |= GF_DOM_EVENT_SVG;
-       if (sg->nb_evts_mae) sg->dom_evt_filter |= GF_DOM_EVENT_MEDIA_ACCESS;
+       if (sg->nb_evts_media) sg->dom_evt_filter |= GF_DOM_EVENT_MEDIA;
 
        /*for each graph until top, update event filter*/
        par = sg->parent_scene;
@@ -71,7 +71,7 @@ void gf_sg_unregister_event_type(GF_SceneGraph *sg, u32 type)
        if (sg->nb_evts_laser && (type & GF_DOM_EVENT_LASER)) sg->nb_evts_laser--;
        if (sg->nb_evts_text && (type & GF_DOM_EVENT_TEXT)) sg->nb_evts_text--;
        if (sg->nb_evts_svg && (type & GF_DOM_EVENT_SVG)) sg->nb_evts_svg--;
-       if (sg->nb_evts_mae && (type & GF_DOM_EVENT_MEDIA_ACCESS)) sg->nb_evts_mae--;
+       if (sg->nb_evts_media && (type & GF_DOM_EVENT_MEDIA)) sg->nb_evts_media--;
 
        gf_dom_refresh_event_filter(sg);
 }
@@ -88,7 +88,7 @@ void gf_sg_register_event_type(GF_SceneGraph *sg, u32 type)
        if (type & GF_DOM_EVENT_SMIL) sg->nb_evts_smil++;
        if (type & GF_DOM_EVENT_LASER) sg->nb_evts_laser++;
        if (type & GF_DOM_EVENT_SVG) sg->nb_evts_svg++;
-       if (type & GF_DOM_EVENT_MEDIA_ACCESS) sg->nb_evts_mae++;
+       if (type & GF_DOM_EVENT_MEDIA) sg->nb_evts_media++;
 
        gf_dom_refresh_event_filter(sg);
 }
@@ -526,12 +526,10 @@ Bool gf_dom_event_fire(GF_Node *node, GF_DOM_Event *event)
 
 GF_DOMHandler *gf_dom_listener_build_ex(GF_Node *node, u32 event_type, u32 event_parameter, GF_Node *handler, GF_Node **out_listener)
 {
-       u32 tag;
        SVG_Element *listener;
        GF_FieldInfo info;
        GF_ChildNodeItem *last = NULL;
 
-       tag = gf_node_get_tag(node);
        listener = (SVG_Element *) gf_node_new(node->sgprivate->scenegraph, TAG_SVG_listener);
        /*don't register the listener, this will be done when adding to the node events list*/
 
index 7204ff2006631cedf09b5bff4efd4456e1d3e4d9..b0ee905bbe9b82ee3c1019a37592487321c6a681 100644 (file)
@@ -1306,7 +1306,6 @@ static JSBool dom_node_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER
 {
        u32 tag;
        GF_Node *n;
-       GF_ParentNode *par;
 
        n = dom_get_node(c, obj);
        /*note an element - we don't support property setting on document yet*/
@@ -1315,7 +1314,6 @@ static JSBool dom_node_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER
        if (!SMJS_ID_IS_INT(id)) return JS_TRUE;
 
        tag = n ? gf_node_get_tag(n) : 0;
-       par = (GF_ParentNode*)n;
 
        switch (SMJS_ID_TO_INT(id)) {
        /*"nodeValue"*/
@@ -1799,10 +1797,154 @@ exit:
        return JS_TRUE;
 }
 
+static void gf_dom_add_handler_listener(GF_Node *n, u32 evtType, char *handlerCode)
+{
+       /*check if we're modifying an existing listener*/
+       SVG_handlerElement *handler;
+       u32 i, count = gf_dom_listener_count(n);
+       for (i=0;i<count; i++) {
+               GF_FieldInfo info;
+               GF_DOMText *text;
+               GF_Node *listen = gf_dom_listener_get(n, i);
+
+               gf_node_get_attribute_by_tag(listen, TAG_XMLEV_ATT_event, 0, 0, &info);
+               if (!info.far_ptr || (((XMLEV_Event*)info.far_ptr)->type != evtType)) continue;
+
+               /* found a listener for this event, override the handler 
+               TODO: FIX this, there may be a listener/handler already set with JS, why overriding ? */
+               gf_node_get_attribute_by_tag(listen, TAG_XMLEV_ATT_handler, 0, 0, &info);
+               assert(info.far_ptr);
+               handler = (SVG_handlerElement *) ((XMLRI*)info.far_ptr)->target;
+               text = (GF_DOMText*)handler->children->node;
+               if (text->sgprivate->tag==TAG_DOMText) {
+                       if (text->textContent) gf_free(text->textContent);
+                       text->textContent = gf_strdup(handlerCode);
+               }
+               return;
+       }
+       /*nope, create a listener*/
+       handler = gf_dom_listener_build(n, evtType, 0);
+       gf_dom_add_text_node((GF_Node*)handler, gf_strdup(handlerCode));
+       return;
+}
+
+static void gf_dom_full_set_attribute(GF_DOMFullNode *node, char *attribute_name, char *attribute_content)
+{
+       GF_DOMFullAttribute *prev = NULL;
+       GF_DOMFullAttribute *att = (GF_DOMFullAttribute*)node->attributes;
+       while (att) {
+               if ((att->tag==TAG_DOM_ATT_any) && !strcmp(att->name, attribute_name)) {
+                       if (att->data) gf_free(att->data);
+                       att->data = gf_strdup(attribute_content);
+                       dom_node_changed((GF_Node *)node, 0, NULL);
+                       return;
+               }
+               prev = att;
+               att = (GF_DOMFullAttribute *) att->next;
+       }
+       /*create new att*/
+       GF_SAFEALLOC(att, GF_DOMFullAttribute);
+       att->name = gf_strdup(attribute_name);
+       att->data = gf_strdup(attribute_content);
+       if (prev) prev->next = (GF_DOMAttribute*) att;
+       else node->attributes = (GF_DOMAttribute*) att;
+       return;
+}
+
+static void gf_svg_set_attribute(GF_Node *n, char * ns, char *name, char *val)
+{
+       GF_FieldInfo info;
+       u32 anim_value_type = 0;
+       u32 ns_code = 0;
+       if (ns) {
+               ns_code = gf_sg_get_namespace_code_from_name(n->sgprivate->scenegraph, ns);
+       } else {
+               ns_code = gf_xml_get_element_namespace(n);
+       }
+
+       if (!strcmp(name, "attributeName")) {
+               if (gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_attributeName, 0, 0, &info) == GF_OK) {
+                       SMIL_AttributeName *attname = (SMIL_AttributeName *)info.far_ptr;
+
+                       /*parse the attribute name even if the target is not found, because a namespace could be specified and 
+                       only valid for the current node*/
+                       if (!attname->type) {
+                               char *sep;
+                               char *name = attname->name;
+                               sep = strchr(name, ':');
+                               if (sep) {
+                                       sep[0] = 0;
+                                       attname->type = gf_sg_get_namespace_code(n->sgprivate->scenegraph, name);
+                                       sep[0] = ':';
+                                       name = gf_strdup(sep+1);
+                                       gf_free(attname->name);
+                                       attname->name = name;
+                               }
+                       }
+               }
+       }
+
+       if ((n->sgprivate->tag == TAG_SVG_animateTransform) && (strstr(name, "from") || strstr(name, "to")) ) {
+               if (gf_node_get_attribute_by_tag((GF_Node *)n, TAG_SVG_ATT_transform_type, 1, 0, &info) != GF_OK) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_SCRIPT, ("Cannot retrieve attribute 'type' from animateTransform\n"));
+                       return;
+               }
+
+               switch(*(SVG_TransformType *) info.far_ptr) {
+               case SVG_TRANSFORM_TRANSLATE: anim_value_type = SVG_Transform_Translate_datatype; break;
+               case SVG_TRANSFORM_SCALE: anim_value_type = SVG_Transform_Scale_datatype; break;
+               case SVG_TRANSFORM_ROTATE: anim_value_type = SVG_Transform_Rotate_datatype; break;
+               case SVG_TRANSFORM_SKEWX: anim_value_type = SVG_Transform_SkewX_datatype; break;
+               case SVG_TRANSFORM_SKEWY: anim_value_type = SVG_Transform_SkewY_datatype; break;
+               case SVG_TRANSFORM_MATRIX: anim_value_type = SVG_Transform_datatype; break;
+               default:
+                       return;
+               }
+       }
+
+       if (gf_node_get_attribute_by_name(n, name, ns_code,  1, 1, &info)==GF_OK) {
+               GF_Err e;
+               if (!strcmp(name, "from") || !strcmp(name, "to") || !strcmp(name, "values") ) {
+                       GF_FieldInfo attType;
+                       SMIL_AttributeName *attname;
+                       if (gf_node_get_attribute_by_tag((GF_Node *)n, TAG_SVG_ATT_attributeName, 0, 0, &attType) != GF_OK) {
+                               GF_LOG(GF_LOG_WARNING, GF_LOG_SCRIPT, ("Cannot retrieve attribute 'attributeName'\n"));
+                               return;
+                       }
+               
+                       attname = (SMIL_AttributeName *)attType.far_ptr;
+                       if (!attname->type && attname->name) {
+                               GF_Node *anim_target = gf_smil_anim_get_target(n);
+                               if (anim_target) {
+                                       gf_node_get_attribute_by_name((GF_Node *)anim_target, attname->name, attname->type, 0, 0, &attType);
+                                       attname->type = attType.fieldType;
+                               } else {
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[DOM] Cannot find attribute 'type' on <%s> element and cannot find target of the animation to parse attribute %s\n", gf_node_get_class_name(n), attname->name));
+                               }
+                       }
+
+                       anim_value_type = attname->type;
+               }
+               e = gf_svg_parse_attribute(n, &info, val, anim_value_type);
+               if (e != GF_OK) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[DOM] Error parsing attribute\n"));
+               }
+
+               if (info.fieldType==SVG_ID_datatype) {
+                       char *idname = *(SVG_String*)info.far_ptr;
+                       gf_svg_parse_element_id(n, idname, 0);
+               }
+               if (info.fieldType==XMLRI_datatype) {
+                       gf_node_dirty_set(n, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
+               }
+               dom_node_changed(n, 0, &info);
+               return;
+       }
+}
 
 static JSBool SMJS_FUNCTION(xml_element_set_attribute)
 {
-       u32 evtType, idx;
+       u32 idx;
        char *name, *val, *ns, *_val;
        char szVal[100];
        SMJS_OBJ
@@ -1811,14 +1953,16 @@ static JSBool SMJS_FUNCTION(xml_element_set_attribute)
        if (!n) return JS_TRUE;
        if ((argc < 2)) return JS_TRUE;
 
-       if (!JSVAL_CHECK_STRING(argv[0])) return JS_TRUE;
+       if (!JSVAL_CHECK_STRING(argv[0])) 
+               return JS_TRUE;
 
        idx = 1;
        _val = name = ns = NULL;
        /*NS version*/
        if (argc==3) {
                char *sep;
-               if (!JSVAL_CHECK_STRING(argv[1])) return JS_TRUE;
+               if (!JSVAL_CHECK_STRING(argv[1])) 
+                       return JS_TRUE;
                ns = js_get_utf8(c, argv[0]);
                gf_sg_add_namespace(n->sgprivate->scenegraph, ns, NULL);
                name = SMJS_CHARS(c, argv[1]);
@@ -1848,59 +1992,21 @@ static JSBool SMJS_FUNCTION(xml_element_set_attribute)
        } else {
                goto exit;
        }
-       if (!name || !val) goto exit;
+       if (!name || !val) 
+               goto exit;
 
 
+       /* For on* attribute (e.g. onclick), we create a couple listener/handler elements on setting the attribute */
        if ((name[0]=='o') && (name[1]=='n')) {
-               evtType = gf_dom_event_type_by_name(name + 2);
+               u32 evtType = gf_dom_event_type_by_name(name + 2);
                if (evtType != GF_EVENT_UNKNOWN) {
-                       /*check if we're modifying an existing listener*/
-                       SVG_handlerElement *handler;
-                       u32 i, count = gf_dom_listener_count(n);
-                       for (i=0;i<count; i++) {
-                               GF_FieldInfo info;
-                               GF_DOMText *text;
-                               GF_Node *listen = gf_dom_listener_get(n, i);
-
-                               gf_node_get_attribute_by_tag(listen, TAG_XMLEV_ATT_event, 0, 0, &info);
-                               if (!info.far_ptr || (((XMLEV_Event*)info.far_ptr)->type != evtType)) continue;
-                               gf_node_get_attribute_by_tag(listen, TAG_XMLEV_ATT_handler, 0, 0, &info);
-                               assert(info.far_ptr);
-                               handler = (SVG_handlerElement *) ((XMLRI*)info.far_ptr)->target;
-                               text = (GF_DOMText*)handler->children->node;
-                               if (text->sgprivate->tag==TAG_DOMText) {
-                                       if (text->textContent) gf_free(text->textContent);
-                                       text->textContent = gf_strdup(val);
-                               }
-                               goto exit;
-                       }
-                       /*nope, create a listener*/
-                       handler = gf_dom_listener_build(n, evtType, 0);
-                       gf_dom_add_text_node((GF_Node*)handler, gf_strdup(val) );
+                       gf_dom_add_handler_listener(n, evtType, val);
                        goto exit;
                }
        }
 
        if (n->sgprivate->tag==TAG_DOMFullNode) {
-               GF_DOMFullAttribute *prev = NULL;
-               GF_DOMFullNode *node = (GF_DOMFullNode*)n;
-               GF_DOMFullAttribute *att = (GF_DOMFullAttribute*)node->attributes;
-               while (att) {
-                       if ((att->tag==TAG_DOM_ATT_any) && !strcmp(att->name, name)) {
-                               if (att->data) gf_free(att->data);
-                               att->data = gf_strdup(val);
-                               dom_node_changed(n, 0, NULL);
-                               goto exit;
-                       }
-                       prev = att;
-                       att = (GF_DOMFullAttribute *) att->next;
-               }
-               /*create new att*/
-               GF_SAFEALLOC(att, GF_DOMFullAttribute);
-               att->name = gf_strdup(name);
-               att->data = gf_strdup(val);
-               if (prev) prev->next = (GF_DOMAttribute*) att;
-               else node->attributes = (GF_DOMAttribute*) att;
+               gf_dom_full_set_attribute((GF_DOMFullNode*)n, name, val);
                goto exit;
        }
 
@@ -1909,80 +2015,7 @@ static JSBool SMJS_FUNCTION(xml_element_set_attribute)
        }
 
        if (n->sgprivate->tag<=GF_NODE_RANGE_LAST_SVG) {
-               GF_FieldInfo info;
-               u32 anim_value_type = 0;
-               u32 ns_code = 0;
-               if (ns) {
-                       ns_code = gf_sg_get_namespace_code_from_name(n->sgprivate->scenegraph, ns);
-               } else {
-                       ns_code = gf_xml_get_element_namespace(n);
-               }
-               if (!strcmp(name, "attributeName")) {
-                       if (gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_attributeName, 0, 0, &info) == GF_OK) {
-                               SMIL_AttributeName *attname = (SMIL_AttributeName *)info.far_ptr;
-
-                               /*parse the attribute name even if the target is not found, because a namespace could be specified and 
-                               only valid for the current node*/
-                               if (!attname->type) {
-                                       char *sep;
-                                       char *name = attname->name;
-                                       sep = strchr(name, ':');
-                                       if (sep) {
-                                               sep[0] = 0;
-                                               attname->type = gf_sg_get_namespace_code(n->sgprivate->scenegraph, name);
-                                               sep[0] = ':';
-                                               name = gf_strdup(sep+1);
-                                               gf_free(attname->name);
-                                               attname->name = name;
-                                       }
-                               }
-                       }
-               }
-
-               if ((n->sgprivate->tag == TAG_SVG_animateTransform) && (strstr(name, "from") || strstr(name, "to")) ) {
-                       if (gf_node_get_attribute_by_tag((GF_Node *)n, TAG_SVG_ATT_transform_type, 1, 0, &info) != GF_OK)
-                               goto exit;
-
-                       switch(*(SVG_TransformType *) info.far_ptr) {
-                       case SVG_TRANSFORM_TRANSLATE: anim_value_type = SVG_Transform_Translate_datatype; break;
-                       case SVG_TRANSFORM_SCALE: anim_value_type = SVG_Transform_Scale_datatype; break;
-                       case SVG_TRANSFORM_ROTATE: anim_value_type = SVG_Transform_Rotate_datatype; break;
-                       case SVG_TRANSFORM_SKEWX: anim_value_type = SVG_Transform_SkewX_datatype; break;
-                       case SVG_TRANSFORM_SKEWY: anim_value_type = SVG_Transform_SkewY_datatype; break;
-                       case SVG_TRANSFORM_MATRIX: anim_value_type = SVG_Transform_datatype; break;
-                       default:
-                               goto exit;
-                       }
-               }
-
-               if (gf_node_get_attribute_by_name(n, name, ns_code,  1, 1, &info)==GF_OK) {
-                       if (!strcmp(name, "from") || !strcmp(name, "to") || !strcmp(name, "values") ) {
-                               GF_FieldInfo attType;
-                               SMIL_AttributeName *attname;
-                               if (gf_node_get_attribute_by_tag((GF_Node *)n, TAG_SVG_ATT_attributeName, 0, 0, &attType) != GF_OK) 
-                                       goto exit;
-                       
-                               attname = (SMIL_AttributeName *)attType.far_ptr;
-                               if (!attname->type && attname->name) {
-                                       GF_Node *anim_target = gf_smil_anim_get_target(n);
-                                       gf_node_get_attribute_by_name((GF_Node *)anim_target, attname->name, attname->type, 0, 0, &attType);
-                                       attname->type = attType.fieldType;
-                               }
-
-                               anim_value_type = attname->type;
-                       }
-                       gf_svg_parse_attribute(n, &info, val, anim_value_type);
-
-                       if (info.fieldType==SVG_ID_datatype) {
-                               char *idname = *(SVG_String*)info.far_ptr;
-                               gf_svg_parse_element_id(n, idname, 0);
-                       }
-                       if (info.fieldType==XMLRI_datatype) {
-                               gf_node_dirty_set(n, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
-                       }
-                       dom_node_changed(n, 0, &info);
-                       goto exit;
-               }
+               gf_svg_set_attribute(n, ns, name, val);
        }
 exit:
        if (ns) gf_free(ns);
@@ -2027,7 +2060,6 @@ static JSBool SMJS_FUNCTION(xml_element_elements_by_tag)
 
 static JSBool SMJS_FUNCTION(xml_element_set_id)
 {
-       const char *node_name;
        u32 node_id;
        char *name;
        Bool is_id;
@@ -2047,7 +2079,7 @@ static JSBool SMJS_FUNCTION(xml_element_set_id)
                name = SMJS_CHARS(c, argv[0]);
                is_id = (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ? 1 : 0;
        }
-       node_name = gf_node_get_name_and_id(n, &node_id);
+       gf_node_get_name_and_id(n, &node_id);
        if (node_id && is_id) {
                /*we only support ONE ID per node*/
                SMJS_FREE(c, name);
@@ -2239,22 +2271,29 @@ static JSBool event_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j
                case 42:
                        *vp = INT_TO_JSVAL(evt->detail); return JS_TRUE;
 
-               /*MAE*/
+               case 52:/*loaded*/
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = INT_TO_JSVAL( evt->media_event->loaded_size);
+                       return JS_TRUE;
+               case 53:/*total*/
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = INT_TO_JSVAL( evt->media_event->total_size);
+                       return JS_TRUE;
                case 54:/*bufferLevelValid*/
-                       if (!evt->mae) return JS_TRUE;
-                       *vp = BOOLEAN_TO_JSVAL( evt->mae->bufferValid ? JS_TRUE : JS_FALSE);
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = BOOLEAN_TO_JSVAL( evt->media_event->bufferValid ? JS_TRUE : JS_FALSE);
                        return JS_TRUE;
                case 55:/*bufferLevel*/
-                       if (!evt->mae) return JS_TRUE;
-                       *vp = INT_TO_JSVAL( evt->mae->level);
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = INT_TO_JSVAL( evt->media_event->level);
                        return JS_TRUE;
                case 56:/*bufferRemainingTime*/
-                       if (!evt->mae) return JS_TRUE;
-                       *vp = JS_MAKE_DOUBLE(c, evt->mae->remaining_time);
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = JS_MAKE_DOUBLE(c, evt->media_event->remaining_time);
                        return JS_TRUE;
                case 57:/*status*/
-                       if (!evt->mae) return JS_TRUE;
-                       *vp = INT_TO_JSVAL( evt->mae->status);
+                       if (!evt->media_event) return JS_TRUE;
+                       *vp = INT_TO_JSVAL( evt->media_event->status);
                        return JS_TRUE;
 
                /*VRML ones*/
@@ -2324,8 +2363,6 @@ typedef struct
        GF_List *node_stack;
        /*dom graph*/
        GF_SceneGraph *document;
-
-       Bool use_cache;
 } XMLHTTPContext;
 
 static void xml_http_append_send_header(XMLHTTPContext *ctx, char *hdr, char *val)
@@ -2783,7 +2820,8 @@ static void xml_http_on_data(void *usr_cbk, GF_NETIO_Parameter *parameter)
                if (!strncmp(parameter->value, "application/xml", 15)
                        || !strncmp(parameter->value, "text/xml", 8)
                        || strstr(parameter->value, "+xml")
-                       || !strncmp(parameter->value, "text/plain", 10)
+                       || strstr(parameter->value, "/xml")
+//                     || !strncmp(parameter->value, "text/plain", 10)
                ) {
                        assert(!ctx->sax);
                        ctx->sax = gf_xml_sax_new(xml_http_sax_start, xml_http_sax_end, xml_http_sax_text, ctx);
@@ -2792,7 +2830,7 @@ static void xml_http_on_data(void *usr_cbk, GF_NETIO_Parameter *parameter)
                        /*mark this doc as "nomade", and let it leave until all references to it are destroyed*/
                        ctx->document->reference_count = 1;
                } else {
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[XmlHttpRequest] content type %s not supported\n", parameter->value));
+                       GF_LOG(GF_LOG_INFO, GF_LOG_SCRIPT, ("[XmlHttpRequest] content type %s - ResponseXML not supported\n", parameter->value));
                }
                return;
        case GF_NETIO_DATA_EXCHANGE:
@@ -2816,23 +2854,18 @@ static void xml_http_on_data(void *usr_cbk, GF_NETIO_Parameter *parameter)
                return;
        case GF_NETIO_DATA_TRANSFERED:
                if (ctx->sax) {
-                       if(ctx->use_cache ) {
-                               const char *filename;
-                               ctx->sax = gf_xml_sax_new(xml_http_sax_start, xml_http_sax_end, xml_http_sax_text, ctx);
-                               filename = gf_dm_sess_get_cache_name(ctx->sess);
-                               gf_xml_sax_parse_file(ctx->sax, filename, NULL);
-                       }
 #if !USE_PROGRESSIVE_SAX
-                       else {
-                               gf_xml_sax_init(ctx->sax, ctx->data);
-                       }
+                       gf_xml_sax_init(ctx->sax, ctx->data);
 #endif
                }
+               /* No return, go till the end of the function */
                break;
        case GF_NETIO_DISCONNECTED:
                return;
        case GF_NETIO_STATE_ERROR:
                ctx->ret_code = parameter->error;
+               /* No return, go till the end of the function */
+               GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[XmlHttpRequest] Download error: %s\n", gf_error_to_string(parameter->error)));
                break;
        }
 
@@ -2845,6 +2878,8 @@ static void xml_http_on_data(void *usr_cbk, GF_NETIO_Parameter *parameter)
        /*error, complete reset*/
        if (parameter->error) {
                xml_http_reset(ctx);
+       } else {
+               ctx->html_status = 200;
        }
        /*but stay in loaded mode*/
        ctx->readyState = 4;
@@ -2857,7 +2892,6 @@ static JSBool SMJS_FUNCTION(xml_http_send)
        GF_SceneGraph *scene;
        char *data = NULL;
        XMLHTTPContext *ctx;
-       GF_Err e;
        SMJS_OBJ
        SMJS_ARGS
 
@@ -2892,20 +2926,19 @@ static JSBool SMJS_FUNCTION(xml_http_send)
        ctx->data = data ? gf_strdup(data) : NULL;
        SMJS_FREE(c, data);
 
-       ctx->use_cache = 0;
        if (!strncmp(ctx->url, "http://", 7)) {
-               ctx->sess = gf_dm_sess_new(par.dnld_man, ctx->url, (ctx->use_cache ? 0 : GF_NETIO_SESSION_NOT_CACHED), xml_http_on_data, ctx, &e);
-               
+               GF_Err e;
+
+               ctx->sess = gf_dm_sess_new(par.dnld_man, ctx->url, ctx->async ? 0 : GF_NETIO_SESSION_NOT_THREADED, xml_http_on_data, ctx, &e);                  
                if (!ctx->sess) return JS_TRUE;
-       
-               /*just wait for destruction*/
-               if (!ctx->async) {
-                       while (ctx->sess) {
-                               gf_sg_lock_javascript(ctx->c, 0);
-                               gf_sleep(20);
-                               gf_sg_lock_javascript(ctx->c, 1);
-                       }
+
+               /*start our download (whether the session is threaded or not)*/
+               e = gf_dm_sess_process(ctx->sess);
+               if (e!=GF_OK) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[XmlHttpRequest] Error processing %s: %s\n", ctx->url, gf_error_to_string(e) ));
                }
+               /**/
+               if (!ctx->async && ctx->sess) gf_dm_sess_del(ctx->sess);
        } else {
                u64 fsize;
                FILE * xmlf;
@@ -3082,7 +3115,7 @@ static JSBool xml_http_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER
                /*responseXML*/
                case 3:
                        if (ctx->readyState<3) return JS_TRUE;
-                       if (ctx->data) {
+                       if (ctx->data && ctx->document) {
                                *vp = dom_document_construct(c, ctx->document);
                        } else {
                                *vp = JSVAL_VOID;
@@ -3827,7 +3860,8 @@ void dom_js_pre_destroy(JSContext *c, GF_SceneGraph *sg, GF_Node *n)
        count = gf_list_count(dom_rt->handlers);
        for (i=0; i<count; i++) {
                SVG_handlerElement *handler = (SVG_handlerElement *)gf_list_get(dom_rt->handlers, i);
-               if (handler->js_context==c) {
+               /*if same context and same document, discard handler*/
+               if ( (handler->js_context==c) && (!sg || (handler->sgprivate->scenegraph==sg)) ) {
                        /*unprotect the function*/
                        gf_js_remove_root(handler->js_context, &(handler->js_fun_val), GF_JSGC_VAL);
                        handler->js_fun_val=0;
index 621cafb36851828e938d5873767ac567a7e0c305..df72149cc1d59001efeffbed723a546df5ea6114 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /*
-       DO NOT MOFIFY - File generated on GMT Wed Jul 20 05:50:21 2011
+       DO NOT MOFIFY - File generated on GMT Tue Nov 08 09:10:57 2011
 
        BY MPEG4Gen for GPAC Version 0.4.6-DEV
 */
@@ -2776,14 +2776,14 @@ static Bool CompositeTexture2D_get_aq_info(GF_Node *n, u32 FieldIndex, u8 *QType
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 4:
                *AType = 0;
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 7:
                *AType = 0;
@@ -2969,14 +2969,14 @@ static Bool CompositeTexture3D_get_aq_info(GF_Node *n, u32 FieldIndex, u8 *QType
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 4:
                *AType = 0;
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        default:
                return 0;
@@ -30855,14 +30855,14 @@ static Bool SynthesizedTexture_get_aq_info(GF_Node *n, u32 FieldIndex, u8 *QType
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 3:
                *AType = 0;
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 5:
                *AType = 7;
@@ -32120,20 +32120,20 @@ static Bool AdvancedAudioBuffer_get_aq_info(GF_Node *n, u32 FieldIndex, u8 *QTyp
                *QType = 13;
                *QT13_bits = 16;
                *b_min = FLT2FIX(0);
-               *b_max = FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/;
+               *b_max = FIX_MAX;
                return 1;
        case 11:
                *AType = 0;
                *QType = 13;
                *QT13_bits = 17;
-               *b_min = FLT2FIX(-65536);
+               *b_min = FIX_MIN;
                *b_max = FLT2FIX( 0);
                return 1;
        case 12:
                *AType = 0;
                *QType = 13;
                *QT13_bits = 17;
-               *b_min = FLT2FIX(-65536);
+               *b_min = FIX_MIN;
                *b_max = FLT2FIX( 0);
                return 1;
        case 13:
index 4b8568f26bdbfe66d9e8b48b14bcdc8eec7ebf45..c16f05b8e5d9d41645134842be742c303ab3f65e 100644 (file)
@@ -145,12 +145,18 @@ static void gf_smil_anim_set(SMIL_Anim_RTI *rai)
        GF_FieldInfo to_info;
        SMILAnimationAttributesPointers *animp = rai->animp;
 
-       if (!animp->to || !animp->to->type) {
+       if (!animp->to) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_SMIL, 
                           ("[SMIL Animation] Animation     %s - set element without to attribute\n", 
                           gf_node_get_log_name((GF_Node *)rai->anim_elt)));
                return;
        }
+       if (!animp->to->type) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_SMIL, 
+                          ("[SMIL Animation] Animation     %s - set element with an unparsed to attribute\n", 
+                          gf_node_get_log_name((GF_Node *)rai->anim_elt)));
+               return;
+       }
 
        if (rai->change_detection_mode) {
                /* if the set has been applied, unless next animations are additive we don't need 
@@ -618,7 +624,7 @@ static void gf_smil_anim_compute_interpolation_value(SMIL_Anim_RTI *rai, Fixed n
        }
 
 #ifndef GPAC_DISABLE_LOG
-       if (0 && (gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_SMIL)) { 
+       if (0 && gf_log_tool_level_on(GF_LOG_SMIL, GF_LOG_DEBUG)) { 
                char *str;
                gf_log_lt(GF_LOG_DEBUG, GF_LOG_SMIL); 
                str = gf_svg_dump_attribute(rai->anim_elt, &rai->interpolated_value);
@@ -779,7 +785,7 @@ static void gf_smil_apply_additive(SMIL_Anim_RTI *rai)
                                                                  1);
 
 #ifndef GPAC_DISABLE_LOG
-               if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_SMIL)) { 
+               if (gf_log_tool_level_on(GF_LOG_SMIL, GF_LOG_DEBUG)) { 
                        char *str;
                        gf_log_lt(GF_LOG_DEBUG, GF_LOG_SMIL); 
                        str = gf_svg_dump_attribute((GF_Node*)rai->anim_elt, &rai->owner->presentation_value);
@@ -807,7 +813,7 @@ static void gf_smil_apply_additive(SMIL_Anim_RTI *rai)
                        
                        gf_svg_attributes_copy(&rai->owner->presentation_value, &rai->interpolated_value, 1);
 #ifndef GPAC_DISABLE_LOG
-                       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_SMIL)) { 
+                       if (gf_log_tool_level_on(GF_LOG_SMIL, GF_LOG_DEBUG)) { 
                                char *str;
                                gf_log_lt(GF_LOG_DEBUG, GF_LOG_SMIL); 
                                str = gf_svg_dump_attribute((GF_Node*)rai->anim_elt, &rai->owner->presentation_value);
@@ -904,7 +910,7 @@ static void gf_smil_anim_remove(SMIL_Timing_RTI *rti, Fixed normalized_simple_ti
                rai->anim_done = 1;
 
 #ifndef GPAC_DISABLE_LOG
-               if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_SMIL)) { 
+               if (gf_log_tool_level_on(GF_LOG_SMIL, GF_LOG_DEBUG)) { 
                        char *str;
                        gf_log_lt(GF_LOG_DEBUG, GF_LOG_SMIL); 
                        str = gf_svg_dump_attribute((GF_Node*)rai->anim_elt, &rai->owner->presentation_value);
@@ -957,7 +963,7 @@ void gf_svg_apply_animations(GF_Node *node, SVGPropertiesPointers *render_svg_pr
 #ifndef GPAC_DISABLE_LOG
        u32 time=0;
 
-       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_RTI)) { 
+       if (gf_log_tool_level_on(GF_LOG_RTI, GF_LOG_DEBUG)) { 
                time = gf_sys_clock();
        }
 #endif
@@ -1038,7 +1044,7 @@ void gf_svg_apply_animations(GF_Node *node, SVGPropertiesPointers *render_svg_pr
 
 #ifndef GPAC_DISABLE_LOG
                if (aa->presentation_value_changed) {
-                       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_SMIL)) { 
+                       if (gf_log_tool_level_on(GF_LOG_SMIL, GF_LOG_DEBUG)) { 
                                char *str;
                                gf_log_lt(GF_LOG_DEBUG, GF_LOG_SMIL); 
                                str = gf_svg_dump_attribute(node, &aa->presentation_value);
@@ -1066,7 +1072,7 @@ void gf_svg_apply_animations(GF_Node *node, SVGPropertiesPointers *render_svg_pr
        }
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= GF_LOG_DEBUG) && (gf_log_get_tools() & GF_LOG_RTI)) { 
+       if (gf_log_tool_level_on(GF_LOG_RTI, GF_LOG_DEBUG)) { 
                time_spent_in_anim += gf_sys_clock() - time;
        }
 #endif
@@ -1078,9 +1084,13 @@ GF_Node *gf_smil_anim_get_target(GF_Node *e)
        XLinkAttributesPointers *xlinkp = NULL;
        if (!gf_svg_is_animation_tag(e->sgprivate->tag)) return NULL;
        xlinkp = ((SVGTimedAnimBaseElement *)e)->xlinkp;
-       return xlinkp->href->target;
+       return (xlinkp && xlinkp->href) ? xlinkp->href->target : NULL;
 }
 
+/* Attributes from the animation elements are not easy to use during runtime, 
+   the runtime info is a set of easy to use structures. 
+   This function initializes them (interpolation values ...) 
+   Needs to be called after gf_smil_timing_init_runtime_info */
 void gf_smil_anim_init_runtime_info(GF_Node *e)
 {
        u32 i;
@@ -1097,6 +1107,7 @@ void gf_smil_anim_init_runtime_info(GF_Node *e)
        /* Filling animation structures to be independent of the SVG Element structure */
        animp = ((SVGTimedAnimBaseElement *)e)->animp;
        timingp = ((SVGTimedAnimBaseElement *)e)->timingp;
+       if (!animp || !timingp) return;
        xlinkp = ((SVGTimedAnimBaseElement *)e)->xlinkp;
 
        target = xlinkp->href->target;
@@ -1104,8 +1115,7 @@ void gf_smil_anim_init_runtime_info(GF_Node *e)
        memset(&target_attribute, 0, sizeof(GF_FieldInfo));
        if (animp->attributeName && (animp->attributeName->name || animp->attributeName->tag)) {
                /* Filling the target_attribute structure with info on the animated attribute (type, pointer to data, ...)
-               NOTE: in the mode Dynamic Allocation of Attributes, this means that the animated 
-               attribute is created with a default value, if it was not specified on the target element */
+               NOTE: the animated attribute is created with a default value, if it was not specified on the target element */
                if (animp->attributeName->tag) {
                        gf_node_get_attribute_by_tag(target, animp->attributeName->tag, 1, 1, &target_attribute);
                } else {
@@ -1421,7 +1431,8 @@ void gf_smil_anim_init_node(GF_Node *node)
        xlinkp->href = all_atts.xlink_href;
        xlinkp->type = all_atts.xlink_type;             
 
-       /*perform init of default values*/
+       /*perform init of default values
+         When the xlink:href attribute of animation is not set, the target defaults to the parent element */
        if (!xlinkp->href) {
                GF_FieldInfo info;
                gf_node_get_attribute_by_tag((GF_Node *)node, TAG_XLINK_ATT_href, 1, 0, &info);
@@ -1431,7 +1442,7 @@ void gf_smil_anim_init_node(GF_Node *node)
        }
        if (xlinkp->href->type == XMLRI_STRING) {
                if (!xlinkp->href->string) { 
-                       fprintf(stderr, "Error: IRI not initialized\n");
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_SMIL,("Error: IRI not initialized\n"));
                        return;
                } else {
                        GF_Node *n;
@@ -1446,14 +1457,21 @@ void gf_smil_anim_init_node(GF_Node *node)
                        }
                }
        } 
-       if (!xlinkp->href->target) return;
+       if (!xlinkp->href->target) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_SMIL,("Trying to initialize an animation when the target is not known\n"));
+               return;
+       }
 
        // We may not have an attribute name, when using an animateMotion element
-    if (node->sgprivate->tag != TAG_SVG_animateMotion && !all_atts.attributeName) return;
+       if (node->sgprivate->tag != TAG_SVG_animateMotion && !all_atts.attributeName) {
+               goto end_init;
+       }
 
+       /* if an attribute (to, from or by) is present but its type is not set 
+       (e.g. it could not be determined before, the target was not known), we try to get the type from the target */
        if ( (all_atts.to && (all_atts.to->type==0))
                || (all_atts.from && (all_atts.from->type==0))
-               || (all_atts.from && (all_atts.from->type==0))
+               || (all_atts.by && (all_atts.by->type==0))
        ) {
                GF_FieldInfo info;
                if (gf_node_get_attribute_by_name((GF_Node *)xlinkp->href->target, all_atts.attributeName->name, 0, 1, 1, &info)==GF_OK) {
@@ -1469,11 +1487,10 @@ void gf_smil_anim_init_node(GF_Node *node)
                                if (gf_node_get_attribute_by_tag((GF_Node *)node, tag, 0, 0, &info)==GF_OK) {
                                        SMIL_AnimateValue *attval = info.far_ptr;
                                        if (attval->type==0) {
-                                               SVG_String *string = attval->value;
+                                               SVG_String string = attval->value;
                                                attval->value = NULL;
                                                if (string) {
-                                                       gf_svg_parse_attribute((GF_Node *)node, &info, * string, anim_value_type);
-                                                       if (* string) gf_free(* string);
+                                                       gf_svg_parse_attribute((GF_Node *)node, &info, string, anim_value_type);
                                                        gf_free(string);
                                                }
                                        }
@@ -1509,7 +1526,7 @@ void gf_smil_anim_init_node(GF_Node *node)
                e->animp->rotate = NULL;
        }
        
-
+end_init:
        gf_smil_timing_init_runtime_info(node);
        gf_smil_anim_init_runtime_info(node);
        gf_smil_anim_set_anim_runtime_in_timing(node);
index 36f3f4e912629d69a55087e46790d7c7938933bd..aa525d9a58b7618c32874da3e7e6f5a21c685daf 100644 (file)
@@ -307,7 +307,8 @@ static void gf_smil_mark_modified(SMIL_Timing_RTI *rti, Bool remove)
 
 /* Attributes from the timed elements are not easy to use during runtime, 
    the runtime info is a set of easy to use structures. 
-   This function initializes them (intervals, status ...). */
+   This function initializes them (intervals, status ...) 
+   and registers the element with the scenegraph */
 GF_EXPORT
 void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
 {
@@ -332,6 +333,7 @@ void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
        e->timingp->repeatDur   = all_atts.repeatDur;
        e->timingp->restart             = all_atts.restart;
        timingp = e->timingp;
+       if (!timingp) return;
 
        if (tag == TAG_SVG_audio || tag == TAG_SVG_video) {
                /* if the dur attribute is not set, then it should be set to media 
@@ -342,14 +344,13 @@ void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
                   have a defined duration."
                TODO: Check if this should work with the animation element */
                if (!e->timingp->dur) {
-                       SVGAttribute *att = gf_xml_create_attribute((GF_Node *)e, TAG_SVG_ATT_dur);
-                       e->timingp->dur = (SMIL_Duration *)att->data;
+                       GF_FieldInfo info;
+                       gf_node_get_attribute_by_tag((GF_Node *)e, TAG_SVG_ATT_dur, 1, 0, &info);
+                       e->timingp->dur = (SMIL_Duration *)info.far_ptr;
                        e->timingp->dur->type = SMIL_DURATION_MEDIA;
                }
        }
 
-       if (!timingp) return;
-
        GF_SAFEALLOC(rti, SMIL_Timing_RTI)
        timingp->runtime = rti;
        rti->timed_elt = timed_elt;
index 2f7eaa1d0de2d85563bcb99842e9e5c21ab5f43f..a6a7802fada77a5b2d03338486697e4097ec559a 100644 (file)
@@ -122,6 +122,7 @@ static const struct dom_event_def {u32 event;  const char *name; u32 category; }
        { GF_EVENT_CPU, "cpu", GF_DOM_EVENT_LASER },
 
        /*MediaAccess events*/
+#if 0
        { GF_EVENT_MEDIA_BEGIN_SESSION_SETUP, "BeginSessionSetup", GF_DOM_EVENT_MEDIA_ACCESS },
        { GF_EVENT_MEDIA_END_SESSION_SETUP, "EndSessionSetup", GF_DOM_EVENT_MEDIA_ACCESS },
        { GF_EVENT_MEDIA_DATA_REQUEST, "DataRequest", GF_DOM_EVENT_MEDIA_ACCESS },
@@ -131,6 +132,34 @@ static const struct dom_event_def {u32 event;  const char *name; u32 category; }
        { GF_EVENT_MEDIA_END_OF_DATA, "EndOfDataReception", GF_DOM_EVENT_MEDIA_ACCESS },
        { GF_EVENT_MEDIA_STOP, "Stop", GF_DOM_EVENT_MEDIA_ACCESS },
        { GF_EVENT_MEDIA_ERROR, "Error", GF_DOM_EVENT_MEDIA_ACCESS },
+#endif
+
+       { GF_EVENT_MEDIA_SETUP_BEGIN, "setupbegin", GF_DOM_EVENT_MEDIA},
+       { GF_EVENT_MEDIA_SETUP_DONE, "setupdone", GF_DOM_EVENT_MEDIA},
+
+       { GF_EVENT_MEDIA_LOAD_START, "loadstart", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_LOAD_DONE, "loaddone", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_PROGRESS, "progress", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_SUSPEND, "suspend", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_ABORT, "abort", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_ERROR, "error", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_EMPTIED, "emptied", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_STALLED, "stalled", GF_DOM_EVENT_MEDIA },      
+       { GF_EVENT_MEDIA_LOADED_METADATA, "loadedmetadata", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_LODADED_DATA, "loadeddata", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_CANPLAY, "canplay", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_CANPLAYTHROUGH, "canplaythrough", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_PLAYING, "playing", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_WAITING, "waiting", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_SEEKING, "seeking", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_SEEKED, "seeked", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_ENDED, "ended", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_DURATION_CHANGED, "durationchanged", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_TIME_UPDATE, "timeupdate", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_PLAY, "play", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_PAUSE, "pause", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_RATECHANGE, "ratechange", GF_DOM_EVENT_MEDIA },
+       { GF_EVENT_MEDIA_VOLUME_CHANGED, "volumechange", GF_DOM_EVENT_MEDIA },
 
        /*GPAC internals*/
        { GF_EVENT_SCENE_ATTACHED, "gpac_scene_attached", GF_DOM_EVENT_DOM },
@@ -1297,6 +1326,9 @@ Bool gf_svg_parse_transformlist(GF_Matrix2D *mat, char *attribute_content)
                                GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Missing opening parenthesis in transform attribute: %s\n", attribute_content));
                 return 0;
                        }
+               } else {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Unrecognized transofrm type in attribute %s\n", attribute_content));
+            return 0;
                }
                /*for svgView parsing*/
                if (str[i] == ')') i++;
@@ -5323,7 +5355,7 @@ Bool gf_svg_attributes_equal(GF_FieldInfo *f1, GF_FieldInfo *f2)
                return 1;
        }
        default:
-               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING|GF_LOG_INTERACT, ("[SVG Attributes] comparaison for field %s of type %s not supported\n", f1->name, gf_svg_attribute_type_to_string(f1->fieldType)));
+               GF_LOG(GF_LOG_WARNING, GF_LOG_INTERACT, ("[SVG Attributes] comparaison for field %s of type %s not supported\n", f1->name, gf_svg_attribute_type_to_string(f1->fieldType)));
                return 0;
        }
 }
index c0b6b566048ebcd525e751eb5febcaed81625c95..7a1bd54f570fb3208e73b654181b67c2d06d4746 100644 (file)
@@ -65,9 +65,9 @@ jsval dom_node_get_sibling(JSContext *c, GF_Node *n, Bool is_prev, Bool elt_only
 
 
 
-#define _ScriptMessage(_sg, _e, _msg) {\
+#define _ScriptMessage(_sg, _msg) {\
                        GF_JSAPIParam par;      \
-                       par.info.e = _e;                        \
+                       par.info.e = GF_SCRIPT_INFO;                    \
                        par.info.msg = _msg;            \
                        _sg->script_action(_sg->script_action_cbck, GF_JSAPI_OP_MESSAGE, NULL, &par);\
                }
@@ -188,7 +188,7 @@ static JSBool SMJS_FUNCTION(svg_echo)
 
        if (JSVAL_IS_STRING(argv[0])) {
                char *str = SMJS_CHARS_FROM_STRING(c, JS_ValueToString(c, argv[0]) );
-               _ScriptMessage(sg, GF_SCRIPT_INFO, str);
+               _ScriptMessage(sg, str);
                SMJS_FREE(c, str);
        }
        return JS_TRUE;
@@ -320,7 +320,6 @@ static JSBool svg_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GET
        if (!SMJS_ID_IS_INT(id)) return JS_TRUE;
        prop_id = SMJS_ID_TO_INT(id);
 
-
        switch (prop_id) {
        case 0: /*id*/
        {
@@ -518,6 +517,9 @@ JSBool SMJS_FUNCTION_EXT(svg_udom_smil_time_insert, Bool is_end)
        } else {
                info.far_ptr = ((SVGTimedAnimBaseElement *)n)->timingp->begin;
        }
+       if (!info.far_ptr) {
+               return JS_FALSE;
+       }
 
 
        times = *((GF_List **)info.far_ptr);
@@ -572,6 +574,8 @@ JSBool SMJS_FUNCTION(svg_udom_smil_pause)
                gf_smil_timing_pause(n);
        } else if (gf_svg_is_timing_tag(tag)) {
                ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_PAUSE_SVG, n, NULL);
+       } else if ((tag==TAG_SVG_svg) && (n->sgprivate->scenegraph->RootNode==n)) {
+               ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_PAUSE_SVG, n, NULL);
        } else {
                return JS_TRUE;
        }
@@ -590,6 +594,49 @@ JSBool SMJS_FUNCTION(svg_udom_smil_resume)
                gf_smil_timing_resume(n);
        } else if (gf_svg_is_timing_tag(tag)) {
                ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_RESUME_SVG, n, NULL);
+       } else if ((tag==TAG_SVG_svg) && (n->sgprivate->scenegraph->RootNode==n)) {
+               ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_RESUME_SVG, n, NULL);
+       } else {
+               return JS_TRUE;
+       }
+       return JS_TRUE;
+}
+
+JSBool SMJS_FUNCTION(svg_udom_smil_restart)
+{
+       u32 tag;
+       SMJS_OBJ
+       GF_Node *n = dom_get_element(c, obj);
+
+       tag = gf_node_get_tag(n);
+       if ((tag==TAG_SVG_svg) && (n->sgprivate->scenegraph->RootNode==n)) {
+               ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_RESTART_SVG, n, NULL);
+       } else {
+               return JS_TRUE;
+       }
+       return JS_TRUE;
+}
+
+JSBool SMJS_FUNCTION(svg_udom_smil_set_speed)
+{
+       u32 tag;
+       Double speed = 1.0;
+       SMJS_OBJ
+       SMJS_ARGS
+       GF_Node *n = dom_get_element(c, obj);
+
+       if (argc && JSVAL_IS_NUMBER(argv[0]) ) {
+               jsdouble d;
+               JS_ValueToNumber(c, argv[0], &d);
+               speed = d;
+       }
+
+       tag = gf_node_get_tag(n);
+       if ((tag==TAG_SVG_svg) && (n->sgprivate->scenegraph->RootNode==n)) {
+               GF_JSAPIParam par;
+               memset(&par, 0, sizeof(GF_JSAPIParam));
+               par.val = FLT2FIX(speed);
+               ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_SET_SCENE_SPEED, n, &par);
        } else {
                return JS_TRUE;
        }
@@ -1217,7 +1264,6 @@ static JSBool SMJS_FUNCTION_EXT(svg_get_bbox, Bool get_screen)
 {
        GF_JSAPIParam par;
        SMJS_OBJ
-       SMJS_ARGS
        GF_Node *n = dom_get_element(c, obj);
        if (!n || argc) return JS_TRUE;
 
@@ -1254,7 +1300,6 @@ JSBool SMJS_FUNCTION(svg_udom_get_screen_ctm)
 {
        GF_JSAPIParam par;
        SMJS_OBJ
-       SMJS_ARGS
        GF_Node *n = dom_get_element(c, obj);
        if (!n || argc) return JS_TRUE;
 
@@ -2187,6 +2232,8 @@ static void svg_init_js_api(GF_SceneGraph *scene)
                        SMJS_FUNCTION_SPEC("endElement", svg_udom_smil_end, 0),
                        SMJS_FUNCTION_SPEC("pauseElement", svg_udom_smil_pause, 0),
                        SMJS_FUNCTION_SPEC("resumeElement", svg_udom_smil_resume, 0),
+                       SMJS_FUNCTION_SPEC("restartElement", svg_udom_smil_restart, 0),
+                       SMJS_FUNCTION_SPEC("setSpeed", svg_udom_smil_set_speed, 0),
 
                        SMJS_FUNCTION_SPEC("getTotalLength", svg_path_get_total_length, 0),
 
@@ -2557,7 +2604,7 @@ void JSScript_LoadSVG(GF_Node *node)
                if (!txt) return;
                ret = JS_EvaluateScript(svg_js->js_ctx, svg_js->global, txt->textContent, strlen(txt->textContent), 0, 0, &rval);
                if (ret==JS_FALSE) {
-                       _ScriptMessage(node->sgprivate->scenegraph, GF_SCRIPT_ERROR, "SVG: Invalid script");
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("SVG: Invalid script\n") );
                }
                gf_dom_listener_process_add(node->sgprivate->scenegraph);
        }
@@ -2601,7 +2648,7 @@ static Bool svg_script_execute_handler(GF_Node *node, GF_DOM_Event *event, GF_No
        svg_js = node->sgprivate->scenegraph->svg_js;
 
 #ifndef GPAC_DISABLE_LOG
-       if ((gf_log_get_level() >= (GF_LOG_DEBUG)) && (gf_log_get_tools() & (GF_LOG_SCRIPT))) { 
+       if (gf_log_tool_level_on(GF_LOG_SCRIPT, GF_LOG_DEBUG)) { 
                char *content, *_content = NULL;
                if (utf8_script) {
                        content = utf8_script;
@@ -2703,7 +2750,7 @@ static Bool svg_script_execute_handler(GF_Node *node, GF_DOM_Event *event, GF_No
 #endif
 
        if (ret==JS_FALSE) {
-               _ScriptMessage(node->sgprivate->scenegraph, GF_SCRIPT_ERROR, "SVG: Invalid handler textContent");
+               GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("SVG: Invalid handler textContent\n" ));
                return 0;
        }
        return 1;
index 48d1e229f9a0f36a4f967bd53f7f96e3c3bdbf31..556a2685dabc0b07a9197c6b745a1e6336d793b4 100644 (file)
@@ -92,6 +92,14 @@ void gf_svg_node_del(GF_Node *node)
        if (p->sgprivate->tag==TAG_SVG_handler) {
                GF_Node *listener = p->sgprivate->UserPrivate;
                if (listener && (listener->sgprivate->tag==TAG_SVG_listener)) {
+                       GF_FieldInfo info;
+                       if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 0, 0, &info) == GF_OK) {
+                               XMLRI *iri = (XMLRI *)info.far_ptr;
+                               if (iri->target) {
+                                       assert(iri->target==p);
+                                       iri->target = NULL;
+                               }
+                       }
                        gf_node_unregister(listener, NULL);
 //                     gf_svg_node_del(listener);
                }
@@ -222,10 +230,9 @@ void gf_svg_reset_path(SVG_PathData d)
 GF_EXPORT
 void gf_svg_path_build(GF_Path *path, GF_List *commands, GF_List *points)
 {
-       u32 i, j, command_count, points_count;
+       u32 i, j, command_count;
        SVG_Point orig, ct_orig, ct_end, end, *tmp;
        command_count = gf_list_count(commands);
-       points_count = gf_list_count(points);
        orig.x = orig.y = ct_orig.x = ct_orig.y = 0;
 
        for (i=0, j=0; i<command_count; i++) {
index d9f0ed7619734a462416ee9aa3b934fd02f0dc2a..c8eabaf9417f9a91fae7c68933e86667230b770e 100644 (file)
@@ -457,17 +457,6 @@ GF_Node *gf_vrml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *clon
                }
        }
 
-       if (node->sgprivate->tag==TAG_MPEG4_InputSensor) {
-               GF_Command *com_o, *com_f;
-               u32 k = 0;
-               M_InputSensor *clone_is = (M_InputSensor *)node;
-               M_InputSensor *orig_is = (M_InputSensor *)orig;
-               while ( (com_o = (GF_Command *)gf_list_enum(orig_is->buffer.commandList, &k) ) ) {
-                       com_f = gf_sg_vrml_command_clone(com_o, node->sgprivate->scenegraph, 1);
-                       gf_list_add(clone_is->buffer.commandList, com_f);
-               }
-       }
-
        /*init node before creating ISed routes so the eventIn handler are in place*/
        if (node->sgprivate->tag == TAG_MPEG4_Conditional) BIFS_SetupConditionalClone(node, orig);
        else if (node->sgprivate->tag != TAG_ProtoNode) gf_node_init(node);
index e410514d4fd1ee76fa175cd4d2e4abe3baaab047..13a48eee343d9aa4d4e2a7fc8304bc05ee5f956c 100644 (file)
@@ -55,10 +55,9 @@ GF_Route *gf_sg_route_new(GF_SceneGraph *sg, GF_Node *fromNode, u32 fromField, G
 void gf_sg_route_del(GF_Route *r)
 {
        GF_SceneGraph *sg;
-       s32 ind;
 
        /*remove declared routes*/
-       ind = gf_list_del_item(r->graph->Routes, r);
+       gf_list_del_item(r->graph->Routes, r);
        /*remove route from node - do this regardless of setup state since the route is registered upon creation*/
        if (r->FromNode && r->FromNode->sgprivate->interact && r->FromNode->sgprivate->interact->routes) {
                gf_list_del_item(r->FromNode->sgprivate->interact->routes, r);
index d7f05b173f1d85fedb63123cf54b375c30126a80..ee4a0e10ec7dbe4b0c536fc37c7f84f5585e2e33 100644 (file)
@@ -157,11 +157,11 @@ typedef struct
 } GF_RouteToFunction;
 
 
-#define _ScriptMessage(_c, _e, _msg) { \
+#define _ScriptMessage(_c, _msg) {     \
                GF_Node *_n = (GF_Node *) JS_GetContextPrivate(_c);     \
                if (_n->sgprivate->scenegraph->script_action) {\
                        GF_JSAPIParam par;      \
-                       par.info.e = (_e);                      \
+                       par.info.e = GF_SCRIPT_INFO;                    \
                        par.info.msg = (_msg);          \
                        _n->sgprivate->scenegraph->script_action(_n->sgprivate->scenegraph->script_action_cbck, GF_JSAPI_OP_MESSAGE, NULL, &par);\
                }       \
@@ -477,7 +477,7 @@ static JSBool SMJS_FUNCTION(JSPrint)
        SMJS_ARGS       
        if (JSVAL_IS_STRING(argv[0])) {
                char *str = SMJS_CHARS(c, argv[0]);
-               _ScriptMessage(c, GF_SCRIPT_INFO, str);
+               _ScriptMessage(c, str);
                SMJS_FREE(c, str);
        }
        return JS_TRUE;
@@ -2319,19 +2319,24 @@ static JSBool SMJS_FUNCTION(rot_multVec)
 static JSBool SMJS_FUNCTION(rot_setAxis)
 {
        SFVec3f v;
-       SFRotation r;
-       SMJS_ARGS
+       SFRotation *r;
+       GF_JSField *ptr;
        SMJS_OBJ
+       SMJS_ARGS
        if (argc<=0) return JS_FALSE;
 
        if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL))
                return JS_FALSE;
 
-       r = *(SFRotation *) ((GF_JSField *) JS_GetPrivate(c, obj))->field.far_ptr;
+       ptr = (GF_JSField *) JS_GetPrivate(c, obj);
+       r = (SFRotation *) ptr->field.far_ptr;
+
        v = *(SFVec3f *) ((GF_JSField *) JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr;
-       r.x = v.x;
-       r.y = v.y;
-       r.z = v.z;
+
+       r->x = v.x;      
+       r->y = v.y;      
+       r->z = v.z;
+       Script_FieldChanged(c, NULL, ptr, NULL);
        return JS_TRUE;
 }
 static JSBool SMJS_FUNCTION(rot_slerp)
@@ -2993,7 +2998,6 @@ JSBool SMJS_FUNCTION(vrml_event_add_listener)
        GF_Node *node;
        GF_JSField *ptr;
        SMJS_OBJ
-       SMJS_ARGS
        if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
        ptr = (GF_JSField *) JS_GetPrivate(c, obj);
        assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
@@ -3006,7 +3010,6 @@ JSBool SMJS_FUNCTION(vrml_event_remove_listener)
        GF_Node *node;
        GF_JSField *ptr;
        SMJS_OBJ
-       SMJS_ARGS
        if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
        ptr = (GF_JSField *) JS_GetPrivate(c, obj);
        assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
@@ -3587,9 +3590,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF
                        break;
                case GF_SG_VRML_MFCOLOR:
                        if ( JSVAL_IS_OBJECT(item) && JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFColorClass, NULL) ) {
-                               SFColor *col;
                                from = (GF_JSField *) JS_GetPrivate(c, JSVAL_TO_OBJECT(item));
-                               col = (SFColor *)from->field.far_ptr;
                                gf_sg_vrml_field_copy(& ((MFColor*)field->far_ptr)->vals[i], from->field.far_ptr, GF_SG_VRML_SFCOLOR);
                        }
                        break;
@@ -4159,6 +4160,8 @@ static void JS_PreDestroy(GF_Node *node)
        dom_js_pre_destroy(priv->js_ctx, node->sgprivate->scenegraph, NULL);
 #endif
 
+       gf_sg_lock_javascript(priv->js_ctx, 0);
+
        gf_sg_ecmascript_del(priv->js_ctx);
 
 #ifndef GPAC_DISABLE_SVG
@@ -4169,8 +4172,6 @@ static void JS_PreDestroy(GF_Node *node)
 
        priv->js_ctx = NULL;
 
-       gf_sg_lock_javascript(priv->js_ctx, 0);
-
        /*unregister script from parent scene (cf base_scenegraph::sg_reset) */
        gf_list_del_item(node->sgprivate->scenegraph->scripts, node);
 }
@@ -4522,6 +4523,8 @@ static void JSScript_NodeModified(GF_SceneGraph *sg, GF_Node *node, GF_FieldInfo
                        jsf = JS_GetPrivate(priv->js_ctx, obj);
                        if (jsf->node && (jsf->node==node)) {
                                jsf->node = NULL;
+                               /*Ivica patch*/
+                               node->sgprivate->interact->js_binding->node = NULL;
                        }
                }
                return;
@@ -4543,7 +4546,7 @@ static void JSScript_NodeModified(GF_SceneGraph *sg, GF_Node *node, GF_FieldInfo
                                else
                                {
                                        gf_sg_js_call_gc(sg->svg_js->js_ctx);
-                                       JS_ClearNewbornRoots(sg->svg_js->js_ctx);
+                                       //invalid with firefox>7: JS_ClearNewbornRoots(sg->svg_js->js_ctx);
                                }
 #endif
                        }
@@ -4638,7 +4641,7 @@ void gf_sg_handle_dom_event_for_vrml(GF_Node *node, GF_DOM_Event *event, GF_Node
 #ifndef GPAC_DISABLE_SVG
        GF_ScriptPriv *priv;
        Bool prev_type;
-       JSBool ret = JS_FALSE;
+       //JSBool ret = JS_FALSE;
        GF_DOM_Event *prev_event = NULL;
        SVG_handlerElement *hdl;
        jsval rval;
@@ -4658,19 +4661,26 @@ void gf_sg_handle_dom_event_for_vrml(GF_Node *node, GF_DOM_Event *event, GF_Node
 
        gf_sg_lock_javascript(priv->js_ctx, 1);
 
+       evt = gf_dom_new_event(priv->js_ctx);
+       if (!evt) {
+               gf_sg_lock_javascript(priv->js_ctx, 0);
+               GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[DOM Events] Cannot create JavaScript dom event for event type %d\n", event->type));
+               return;
+       }
+
        prev_type = event->is_vrml;
        event->is_vrml = 1;
        JS_SetPrivate(priv->js_ctx, priv->event, event);
 
-       evt = gf_dom_new_event(priv->js_ctx);
+
        JS_SetPrivate(priv->js_ctx, evt, event);
        argv[0] = OBJECT_TO_JSVAL(evt);
 
        if (hdl->js_fun_val) {
                jsval funval = (jsval ) hdl->js_fun_val;
-               ret = JS_CallFunctionValue(priv->js_ctx, hdl->evt_listen_obj ? (JSObject *)hdl->evt_listen_obj: priv->js_obj, funval, 1, argv, &rval);
+               /*ret = */JS_CallFunctionValue(priv->js_ctx, hdl->evt_listen_obj ? (JSObject *)hdl->evt_listen_obj: priv->js_obj, funval, 1, argv, &rval);
        } else {
-               ret = JS_CallFunctionName(priv->js_ctx, hdl->evt_listen_obj, "handleEvent", 1, argv, &rval);
+               /*ret = */JS_CallFunctionName(priv->js_ctx, hdl->evt_listen_obj, "handleEvent", 1, argv, &rval);
        }
 
        /*check any pending exception if outer-most event*/
@@ -4711,7 +4721,6 @@ void gf_sg_set_script_action(GF_SceneGraph *scene, gf_sg_script_action script_ac
 
 GF_Node *gf_sg_js_get_node(JSContext *c, JSObject *obj)
 {
-       JSBool has_p;
 #ifndef GPAC_DISABLE_VRML
        if (js_rt && JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) {
                GF_JSField *ptr = (GF_JSField *) JS_GetPrivate(c, obj);
@@ -4720,9 +4729,11 @@ GF_Node *gf_sg_js_get_node(JSContext *c, JSObject *obj)
 #endif
 
 #ifndef GPAC_DISABLE_SVG
-       has_p = 0;
-       if (JS_HasProperty(c, obj, "namespaceURI", &has_p)) {
-               if (has_p==JS_TRUE) return dom_get_element(c, obj);
+       {
+               JSBool has_p = 0;
+               if (JS_HasProperty(c, obj, "namespaceURI", &has_p)) {
+                       if (has_p==JS_TRUE) return dom_get_element(c, obj);
+               }
        }
 #endif
        return NULL;
index e51db21e3589ec779a857777f261871ae37d3408..5c73e63f36afbeeb8d5f7b5db80c48c3d1a4794d 100644 (file)
@@ -1120,13 +1120,13 @@ void VRML_FieldCopyCast(void *dest, u32 dst_field_type, void *orig, u32 ori_fiel
                                ((SFString*)dest)->buffer = gf_strdup(tmp);
                        } else {
                                if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer);
-                               ((SFString*)dest)->buffer = gf_strdup(url->url);
+                               ((SFString*)dest)->buffer = url->url ? gf_strdup(url->url) : NULL;
                        }
                }
                /*for SFString to MFString cast*/
                else if (ori_field_type == GF_SG_VRML_SFSTRING) {
                        if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer);
-                       ((SFString*)dest)->buffer = gf_strdup(((SFString*)orig)->buffer);
+                       ((SFString*)dest)->buffer = ((SFString*)orig)->buffer ? gf_strdup(((SFString*)orig)->buffer) : NULL;
                }
                return;
        case GF_SG_VRML_SFURL:
@@ -1235,7 +1235,7 @@ void gf_sg_vrml_field_clone(void *dest, void *orig, u32 field_type, GF_SceneGrap
                SFCommandBuffer *cb_src = (SFCommandBuffer *)orig;
 
                cb_dst->bufferSize = cb_src->bufferSize;
-               if (cb_dst->bufferSize) {
+               if (cb_dst->bufferSize && !gf_list_count(cb_src->commandList) ) {
                        cb_dst->buffer = (u8*)gf_realloc(cb_dst->buffer, sizeof(char)*cb_dst->bufferSize);
                        memcpy(cb_dst->buffer, cb_src->buffer, sizeof(char)*cb_src->bufferSize);
                } else {
index 02434106a3725aa9c264ebf3c05a0fc898cd55df..0af4aa216364de03dd9b4b9947b41b49751f25a3 100644 (file)
@@ -56,7 +56,7 @@ typedef struct
 static GF_Err xbl_parse_report(GF_XBL_Parser *parser, GF_Err e, char *format, ...)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {
+       if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
                char szMsg[2048];
                va_list args;
                va_start(args, format);
index 466dde67967106732bc0566bca119b18bdc2726f..42b3240230504c44fe9d9c10d3a1819e464714e4 100644 (file)
@@ -1131,7 +1131,7 @@ GF_Err gf_node_store_embedded_data(XMLRI *iri, const char *cache_dir, const char
                        iri->string = NULL;
                        return GF_IO_ERR;
                }
-               fwrite(data, data_size, 1, f);
+               gf_fwrite(data, data_size, 1, f);
                fclose(f);
        }
        gf_free(data);
index 39c7d6a611ae3730702a703f16ffe4ef8a7e43e5..7c833edf317f7b6e5962345744d43c65e869f42a 100644 (file)
@@ -345,13 +345,13 @@ static void Channel_UpdateBuffering(GF_Channel *ch, Bool update_info)
 {
        if (update_info && ch->MaxBuffer) gf_scene_buffering_info(ch->odm->parentscene ? ch->odm->parentscene : ch->odm->subscene);
 
-       gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_DATA_PROGRESS);
+       gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_PROGRESS);
        
        if (!Channel_NeedsBuffering(ch, 0)) {
                ch_buffer_off(ch);
                if (ch->MaxBuffer && update_info) gf_scene_buffering_info(ch->odm->parentscene ? ch->odm->parentscene : ch->odm->subscene);
 
-               gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_PLAYABLE);
+               gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_PLAYING);
        }
 }
 
@@ -578,7 +578,7 @@ static void Channel_DispatchAU(GF_Channel *ch, u32 duration)
        } else {
                /*trigger the data progress every 500 ms*/
                if (ch->last_au_time + 500 > time) {
-                       gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_DATA_PROGRESS);
+                       gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_PROGRESS);
                        ch->last_au_time = time;
                }
        }
@@ -659,7 +659,12 @@ static void gf_es_check_timing(GF_Channel *ch)
        /*if channel is not the OCR, shift all time stamps to match the current time at clock init*/
        else if (!ch->IsClockInit ) {
 //             ch->ts_offset += gf_clock_real_time(ch->clock);
-               if (ch->clock->clock_init) ch->IsClockInit = 1;
+               if (ch->clock->clock_init) {
+                       ch->IsClockInit = 1;
+                       if (ch->odm->flags & GF_ODM_INHERIT_TIMELINE) {
+//                             ch->ts_offset += gf_clock_real_time(ch->clock) - ch->CTS;
+                       }
+               }
        }
        /*deal with some broken DMB streams were the timestamps on BIFS/OD are not set (0) or completely out of sync
        of the OCR clock (usually audio). If the audio codec (BSAC ...) is not found, we force re-initializing of the clock
@@ -675,11 +680,24 @@ static void gf_es_check_timing(GF_Channel *ch)
 
 void gf_es_dispatch_raw_media_au(GF_Channel *ch, char *payload, u32 payload_size, u32 cts)
 {
+       u32 now;
        GF_CompositionMemory *cb;
        GF_CMUnit *cu;
        if (!payload || !ch->odm->codec->CB) return;
        if (!ch->odm->codec->CB->no_allocation) return;
 
+       now = gf_clock_real_time(ch->clock);
+       if (cts + ch->MinBuffer < now) {
+               if (ch->MinBuffer && (ch->is_raw_channel==2)) {
+                       ch->clock->clock_init = 0;
+                       gf_clock_set_time(ch->clock, cts);
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched at OTB %d but frame TS is %d ms - adjusting clock\n", ch->odm->OD->objectDescriptorID, now, cts));
+               } else {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched at OTB %d but frame TS is %d ms - DROPPING\n", ch->odm->OD->objectDescriptorID, now, cts));
+               }
+               return;
+       }
+
        cb = ch->odm->codec->CB;
        cu = gf_cm_lock_input(cb, cts, 1);
        if (cu) {
@@ -689,7 +707,7 @@ void gf_es_dispatch_raw_media_au(GF_Channel *ch, char *payload, u32 payload_size
                        cu->data = payload;
                        size = payload_size;
                        cu->TS = cts;
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched to CB - TS %d ms\n", ch->odm->OD->objectDescriptorID, cu->TS));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] Raw Frame dispatched to CB - TS %d ms - OTB %d ms - OTB_drift %d ms\n", ch->odm->OD->objectDescriptorID, cu->TS, gf_clock_real_time(ch->clock), gf_clock_time(ch->clock) ));
                }
                gf_cm_unlock_input(cb, cu, size, 1);
 
@@ -762,18 +780,30 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                        /*channel is the OCR, re-initialize the clock with the proper OCR*/
                        if (gf_es_owns_clock(ch)) {
                                u32 OCR_TS;
+
+                               /*timestamps of PCR stream haven been shifted - shift the OCR as well*/
+                               if (ch->seed_ts) {
+                                       u64 diff_ts;
+                                       Double scale = hdr.m2ts_pcr ? 27000000 : ch->esd->slConfig->OCRResolution;
+                                       scale /= ch->ts_res;
+                                       diff_ts = (u64) (ch->seed_ts * scale);
+                                       hdr.objectClockReference -= diff_ts;
+                               }
+
                                /*if SL is mapped from network module(eg not coded), OCR=PCR shall be given in 27Mhz units*/
                                if (hdr.m2ts_pcr) {
                                        OCR_TS = (u32) ( hdr.objectClockReference / 27000);
                                } else {
                                        OCR_TS = (u32) ( (s64) (hdr.objectClockReference) * ch->ocr_scale);
                                }
+                               OCR_TS += ch->ts_offset;
                                ch->clock->clock_init = 0;
+
                                gf_clock_set_time(ch->clock, OCR_TS);
                                /*many TS streams deployed with HLS have broken PCRs - we will check their consistency
                                when receiving the first AU with DTS/CTS on this channel*/
                                ch->clock->probe_ocr = 1;
-                               GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: initializing clock at STB %d from OCR TS %d (origial TS "LLD") - %d buffering - OTB %d\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), OCR_TS, hdr.objectClockReference, ch->clock->Buffering, gf_clock_time(ch->clock) ));
+                               GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: initializing clock at STB %d from OCR TS %d (original TS "LLD") - %d buffering - OTB %d\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), OCR_TS, hdr.objectClockReference, ch->clock->Buffering, gf_clock_time(ch->clock) ));
                                if (ch->clock->clock_init) ch->IsClockInit = 1;
 
                        }
@@ -784,7 +814,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                        u32 ck;
                        u32 OCR_TS = (u32) ( hdr.objectClockReference / 27000);
                        ck = gf_clock_time(ch->clock);
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d - OCR Discontinuity OCR: adjusting to %d (origial TS "LLD") - original clock %d\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, ck));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d - OCR Discontinuity OCR: adjusting to %d (original TS "LLD") - original clock %d\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, ck));
 //                     gf_clock_set_time(ch->clock, (u32) OCR_TS);
                }
                /*compute clock drift*/
@@ -797,7 +827,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                                OCR_TS = (u32) ( (s64) (hdr.objectClockReference) * ch->ocr_scale);
                        }
                        ck = gf_clock_time(ch->clock);
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d adjusting OCR to %d (origial TS "LLD") - diff %d\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, (s32) OCR_TS - (s32) ck));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d adjusting OCR to %d (original TS "LLD") - diff %d\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, (s32) OCR_TS - (s32) ck));
 //                     gf_clock_set_time(ch->clock, (u32) OCR_TS);
                }
 #else
@@ -810,7 +840,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                                OCR_TS = (u32) ( (s64) (hdr.objectClockReference) * ch->ocr_scale);
                        }
                        ck = gf_clock_time(ch->clock);
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d got OCR %d (origial TS "LLD") - diff %d%s\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, (s32) OCR_TS - (s32) ck, (hdr.m2ts_pcr==2) ? " - PCR Discontinuity flag" : "" ));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: At OTB %d got OCR %d (original TS "LLD") - diff %d%s\n", ch->esd->ESID, gf_clock_real_time(ch->clock), OCR_TS, hdr.objectClockReference, (s32) OCR_TS - (s32) ck, (hdr.m2ts_pcr==2) ? " - PCR Discontinuity flag" : "" ));
                }
 #endif
                if (!payload_size) return;
@@ -883,7 +913,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                                GF_LOG(GF_LOG_WARNING, GF_LOG_SYNC, ("[SyncLayer] ES%d: missed end of AU (DTS %d)\n", ch->esd->ESID, ch->DTS));
                        }
                        if (ch->codec_resilient) {
-                               if (!ch->IsClockInit) gf_es_check_timing(ch);
+                               if (!ch->IsClockInit && !ch->skip_time_check_for_pending) gf_es_check_timing(ch);
                                Channel_DispatchAU(ch, 0);
                        } else {
                                gf_free(ch->buffer);
@@ -892,6 +922,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                                ch->len = ch->allocSize = 0;
                        }
                }
+               ch->skip_time_check_for_pending = 0;
                AUSeqNum = hdr.AU_sequenceNumber;
                /*Get CTS */
                if (ch->esd->slConfig->useTimestampsFlag) {
@@ -928,7 +959,7 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                                        s32 diff_ts = ch->DTS;
                                        diff_ts -= ch->clock->init_time;
                                        if (ABS(diff_ts) > 10000) {
-                                               GF_LOG(GF_LOG_ERROR, GF_LOG_SYNC, ("[SyncLayer] ES%d: invalid clock reference detected - DTS %d OCR %d - using DTS as OCR\n", ch->DTS, ch->clock->init_time));
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_SYNC, ("[SyncLayer] ES%d: invalid clock reference detected - DTS %d but OCR %d - using DTS as OCR\n", ch->esd->ESID, ch->DTS, ch->clock->init_time));
                                                ch->clock->clock_init = 0;
                                                gf_clock_set_time(ch->clock, ch->DTS-1000);
                                        }
@@ -941,7 +972,8 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                        }
                } else {
                        /*use CU duration*/
-                       if (!ch->IsClockInit) ch->DTS = ch->CTS = ch->ts_offset;
+                       if (!ch->IsClockInit)
+                               ch->DTS = ch->CTS = ch->ts_offset;
 
                        if (!ch->esd->slConfig->AUSeqNumLength) {
                                if (!ch->au_sn) {
@@ -1137,6 +1169,8 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
                }
        }
 
+       gf_es_lock(ch, 1);
+
        if (hdr.paddingFlag && !EndAU) {        
                /*to do - this shouldn't happen anyway */
 
@@ -1157,6 +1191,9 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo
        }
 
        if (EndAU) Channel_DispatchAU(ch, hdr.au_duration);
+
+
+       gf_es_lock(ch, 0);
 }
 
 
@@ -1318,7 +1355,7 @@ void gf_es_drop_au(GF_Channel *ch)
        /*if we get under our limit, rebuffer EXCEPT WHEN EOS is signaled*/
        if (!ch->IsEndOfStream && Channel_NeedsBuffering(ch, 1)) {
                ch_buffer_on(ch);
-               gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_NOT_PLAYABLE);
+               gf_term_service_media_event(ch->odm, GF_EVENT_MEDIA_WAITING);
        }
 
        /*unlock the channel*/
index aa3d6440d4cd84c84a628d9ba0373fe03f684d35..88838479b71bb8d125f468896126692dbbe1a87b 100644 (file)
@@ -164,8 +164,8 @@ void gf_clock_reset(GF_Clock *ck)
 
 void gf_clock_stop(GF_Clock *ck)
 {
-       ck->StartTime = gf_clock_time(ck);
        ck->clock_init = 0;
+       ck->StartTime = 0;
 }
 
 void gf_clock_set_time(GF_Clock *ck, u32 TS)
@@ -202,7 +202,7 @@ void gf_clock_pause(GF_Clock *ck)
 void gf_clock_resume(GF_Clock *ck)
 {
        gf_mx_p(ck->mx);
-//     assert(ck->Paused);
+       assert(ck->Paused);
        ck->Paused -= 1;
        if (!ck->Paused) 
                ck->StartTime += gf_term_get_time(ck->term) - ck->PauseTime;
@@ -240,7 +240,7 @@ u32 gf_clock_ellapse_time(GF_Clock *ck)
 
 Bool gf_clock_is_started(GF_Clock *ck)
 {
-       if (/*!ck->StartTime || */ck->Buffering || ck->Paused) return 0;
+       if (!ck || ck->Buffering || ck->Paused) return 0;
        return 1;
 }
 
index 38b308112cbd33c40011d7b7c0f13428f47a98ee..4441ae95e85bbc11369b6bcaa8786ec5a73397bc 100644 (file)
@@ -83,8 +83,7 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch)
        GF_Err e;
        GF_NetworkCommand com;
        GF_Channel *a_ch;
-       char *dsi;
-       u32 dsiSize, CUsize, i;
+       u32 CUsize, i;
        GF_CodecCapability cap;
        u32 min, max;
 
@@ -92,22 +91,13 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch)
        /*only for valid codecs (eg not OCR)*/
        if (codec->decio) {
                com.get_dsi.dsi = NULL;
-               dsi = NULL;
-               dsiSize = 0;
                if (ch->esd->decoderConfig->upstream) codec->flags |= GF_ESM_CODEC_HAS_UPSTREAM;
-               if (ch->esd->decoderConfig->decoderSpecificInfo) {
-                       dsi = ch->esd->decoderConfig->decoderSpecificInfo->data;
-                       dsiSize = ch->esd->decoderConfig->decoderSpecificInfo->dataLength;
-               }
                /*For objects declared in OD stream, override with network DSI if any*/
                if (ch->service && !(ch->odm->flags & GF_ODM_NOT_IN_OD_STREAM) ) {
                        com.command_type = GF_NET_CHAN_GET_DSI;
                        com.base.on_channel = ch;
                        e = gf_term_service_command(ch->service, &com);
                        if (!e && com.get_dsi.dsi) {
-                               dsi = com.get_dsi.dsi;
-                               dsiSize = com.get_dsi.dsi_len;
-
                                if (ch->esd->decoderConfig->decoderSpecificInfo->data) gf_free(ch->esd->decoderConfig->decoderSpecificInfo->data);
                                ch->esd->decoderConfig->decoderSpecificInfo->data = com.get_dsi.dsi;
                                ch->esd->decoderConfig->decoderSpecificInfo->dataLength = com.get_dsi.dsi_len;
@@ -144,9 +134,11 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch)
                case GF_STREAM_VISUAL:
                case GF_STREAM_AUDIO:
                        cap.CapCode = GF_CODEC_BUFFER_MIN;
+                       cap.cap.valueInt = 1;
                        gf_codec_get_capability(codec, &cap);
                        min = cap.cap.valueInt;
                        cap.CapCode = GF_CODEC_BUFFER_MAX;
+                       cap.cap.valueInt = 1;
                        gf_codec_get_capability(codec, &cap);
                        max = cap.cap.valueInt;
                        break;
@@ -193,6 +185,7 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch)
                        com.base.on_channel = ch;
 
                        com.cfg.priority = ch->esd->streamPriority;
+                       assert( ch->clock );
                        com.cfg.sync_id = ch->clock->clockID;
                        memcpy(&com.cfg.sl_config, ch->esd->slConfig, sizeof(GF_SLConfig));
                        /*get the frame duration if audio (used by some network stack)*/
@@ -234,6 +227,9 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch)
                codec->CB->Min = 0;
                codec->CB->odm = codec->odm;
                ch->is_raw_channel = 1;
+               if (gf_es_owns_clock(ch))
+                       ch->is_raw_channel = 2;
+
                if (ch->is_pulling) {
                        codec->process = gf_codec_process_raw_media_pull;
                }
@@ -502,7 +498,6 @@ exit:
 /*special handling of decoders not using ESM*/
 static GF_Err PrivateScene_Process(GF_Codec *codec, u32 TimeAvailable)
 {
-       Bool resume_clock;
        u32 now;
        GF_Channel *ch;
        GF_Scene *scene_locked;
@@ -522,7 +517,6 @@ static GF_Err PrivateScene_Process(GF_Codec *codec, u32 TimeAvailable)
 
        ch = (GF_Channel*)gf_list_get(codec->inChannels, 0);
        if (!ch) return GF_OK;
-       resume_clock = 0;
        /*init channel clock*/
        if (!ch->IsClockInit) {
                Bool started;
@@ -697,7 +691,7 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable)
        if (codec->CB->Capacity == 1) {
                /*a SHA signature is computed for each AU. This avoids decoding/recompositing when identical (for instance streaming a carousel)*/
                u8 new_unit_signature[20];
-               gf_sha1_csum(AU->data, AU->dataLength, new_unit_signature);
+               gf_sha1_csum((u8*)AU->data, AU->dataLength, new_unit_signature);
                if (!memcmp(codec->last_unit_signature, new_unit_signature, sizeof(new_unit_signature))) {
                        codec->nb_repeted_frames++;
                        gf_es_drop_au(ch);
@@ -816,7 +810,7 @@ scalable_retry:
                                unit_size = 0;
                        e = UnlockCompositionUnit(codec, CU, unit_size);
 
-                       GF_LOG(GF_LOG_DEBUG, GF_LOG_RTI|GF_LOG_CODEC, ("[%s] ODM%d at %d decoded packed frame TS %d in %d ms\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, gf_clock_real_time(ch->clock), AU->CTS, now));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] ODM%d at %d decoded packed frame TS %d in %d ms\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, gf_clock_real_time(ch->clock), AU->CTS, now));
                        if (ch->skip_sl) {
                                if (codec->bytes_per_sec) {
                                        codec->cur_audio_bytes += unit_size;
@@ -841,7 +835,7 @@ scalable_retry:
                processing a scalable stream*/
                case GF_OK:
                        if (unit_size) {
-                               GF_LOG(GF_LOG_DEBUG, GF_LOG_RTI|GF_LOG_CODEC, ("[%s] ODM%d at %d decoded frame TS %d in %d ms (DTS %d) - %d in CB\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, gf_clock_real_time(ch->clock), AU->CTS, now, AU->DTS, codec->CB->UnitCount + 1));
+                               GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] ODM%d at %d decoded frame TS %d in %d ms (DTS %d) - %d in CB\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, gf_clock_real_time(ch->clock), AU->CTS, now, AU->DTS, codec->CB->UnitCount + 1));
                        }
                        /*if no size the decoder is not using the composition memory - if the object is in intitial buffering resume it!!*/
                        else if (codec->CB->Status == CB_BUFFER) {
@@ -1012,7 +1006,7 @@ GF_Err gf_codec_get_capability(GF_Codec *codec, GF_CodecCapability *cap)
 
        if (codec->flags & GF_ESM_CODEC_IS_RAW_MEDIA) {
                GF_BitStream *bs;
-               u32 pf, w, h, stride, out_size, sr, nb_ch, bpp, ch_cfg;
+               u32 pf, w, h, stride=0, out_size, sr, nb_ch, bpp, ch_cfg;
                GF_Channel *ch = gf_list_get(codec->odm->channels, 0);
                if (!ch || !ch->esd->decoderConfig->decoderSpecificInfo || !ch->esd->decoderConfig->decoderSpecificInfo->data) return 0;
                bs = gf_bs_new(ch->esd->decoderConfig->decoderSpecificInfo->data, ch->esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ);
@@ -1060,6 +1054,15 @@ GF_Err gf_codec_get_capability(GF_Codec *codec, GF_CodecCapability *cap)
                case GF_CODEC_CHANNEL_CONFIG:
                        cap->cap.valueInt = ch_cfg;
                        return GF_OK;
+               case GF_CODEC_PAR:
+                       cap->cap.valueInt = 0;
+                       return GF_OK;
+               case GF_CODEC_PADDING_BYTES:
+                       cap->cap.valueInt = 0;
+                       return GF_OK;
+               case GF_CODEC_RESILIENT:
+                       cap->cap.valueInt = 1;
+                       return GF_OK;
                }
        }
        return GF_BAD_PARAM;
@@ -1120,18 +1123,9 @@ static GF_Err Codec_LoadModule(GF_Codec *codec, GF_ESD *esd, u32 PL)
        GF_BaseDecoder *ifce, *dec_ifce;
        u32 i, plugCount;
        u32 ifce_type;
-       char *cfg;
-       u32 cfg_size, dec_confidence;
+       u32 dec_confidence;
        GF_Terminal *term = codec->odm->term;
 
-       if (esd->decoderConfig->decoderSpecificInfo) {
-               cfg = esd->decoderConfig->decoderSpecificInfo->data;
-               cfg_size = esd->decoderConfig->decoderSpecificInfo->dataLength;
-       } else {
-               cfg = NULL;
-               cfg_size = 0;
-       }
-
        switch (esd->decoderConfig->streamType) {
        case GF_STREAM_AUDIO:
        case GF_STREAM_VISUAL:
index 0a427fea49222111099d413383c8525d2bb4d7e9..a79f127c6d0558653f6abaddf57dc6c34b6cf2e1 100644 (file)
@@ -603,7 +603,7 @@ void gf_term_mouse_input(GF_Terminal *term, GF_EventMouse *event)
        gf_free(buf);
 }
 
-void gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool isKeyUp)
+Bool gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool isKeyUp)
 {
        u32 i;
        GF_BitStream *bs;
@@ -618,7 +618,7 @@ void gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool i
        GF_Codec *cod;
        s32 keyPressed, keyReleased, actionKeyPressed, actionKeyReleased;
 
-       if (!term || (!gf_list_count(term->input_streams) && !gf_list_count(term->x3d_sensors)) ) return;
+       if (!term || (!gf_list_count(term->input_streams) && !gf_list_count(term->x3d_sensors)) ) return 0;
 
        memset(&slh, 0, sizeof(GF_SLHeader));
        slh.accessUnitStartFlag = slh.accessUnitEndFlag = 1;
@@ -724,7 +724,7 @@ void gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool i
                char szStr[10];
                const unsigned short *ptr;
                if (gf_node_get_tag((GF_Node*)n) != TAG_X3D_KeySensor) continue;
-               if (!n->enabled) return;
+               if (!n->enabled) return 0;
 
                if (keyPressed) {
                        if (n->keyPress.buffer) gf_free(n->keyPress.buffer);
@@ -777,6 +777,8 @@ void gf_term_keyboard_input(GF_Terminal *term, u32 key_code, u32 hw_code, Bool i
                }
        }
 #endif
+       /*with KeySensor, we don't know if the key will be consumed or not, assume it is*/
+       return 1;
 }
 
 void gf_term_string_input(GF_Terminal *term, u32 character)
@@ -806,7 +808,7 @@ void gf_term_string_input(GF_Terminal *term, u32 character)
                ISPriv *is = (ISPriv *)cod->decio->privateStack;
                if (is->type==IS_StringSensor) {
 
-                       GF_Channel *ch = (GF_Channel *)gf_list_get(cod->inChannels, 0);
+//                     GF_Channel *ch = (GF_Channel *)gf_list_get(cod->inChannels, 0);
                        is->enteredText[is->text_len] = character;
                        is->text_len += 1;
 
@@ -818,7 +820,8 @@ void gf_term_string_input(GF_Terminal *term, u32 character)
                        gf_bs_get_content(bs, &buf, &buf_size);
                        gf_bs_del(bs);
                        
-                       gf_es_receive_sl_packet(ch->service, ch, buf, buf_size, &slh, GF_OK);
+//                     gf_es_receive_sl_packet(ch->service, ch, buf, buf_size, &slh, GF_OK);
+                       IS_ProcessData((GF_SceneDecoder*)cod->decio, buf, buf_size, 0, 0, 0);
                        
                        gf_free(buf);
                }
index d3485a439df61dca9d9515a9fa5267f573bdafc4..d7284e776132277baa7b45f83238acc48e2d2e9c 100644 (file)
@@ -346,7 +346,10 @@ void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy)
                /*OD not ready yet*/
                if (!stack->ck) {
                        stack->stream = NULL;
-                       if (stack->control->url.count) gf_term_invalidate_compositor(stack->parent->root_od->term);
+                       if (stack->control->url.count) {
+                               stack->is_init = 0;
+                               gf_term_invalidate_compositor(stack->parent->root_od->term);
+                       }
                        return;
                }
                gf_sg_vrml_field_copy(&stack->url, &stack->control->url, GF_SG_VRML_MFURL);
@@ -385,7 +388,14 @@ void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy)
                stack->media_stop = stack->control->mediaStopTime;
                stack->is_init = 1;
                /*the object has already been started, and media start time is not 0, restart*/
-               if (stack->stream->num_open && (stack->media_start > 0) ) mediacontrol_restart(odm);
+               if (stack->stream->num_open) {
+                       if (stack->media_start > 0) {
+                               mediacontrol_restart(odm);
+                       } else if (stack->media_speed == 0) {
+                               mediacontrol_pause(odm);
+                               stack->paused = 1;
+                       }
+               }
                return;
        }
 
index 19506b35fc9bd486a89507ad6f30c222da68f467..86d753892b581da562ac3a3df427723b27b23f02 100644 (file)
@@ -149,6 +149,8 @@ void gf_term_add_codec(GF_Terminal *term, GF_Codec *codec)
        } else if (term->flags & GF_TERM_SINGLE_THREAD) {
                threaded = 0;
        }
+       if (codec->flags & GF_ESM_CODEC_IS_RAW_MEDIA) 
+               threaded = 0;
        
        if (threaded) {
                cd->thread = gf_th_new(cd->dec->decio->module_name);
@@ -342,19 +344,6 @@ static u32 MM_SimulationStep_Decoder(GF_Terminal *term)
        return time_left;
 }
 
-u32 MM_SimulationStep_Compositor(GF_Terminal *term, u32 time_left)
-{
-       u32 time_taken = gf_sys_clock();
-       gf_sc_draw_frame(term->compositor);
-       time_taken = gf_sys_clock() - time_taken;
-       if (time_left>time_taken) 
-               time_left -= time_taken;
-       else
-               time_left = 0;
-
-       return time_left;
-}
-
 u32 MM_Loop(void *par)
 {
        GF_Terminal *term = (GF_Terminal *) par;
@@ -371,8 +360,15 @@ u32 MM_Loop(void *par)
                if (do_codec) left = MM_SimulationStep_Decoder(term);
                else left = term->frame_duration;
                
-               if (do_scene) left = MM_SimulationStep_Compositor(term, left);
-
+               if (do_scene) {
+                       u32 time_taken = gf_sys_clock();
+                       gf_sc_draw_frame(term->compositor);
+                       time_taken = gf_sys_clock() - time_taken;
+                       if (left>time_taken) 
+                               left -= time_taken;
+                       else
+                               left = 0;
+               }
                if (do_regulate)
                        gf_sleep(left);
        }
@@ -551,7 +547,7 @@ void gf_term_set_threading(GF_Terminal *term, u32 mode)
 
                if (ce->flags & GF_MM_CE_THREADED) {
                        /*wait for thread to die*/
-                       while (!(ce->flags & GF_MM_CE_DEAD)) gf_sleep(0);
+                       while (!(ce->flags & GF_MM_CE_DEAD)) gf_sleep(1);
                        ce->flags &= ~GF_MM_CE_DEAD;
                        gf_th_del(ce->thread);
                        ce->thread = NULL;
@@ -619,23 +615,27 @@ void gf_term_set_priority(GF_Terminal *term, s32 Priority)
 }
 
 GF_EXPORT
-GF_Err gf_term_process_step(GF_Terminal *term)
+u32 gf_term_process_step(GF_Terminal *term)
 {
-       u32 left = 0;
+       u32 time_taken = gf_sys_clock();
 
        if (term->flags & GF_TERM_NO_DECODER_THREAD) {
-               left = MM_SimulationStep_Decoder(term);
-       } else {
-               left = term->frame_duration;
-       }
+               MM_SimulationStep_Decoder(term);
+       } 
 
        if (term->flags & GF_TERM_NO_COMPOSITOR_THREAD) {
-               left = MM_SimulationStep_Compositor(term, left);
+               gf_sc_draw_frame(term->compositor);
        }
-       if (term->user->init_flags & GF_TERM_NO_REGULATION) return GF_OK;
+       time_taken = gf_sys_clock() - time_taken;
+       if (time_taken > term->compositor->frame_duration) {
+               time_taken = 0;
+       } else {
+               time_taken = term->compositor->frame_duration - time_taken;
+       }
+       if (term->user->init_flags & GF_TERM_NO_REGULATION) return time_taken;
 
-       gf_sleep(left);
-       return GF_OK;
+       gf_sleep(time_taken);
+       return time_taken;
 }
 
 GF_EXPORT
index 892c1310f496b2dcfa2cf70c04a8db699fa8558d..4c8741e0db8bb00dc499b01f63ba856be8a1f57c 100644 (file)
@@ -358,6 +358,8 @@ void gf_cm_unlock_input(GF_CompositionMemory *cb, GF_CMUnit *cu, u32 cu_size, Bo
                        gf_clock_buffer_off(cb->odm->codec->ck);
                        cb->odm->codec->ck->data_timeout = 0;
                        GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ODM%d: buffering off at %d (nb buffering on clock: %d)\n", cb->odm->OD->objectDescriptorID, gf_term_get_time(cb->odm->term), cb->odm->codec->ck->Buffering));
+
+                       gf_term_service_media_event(cb->odm->parentscene->root_od, GF_EVENT_MEDIA_CANPLAY);
                } 
 
                /*since a new CU is here notify the compositor*/
@@ -551,14 +553,17 @@ void gf_cm_drop_output(GF_CompositionMemory *cb)
        /*this allows reuse of the CU*/
        cb->output->RenderedLength = 0;
        cb->LastRenderedTS = cb->output->TS;
-       if (cb->odm->raw_frame_sema) {
-               cb->output->dataLength = 0;
-               gf_sema_notify(cb->odm->raw_frame_sema, 1);
-       }
+
+       /*WARNING: in RAW mode, we (for the moment) only have one unit - setting output->dataLength to 0 means the input is available 
+       for the raw channel - we have to make sure the output is completely reseted before releasing the sema*/
 
        /*on visual streams (except raw oness), always keep the last AU*/
        if (!cb->no_allocation && cb->output->dataLength && (cb->odm->codec->type == GF_STREAM_VISUAL) ) {
                if ( !cb->output->next->dataLength || (cb->Capacity == 1) )  {
+                       if (cb->odm->raw_frame_sema) {
+                               cb->output->dataLength = 0;
+                               gf_sema_notify(cb->odm->raw_frame_sema, 1);
+                       }
                        return;
                }
        }
@@ -572,6 +577,10 @@ void gf_cm_drop_output(GF_CompositionMemory *cb)
        if (!cb->HasSeenEOS && cb->UnitCount <= cb->Min) {
                cb->odm->codec->PriorityBoost = 1;
        }
+
+       if (cb->odm->raw_frame_sema) {
+               gf_sema_notify(cb->odm->raw_frame_sema, 1);
+       }
 }
 
 void gf_cm_set_status(GF_CompositionMemory *cb, u32 Status)
index 36367e7295712eb3b8db0b58eed939094750e235..d6dec1f49134c8ccb670b425b6259943fc1496dd 100644 (file)
@@ -120,6 +120,9 @@ GF_MediaObject *gf_mo_register(GF_Node *node, MFURL *url, Bool lock_timelines, B
        case TAG_MPEG4_AnimationStream: 
                obj_type = GF_MEDIA_OBJECT_UPDATES; 
                break;
+       case TAG_MPEG4_BitWrapper:
+               obj_type = GF_MEDIA_OBJECT_SCENE;
+               break;
        case TAG_MPEG4_InputSensor: 
                obj_type = GF_MEDIA_OBJECT_INTERACT; 
                break;
@@ -181,9 +184,6 @@ GF_MediaObject *gf_mo_register(GF_Node *node, MFURL *url, Bool lock_timelines, B
                scene = scene->root_od->parentscene;
 
        res = gf_scene_get_media_object_ex(scene, url, obj_type, lock_timelines, syncRef, force_new_res, node);
-
-       if (res) {
-       }
        return res;
 }
 
@@ -235,6 +235,36 @@ Bool gf_mo_get_visual_info(GF_MediaObject *mo, u32 *width, u32 *height, u32 *str
                cap.CapCode = GF_CODEC_PIXEL_FORMAT;
                gf_codec_get_capability(mo->odm->codec, &cap);
                *pixelFormat = cap.cap.valueInt;
+
+               if (mo->odm && mo->odm->parentscene->is_dynamic_scene) {
+                       const char *name = gf_node_get_name(gf_list_get(mo->nodes, 0));
+                       if (name && !strcmp(name, "DYN_VIDEO")) {
+                               const char *opt;
+                               u32 r, g, b, a;
+                               M_Background2D *back = (M_Background2D *) gf_sg_find_node_by_name(mo->odm->parentscene->graph, "DYN_BACK");
+                               if (back) {
+                                       switch (cap.cap.valueInt) {
+                                       case GF_PIXEL_ARGB:
+                                       case GF_PIXEL_RGBA:
+                                       case GF_PIXEL_YUVA:
+                                               opt = gf_cfg_get_key(mo->odm->term->user->config, "Compositor", "BackColor");
+                                               if (!opt) {
+                                                       gf_cfg_set_key(mo->odm->term->user->config, "Compositor", "BackColor", "FF999999");
+                                                       opt = "FF999999";
+                                               }
+                                               sscanf(opt, "%02X%02X%02X%02X", &a, &r, &g, &b);
+                                               back->backColor.red = INT2FIX(r)/255;
+                                               back->backColor.green = INT2FIX(g)/255;
+                                               back->backColor.blue = INT2FIX(b)/255;
+                                               break;
+                                       default:
+                                               back->backColor.red = back->backColor.green = back->backColor.blue = FIX_ONE;
+                                               break;
+                                       }
+                                       gf_node_dirty_set((GF_Node *)back, 0, 1);
+                               }
+                       }
+               }
        }
        /*get PAR settings*/
        if (pixel_ar) {
@@ -417,8 +447,12 @@ char *gf_mo_fetch_data(GF_MediaObject *mo, Bool resync, Bool *eos, u32 *timestam
        mo->frame = CU->data + CU->RenderedLength;
        if (mo->timestamp != CU->TS) {
 #ifndef GPAC_DISABLE_VRML
-               mediasensor_update_timing(mo->odm, *eos);
+               mediasensor_update_timing(mo->odm, mo->odm->codec->CB->HasSeenEOS);
 #endif
+       
+               if (mo->odm->parentscene->is_dynamic_scene)
+                       mo->odm->parentscene->root_od->current_time = mo->odm->current_time;
+
                mo->timestamp = CU->TS;
                GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] At OTB %d fetch frame TS %d size %d - %d unit in CB\n", mo->odm->OD->objectDescriptorID, gf_clock_time(mo->odm->codec->ck), mo->timestamp, mo->framesize, mo->odm->codec->CB->UnitCount));
                /*signal EOS after rendering last frame, not while rendering it*/
@@ -598,11 +632,14 @@ Bool gf_mo_stop(GF_MediaObject *mo)
 
        mo->num_open--;
        if (!mo->num_open && mo->odm) {
+               if (mo->odm->flags & GF_ODM_DESTROYED) return 1;
+
                /*do not stop directly, this can delete channel data currently being decoded (BIFS anim & co)*/
                gf_term_lock_media_queue(mo->odm->term, 1);
                /*if object not in media queue, add it*/
-               if (gf_list_find(mo->odm->term->media_queue, mo->odm)<0)
+               if (gf_list_find(mo->odm->term->media_queue, mo->odm)<0) {
                        gf_list_add(mo->odm->term->media_queue, mo->odm);
+               }
                
                /*signal STOP request*/
                if ((mo->OD_ID==GF_MEDIA_EXTERNAL_ID) || (mo->odm && mo->odm->OD && (mo->odm->OD->objectDescriptorID==GF_MEDIA_EXTERNAL_ID))) {
@@ -706,15 +743,10 @@ Bool gf_mo_is_same_url(GF_MediaObject *obj, MFURL *an_url, Bool *keep_fragment,
        u32 i;
        char szURL1[GF_MAX_PATH], szURL2[GF_MAX_PATH], *ext;
 
-       if (obj->OD_ID==GF_MEDIA_EXTERNAL_ID) {
-               if (!obj->URLs.count) {
-                       if (!obj->odm) return 0;
-                       strcpy(szURL1, obj->odm->net_service->url);
-               } else {
-                       strcpy(szURL1, obj->URLs.vals[0].url);
-               }
+       if (!obj->URLs.count) {
+               if (!obj->odm) return 0;
+               strcpy(szURL1, obj->odm->net_service->url);
        } else {
-               if (!obj->URLs.count) return 0;
                strcpy(szURL1, obj->URLs.vals[0].url);
        }
 
@@ -766,6 +798,8 @@ Bool gf_mo_is_same_url(GF_MediaObject *obj, MFURL *an_url, Bool *keep_fragment,
                for (i=0; i<an_url->count; i++) {
                        if (an_url->vals[i].url && !stricmp(szURL1, an_url->vals[i].url)) return 1;
                }
+               /*not same resource, we will have to check fragment as URL might point to a sub-service or single stream of a mux*/
+               if (keep_fragment) *keep_fragment = 1;
                return 0;
        }
        ext = strrchr(szURL1, '#');
@@ -835,6 +869,8 @@ void gf_mo_set_speed(GF_MediaObject *mo, Fixed speed)
        ctrl = gf_odm_get_mediacontrol(mo->odm);
        if (ctrl) return;
 #endif
+       if (mo->odm->net_service && (mo->odm->net_service->owner->flags & GF_ODM_INHERIT_TIMELINE))
+               return;
        gf_odm_set_speed(mo->odm, speed);
 }
 
@@ -1034,7 +1070,7 @@ Bool gf_mo_set_position(GF_MediaObject *mo, GF_Window *src, GF_Window *dst)
 }
 
 GF_EXPORT
-Bool gf_mo_has_audio(GF_MediaObject *mo)
+u32 gf_mo_has_audio(GF_MediaObject *mo)
 {
        char *sub_url, *ext;
        u32 i;
@@ -1043,6 +1079,7 @@ Bool gf_mo_has_audio(GF_MediaObject *mo)
        GF_Scene *scene;
        if (!mo || !mo->odm) return 0;
        if (mo->type != GF_MEDIA_OBJECT_VIDEO) return 0;
+       if (!mo->odm->net_service) return 2;
 
        ns = mo->odm->net_service;
        scene = mo->odm->parentscene;
index 9c5afd0d37e0292d1e923dcf638046ad4a9b7e38..4988b47fe10460dac98f041e2dc9f6b226bb7163 100644 (file)
@@ -110,7 +110,7 @@ void MS_Modified(GF_Node *node)
                        gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/);
                }
        }
-       st->stream = gf_mo_register(node, &st->sensor->url, 0, 0);
+       st->stream = NULL;
        st->is_init = 0;
        gf_term_invalidate_compositor(st->parent->root_od->term);
 }
@@ -137,6 +137,10 @@ void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos)
                                GF_Clock *ck = gf_odm_get_media_clock(odm);
                                if (ck->has_seen_eos && (1000*time>=(Double) (s64)odm->subscene->duration)) {
                                        if (media_sens->sensor->isActive) {
+                                               /*force notification of time (ntify the scene duration rather than the current clock*/
+                                               media_sens->sensor->mediaCurrentTime = (Double) odm->subscene->duration;
+                                               media_sens->sensor->mediaCurrentTime /= 1000;
+                                               gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
                                                media_sens->sensor->isActive = 0;
                                                gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
 
@@ -161,13 +165,21 @@ void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos)
 
                                gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
                        }
-                       if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) {
-                               media_sens->sensor->mediaCurrentTime = time;
-                               gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
-                       }
+
                        if (is_eos && media_sens->sensor->isActive) {
+                               if (media_sens->sensor->mediaDuration>=0) {
+                                       media_sens->sensor->mediaCurrentTime = media_sens->sensor->mediaDuration;
+                               } else {
+                                       media_sens->sensor->mediaCurrentTime = time;
+                               }
+                               gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
                                media_sens->sensor->isActive = 0;
                                gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
+                       } else {
+                               if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) {
+                                       media_sens->sensor->mediaCurrentTime = time;
+                                       gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
+                               }
                        }
                        continue;
                }
index d2a5d0f4c3a2ec4b18647c9fdb1ca6a5d09f5ab1..6a2b55645a9dc1925eda7665c49ae3c3871b3b90 100644 (file)
@@ -139,10 +139,24 @@ void gf_inline_on_modified(GF_Node *node)
                                }
                        }
                }
-       } else {
-               gf_node_dirty_parents(node);
+       } 
+       /*force a redraw and load scene at next pass - we cannot load the scene now because 
+               - we can be in a JS call (eg JS mutex blocked)
+               - locating scene objects matching the new url needs exclusive access to the MediaObject list, achieved with the term net mutex
+               - another service may already be setting up objects (eg exclusive access to the net mutex grabbed), which can trigger event forwarding
+               - some event forwarders may request JS context (eg access to JS mutex)
+
+               In such a case we would end up in a deadlock - this needs urgent fixing ...
+       */
+
+       if (ODID) {
+               /*if no parent we must process the url change as we may not be traversed later on (not in the scene tree)*/
+               if (gf_node_get_parent(node, 0)==NULL) {
+                       gf_inline_set_scene(pInline);
+               } else {
+                       gf_node_dirty_parents(node);
+               }
        }
-       if (ODID) gf_inline_set_scene(pInline);
 }
 
 static void gf_inline_check_restart(GF_Scene *scene)
@@ -170,9 +184,12 @@ static void gf_inline_check_restart(GF_Scene *scene)
                                e = -1;
                                MC_GetRange(scene->root_od->media_ctrl, &s, &e);
                                if ((e>=0) && (e<GF_MAX_FLOAT)) dur = (u32) (e*1000);
-                               if (dur<now) {
+                               if (dur<=now) {
                                        scene->needs_restart = 1;
                                        scene->root_od->media_ctrl->current_seg = 0;
+                               } else {
+                                       /*trigger render until to watch for restart...*/
+                                       gf_term_invalidate_compositor(scene->root_od->term);
                                }
                        }
                } else {
@@ -334,7 +351,9 @@ GF_SceneGraph *gf_inline_get_proto_lib(void *_is, MFURL *lib_url)
 
        i=0;
        while ((pl = (GF_ProtoLink*)gf_list_enum(scene->extern_protos, &i))) {
-               if (!pl->mo) continue;
+               /*not ready yet*/
+               if (!pl->mo || !pl->mo->odm || ! pl->mo->odm->net_service) continue;
+
                if (gf_mo_get_od_id(pl->url) != GF_MEDIA_EXTERNAL_ID) {
                        if (gf_mo_get_od_id(pl->url) == gf_mo_get_od_id(lib_url)) {
                                if (!pl->mo->odm || !pl->mo->odm->subscene) return NULL;
@@ -352,6 +371,7 @@ GF_SceneGraph *gf_inline_get_proto_lib(void *_is, MFURL *lib_url)
                                char *url1, *url2;
                                Bool ok;
                                if (!pl->mo) continue;
+                               if (! pl->mo->odm->net_service) continue;
                                if (gf_mo_get_od_id(pl->url) != GF_MEDIA_EXTERNAL_ID) continue;
                                /*not the same url*/
                                if (!gf_mo_is_same_url(pl->mo, lib_url, NULL, 0)) continue;
index 77fdce5e34f8bac81a77969a6a1972c447a479ff..85015f172dc5f4f65a031f3b85801c76374a9cd3 100644 (file)
@@ -26,6 +26,7 @@
 #include <gpac/network.h>
 #include <gpac/cache.h>
 #include "media_memory.h"
+#include "media_control.h"
 
 
 
@@ -77,17 +78,17 @@ static void term_on_connect(void *user_priv, GF_ClientService *service, LPNETCHA
        }
        /*this is service connection*/
        if (!netch) {
-               gf_term_service_media_event(service->owner, GF_EVENT_MEDIA_END_SESSION_SETUP);
+               gf_term_service_media_event(service->owner, GF_EVENT_MEDIA_SETUP_DONE);
                if (err) {
                        char msg[5000];
                        snprintf(msg, sizeof(msg), "Cannot open %s", service->url);
                        gf_term_message(term, service->url, msg, err);
 
-                       gf_term_service_media_event(service->owner, GF_EVENT_MEDIA_ERROR);
+                       gf_term_service_media_event(service->owner, GF_EVENT_ERROR);
 
                        /*destroy service only if attached*/
                        if (root) {
-                               gf_mx_p(term->media_queue_mx);
+                               gf_term_lock_media_queue(term, 1);
                                service->ifce->CloseService(service->ifce);
                                root->net_service = NULL;
                                if (service->owner && service->nb_odm_users) service->nb_odm_users--;
@@ -97,7 +98,7 @@ static void term_on_connect(void *user_priv, GF_ClientService *service, LPNETCHA
                                        /*and queue for destroy*/
                                        gf_list_add(term->net_services_to_remove, service);
                                }
-                               gf_mx_v(term->media_queue_mx);
+                               gf_term_lock_media_queue(term, 0);
 
                                if (!root->parentscene) {
                                        GF_Event evt;
@@ -214,13 +215,21 @@ static void term_on_disconnect(void *user_priv, GF_ClientService *service, LPNET
        }
        /*this is service disconnect*/
        if (!netch) {
-               gf_mx_p(term->media_queue_mx);
+               if (service->subservice_disconnect) {
+                       if (service->owner && service->subservice_disconnect==1) {
+                               GF_Scene *scene = service->owner->subscene ? service->owner->subscene : service->owner->parentscene;
+                               /*destrou all media*/
+                               gf_scene_disconnect(scene, 1);
+                       }
+                       return;
+               }
+               gf_term_lock_media_queue(term, 1);
                /*unregister from valid services*/
                if (gf_list_del_item(term->net_services, service)>=0) {
                        /*and queue for destroy*/
                        gf_list_add(term->net_services_to_remove, service);
                }
-               gf_mx_v(term->media_queue_mx);
+               gf_term_lock_media_queue(term, 0);
                return;
        }
        /*this is channel disconnect*/
@@ -273,10 +282,14 @@ static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Des
        GET_TERM();
 
        root = service->owner;
-       if (!root){
+       if (!root) {
          GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] has not root, aborting !\n", service->url));
          return;
        }
+       if (root->flags & GF_ODM_DESTROYED) {
+         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] root has been scheduled for destruction - aborting !\n", service->url));
+         return;
+       }
        scene = root->subscene ? root->subscene : root->parentscene;
 
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Service %s] %s\n", service->url, media_desc ? "Adding new media object" : "Regenerating scene graph"));
@@ -309,17 +322,21 @@ static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Des
                char *frag, *ext;
                GF_ESD *esd;
                char *url;
+               u32 match_esid = 0;
                GF_MediaObject *mo = gf_list_get(scene->scene_objects, i);
-               if (!mo->odm) continue;
 
                if ((mo->OD_ID != GF_MEDIA_EXTERNAL_ID) && (min_od_id<mo->OD_ID)) 
                        min_od_id = mo->OD_ID;
 
+               if (!mo->odm) continue;
+               /*if object is attached to a service, don't bother looking in a different one*/
+               if (mo->odm->net_service && (mo->odm->net_service != service)) continue;
+
                /*already assigned object - this may happen since the compositor has no control on when objects are declared by the service,
                therefore opening file#video and file#audio may result in the objects being declared twice if the service doesn't
                keep track of declared objects*/
                if (mo->odm->OD) {
-                       if (is_same_od(mo->odm->OD, od)) {
+                       if (od->objectDescriptorID && is_same_od(mo->odm->OD, od)) {
                                /*reassign OD ID*/
                                mo->OD_ID = od->objectDescriptorID;
                                gf_odf_desc_del(media_desc);
@@ -348,14 +365,17 @@ static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Des
                if (!strnicmp(url, "file://localhost", 16)) url += 16;
                else if (!strnicmp(url, "file://", 7)) url += 7;
                else if (!strnicmp(url, "gpac://", 7)) url += 7;
+               else if (!strnicmp(url, "pid://", 6)) match_esid = atoi(url+6);
 
-               if (!strstr(service->url, url)) {
+               if (!match_esid && !strstr(service->url, url)) {
                        if (ext) ext[0] = '#';
                        continue;
                }
                if (ext) ext[0] = '#';
 
                esd = gf_list_get(od->ESDescriptors, 0);
+               if (match_esid && (esd->ESID != match_esid)) 
+                       continue;
                /*match type*/
                switch (esd->decoderConfig->streamType) {
                case GF_STREAM_VISUAL:
@@ -385,6 +405,17 @@ static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Des
                odm = mo->odm;
                break;
        }
+
+       /*add a pass on scene->resource to check for min_od_id, 
+       otherwise we may have another modules declaring an object with ID 0 from
+       another thread, which will assert (only one object with a givne OD ID)*/
+       for (i=0; i<gf_list_count(scene->resources); i++) {
+               GF_ObjectManager *an_odm = gf_list_get(scene->resources, i);
+
+               if (an_odm->OD && (an_odm->OD->objectDescriptorID != GF_MEDIA_EXTERNAL_ID) && (min_od_id < an_odm->OD->objectDescriptorID)) 
+                       min_od_id = an_odm->OD->objectDescriptorID;
+       }
+
        if (!odm) {
                odm = gf_odm_new();
                odm->term = term;
@@ -402,13 +433,14 @@ static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Des
        if (!scene->selected_service_id) 
                scene->selected_service_id = od->ServiceID;
 
-       GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] setup object - MO %08x\n", odm->OD->objectDescriptorID, odm->mo));
-       gf_odm_setup_object(odm, service);
 
-       /*unlock net once the object has been added to the scene, otherwise we may have another modules declaring an object with ID 0 from
-       another thread, which will assert (only one object with a givne OD ID)*/
+       /*net is unlocked before seting up the object as this might trigger events going into JS and deadlocks 
+       with the compositor*/
        gf_term_lock_net(term, 0);
 
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] setup object - MO %08x\n", odm->OD->objectDescriptorID, odm->mo));
+       gf_odm_setup_object(odm, service);
+
        /*OD inserted by service: resetup scene*/
        if (!no_scene_check && scene->is_dynamic_scene) gf_scene_regenerate(scene);
 }
@@ -443,6 +475,8 @@ static void term_on_command(void *user_priv, GF_ClientService *service, GF_Netwo
                /*get exclusive access to media scheduler, to make sure ODs are not being
                manipulated*/
                gf_mx_p(term->mm_mx);
+               if (!gf_list_count(od_list))
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM] No object manager found for the scene (URL: %s), buffer occupancy will remain unchanged\n", service->url));
                i=0;
                while ((odm = (GF_ObjectManager*)gf_list_enum(od_list, &i))) {
                        u32 j, count;
@@ -496,7 +530,27 @@ static void term_on_command(void *user_priv, GF_ClientService *service, GF_Netwo
        case GF_NET_CHAN_MAP_TIME:
                ch->seed_ts = com->map_time.timestamp;
                ch->ts_offset = (u32) (com->map_time.media_time*1000);
-               if (com->map_time.reset_buffers) gf_es_reset_buffers(ch);
+               GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: mapping TS "LLD" to media time %f - current time %d\n", ch->esd->ESID, com->map_time.timestamp, com->map_time.media_time, gf_clock_time(ch->clock)));
+
+               if (com->map_time.reset_buffers) {
+                       gf_es_reset_buffers(ch);
+               }
+               /*if we were reassembling an AU, do not perform clock init check when dispatching it since we computed its timestamps 
+               according to the previous clock origin*/
+               else {
+                       gf_mx_p(ch->mx);
+                       ch->skip_time_check_for_pending = 1;
+                       gf_mx_v(ch->mx);
+               }
+               /*if the channel is the clock, force a re-init*/
+               if (gf_es_owns_clock(ch)) {
+                       ch->IsClockInit = 0;
+                       gf_clock_reset(ch->clock);
+               }
+               else if (ch->odm->flags & GF_ODM_INHERIT_TIMELINE) {
+                       ch->IsClockInit = 0;
+//                     ch->ts_offset -= ch->seed_ts*1000/ch->ts_res;
+               }
                break;
        /*duration changed*/
        case GF_NET_CHAN_DURATION:
@@ -560,7 +614,10 @@ static char *get_mime_type(GF_Terminal *term, const char *url, GF_Err *ret_code,
                        if (*ret_code) break;
                        if (gf_dm_sess_get_status(sess)>=GF_NETIO_DATA_EXCHANGE) {
                                const char * mime = gf_dm_sess_mime_type(sess);
-                               if (mime) ret = gf_strdup(mime);
+                               /* The mime type is returned lower case */
+                               if (mime){
+                                       ret = gf_strdup(mime);
+                               }
                                break;
                        }
                }
@@ -798,8 +855,9 @@ exit:
 
 GF_ClientService *gf_term_service_new(GF_Terminal *term, struct _od_manager *owner, const char *url, const char *parent_url, GF_Err *ret_code)
 {
-       GF_DownloadSession *download_session;
+       GF_DownloadSession *download_session = NULL;
        char *sURL;
+       const char *opt;
        GF_ClientService *serv;
        GF_InputService *ifce = gf_term_can_handle_service(term, url, parent_url, 0, &sURL, ret_code, &download_session);
        if (!ifce) return NULL;
@@ -812,6 +870,20 @@ GF_ClientService *gf_term_service_new(GF_Terminal *term, struct _od_manager *own
        serv->Clocks = gf_list_new();
        serv->dnloads = gf_list_new();
        serv->pending_service_session = download_session;
+
+       opt = gf_cfg_get_key(term->user->config, "Network", "HTTPRebuffer");
+       if (!opt) {
+               opt = "5000";
+               gf_cfg_set_key(term->user->config, "Network", "HTTPRebuffer", "5000");
+       }
+       serv->download_rebuffer = atoi(opt);
+       opt = gf_cfg_get_key(term->user->config, "Network", "HTTPAutoRebuffer");
+       if (!opt) {
+               opt = "no";
+               gf_cfg_set_key(term->user->config, "Network", "HTTPAutoRebuffer", "no");
+       }
+       serv->auto_rebuffer = !strcmp(opt, "yes") ? 1 : 0;
+
        gf_list_add(term->net_services, serv);
 
        return serv;
@@ -990,6 +1062,7 @@ GF_DownloadSession *gf_term_download_new(GF_ClientService *service, const char *
 GF_EXPORT
 void gf_term_download_del(GF_DownloadSession * sess)
 {
+       Bool locked;
        GF_ClientService *serv;
        if (!sess) return;
        serv = (GF_ClientService *)gf_dm_sess_get_private(sess);
@@ -997,7 +1070,7 @@ void gf_term_download_del(GF_DownloadSession * sess)
        /*avoid sending data back to user*/
        gf_dm_sess_abort(sess);
 
-       gf_mx_p(serv->term->media_queue_mx); 
+       locked = gf_mx_try_lock(serv->term->media_queue_mx);
 
        /*unregister from service*/
        gf_list_del_item(serv->dnloads, sess);
@@ -1005,7 +1078,9 @@ void gf_term_download_del(GF_DownloadSession * sess)
        /*same as service: this may be called in the downloader thread (typically when download fails)
        so we must queue the downloader and let the term delete it later on*/
        gf_list_add(serv->term->net_services_to_remove, sess);
-       gf_mx_v(serv->term->media_queue_mx); 
+
+       if (locked)
+               gf_term_lock_media_queue(serv->term, 0);
 }
 
 GF_EXPORT
@@ -1029,6 +1104,9 @@ void gf_term_download_update_stats(GF_DownloadSession * sess)
        case GF_NETIO_WAIT_FOR_REPLY:
                gf_term_on_message(serv, GF_OK, "Waiting for reply...");
                break;
+       case GF_NETIO_PARSE_REPLY:
+               gf_term_on_message(serv, GF_OK, "Starting download...");
+               break;
        case GF_NETIO_DATA_EXCHANGE:
                /*notify some connection / ...*/
                if (total_size) {
@@ -1042,6 +1120,70 @@ void gf_term_download_update_stats(GF_DownloadSession * sess)
                        gf_term_send_event(serv->term, &evt);
                }
                GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size));
+               gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec);
+
+               if ( (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
+                       GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
+                       Double download_percent, playback_percent, adj_percent;
+                       download_percent = 100 * bytes_done; 
+                       download_percent /= total_size;
+
+                       playback_percent = 100 * serv->owner->current_time; 
+                       playback_percent /= serv->owner->duration;
+                       if (serv->auto_rebuffer)
+                               adj_percent = 0.0;
+                       else
+                               adj_percent = 100.0 * serv->download_rebuffer / serv->owner->duration;
+
+                       if (playback_percent >= download_percent) {
+                               if (gf_clock_is_started(ck)) {
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% but downloaded %d %% - Pausing\n", (u32) playback_percent, (u32) download_percent));
+                                       if (!serv->is_paused) {
+                                               serv->is_paused = 1;
+                                               mediacontrol_pause(serv->owner);
+                                       }
+                                       gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_WAITING);
+                                       gf_term_on_message(serv, GF_OK, "HTTP Buffering ...");
+                               }
+                       } else if (playback_percent + adj_percent <= download_percent) {
+                               Double time_to_play = 0;
+                               Double time_to_download = 0;
+                               /*automatic rebuffer: make sure we can finish playback before resuming*/
+                               if (serv->auto_rebuffer) {
+                                       if (bytes_per_sec) {
+                                               time_to_download = 1000.0*(total_size - bytes_done);
+                                               time_to_download /= bytes_per_sec;
+                                       }
+                                       time_to_play = (Double) serv->owner->duration;
+                                       time_to_play -= serv->owner->current_time;
+                               }
+                               if ((time_to_download<=time_to_play) && !gf_clock_is_started(ck)) {
+                                       GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% and downloaded %d %% - Resuming\n", (u32) playback_percent, (u32) download_percent));
+                                       if (serv->auto_rebuffer) {
+                                               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Auto-rebuffer done: should be done downloading in %d ms and remains %d ms to play\n", (u32) time_to_download, (u32) (serv->owner->duration - serv->owner->current_time) ));
+                                       }
+                                       gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_PLAYING);
+                                       if (serv->is_paused) {
+                                               serv->is_paused = 0;
+                                               mediacontrol_resume(serv->owner);
+                                       }
+                                       gf_term_on_message(serv, GF_OK, "HTTP Resuming playback");
+                               }
+                       }
+               }
+               break;
+       case GF_NETIO_DATA_TRANSFERED:
+               gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE);
+               if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
+                       GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
+                       if (!gf_clock_is_started(ck)) {
+                               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n"));
+                               if (serv->is_paused) {
+                                       serv->is_paused = 0;
+                                       mediacontrol_resume(serv->owner);
+                               }
+                       }
+               }
                break;
        }
 }
index 227a82b434bf7816df43ab399f22a394db3043ba..ed6fed0f3336c1d1cfc852dd230b567c420bfb24 100644 (file)
@@ -148,14 +148,19 @@ GF_Err gf_term_get_object_info(GF_Terminal *term, GF_ObjectManager *odm, GF_Medi
                if (odm->codec->ck) info->current_time = odm->codec->CB ? odm->current_time : gf_clock_time(odm->codec->ck);
                info->current_time /= 1000;
                info->nb_droped = odm->codec->nb_droped;
-       } else if (odm->subscene && odm->subscene->scene_codec) {
-               if (odm->subscene->scene_codec->ck) {
-                       info->current_time = gf_clock_time(odm->subscene->scene_codec->ck);
+       } else if (odm->subscene) {
+               if (odm->subscene->scene_codec) {
+                       if (odm->subscene->scene_codec->ck) {
+                               info->current_time = gf_clock_time(odm->subscene->scene_codec->ck);
+                               info->current_time /= 1000;
+                       }
+                       info->duration = (Double) (s64)odm->subscene->duration;
+                       info->duration /= 1000;
+                       info->nb_droped = odm->subscene->scene_codec->nb_droped;
+               } else if (odm->subscene->is_dynamic_scene && odm->subscene->dyn_ck) {
+                       info->current_time = gf_clock_time(odm->subscene->dyn_ck);
                        info->current_time /= 1000;
                }
-               info->duration = (Double) (s64)odm->subscene->duration;
-               info->duration /= 1000;
-               info->nb_droped = odm->subscene->scene_codec->nb_droped;
        }
 
        info->buffer = -2;
index 7ff6164d84bee7d4de9c43664ed31b95c3e25e28..d1621a86bc10791196af7f874b9fc53b08f11d28 100644 (file)
@@ -56,7 +56,6 @@ GF_ObjectManager *gf_odm_new()
 
 void gf_odm_del(GF_ObjectManager *odm)
 {
-       Bool lock;
 #ifndef GPAC_DISABLE_VRML
        u32 i;
        MediaSensorStack *media_sens;
@@ -66,9 +65,17 @@ void gf_odm_del(GF_ObjectManager *odm)
        /*make sure we are not in the media queue*/
        gf_term_lock_media_queue(odm->term, 1);
        gf_list_del_item(odm->term->media_queue, odm);
+       gf_term_check_connections_for_delete(odm->term, odm);
        gf_term_lock_media_queue(odm->term, 0);
 
-       lock = gf_mx_try_lock(odm->mx);
+       /*detach media object as referenced by the scene - this should ensures that any attempt to lock the ODM from the 
+       compositor will fail as the media object is no longer linked to object manager*/
+       gf_mx_p(odm->mx);
+       if (odm->mo) odm->mo->odm = NULL;
+       gf_mx_v(odm->mx);
+       
+       /*relock the mutex for final object destruction*/
+       gf_mx_p(odm->mx);
 
 #ifndef GPAC_DISABLE_VRML
        i=0;
@@ -86,16 +93,15 @@ void gf_odm_del(GF_ObjectManager *odm)
        }
        gf_list_del(odm->mc_stack);
 #endif
-       if (odm->mo) odm->mo->odm = NULL;
 
        if (odm->raw_frame_sema) gf_sema_del(odm->raw_frame_sema);
 
        gf_list_del(odm->channels);
        odm->channels = NULL;
+       assert (!odm->net_service);
        gf_odf_desc_del((GF_Descriptor *)odm->OD);
        odm->OD = NULL;
-       assert (!odm->net_service);
-       if (lock) gf_mx_v(odm->mx);
+       gf_mx_v(odm->mx);
        gf_mx_del(odm->mx);
        gf_free(odm);
 }
@@ -122,9 +128,14 @@ Bool gf_odm_lock_mo(GF_MediaObject *mo)
 GF_EXPORT
 void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
 {
+       GF_Terminal *term;
        GF_Channel *ch;
 
-       if (do_remove) odm->flags |= GF_ODM_DESTROYED;
+       if (do_remove) {
+               gf_mx_p(odm->term->net_mx);
+               odm->flags |= GF_ODM_DESTROYED;
+               gf_mx_v(odm->term->net_mx);
+       }
        gf_odm_stop(odm, 1);
 
        /*disconnect sub-scene*/
@@ -195,23 +206,34 @@ void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
        if (odm->net_service) {
                GF_ClientService *ns = odm->net_service;
                if (ns->nb_odm_users) ns->nb_odm_users--;
-               //if (odm->flags & GF_ODM_SERVICE_ENTRY) 
-               {
-                       if (ns->owner == odm) {
-                               /*detach it!!*/
-                               ns->owner = NULL;
-                               /*try to assign a new root in case this is not scene shutdown*/
-                               if (ns->nb_odm_users && odm->parentscene) {
-                                       GF_ObjectManager *new_root;
-                                       u32 i = 0;
-                                       while ((new_root = (GF_ObjectManager *)gf_list_enum(odm->parentscene->resources, &i)) ) {
-                                               if (new_root == odm) continue;
-                                               if (new_root->net_service != ns) continue;
-                                               ns->owner = new_root;
-                                               break;
+               if (ns->owner == odm) {
+                       /*detach it!!*/
+                       ns->owner = NULL;
+                       /*try to assign a new root in case this is not scene shutdown*/
+                       if (ns->nb_odm_users && odm->parentscene) {
+                               GF_ObjectManager *new_root;
+                               u32 i = 0;
+                               while ((new_root = (GF_ObjectManager *)gf_list_enum(odm->parentscene->resources, &i)) ) {
+                                       if (new_root == odm) continue;
+                                       if (new_root->net_service != ns) continue;
+
+                                       /*if the new root is not playing or assoicated with the scene, force a destroy on it - this
+                                       is needed for services declaring their objects dynamically*/
+                                       if (!new_root->mo || (!new_root->mo->num_open)) {
+                                               gf_term_lock_media_queue(odm->term, 1);
+                                               new_root->action_type = GF_ODM_ACTION_DELETE;
+                                               if (gf_list_find(odm->term->media_queue, new_root)<0) {
+                                                       assert(! (new_root->flags & GF_ODM_DESTROYED));
+                                                       gf_list_add(odm->term->media_queue, new_root);
+                                               }
+                                               gf_term_lock_media_queue(odm->term, 0);
                                        }
+                                       ns->owner = new_root;
+                                       break;
                                }
                        }
+               } else {
+                       assert(ns->nb_odm_users);
                }
                odm->net_service = NULL;
                if (!ns->nb_odm_users) gf_term_close_service(odm->term, ns);
@@ -219,6 +241,8 @@ void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
 
        gf_odm_lock(odm, 0);
 
+       term = odm->term;
+
        /*delete from the parent scene.*/
        if (odm->parentscene) {
                GF_Event evt;
@@ -226,9 +250,11 @@ void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
                evt.connect.is_connected = 0;
                gf_term_forward_event(odm->term, &evt, 0, 1);
 
+               gf_term_lock_net(term, 1);
                gf_scene_remove_object(odm->parentscene, odm, do_remove);
                if (odm->subscene) gf_scene_del(odm->subscene);
                gf_odm_del(odm);
+               gf_term_lock_net(term, 0);
                return;
        }
        
@@ -245,8 +271,11 @@ void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
                gf_term_send_event(odm->term, &evt);
        }
 
+       gf_term_lock_net(term, 1);
        /*delete the ODMan*/
        gf_odm_del(odm);
+
+       gf_term_lock_net(term, 0);
 }
 
 /*setup service for OD (extract IOD and go)*/
@@ -258,6 +287,10 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url
        GF_Terminal *term;
        GF_Descriptor *desc;
 
+       if (odm->flags & GF_ODM_DESTROYED) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM] Root object of service %s has been scheduled for destruction - ignoring object setup\n", service_sub_url));
+               return;
+       }
 //     assert(odm->OD==NULL);
 
        term = odm->term;
@@ -287,8 +320,9 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url
 
        if (!desc) {
                /*if desc is NULL for a media, the media will be declared later by the service (gf_term_media_add)*/
-               if (od_type != GF_MEDIA_OBJECT_SCENE)
+               if (od_type != GF_MEDIA_OBJECT_SCENE) {
                        return;
+               }
                /*create empty service descriptor, this will automatically create a dynamic scene*/
                desc = gf_odf_desc_new(GF_ODF_OD_TAG);
        }
@@ -331,9 +365,7 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url
                goto err_exit;
        }
        
-       gf_term_lock_net(term, 1);
        gf_odm_setup_object(odm, odm->net_service);
-       gf_term_lock_net(term, 0);
 
        /*it may happen that this object was inserted in a dynamic scene from a service through a URL redirect. In which case, 
        the scene regeneration might not have been completed since the redirection was not done yet - force a scene regenerate*/
@@ -423,7 +455,7 @@ GF_Err ODM_ValidateOD(GF_ObjectManager *odm, Bool *hasInline)
        u16 es_id;
        GF_ESD *esd, *base_scene;
        const char *sOpt;
-       u32 lang, nb_od, nb_ocr, nb_scene, nb_mp7, nb_ipmp, nb_oci, nb_mpj, nb_other, prev_st;
+       u32 nb_od, nb_ocr, nb_scene, nb_mp7, nb_ipmp, nb_oci, nb_mpj, nb_other, prev_st;
 
        nb_od = nb_ocr = nb_scene = nb_mp7 = nb_ipmp = nb_oci = nb_mpj = nb_other = 0;
        prev_st = 0;
@@ -478,8 +510,8 @@ GF_Err ODM_ValidateOD(GF_ObjectManager *odm, Bool *hasInline)
                gf_cfg_set_key(odm->term->user->config, "Systems", "Language2CC", "en");
                gf_cfg_set_key(odm->term->user->config, "Systems", "LanguageName", "English");
        }
-       lang = (sOpt[0]<<16) | (sOpt[1]<<8) | sOpt[2];
 #if 0
+       lang = (sOpt[0]<<16) | (sOpt[1]<<8) | sOpt[2];
        if (gf_list_count(odm->OD->ESDescriptors)>1) {
                ODM_SelectAlternateStream(odm, lang, GF_STREAM_SCENE);
                ODM_SelectAlternateStream(odm, lang, GF_STREAM_OD);
@@ -544,7 +576,14 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
        GF_ESD *esd;
        GF_MediaObject *syncRef;
 
+       gf_term_lock_net(odm->term, 1);
+
        if (!odm->net_service) {
+               if (odm->flags & GF_ODM_DESTROYED) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Object has been scheduled for destruction - ignoring object setup\n", odm->OD->objectDescriptorID));
+                       gf_term_lock_net(odm->term, 0);
+                       return;
+               }
                odm->net_service = serv;
                if (!odm->OD->URLString) 
                        odm->net_service->nb_odm_users++;
@@ -570,8 +609,9 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
                        odm->subscene = gf_scene_new(odm->parentscene);
                        odm->subscene->root_od = odm;
                }
-               gf_term_connect_object(odm->term, odm, url, parent ? parent->url : NULL);
+               gf_term_post_connect_object(odm->term, odm, url, parent ? parent->url : NULL);
                gf_free(url);
+               gf_term_lock_net(odm->term, 0);
                return;
        }
        /*restore OD ID */
@@ -589,6 +629,7 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
        if (e) {
                gf_term_message(odm->term, odm->net_service->url, "MPEG-4 Service Error", e);
                gf_odm_disconnect(odm, 1);
+               gf_term_lock_net(odm->term, 0);
                return;
        }
 
@@ -596,12 +637,20 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
                hasInline = 0;
        }
 
+       if (odm->net_service->owner &&  (odm->net_service->owner->flags & GF_ODM_INHERIT_TIMELINE)) {
+               odm->flags |= GF_ODM_INHERIT_TIMELINE;
+       }
+
        /*if there is a BIFS stream in the OD, we need an GF_Scene (except if we already 
        have one, which means this is the first IOD)*/
        if (hasInline && !odm->subscene) {
                odm->subscene = gf_scene_new(odm->parentscene);
                odm->subscene->root_od = odm;
        }
+       /*patch for DASH and OD streams: we need to keep track of the original service demuxing the channel, which is not the DASH service*/
+       if (!odm->OD->service_ifce && odm->parentscene) {
+               odm->OD->service_ifce  = odm->parentscene->root_od->OD->service_ifce;
+       }
 
        numOK = odm->pending_channels = 0;
        /*empty IOD, use a dynamic scene*/
@@ -627,8 +676,7 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
                }
                odm->state = GF_ODM_STATE_STOP;
                gf_odm_lock(odm, 0);
-       }
-       
+       }       
        /*setup mediaobject info except for top-level OD*/
        if (odm->parentscene) {
                GF_Event evt;
@@ -645,20 +693,29 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
                        gf_odm_start(odm, 0);
                }
 
+               gf_term_lock_net(odm->term, 0);
+
                evt.type = GF_EVENT_CONNECT;
                evt.connect.is_connected = 1;
                gf_term_forward_event(odm->term, &evt, 0, 1);
+
+               gf_term_lock_net(odm->term, 1);
        } else {
                /*othewise send a connect ack for top level*/
                GF_Event evt;
 
                GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Root object connected !\n", odm->net_service->url));
                
+               gf_term_lock_net(odm->term, 0);
+
                evt.type = GF_EVENT_CONNECT;
                evt.connect.is_connected = 1;
                gf_term_send_event(odm->term, &evt);
+
+               gf_term_lock_net(odm->term, 1);
        }
 
+
        /* start object*/
        /*case 1: object is the root, always start*/
        if (!odm->parentscene) {
@@ -675,10 +732,21 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
        have to wait for an entire image carousel period to start filling the buffers, which is sub-optimal
        we also force a prefetch for object declared outside the OD stream to make sure we don't loose any data before object declaration and play
        as can be the case with MPEG2 TS (first video packet right after the PMT) - this should be refined*/
-       else if (!odm->state && ((odm->flags & GF_ODM_NO_TIME_CTRL) || (odm->flags & GF_ODM_NOT_IN_OD_STREAM)) && (odm->parentscene->selected_service_id == odm->OD->ServiceID)) {
-               GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Inserted from broadcast - forcing play\n", odm->OD->objectDescriptorID));
-               gf_odm_start(odm, 2);
-               odm->flags |= GF_ODM_PREFETCH;
+       else if ( ((odm->flags & GF_ODM_NO_TIME_CTRL) || (odm->flags & GF_ODM_NOT_IN_OD_STREAM)) && (odm->parentscene->selected_service_id == odm->OD->ServiceID)) {
+               Bool force_play = 0;
+               if (odm->state==GF_ODM_STATE_STOP) {
+                       odm->flags |= GF_ODM_PREFETCH;
+                       force_play = 1;
+               }
+               /*the object could have been queued for play when setting up the scene object. If so, remove from queue and start right away*/
+               else if ((odm->state==GF_ODM_STATE_PLAY) && (gf_list_del_item(odm->term->media_queue, odm)>=0) ) {
+                       force_play = 1;
+               }
+               if (force_play) {
+                       odm->flags |= GF_ODM_INITIAL_BROADCAST_PLAY;
+                       GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Inserted from broadcast - forcing play\n", odm->OD->objectDescriptorID));
+                       gf_odm_start(odm, 2);
+               }
        }
                
        /*for objects inserted by user (subs & co), auto select*/
@@ -692,10 +760,16 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
                        odm->OD_PL = 0;
                }
                if (odm->parentscene==odm->term->root_scene) {
+                       gf_term_lock_net(odm->term, 0);
+                       gf_mx_v(odm->term->net_mx);
                        evt.type = GF_EVENT_STREAMLIST;
                        gf_term_send_event(odm->term,&evt);
+       
+                       gf_term_lock_net(odm->term, 1);
                }
        }
+
+       gf_term_lock_net(odm->term, 0);
 }
 
 
@@ -734,11 +808,28 @@ GF_Err gf_odm_setup_es(GF_ObjectManager *odm, GF_ESD *esd, GF_ClientService *ser
        }
        /*timeline override*/
        if (odm->flags & GF_ODM_INHERIT_TIMELINE) {
-               if (odm->parentscene->root_od->subscene->scene_codec)
+               if (odm->parentscene->root_od->subscene->scene_codec) {
                        ck = odm->parentscene->root_od->subscene->scene_codec->ck;
-               else
+               } else {
                        ck = odm->parentscene->root_od->subscene->dyn_ck;
-               goto clock_setup;
+               }
+               /**/
+               if (!ck) {
+                       GF_ObjectManager *odm_par = odm->parentscene->root_od->parentscene->root_od;
+                       while (odm_par) {
+                               if (odm_par->subscene->scene_codec)
+                                       ck = odm_par->subscene->scene_codec->ck;
+                               else 
+                                       ck = odm_par->subscene->dyn_ck;
+
+                               if (ck) break;
+
+                               odm_par = odm->parentscene->root_od->parentscene ? odm->parentscene->root_od->parentscene->root_od : NULL;
+                       }
+               }
+               if (ck)
+                       goto clock_setup;
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[ODM] Cannot inherit timeline from parent scene for scene %s\n", odm->net_service->url));
        }
 
        /*get clocks namespace (eg, parent scene)*/
@@ -816,22 +907,21 @@ clock_setup:
                /*OD codec acts as main scene codec when used to generate scene graph*/
                if (! odm->subscene->od_codec) {
                        odm->subscene->od_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
-                       if (e) return e;
-                       gf_term_add_codec(odm->term, odm->subscene->od_codec);
+                       if (!e) gf_term_add_codec(odm->term, odm->subscene->od_codec);
                } 
                dec = odm->subscene->od_codec;
                break;
        case GF_STREAM_OCR:
                /*OD codec acts as main scene codec when used to generate scene graph*/
                dec = odm->ocr_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
-               gf_term_add_codec(odm->term, odm->ocr_codec);
+               if (!e) gf_term_add_codec(odm->term, odm->ocr_codec);
                break;
        case GF_STREAM_SCENE:
                /*animationStream */
                if (!odm->subscene) {
                        if (!odm->codec) {
                                odm->codec = gf_codec_new(odm, esd, odm->Scene_PL, &e);
-                               gf_term_add_codec(odm->term, odm->codec);
+                               if (!e) gf_term_add_codec(odm->term, odm->codec);
                        }
                        dec = odm->codec;
                }
@@ -852,7 +942,7 @@ clock_setup:
                } else {
                        odm->oci_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
                        odm->oci_codec->odm = odm;
-                       gf_term_add_codec(odm->term, odm->oci_codec);
+                       if (!e) gf_term_add_codec(odm->term, odm->oci_codec);
                }
                break;
 #endif
@@ -1085,6 +1175,7 @@ GF_Err gf_odm_post_es_setup(GF_Channel *ch, GF_Codec *dec, GF_Err had_err)
 
                gf_term_lock_net(ch->odm->term, 1);
                gf_es_start(ch);
+               memset(&com, 0, sizeof(GF_NetworkCommand));
                com.command_type = GF_NET_CHAN_PLAY;
                com.base.on_channel = ch;
                com.play.speed = FIX2FLT(ch->clock->speed);
@@ -1236,6 +1327,7 @@ void gf_odm_start(GF_ObjectManager *odm, u32 media_queue_state)
                        gf_odm_play(odm);
                } else if (!skip_register && (gf_list_find(odm->term->media_queue, odm)<0)) {
                        odm->action_type = GF_ODM_ACTION_PLAY;
+                       assert(! (odm->flags & GF_ODM_DESTROYED));
                        gf_list_add(odm->term->media_queue, odm);
                }
        }
@@ -1284,7 +1376,15 @@ void gf_odm_play(GF_ObjectManager *odm)
        nb_failure = gf_list_count(odm->channels);
 
        /*send play command*/
+       memset(&com, 0, sizeof(GF_NetworkCommand));
        com.command_type = GF_NET_CHAN_PLAY;
+       
+       if (odm->flags & GF_ODM_INITIAL_BROADCAST_PLAY) {
+               odm->flags &= ~GF_ODM_INITIAL_BROADCAST_PLAY;
+               com.play.initial_broadcast_play = 1;
+       }
+
+
        i=0;
        while ( (ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
                Double ck_time;
@@ -1395,7 +1495,7 @@ void gf_odm_play(GF_ObjectManager *odm)
                return;
        }
 
-       gf_term_service_media_event(odm, GF_EVENT_MEDIA_DATA_REQUEST);
+       gf_term_service_media_event(odm, GF_EVENT_MEDIA_LOAD_START);
 
 
        /*start codecs last (otherwise we end up pulling data from channels not yet connected->pbs when seeking)*/
@@ -1490,6 +1590,7 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
                return;
        }
 
+       if (force_close && odm->mo) odm->mo->flags |= GF_MO_DISPLAY_REMOVE;
        /*stop codecs*/
        if (odm->codec) {
                gf_term_stop_codec(odm->codec);
@@ -1509,7 +1610,7 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
        if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec);
 #endif
 
-       gf_term_lock_net(odm->term, 1);
+//     gf_term_lock_net(odm->term, 1);
 
        /*send stop command*/
        com.command_type = GF_NET_CHAN_STOP;
@@ -1530,7 +1631,7 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
                        GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH %d At OTB %d requesting STOP\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock)));
                }
        }
-       gf_term_service_media_event(odm, GF_EVENT_MEDIA_STOP);
+       gf_term_service_media_event(odm, GF_EVENT_ABORT);
 
        /*stop channels*/
        i=0;
@@ -1542,7 +1643,7 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
                gf_es_stop(ch);
        }
 
-       gf_term_lock_net(odm->term, 0);
+//     gf_term_lock_net(odm->term, 0);
 
        odm->state = GF_ODM_STATE_STOP;
        odm->current_time = 0;
@@ -1588,7 +1689,7 @@ void gf_odm_on_eos(GF_ObjectManager *odm, GF_Channel *on_channel)
        } else {
                if (nb_eos != count) return;
        }
-       gf_term_service_media_event(odm, GF_EVENT_MEDIA_END_OF_DATA);
+       gf_term_service_media_event(odm, GF_EVENT_MEDIA_LOAD_DONE);
        
        if (odm->codec && (on_channel->esd->decoderConfig->streamType==odm->codec->type)) {
                gf_codec_set_status(odm->codec, GF_ESM_CODEC_EOS);
index 44484ef121c440c6a25053aee1a23e3facdefa5e..fb4fcfa58d26c2f9716ca6a82408b7c42b02cc35 100644 (file)
@@ -39,6 +39,8 @@
 #include <gpac/scenegraph_svg.h>
 #endif
 
+#include "input_sensor.h"
+
 GF_EXPORT
 Double gf_scene_get_time(void *_is)
 {
@@ -194,7 +196,6 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown)
 {
        u32 i;
        GF_MediaObject *obj;
-       GF_Node *root_node;
        GF_ObjectManager *odm;
        GF_SceneDecoder *dec = NULL;
        if (scene->scene_codec) dec = (GF_SceneDecoder *)scene->scene_codec->decio;
@@ -202,36 +203,8 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown)
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Scene] disconnecting\n"));
 
        gf_term_lock_compositor(scene->root_od->term, 1);
-       
-       /*disconnect / kill all objects BEFORE reseting the scene graph since we have 
-       potentially registered Inline nodes of the graph with the sub-scene*/
-       if (!for_shutdown && scene->static_media_ressources) {
-               i=0;
-               /*stop all objects but DON'T DESTROY THEM*/
-               while ((odm = (GF_ObjectManager *)gf_list_enum(scene->resources, &i))) {
-                       if (odm->state) gf_odm_disconnect(odm, 0);
-               }
-               /*reset all stream associations*/
-               i=0;
-               while ((obj = (GF_MediaObject*)gf_list_enum(scene->scene_objects, &i))) {
-                       gf_sg_vrml_mf_reset(&obj->URLs, GF_SG_VRML_MFURL);
-                       gf_list_reset(obj->nodes);
-               }
-       } else {
-               while (gf_list_count(scene->resources)) {
-                       odm = (GF_ObjectManager *)gf_list_get(scene->resources, 0);
-                       gf_odm_disconnect(odm, (for_shutdown || !scene->static_media_ressources) ? 1 : 0);
-               }
-#ifndef GPAC_DISABLE_VRML
-               while (gf_list_count(scene->extern_protos)) {
-                       GF_ProtoLink *pl = (GF_ProtoLink *)gf_list_get(scene->extern_protos, 0);
-                       gf_list_rem(scene->extern_protos, 0);
-                       gf_free(pl);
-               }
-#endif
-       }
-       
-       root_node = gf_sg_get_root_node(scene->graph);
+               
+       /*force unregistering of inline nodes (for safety)*/
        if (for_shutdown && scene->root_od->mo) {
                /*reset private stack of all inline nodes still registered*/
                while (gf_list_count(scene->root_od->mo->nodes)) {
@@ -250,9 +223,34 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown)
                }
        }
 
-       /*remove all associated eventTargets - THIS NEEDS CLEANUP*/
+       //Ivica patch: Remove all Registered InputSensor nodes -> shut down the InputSensor threads -> prevent illegal access on deleted pointers
+#ifndef GPAC_DISABLE_VRML
+       if (for_shutdown) {
+               i = 0;
+               while ((odm = (GF_ObjectManager *)gf_list_enum(scene->resources, &i))) {
+                       if (for_shutdown && odm->mo) {
+                               obj = odm->mo;
+                               while (gf_list_count(obj->nodes)) {
+                                       GF_Node *n = (GF_Node *)gf_list_get(obj->nodes, 0);
+                                       switch (gf_node_get_tag(n)) {
+                                               case TAG_MPEG4_InputSensor:
+                                                       {
+                                                               M_InputSensor* is = (M_InputSensor*)n;
+                                                               is->enabled = 0;
+                                                               InputSensorModified(n);
+                                                               break;
+                                                       }
+                                       }
+                                       gf_list_rem(obj->nodes, 0);
+                               }       
+                       }
+               }
+       }
+#endif
+
+       /*remove all associated eventTargets*/
        i=0;
-       while ((obj = (GF_MediaObject *)gf_list_enum(scene->resources, &i))) {
+       while ((obj = (GF_MediaObject *)gf_list_enum(scene->scene_objects, &i))) {
                if (obj->nodes) gf_list_reset(obj->nodes);
        }
 
@@ -267,15 +265,44 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown)
        if (scene->root_od->term->root_scene == scene) {
                gf_sc_set_scene(scene->root_od->term->compositor, NULL);
        }
-       /*release the scene*/
+
+       /*release the scene - at this stage, we no longer have any node stack refering to our media objects */
        if (dec && dec->ReleaseScene) dec->ReleaseScene(dec);
        gf_sg_reset(scene->graph);
        scene->graph_attached = 0;
        
-       assert(!gf_list_count(scene->extra_scenes) );
+
        /*reset statc ressource flag since we destroyed scene objects*/
        scene->static_media_ressources = 0;
 
+
+       /*disconnect and kill all objects*/
+       if (!for_shutdown && scene->static_media_ressources) {
+               i=0;
+               /*stop all objects but DON'T DESTROY THEM*/
+               while ((odm = (GF_ObjectManager *)gf_list_enum(scene->resources, &i))) {
+                       if (odm->state) gf_odm_disconnect(odm, 0);
+               }
+               /*reset all stream associations*/
+               i=0;
+               while ((obj = (GF_MediaObject*)gf_list_enum(scene->scene_objects, &i))) {
+                       gf_sg_vrml_mf_reset(&obj->URLs, GF_SG_VRML_MFURL);
+                       gf_list_reset(obj->nodes);
+               }
+       } else {
+               while (gf_list_count(scene->resources)) {
+                       odm = (GF_ObjectManager *)gf_list_get(scene->resources, 0);     
+                       gf_odm_disconnect(odm, (for_shutdown || !scene->static_media_ressources) ? 2 : 0);
+               }
+#ifndef GPAC_DISABLE_VRML
+               while (gf_list_count(scene->extern_protos)) {
+                       GF_ProtoLink *pl = (GF_ProtoLink *)gf_list_get(scene->extern_protos, 0);
+                       gf_list_rem(scene->extern_protos, 0);
+                       gf_free(pl);
+               }
+#endif
+       }
+
        /*remove stream associations*/
        while (gf_list_count(scene->scene_objects)) {
                obj = (GF_MediaObject*)gf_list_get(scene->scene_objects, 0);
@@ -285,9 +312,6 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown)
                gf_list_del(obj->nodes);
                gf_free(obj);
        }
-
-       if (for_shutdown && scene->root_od && scene->root_od->mo) {
-       }
        gf_term_lock_compositor(scene->root_od->term, 0);
 }
 
@@ -457,7 +481,7 @@ void gf_scene_remove_object(GF_Scene *scene, GF_ObjectManager *odm, Bool for_shu
                                }
                        }
 
-                       if (discard_obj==1) {
+                       if ((discard_obj==1) && !obj->num_open) {
                                gf_list_rem(scene->scene_objects, i-1);
                                gf_sg_vrml_mf_reset(&obj->URLs, GF_SG_VRML_MFURL);
                                gf_list_del(obj->nodes);
@@ -647,37 +671,68 @@ GF_MediaObject *gf_scene_get_media_object_ex(GF_Scene *scene, MFURL *url, u32 ob
        OD_ID = gf_mo_get_od_id(url);
        if (!OD_ID) return NULL;
 
+       gf_term_lock_net(scene->root_od->term, 1);
+
        /*the first pass is needed to detect objects already inserted and registered with the given nodes, regardless of 
        the force_new_if_not_attached flag. This ty^pically occurs when a resource is first created then linked to an animation/inline*/
 restart:
        obj = NULL;
        i=0;
        while ((obj = (GF_MediaObject *)gf_list_enum(scene->scene_objects, &i))) {
-               if (obj->odm && ((obj->odm->flags & GF_ODM_DESTROYED) || (obj->odm->action_type == GF_ODM_ACTION_DELETE)) )
-                       continue;
+               Bool odm_matches = 0;
 
                if (
                        /*regular OD scheme*/
                        (OD_ID != GF_MEDIA_EXTERNAL_ID && (obj->OD_ID==OD_ID)) 
                ||
-                       /*dynamic OD scheme*/
-                       ((OD_ID == GF_MEDIA_EXTERNAL_ID) && (obj->OD_ID==GF_MEDIA_EXTERNAL_ID)
+                       /*dynamic OD scheme - !! obj->OD_ID may different from GF_MEDIA_EXTERNAL_ID when ODs are 
+                       directly added to the terminal by the service*/
+                       ((OD_ID == GF_MEDIA_EXTERNAL_ID) 
                                /*if object type unknown (media control, media sensor), return first obj matching URL
                                otherwise check types*/
                                && is_match_obj_type(obj->type, obj_type_hint)
                                /*locate sub-url in given one and handle fragments (viewpoint/segments/...)*/
                                && gf_mo_is_same_url(obj, url, &keep_fragment, obj_type_hint) 
                        )
-               ) {                     
-                       if (!first_pass && !force_new_if_not_attached) {
-                               if (node && (gf_list_find(obj->nodes, node)<0))
-                                       gf_list_add(obj->nodes, node);
-                               return obj;
-                       }
-                       /*special case where the URL is requested twice for the same node: use the existing resource*/
-                       else if (node && (gf_list_find(obj->nodes, node)>=0)) {
-                               return obj;
+               ) {     
+                       odm_matches = 1;
+               }
+
+               if (!odm_matches) continue;
+
+               if (obj->odm) {
+                       Bool can_reuse = 1;
+                       Bool timeline_locked = (obj->odm->flags & GF_ODM_INHERIT_TIMELINE) ? 1 : 0;
+                       if (timeline_locked != lock_timelines) 
+                               continue;
+
+                       gf_term_lock_media_queue(scene->root_od->term, 1);
+                       if (obj->odm->flags & GF_ODM_DESTROYED) can_reuse = 0;
+                       else if (obj->odm->action_type == GF_ODM_ACTION_DELETE) {
+                               /*check if object is being destroyed (no longer in the queue)*/
+                               if (gf_list_del_item(scene->root_od->term->media_queue, obj->odm)<0) { 
+                                       can_reuse = 0;
+                               } 
+                               /*otherwise reuse object, discard current destroy command*/
+                               else {
+                                       obj->odm->action_type = GF_ODM_ACTION_PLAY;
+                               }
                        }
+                       gf_term_lock_media_queue(scene->root_od->term, 0);
+                       if (!can_reuse) continue;
+
+               }
+
+               if (!first_pass && !force_new_if_not_attached) {
+                       if (node && (gf_list_find(obj->nodes, node)<0))
+                               gf_list_add(obj->nodes, node);
+                       gf_term_lock_net(scene->root_od->term, 0);
+                       return obj;
+               }
+               /*special case where the URL is requested twice for the same node: use the existing resource*/
+               else if (node && (gf_list_find(obj->nodes, node)>=0)) {
+                       gf_term_lock_net(scene->root_od->term, 0);
+                       return obj;
                }
        }
        if (first_pass) {
@@ -686,7 +741,10 @@ restart:
        }
 
        /*we cannot create an OD manager at this point*/
-       if (obj_type_hint==GF_MEDIA_OBJECT_UNDEF) return NULL;
+       if (obj_type_hint==GF_MEDIA_OBJECT_UNDEF) {
+               gf_term_lock_net(scene->root_od->term, 0);
+               return NULL;
+       }
 
        /*create a new object identification*/
        obj = gf_mo_new();
@@ -711,16 +769,21 @@ restart:
                gf_sg_vrml_copy_mfurl(&obj->URLs, url);
                gf_scene_insert_object(scene, obj, lock_timelines, sync_ref, keep_fragment, original_parent_scene);
                /*safety check!!!*/
-               if (gf_list_find(scene->scene_objects, obj)<0) 
+               if (gf_list_find(scene->scene_objects, obj)<0) {
+                       gf_term_lock_net(scene->root_od->term, 0);
                        return NULL;
+               }
 
                if (obj->odm==NULL) {
                        gf_list_del_item(scene->scene_objects, obj); 
                        if (obj->nodes) gf_list_del(obj->nodes);
                        gf_free(obj);
+                       gf_term_lock_net(scene->root_od->term, 0);
                        return NULL;
                }
        }
+
+       gf_term_lock_net(scene->root_od->term, 0);
        return obj;
 }
 
@@ -742,6 +805,9 @@ void gf_scene_setup_object(GF_Scene *scene, GF_ObjectManager *odm)
 
        i=0;
        while ((obj = (GF_MediaObject*)gf_list_enum(scene->scene_objects, &i))) {
+               /*make sure services are different*/
+               if (obj->odm && (odm->net_service != obj->odm->net_service)) continue;
+
                if (obj->OD_ID==GF_MEDIA_EXTERNAL_ID) {
                        //assert(obj->odm);
                        if (obj->odm == odm) {
@@ -812,6 +878,8 @@ void gf_scene_set_duration(GF_Scene *scene)
        if (scene->duration == max_dur) return;
 
        scene->duration = max_dur;
+       if (scene->is_dynamic_scene && !scene->root_od->duration) scene->root_od->duration = max_dur;
+
        dur = (Double) (s64) scene->duration;
        dur /= 1000;
        
@@ -955,7 +1023,7 @@ static void set_media_url(GF_Scene *scene, SFURL *media_url, GF_Node *node,  MFU
                                if (!odm->codec || ((odm->codec->type!=type) && (odm->codec->type!=GF_STREAM_ND_SUBPIC))) continue;
                        }
                        else if (type==GF_STREAM_SCENE) {
-                               if (!odm->subscene || !odm->subscene->scene_codec) continue;
+                               if (!odm->subscene || (!odm->subscene->scene_codec && !odm->subscene->is_dynamic_scene) ) continue;
                        }
                        else {
                                if (!odm->codec || (odm->codec->type!=type)) continue;
@@ -965,9 +1033,9 @@ static void set_media_url(GF_Scene *scene, SFURL *media_url, GF_Node *node,  MFU
                        if (media_url->OD_ID==GF_MEDIA_EXTERNAL_ID) media_url->url = gf_strdup(odm->net_service->url);
 
                        if (!scene->dyn_ck) {
-                               if (odm->subscene) {
+                               if (odm->subscene && odm->subscene->scene_codec) {
                                        scene->dyn_ck = odm->subscene->scene_codec->ck;
-                               } else {
+                               } else if (odm->codec) {
                                        scene->dyn_ck = odm->codec->ck;
                                }
                        }
@@ -1022,7 +1090,7 @@ void gf_scene_regenerate(GF_Scene *scene)
        M_AnimationStream *as;
        M_Inline *dims;
 
-       if (!scene->is_dynamic_scene) return;
+       if (scene->is_dynamic_scene != 1) return;
 
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Inline] Regenerating scene graph for service %s\n", scene->root_od->net_service->url));
 
@@ -1037,6 +1105,12 @@ void gf_scene_regenerate(GF_Scene *scene)
                gf_sg_set_root_node(scene->graph, n1);
                gf_node_register(n1, NULL);
 
+               if (! scene->root_od->parentscene) {
+                       n2 = is_create_node(scene->graph, TAG_MPEG4_Background2D, "DYN_BACK");
+                       gf_node_list_add_child( &((GF_ParentNode *)n1)->children, n2);
+                       gf_node_register(n2, n1);
+               }
+
                /*create an sound2D and an audioClip node*/
                n2 = is_create_node(scene->graph, TAG_MPEG4_Sound2D, NULL);
                gf_node_list_add_child( &((GF_ParentNode *)n1)->children, n2);
@@ -1222,26 +1296,36 @@ void gf_scene_select_object(GF_Scene *scene, GF_ObjectManager *odm)
 void gf_scene_restart_dynamic(GF_Scene *scene, u64 from_time)
 {
        u32 i;
+       GF_Clock *ck;
        GF_List *to_restart;
        GF_ObjectManager *odm;
 
-       GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[InlineScene] Restarting from "LLD"\n", LLD_CAST from_time));
+       GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[Scene] Restarting from "LLD"\n", LLD_CAST from_time));
+
+       ck = scene->dyn_ck;
+       if (scene->scene_codec) ck = scene->scene_codec->ck;
+       if (!ck) return;
+
        to_restart = gf_list_new();
+
+
        i=0;
        while ((odm = (GF_ObjectManager*)gf_list_enum(scene->resources, &i))) {
-               if (odm->state != GF_ODM_STATE_BLOCKED) {
-                       gf_list_add(to_restart, odm);
-                       if (odm->state == GF_ODM_STATE_PLAY) {
-                               gf_odm_stop(odm, 1);
+               if (gf_odm_shares_clock(odm, ck)) {
+                       if (odm->state != GF_ODM_STATE_BLOCKED) {
+                               gf_list_add(to_restart, odm);
+                               if (odm->state == GF_ODM_STATE_PLAY) {
+                                       gf_odm_stop(odm, 1);
+                               }
                        }
                }
        }
 
        /*reset clock*/
-       if (scene->dyn_ck) {
-               gf_clock_reset(scene->dyn_ck);
-               scene->simulation_time = from_time/1000.0;
-       }
+       gf_clock_reset(ck);
+       scene->simulation_time = from_time/1000.0;
+       if (!scene->is_dynamic_scene) gf_clock_set_time(ck, 0);
+
        /*restart objects*/
        i=0;
        while ((odm = (GF_ObjectManager*)gf_list_enum(to_restart, &i))) {
@@ -1251,7 +1335,7 @@ void gf_scene_restart_dynamic(GF_Scene *scene, u64 from_time)
        gf_list_del(to_restart);
 
        /*also check nodes since they may be deactivated (end of stream)*/
-       {
+       if (scene->is_dynamic_scene) {
                M_AudioClip *ac = (M_AudioClip *) gf_sg_find_node_by_name(scene->graph, "DYN_AUDIO");
                M_MovieTexture *mt = (M_MovieTexture *) gf_sg_find_node_by_name(scene->graph, "DYN_VIDEO");
                M_AnimationStream *as = (M_AnimationStream *) gf_sg_find_node_by_name(scene->graph, "DYN_TEXT");
@@ -1447,6 +1531,13 @@ Bool gf_scene_is_over(GF_SceneGraph *sg)
        return 1;
 }
 
+GF_SceneGraph *gf_scene_enum_extra_scene(GF_SceneGraph *sg, u32 *i)
+{
+       GF_Scene *scene = gf_sg_get_private(sg);
+       if (!scene) return NULL;
+       return gf_list_enum(scene->extra_scenes, i);
+}
+
 #define USE_TEXTURES   0
 
 void gf_scene_generate_views(GF_Scene *scene, char *url)
@@ -1516,7 +1607,7 @@ void gf_scene_generate_views(GF_Scene *scene, char *url)
        gf_sg_set_scene_size_info(scene->graph, 0, 0, 1);
        gf_sc_set_scene(scene->root_od->term->compositor, scene->graph);
        scene->graph_attached = 1;
-       scene->is_dynamic_scene = 1;
+       scene->is_dynamic_scene = 2;
 
        evt.type = GF_EVENT_CONNECT;
        evt.connect.is_connected = 1;
index 3eb6d68c385719611073c44bd5c14104306afd8c..bd44c1d1f2664794a7ac8210d9141a5f2729c44b 100644 (file)
 #include <gpac/xml.h>
 #include "../utils/module_wrap.h"
 
+#include "media_control.h"
+
 /*textual command processing*/
 #include <gpac/scene_manager.h>
 
 #include "media_memory.h"
 
+
+/*creates service for given OD / URL
+SHALL ONLY BE USED BY MAIN CLIENT*/
+static void gf_term_connect_object(GF_Terminal *app, GF_ObjectManager *odm, char *serviceURL, char *parent_url);
+
 void gf_term_load_shortcuts(GF_Terminal *term);
 
 u32 gf_term_get_time(GF_Terminal *term)
@@ -127,6 +134,54 @@ static Bool term_script_action(void *opaque, u32 type, GF_Node *n, GF_JSAPIParam
                return 1;
        }
 
+       /*special case for pause/stop/resume*/
+       if (type==GF_JSAPI_OP_PAUSE_SVG) {
+               GF_SceneGraph *graph = gf_node_get_graph(n);
+               if (n == gf_sg_get_root_node(graph)) {
+                       GF_Scene *scene = (GF_Scene *)gf_sg_get_private(graph);
+                       GF_Clock *ck = scene->scene_codec ? scene->scene_codec->ck : scene->dyn_ck;
+                       if (ck) gf_clock_pause(ck);
+                       return 1;
+               }
+       }
+       if (type==GF_JSAPI_OP_RESUME_SVG) {
+               GF_SceneGraph *graph = gf_node_get_graph(n);
+               if (n == gf_sg_get_root_node(graph)) {
+                       GF_Scene *scene = (GF_Scene *)gf_sg_get_private(graph);
+                       GF_Clock *ck = scene->scene_codec ? scene->scene_codec->ck : scene->dyn_ck;
+                       if (ck) gf_clock_resume(ck);
+                       return 1;
+               }
+       }
+       if (type==GF_JSAPI_OP_RESTART_SVG) {
+               GF_SceneGraph *graph = gf_node_get_graph(n);
+               if (n == gf_sg_get_root_node(graph)) {
+                       GF_Scene *scene = (GF_Scene *)gf_sg_get_private(graph);
+                       GF_Clock *ck = scene->scene_codec ? scene->scene_codec->ck : scene->dyn_ck;
+                       if (ck) {
+                               Bool is_paused = ck->Paused;
+                               if (is_paused) gf_clock_resume(ck);
+                               gf_scene_restart_dynamic(scene, 0);
+                               if (is_paused) gf_clock_pause(ck);
+                       }
+                       return 1;
+               }
+               return 0;
+       }
+       if (type==GF_JSAPI_OP_SET_SCENE_SPEED) {
+               GF_SceneGraph *graph = gf_node_get_graph(n);
+               if (n == gf_sg_get_root_node(graph)) {
+                       GF_Scene *scene = (GF_Scene *)gf_sg_get_private(graph);
+                       GF_Clock *ck = scene->scene_codec ? scene->scene_codec->ck : scene->dyn_ck;
+                       if (ck) {
+                               gf_clock_set_speed(ck, param->val);
+                       }
+                       return 1;
+               }
+               return 0;
+       }
+
+
        ret = gf_sc_script_action(term->compositor, type, n, param);
        if (ret) return ret;
 
@@ -244,7 +299,6 @@ static Bool term_check_locales(void *__self, const char *locales_parent_path, co
 static void gf_term_reload_cfg(GF_Terminal *term)
 {
        const char *sOpt;
-       Double fps;
        u32 mode;
        s32 prio;
 
@@ -264,14 +318,12 @@ static void gf_term_reload_cfg(GF_Terminal *term)
        else
                term->flags &= ~GF_TERM_SINGLE_CLOCK;
 
-       sOpt = gf_cfg_get_key(term->user->config, "Compositor", "FrameRate");
+       sOpt = gf_cfg_get_key(term->user->config, "Systems", "TimeSlice");
        if (!sOpt) {
-               sOpt = "30.0";
-               gf_cfg_set_key(term->user->config, "Compositor", "FrameRate", "30.0");
+               sOpt = "30";
+               gf_cfg_set_key(term->user->config, "Systems", "TimeSlice", "30");
        }
-       fps = atof(sOpt);
-       term->frame_duration = (u32) (1000/fps);
-       gf_sc_set_fps(term->compositor, fps);
+       term->frame_duration = atoi(sOpt);
 
        if (!(term->user->init_flags & GF_TERM_NO_DECODER_THREAD) ){
                prio = GF_THREAD_PRIORITY_NORMAL;
@@ -528,7 +580,7 @@ GF_Terminal *gf_term_new(GF_User *user)
 
        tmp->net_services = gf_list_new();
        tmp->net_services_to_remove = gf_list_new();
-       tmp->net_services_to_connect = gf_list_new();
+       tmp->connection_tasks = gf_list_new();
        tmp->channels_pending = gf_list_new();
        tmp->media_queue = gf_list_new();
        tmp->media_queue_mx = gf_mx_new("MediaQueue");
@@ -681,8 +733,8 @@ GF_Err gf_term_del(GF_Terminal * term)
        gf_sc_del(term->compositor);
 
        gf_list_del(term->net_services);
-       gf_list_del(term->net_services_to_connect);
        gf_list_del(term->net_services_to_remove);
+       gf_list_del(term->connection_tasks);
        gf_list_del(term->input_streams);
        gf_list_del(term->x3d_sensors);
        assert(!gf_list_count(term->channels_pending));
@@ -774,18 +826,36 @@ void gf_term_connect_with_path(GF_Terminal * term, const char *URL, const char *
 GF_EXPORT
 void gf_term_disconnect(GF_Terminal *term)
 {
+       Bool handle_services;
        if (!term->root_scene) return;
        /*resume*/
        if (term->play_state != GF_STATE_PLAYING) gf_term_set_play_state(term, GF_STATE_PLAYING, 1, 1);
 
        if (term->root_scene->root_od) {
-               gf_odm_disconnect(term->root_scene->root_od, 1);
+
+               gf_term_lock_media_queue(term, 1);
+
+               term->root_scene->root_od->action_type = GF_ODM_ACTION_DELETE;
+               if (gf_list_find(term->media_queue, term->root_scene->root_od)<0)
+                       gf_list_add(term->media_queue, term->root_scene->root_od);
+
+               gf_term_lock_media_queue(term, 0);
        } else {
                gf_scene_del(term->root_scene);
                term->root_scene = NULL;
        }
-       while (term->root_scene || gf_list_count(term->net_services_to_remove)) {
-               gf_term_handle_services(term);
+       handle_services = 0;
+       if (term->flags & GF_TERM_NO_DECODER_THREAD) 
+               handle_services = 1;
+       /*if an unthreaded term extension decides to disconnect the scene (validator does so), we must flush services now
+       because we are called from gf_term_handle_services*/
+       if (term->thread_id_handling_services == gf_th_id()) 
+               handle_services = 1;
+
+       while (term->root_scene || gf_list_count(term->net_services_to_remove) || gf_list_count(term->connection_tasks)  || gf_list_count(term->media_queue) ) {
+               if (handle_services) {
+                       gf_term_handle_services(term);
+               }
                gf_sleep(10);
        }
 }
@@ -922,6 +992,13 @@ GF_Err gf_term_set_size(GF_Terminal * term, u32 NewWidth, u32 NewHeight)
        return gf_sc_set_size(term->compositor, NewWidth, NewHeight);
 }
 
+typedef struct
+{
+       GF_ObjectManager *odm;
+       char *service_url, *parent_url;
+} GF_TermConnectObject;
+
+
 void gf_term_handle_services(GF_Terminal *term)
 {
        GF_ClientService *ns;
@@ -929,31 +1006,9 @@ void gf_term_handle_services(GF_Terminal *term)
        /*we could run into a deadlock if some thread has requested opening of a URL. If we cannot
        grab the media queue now, we'll do our management at the next cycle*/
        if (!gf_mx_try_lock(term->media_queue_mx))
-               return;
-
-
-       while (gf_list_count(term->net_services_to_connect)) {
-               GF_ClientService *ns = (GF_ClientService*)gf_list_get(term->net_services_to_connect, 0);
-               GF_ObjectManager *odm = ns->owner;
-               assert(odm);
-
-               gf_list_rem(term->net_services_to_connect, 0);
-               /*unlock media queue before connecting*/
-               gf_mx_v(term->media_queue_mx);
-       
-               /*OK connect*/
-               gf_term_service_media_event(odm, GF_EVENT_MEDIA_BEGIN_SESSION_SETUP);
-               odm->net_service->ifce->ConnectService(odm->net_service->ifce, odm->net_service, odm->net_service->url);
-
-               /*remove pending download session if any*/
-               gf_term_cleanup_pending_session(term, ns);
-
-               /*lock media queue after connecting*/
-               gf_mx_p(term->media_queue_mx);
-       }
-
-       /*!! media queue is still locked here*/
+               return; 
 
+       term->thread_id_handling_services = gf_th_id();
 
        /*play ODs that need it*/
        while (gf_list_count(term->media_queue)) {
@@ -962,7 +1017,7 @@ void gf_term_handle_services(GF_Terminal *term)
                GF_ObjectManager *odm = (GF_ObjectManager *)gf_list_get(term->media_queue, 0);
                gf_list_rem(term->media_queue, 0);
                /*unlock media queue before sending play/pause*/
-               gf_mx_v(term->media_queue_mx);
+               gf_term_lock_media_queue(term, 0);
 
                act_type = odm->action_type;
                odm->action_type = GF_ODM_ACTION_PLAY;
@@ -1000,9 +1055,36 @@ void gf_term_handle_services(GF_Terminal *term)
                }
        
                /*relock before sending play/pause*/
-               gf_mx_p(term->media_queue_mx);
+               gf_term_lock_media_queue(term, 1);
+       }
+
+       /*finally process all connection tasks - we MUST do that after processing ODM tasks, as an ODM might have just destroyed 
+       a service we could query during the connection step*/
+       while (gf_list_count(term->connection_tasks)) {
+               GF_TermConnectObject *connect = gf_list_get(term->connection_tasks, 0);
+               gf_list_rem(term->connection_tasks, 0);
+       
+               /*unlock media queue before sending connect*/
+               gf_term_lock_media_queue(term, 0);
+
+//             gf_mx_p(term->net_mx);
+
+               /*if object has already been attached to its service (eg, task was posted but media_add occured inbetween), ignore*/
+               if (!connect->odm->net_service && !(connect->odm->flags & GF_ODM_DESTROYED) ) {
+                       gf_term_connect_object(term, connect->odm, connect->service_url, connect->parent_url);
+               }
+
+//             gf_mx_v(term->net_mx);
+               
+               gf_free(connect->service_url);
+               if (connect->parent_url) gf_free(connect->parent_url);
+               gf_free(connect);
+
+               /*relock media queue after sending connect*/
+               gf_term_lock_media_queue(term, 1);
        }
-       gf_mx_v(term->media_queue_mx);
+
+       gf_term_lock_media_queue(term, 0);
 
        /*lock to avoid any start attemps from compositor*/
        if (gf_mx_try_lock(term->compositor->mx)) {
@@ -1049,14 +1131,16 @@ void gf_term_handle_services(GF_Terminal *term)
                term->reload_state = 2;
        }
        if (term->reload_state == 2) {
-               if (gf_list_count(term->net_services)) return;
-               term->reload_state = 0;
-               if (term->reload_url) {
-                       gf_term_connect(term, term->reload_url);
-                       gf_free(term->reload_url);
+               if (! gf_list_count(term->net_services)) {
+                       term->reload_state = 0;
+                       if (term->reload_url) {
+                               gf_term_connect(term, term->reload_url);
+                               gf_free(term->reload_url);
+                       }
+                       term->reload_url = NULL;
                }
-               term->reload_url = NULL;
        }
+       term->thread_id_handling_services = 0;
 }
 
 void gf_term_queue_node_traverse(GF_Terminal *term, GF_Node *node)
@@ -1079,30 +1163,58 @@ void gf_term_unqueue_node_traverse(GF_Terminal *term, GF_Node *node)
        gf_sc_lock(term->compositor, 0);
 }
 
+void gf_term_check_connections_for_delete(GF_Terminal *term, GF_ObjectManager *odm)
+{
+       GF_TermConnectObject *ct;
+       u32 i = 0;
+       while (NULL != (ct = (gf_list_enum(term->connection_tasks, &i)))) {
+               if (ct->odm == odm) {
+                       i--;
+                       gf_list_rem(term->connection_tasks, i);
+                       if (ct->parent_url) gf_free(ct->parent_url);
+                       gf_free(ct->service_url);
+                       gf_free(ct);
+               }
+       }
+}
+
 void gf_term_close_service(GF_Terminal *term, GF_ClientService *ns)
 {
-       s32 idx;
        GF_Err e;
 
        /*prevent the media manager / term to access the list of services to destroy, otherwise
        we could unload the module while poping its CloseService() call stack which can lead to 
        random crashes (return adresses no longer valid) - cf any "stress mode" playback of a playlist*/
-       gf_mx_p(term->media_queue_mx);
-       ns->owner = NULL;
-       idx = gf_list_find(term->net_services_to_connect, ns);
-       if (idx>=0) {
-               gf_list_rem(term->net_services_to_connect, idx);
-               e = GF_BAD_PARAM;
-       } else {
-               e = ns->ifce->CloseService(ns->ifce);
+       gf_term_lock_media_queue(term, 1);
+
+#if 0
+       {
+               GF_ObjectManager *odm;
+               u32 i = 0;
+               while (odm = gf_list_enum(term->media_queue, &i)) {
+                       assert(odm->net_service != ns);
+               }
+       }
+
+       {
+               GF_TermConnectObject *ct;
+               u32 i = 0;
+               while (ct = gf_list_enum(term->connection_tasks, &i)) {
+                       assert(ct->odm->net_service != ns);
+               }
        }
+#endif
+
+       ns->owner = NULL;
+       e = ns->ifce->CloseService(ns->ifce);
+
        /*if error don't wait for ACK to remove from main list*/
        if (e) {
                gf_list_del_item(term->net_services, ns);
                if (gf_list_find(term->net_services_to_remove, ns)<0)
                        gf_list_add(term->net_services_to_remove, ns);
        }
-       gf_mx_v(term->media_queue_mx);
+       gf_term_lock_media_queue(term, 0);
 }
 
 void gf_term_lock_compositor(GF_Terminal *term, Bool LockIt)
@@ -1129,7 +1241,7 @@ void gf_term_lock_net(GF_Terminal *term, Bool LockIt)
        }
 }
 
-static void mae_collect_info(GF_ClientService *net, GF_ObjectManager *odm, GF_DOMMediaAccessEvent *mae, u32 transport, u32 *min_time, u32 *min_buffer)
+static void media_event_collect_info(GF_ClientService *net, GF_ObjectManager *odm, GF_DOMMediaEvent *media_event, u32 *min_time, u32 *min_buffer)
 {
        u32 i=0;
        GF_Channel *ch;
@@ -1138,7 +1250,7 @@ static void mae_collect_info(GF_ClientService *net, GF_ObjectManager *odm, GF_DO
                u32 val;
                if (ch->service != net) continue;
 
-               mae->bufferValid = 1;
+               media_event->bufferValid = 1;
                if (ch->BufferTime>0) {
                        if (ch->MaxBuffer) {
                                val = (ch->BufferTime * 100) / ch->MaxBuffer;
@@ -1152,21 +1264,15 @@ static void mae_collect_info(GF_ClientService *net, GF_ObjectManager *odm, GF_DO
                        *min_time = 0;
                        *min_buffer = 0;
                }
-               if (mae->nb_streams<20) {
-                       mae->streams[mae->nb_streams].streamType = ch->esd->decoderConfig->streamType;
-                       mae->streams[mae->nb_streams].mediaType = ch->esd->decoderConfig->objectTypeIndication;
-                       mae->streams[mae->nb_streams].transport = transport;
-                       mae->nb_streams ++;
-               }
        }
 }
 
-void gf_term_service_media_event(GF_ObjectManager *odm, u32 event_type)
+void gf_term_service_media_event_with_download(GF_ObjectManager *odm, u32 event_type, u64 loaded_size, u64 total_size, u32 bytes_per_sec)
 {
 #ifndef GPAC_DISABLE_SVG
        u32 i, count, min_buffer, min_time, transport;
        Bool locked;
-       GF_DOMMediaAccessEvent mae;
+       GF_DOMMediaEvent media_event;
        GF_DOM_Event evt;
        GF_ObjectManager *an_od;
        GF_Scene *scene;
@@ -1175,46 +1281,44 @@ void gf_term_service_media_event(GF_ObjectManager *odm, u32 event_type)
        if (odm->mo) {
                count = gf_list_count(odm->mo->nodes);
                if (!count) return;
-               if (!(gf_node_get_dom_event_filter(gf_list_get(odm->mo->nodes, 0)) & GF_DOM_EVENT_MEDIA_ACCESS))
+               if (!(gf_node_get_dom_event_filter(gf_list_get(odm->mo->nodes, 0)) & GF_DOM_EVENT_MEDIA))
                        return;
        } else {
                count = 0;
        }
 
 
-       memset(&mae, 0, sizeof(GF_DOMMediaAccessEvent));
+       memset(&media_event, 0, sizeof(GF_DOMMediaEvent));
        transport = 0;
-       mae.bufferValid = 0;
-       mae.session_name = odm->net_service->url;
-       if (!strnicmp(mae.session_name, "rtsp:", 5) 
-               || !strnicmp(mae.session_name, "sdp:", 4)
-               || !strnicmp(mae.session_name, "rtp:", 4)
-       ) 
-               transport = 1;
-       else if (!strnicmp(mae.session_name, "dvb:", 4)) 
-               transport = 2;
+       media_event.bufferValid = 0;
+       media_event.session_name = odm->net_service->url;
 
        min_time = min_buffer = (u32) -1;
        scene = odm->subscene ? odm->subscene : odm->parentscene;
        /*get buffering on root OD*/
-       mae_collect_info(odm->net_service, scene->root_od, &mae, transport, &min_time, &min_buffer);
+       media_event_collect_info(odm->net_service, scene->root_od, &media_event, &min_time, &min_buffer);
        /*get buffering on all ODs*/
        i=0;
        while ((an_od = (GF_ObjectManager*)gf_list_enum(scene->resources, &i))) {
-               mae_collect_info(odm->net_service, an_od, &mae, transport, &min_time, &min_buffer);
+               if (odm->net_service == an_od->net_service)
+                       media_event_collect_info(odm->net_service, an_od, &media_event, &min_time, &min_buffer);
        }
 
-       mae.level = min_buffer;
-       mae.remaining_time = INT2FIX(min_time) / 60;
-       mae.status = 0;
+       media_event.level = min_buffer;
+       media_event.remaining_time = INT2FIX(min_time) / 60;
+       media_event.status = 0;
+       media_event.loaded_size = loaded_size;
+       media_event.total_size = total_size;
 
        memset(&evt, 0, sizeof(GF_DOM_Event));
-       evt.mae = &mae;
+       evt.media_event = &media_event;
        evt.type = event_type;
        evt.bubbles = 0;        /*the spec says yes but we force it to NO*/
 
        /*lock scene to prevent concurrent access of scene data*/
        locked = gf_mx_try_lock(odm->term->compositor->mx);
+       if (!locked) return;
+
        for (i=0; i<count; i++) {
                GF_Node *node = gf_list_get(odm->mo->nodes, i);
                gf_dom_event_fire(node, &evt);
@@ -1223,10 +1327,14 @@ void gf_term_service_media_event(GF_ObjectManager *odm, u32 event_type)
                GF_Node *root = gf_sg_get_root_node(scene->graph);
                if (root) gf_dom_event_fire(root, &evt);
        }
-       if (locked) gf_sc_lock(odm->term->compositor, 0);
+       gf_sc_lock(odm->term->compositor, 0);
 #endif
 }
 
+void gf_term_service_media_event(GF_ObjectManager *odm, u32 event_type)
+{
+       gf_term_service_media_event_with_download(odm, event_type, 0, 0, 0);
+}
 
 /* Browses all registered relocators (ZIP-based, ISOFF-based or file-system-based to relocate a URI based on the locale */
 Bool gf_term_relocate_url(GF_Terminal *term, const char *service_url, const char *parent_url, char *out_relocated_url, char *out_localized_url) 
@@ -1244,15 +1352,30 @@ Bool gf_term_relocate_url(GF_Terminal *term, const char *service_url, const char
        return 0;
 }
 
+/*in most cases we cannot directly connect an object, as the request may come from a different thread than the one handling
+ODM disconnection. We could therefore end up attaching an object to a service currently being destroyed because of a concurrent
+odm_disconnect*/
+void gf_term_post_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serviceURL, char *parent_url)
+{
+       GF_TermConnectObject *connect;
+       GF_SAFEALLOC(connect, GF_TermConnectObject);
+       connect->odm = odm;
+       connect->service_url = gf_strdup(serviceURL);
+       connect->parent_url = parent_url ? gf_strdup(parent_url) : NULL;
+
+       gf_term_lock_media_queue(term, 1);
+       gf_list_add(term->connection_tasks, connect);
+       gf_term_lock_media_queue(term, 0);
+}
+
 /*connects given OD manager to its URL*/
-void gf_term_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serviceURL, char *parent_url)
+static void gf_term_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serviceURL, char *parent_url)
 {
        GF_ClientService *ns;
        u32 i, count;
        GF_Err e;
-       Bool reloc_result; 
+       Bool reloc_result, net_locked
        char relocated_url[GF_MAX_PATH], localized_url[GF_MAX_PATH];
-       gf_term_lock_net(term, 1);
 
        /*try to relocate the url*/
        reloc_result = gf_term_relocate_url(term, serviceURL, parent_url, relocated_url, localized_url);
@@ -1290,46 +1413,81 @@ void gf_term_connect_object(GF_Terminal *term, GF_ObjectManager *odm, char *serv
                }
        }
 
-       /*for remoteODs/dynamic ODs, check if one of the running service cannot be used*/
+       /*for remoteODs/dynamic ODs, check if one of the running service cannot be used
+       net mutex may be locked at this time (if another service sends a connect OK)*/
+       net_locked = gf_mx_try_lock(term->net_mx);
        i=0;
        while ( (ns = (GF_ClientService*)gf_list_enum(term->net_services, &i)) ) {
+               /*we shall not have a service scheduled for destruction here*/
+               if (ns->owner && ( (ns->owner->flags & GF_ODM_DESTROYED) || (ns->owner->action_type == GF_ODM_ACTION_DELETE)) )
+                       continue;
+
+               /*if service has timeline locked to its parent scene, only reuse it if new object does as well*/
+               if (ns->owner->flags & GF_ODM_INHERIT_TIMELINE) {
+                       if (!(odm->flags & GF_ODM_INHERIT_TIMELINE)) continue;
+               }
+
                if (gf_term_service_can_handle_url(ns, serviceURL)) {
-                       gf_term_lock_net(term, 0);
+                       if (net_locked) {
+                               gf_term_lock_net(term, 0);
+                               net_locked = 0;
+                       }
 
                        /*wait for service to setup - service may become destroyed if not available*/
                        while (1) {
-                               gf_term_lock_net(term, 1);
+                               net_locked = gf_mx_try_lock(term->net_mx);
                                if (!ns->owner) {
-                                       gf_term_lock_net(term, 0);
+                                       if (net_locked) {
+                                               gf_term_lock_net(term, 0);
+                                               net_locked = 0;
+                                       }
                                        return;
                                }
-                               gf_term_lock_net(term, 0);
+                               if (net_locked) {
+                                       gf_term_lock_net(term, 0);
+                                       net_locked = 0;
+                               }
+
                                if (ns->owner->OD) break;
                                gf_sleep(5);
                        }
+                       
+                       gf_mx_p(term->net_mx);
+                       if (odm->net_service) {
+                               gf_mx_v(term->net_mx);
+                               return;
+                       }
+                       if (odm->flags & GF_ODM_DESTROYED) {
+                               gf_mx_v(term->net_mx);
+                               GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Object has been scheduled for destruction - ignoring object setup\n", odm->OD->objectDescriptorID));
+                               return;
+                       }
                        odm->net_service = ns;
+                       odm->net_service->nb_odm_users ++;
                        gf_odm_setup_entry_point(odm, serviceURL);
+                       gf_mx_v(term->net_mx);
                        return;
                }
        }
+       if (net_locked) 
+               gf_term_lock_net(term, 0);
 
        odm->net_service = gf_term_service_new(term, odm, serviceURL, reloc_result ? NULL : parent_url, &e);
        if (!odm->net_service) {
-               gf_term_lock_net(term, 0);
                gf_term_message(term, serviceURL, "Cannot open service", e);
                gf_odm_disconnect(odm, 1);
                return;
        }
        odm->net_service->nb_odm_users++;
-       gf_term_lock_net(term, 0);
 
-       gf_mx_p(term->media_queue_mx);
        assert(odm->net_service->owner == odm);
-       /*we are all set but we cannot assume it is safe to call connect from this thread, as this could be a
-       script callback (JS locked) and connecting the media could trigger JS calls, which would deadlock*/
-       gf_list_add(term->net_services_to_connect, odm->net_service);
-       
-       gf_mx_v(term->media_queue_mx);
+
+       /*OK connect*/
+       gf_term_service_media_event(odm, GF_EVENT_MEDIA_SETUP_BEGIN);
+       odm->net_service->ifce->ConnectService(odm->net_service->ifce, odm->net_service, odm->net_service->url);
+
+       /*remove pending download session if any*/
+       gf_term_cleanup_pending_session(term, ns);
 }
 
 /*connects given channel to its URL if needed*/
@@ -1835,13 +1993,16 @@ void gf_term_set_speed(GF_Terminal *term, Fixed speed)
                }
        }
 
+       opt = gf_cfg_get_key(term->user->config, "Systems", "TimeSlice");
+       if (!opt) opt="30";     
+       i = (u32) ( atoi(opt) / FIX2FLT(speed) );
+       if (!i) i = 1;
+       term->frame_duration = i;
+
        opt = gf_cfg_get_key(term->user->config, "Compositor", "FrameRate");
-       if (!opt) opt="30.0";
-       
-       fps = atof(opt);
+       fps = atoi(opt);
        fps *= FIX2FLT(speed);
        if (fps>100) fps = 1000;
-       term->frame_duration = (u32) (1000/fps);
        gf_sc_set_fps(term->compositor, fps);
 }
 
@@ -2049,27 +2210,33 @@ void gf_term_load_shortcuts(GF_Terminal *term)
 void gf_scene_switch_quality(GF_Scene *scene, Bool up)
 {
        u32 i;
+       GF_ClientService *root_service = NULL;
        GF_ObjectManager *odm;
        GF_CodecCapability caps;
        GF_NetworkCommand net_cmd;
 
        if (!scene) return;
-       caps.CapCode = GF_CODEC_MEDIA_SWITCH_QUALITY;
-       caps.cap.valueInt = up ? 1 : 0;
+
+       /*send network command*/
        net_cmd.command_type = GF_NET_SERVICE_QUALITY_SWITCH;
        net_cmd.switch_quality.on_channel = NULL;
        net_cmd.switch_quality.up = up;
+       if (scene->root_od->net_service) {
+               root_service = scene->root_od->net_service; 
+               root_service->ifce->ServiceCommand(root_service->ifce, &net_cmd);
+       }
 
+       /*notify all codecs in the scene and subscenes*/
+       caps.CapCode = GF_CODEC_MEDIA_SWITCH_QUALITY;
+       caps.cap.valueInt = up ? 1 : 0;
        if (scene->scene_codec) {
                scene->scene_codec->decio->SetCapabilities(scene->scene_codec->decio, caps);
-               if (scene->root_od->net_service)
-                       scene->root_od->net_service->ifce->ServiceCommand(scene->root_od->net_service->ifce, &net_cmd);
        }
        i=0;
        while (NULL != (odm = gf_list_enum(scene->resources, &i))) {
                if (odm->codec)
                        odm->codec->decio->SetCapabilities(odm->codec->decio, caps);
-               if (odm->net_service)
+               if (odm->net_service && (odm->net_service != root_service) )
                        odm->net_service->ifce->ServiceCommand(odm->net_service->ifce, &net_cmd);
                if (odm->subscene)
                        gf_scene_switch_quality(odm->subscene, up);
index 846fbab1d7e056d696b436d58e69a2017ed73152..7ef1876bce8346543f4e04ff9a29f8faf4c84f31 100644 (file)
@@ -183,6 +183,8 @@ static int unregister_address(void *ptr, char *filename, int line);
 static void gf_memory_log(unsigned int level, const char *fmt, ...);
 enum
 {
+       /*! Disable all Log message*/
+       GF_MEMORY_QUIET = 0,
        /*! Log message describes an error*/
        GF_MEMORY_ERROR = 1,
        /*! Log message describes a warning*/
@@ -538,6 +540,30 @@ static void register_address(void *ptr, size_t size, char *filename, int line)
        gf_mx_v(gpac_allocations_lock);
 }
 
+#if 0
+void gf_check_address(void *ptr)
+{
+       int pos;
+
+       /*lock*/
+       gf_mx_p(gpac_allocations_lock);
+
+       if ( (pos=gf_memory_find(memory_rem, ptr)) ) {
+               int i;
+               unsigned int hash = gf_memory_hash(ptr);
+               memory_element *element = memory_rem[hash];
+               assert(element);
+               for (i=1; i<pos; i++)
+                       element = element->next;
+               assert(element);
+               gf_memory_log(GF_MEMORY_ERROR, "[MemTracker] the block %p has already been freed\n             in file %s at line %d\n", ptr, element->filename, element->line);
+               assert(0);
+       }
+       /*unlock*/
+       gf_mx_v(gpac_allocations_lock);
+}
+#endif
+
 /*returns the size of the unregistered block*/
 static int unregister_address(void *ptr, char *filename, int line)
 {
@@ -562,8 +588,12 @@ static int unregister_address(void *ptr, char *filename, int line)
                                /* assert(0); */ /*don't assert since this is often due to allocations that occured out of gpac (fonts, etc.)*/
                        } else {
                                int i;
+#if GPAC_MEMORY_TRACKING_HASH_TABLE
                                unsigned int hash = gf_memory_hash(ptr);
                                memory_element *element = memory_rem[hash];
+#else
+                               memory_element *element = memory_rem;
+#endif
                                assert(element);
                                for (i=1; i<pos; i++)
                                        element = element->next;
@@ -621,7 +651,7 @@ static void gf_memory_log(unsigned int level, const char *fmt, ...)
 void gf_memory_size()
 {
        unsigned int level = gpac_nb_alloc_blocs ? GF_MEMORY_ERROR : GF_MEMORY_INFO;
-       gf_memory_log(level, "[MemTracker] Total: %d bytes allocated on %d blocks\n", gpac_allocated_memory, gpac_nb_alloc_blocs);
+       gf_memory_log(level, "[MemTracker] Total: %d bytes allocated in %d blocks\n", gpac_allocated_memory, gpac_nb_alloc_blocs);
 }
 
 /*prints the state of current allocations*/
@@ -663,7 +693,7 @@ void gf_memory_print()
 
 
 /*gf_asprintf(): as_printf portable implementation*/
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(WIN32) || defined(_WIN32_WCE) || (defined (__SVR4) && defined (__sun))
 static GFINLINE int gf_vasprintf (char **strp, const char *fmt, va_list ap)
 {
        int vsn_ret, size;
@@ -675,6 +705,9 @@ static GFINLINE int gf_vasprintf (char **strp, const char *fmt, va_list ap)
                return -1;
 
        while (1) {
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#define _vsnprintf vsnprintf
+#endif
                vsn_ret = _vsnprintf(buffer, size, fmt, ap);
 
                /* If that worked, return the string. */
@@ -702,7 +735,7 @@ int gf_asprintf(char **strp, const char *fmt, ...)
        s32 size;
        va_list args;
        va_start(args, fmt);
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(WIN32) || defined(_WIN32_WCE) || (defined (__SVR4) && defined (__sun))
        size = gf_vasprintf(strp, fmt, args);
 #else
        size = asprintf(strp, fmt, args);
index 52297750ada8d8b495a069627955d01cfee262ea..509185065523d3365dbe7f4dbd0f4ec247446ef2 100644 (file)
@@ -493,7 +493,7 @@ u32 gf_bs_write_byte(GF_BitStream *bs, u8 byte, u32 repeat_count)
                return repeat_count;
        case GF_BITSTREAM_FILE_READ:
        case GF_BITSTREAM_FILE_WRITE:
-               if (fwrite(&byte, 1, repeat_count, bs->stream) != repeat_count) return 0;
+               if (gf_fwrite(&byte, 1, repeat_count, bs->stream) != repeat_count) return 0;
                if (bs->size == bs->position) bs->size += repeat_count;
                bs->position += repeat_count;
                return repeat_count;
@@ -564,7 +564,7 @@ u32 gf_bs_write_data(GF_BitStream *bs, const char *data, u32 nbBytes)
                        return nbBytes;
                case GF_BITSTREAM_FILE_READ:
                case GF_BITSTREAM_FILE_WRITE:
-                       if (fwrite(data, nbBytes, 1, bs->stream) != 1) return 0;
+                       if (gf_fwrite(data, nbBytes, 1, bs->stream) != 1) return 0;
                        if (bs->size == bs->position) bs->size += nbBytes;
                        bs->position += nbBytes;
                        return nbBytes;
index 318d45d2f1a524302c6774e2d671985b2766463a..8745c8b50850c263adee1baa50f68315faf15820 100644 (file)
@@ -560,11 +560,11 @@ GF_Err gf_cache_open_write_cache( const DownloadedCacheEntry entry, const GF_Dow
        entry->write_session = sess;
        assert( ! entry->writeFilePtr);
        GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK,
-               ("[CACHE] Opening cache file %s for write (%s)...", entry->cache_filename, entry->url));
+               ("[CACHE] Opening cache file %s for write (%s)...\n", entry->cache_filename, entry->url));
        entry->writeFilePtr = gf_f64_open(entry->cache_filename, "wb");
        if (!entry->writeFilePtr) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK,
-                       ("[CACHE] Error while opening cache file %s for writting.", entry->cache_filename));
+                       ("[CACHE] Error while opening cache file %s for writting.\n", entry->cache_filename));
                entry->write_session = NULL;
 #ifdef ENABLE_WRITE_MX
                gf_mx_v(entry->write_mutex);
@@ -583,7 +583,7 @@ GF_Err gf_cache_write_to_cache( const DownloadedCacheEntry entry, const GF_Downl
                GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("Incorrect parameter : data=%p, entry->writeFilePtr=%p at "__FILE__, data, entry->writeFilePtr));
                return GF_BAD_PARAM;
        }
-       readen = fwrite(data, sizeof(char), size, entry->writeFilePtr);
+       readen = gf_fwrite(data, sizeof(char), size, entry->writeFilePtr);
        if (readen > 0)
                entry->written_in_cache+= readen;
        if (readen != size) {
index 91620636092f2e777a466746abeccd8df80e4712..3504752e4b8dc7aa6194e31d99eb72ed3b5ddd8b 100644 (file)
@@ -223,13 +223,13 @@ static s32 mul255(s32 a, s32 b)
 }
 
 typedef void (*copy_row_proto)(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha);
-typedef void (*load_line_proto)(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits);
+typedef void (*load_line_proto)(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 src_width, u32 src_height, u8 *dst_bits);
 
 static void copy_row_rgb_555(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
        s32 pos;
        u16 *dst = (u16 *)_dst;
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
        x_pitch /= 2;
        pos = 0x10000;
        while (dst_w) {
@@ -248,7 +248,7 @@ static void copy_row_rgb_565(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc,
 {
        s32 pos;
        u16 *dst = (u16 *)_dst;
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
        x_pitch /= 2;
        pos = 0x10000;
        while (dst_w) {
@@ -267,7 +267,7 @@ static void copy_row_rgb_565(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc,
 static void copy_row_rgb_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
        s32 pos;
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
 
        pos = 0x10000;
        while (dst_w) {
@@ -285,7 +285,7 @@ static void copy_row_rgb_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s
 static void copy_row_bgr_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
        s32 pos;
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
 
        pos = 0x10000;
        while (dst_w) {
@@ -302,7 +302,7 @@ static void copy_row_bgr_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s
 
 static void copy_row_bgrx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
        s32 pos = 0x10000L;
 
        while (dst_w) {
@@ -324,7 +324,7 @@ static void copy_row_bgrx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32
 
 static void copy_row_rgbx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
        s32 pos = 0x10000L;
 
        while ( dst_w) {
@@ -346,7 +346,7 @@ static void copy_row_rgbx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32
 
 static void copy_row_rgbd(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u8 a, r, g, b;
+       u8 a=0, r=0, g=0, b=0;
        s32 pos = 0x10000L;
 
        while ( dst_w) {
@@ -368,7 +368,7 @@ static void copy_row_rgbd(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32
 
 static void merge_row_rgb_555(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
        u16 col, *dst = (u16 *)_dst;
        x_pitch /= 2;
@@ -397,7 +397,7 @@ static void merge_row_rgb_555(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc
 
 static void merge_row_rgb_565(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
        u16 col, *dst = (u16 *)_dst;
        x_pitch /= 2;
@@ -427,7 +427,7 @@ static void merge_row_rgb_565(u8 *src, u32 src_w, u8 *_dst, u32 dst_w, s32 h_inc
 
 static void merge_row_rgb_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
 
        pos = 0x10000;
@@ -451,7 +451,7 @@ static void merge_row_rgb_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc,
 
 static void merge_row_bgr_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
 
        pos = 0x10000;
@@ -479,7 +479,7 @@ static void merge_row_bgr_24(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc,
 
 static void merge_row_bgrx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
 
        pos = 0x10000;
@@ -512,7 +512,7 @@ static void merge_row_bgrx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s3
 
 static void merge_row_rgbx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _r, _g, _b, a, r, g, b;
+       u32 _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
 
        pos = 0x10000;
@@ -544,7 +544,7 @@ static void merge_row_rgbx(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s3
 
 static void merge_row_bgra(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _a, _r, _g, _b, a, r, g, b;
+       u32 _a, _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
 
        pos = 0x10000;
@@ -583,7 +583,7 @@ static void merge_row_bgra(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s3
 
 static void merge_row_rgba(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s32 x_pitch, u8 alpha)
 {
-       u32 _a, _r, _g, _b, a, r, g, b;
+       u32 _a, _r, _g, _b, a=0, r=0, g=0, b=0;
        s32 pos;
        pos = 0x10000;
        while (dst_w) {
@@ -619,13 +619,36 @@ static void merge_row_rgba(u8 *src, u32 src_w, u8 *dst, u32 dst_w, s32 h_inc, s3
        }
 }
 
+
+static void load_line_grey(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
+{
+       u32 i;
+       src_bits += x_offset + y_offset*y_pitch;
+       for (i=0; i<width; i++) {
+               dst_bits[0] = dst_bits[1] = dst_bits[2] = *src_bits++;
+               dst_bits[3] = 0xFF;
+               dst_bits+=4;
+       }
+}
+
+static void load_line_alpha_grey(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
+{
+       u32 i;
+       src_bits += x_offset*2 + y_offset*y_pitch;
+       for (i=0; i<width; i++) {
+               dst_bits[0] = dst_bits[1] = dst_bits[2] = *src_bits++;
+               dst_bits[3] = *src_bits++;
+               dst_bits+=4;
+       }
+}
+
 static GFINLINE u8 colmask(s32 a, s32 n)
 {
     s32 mask = (1 << n) - 1;
     return (u8) (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
 }
 
-static void load_line_rgb_555(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgb_555(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*3 + y_offset*y_pitch;
@@ -639,7 +662,7 @@ static void load_line_rgb_555(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pi
        }
 }
 
-static void load_line_rgb_565(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgb_565(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*3 + y_offset*y_pitch;
@@ -653,7 +676,7 @@ static void load_line_rgb_565(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pi
        }
 }
 
-static void load_line_rgb_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgb_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*3 + y_offset*y_pitch;
@@ -666,7 +689,7 @@ static void load_line_rgb_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pit
        }
 }
 
-static void load_line_bgr_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_bgr_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*3 + y_offset*y_pitch;
@@ -679,7 +702,7 @@ static void load_line_bgr_24(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pit
        }
 }
 
-static void load_line_rgb_32(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgb_32(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*4 + y_offset*y_pitch;
@@ -692,7 +715,7 @@ static void load_line_rgb_32(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pit
        }
 }
 
-static void load_line_rgbd(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgbd(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*4 + y_offset*y_pitch;
@@ -706,7 +729,7 @@ static void load_line_rgbd(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch
        }
 }
 
-static void load_line_rgbds(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_rgbds(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*4 + y_offset*y_pitch;
@@ -719,7 +742,7 @@ static void load_line_rgbds(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitc
        }
 }
 
-static void load_line_argb(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_argb(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u32 i;
        src_bits += x_offset*4 + y_offset*y_pitch;
@@ -732,7 +755,7 @@ static void load_line_argb(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch
        }
 }
 
-static void load_line_bgr_32(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_bgr_32(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        src_bits += x_offset*4 + y_offset*y_pitch;
        memcpy(dst_bits, src_bits, sizeof(char)*4*width);
@@ -765,7 +788,7 @@ static void load_line_yuva(char *src_bits, u32 x_offset, u32 y_offset, u32 y_pit
        gf_yuva_load_lines(dst_bits, 4*width, pY, pU, pV, pA, y_pitch, y_pitch/2, width);
 }
 
-static void load_line_yuyv(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u8 *dst_bits)
+static void load_line_yuyv(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
 {
        u8 *pY, *pU, *pV;
        pY = (u8 *)src_bits + x_offset + y_offset*y_pitch;
@@ -774,6 +797,52 @@ static void load_line_yuyv(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch
        gf_yuv_load_lines_packed((unsigned char*)dst_bits, 4*width, pY, pU, pV, width);
 }
 
+/*Ivica patch - todo, align it with other YUV loader (2 lines at a time) to avoid fetching twice U and V*/
+static void load_line_YUV420SP(u8 *src_bits, u32 x_offset, u32 y_offset, u32 y_pitch, u32 width, u32 height, u8 *dst_bits)
+{
+       s32 frameSize = width * height;
+       s32 j, yp, uvp, y, y1192, r, g, b, u, v;
+       u32 i;
+
+       yp = (s32)(x_offset + y_offset * y_pitch / 1.5f);
+       j = y_offset;
+
+       uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+
+       for (i=0; i<width; i++, yp++) {
+
+               y = (0xff & ((int) src_bits[yp])) - 16;
+               if (y < 0) y = 0;
+               if ((i & 1) == 0)
+               {
+                       v = (0xff & src_bits[uvp++]) - 128;
+                       u = (0xff & src_bits[uvp++]) - 128;
+               }
+
+               y1192 = 1192 * y;
+               r = (y1192 + 1634 * v);
+               g = (y1192 - 833 * v - 400 * u);
+               b = (y1192 + 2066 * u);
+
+               if (r < 0)
+                       r = 0;
+               else if (r > 262143)
+                       r = 262143;
+               if (g < 0)
+                       g = 0;
+               else if (g > 262143)
+                       g = 262143;
+               if (b < 0)
+                       b = 0;
+               else if (b > 262143)
+                       b = 262143;
+
+               *((u32*)dst_bits) = 0xff000000 | ((b << 6) & 0xff0000)
+                                       | ((g >> 2) & 0xff00) | ((r >> 10) & 0xff);
+               dst_bits+=4;
+       }
+}
+
 
 static void gf_cmx_apply_argb(GF_ColorMatrix *_this, u8 *a_, u8 *r_, u8 *g_, u8 *b_);
 
@@ -790,7 +859,7 @@ GF_Err gf_stretch_bits(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *ds
        u32 dst_bpp, dst_w_size;
        s32 pos_y, inc_y, inc_x, prev_row, x_off;
        u32 src_w, src_h, dst_w, dst_h;
-       u8 *src_bits = NULL, *dst_bits = NULL, *dst_bits_prev = NULL, *dst_temp_bits = NULL;
+       u8 *dst_bits = NULL, *dst_bits_prev = NULL, *dst_temp_bits = NULL;
        s32 dst_x_pitch = dst->pitch_x;
 
        copy_row_proto copy_row = NULL;
@@ -800,6 +869,13 @@ GF_Err gf_stretch_bits(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *ds
        else if (key && (key->alpha<0xFF)) has_alpha = 1;
 
        switch (src->pixel_format) {
+       case GF_PIXEL_GREYSCALE:
+               load_line = load_line_grey;
+               break;
+       case GF_PIXEL_ALPHAGREY:
+               load_line = load_line_alpha_grey;
+               has_alpha = 1;
+               break;
        case GF_PIXEL_RGB_555:
                load_line = load_line_rgb_555;
                break;
@@ -839,6 +915,9 @@ GF_Err gf_stretch_bits(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *ds
                yuv2rgb_init();
                yuv_planar_type = 1;
                break;
+       case GF_PIXEL_NV21:
+               load_line = load_line_YUV420SP;
+               break;
        case GF_PIXEL_YUVA:
                has_alpha = 1;
        case GF_PIXEL_YUVD:
@@ -909,7 +988,6 @@ GF_Err gf_stretch_bits(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *ds
        tmp = (u8 *) gf_malloc(sizeof(u8) * src_w * (yuv_planar_type ? 8 : 4) );
        rows = tmp;
 
-       src_bits = (u8 *) src->video_buffer;
        dst_bits = (u8 *) dst->video_buffer;
 
        pos_y = 0x10000;
@@ -1002,7 +1080,7 @@ GF_Err gf_stretch_bits(GF_VideoSurface *dst, GF_VideoSurface *src, GF_Window *ds
                                }
                        } else {
                                if (flip) the_row = src->height-1 - the_row;
-                               load_line((u8*)src->video_buffer, x_off, the_row, src->pitch_y, src_w, tmp);
+                               load_line((u8*)src->video_buffer, x_off, the_row, src->pitch_y, src_w, src->height, tmp);
                                rows = tmp;
                                if (cmat) {
                                        for (i=0; i<src_w; i++) {
index 0556facce82f36e055d3c78b05478d261b7b8fcb..97a5e9819ddbbb90a42a0cfc72e09af105ba0cb8 100644 (file)
@@ -284,6 +284,26 @@ get_key:
        return NULL;
 }
 
+GF_EXPORT
+const char *gf_cfg_get_ikey(GF_Config *iniFile, const char *secName, const char *keyName)
+{
+        u32 i;
+        IniSection *sec;
+        IniKey *key;
+
+        i=0;
+        while ( (sec = (IniSection *) gf_list_enum(iniFile->sections, &i)) ) {
+                if (!stricmp(secName, sec->section_name)) goto get_key;
+        }
+        return NULL;
+
+get_key:
+        i=0;
+        while ( (key = (IniKey *) gf_list_enum(sec->keys, &i)) ) {
+                if (!stricmp(key->name, keyName)) return key->value;
+        }
+        return NULL;
+}
 
 
 GF_EXPORT
index 3b4e063e76fe2567f2c35e365cf32bbec40089d8..8a7763e61f35280f50395c9492eaf7d7992537e5 100644 (file)
@@ -60,20 +60,20 @@ static void gf_dm_connect(GF_DownloadSession *sess);
 /*internal flags*/
 enum
 {
-    GF_DOWNLOAD_SESSION_USE_SSL                =       1<<10,
-    GF_DOWNLOAD_SESSION_THREAD_DEAD    =       1<<11
+       GF_DOWNLOAD_SESSION_USE_SSL             =       1<<10,
+       GF_DOWNLOAD_SESSION_THREAD_DEAD =       1<<11
 };
 
 typedef struct __gf_user_credentials
 {
-    char site[1024];
-    char username[50];
-    char digest[1024];
-    Bool valid;
+       char site[1024];
+       char username[50];
+       char digest[1024];
+       Bool valid;
 } gf_user_credentials_struct;
 
 enum REQUEST_TYPE {
-    GET = 0,
+       GET = 0,
     HEAD = 1,
     OTHER = 2
 };
@@ -135,7 +135,8 @@ struct __gf_download_session
     /* True if cache file must be stored on disk */
     Bool use_cache_file;
        Bool disable_cache;
-
+       /*forces notification of data exchange to be sent regardless of threading mode*/
+       Bool force_data_write_callback;
 #ifdef GPAC_HAS_SSL
     SSL *ssl;
 #endif
@@ -595,6 +596,9 @@ void gf_dm_delete_cached_file_entry_session(const GF_DownloadSession * sess,  co
 
 static void gf_dm_disconnect(GF_DownloadSession *sess, Bool force_close)
 {
+    assert( sess );
+    if (sess->status >= GF_NETIO_DISCONNECTED)
+       return;
     GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Downloader] gf_dm_disconnect(%p)\n", sess ));
     if (sess->mx)
         gf_mx_p(sess->mx);
@@ -608,8 +612,10 @@ static void gf_dm_disconnect(GF_DownloadSession *sess, Bool force_close)
                }
 #endif
                if (sess->sock) {
-                       gf_sk_del(sess->sock);
+                       GF_Socket * sx = sess->sock;
                        sess->sock = NULL;
+                       gf_sk_del(sx);
+                       //sess->sock = NULL;
                }
        }
     sess->status = GF_NETIO_DISCONNECTED;
@@ -1007,12 +1013,8 @@ GF_DownloadSession *gf_dm_sess_new_simple(GF_DownloadManager * dm, const char *u
         return NULL;
     }
     assert( sess );
-    if (!(sess->flags & GF_NETIO_SESSION_NOT_THREADED) ) {
-        sess->th = gf_th_new(url);
-        sess->mx = gf_mx_new(url);
-        gf_th_run(sess->th, gf_dm_session_thread, sess);
-    }
     sess->num_retry = SESSION_RETRY_COUNT;
+       /*threaded session must be started with gf_dm_sess_process*/
     return sess;
 }
 
@@ -1310,6 +1312,21 @@ GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_r
 GF_Err gf_dm_sess_process(GF_DownloadSession *sess)
 {
     Bool go;
+
+       /*if session is threaded, start thread*/
+       if (! (sess->flags & GF_NETIO_SESSION_NOT_THREADED)) {
+               if (sess->th) {
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[HTTP] Session already started - ignoring start\n"));
+                       return GF_OK;
+               }
+               sess->th = gf_th_new(sess->orig_url);
+               if (!sess->th) return GF_OUT_OF_MEM;
+               sess->mx = gf_mx_new(sess->orig_url);
+               if (!sess->mx) return GF_OUT_OF_MEM;
+               gf_th_run(sess->th, gf_dm_session_thread, sess);
+               return GF_OK;
+       }
+       /*otherwise do a synchronous download*/
     go = 1;
     while (go) {
         switch (sess->status) {
@@ -1706,7 +1723,7 @@ GF_EXPORT
 const char *gf_dm_sess_get_cache_name(GF_DownloadSession * sess)
 {
     if (!sess) return NULL;
-    assert( sess->cache_entry );
+    if (! sess->cache_entry )  return NULL;
     return gf_cache_get_cache_filename(sess->cache_entry);
 }
 
@@ -1719,6 +1736,7 @@ Bool gf_dm_sess_can_be_cached_on_disk(const GF_DownloadSession *sess)
 
 void gf_dm_sess_abort(GF_DownloadSession * sess)
 {
+    assert(sess);
     if (sess->mx) {
         gf_mx_p(sess->mx);
         gf_dm_disconnect(sess, 1);
@@ -2030,28 +2048,32 @@ static GF_Err http_parse_remaining_body(GF_DownloadSession * sess, char * sHTTP)
             return GF_OK;
         }
 
-        if (e) {
-           if (e == GF_IP_CONNECTION_CLOSED){
-               u32 len = gf_cache_get_content_length(sess->cache_entry);
-               if (size > 0)
-                       gf_dm_data_received(sess, sHTTP, size);
-               if (len == 0){
-                       sess->total_size = sess->bytes_done;
-                       // HTTP 1.1 without content length...
-                       gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
-                       assert(sess->server_name);
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[HTTP] Disconnected from %s: %s\n", sess->server_name, gf_error_to_string(e)));
-                       sess->status = GF_NETIO_DISCONNECTED;
-                       gf_cache_set_content_length(sess->cache_entry, sess->bytes_done);
-                       e = GF_OK;
+               if (e) {
+                       if (e == GF_IP_CONNECTION_CLOSED){
+                               u32 len = gf_cache_get_content_length(sess->cache_entry);
+                               if (size > 0)
+                                       gf_dm_data_received(sess, sHTTP, size);
+                               if ( ( (len == 0) && sess->use_cache_file) 
+                                       /*ivica patch*/
+                                       || (size==0)
+                               ) {
+                                       sess->total_size = sess->bytes_done;
+                                       // HTTP 1.1 without content length...
+                                       gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
+                                       assert(sess->server_name);
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[HTTP] Disconnected from %s: %s\n", sess->server_name, gf_error_to_string(e)));
+                                       sess->status = GF_NETIO_DISCONNECTED;
+                                       if (sess->use_cache_file) 
+                                               gf_cache_set_content_length(sess->cache_entry, sess->bytes_done);
+                                       e = GF_OK;
+                               }
+                       }
+                       gf_dm_disconnect(sess, 1);
+                       sess->last_error = e;
+                       gf_dm_sess_notify_state(sess, sess->status, e);
+                       return e;
                }
-           }
-            gf_dm_disconnect(sess, 1);
-            sess->last_error = e;
-            gf_dm_sess_notify_state(sess, sess->status, e);
-            return e;
-        }
-        gf_dm_data_received(sess, sHTTP, size);
+               gf_dm_data_received(sess, sHTTP, size);
 
         /*socket empty*/
         if (size < GF_DOWNLOAD_BUFFER_SIZE) return GF_OK;
@@ -2171,16 +2193,23 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
             if (hdr_sep) hdr_sep[0] = 0;
         }
 
-        par.error = 0;
+               /*header signaling is moved after response processing*/
+#if 0
+               par.error = 0;
         par.msg_type = GF_NETIO_PARSE_HEADER;
         par.name = hdr;
         par.value = hdr_val;
-        GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] Processing header %s: %s\n", hdr, hdr_val));
         gf_dm_sess_user_io(sess, &par);
+#endif
+
+        GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] Processing header %s: %s\n", hdr, hdr_val));
 
         if (!stricmp(hdr, "Content-Length") ) {
             ContentLength = (u32) atoi(hdr_val);
             gf_cache_set_content_length(sess->cache_entry, ContentLength);
+                       /*Ivica patch*/
+                       if (ContentLength==0)
+                               sess->use_cache_file = 0;
         }
         else if (!stricmp(hdr, "Content-Type")) {
             char * mime_type = gf_strdup(hdr_val);
@@ -2195,6 +2224,7 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
             }
             hdr = strchr(mime_type, ';');
             if (hdr) hdr[0] = 0;
+           strlwr(mime_type);
             gf_cache_set_mime_type(sess->cache_entry, mime_type);
             gf_free(mime_type);
         }
@@ -2240,12 +2270,11 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
         /*                     else if (!stricmp(hdr, "Connection") )
                                        if (strstr(hdr_val, "close")) sess->http_read_type = 1; */
 
-
         if (sep) sep[0]=':';
         if (hdr_sep) hdr_sep[0] = '\r';
 
 
-               if (sess->status==GF_NETIO_DISCONNECTED) return GF_OK;
+        if (sess->status==GF_NETIO_DISCONNECTED) return GF_OK;
     }
     if (no_range) first_byte = 0;
 
@@ -2321,8 +2350,15 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
                 }
                 return e;
             }
+
+            par.error = 0;
+            par.msg_type = GF_NETIO_PARSE_HEADER;
+            par.name = "Content-Type";
+            par.value = (char *) gf_cache_get_mime_type(sess->cache_entry);
+            gf_dm_sess_user_io(sess, &par);
+
             sess->status = GF_NETIO_DATA_EXCHANGE;
-                       if (! (sess->flags & GF_NETIO_SESSION_NOT_THREADED)) {
+                       if (! (sess->flags & GF_NETIO_SESSION_NOT_THREADED) || sess->force_data_write_callback) {
                 char file_cache_buff[16384];
                 int read = 0;
                 u32 total_size = gf_cache_get_cache_filesize(sess->cache_entry);
@@ -2409,7 +2445,7 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
             return e;
         }
 
-               gf_dm_sess_user_io(sess, &par);
+        gf_dm_sess_user_io(sess, &par);
         e = GF_REMOTE_SERVICE_ERROR;
         goto exit;
 
@@ -2427,6 +2463,36 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP)
         goto exit;
     }
 
+
+    /* FIXME UGLY CODE DUPLICATION to fix later on: we only send the headers to the user if no problem in response (eg no relocation, ...)*/
+    while (1) {
+        char *sep, *hdr_sep, *hdr, *hdr_val;
+        if ( (s32) LinePos + 4 > BodyStart) break;
+        LinePos = gf_token_get_line(sHTTP, LinePos , bytesRead, buf, 1024);
+        if (LinePos < 0) break;
+
+        hdr_sep = NULL;
+        hdr_val = NULL;
+        hdr = buf;
+        sep = strchr(buf, ':');
+        if (sep) {
+            sep[0]=0;
+            hdr_val = sep+1;
+            while (hdr_val[0]==' ') hdr_val++;
+            hdr_sep = strrchr(hdr_val, '\r');
+            if (hdr_sep) hdr_sep[0] = 0;
+        }
+
+        par.error = 0;
+        par.msg_type = GF_NETIO_PARSE_HEADER;
+        par.name = hdr;
+        par.value = hdr_val;
+        gf_dm_sess_user_io(sess, &par);
+        if (sep) sep[0]=':';
+        if (hdr_sep) hdr_sep[0] = '\r';
+    }
+
+
     if (sess->http_read_type != GET)
         sess->use_cache_file = 0;
 
@@ -2535,111 +2601,117 @@ void http_do_requests(GF_DownloadSession *sess)
  */
 static void wget_NetIO(void *cbk, GF_NETIO_Parameter *param)
 {
-    FILE * f = (FILE*) cbk;
+       FILE * f = (FILE*) cbk;
 
-    /*handle service message*/
-    if (param->msg_type == GF_NETIO_DATA_EXCHANGE) {
-               s32 written = fwrite( param->data, sizeof(char), param->size, f);
+       /*handle service message*/
+       if (param->msg_type == GF_NETIO_DATA_EXCHANGE) {
+               s32 written = gf_fwrite( param->data, sizeof(char), param->size, f);
                if (written != param->size) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("Failed to write data on disk\n"));
                }
-    }
+       }
 }
 
 
 GF_Err gf_dm_wget(const char *url, const char *filename){
-    GF_Err e;
-    GF_DownloadManager * dm = NULL;
-    dm = gf_dm_new(NULL);
-    if (!dm)
-        return GF_OUT_OF_MEM;
-    e = gf_dm_wget_with_cache(dm, url, filename);
-    gf_dm_del(dm);
-    return e;
+       GF_Err e;
+       GF_DownloadManager * dm = NULL;
+       dm = gf_dm_new(NULL);
+       if (!dm)
+               return GF_OUT_OF_MEM;
+       e = gf_dm_wget_with_cache(dm, url, filename);
+       gf_dm_del(dm);
+       return e;
 }
 
 GF_Err gf_dm_wget_with_cache(GF_DownloadManager * dm,
                                const char *url, const char *filename)
 {
-    GF_Err e;
-    FILE * f;
-    GF_DownloadSession *dnload;
-    if (!filename || !url || !dm)
-        return GF_BAD_PARAM;
-    f= fopen(filename, "w");
-    if (!f){
+       GF_Err e;
+       FILE * f;
+       GF_DownloadSession *dnload;
+       if (!filename || !url || !dm)
+               return GF_BAD_PARAM;
+       f= fopen(filename, "w");
+       if (!f){
        GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[WGET] Failed to open file %s for write.\n", filename));
        return GF_IO_ERR;
-    }
-    dnload = gf_dm_sess_new_simple(dm, (char *)url, GF_NETIO_SESSION_NOT_THREADED, &wget_NetIO, f, &e);
-    if (!dnload) {
-        return GF_BAD_PARAM;
-    }
-    dnload->use_cache_file = 1;
-    if (e == GF_OK) {
-        e = gf_dm_sess_process(dnload);
-    }
-    e|= gf_cache_close_write_cache(dnload->cache_entry, dnload, e == GF_OK);
-    fclose(f);
-    gf_dm_sess_del(dnload);
-    return e;
+       }
+       dnload = gf_dm_sess_new_simple(dm, (char *)url, GF_NETIO_SESSION_NOT_THREADED, &wget_NetIO, f, &e);
+       if (!dnload) {
+               return GF_BAD_PARAM;
+       }
+       dnload->use_cache_file = 1;
+       dnload->force_data_write_callback = 1;
+       if (e == GF_OK) {
+               e = gf_dm_sess_process(dnload);
+       }
+       e |= gf_cache_close_write_cache(dnload->cache_entry, dnload, e == GF_OK);
+       fclose(f);
+       gf_dm_sess_del(dnload);
+       return e;
 }
 
 GF_Err gf_dm_get_file_memory(const char *url, char **out_data, u32 *out_size, char **out_mime)
 {
-    GF_Err e;
-    FILE * f;
-    GF_DownloadSession *dnload;  
-    GF_DownloadManager *dm;
+       GF_Err e;
+       FILE * f;
+       GF_DownloadSession *dnload;  
+       GF_DownloadManager *dm;
        
        if (!url || !out_data || !out_size)
-        return GF_BAD_PARAM;
-    f = gf_temp_file_new();
-    if (!f) {
+               return GF_BAD_PARAM;
+       f = gf_temp_file_new();
+       if (!f) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[WGET] Failed to create temp file for write.\n"));
                return GF_IO_ERR;
-    }
+       }
 
        dm = gf_dm_new(NULL);
        if (!dm) {
                fclose(f);
-        return GF_OUT_OF_MEM;
+               return GF_OUT_OF_MEM;
        }
        
-    dnload = gf_dm_sess_new_simple(dm, (char *)url, GF_NETIO_SESSION_NOT_THREADED, &wget_NetIO, f, &e);
-    if (!dnload) {
+       dnload = gf_dm_sess_new_simple(dm, (char *)url, GF_NETIO_SESSION_NOT_THREADED, &wget_NetIO, f, &e);
+       if (!dnload) {
                gf_dm_del(dm);
-        return GF_BAD_PARAM;
-    }
-    dnload->use_cache_file = 0;
+               return GF_BAD_PARAM;
+       }
+       dnload->use_cache_file = 0;
        dnload->disable_cache = 1;
-    if (!e)  
+       if (!e)  
                e = gf_dm_sess_process(dnload);
-    
+
        if (!e)  
-           e = gf_cache_close_write_cache(dnload->cache_entry, dnload, e == GF_OK);
+               e = gf_cache_close_write_cache(dnload->cache_entry, dnload, e == GF_OK);
        
        if (!e) {
-               u32 size = ftell(f);
+               u32 size = ftell(f), read;
                *out_size = size;
                *out_data = gf_malloc(sizeof(char)* ( 1 + size));
                fseek(f, 0, SEEK_SET);
-               fread(*out_data, 1, size, f);
-               (*out_data)[size] = 0;
-               if (out_mime) {
-                       const char *mime = gf_dm_sess_mime_type(dnload);
-                       if (mime) *out_mime = gf_strdup(mime);
+               read = fread(*out_data, 1, size, f);
+               if (read != size) {
+                       gf_free(*out_data);
+                       e = GF_IO_ERR;
+               } else {
+                       (*out_data)[size] = 0;
+                       if (out_mime) {
+                               const char *mime = gf_dm_sess_mime_type(dnload);
+                               if (mime) *out_mime = gf_strdup(mime);
+                       }
                }
        }
        fclose(f);
-    gf_dm_sess_del(dnload);
+       gf_dm_sess_del(dnload);
        gf_dm_del(dm);
-    return e;
+       return e;
 }
 
 const char *gf_dm_sess_get_resource_name(GF_DownloadSession *dnload)
 {
-    return dnload ? dnload->orig_url : NULL;
+       return dnload ? dnload->orig_url : NULL;
 }
 
 const char *gf_dm_sess_get_original_resource_name(GF_DownloadSession *dnload)
@@ -2726,7 +2798,7 @@ const char * gf_cache_get_cache_filename_range( const GF_DownloadSession * sess,
                 read = fread(copyBuff, sizeof(char), MIN(sizeof(copyBuff), (size_t)  total), fr);
                 if (read > 0) {
                     total-= read;
-                    write = fwrite(copyBuff, sizeof(char), (size_t) read, fw);
+                    write = gf_fwrite(copyBuff, sizeof(char), (size_t) read, fw);
                     if (write != read) {
                         /* Something bad happened */
                         fclose( fw );
@@ -2819,12 +2891,7 @@ GF_Err gf_dm_sess_reassign(GF_DownloadSession *sess, u32 flags, gf_dm_user_io us
        if (sess->status==GF_NETIO_DISCONNECTED)
                sess->status = GF_NETIO_SETUP;
 
-       if ( ! (flags & GF_NETIO_SESSION_NOT_THREADED) ) {
-               sess->th = gf_th_new(sess->orig_url);
-        sess->mx = gf_mx_new(sess->orig_url);
-        gf_th_run(sess->th, gf_dm_session_thread, sess);
-    }
-
+       /*threaded session shall be started with gf_dm_sess_process*/
        return GF_OK;
 }
 
@@ -2843,4 +2910,3 @@ u32 gf_dm_get_data_rate(GF_DownloadManager *dm)
 {
        return dm->limit_data_rate;
 }
-
index ea44a57c74fa3760f72333608827e409e848597b..d1059f6ece84a27ef223580fd363fadbcfe2cb96 100644 (file)
@@ -126,65 +126,187 @@ void gf_set_progress_callback(void *_user_cbk, gf_on_progress_cbk _prog_cbk)
        user_cbk = _user_cbk;
 }
 
+/*ENTRIES MUST BE IN THE SAME ORDER AS LOG_TOOL DECLARATION IN <gpac/tools.h>*/
+static struct log_tool_info {u32 type;  const char *name; u32 level; } global_log_tools [] =
+{
+       { GF_LOG_CORE, "core", GF_LOG_WARNING },
+       { GF_LOG_CODING, "coding", GF_LOG_WARNING },
+       { GF_LOG_CONTAINER, "container", GF_LOG_WARNING },
+       { GF_LOG_NETWORK, "network", GF_LOG_WARNING },
+       { GF_LOG_RTP, "rtp", GF_LOG_WARNING },
+       { GF_LOG_AUTHOR, "author", GF_LOG_WARNING },
+       { GF_LOG_SYNC, "sync", GF_LOG_WARNING },
+       { GF_LOG_CODEC, "codec", GF_LOG_WARNING },
+       { GF_LOG_PARSER, "parser", GF_LOG_WARNING },
+       { GF_LOG_MEDIA, "media", GF_LOG_WARNING },
+       { GF_LOG_SCENE, "scene", GF_LOG_WARNING },
+       { GF_LOG_SCRIPT, "script", GF_LOG_WARNING },
+       { GF_LOG_INTERACT, "interact", GF_LOG_WARNING },
+       { GF_LOG_COMPOSE, "compose", GF_LOG_WARNING },
+       { GF_LOG_CACHE, "cache", GF_LOG_WARNING },
+       { GF_LOG_MMIO, "mmio", GF_LOG_WARNING },
+       { GF_LOG_RTI, "rti", GF_LOG_WARNING },
+       { GF_LOG_SMIL, "smil", GF_LOG_WARNING },
+       { GF_LOG_MEMORY, "mem", GF_LOG_WARNING },
+       { GF_LOG_AUDIO, "audio", GF_LOG_WARNING },
+       { GF_LOG_MODULE, "module", GF_LOG_WARNING },
+       { GF_LOG_MUTEX, "mutex", GF_LOG_WARNING },
+       { GF_LOG_CONSOLE, "console", GF_LOG_INFO }
+};
 
-u32 global_log_level = 0;
-u32 global_log_tools = 0;
+GF_EXPORT
+GF_Err gf_log_modify_tools_levels(const char *val)
+{
+#ifndef GPAC_DISABLE_LOG
+       u32 level;
+       char *sep, *sep_level;
+       while (val && strlen(val)) {
+               const char *next_val = NULL;
+               const char *tools = NULL;
+               /*look for log level*/
+               sep_level = strchr(val, '@');
+               if (!sep_level) {
+                       fprintf(stderr, "Unrecognized log format %s - expecting logTool@logLevel\n", val);
+                       return GF_BAD_PARAM;
+               }
 
-u32 gf_log_parse_level(const char *val)
+               level = 0;
+               if (!strnicmp(sep_level+1, "error", 5)) {
+                       level = GF_LOG_ERROR;
+                       next_val = sep_level+1 + 5;
+               }
+               else if (!strnicmp(sep_level+1, "warning", 7)) {
+                       level = GF_LOG_WARNING;
+                       next_val = sep_level+1 + 7;
+               }
+               else if (!strnicmp(sep_level+1, "info", 4)) {
+                       level = GF_LOG_INFO;
+                       next_val = sep_level+1 + 4;
+               }
+               else if (!strnicmp(sep_level+1, "debug", 5)) {
+                       level = GF_LOG_DEBUG;
+                       next_val = sep_level+1 + 5;
+               }
+               else if (!strnicmp(sep_level+1, "quiet", 5)) {
+                       level = GF_LOG_QUIET;
+                       next_val = sep_level+1 + 5;
+               }
+               else {
+                       fprintf(stderr, "Unknown log level specified: %s\n", sep_level+1);
+                       return GF_BAD_PARAM;
+               }
+       
+               sep_level[0] = 0;
+               tools = val;
+               while (tools) {
+                       u32 i;
+
+                       sep = strchr(tools, ':');
+                       if (sep) sep[0] = 0;
+
+                       if (!stricmp(tools, "all")) {
+                               for (i=0; i<GF_LOG_TOOL_MAX; i++) 
+                                       global_log_tools[i].level = level;
+                       }
+                       else {
+                               Bool found = 0;
+                               for (i=0; i<GF_LOG_TOOL_MAX; i++) {
+                                       if (!strcmp(global_log_tools[i].name, tools)) {
+                                               global_log_tools[i].level = level;
+                                               found = 1;
+                                       }
+                               }
+                               if (!found) {
+                                       sep_level[0] = '@';
+                                       if (sep) sep[0] = ':';
+                                       fprintf(stderr, "Unknown log tool specified: %s\n", val);
+                                       return GF_BAD_PARAM;
+                               }
+                       }
+
+                       if (!sep) break;
+                       sep[0] = ':';
+                       tools = sep+1;
+               }
+
+               sep_level[0] = '@';
+               if (!next_val[0]) break;
+               val = next_val+1;
+       }
+#endif
+       return GF_OK;
+}
+
+GF_EXPORT
+GF_Err gf_log_set_tools_levels(const char *val)
 {
 #ifndef GPAC_DISABLE_LOG
-       if (!val) return 0;
-       if (!stricmp(val, "error")) return GF_LOG_ERROR;
-       if (!stricmp(val, "warning")) return GF_LOG_WARNING;
-       if (!stricmp(val, "info")) return GF_LOG_INFO;
-       if (!stricmp(val, "debug")) return GF_LOG_DEBUG;
-       fprintf(stderr, "Unknown log level specified: %s\n", val);
+       u32 i;
+       for (i=0; i<GF_LOG_TOOL_MAX; i++) 
+               global_log_tools[i].level = GF_LOG_WARNING;
+
+       return gf_log_modify_tools_levels(val);
+#else
+       return GF_OK;
 #endif
-       return 0;
 }
 
-u32 gf_log_parse_tools(const char *val)
+GF_EXPORT
+char *gf_log_get_tools_levels()
 {
-       u32 flags = 0;
 #ifndef GPAC_DISABLE_LOG
-       char *sep;
-       while (val) {
-               sep = strchr(val, ':');
-               if (sep) sep[0] = 0;
-               if (!stricmp(val, "core")) flags |= GF_LOG_CORE;
-               else if (!stricmp(val, "coding")) flags |= GF_LOG_CODING;
-               else if (!stricmp(val, "container")) flags |= GF_LOG_CONTAINER;
-               else if (!stricmp(val, "network")) flags |= GF_LOG_NETWORK;
-               else if (!stricmp(val, "rtp")) flags |= GF_LOG_RTP;
-               else if (!stricmp(val, "author")) flags |= GF_LOG_AUTHOR;
-               else if (!stricmp(val, "sync")) flags |= GF_LOG_SYNC;
-               else if (!stricmp(val, "codec")) flags |= GF_LOG_CODEC;
-               else if (!stricmp(val, "parser")) flags |= GF_LOG_PARSER;
-               else if (!stricmp(val, "media")) flags |= GF_LOG_MEDIA;
-               else if (!stricmp(val, "scene")) flags |= GF_LOG_SCENE;
-               else if (!stricmp(val, "script")) flags |= GF_LOG_SCRIPT;
-               else if (!stricmp(val, "interact")) flags |= GF_LOG_INTERACT;
-               else if (!stricmp(val, "smil")) flags |= GF_LOG_SMIL;
-               else if (!stricmp(val, "compose")) flags |= GF_LOG_COMPOSE;
-               else if (!stricmp(val, "mmio")) flags |= GF_LOG_MMIO;
-               else if (!stricmp(val, "rti")) flags |= GF_LOG_RTI;
-               else if (!stricmp(val, "cache")) flags |= GF_LOG_CACHE;
-               else if (!stricmp(val, "audio")) flags |= GF_LOG_AUDIO;
-               else if (!stricmp(val, "mem")) flags |= GF_LOG_MEMORY;
-               else if (!stricmp(val, "module")) flags |= GF_LOG_MODULE;
-               else if (!stricmp(val, "mutex")) flags |= GF_LOG_MUTEX;
-               else if (!stricmp(val, "none")) flags = 0;
-               else if (!stricmp(val, "all")) flags = 0xFFFFFFFF;
-               else {
-                       fprintf(stderr, "Unknown log tool specified: %s\n", val);
-                       return 0;
+       u32 i, level, len;
+       char szLogs[GF_MAX_PATH];
+       char szLogTools[GF_MAX_PATH];
+       strcpy(szLogTools, "");
+       
+       level = GF_LOG_QUIET;
+       while (level <= GF_LOG_DEBUG) {
+               u32 nb_tools = 0;
+               strcpy(szLogs, "");
+               for (i=0; i<GF_LOG_TOOL_MAX; i++) {
+                       if (global_log_tools[i].level == level) {
+                               strcat(szLogs, global_log_tools[i].name);
+                               strcat(szLogs, ":");
+                               nb_tools++;
+                       }
                }
-               if (!sep) break;
-               sep[0] = ':';
-               val = sep+1;
+               if (nb_tools) {
+                       char *levelstr = "@warning";
+                       if (level==GF_LOG_QUIET) levelstr = "@quiet";
+                       else if (level==GF_LOG_ERROR) levelstr = "@error";
+                       else if (level==GF_LOG_WARNING) levelstr = "@warning";
+                       else if (level==GF_LOG_INFO) levelstr = "@info";
+                       else if (level==GF_LOG_DEBUG) levelstr = "@debug";
+
+                       if (nb_tools>GF_LOG_TOOL_MAX/2) {
+                               strcpy(szLogs, szLogTools);
+                               strcpy(szLogTools, "all");
+                               strcat(szLogTools, levelstr);
+                               if (strlen(szLogs)) {
+                                       strcat(szLogTools, ":");
+                                       strcat(szLogTools, szLogs);
+                               }
+                       } else {
+                               if (strlen(szLogTools)) {
+                                       strcat(szLogTools, ":");
+                               }
+                               /*remove last ':' from tool*/
+                               szLogs[ strlen(szLogs) - 1 ] = 0;
+                               strcat(szLogTools, szLogs);
+                               strcat(szLogTools, levelstr);
+                       }
+               }
+               level++;
+       }
+       len = strlen(szLogTools);
+       if (len) {
+               /*remove last ':' from level*/
+               if (szLogTools[ len-1 ] == ':') szLogTools[ len-1 ] = 0;
+               return gf_strdup(szLogTools);
        }
 #endif
-       return flags;
+       return gf_strdup("all@quiet");
 }
 
 #ifndef GPAC_DISABLE_LOG
@@ -192,10 +314,12 @@ u32 call_lev = 0;
 u32 call_tool = 0;
 
 GF_EXPORT
-u32 gf_log_get_level() { return global_log_level; }
-
-GF_EXPORT
-u32 gf_log_get_tools() { return global_log_tools; }
+Bool gf_log_tool_level_on(u32 log_tool, u32 log_level)
+{
+       assert(log_tool<GF_LOG_TOOL_MAX); 
+       if (global_log_tools[log_tool].level >= log_level) return 1;
+       return 0;
+}
 
 void default_log_callback(void *cbck, u32 level, u32 tool, const char* fmt, va_list vlist)
 {
@@ -219,12 +343,6 @@ void gf_log(const char *fmt, ...)
                exit(1);
 }
 
-GF_EXPORT
-void gf_log_set_level(u32 level)
-{
-       global_log_level = level;
-}
-
 GF_EXPORT
 void gf_log_set_strict_error(Bool strict)
 {
@@ -232,9 +350,16 @@ void gf_log_set_strict_error(Bool strict)
 }
 
 GF_EXPORT
-void gf_log_set_tools(u32 modules)
+void gf_log_set_tool_level(u32 tool, u32 level)
 {
-       global_log_tools = modules;
+       assert(tool<=GF_LOG_TOOL_MAX); 
+       if (tool==GF_LOG_ALL) {
+               u32 i;
+               for (i=0; i<GF_LOG_TOOL_MAX; i++)
+                       global_log_tools[i].level = level;
+       } else {
+               global_log_tools[tool].level = level;
+       }
 }
 
 GF_EXPORT
@@ -253,6 +378,7 @@ gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
        user_log_cbk = usr_cbk;
        return prev_cbk;
 }
+
 #else
 GF_EXPORT
 void gf_log(const char *fmt, ...)
@@ -263,28 +389,15 @@ void gf_log_lt(u32 ll, u32 lt)
 {
 }
 GF_EXPORT
-void gf_log_set_level(u32 level)
-{
-}
-GF_EXPORT
 void gf_log_set_strict_error(Bool strict)
 {
 }
-GF_EXPORT
-void gf_log_set_tools(u32 modules)
-{
-}
+
 GF_EXPORT
 gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
 {
        return NULL;
 }
-GF_EXPORT
-u32 gf_log_get_level() { return 0; }
-
-GF_EXPORT
-u32 gf_log_get_tools() { return 0; }
-
 #endif
 
 
@@ -292,8 +405,6 @@ GF_EXPORT
 const char *gf_error_to_string(GF_Err e)
 {
        switch (e) {
-       case GF_SCRIPT_INFO:
-               return "Script message";
        case GF_EOS:
                return "End Of Stream / File";
        case GF_OK:
index 3d0dd7ce1a38ce5cd17780c19800ec04996ed39d..8e8e8f0bb10e7705ebf7b22ef40049bc8513d74e 100644 (file)
@@ -728,3 +728,29 @@ void *gf_list_enum(GF_List *ptr, u32 *pos)
        (*pos)++;
        return res;
 }
+
+GF_EXPORT
+GF_Err gf_list_swap(GF_List *l1, GF_List *l2)
+{
+       GF_Err e;
+       u32 count = gf_list_count(l1);
+       if (!l1 || !l2) return GF_BAD_PARAM;
+       if (l1 == l2) return GF_OK;
+
+       while (gf_list_count(l2)) {
+               void *ptr = gf_list_get(l2, 0);
+               e = gf_list_rem(l2, 0);
+               if (e) return e;
+               e = gf_list_add(l1, ptr);
+               if (e) return e;
+       }
+       while (count) {
+               void *ptr = gf_list_get(l1, 0);
+               e = gf_list_rem(l1, 0);
+               if (e) return e;
+               count--;
+               e = gf_list_add(l2, ptr);
+               if (e) return e;
+       }
+       return GF_OK;
+}
index 97586bb007248dc7eced9d1ea97ed4967d68c02a..7e9b6b382c07ede39390bc7b8a93003e4f5f665c 100644 (file)
@@ -652,6 +652,14 @@ Fixed gf_asin(_a) { return (Float) asin(_a); }
 
 #endif
 
+GF_EXPORT
+Fixed gf_v2d_distance(GF_Point2D *a, GF_Point2D *b)
+{
+       GF_Point2D d;
+       d.x = a->x - b->x;
+       d.y = a->y - b->y;
+       return gf_v2d_len(&d);
+}
 
 GF_EXPORT
 Fixed gf_angle_diff(Fixed angle1, Fixed angle2)
@@ -1897,7 +1905,7 @@ Bool gf_ray_hit_box(GF_Ray *ray, GF_Vec box_min, GF_Vec box_max, GF_Vec *outPoin
 {
        Fixed t1, t2, tNEAR=FIX_MIN, tFAR=FIX_MAX;
        Fixed temp;
-       s8 xyorz, sign;
+       //s8 xyorz, sign;
        
        if (ray->dir.x == 0) {
                if ((ray->orig.x < box_min.x) || (ray->orig.x > box_max.x))
@@ -1912,8 +1920,8 @@ Bool gf_ray_hit_box(GF_Ray *ray, GF_Vec box_min, GF_Vec box_max, GF_Vec *outPoin
                }
                if (t1 > tNEAR) {
                        tNEAR = t1;
-                       xyorz = XPLANE;
-                       sign = (ray->dir.x < 0) ? 1 : -1;
+                       //xyorz = XPLANE;
+                       //sign = (ray->dir.x < 0) ? 1 : -1;
                }
                if (t2 < tFAR) tFAR = t2;
                if (tNEAR > tFAR) return 0; // box missed
@@ -1935,8 +1943,8 @@ Bool gf_ray_hit_box(GF_Ray *ray, GF_Vec box_min, GF_Vec box_max, GF_Vec *outPoin
                }
                if (t1 > tNEAR) {
                        tNEAR = t1;
-                       xyorz = YPLANE;
-                       sign = (ray->dir.y < 0) ? 1 : -1;
+                       //xyorz = YPLANE;
+                       //sign = (ray->dir.y < 0) ? 1 : -1;
                }
                if (t2 < tFAR) tFAR = t2;
                if (tNEAR > tFAR) return 0; // box missed
@@ -1959,8 +1967,8 @@ Bool gf_ray_hit_box(GF_Ray *ray, GF_Vec box_min, GF_Vec box_max, GF_Vec *outPoin
                }
                if (t1 > tNEAR) {
                        tNEAR = t1;
-                       xyorz = ZPLANE;
-                       sign = (ray->dir.z < 0) ? 1 : -1;
+                       //xyorz = ZPLANE;
+                       //sign = (ray->dir.z < 0) ? 1 : -1;
                }
                if (t2 < tFAR) tFAR = t2;
                if (tNEAR>tFAR) return 0; // box missed
index 802cdc73f1c70ac0e2aba5f7564273466e7b6647..38539dc0857a48ed8b4c41c006697061744072b9 100644 (file)
@@ -219,10 +219,10 @@ GF_BaseInterface *gf_modules_load_interface_by_name(GF_ModuleManager *pm, const
        const char *file_name;
        u32 i, count;
        GF_BaseInterface *ifce;
-        if (!pm || !plug_name || !pm->plug_list || !pm->cfg){
-          GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load_interface_by_name has bad parameters pm=%p, plug_name=%s.\n", pm, plug_name));
-          return NULL;
-        }
+       if (!pm || !plug_name || !pm->plug_list || !pm->cfg){
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] gf_modules_load_interface_by_name has bad parameters pm=%p, plug_name=%s.\n", pm, plug_name));
+               return NULL;
+       }
        count = gf_list_count(pm->plug_list);
        /*look for cache entry*/
        file_name = gf_cfg_get_key(pm->cfg, "PluginsCache", plug_name);
@@ -237,14 +237,14 @@ GF_BaseInterface *gf_modules_load_interface_by_name(GF_ModuleManager *pm, const
                        }
                }
        }
-        GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Plugin %s of type %d not found in cache, searching for it...\n", plug_name, InterfaceFamily));
+       GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Plugin %s of type %d not found in cache, searching for it...\n", plug_name, InterfaceFamily));
        for (i=0; i<count; i++) {
                ifce = gf_modules_load_interface(pm, i, InterfaceFamily);
                if (!ifce) continue;
                if (ifce->module_name && !strnicmp(ifce->module_name, plug_name, MIN(strlen(ifce->module_name), strlen(plug_name)) )) {
                        /*update cache entry*/
                        gf_cfg_set_key(pm->cfg, "PluginsCache", plug_name, ((ModuleInstance*)ifce->HPLUG)->name);
-                        GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Added plugin cache %s for %s\n", plug_name, ((ModuleInstance*)ifce->HPLUG)->name));
+                       GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Added plugin cache %s for %s\n", plug_name, ((ModuleInstance*)ifce->HPLUG)->name));
                        return ifce;
                }
                gf_modules_close_interface(ifce);
@@ -282,7 +282,7 @@ const char *gf_modules_get_option(GF_BaseInterface *ifce, const char *secName, c
        if (!ifce || !ifce->HPLUG) return NULL;
        cfg = ((ModuleInstance *)ifce->HPLUG)->plugman->cfg;
        if (!cfg) return NULL;
-       return gf_cfg_get_key(cfg, secName, keyName);
+       return gf_cfg_get_ikey(cfg, secName, keyName);
 }
 
 GF_EXPORT
index c25aa410c0533315e5be94a0601f9775f3bfed10..6a0a23dce90fee10d55e72874b6d83f8aaa0381e 100644 (file)
@@ -107,10 +107,10 @@ static Bool get_default_install_path(char *file_path, u32 path_type)
        if (!strstr(file_path, "gpac")) {\r
                HKEY hKey = NULL;\r
                DWORD dwSize = GF_MAX_PATH;\r
-               DWORD dwType = REG_SZ;\r
                \r
                /*locate the key in current user, then in local machine*/\r
 #ifdef _WIN32_WCE\r
+               DWORD dwType = REG_SZ;\r
                u16 w_path[1024];\r
                RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\GPAC"), 0, KEY_READ, &hKey);\r
 #ifdef _DEBUG\r
@@ -153,6 +153,7 @@ static Bool get_default_install_path(char *file_path, u32 path_type)
        if (path_type==GF_PATH_MODULES) return 1;\r
 \r
        /*we are looking for the config file path - make sure it is writable*/\r
+       assert(path_type == GF_PATH_CFG);\r
 \r
        strcpy(szPath, file_path);\r
        strcat(szPath, "\\gpaccfgtest.txt");\r
@@ -375,6 +376,7 @@ static GF_Config *create_default_config(char *file_path)
                gf_cfg_set_key(cfg, "General", "CacheDirectory", cache_dir);\r
                gf_free(cache_dir);\r
        }\r
+       gf_cfg_set_key(cfg, "DSMCC", "Activated", "false");\r
 \r
        gf_cfg_set_key(cfg, "Compositor", "Raster2D", "GPAC 2D Raster");\r
        gf_cfg_set_key(cfg, "Audio", "ForceConfig", "yes");\r
@@ -383,7 +385,7 @@ static GF_Config *create_default_config(char *file_path)
        gf_cfg_set_key(cfg, "Audio", "DisableNotification", "no");\r
 \r
        /*Setup font engine to FreeType by default, and locate TrueType font directory on the system*/\r
-       gf_cfg_set_key(cfg, "FontEngine", "FontReader", "ft_font");\r
+       gf_cfg_set_key(cfg, "FontEngine", "FontReader", "FreeType Font Reader");\r
        gf_cfg_set_key(cfg, "FontEngine", "RescanFonts", "yes");\r
 \r
 \r
@@ -409,7 +411,7 @@ static GF_Config *create_default_config(char *file_path)
 \r
        gf_cfg_set_key(cfg, "Downloader", "CleanCache", "yes");\r
        gf_cfg_set_key(cfg, "Compositor", "AntiAlias", "All");\r
-       gf_cfg_set_key(cfg, "Compositor", "FrameRate", "30");\r
+       gf_cfg_set_key(cfg, "Compositor", "FrameRate", "30.0");\r
        /*use power-of-2 emulation in OpenGL if no rectangular texture extension*/\r
        gf_cfg_set_key(cfg, "Compositor", "EmulatePOW2", "yes");\r
        gf_cfg_set_key(cfg, "Compositor", "ScalableZoom", "yes");\r
@@ -504,7 +506,7 @@ GF_Config *gf_cfg_init(const char *file, Bool *new_cfg)
        }\r
 \r
        if (!cfg) {\r
-               fprintf(stdout, "cannot create config file %s in %s directory\n", CFG_FILE_NAME, szPath);\r
+               fprintf(stdout, "Cannot create config file %s in %s directory\n", CFG_FILE_NAME, szPath);\r
                return NULL;\r
        }\r
 \r
index 87ce36c1d73811554b7ce9b24f0c0dec079d1c75..f69a7a8332582fa638d9fc124162491a5a52c8e4 100644 (file)
@@ -29,6 +29,7 @@
 #include <winbase.h>
 #include <winsock.h>
 #include <tlhelp32.h>
+//#include <direct.h>
 
 #if !defined(__GNUC__)
 #pragma comment(lib, "toolhelp")
@@ -41,6 +42,7 @@
 #include <io.h>
 #include <windows.h>
 #include <tlhelp32.h>
+#include <direct.h>
 
 #if !defined(__GNUC__)
 #pragma comment(lib, "winmm")
@@ -121,6 +123,92 @@ void gf_sleep(u32 ms)
 #endif
 }
 
+
+GF_Err gf_rmdir(char *DirPathName)
+{
+#if defined (_WIN32_WCE)
+       TCHAR swzName[MAX_PATH];
+       BOOL res;
+       CE_CharToWide(DirPathName, swzName);
+       res = RemoveDirectory(swzName);
+       if (! res) {
+               int err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot delete director %s: last error %d\n", DirPathName, err ));
+       }
+#elif defined (WIN32)
+       int res = rmdir(DirPathName);
+       if (res==-1) {
+               int err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot delete director %s: last error %d\n", DirPathName, err ));
+               return GF_IO_ERR;
+       }
+#else
+    int res = rmdir(DirPathName);
+       if (res==-1) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot delete director %s: last error %d\n", DirPathName, errno  ));
+               return GF_IO_ERR;
+       }
+#endif
+       return GF_OK;
+}   
+
+GF_Err gf_mkdir(char* DirPathName)
+{
+#if defined (_WIN32_WCE)
+       TCHAR swzName[MAX_PATH];
+       BOOL res;
+       CE_CharToWide(DirPathName, swzName);
+       res = CreateDirectory(swzName, NULL);
+       if (! res) {
+               int err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot create director %s: last error %d\n", DirPathName, err ));
+       }
+#elif defined (WIN32) 
+       int res = mkdir(DirPathName);
+       if (res==-1) {
+               int err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot create director %s: last error %d\n", DirPathName, err ));
+       }
+#else  
+    int res = mkdir(DirPathName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+       if (res==-1) {          
+               if(errno == 17){
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot create director %s, it already exists: last error %d \n", DirPathName, errno ));
+                       return GF_BAD_PARAM;
+               }else{
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cannot create director %s: last error %d\n", DirPathName, errno ));
+                       return GF_IO_ERR;
+               }
+       }
+#endif
+       return GF_OK;
+}
+
+static Bool delete_carousel_data(void *cbck, char *item_name, char *item_path)
+{
+       Bool directory_clean_mode = *(Bool*)cbck;
+
+       if(directory_clean_mode){
+                gf_cleanup_dir(item_path);
+                gf_rmdir(item_path);           
+       }else{
+               gf_delete_file(item_path);              
+       }       
+       return GF_OK;
+}
+
+GF_Err gf_cleanup_dir(char* DirPathName)
+{
+       Bool directory_clean_mode;
+
+       directory_clean_mode = 1;
+       gf_enum_directory(DirPathName, 1, delete_carousel_data, &directory_clean_mode, NULL);                                                                                                           
+       directory_clean_mode = 0;
+       gf_enum_directory(DirPathName, 0, delete_carousel_data, &directory_clean_mode, NULL);
+
+       return GF_OK;
+}
+
 #ifndef gettimeofday
 #ifdef _WIN32_WCE
 
@@ -138,7 +226,7 @@ s32 gettimeofday(struct timeval *tp, void *tz)
        s32 val;
 
        GetSystemTime(&st);
-    SystemTimeToFileTime(&st, &ft);
+       SystemTimeToFileTime(&st, &ft);
 
        val = (s32) ((*(LONGLONG *) &ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
        tp->tv_sec = (u32) val;
@@ -249,12 +337,17 @@ u64 gf_file_modification_time(const char *filename)
        HANDLE fh;
        ULARGE_INTEGER uli;
        ULONGLONG time_ms;
+       BOOL ret;
        CE_CharToWide((char *) filename, _file);
        fh = FindFirstFile(_file, &FindData);
        if (fh == INVALID_HANDLE_VALUE) return 0;
        uli.LowPart = FindData.ftLastWriteTime.dwLowDateTime;
        uli.HighPart = FindData.ftLastWriteTime.dwHighDateTime;
-       FindClose(fh);
+       ret = FindClose(fh);
+       if (!ret) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] FindClose() in gf_file_modification_time() returned the following error code: %d\n", err));
+       }
        time_ms = uli.QuadPart/10000;
        return time_ms;
 #elif defined(WIN32) && !defined(__GNUC__)
@@ -513,7 +606,11 @@ GF_Err gf_enum_directory(const char *dir, Bool enum_directory, gf_enum_dir_item
 #endif
                if (enum_dir_fct(cbck, file, item_path)) {
 #ifdef WIN32
-                       FindClose(SearchH);
+                       BOOL ret = FindClose(SearchH);
+                       if (!ret) {
+                               DWORD err = GetLastError();
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] FindClose() in gf_enum_directory() returned(1) the following error code: %d\n", err));
+                       }
 #endif
                        break;
                }
@@ -521,7 +618,11 @@ GF_Err gf_enum_directory(const char *dir, Bool enum_directory, gf_enum_dir_item
 next:
 #ifdef WIN32
                if (!FindNextFile(SearchH, &FindData)) {
-                       FindClose(SearchH);
+                       BOOL ret = FindClose(SearchH);
+                       if (!ret) {
+                               DWORD err = GetLastError();
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] FindClose() in gf_enum_directory() returned(2) the following error code: %d\n", err));
+                       }
                        break;
                }
 #else
@@ -601,6 +702,41 @@ FILE *gf_f64_open(const char *file_name, const char *mode)
 #endif
 }
 
+#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
+#define HAVE_STRERROR_R 1
+#endif
+size_t gf_fwrite(const void *ptr, size_t size, size_t nmemb, 
+                       FILE *stream)
+{
+       size_t result = fwrite(ptr, size, nmemb, stream);
+       if (result != nmemb) {
+#ifdef _WIN32_WCE
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Error writing data: %d blocks to write but %d blocks written\n", nmemb, result));
+#else
+#if defined WIN32 && !defined(GPAC_CONFIG_WIN32)
+               errno_t errno_save;
+               _get_errno(&errno_save);
+#else
+               int errno_save = errno;
+#endif
+               //if (errno_save!=0)
+               {
+#ifdef HAVE_STRERROR_R
+#define ERRSTR_BUF_SIZE 256
+                       char errstr[ERRSTR_BUF_SIZE];
+                       if(strerror_r(errno_save, errstr, ERRSTR_BUF_SIZE) != 0)
+                       {
+                               strerror_r(0, errstr, ERRSTR_BUF_SIZE);
+                       }
+#else
+                       char *errstr = (char*)strerror(errno_save);
+#endif
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Error writing data (%s): %d blocks to write but %d blocks written\n", errstr, nmemb, result));
+               }
+#endif
+       }
+       return result;
+}
 
 
 /*seems OK under mingw also*/
@@ -631,7 +767,11 @@ void gf_prompt_set_echo_off(Bool echo_off)
 {
        DWORD flags;
        HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
-       GetConsoleMode(hStdin, &flags);
+       BOOL ret = GetConsoleMode(hStdin, &flags);
+       if (!ret) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleMode() return with the following error code: %d\n", err));
+       }
        if (echo_off) flags &= ~ENABLE_ECHO_INPUT;
        else flags |= ENABLE_ECHO_INPUT;
        SetConsoleMode(hStdin, flags);
@@ -821,7 +961,7 @@ sh4_get_fpscr()
 static void
 sh4_put_fpscr(int nv)
 {
-    asm volatile ("lds %0,fpscr" : : "r" (nv));
+       asm volatile ("lds %0,fpscr" : : "r" (nv));
 }
 
 #define SH4_FPSCR_FR 0x00200000
@@ -870,6 +1010,10 @@ void gf_sys_init(Bool enable_memory_tracker)
                        gf_mem_enable_tracker();
 #endif
                }
+               /*by default log subsystem is initialized to error on all tools, and info on console to debug scripts*/
+               gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_ERROR);
+               gf_log_set_tool_level(GF_LOG_CONSOLE, GF_LOG_INFO);
+
 
 #if defined(__sh__)
                /* Round all denormalized floatting point number to 0.0 */
@@ -1090,7 +1234,7 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
        }
        /*no special API available, ONLY FETCH TIMES if requested (may eat up some time)*/
        else if (flags & GF_RTI_ALL_PROCESSES_TIMES) {
-           PROCESSENTRY32 pentry; 
+               PROCESSENTRY32 pentry; 
                /*get a snapshot of all running threads*/
                hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
                if (!hSnapShot) return 0;
@@ -1247,6 +1391,7 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
 #else
 #include <mach/shared_memory_server.h>
 #endif
+#include <mach/mach_error.h>
        
 static u64 total_physical_memory = 0;
        
@@ -1254,37 +1399,37 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
 {
        size_t length;
        u32 entry_time, i, percent;
-    int mib[6];
-    int result;
-    int pagesize;
+       int mib[6];
+       int result;
+       int pagesize;
        u64 process_u_k_time;
-    mach_msg_type_number_t count = HOST_VM_INFO_COUNT; 
-    vm_statistics_data_t vmstat;
-    task_t task;
-    kern_return_t error;
-    thread_array_t thread_table;
-    thread_basic_info_t thi;
-    thread_basic_info_data_t thi_data;
-    unsigned table_size;
-    struct task_basic_info ti;
        double utime, stime;
-       
+       vm_statistics_data_t vmstat;
+       task_t task;
+       kern_return_t error;
+       thread_array_t thread_table;
+       unsigned table_size;
+       thread_basic_info_t thi;
+       thread_basic_info_data_t thi_data;
+       struct task_basic_info ti;
+       mach_msg_type_number_t count = HOST_VM_INFO_COUNT, size = sizeof(ti);
+
        entry_time = gf_sys_clock();
        if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
                memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
                return 0;
        }
-       
+
        mib[0] = CTL_HW;
-    mib[1] = HW_PAGESIZE;
-    length = sizeof(pagesize);
-    if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0) {
+       mib[1] = HW_PAGESIZE;
+       length = sizeof(pagesize);
+       if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0) {
                return 0;
-    }
+       }
 
        if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count) != KERN_SUCCESS) {
                return 0;
-    }
+       }
 
        the_rti.physical_memory = (vmstat.wire_count + vmstat.active_count + vmstat.inactive_count + vmstat.free_count)* pagesize;
        the_rti.physical_memory_avail = vmstat.free_count * pagesize;
@@ -1298,9 +1443,15 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
                }
        }
        
-       
-    error = task_for_pid(mach_task_self(), the_rti.pid, &task);
+       error = task_for_pid(mach_task_self(), the_rti.pid, &task);
        if (error) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task for PID %d: error %d\n", the_rti.pid, error));
+               return 0;
+       }
+
+       error = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&ti, &size);
+       if (error) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task info (PID %d): error %d\n", the_rti.pid, error));
                return 0;
        }
        
@@ -1308,12 +1459,19 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
        utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6;
        stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6;
        error = task_threads(task, &thread_table, &table_size);
-       assert(error == KERN_SUCCESS);
+       if (error != KERN_SUCCESS) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get threads task for PID %d: error %d\n", the_rti.pid, error));
+               return 0;
+       }
        thi = &thi_data;
        for (i = 0; i != table_size; ++i) {
                count = THREAD_BASIC_INFO_COUNT;
                error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count);
-               assert(error == KERN_SUCCESS);
+               if (error != KERN_SUCCESS) {
+                       mach_error("[RTI] Unexpected thread_info() call return", error);
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[RTI] Unexpected thread info for PID %d\n", the_rti.pid));
+                       break;
+               }
                if ((thi->flags & TH_FLAGS_IDLE) == 0) {
                        utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
                        stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
@@ -1321,7 +1479,7 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
                }
        }
        error = vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t));
-    mach_port_deallocate(mach_task_self(), task);
+       mach_port_deallocate(mach_task_self(), task);
        
        process_u_k_time = utime + stime;
        
@@ -1372,77 +1530,77 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
 
   entry_time = gf_sys_clock();
   if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
-    memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
-    return 0;
+         memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
+         return 0;
   }
 
   u_k_time = idle_time = 0;
   f = gf_f64_open("/proc/stat", "r");
   if (f) {
-    u32 k_time, nice_time, u_time;
-    if (fgets(line, 128, f) != NULL) {
-      if (sscanf(line, "cpu  %u %u %u %u\n", &u_time, &k_time, &nice_time, &idle_time) == 4) {
-       u_k_time = u_time + k_time + nice_time;
-      }
-    }
-    fclose(f);
+         u32 k_time, nice_time, u_time;
+         if (fgets(line, 128, f) != NULL) {
+                 if (sscanf(line, "cpu  %u %u %u %u\n", &u_time, &k_time, &nice_time, &idle_time) == 4) {
+                         u_k_time = u_time + k_time + nice_time;
+                 }
+         }
+         fclose(f);
   }
 
   process_u_k_time = 0;
   the_rti.process_memory = 0;
 
   /*FIXME? under LinuxThreads this will only fetch stats for the calling thread, we would have to enumerate /proc to get
-   the complete CPU usage of all therads of the process...*/
+  the complete CPU usage of all therads of the process...*/
 #if 0
   sprintf(szProc, "/proc/%d/stat", the_rti.pid);
   f = gf_f64_open(szProc, "r");
   if (f) {
-    fflush(f);
-    if (fgets(line, 2048, f) != NULL) {
-      char state;
-      char *start;
-      long cutime, cstime, priority, nice, itrealvalue, rss;
-      int exit_signal, processor;
-      unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime,starttime, vsize, rlim, startcode, endcode, startstack, kstkesp, kstkeip, signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap, rem;
-      int ppid, pgrp ,session, tty_nr, tty_pgrp, res;
-      start = strchr(line, ')');
-      if (start) start += 2;
-      else {
-       start = strchr(line, ' ');
-       start++;
-      }
-      res = sscanf(start,"%c %d %d %d %d %d %lu %lu %lu %lu \
+         fflush(f);
+         if (fgets(line, 2048, f) != NULL) {
+                 char state;
+                 char *start;
+                 long cutime, cstime, priority, nice, itrealvalue, rss;
+                 int exit_signal, processor;
+                 unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime,starttime, vsize, rlim, startcode, endcode, startstack, kstkesp, kstkeip, signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap, rem;
+                 int ppid, pgrp ,session, tty_nr, tty_pgrp, res;
+                 start = strchr(line, ')');
+                 if (start) start += 2;
+                 else {
+                         start = strchr(line, ' ');
+                         start++;
+                 }
+                 res = sscanf(start,"%c %d %d %d %d %d %lu %lu %lu %lu \
 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu \
 %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %d %d",
-                  &state, &ppid, &pgrp, &session, &tty_nr, &tty_pgrp, &flags, &minflt, &cminflt, &majflt,
-                  &cmajflt, &utime, &stime, &cutime, &cstime, &priority, &nice, &itrealvalue, &rem, &starttime,
-                  &vsize, &rss, &rlim, &startcode, &endcode, &startstack, &kstkesp, &kstkeip, &signal, &blocked,
-                  &sigignore, &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor);
-      if (res) process_u_k_time = (u64) (cutime + cstime);
-      else {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] PROC %s parse error\n", szProc));
+                                                        &state, &ppid, &pgrp, &session, &tty_nr, &tty_pgrp, &flags, &minflt, &cminflt, &majflt,
+                                                        &cmajflt, &utime, &stime, &cutime, &cstime, &priority, &nice, &itrealvalue, &rem, &starttime,
+                                                        &vsize, &rss, &rlim, &startcode, &endcode, &startstack, &kstkesp, &kstkeip, &signal, &blocked,
+                                                        &sigignore, &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor);
+
+                 if (res) process_u_k_time = (u64) (cutime + cstime);
+                 else {
+                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] PROC %s parse error\n", szProc));
+                 }
+         } else {
+                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] error reading pid/stat\n\n", szProc));
          }
-    } else {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] error reading pid/stat\n\n", szProc));
-    }
-    fclose(f);
+         fclose(f);
   } else {
-       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
+         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
   }
   sprintf(szProc, "/proc/%d/status", the_rti.pid);
   f = gf_f64_open(szProc, "r");
   if (f) {
-    while (fgets(line, 1024, f) != NULL) {
-      if (!strnicmp(line, "VmSize:", 7)) {
-       sscanf(line, "VmSize: %"LLD" kB",  &the_rti.process_memory);
-       the_rti.process_memory *= 1024;
-      }
-    }
-    fclose(f);
+         while (fgets(line, 1024, f) != NULL) {
+                 if (!strnicmp(line, "VmSize:", 7)) {
+                         sscanf(line, "VmSize: %"LLD" kB",  &the_rti.process_memory);
+                         the_rti.process_memory *= 1024;
+                 }
+         }
+         fclose(f);
   } else {
-       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
+         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
   }
 #endif
 
@@ -1450,57 +1608,57 @@ Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
   the_rti.physical_memory = the_rti.physical_memory_avail = 0;
   f = gf_f64_open("/proc/meminfo", "r");
   if (f) {
-    while (fgets(line, 1024, f) != NULL) {
-      if (!strnicmp(line, "MemTotal:", 9)) {
-       sscanf(line, "MemTotal: "LLU" kB",  &the_rti.physical_memory);
-       the_rti.physical_memory *= 1024;
-      }else if (!strnicmp(line, "MemFree:", 8)) {
-       sscanf(line, "MemFree: "LLU" kB",  &the_rti.physical_memory_avail);
-       the_rti.physical_memory_avail *= 1024;
-       break;
-      }
-    }
-    fclose(f);
+         while (fgets(line, 1024, f) != NULL) {
+                 if (!strnicmp(line, "MemTotal:", 9)) {
+                         sscanf(line, "MemTotal: "LLU" kB",  &the_rti.physical_memory);
+                         the_rti.physical_memory *= 1024;
+                 }else if (!strnicmp(line, "MemFree:", 8)) {
+                         sscanf(line, "MemFree: "LLU" kB",  &the_rti.physical_memory_avail);
+                         the_rti.physical_memory_avail *= 1024;
+                         break;
+                 }
+         }
+         fclose(f);
   } else {
-       GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open /proc/meminfo\n"));
+         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open /proc/meminfo\n"));
   }
 
 
   the_rti.sampling_instant = last_update_time;
-  
+
   if (last_update_time) {
-    the_rti.sampling_period_duration = (entry_time - last_update_time);
-    the_rti.process_cpu_time_diff = (process_u_k_time - last_process_k_u_time) * 10;
-
-    /*oops, we have no choice but to assume 100% cpu usage during this period*/
-    if (!u_k_time) {
-      the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
-      u_k_time = last_cpu_u_k_time + the_rti.sampling_period_duration;
-      the_rti.cpu_idle_time = 0;
-      the_rti.total_cpu_usage = 100;
-      if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
-      the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
-    } else {
-      u64 samp_sys_time;
-      /*move to ms (/proc/stat gives times in 100 ms unit*/
-      the_rti.total_cpu_time_diff = (u_k_time - last_cpu_u_k_time)*10;
-
-      /*we're not that accurate....*/
-      if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
-       the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
-
-   
-      if (!idle_time) idle_time = (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff)/10;
-      samp_sys_time = u_k_time - last_cpu_u_k_time;
-      the_rti.cpu_idle_time = idle_time - last_cpu_idle_time;
-      the_rti.total_cpu_usage = (u32) ( 100 * samp_sys_time / (the_rti.cpu_idle_time + samp_sys_time ) );
-      /*move to ms (/proc/stat gives times in 100 ms unit*/
-      the_rti.cpu_idle_time *= 10;
-      if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
-      the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / (the_rti.cpu_idle_time + 10*samp_sys_time ) );
-    }
+         the_rti.sampling_period_duration = (entry_time - last_update_time);
+         the_rti.process_cpu_time_diff = (process_u_k_time - last_process_k_u_time) * 10;
+
+         /*oops, we have no choice but to assume 100% cpu usage during this period*/
+         if (!u_k_time) {
+                 the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
+                 u_k_time = last_cpu_u_k_time + the_rti.sampling_period_duration;
+                 the_rti.cpu_idle_time = 0;
+                 the_rti.total_cpu_usage = 100;
+                 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
+                 the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
+         } else {
+                 u64 samp_sys_time;
+                 /*move to ms (/proc/stat gives times in 100 ms unit*/
+                 the_rti.total_cpu_time_diff = (u_k_time - last_cpu_u_k_time)*10;
+
+                 /*we're not that accurate....*/
+                 if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
+                         the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
+
+
+                 if (!idle_time) idle_time = (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff)/10;
+                 samp_sys_time = u_k_time - last_cpu_u_k_time;
+                 the_rti.cpu_idle_time = idle_time - last_cpu_idle_time;
+                 the_rti.total_cpu_usage = (u32) ( 100 * samp_sys_time / (the_rti.cpu_idle_time + samp_sys_time ) );
+                 /*move to ms (/proc/stat gives times in 100 ms unit*/
+                 the_rti.cpu_idle_time *= 10;
+                 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
+                 the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / (the_rti.cpu_idle_time + 10*samp_sys_time ) );
+         }
   } else {
-    mem_at_startup = the_rti.physical_memory_avail;
+         mem_at_startup = the_rti.physical_memory_avail;
   }
   the_rti.process_memory = mem_at_startup - the_rti.physical_memory_avail;
 #ifdef GPAC_MEMORY_TRACKING
@@ -1531,16 +1689,14 @@ Bool gf_sys_get_rti(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
 
 char * gf_get_default_cache_directory(){  
 #ifdef _WIN32_WCE
-  return gf_strdup( "\\windows\\temp" );
+       return gf_strdup( "\\windows\\temp" );
 #elif defined(WIN32)
-  char szPath[512];
-  GetWindowsDirectory(szPath, 507);
-  if (szPath[strlen(szPath)-1] != '\\')
-    strcat((char*)szPath, "\\");
-  strcat((char *)szPath, "Temp");
-  return gf_strdup( szPath );
+       char szPath[MAX_PATH];
+       /*ivica patch*/
+       GetTempPath(MAX_PATH, szPath);
+       return gf_strdup( szPath );
 #else
-  return gf_strdup("/tmp");
+       return gf_strdup("/tmp");
 #endif
 }
 
@@ -1571,7 +1727,7 @@ Bool gf_sys_get_battery_state(Bool *onBattery, u32 *onCharge, u32*level, u32 *ba
 
 
 struct GF_GlobalLock {
-    const char * resourceName;
+       const char * resourceName;
 };
 
 
@@ -1583,92 +1739,92 @@ struct GF_GlobalLock {
 #include <unistd.h>
 
 struct _GF_GlobalLock_opaque {
-    char * resourceName;
-    char * pidFile;
-    int fd;
+       char * resourceName;
+       char * pidFile;
+       int fd;
 };
 
 GF_GlobalLock * gf_create_PID_file( const char * resourceName )
 {
-  const char * prefix = "/gpac_lock_";
-  const char * dir = gf_get_default_cache_directory();
-  char * pidfile;
-  int flags;
-  int status;
-  pidfile = gf_malloc(strlen(dir)+strlen(prefix)+strlen(resourceName)+1);
-  strcpy(pidfile, dir);
-  strcat(pidfile, prefix);
-  /* Use only valid names for file */
-  {
-    const char *res;
-    char * pid = &(pidfile[strlen(pidfile)]);
-    for (res = resourceName; *res ; res++){
-      if (*res >= 'A' && *res <= 'z')
-       *pid = * res;
-      else
-       *pid = '_';
-      pid++;
-    }
-    *pid = '\0';
-  }
-  int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
-  if (fd == -1)
-    goto exit;
-  /* Get the flags */
-  flags = fcntl(fd, F_GETFD);
-  if (flags == -1){
-      goto exit;
-  }
-   /* Set FD_CLOEXEC, so exclusive lock will be removed on exit, so even if GPAC crashes,
-    * lock will be allowed for next instance */
-  flags |= FD_CLOEXEC;
-  /* Now, update the flags */
-  if (fcntl(fd, F_SETFD, flags) == -1){
-    goto exit;
-  }
-  
-  /* Now, we try to lock the file */
-  {
-    struct flock fl;
-    fl.l_type = F_WRLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = fl.l_len = 0;
-    status = fcntl(fd, F_SETLK, &fl);
-  }
+       const char * prefix = "/gpac_lock_";
+       const char * dir = gf_get_default_cache_directory();
+       char * pidfile;
+       int flags;
+       int status;
+       pidfile = gf_malloc(strlen(dir)+strlen(prefix)+strlen(resourceName)+1);
+       strcpy(pidfile, dir);
+       strcat(pidfile, prefix);
+       /* Use only valid names for file */
+       {
+               const char *res;
+               char * pid = &(pidfile[strlen(pidfile)]);
+               for (res = resourceName; *res ; res++){
+                       if (*res >= 'A' && *res <= 'z')
+                               *pid = * res;
+                       else
+                               *pid = '_';
+                       pid++;
+               }
+               *pid = '\0';
+       }
+       int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+       if (fd == -1)
+               goto exit;
+       /* Get the flags */
+       flags = fcntl(fd, F_GETFD);
+       if (flags == -1){
+               goto exit;
+       }
+       /* Set FD_CLOEXEC, so exclusive lock will be removed on exit, so even if GPAC crashes,
+       * lock will be allowed for next instance */
+       flags |= FD_CLOEXEC;
+       /* Now, update the flags */
+       if (fcntl(fd, F_SETFD, flags) == -1){
+               goto exit;
+       }
 
-  if (status == -1) {
-    goto exit;
-  }
+       /* Now, we try to lock the file */
+       {
+               struct flock fl;
+               fl.l_type = F_WRLCK;
+               fl.l_whence = SEEK_SET;
+               fl.l_start = fl.l_len = 0;
+               status = fcntl(fd, F_SETLK, &fl);
+       }
 
-    if (ftruncate(fd, 0) == -1){
-      goto exit;
-    }
-  /* Write the PID */
-  {
-    int sz = 100;
-    char * buf = gf_malloc( sz );
-    sz = snprintf(buf, sz, "%ld\n", (long) getpid());
-    if (write(fd, buf, sz) != sz){
-        gf_free(buf);
-       goto exit;
-    }
-  }
-  sync();
-  {
-      GF_GlobalLock * lock = gf_malloc( sizeof(GF_GlobalLock));
-      lock->resourceName = gf_strdup(resourceName);
-      lock->pidFile = pidfile;
-      lock->fd = fd;
-      return lock;
-  }
+       if (status == -1) {
+               goto exit;
+       }
+
+       if (ftruncate(fd, 0) == -1){
+               goto exit;
+       }
+       /* Write the PID */
+       {
+               int sz = 100;
+               char * buf = gf_malloc( sz );
+               sz = snprintf(buf, sz, "%ld\n", (long) getpid());
+               if (write(fd, buf, sz) != sz){
+                       gf_free(buf);
+                       goto exit;
+               }
+       }
+       sync();
+       {
+               GF_GlobalLock * lock = gf_malloc( sizeof(GF_GlobalLock));
+               lock->resourceName = gf_strdup(resourceName);
+               lock->pidFile = pidfile;
+               lock->fd = fd;
+               return lock;
+       }
 exit:
-  if (fd >= 0)
-    close(fd);
-  return NULL;
+       if (fd >= 0)
+               close(fd);
+       return NULL;
 }
 #else /* WIN32 */
 struct _GF_GlobalLock_opaque {
-    char * resourceName;
+       char * resourceName;
        HANDLE hMutex; /*a named mutex is a system-mode object on windows*/
 };
 #endif
@@ -1679,6 +1835,7 @@ GF_GlobalLock * gf_global_resource_lock(const char * resourceName){
 #ifdef _WIN32_WCE
        unsigned short sWResourceName[MAX_PATH];
 #endif
+       DWORD lastErr;
        GF_GlobalLock *lock = gf_malloc(sizeof(GF_GlobalLock));
        lock->resourceName = gf_strdup(resourceName);
 
@@ -1689,10 +1846,13 @@ GF_GlobalLock * gf_global_resource_lock(const char * resourceName){
 #else
        lock->hMutex = CreateMutex(NULL, TRUE, resourceName);
 #endif
-       if (!lock->hMutex) {
-               DWORD lastErr = GetLastError();
-               if (lastErr != ERROR_ALREADY_EXISTS)
-                       return NULL;
+       lastErr = GetLastError();
+       if (lastErr && lastErr == ERROR_ALREADY_EXISTS)
+               return NULL;
+       if (!lock->hMutex)
+       {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't create mutex for global lock: %d\n", lastErr));
+               return NULL;
        }
 
        /*then lock it*/
@@ -1700,6 +1860,7 @@ GF_GlobalLock * gf_global_resource_lock(const char * resourceName){
        case WAIT_ABANDONED:
        case WAIT_TIMEOUT:
                assert(0); /*serious error: someone has modified the object elsewhere*/
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't get the global lock\n"));
                gf_global_resource_unlock(lock);
                return NULL;
        }
@@ -1716,28 +1877,52 @@ GF_GlobalLock * gf_global_resource_lock(const char * resourceName){
  * \return GF_OK if evertything went fine
  */
 GF_Err gf_global_resource_unlock(GF_GlobalLock * lock){
-    if (!lock)
-      return GF_BAD_PARAM;
+       if (!lock)
+               return GF_BAD_PARAM;
 #ifndef WIN32
-    assert( lock->pidFile);
-    close(lock->fd);
-    if (unlink(lock->pidFile))
-      perror("Failed to unlink lock file");
-    gf_free(lock->pidFile);
-    lock->pidFile = NULL;
-    lock->fd = -1;
+       assert( lock->pidFile);
+       close(lock->fd);
+       if (unlink(lock->pidFile))
+               perror("Failed to unlink lock file");
+       gf_free(lock->pidFile);
+       lock->pidFile = NULL;
+       lock->fd = -1;
 #else /* WIN32 */
        {
                /*MSDN: "The mutex object is destroyed when its last handle has been closed."*/
                BOOL ret = ReleaseMutex(lock->hMutex);
-               assert(ret);
+               if (!ret) {
+                       DWORD err = GetLastError();
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't release mutex for global lock: %d\n", err));
+               }
                ret = CloseHandle(lock->hMutex);
-               assert(ret);
+               if (!ret) {
+                       DWORD err = GetLastError();
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't destroy mutex for global lock: %d\n", err));
+               }
        }
 #endif
        if (lock->resourceName)
                gf_free(lock->resourceName);
-    lock->resourceName = NULL;
-    gf_free(lock);
-    return GF_OK;
+       lock->resourceName = NULL;
+       gf_free(lock);
+       return GF_OK;
 }
+
+#ifdef GPAC_ANDROID
+
+fm_callback_func fm_cbk = NULL;
+static void *fm_cbk_obj = NULL;
+
+void gf_fm_request_set_callback(void *cbk_obj, fm_callback_func cbk_func) {
+       fm_cbk = cbk_func;
+       fm_cbk_obj = cbk_obj;
+}
+
+void gf_fm_request_call(u32 type, u32 param, int *value) {
+       if (fm_cbk)
+               fm_cbk(fm_cbk_obj, type, param, value);
+}
+
+#endif //GPAC_ANDROID
+
index bd2595b9803d1e97c41d586ea4d923f6f8908eed..36bd87451817cfc43ee02028ee4a5625f045f146 100644 (file)
@@ -79,6 +79,10 @@ Bool gf_modules_load_library(ModuleInstance *inst)
        if (inst->lib_handle) return 1;
        GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Load module file %s\n", inst->name));
 
+#if _WIN32_WINNT >= 0x0502
+       SetDllDirectory(inst->plugman->dir);
+#endif
+
 #ifdef _WIN32_WCE
        sprintf(s_path, "%s%c%s", inst->plugman->dir, GF_PATH_SEPARATOR, inst->name);
        CE_CharToWide(s_path, path);
@@ -321,9 +325,16 @@ u32 gf_modules_refresh(GF_ModuleManager *pm)
                GF_SAFEALLOC(inst, ModuleInstance);
                inst->interfaces = gf_list_new();
                inst->plugman = pm;
-               inst->name = gf_strdup("gm_gpac_js.dylib");
+               inst->name = gf_strdup("gm_hyb_in.dylib");
                gf_list_add(pm->plug_list, inst);
        }
+       {
+               ModuleInstance *inst;
+               GF_SAFEALLOC(inst, ModuleInstance);
+               inst->interfaces = gf_list_new();
+               inst->plugman = pm;
+               inst->name = gf_strdup("gm_gpac_js.dylib");
+       }
        {
                ModuleInstance *inst;
                GF_SAFEALLOC(inst, ModuleInstance);
index 71f2546b6174a1f2d4ceb1d70f42bf86c45fc33f..569916e1f49cd371199f5bb3e1f9fcc1be607bcf 100644 (file)
@@ -145,7 +145,7 @@ typedef s32 SOCKET;
 static u32 ipv6_check_state = 0;
 #endif
 
-#ifdef __x86_64__
+#ifdef _LP64
 #define NULL_SOCKET 0
 #else
 #define NULL_SOCKET (SOCKET)NULL
@@ -407,9 +407,11 @@ GF_Err gf_sk_set_block_mode(GF_Socket *sock, u32 NonBlockingOn)
        return GF_OK;
 }
 
+#include <assert.h>
 
 static void gf_sk_free(GF_Socket *sock)
 {
+       assert( sock );
        /*leave multicast*/
        if (sock->socket && (sock->flags & GF_SOCK_IS_MULTICAST) ) {
                struct ip_mreq mreq;
@@ -441,8 +443,10 @@ static void gf_sk_free(GF_Socket *sock)
        }
 }
 
+
 void gf_sk_del(GF_Socket *sock)
 {
+       assert( sock );
        gf_sk_free(sock);
 #ifdef WIN32
        wsa_init --;
@@ -799,7 +803,6 @@ GF_Err gf_sk_bind(GF_Socket *sock, const char *local_ip, u16 port, const char *p
 //send length bytes of a buffer
 GF_Err gf_sk_send(GF_Socket *sock, const char *buffer, u32 length)
 {
-       GF_Err e;
        u32 count;
        s32 res;
 #ifndef __SYMBIAN32__
@@ -808,8 +811,6 @@ GF_Err gf_sk_send(GF_Socket *sock, const char *buffer, u32 length)
        fd_set Group;
 #endif
 
-       e = GF_OK;
-
        //the socket must be bound or connected
        if (!sock || !sock->socket) return GF_BAD_PARAM;
 
@@ -1077,7 +1078,6 @@ GF_Err gf_sk_setup_multicast(GF_Socket *sock, const char *multi_IPAdd, u16 Multi
 //BytesRead is the number of bytes read from the network
 GF_Err gf_sk_receive(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u32 *BytesRead)
 {
-       GF_Err e;
        s32 res;
 #ifndef __SYMBIAN32__
        s32 ready;
@@ -1085,8 +1085,6 @@ GF_Err gf_sk_receive(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u
        fd_set Group;
 #endif
 
-       e = GF_OK;
-
        *BytesRead = 0;
        if (!sock->socket) return GF_BAD_PARAM;
        if (startFrom >= length) return GF_IO_ERR;
@@ -1169,7 +1167,6 @@ GF_Err gf_sk_listen(GF_Socket *sock, u32 MaxConnection)
 GF_Err gf_sk_accept(GF_Socket *sock, GF_Socket **newConnection)
 {
        u32 client_address_size;
-       s32 res;
        SOCKET sk;
 #ifndef __SYMBIAN32__
        s32 ready;
@@ -1186,7 +1183,6 @@ GF_Err gf_sk_accept(GF_Socket *sock, GF_Socket **newConnection)
        timeout.tv_sec = 0;
        timeout.tv_usec = SOCK_MICROSEC_WAIT;
 
-       res = 0;
        ready = select(sock->socket+1, &Group, NULL, NULL, &timeout);
        if (ready == SOCKET_ERROR) {
                switch (LASTSOCKERROR) {
@@ -1401,19 +1397,16 @@ GF_Err gf_sk_send_to(GF_Socket *sock, const char *buffer, u32 length, char *remo
 
 GF_Err gf_sk_receive_wait(GF_Socket *sock, char *buffer, u32 length, u32 startFrom, u32 *BytesRead, u32 Second )
 {
-       GF_Err e;
        s32 res;
 #ifndef __SYMBIAN32__
        s32 ready;
        struct timeval timeout;
        fd_set Group;
 #endif
-       e = GF_OK;
 
        *BytesRead = 0;
        if (startFrom >= length) return GF_OK;
 
-
 #ifndef __SYMBIAN32__
        //can we read?
        FD_ZERO(&Group);
@@ -1454,8 +1447,6 @@ GF_Err gf_sk_receive_wait(GF_Socket *sock, char *buffer, u32 length, u32 startFr
 //send length bytes of a buffer
 GF_Err gf_sk_send_wait(GF_Socket *sock, const char *buffer, u32 length, u32 Second )
 {
-
-       GF_Err e;
        u32 count;
        s32 res;
 #ifndef __SYMBIAN32__
@@ -1463,7 +1454,6 @@ GF_Err gf_sk_send_wait(GF_Socket *sock, const char *buffer, u32 length, u32 Seco
        struct timeval timeout;
        fd_set Group;
 #endif
-       e = GF_OK;
 
        //the socket must be bound or connected
        if (!sock || !sock->socket) return GF_BAD_PARAM;
index a01a114fb080d7c510aa041a4d63910ed67a559b..f74cc0869ae16f97a312d76cd6c682cdae15f557 100644 (file)
@@ -65,7 +65,7 @@ struct __tag_thread
        char *log_name;
 #endif
 #ifdef GPAC_ANDROID
-        u32 (*RunBeforeExit)(void *param);
+       u32 (*RunBeforeExit)(void *param);
 #endif
 };
 
@@ -133,17 +133,19 @@ static pthread_once_t currentThreadInfoKey_once = PTHREAD_ONCE_INIT;
 
 GF_Err gf_register_before_exit_function(GF_Thread *t, u32 (*toRunBeforePthreadExit)(void *param) )
 {
-      if (!t)
-        return GF_BAD_PARAM;
-      t->RunBeforeExit = toRunBeforePthreadExit;
-      return GF_OK;
+       if (!t)
+               return GF_BAD_PARAM;
+       t->RunBeforeExit = toRunBeforePthreadExit;
+       return GF_OK;
 }
 
 /* Unique key allocation */
 static void currentThreadInfoKey_alloc()
 {
+       int err;
   /* We do not use any destructor */
-  pthread_key_create(&currentThreadInfoKey, NULL);
+  if (err = pthread_key_create(&currentThreadInfoKey, NULL))
+       GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] pthread_key_create() failed with error %d\n", err));
 }
 
 GF_Thread * gf_th_current(){
@@ -167,8 +169,8 @@ void * RunThread(void *ptr)
        /* Signal the caller */
        if (! t->_signal) goto exit;
 #ifdef GPAC_ANDROID
-        pthread_once(&currentThreadInfoKey_once, &currentThreadInfoKey_alloc);
-        pthread_setspecific(currentThreadInfoKey, t);
+       if (pthread_once(&currentThreadInfoKey_once, &currentThreadInfoKey_alloc) || pthread_setspecific(currentThreadInfoKey, t))
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't run thread %s, ID 0x%08x\n", t->log_name, t->id));
 #endif /* GPAC_ANDROID */
        t->status = GF_THREAD_STATUS_RUN;
        gf_sema_notify(t->_signal, 1);
@@ -191,17 +193,20 @@ exit:
        t->status = GF_THREAD_STATUS_DEAD;
        t->Run = NULL;
 #ifdef WIN32
-       CloseHandle(t->threadH);
+       if (!CloseHandle(t->threadH)) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Thread %s] Couldn't close handle when exiting thread proc, error code: %d\n", t->log_name, err));
+       }
        t->threadH = NULL;
        return ret;
 #else
 
 #ifdef GPAC_ANDROID
-        #ifndef GPAC_DISABLE_LOG
-          GF_LOG(GF_LOG_INFO, GF_LOG_MUTEX, ("[Thread %s] RunBeforeExit=%p\n", t->log_name, t->RunBeforeExit));
-        #endif
-        if (t->RunBeforeExit)
-          t->RunBeforeExit(t->args);
+       #ifndef GPAC_DISABLE_LOG
+               GF_LOG(GF_LOG_INFO, GF_LOG_MUTEX, ("[Thread %s] RunBeforeExit=%p\n", t->log_name, t->RunBeforeExit));
+       #endif
+       if (t->RunBeforeExit)
+               t->RunBeforeExit(t->args);
 #endif /* GPAC_ANDROID */
        pthread_exit((void *)0);
        return (void *)ret;
@@ -248,7 +253,11 @@ void Thread_Stop(GF_Thread *t, Bool Destroy)
 #ifdef WIN32
                if (Destroy) {
                        DWORD dw = 1;
-                       TerminateThread(t->threadH, dw);
+                       BOOL ret = TerminateThread(t->threadH, dw);
+                       if (!ret) {
+                               DWORD err = GetLastError();
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Thread %s] Couldn't stop thread ID 0x%08x, error code %d\n", t->log_name, t->id, err));
+                       }
                        t->threadH = NULL;
                } else {
                        WaitForSingleObject(t->threadH, INFINITE);
@@ -256,14 +265,16 @@ void Thread_Stop(GF_Thread *t, Bool Destroy)
 #else
                if (Destroy) {
 #ifdef GPAC_ANDROID
-                       pthread_kill(t->threadH, SIGQUIT);
+                       if (pthread_kill(t->threadH, SIGQUIT))
 #else
-                       pthread_cancel(t->threadH);
+                       if (pthread_cancel(t->threadH))
 #endif
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Thread %s] Couldn't kill thread ID 0x%08x\n", t->log_name, t->id));
                        t->threadH = 0;
                } else {
                        /*gracefully wait for Run to finish*/
-                       pthread_join(t->threadH, NULL);
+                       if (pthread_join(t->threadH, NULL))
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Thread %s] pthread_join() returned an error with thread ID 0x%08x\n", t->log_name, t->id));
                }
 #endif
        }
@@ -300,7 +311,39 @@ void gf_th_set_priority(GF_Thread *t, s32 priority)
 #ifdef WIN32
        /*!! in WinCE, changin thread priority is extremely dangerous, it may freeze threads randomly !!*/
 #ifndef _WIN32_WCE
-       SetThreadPriority(t ? t->threadH : GetCurrentThread(), priority);
+       int _prio;
+       BOOL ret;
+       switch (priority) {
+       case GF_THREAD_PRIORITY_IDLE:
+               _prio = THREAD_PRIORITY_IDLE;
+               break;
+       case GF_THREAD_PRIORITY_LESS_IDLE:
+               _prio = THREAD_PRIORITY_IDLE;
+               break;
+       case GF_THREAD_PRIORITY_LOWEST:
+               _prio = THREAD_PRIORITY_LOWEST;
+               break;
+       case GF_THREAD_PRIORITY_LOW:
+               _prio = THREAD_PRIORITY_BELOW_NORMAL;
+               break;
+       case GF_THREAD_PRIORITY_NORMAL:
+               _prio = THREAD_PRIORITY_NORMAL;
+               break;
+       case GF_THREAD_PRIORITY_HIGH:
+               _prio = THREAD_PRIORITY_ABOVE_NORMAL;
+               break;
+       case GF_THREAD_PRIORITY_HIGHEST:
+               _prio = THREAD_PRIORITY_HIGHEST;
+               break;
+       default: /*GF_THREAD_PRIORITY_REALTIME -> GF_THREAD_PRIORITY_REALTIME_END*/
+               _prio = THREAD_PRIORITY_TIME_CRITICAL;
+               break;
+       }
+       ret = SetThreadPriority(t ? t->threadH : GetCurrentThread(), _prio);
+       if (!ret) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_WARNING, GF_LOG_MUTEX, ("[Thread %s] Couldn't set priority for thread ID 0x%08x, error %d\n", t->log_name, t->id, err));
+       }
 #endif
 
 #else
@@ -311,10 +354,12 @@ void gf_th_set_priority(GF_Thread *t, s32 priority)
        /* consider this as real-time priority */
        if (priority > 200) {
                s_par.sched_priority = priority - 200;
-               pthread_setschedparam(t->threadH, SCHED_RR, &s_par);
+               if (pthread_setschedparam(t->threadH, SCHED_RR, &s_par))
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MUTEX, ("[Thread %s] Couldn't set priority(1) for thread ID 0x%08x\n", t->log_name, t->id));
        } else {
                s_par.sched_priority = priority;
-               pthread_setschedparam(t->threadH, SCHED_OTHER, &s_par);
+               if (pthread_setschedparam(t->threadH, SCHED_OTHER, &s_par))
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_MUTEX, ("[Thread %s] Couldn't set priority(2) for thread ID 0x%08x\n", t->log_name, t->id));
        }
 
 #endif
@@ -372,6 +417,7 @@ GF_Mutex *gf_mx_new(const char *name)
        pthread_mutexattr_init(&attr);
        if ( pthread_mutex_init(&tmp->hMutex, &attr) != 0 ) {
 #endif
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't create mutex %s\n", strlen(name) ? name : ""));
                gf_free(tmp);
                return NULL;
        }
@@ -393,9 +439,15 @@ GF_Mutex *gf_mx_new(const char *name)
 void gf_mx_del(GF_Mutex *mx)
 {
 #ifdef WIN32
-       CloseHandle(mx->hMutex);
+       if (!CloseHandle(mx->hMutex)) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex %s] CloseHandle when deleting mutex failed with error code %d\n", mx->log_name, err));
+       }
 #else
-       pthread_mutex_destroy(&mx->hMutex);
+       int err = pthread_mutex_destroy(&mx->hMutex);
+       if (err)
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex %s] pthread_mutex_destroy failed with error code %d\n", mx->log_name, err));
+
 #endif
 #ifndef GPAC_DISABLE_LOG
        gf_free(mx->log_name);
@@ -422,9 +474,16 @@ void gf_mx_v(GF_Mutex *mx)
 #endif
                mx->Holder = 0;
 #ifdef WIN32
-               ReleaseMutex(mx->hMutex);
+               {
+                       BOOL ret = ReleaseMutex(mx->hMutex);
+                       if (!ret) {
+                               DWORD err = GetLastError();
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't release mutex (thread %s, error %d)\n", log_th_name(mx->Holder), err));
+                       }
+               }
 #else
-               pthread_mutex_unlock(&mx->hMutex);
+               if (pthread_mutex_unlock(&mx->hMutex))
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't release mutex (thread %s)\n", log_th_name(mx->Holder)));
 #endif
        }
 }
@@ -475,6 +534,18 @@ u32 gf_mx_p(GF_Mutex *mx)
        return 1;
 }
 
+
+s32 gf_mx_get_num_locks(GF_Mutex *mx)
+{
+       u32 caller;
+       if (!mx) return 0;
+       caller = gf_th_id();
+       if (caller == mx->Holder) {
+               return mx->HolderCount;
+       }
+       return -1;
+}
+
 Bool gf_mx_try_lock(GF_Mutex *mx)
 {
        u32 caller;
@@ -538,6 +609,13 @@ GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount)
        if (!tmp) return NULL;
 #if defined(WIN32)
        tmp->hSemaphore = CreateSemaphore(NULL, InitCount, MaxCount, NULL);
+
+       if (!tmp->hSemaphore) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("Couldn't create semaphore\n"));
+               gf_free(tmp);
+               return NULL;
+       }
+
 #elif defined(__DARWIN__) || defined(__APPLE__)
        /* sem_init isn't supported on Mac OS X 10.3 & 10.4; it returns ENOSYS
        To get around this, a NAMED semaphore needs to be used
@@ -550,28 +628,31 @@ GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount)
                tmp->SemName = gf_strdup(semaName);
        }
        tmp->hSemaphore = sem_open(tmp->SemName, O_CREAT, S_IRUSR|S_IWUSR, InitCount);
+       if (tmp->hSemaphore==SEM_FAILED) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("Couldn't init semaphore: error %d\n", errno));
+               gf_free(tmp);
+               return NULL;
+       }
 #else
        if (sem_init(&tmp->SemaData, 0, InitCount) < 0 ) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("Couldn't init semaphore: error %d\n", errno));
                gf_free(tmp);
                return NULL;
        }
        tmp->hSemaphore = &tmp->SemaData;
 #endif
-
-       if (!tmp->hSemaphore) {
-               gf_free(tmp);
-               return NULL;
-       }
        return tmp;
 }
 
 void gf_sema_del(GF_Semaphore *sm)
 {
 #if defined(WIN32)
-       CloseHandle(sm->hSemaphore);
+       if (!CloseHandle(sm->hSemaphore)) {
+               DWORD err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] CloseHandle when deleting semaphore failed with error code %d\n", err));
+       }
 #elif defined(__DARWIN__) || defined(__APPLE__)
-       sem_t *sema = sem_open(sm->SemName, 0);
-       sem_destroy(sema);
+       sem_destroy(sm->hSemaphore);
        gf_free(sm->SemName);
 #else
        sem_destroy(sm->hSemaphore);
@@ -593,7 +674,7 @@ u32 gf_sema_notify(GF_Semaphore *sm, u32 NbRelease)
 #else
 
 #if defined(__DARWIN__) || defined(__APPLE__)
-       hSem = sem_open(sm->SemName, 0);
+       hSem = sm->hSemaphore;
 #else
        hSem = sm->hSemaphore;
 #endif
@@ -610,14 +691,14 @@ void gf_sema_wait(GF_Semaphore *sm)
 {
 #ifdef WIN32
        WaitForSingleObject(sm->hSemaphore, INFINITE);
+#elif defined (__DARWIN__) || defined(__APPLE__)
+       if (sem_wait(sm->hSemaphore)) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Semaphore] failed to wait for semaphore %s: %d\n", sm->SemName, errno));
+       }
 #else
-       sem_t *hSem;
-#if defined(__DARWIN__) || defined(__APPLE__)
-       hSem = sem_open(sm->SemName, 0);
-#else
-       hSem = sm->hSemaphore;
-#endif
-       sem_wait(hSem);
+       if (sem_wait(sm->hSemaphore)) {
+               GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Semaphore] failed to wait for semaphore: %d\n", errno));
+       }
 #endif
 }
 
@@ -629,7 +710,7 @@ Bool gf_sema_wait_for(GF_Semaphore *sm, u32 TimeOut)
 #else
        sem_t *hSem;
 #if defined(__DARWIN__) || defined(__APPLE__)
-       hSem = sem_open(sm->SemName, 0);
+       hSem = sm->hSemaphore;
 #else
        hSem = sm->hSemaphore;
 #endif
index 0e0033f17e63cbdc254d7ebc82e28865c0e7d1e8..8a618dab1f75b5b7baf52efc55464ff734ef3513 100644 (file)
@@ -337,15 +337,13 @@ static void gf_add_n_bezier(GF_Path *gp, GF_Point2D *newpts, u32 nbPoints)
 {
        Double mu;
        u32 numPoints, i;
-       GF_Point2D start, end;
+       GF_Point2D end;
        numPoints = (u32) FIX2INT(GF_2D_DEFAULT_RES * gp->fineness);
        mu = 0.0;
        if (numPoints) mu = 1/(Double)numPoints;
-       start = newpts[0];
        for (i=1; i<numPoints; i++) {
                NBezier(newpts, nbPoints - 1, i*mu, &end);
                gf_path_add_line_to(gp, end.x, end.y);
-               start = end;
        }
        gf_path_add_line_to(gp, newpts[nbPoints-1].x, newpts[nbPoints-1].y);
 }
@@ -765,7 +763,7 @@ GF_Err gf_path_get_bounds(GF_Path *gp, GF_Rect *rc)
                gp->flags &= ~GF_PATH_BBOX_DIRTY;
                e = gf_path_get_control_bounds(gp, &gp->bbox);
                *rc = gp->bbox;
-               return GF_OK;
+               return e;
        }
 
        gp->flags &= ~GF_PATH_BBOX_DIRTY;
index 75c06c8e0489ac408557cde81ad687ab961edbd6..dafa8728edd061f454dc0f8e00707f061d0cdd6e 100644 (file)
@@ -485,6 +485,11 @@ att_retry:
                sep = strchr(parser->buffer + parser->current_pos, parser->att_sep);
                if (!sep || !sep[1]) return 1;
 
+               if (sep[1]==parser->att_sep) {
+                       format_sax_error(parser, sep - parser->buffer, "Invalid character %c after attribute value separator %c ", sep[1], parser->att_sep);
+                       return 1;
+               }
+
                if (!parser->init_state && (strchr(" />\n\t\r", sep[1])==NULL)) {
                        parser->current_pos = sep - parser->buffer + 1;
                        goto att_retry;
@@ -1577,6 +1582,7 @@ static void on_dom_node_end(void *cbk, const char *name, const char *ns)
        gf_list_rem_last(par->stack);
 
        if (!last || strcmp(last->name, name) || (!ns && last->ns) || (ns && !last->ns) || (ns && strcmp(last->ns, ns) ) ) {
+               format_sax_error(par->parser, 0, "Invalid node stack: closing node is %s but %s was expected", name, last->name);
                par->parser->suspended = 1;
                gf_xml_dom_node_del(last);
                if (last==par->root) par->root=NULL;
@@ -1671,6 +1677,18 @@ GF_Err gf_xml_dom_parse(GF_DOMParser *dom, const char *file, gf_xml_sax_progress
        return e<0 ? e : GF_OK;
 }
 
+GF_EXPORT
+GF_Err gf_xml_dom_parse_string(GF_DOMParser *dom, char *string)
+{
+       GF_Err e;
+       gf_xml_dom_reset(dom, 1);
+       dom->stack = gf_list_new();
+       dom->parser = gf_xml_sax_new(on_dom_node_start, on_dom_node_end, on_dom_text_content, dom);
+       e = gf_xml_sax_init(dom->parser, string);
+       gf_xml_dom_reset(dom, 0);
+       return e<0 ? e : GF_OK;
+}
+
 GF_EXPORT
 GF_XMLNode *gf_xml_dom_get_root(GF_DOMParser *parser)
 {