Projects
Essentials
gpac
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 31
View file
gpac.changes
Changed
@@ -1,4 +1,19 @@ ------------------------------------------------------------------- +Sat Nov 28 13:50:35 UTC 2020 - Luigi Baldoni <aloisio@gmx.com> + +- Update to version 1.0.1 + * better ttml import + * better support for MPEGH audio + * support fur DASH UTCTiming + * manifest generation from pre-fragmented DASH/HLS mp4 + * speed optimization in isobmf reading (normal and fragmented) + * improved JS API for the filter session + * core tools exposed as JS module (file io, bitstream, etc ...) +- Drop gpac-1.0.0-no-pc.patch and gpac-1.0.0-remove_debianism.patch + (no longer necessary) +- Add gpac-1.0.1-desktop.patch + +------------------------------------------------------------------- Sat Jun 27 10:55:16 UTC 2020 - Luigi Baldoni <aloisio@gmx.com> - Update to version 1.0
View file
gpac.spec
Changed
@@ -19,7 +19,7 @@ %define sover 10 Name: gpac -Version: 1.0.0 +Version: 1.0.1 Release: 0 Summary: A multimedia framework covering MPEG-4, VRML/X3D and SVG License: LGPL-2.1-or-later @@ -31,11 +31,9 @@ Patch2: gpac-0.7.1-SVGGen_abuild.patch #PATCH-FIX-UPSTREAM wengxuetian@gmail.com - fix E: 64bit-portability-issue Patch3: gpac-1.0.0-64bit-portability.patch -#PATCH-FIX-UPSTREAM marguerite@opensuse.org - no gpac.pc in devel package -Patch6: gpac-1.0.0-no-pc.patch Patch12: gpac.ssl.patch -# PATCH-FIX-UPSTREAM gpac-1.0.0-remove_debianism.patch -Patch13: gpac-1.0.0-remove_debianism.patch +# PATCH-FIX-OPENSUSE gpac-1.0.1-desktop.patch +Patch14: gpac-1.0.1-desktop.patch BuildRequires: Mesa-devel BuildRequires: dos2unix BuildRequires: doxygen @@ -120,9 +118,6 @@ %autosetup -p1 %build -# remove icon path -sed -i '/^Icon/cIcon=gpac' share/gpac.desktop - # configure the beast ./configure \ --prefix="%{_prefix}" \
View file
gpac-1.0.0-no-pc.patch
Deleted
@@ -1,12 +0,0 @@ -Index: gpac-1.0.0/Makefile -=================================================================== ---- gpac-1.0.0.orig/Makefile -+++ gpac-1.0.0/Makefile -@@ -113,6 +113,7 @@ dep: depend - install: - $(INSTALL) -d "$(DESTDIR)$(prefix)" - $(INSTALL) -d "$(DESTDIR)$(prefix)/$(libdir)" -+ $(INSTALL) -d "$(DESTDIR)$(prefix)/$(libdir)/pkgconfig" - $(INSTALL) -d "$(DESTDIR)$(prefix)/bin" - $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/gpac$(EXE_SUFFIX) "$(DESTDIR)$(prefix)/bin" - ifeq ($(DISABLE_ISOFF), no)
View file
gpac-1.0.0-remove_debianism.patch
Deleted
@@ -1,39 +0,0 @@ -From 45633fabccf331405f5c09aa44db86d6962dfd0f Mon Sep 17 00:00:00 2001 -From: Aurelien David <aurelien.david@telecom-paristech.fr> -Date: Wed, 17 Jun 2020 20:03:59 +0200 -Subject: [PATCH] don't use sylinks for pixmap in make install (#1512) - ---- - Makefile | 11 +++-------- - 1 file changed, 3 insertions(+), 8 deletions(-) - -Index: gpac-1.0.0/Makefile -=================================================================== ---- gpac-1.0.0.orig/Makefile -+++ gpac-1.0.0/Makefile -@@ -164,13 +164,8 @@ ifneq ($(CONFIG_DARWIN),yes) - $(INSTALL) -d "$(DESTDIR)$(prefix)/share/pixmaps" - $(INSTALL) -d "$(DESTDIR)$(prefix)/share/applications" - --ifeq ($(IS_DEB_MAKE),undefined) -- ln -sf $(DESTDIR)$(prefix)/share/gpac/res/gpac.png $(DESTDIR)/usr/share/pixmaps/gpac.png -+ $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/res/gpac.png "$(DESTDIR)$(prefix)/share/pixmaps/" - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gpac.desktop "$(DESTDIR)/usr/share/applications/" --else -- dh_link $(DESTDIR)$(prefix)/share/gpac/res/gpac.png $(DESTDIR)$(prefix)/share/pixmaps/gpac.png -- $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gpac.desktop "$(DESTDIR)$(prefix)/share/applications/" --endif - - endif - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gui/gui.bt "$(DESTDIR)$(prefix)/share/gpac/gui/" -@@ -240,8 +235,8 @@ endif - rm -rf $(DESTDIR)$(mandir)/man1/gpac.1 - rm -rf $(DESTDIR)$(mandir)/man1/gpac-filters.1 - rm -rf $(DESTDIR)$(prefix)/share/gpac -- rm -rf $(DESTDIR)/usr/share/pixmaps/gpac.png -- rm -rf $(DESTDIR)/usr/share/applications/gpac.desktop -+ rm -rf $(DESTDIR)/$(prefix)/share/pixmaps/gpac.png -+ rm -rf $(DESTDIR)/$(prefix)/share/applications/gpac.desktop - rm -rf $(DESTDIR)$(prefix)/include/gpac - - installdylib:
View file
gpac-1.0.1-desktop.patch
Added
@@ -0,0 +1,13 @@ +Index: gpac-1.0.1/configure +=================================================================== +--- gpac-1.0.1.orig/configure ++++ gpac-1.0.1/configure +@@ -3290,7 +3290,7 @@ generate_gpacdesktop () { + echo "Terminal=false" + echo "X-MultipleArgs=false" + echo "Type=Application" +- echo "Icon=$prefix/share/pixmaps/gpac.png" ++ echo "Icon=gpac.png" + echo "Categories=AudioVideo" + echo "MimeType=text/text;text/xml;application/xhtml+xml;application/xml;image/jpeg;image/png;video/webm;video/mp4;video/mpeg;audio/mp4;audio/mpeg;x-scheme-handler/rtsp;x-scheme-handler/rtp;x-scheme-handler/atsc" + echo "StartupNotify=true"
View file
gpac-1.0.0.tar.gz/include/gpac/ismacryp.h
Deleted
@@ -1,222 +0,0 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2000-2012 - * All rights reserved - * - * This file is part of GPAC / Authoring Tools sub-project - * - * 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_ISMACRYP_H_ -#define _GF_ISMACRYP_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * \file <gpac/ismacryp.h> - * \brief Utility tools for ISMA and Common Encryption. - */ - -/*! - * \addtogroup crypt_grp - * \ingroup media_grp - * \brief Utility tools for ISMA and Common Encryption. - * - *This section documents the encryption and decryption of ISOBMF files according to ISMA and CENC specifications. - * @{ - */ - -#include <gpac/isomedia.h> - -#ifndef GPAC_DISABLE_AV_PARSERS -//FIXME - we should move AVC and HEVC parsing to gpac/avparse.h -#include <gpac/internal/media_dev.h> -#endif - -/*loads key and salt from a LOCAL gpac-DRM file (cf MP4Box doc)*/ -GF_Err gf_ismacryp_gpac_get_info(u32 stream_id, char *drm_file, char *key, char *salt); - -/*loads key and salt for MPEG4IP protected files*/ -Bool gf_ismacryp_mpeg4ip_get_info(char *kms_uri, char *key, char *salt); - - -enum -{ - /*ISMA E&A encryption*/ - GF_CRYPT_TYPE_ISMA = GF_4CC( 'i', 'A', 'E', 'C' ), - /*CENC CTR-128 encryption*/ - GF_CRYPT_TYPE_CENC = GF_4CC('c','e','n','c'), - /*CENC CBC-128 encryption*/ - GF_CRYPT_TYPE_CBC1 = GF_4CC('c','b','c','1'), - /*CENC CTR-128 pattern encryption*/ - GF_CRYPT_TYPE_CENS = GF_4CC('c','e','n','s'), - /*CENC CBC-128 pattern encryption*/ - GF_CRYPT_TYPE_CBCS = GF_4CC('c','b','c','s'), - /*Adobe CBC-128 encryption*/ - GF_CRYPT_TYPE_ADOBE = GF_4CC('a','d','k','m'), - /*PIFF encryption*/ - GF_CRYPT_TYPE_PIFF = GF_4CC('p','i','f','f'), -}; - -enum -{ - /*no selective encryption*/ - GF_CRYPT_SELENC_NONE = 0, - /*only encrypts RAP samples*/ - GF_CRYPT_SELENC_RAP, - /*only encrypts non-RAP samples*/ - GF_CRYPT_SELENC_NON_RAP, - /*selective encryption of random samples*/ - GF_CRYPT_SELENC_RAND, - /*selective encryption of a random sample in given range*/ - GF_CRYPT_SELENC_RAND_RANGE, - /*selective encryption of first sample in given range*/ - GF_CRYPT_SELENC_RANGE, - /*encryption of all samples but the preview range*/ - GF_CRYPT_SELENC_PREVIEW, - /*no encryption of samples, signaled as unencrypted sample group for CENC*/ - GF_CRYPT_SELENC_CLEAR, - /*no encryption of samples, NOT signaled as unencrypted sample group for CENC*/ - GF_CRYPT_SELENC_CLEAR_FORCED -}; - -typedef struct -{ - /*0: ISMACryp - 1: OMA DRM*/ - u32 enc_type;//for now only used for ISMACrypt - u32 trackID; - unsigned char key[16]; - unsigned char salt[16]; - - /*the rest is only used for encryption*/ - char KMS_URI[5000]; - char Scheme_URI[5000]; - /*selecive encryption type*/ - u32 sel_enc_type; - u32 sel_enc_range; - /*IPMP signaling: 0: none, 1: IPMP, 2: IPMPX - when IPMP signaling is enabled, the OD stream will be updated with - IPMP Update commands*/ - u32 ipmp_type; - /*if not set and IPMP enabled, defaults to TrackID*/ - u32 ipmp_desc_id; - /*type of box where sample auxiliary informations is saved, or 0 in case of ISMACrypt (it will be written in samples)*/ - u32 sai_saved_box_type; - /*force protection scheme specified in crypt file*/ - Bool force_type; - /*OMA extensions*/ - /*0: none, 1: AES CBC, 2: AES CTR*/ - u8 encryption; - char TextualHeaders[5000]; - u32 TextualHeadersLen; - char TransactionID[17]; - /*CENC extensions*/ - u32 IsEncrypted; - u8 IV_size; - bin128 default_KID; - u32 KID_count; - bin128 *KIDs; - bin128 *keys; - /*IV of first sample in track*/ - unsigned char first_IV[16]; - u32 defaultKeyIdx; - u32 keyRoll; - u32 clear_bytes; - u8 crypt_byte_block, skip_byte_block; - u8 constant_IV_size; - unsigned char constant_IV[16]; - //true if using AES-CTR mode, false if using AES-CBC mode - Bool ctr_mode; - u32 scheme_type; - //for avc1 ctr CENC edition 1 - Bool allow_encrypted_slice_header; - //force cenc and cbc1: 0: default, 1: no block alignment of encrypted data, 2: always block align even if producing non encrypted samples - u32 block_align; - - /*0: same stsd for clear samples - 1: dedicated stsd entry for clear samples, placed before the crypted entry in stsd, - 2: dedicated stsd entry for clear samples, placed after the crypted entry in stsd, - */ - u32 force_clear_stsd_idx; - - char metadata[5000]; - u32 metadata_len; - -#ifndef GPAC_DISABLE_AV_PARSERS - AVCState avc; -#ifndef GPAC_DISABLE_HEVC - HEVCState hevc; -#endif -#ifndef GPAC_DISABLE_AV1 - AV1State av1; -#endif - - Bool slice_header_clear; - Bool is_avc; -#endif - -} GF_TrackCryptInfo; - -#if !defined(GPAC_DISABLE_MCRYPT) && !defined(GPAC_DISABLE_ISOM_WRITE) - -/*encrypts track - logs, progress: info callbacks, NULL for default*/ -GF_Err gf_ismacryp_encrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); - -/*decrypts track - logs, progress: info callbacks, NULL for default*/ -GF_Err gf_ismacryp_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); - -/*Common Encryption*/ -/*AES-CTR*/ -GF_Err gf_cenc_encrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); -GF_Err gf_cenc_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); -/*AES-CBC*/ -GF_Err gf_cbc_encrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); -GF_Err gf_cbc_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); - -/*ADOBE*/ -GF_Err gf_adobe_encrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); -GF_Err gf_adobe_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); - - -/*decrypt a file -@drm_file: location of DRM data (cf MP4Box doc). -@LogMsg: redirection for message or NULL for default -*/ -GF_Err gf_decrypt_file(GF_ISOFile *mp4file, const char *drm_file); - -/*Crypt a the file -@drm_file: location of DRM data. -@LogMsg: redirection for message or NULL for default -*/ -GF_Err gf_crypt_file(GF_ISOFile *mp4file, const char *drm_file); - -#endif /*!defined(GPAC_DISABLE_MCRYPT) && !defined(GPAC_DISABLE_ISOM_WRITE)*/ - -/*! @} */ - -#ifdef __cplusplus -} -#endif - - -#endif /*_GF_ISMACRYP_H_*/ -
View file
gpac-1.0.0.tar.gz/share/gpac.desktop
Deleted
@@ -1,21 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=MP4Client -Comment=GPAC Media Player -GenericName=Media Player -Keywords=Media Player -Exec=MP4Client -gui %u -Terminal=false -X-MultipleArgs=false -Type=Application -Icon=/usr/share/pixmaps/gpac.png -Categories=AudioVideo -MimeType=text/text;text/xml;application/xhtml+xml;application/xml;image/jpeg;image/png;video/webm;video/mp4;video/mpeg;audio/mp4;audio/mpeg;x-scheme-handler/rtsp;x-scheme-handler/rtp;x-scheme-handler/atsc -StartupNotify=true -Actions=new-window - -[Desktop Action new-window] -Name=Open a New Window -Exec=MP4Client - -
View file
gpac-1.0.0.tar.gz/share/gui/iphone_wm_gui.js
Deleted
@@ -1,1651 +0,0 @@ -// 01122011 AMD1 startWidget listWidgets getWidget implemented -/* wrapper as a module - 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"); - } - display_width = parseInt(gpac.get_option('General', 'LastWidth')); - display_height = parseInt(gpac.get_option('General', 'LastHeight')); - alert("display "+display_width+" "+display_height); - if (!gpac.fullscreen && display_width && display_height) { - gpac.set_size(display_width, display_height); - } - 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 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); - } -} - -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.SetActionListener("getWidget", get_widget_callback2, true); - device.standardService.CallAction("getWidget", args); - } - target_widgets.register(root); - } -} - -function get_widget_callback2() { - // msgHandler is the first argument, the next arguments are from the reply to listWidgets - alert("callback2-1"); - var act = arguments[0]; - var act1 = act.GetArgumentValue("widgetUrl"); - var act2 = act.GetArgumentValue("widgetContext"); - alert("callback2-2 " + act1 + " " + act2); - var wid = WidgetManager.load(act1, null, act2); - WidgetManager.on_widget_add(wid); -} - -// -// 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', null)); - 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() { document.getElementById("canc").setAttribute("fill", "red"); }, false); - obj.addEventListener('mouseout', function() { document.getElementById("canc").setAttribute("fill", "black"); }, false); - obj.addEventListener('click', function() { upnp_renders.on_select(-1); }, false); - selector.register = function(disp) { - disp.appendChild(this); - }; - selector.unregister = function(disp) { - disp.removeChild(this); - }; - return selector; -} - -// -// 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', null)); - 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() { document.getElementById("cance").setAttribute("fill", "red"); }, false); - obj.addEventListener('mouseout', function() { document.getElementById("cance").setAttribute("fill", "black"); }, false); - obj.addEventListener('click', function() { target_widgets.on_select(-1); }, false); - selector.register = function(disp) { - disp.appendChild(this); - }; - selector.unregister = function(disp) { - disp.removeChild(this); - }; - return selector; -} - -function sw4(si) { - return function() { upnp_renders.on_select(si); }; -} - -function sw5(si) { - return function() { target_widgets.on_select(si); }; -} - -// -// 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")); - } -} - -// -// 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.get_option('Widgets', 'LastWMWidth')); - var display_height = parseInt(gpac.get_option('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 - } -} - -// -// 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'); - homebar.setAttribute('display', 'none'); - execbar.setAttribute('display', 'inline'); - arrows.setAttribute('display', 'none'); - arrowsW.setAttribute('display', 'inline'); - widgetAddList.setAttribute('display', 'none'); - return true; -} - -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); -} - -// -// 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; -} - -// -// 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.set_option("Widgets", "LastWMWidth", '' + previousWidth); - gpac.set_option("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; - } - } - 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); -} - -// 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); - } - } -} - -// -// 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); - } -} - -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'); - 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 - //should do: 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; - } -} - -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); - } -} - -// -// 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; -} - -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; - } - widget_add(w); - adjustWhereWidgets(false); - w.permanent = false; - } -} - -// -// file list vars -// -var 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, 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 (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; - } - 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("/"); - 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); -} - -// -// 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); - } -} - -// -// 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); - } - } - } - } -} - -// -// 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, null); - }; -} - -// // // // // // // // // // // // // // // -// 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; -} - -// -// 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; -} - -// -// 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; -} - -// -// 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.io/svg-extensions', 'use-as-primary', 'false'); - } - return child; -} - -// -// create use -// -function use(uri) { - var child = document.createElement('use'); - child.setAttributeNS(xlinkns, 'href', '#' + uri); - return child; -} - -// -// 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); -} - -// -// substitute for the useful predefined function endsWith -// -function endsWith(s1, s2) { - return s1.toLowerCase().substring(s1.length - s2.length) == s2; -} - -/* wrapper as a module - // 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, - get_widget_callback2: get_widget_callback2 - } - - }());*/ - -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); -}
View file
gpac-1.0.0.tar.gz/share/gui/iphone_wm_gui.svg
Deleted
@@ -1,552 +0,0 @@ -<?xml version="1.0" encoding="iso-8859-1"?> -<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" - xmlns:gpac-ext='http://gpac.sourceforge.net/svg-extensions' - width="571.35199" xmlns:ev="http://www.w3.org/2001/xml-events" height="462.51999" viewBox="0 0 320 600"> - <!-- - This is a Widget Manager creating an iPhone-style UI. - A certain number of widgets are installed, and their icons are visible on the home page. - If the home page is full, arrows appear at the bottom to get to the other pages of icons. - There is a companion file rifuim.js with the script that adapts this SVG to the size of the screen - --> - <defs id="mainDefs"> - <rect id="lightRect" width="80" height="80" fill="rgb(50,50,50)" stroke="none"/> - <rect id="darkRect" width="80" height="80" fill="rgb(40,40,40)" stroke="none"/> - <g id="odd"> - <use xlink:href="#lightRect"/> - <use xlink:href="#darkRect" x="80"/> - </g> - <g id="even"> - <use xlink:href="#darkRect"/> - <use xlink:href="#lightRect" x="80"/> - </g> - <animation id='go-up' xlink:href='icons/go-up.svg' width='25' height='25'/> - <animation id='go-previous' xlink:href='icons/go-previous.svg' width='25' height='25'/> - <animation id='go-next' xlink:href='icons/go-next.svg' width='25' height='25'/> - <animation id='go-jump' xlink:href='icons/go-jump.svg' width='25' height='25'/> - <animation id='folder' xlink:href='icons/folder.svg' width='25' height='25'/> - <animation id='new' xlink:href='icons/document-new.svg' width='25' height='25'/> - <g id="cartouche"> - <g transform="translate(0,0)"> - <use xlink:href="#go-up"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flUpDir();</handler> - </rect> - </g> - <g transform="translate(25,0)"> - <use xlink:href="#go-previous"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flPrevFiles();</handler> - </rect> - </g> - <g transform="translate(50,0)"> - <use xlink:href="#go-next"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flNextFiles();</handler> - </rect> - </g> - <g transform="translate(75,0)"> - <text id="dir" fill="black" font-family="Comic Sans MS" font-size="15" x="0" y="17"/> - </g> - </g> - <g id="cartoucheflag"> - <g transform="translate(0,0)"> - <use xlink:href="#go-up"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flUpDir();</handler> - </rect> - </g> - <g transform="translate(25,0)"> - <use xlink:href="#go-previous"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flPrevFiles();</handler> - </rect> - </g> - <g transform="translate(50,0)"> - <use xlink:href="#go-next"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flNextFiles();</handler> - </rect> - </g> - <g transform="translate(75,0)"> - <use xlink:href="#go-jump"/> - <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> - <handler ev:event="click">flScanDir();</handler> - </rect> - </g> - <g transform="translate(100,0)"> - <text id="dirflag" fill="black" font-family="Comic Sans MS" font-size="15" x="0" y="17"/> - </g> - </g> - <g id="fileMenuElement0"> - <use id="fileMenuElement0u"/> - <rect id="fileMenuElement0r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement0t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement0r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement0r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement1"> - <use id="fileMenuElement1u"/> - <rect id="fileMenuElement1r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement1t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement1r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement1r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement2"> - <use id="fileMenuElement2u"/> - <rect id="fileMenuElement2r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement2t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement2r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement2r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement3"> - <use id="fileMenuElement3u"/> - <rect id="fileMenuElement3r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement3t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement3r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement3r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement4"> - <use id="fileMenuElement4u"/> - <rect id="fileMenuElement4r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement4t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement4r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement4r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement5"> - <use id="fileMenuElement5u"/> - <rect id="fileMenuElement5r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement5t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement5r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement5r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement6"> - <use id="fileMenuElement6u"/> - <rect id="fileMenuElement6r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement6t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement6r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement6r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement7"> - <use id="fileMenuElement7u"/> - <rect id="fileMenuElement7r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement7t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement7r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement7r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement8"> - <use id="fileMenuElement8u"/> - <rect id="fileMenuElement8r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement8t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement8r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement8r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement9"> - <use id="fileMenuElement9u"/> - <rect id="fileMenuElement9r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement9t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement9r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement9r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement10"> - <use id="fileMenuElement10u"/> - <rect id="fileMenuElement10r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement10t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement10r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement10r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement11"> - <use id="fileMenuElement11u"/> - <rect id="fileMenuElement11r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement11t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement11r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement11r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement12"> - <use id="fileMenuElement12u"/> - <rect id="fileMenuElement12r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement12t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement12r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement12r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement13"> - <use id="fileMenuElement13u"/> - <rect id="fileMenuElement13r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement13t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement13r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement13r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement14"> - <use id="fileMenuElement14u"/> - <rect id="fileMenuElement14r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement14t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement14r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement14r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement15"> - <use id="fileMenuElement15u"/> - <rect id="fileMenuElement15r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement15t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement15r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement15r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement16"> - <use id="fileMenuElement16u"/> - <rect id="fileMenuElement16r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement16t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement16r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement16r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement17"> - <use id="fileMenuElement17u"/> - <rect id="fileMenuElement17r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement17t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement17r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement17r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement18"> - <use id="fileMenuElement18u"/> - <rect id="fileMenuElement18r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement18t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement18r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement18r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement19"> - <use id="fileMenuElement19u"/> - <rect id="fileMenuElement19r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement19t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement19r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement19r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement20"> - <use id="fileMenuElement20u"/> - <rect id="fileMenuElement20r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement20t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement20r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement20r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement21"> - <use id="fileMenuElement21u"/> - <rect id="fileMenuElement21r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement21t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement21r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement21r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement22"> - <use id="fileMenuElement22u"/> - <rect id="fileMenuElement22r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement22t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement22r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement22r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement23"> - <use id="fileMenuElement23u"/> - <rect id="fileMenuElement23r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement23t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement23r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement23r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement24"> - <use id="fileMenuElement24u"/> - <rect id="fileMenuElement24r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement24t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement24r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement24r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement25"> - <use id="fileMenuElement25u"/> - <rect id="fileMenuElement25r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement25t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement25r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement25r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement26"> - <use id="fileMenuElement26u"/> - <rect id="fileMenuElement26r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement26t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement26r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement26r").setAttribute("fill", "rgb(245,245,245)");</handler> - </g> - <g id="fileMenuElement27"> - <use id="fileMenuElement27u"/> - <rect id="fileMenuElement27r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement27t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement27r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement27r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement28"> - <use id="fileMenuElement28u"/> - <rect id="fileMenuElement28r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement28t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement28r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement28r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement29"> - <use id="fileMenuElement29u"/> - <rect id="fileMenuElement29r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement29t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement29r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement29r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement30"> - <use id="fileMenuElement30u"/> - <rect id="fileMenuElement30r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement30t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement30r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement30r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement31"> - <use id="fileMenuElement31u"/> - <rect id="fileMenuElement31r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement31t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement31r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement31r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement32"> - <use id="fileMenuElement32u"/> - <rect id="fileMenuElement32r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement32t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement32r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement32r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement33"> - <use id="fileMenuElement33u"/> - <rect id="fileMenuElement33r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement33t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement33r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement33r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement34"> - <use id="fileMenuElement34u"/> - <rect id="fileMenuElement34r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement34t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement34r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement34r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement35"> - <use id="fileMenuElement35u"/> - <rect id="fileMenuElement35r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement35t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement35r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement35r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement36"> - <use id="fileMenuElement36u"/> - <rect id="fileMenuElement36r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement36t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement36r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement36r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement37"> - <use id="fileMenuElement37u"/> - <rect id="fileMenuElement37r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement37t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement37r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement37r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement38"> - <use id="fileMenuElement38u"/> - <rect id="fileMenuElement38r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement38t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement38r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement38r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement39"> - <use id="fileMenuElement39u"/> - <rect id="fileMenuElement39r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement39t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement39r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement39r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement40"> - <use id="fileMenuElement40u"/> - <rect id="fileMenuElement40r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement40t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement40r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement40r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement41"> - <use id="fileMenuElement41u"/> - <rect id="fileMenuElement41r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement41t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement41r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement41r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement42"> - <use id="fileMenuElement42u"/> - <rect id="fileMenuElement42r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement42t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement42r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement42r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement43"> - <use id="fileMenuElement43u"/> - <rect id="fileMenuElement43r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement43t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement43r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement43r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement44"> - <use id="fileMenuElement44u"/> - <rect id="fileMenuElement44r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement44t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement44r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement44r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement45"> - <use id="fileMenuElement45u"/> - <rect id="fileMenuElement45r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement45t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement45r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement45r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement46"> - <use id="fileMenuElement46u"/> - <rect id="fileMenuElement46r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement46t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement46r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement46r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement47"> - <use id="fileMenuElement47u"/> - <rect id="fileMenuElement47r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement47t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement47r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement47r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement48"> - <use id="fileMenuElement48u"/> - <rect id="fileMenuElement48r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement48t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement48r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement48r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - <g id="fileMenuElement49"> - <use id="fileMenuElement49u"/> - <rect id="fileMenuElement49r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> - <text id="fileMenuElement49t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> - <handler ev:event="mouseover">document.getElementById("fileMenuElement49r").setAttribute("fill", "black");</handler> - <handler ev:event="mouseout">document.getElementById("fileMenuElement49r").setAttribute("fill", "rgb(245,245,245)");</handler> - <handler ev:event="click">;</handler> - </g> - </defs> - <rect id="frame" width="320" height="600" rx="15" fill="black" stroke="black"/> - <!--text id="help" fill="rgb(90,90,120)" font-size="12" x="20" y="15">right click on home removes current widget</text--> - <g id="execbar" display="none"> - <g id="remoting" transform="translate(18, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Push</text> - <handler ev:event="click">on_widget_remote();</handler> - </g> - <g id="kill" transform="translate(55, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">KillW</text> - <handler ev:event="click">on_kill_widget();</handler> - </g> - <text id="widgetName" fill="white" font-family="Comic Sans MS" font-size="20" x="110" y="35">widgetName</text> - </g> - <g id="homebar" display="inline"> - <g id="adding" transform="translate(18, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Add</text> - <handler ev:event="click">on_widget_add_menu();</handler> - </g> - <g id="removing" transform="translate(55, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="10" x="2" y="12">Reset</text> - <handler ev:event="click">on_clean_up();</handler> - </g> - <g id="dirscan" transform="translate(92, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Scan</text> - <handler ev:event="click">on_dir_scan();</handler> - </g> - <g id="get" transform="translate(130, 22)"> - <rect rx="8" ry="8" fill="rgb(140,140,50)" width="36" height="16"/> - <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">GetW</text> - <handler ev:event="click">on_get_widget();</handler> - </g> - </g> - <rect id="screen" width="320" height="480" fill="white" stroke="black" x="0" y="60"/> - - <g id="homepage" transform="translate(0, 60)"> - <rect id="gridback" width="320" height="480" fill="rgb(40,40,40)" stroke="black"/> - <g id="grid"> - <use xlink:href="#odd" transform="translate(0, 0)"/> - <use xlink:href="#even" transform="translate(0, 80)"/> - </g> - <g id="icons" transform="translate(0,0)"> - </g> - </g> - - <g transform="translate(0,60)"> - <g id="widget"> - </g> - </g> - - <g transform="translate(0,60)"> - <g id="widgetAddList"/> - </g> - - - <g id="commands" transform="translate(0, 540)"> - <g id="homeButton" transform="translate(160,30)"> - <circle r="20" fill="rgb(40,40,40)" stroke="yellow"/> - <rect width="18" height="18" x="-9" y="-9" fill="none" stroke="yellow"/> - <handler ev:event="click">home_button(evt);</handler> - </g> - <g id="arrows"> - <g id="left" display="none" transform="translate(10, 10)"> - <animation xlink:href="icons/left_arrow.svg" width="40" height="40"/> - <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> - <handler ev:event="click">left_button();</handler> - </g> - <g id="right" display="none" transform="translate(270, 10)"> - <animation xlink:href="icons/right_arrow.svg" width="40" height="40"/> - <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> - <handler ev:event="click">right_button();</handler> - </g> - </g> - <g id="arrowsW"> - <g id="leftW" display="none" transform="translate(10, 10)"> - <animation xlink:href="icons/go-previous.svg" width="40" height="40"/> - <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> - <handler ev:event="click">left_buttonW();</handler> - </g> - <g id="rightW" display="none" transform="translate(270, 10)"> - <animation xlink:href="icons/go-next.svg" width="40" height="40"/> - <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> - <handler ev:event="click">right_buttonW();</handler> - </g> - </g> - </g> - <rect id="rightCut" width="1000" height="600" x="321" y="0" fill="white" stroke="none"/> - <rect id="leftCut" width="1000" height="600" x="-1001" y="0" fill="white" stroke="none"/> - <rect id="frame2" width="320" height="600" rx="15" fill="none" stroke="black"/> - <script xlink:href="mpegu-core.js"/> - <script xlink:href="iphone_wm_gui.js"/> - <handler ev:event="resize">resize();</handler> - <animateColor id="getAttention" attributeName="fill" xlink:href="#frame" begin="indefinite" dur="1" from="red" - to="black" restart="always" fill="freeze"/> -</svg>
View file
gpac-1.0.0.tar.gz/share/gui/mpegu-core.js
Deleted
@@ -1,1794 +0,0 @@ -//This software module was originally developed by Telecom Paris in the -//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard. -// -//This software module is an implementation of a part of one or -//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets -//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets -//(ISO/IEC 23007-1) free license to this software module or modifications -//thereof for use in hardware or software products claiming conformance to -//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software -//module in hardware or software products are advised that its use may -//infringe existing patents. -//The original developer of this software module and his/her company, the -//subsequent editors and their companies, and ISO/IEC have no liability -//for use of this software module or modifications thereof in an implementation. -//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming -//products. -//Telecom Paris retains full right to use the code for his/her own purpose, -//assign or donate the code to a third party and to inhibit third parties from -//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products. -// -//This copyright notice must be included in all copies or derivative works. -// -//Copyright (c) 2009. -// -///////////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////////////////// -// -// Authors: -// Jean Le Feuvre, Telecom Paris -// Jean-Claude Dufourd, Telecom Paris -// -///////////////////////////////////////////////////////////////////////////////// - -// 01122011 AMD1 startWidget listWidgets getWidget implemented - -/* - The widget manager in MPEG-U reference software is implemented in 2 parts: - - a native GPAC module called gm_widgetman implementing - * W3C widget loading (download, unzip, manifest parsing) - * W3C Widget APIs - * MPEG Widgets interfaces, messages and parameters listing - - - a script module (this file) implementing - * MPEG Widget interface binding with UPnP services (UPnP is implemented in another module) - * MPEG Widget interface binding with other local widgets - * MPEG Widget discovery through UPnP devices announcement. The discovery is done by setting the device presentationURL to the widget URL - - - A typical user of the widget manager will therefore see the following interfaces: - -interface WidgetManager { - readonly unsigned integer num_widgets; - string last_widget_dir; - - Widget open(string url, string source_ip); - void bind(Widget wid); - Widget get(unsigned int idx); - void unload(Widget wid); - void migrate_widget(upnp_renderer, widget); - void corein_message(widget, msg_name, arg1name, arg1val, ....); - - //callback functions for the GUI to be notifed of widgets added / removed when UPnP devices are appearing/disappearing - void on_widget_add(widget); - void on_widget_remove(widget); - - //callback functions for core:out - void coreOutSetSize(wid, args); - void coreOutShow(wid, args); - void coreOutHide(wid, args); - void coreOutRequestActivate(wid, args); - void coreOutRequestDeactivate(wid, args); - void coreOutShowNotification(wid, args); - void coreOutPlaceComponent(wid, args); - void coreOutGetAttention(wid, args); - - } - - -interface Widget { - //exported meta-data from MPEG-U Manifest - readonly string mainEncoding; - readonly string mainMimeType; - readonly integer defaultWidth; - readonly integer defaultHeight; - - readonly Array icons; - readonly Array features; - readonly Array preferences; - - - readonly string identifier; - readonly string name; - readonly string shortName; - readonly string authorName; - readonly string authorEmail; - readonly string authorHref; - readonly string description; - readonly string viewmodes; - readonly string licence; - readonly string licenceHref; - readonly string version; - readonly string uuid; - readonly boolean discardable; - readonly boolean multipleInstances; - - //widget-manager specific data - readonly string manifest; - readonly string main; - readonly string localizedSrc; - readonly Array components; //array of widget objects used as component - boolean permanent; - readonly boolean is_component; - readonly Widget parent; - readonly boolean activated; - readonly string section; - readonly integer num_section; - readonly integer num_interfaces; - readonly integer num_bound_interfaces; - readonly integer num_components; - - - device = local UPnP device created in order to publish interfaces of this widget as upnp services - originating_device = the device who sent the widget, either through migration or device discovery (presentationURL) - originating_device_ip = the IP of the device who sent the widget - - - - void activate(Element node_with_ref_to_main); - void deactivate(); - } - -interface Icon { - readonly string src; - readonly string relocated_src; - readonly integer width; - readonly integer height; -} - -interface Preference { - readonly string name; - readonly string value; - readonly boolean readonly; -} - -interface Features { - readonly string name; - readonly boolean required; - readonly Array params -} - -interface FeatureParam { - readonly string name; - readonly string value; -} - */ - -/*log function*/ -function log(lev, str) { - if (lev <= log_level) alert('[WM] ' + str); -} - -/*log levels*/ -l_err = 0; -l_war = 1; -l_inf = 2; -l_deb = 3; - -/*default log level*/ -log_level = l_deb; - -whiteSpaceRegExp = new RegExp(' ', 'g'); - -/*initializes the widget manager*/ -function widget_manager_init() { - log(l_inf, 'Initializing MPEG-U Widgets'); - /*if UPnP is enabled, override the deviceAdd callback*/ - WidgetManager.upnp = false; - WidgetManager.migrate_widget = wmjs_migrate_widget; - WidgetManager.probe = wmjs_probe_widget; - WidgetManager.open = wmjs_open_widget; - WidgetManager.bind = wmjs_bind_widget; - - WidgetManager.on_widget_add = wmjs_on_widget_add; - WidgetManager.on_widget_remove = wmjs_on_widget_remove; - - WidgetManager.check_bindings = wmjs_bind_widgets; - WidgetManager.unbind_widget = wmjs_unbind_widget; - WidgetManager.corein_message = wmjs_corein_message; - - WidgetManager.get_mpegu_service_providers = wmjs_get_mpegu_service_providers; - WidgetManager.initialize(); - - if (typeof(UPnP) != 'undefined') { - WidgetManager.upnp = true; - log(l_inf, 'Enabling Widget UPnP Discovery') - UPnP.onDeviceAdd = wmjs_on_device_add; - log(l_inf, 'Creating the standard MPEG-U Service') - wmjs_create_standard_service(); - } - log(l_inf, 'MPEG-U Widgets successfully initialized'); - initCore(); -} - -function wmjs_on_widget_add(widget) {} - -function wmjs_on_widget_remove(widget) {} - -function wmjs_probe_widget(url) { - if ((url.lastIndexOf('.wgt') >= 0) || (url.lastIndexOf('.mgt') >= 0) || (url.lastIndexOf('.xml') >= 0)) return 1; - return 0; -} - -function wmjs_bind_output_trigger(widget, msg, callback, udta) -{ - var res = widget.bind_output_trigger(msg, callback, udta); - if (!res) { - log(l_err, 'Cannot bind output trigger of message '+msg.name+' in widget '+widget.name); - } -} - -function wmjs_open_widget(url, src_ip, parent_widget) { - log(l_deb, "wmjs_open_widget"); - var wid; - if (arguments.length>=3) { - wid = WidgetManager.load(url, parent_widget); - } else { - wid = WidgetManager.load(url); - } - if (wid == null) { - log(l_err, 'File ' + url + ' is not a valid widget'); - return null; - } - wid.device = null; - wid.originating_device = null; - wid.originating_device_ip = null; - if (src_ip) { - wid.permanent = false; - wid.originating_device_ip = src_ip; - log(l_inf, 'Widget received - ip ' + wid.originating_device_ip); - } else { - wid.permanent = true; - wid.originating_device_ip = null; - } - return wid; -} - -/*performs an unbind check on all widgets*/ -function wmjs_unbind_widget(widget) { - var i, count, wid, ifce_count, j; - log(l_inf, 'wmjs_unbind_widget ' + widget.name); - - if (WidgetManager.upnp && widget.device) { - UPnP.DeleteDevice(widget.device); - widget.device = null; - } - - count = WidgetManager.num_widgets; - ifce_count = widget.num_interfaces; - for (i = 0; i < count; i++) { - wid = WidgetManager.get(i); - if (!wid) continue; - if (wid == widget) continue; - if (!wid.activated) continue; - - for (j = 0; j < ifce_count; j++) { - var an_ifce = widget.get_interface(j); - wid.unbind_interface(an_ifce, widget); - } - } - wmjs_bind_widgets(); -} - - -/*performs a bind check on all widgets*/ -function wmjs_bind_widgets() { - log(l_deb, 'wmjs_bind_widgets'); - var i, wid, count; - count = WidgetManager.num_widgets; - for (i = 0; i < count; i++) { - wid = WidgetManager.get(i); - if (!wid) continue; - if (!wid.activated) continue; - WidgetManager.bind(wid); - } -} - - -/*performs a bind on the given widget*/ -function wmjs_bind_widget(wid) { - var i, j, ifce_count, device, service, msg, do_bind; - - if (!wid.activated) { - log(l_inf, 'widget not activated - cannot bind'); - return; - } - ifce_count = wid.num_interfaces; - - log(l_inf, 'Binding widget ' + wid.name + ' - Nb Interfaces ' + ifce_count); - - /*browse all interfaces and locate services*/ - for (i = 0; i < ifce_count; i++) { - var ifce = wid.get_interface(i); - log(l_inf, 'Binding interface ' + ifce.type); - - /*look for a core:* service for this interface and setup*/ - if (wmjs_bind_interface_to_core_service(wid, ifce)) { - continue; - } - /*if our widget is already bound to this widget, skip it*/ - if (!ifce.multipleBinding && wid.is_interface_bound(ifce)) { - log(l_deb, 'Widget ' + wid.name + ' interface ' + ifce.type + ' already bound'); - continue; - } - /*if the widget is the provider of the service, create the service*/ - if (ifce.serviceProvider) { - log(l_inf, 'widget is a service provider'); - if (WidgetManager.upnp) wmjs_create_upnp_service(wid, ifce); - continue; - } - /*look for a UPnP service for this interface and setup*/ - if (WidgetManager.upnp && wmjs_bind_interface_to_upnp(wid, ifce)) { - continue; - } - /*look for a local service for this interface*/ - if (wmjs_bind_interface_to_local(wid, ifce)) { - continue; - } - /*no service found*/ - log(l_inf, 'Cannot find service for widget ' + wid.name + ' interface ' + ifce.type); - } -} - -/*called when a new UPnP device has been added or removed in the network*/ -function wmjs_on_device_add(device, is_add) { - log(l_deb, 'wmjs_on_device_add'); - if (!is_add) { - //TODO JCD: this is wrong, sometimes a device is not "is_add" but is not to be removed either - /*log(l_inf, 'Device Removed ' + device.Name); - wmjs_standard_service_remove(device); - wmjs_unbind_upnp_device(device); - if (device.widget != null) { - log(l_inf, 'Widget Removed ' + device.widget.name); - WidgetManager.on_widget_remove(device.widget); - device.widget.originating_device = null; - device.widget = null; - } - WidgetManager.check_bindings();*/ - return; - } - log(l_inf, 'Device Added ' + device.Name + ' URL ' + device.PresentationURL); - wmjs_standard_service_add(device); - WidgetManager.check_bindings(); - /*look for a presentation url - if not given or not identifying a widget, don't do anything*/ - var url = device.PresentationURL; - if (!url || (url == '')) return; - if (! WidgetManager.probe(url)) return; - /*OK load the widget*/ - var widget = WidgetManager.load(url); - widget.newBorn = true; - if (widget == null) { - log(l_err, 'File ' + url + ' is not a valid widget'); - return; - } - widget.originating_device = device; - device.widget = widget; - /*indicate our widget is not to be stored*/ - widget.permanent = false; - WidgetManager.on_widget_add(widget); -} - - -/* - LOCAL INTERFACE BINDING ROUTINES - - In this implementation, widgets-to-widget communication in the same widget manager are called "local" communications. - The implementation do not rely on any service description for that and directly matches the widgets interfaces - */ - -function wmjs_output_trigger_callback_local(msg_out, wid_src, msg_in, wid_dst) { - log(l_deb, "wmjs_output_trigger_callback_local"); - return function(value) { - log(l_deb, "wmjs_output_trigger_callback_local/function " + value + " '" + wid_src.name + "'" + wid_dst.name + "'"); - var param_count = msg_out.num_params; - var args = new Array(); - var is_script = 0; - var ai = 0, i; - if (msg_in.has_script_input) is_script = 1; - log(l_inf, 'Invoking Widget(' + wid_src.name + ').' + msg_out.name); - for (i = 0; i < param_count; i++) { - var param = msg_out.get_param(i); - if (param.is_input) continue; - - if (is_script) { - args[ai] = wid_src.get_param_value(param); - ai++; - } else { - wid_dst.set_input(msg_in.get_param(param.name), wid_src.get_param_value(param)); - } - } - log(l_inf, 'Calling Widget(' + wid_dst.name + ').' + msg_in.name); - - if (msg_in.has_input_action) { - wid_dst.call_input_action(msg_in); - } else if (is_script) { - wid_dst.call_input_script(msg_in, args); - } - }; -} - - -function wmjs_interface_invoke_callback_local(wid_dst, ifce_dst, is_reply) { - log(l_deb, "wmjs_interface_invoke_callback_local '" + wid_dst.name + "' '" + ifce_dst.type + "' - reply " + is_reply); - return function() { - log(l_deb, "wmjs_interface_invoke_callback_local/function '" + wid_dst.name + "' '" + ifce_dst.type + "' - reply " + is_reply); - var j, i, ai, param_count, msgHandler, msg_src, msg_dst, is_script; - var args = new Array(); - is_script = 0; - msgHandler = arguments[0]; - /*get msg from source interface (this object)*/ - msg_src = this.get_message(msgHandler.msgName); - // JCD: take into account message repetition, if any - for (j = 0; j < ifce_dst.num_messages; j++) { - msg_dst = ifce_dst.get_message(j); - if (msg_dst.name == msgHandler.msgName) { - log(l_deb, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on ' + wid_dst.name + '.' + msg_dst.name); - if (msg_dst.has_script_input) is_script = 1; - param_count = msg_src.num_params; - ai = 1; - for (i = 0; i < param_count; i++) { - var param = msg_dst.get_param(i); - if (! param.is_input) continue; - if (is_script) { - args[ai - 1] = arguments[ai]; - } else { - wid_dst.set_input(param, arguments[ai]); - } - ai++; - } - if (msg_dst.has_input_action) { - wid_dst.call_input_action(msg_dst); - } else if (is_script) { - wid_dst.call_input_script(msg_dst, args); - } - } - } - }; -} - -/* - END OF LOCAL INTERFACE BINDING ROUTINES - */ - - -function wmjs_bind_interface_to_local(wid, ifce) { - log(l_deb, "wmjs_bind_interface_to_local '" + wid.name + "' " + ifce.type); - var i, count, count2, j, a_ifce, a_msg, par, a_par, k, nb_ok, ret, set_bind, a_wid; - count = WidgetManager.num_widgets; - ret = false; - // this is the main loop to try to bind a widget to any other - for (i = 0; i < count; i++) { - a_wid = WidgetManager.get(i); - if (!a_wid) continue; - if (a_wid == wid) continue; - if (!a_wid.activated) continue; - count2 = a_wid.num_interfaces; - // now that we know this is a valid widget and not the same as wid - // loop on all its interfaces to find one of the right type - for (j = 0; j < count2; j++) { - a_ifce = a_wid.get_interface(j); - if (a_ifce.type == ifce.type) break; - } - if (j == count2) continue; - - /*if our widget is already bound to this widget (multiple binding==true) or to any widget (multiple binding==false), skip it*/ - if (wid.is_interface_bound(ifce, ifce.multipleBinding ? a_wid : null)) { - log(l_inf, 'Widget ' + wid.name + ' interface ' + ifce.type + ' is already bound'); - continue; - } - /*if our widget is already bound to this widget (multiple binding==true) or to any widget (multiple binding==false), skip it*/ - if (a_wid.is_interface_bound(a_ifce, a_ifce.multipleBinding ? wid : null)) { - log(l_inf, 'Widget ' + a_wid.name + ' interface ' + a_ifce.type + ' is already bound'); - continue; - } - - set_bind = 0; - // we have found an interface of the right type in the other widget - log(l_inf, 'Checking local widget ' + a_wid.name + ' for interface ' + ifce.type); - // loop on the messages to check if they match - for (j = 0; j < ifce.num_messages; j++) { - var msg = ifce.get_message(j), l; - //if (msg.is_input) continue; // JCD: remove test - // does the other interface have this message - // JCD: remove next line and take repetition of messages into account - // a_msg = a_ifce.get_message(msg.name); - for (l = 0; l < a_ifce.num_messages; l++) { - a_msg = a_ifce.get_message(l); - //alert(msg.name+" "+a_msg.name); - if (a_msg.name == msg.name) { - // the messages have matching names, check direction - if (msg.is_input == a_msg.is_input) { - log(l_inf, 'Local widget message for ' + msg.name + ' is not in direction ' + (msg.is_input ? 'output' : 'input')); - continue; - } - // the messages have matching names and directions, check params - if (msg.num_params != a_msg.num_params) { - log(l_war, 'Local widget message ' + msg.name + ' does not have the same number of parameters'); - continue; - } - /*check all params*/ - nb_ok = 0; - for (k = 0; k < msg.num_params; k++) { - par = msg.get_param(k); - a_par = a_msg.get_param(par.name); - if (a_par != null && par.is_input != a_par.is_input) nb_ok ++; - } - if (nb_ok != msg.num_params) { - log(l_war, 'Local widget message ' + msg.name + ' does not have the same input/output parameters'); - continue; - } - set_bind ++; - // the messages match - log(l_inf, 'Binding ' + wid.name + '.' + msg.name + ' to ' + a_wid.name + '.' + a_msg.name); - /*OK let's bind this action: we only need to assign the output trigger, the input action will be called from the other widget*/ - if (msg.has_output_trigger) { - wmjs_bind_output_trigger(wid, msg, wmjs_output_trigger_callback_local(msg, wid, a_msg, a_wid), a_wid); - } - /*OK let's bind this action: we only need to assign the output trigger, the input action will be called from the other widget*/ - if (a_msg.has_output_trigger) { - wmjs_bind_output_trigger(a_wid, a_msg, wmjs_output_trigger_callback_local(a_msg, a_wid, msg, wid), wid); - } - } - } - } - if (!set_bind) continue; - - /*create callback for programmatic action triggers*/ - ifce.invoke = wmjs_interface_invoke_callback_local(a_wid, a_ifce, 0); - ifce.invokeReply = wmjs_interface_invoke_callback_local(a_wid, a_ifce, 1); - /*create callback for programmatic action triggers*/ - a_ifce.invoke = wmjs_interface_invoke_callback_local(wid, ifce, 0); - a_ifce.invokeReply = wmjs_interface_invoke_callback_local(wid, ifce, 1); - a_wid.bind_interface(a_ifce, wid, 'localhost'); - wid.bind_interface(ifce, a_wid, 'localhost'); - ret = true; - } - return ret; -} - - -/* - INTERFACE BINDING TO UPNP SERVICES ROUTINES - - This implemntation supports binding interfaces to existing UPnP services - */ - -/*create a listener function for input parameters*/ -function wmjs_upnp_action_listener(widget, par, msg) { - log(l_deb, "wmjs_upnp_action_listener '" + widget.name + "' " + (par != null ? par.name : 'noPar') + " " + (msg != null ? msg.name : 'noMsg')); - return function(value) { - log(l_deb, "wmjs_upnp_action_listener/function '" + widget.name + "' " + (par != null ? par.name : 'noPar') + " " + - (msg != null ? msg.name : 'noMsg') + " " + value); - if (par != null) widget.set_input(par, value); - if (msg != null) widget.call_input_action(msg); - } -} - -/*create a listener function for input parameters*/ -function wmjs_upnp_action_listener_script(widget, msg) { - log(l_deb, 'wmjs_upnp_action_listener_script'); - return function() { - var i, count, act, par, rval, msgHandler, args; - act = arguments[0]; - log(l_deb, 'wmjs_upnp_action_listener_script/function:nb args ' + arguments.length); - msgHandler = arguments[1]; - log(l_deb, 'wmjs_upnp_action_listener_script/function:msgh ' + msgHandler); - args = new Array(); - count = msg.num_params; - for (i = 0; i < count; i++) { - par = msg.get_param(i); - if (!par.is_input) continue; - rval = act.GetArgumentValue(par.name); - if (par.script_type == 'number') { - args.push(parseInt(rval)); - } else if (par.script_type == 'boolean') { - args.push(rval == 'true'); - } else { - args.push(rval); - } - } - msgHandler.onInvokeReply(args); - } -} - - -/**/ -function wmjs_output_trigger_callback_upnp(service, widget, msg) { - log(l_deb, 'wmjs_output_trigger_callback_upnp'); - return function(value) { - log(l_deb, 'wmjs_output_trigger_callback_upnp/function ' + value); - var i, pi, param_count = msg.num_params; - var args = new Array(); - pi = 0; - for (i = 0; i < param_count; i++) { - var param = msg.get_param(i); - if (param.is_input) continue; - args[pi] = param.name; - args[pi + 1] = widget.get_param_value(param); - pi += 2; - } - log(l_inf, 'Calling UPnP Action ' + msg.name + " " + param_count); - service.CallAction(msg.name, args); - }; -} - - -/*create the action callback*/ -function wmjs_message_setup_upnp(widget, service, msg) { - log(l_deb, 'wmjs_message_setup_upnp ' + msg.name); - /*first let's browse all the message params*/ - var rad, i, param_count, has_script_input; - has_script_input = false; - param_count = msg.num_params; - for (i = 0; i < param_count; i++) { - var param = msg.get_param(i); - /*interface not valid for this service*/ - if (!service.HasAction(msg.name, param.name)) { - if (!param.is_input) { - log(l_war, 'Output param ' + param.name + ' not found in action - cannot bind action'); - return false; - } - continue; - } - /*this is a service -> widget param */ - if (param.is_input) { - if (msg.has_input_action) { - service.SetActionListener(msg.name, wmjs_upnp_action_listener(widget, param, null), param.name); - } else { - has_script_input = true; - // todo: pas vrai d'apres JCD - } - } - /*this is a widget -> service param , used in callback function*/ - } - /*assign the output trigger*/ - if (msg.has_output_trigger) { - var fun_name = 'call_' + msg.name; - widget[fun_name] = wmjs_output_trigger_callback_upnp(service, widget, msg); - wmjs_bind_output_trigger(widget, msg, widget[fun_name], service); - } - /*assign the input action*/ - if (msg.has_input_action) { - service.SetActionListener(msg.name, wmjs_upnp_action_listener(widget, null, msg)); - } else if (has_script_input) { - service.SetActionListener(msg.name, wmjs_upnp_action_listener_script(widget, msg), true); - } - return true; -} - - -function wmjs_interface_invoke_callback_upnp(service) { - log(l_deb, 'wmjs_interface_invoke_callback_upnp'); - return function() { - log(l_deb, 'wmjs_interface_invoke_callback_upnp/function'); - var args = new Array(); - var i, pi, ai, param_count, msg, ifce_msg; - - msg = arguments[0]; - ifce_msg = this.get_message(msg.msgName); - param_count = ifce_msg.num_params; - log(l_inf, 'UPnP invoke action ' + ifce_msg.name + ' - ' + msg.msgName); - - pi = 0; - ai = 1; - for (i = 0; i < param_count; i++) { - var param = ifce_msg.get_param(i); - if (param.is_input) continue; - - args[pi] = param.name; - args[pi + 1] = arguments[ai]; - pi += 2; - ai++; - } - service.CallAction(msg.msgName, args, msg); - }; -} - - -function wmjs_bind_interface_to_upnp(wid, ifce) { - log(l_deb, "wmjs_bind_interface_to_upnp"); - var do_bind, is_upnp = false; - var service = null; - - if (wid.originating_device) { - service = wid.originating_device.FindService(ifce.type); - } else if (wid.originating_device_ip) { - service = UPnP.FindService(wid.originating_device_ip, ifce.type); - } else { - var j, dev_count = UPnP.DevicesCount; - log(l_deb, 'wmjs_bind_interface_to_upnp nb ' + dev_count); - for (j = 0; j < dev_count; j++) { - device = UPnP.GetDevice(j); - log(l_deb, "wmjs_bind_interface_to_upnp " + device.Name + ' - type: ' + ifce.type); - /*do we have a UPnP service with the same interface type ?*/ - service = device.FindService(ifce.type); - - /*our widget is not bound to this service*/ - if (service) { - if (!wid.is_interface_bound(ifce, service)) break; - service = null; - is_upnp = true; - } - } - } - if (!service) return is_upnp; - - /*our widget is already bound to this service*/ - if (wid.is_interface_bound(ifce, service)) { - log(l_inf, 'Found UPnP Service for interface ' + ifce.type); - return true; - } - - log(l_inf, 'Found UPnP Service for interface ' + ifce.type); - do_bind = 0; - for (j = 0; j < ifce.num_messages; j++) { - var msg = ifce.get_message(j); - /*if we have a state variable in the service with the same name as the pin, bind it*/ - if (service.HasStateVariable(msg.name)) { - var param = msg.get_param(0); - if (param && (param.name == msg.name)) { - /*set listeners for declarative action triggers*/ - log(l_deb, 'Found UPnP state variable for message ' + msg.name); - service.SetStateVariableListener(wmjs_upnp_action_listener(wid, param, msg), param.name); - do_bind = 1; - } - } - /*if we have an action in the service with the same name as the pin, bind it*/ - else if (service.HasAction(msg.name)) { - /*set listeners for declarative action triggers*/ - log(l_deb, 'Found UPnP action for message ' + msg.name); - wmjs_message_setup_upnp(wid, service, msg); - do_bind = 1; - } - /*NOTE: UPnP actions are only messageOut, messageIn are UPnP events and don't have output paramaters. We therefore never need to setup - the invokeReply callback for interfaces matching UPnP services. !! This is not true for UPnP services created to publish an interface, eg serviceProvider="true".*/ - } - if (do_bind) { - /*create callback for programmatic action triggers*/ - log(l_inf, 'Binding widget ' + wid.name + ' interface ' + ifce.type + ' to host ' + service.Hostname); - ifce.invoke = wmjs_interface_invoke_callback_upnp(service); - /*bind interface*/ - wid.bind_interface(ifce, service, service.Hostname); - } - return true; -} - -function wmjs_unbind_upnp_device(device) -{ - var i, count, j, ifce_count; - count = WidgetManager.num_widgets; - - for (i = 0; i < count; i++) { - wid = WidgetManager.get(i); - if (!wid) continue; - if (!wid.activated) continue; - - ifce_count = wid.num_interfaces; - for (j = 0; j < ifce_count; j++) { - var ifce = wid.get_interface(j); - /*do we have a UPnP service with the same interface type ?*/ - var service = device.FindService(ifce.type); - if (!service) continue; - - /*unbind this interface*/ - if (wid.is_interface_bound(ifce, service)) { - wid.unbind_interface(ifce, service); - } - } - } -} - -/* - END OF INTERFACE BINDING TO UPNP SERVICES ROUTINES - */ - -// -// section on widget migration -// - -header = '<scpd xmlns="urn:schemas-upnp-org:service-1-0"><specVersion><major>1</major><minor>0</minor></specVersion><actionList>'; -middler = '</actionList><serviceStateTable>'; -footer = '</serviceStateTable></scpd>'; -standard_service_scpd = header+'<action><name>startWidget</name><argumentList><argument><name>widgetUrl</name><direction>in</direction><relatedStateVariable>s1</relatedStateVariable></argument><argument><name>widgetUUID</name><direction>in</direction><relatedStateVariable>s2</relatedStateVariable></argument><argument><name>widgetContext</name><direction>in</direction><relatedStateVariable>s3</relatedStateVariable></argument><argument><name>errorCode</name><direction>out</direction><relatedStateVariable>s4</relatedStateVariable></argument></argumentList></action>'; -{ - standard_service_scpd += '<action><name>requestCapabilitiesList</name><argumentList><argument><name>capabilitiesType</name><direction>out</direction><relatedStateVariable>s5</relatedStateVariable></argument><argument><name>capabilities</name><direction>out</direction><relatedStateVariable>s6</relatedStateVariable></argument></argumentList></action>'; - standard_service_scpd += '<action><name>listWidgets</name><argumentList><argument><name>widgetCodes</name><direction>out</direction><relatedStateVariable>s7</relatedStateVariable></argument><argument><name>widgetNames</name><direction>out</direction><relatedStateVariable>s8</relatedStateVariable></argument><argument><name>widgetIdentifiers</name><direction>out</direction><relatedStateVariable>s9</relatedStateVariable></argument></argumentList></action>'; - standard_service_scpd += '<action><name>getWidget</name><argumentList><argument><name>widgetCode</name><direction>in</direction><relatedStateVariable>s10</relatedStateVariable></argument><argument><name>errorCode</name><direction>out</direction><relatedStateVariable>s11</relatedStateVariable></argument>'; - standard_service_scpd += '<argument><name>widgetUrl</name><direction>out</direction><relatedStateVariable>s41</relatedStateVariable></argument><argument><name>widgetUUID</name><direction>out</direction><relatedStateVariable>s42</relatedStateVariable></argument><argument><name>widgetContext</name><direction>out</direction><relatedStateVariable>s43</relatedStateVariable></argument></argumentList></action>'; - standard_service_scpd += middler+'<stateVariable><name>s1</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s2</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s3</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s4</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s5</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s6</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s7</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s8</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s9</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s10</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s11</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s41</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s42</name><dataType>string</dataType></stateVariable>'; - standard_service_scpd += '<stateVariable><name>s43</name><dataType>string</dataType></stateVariable>'+footer; -} - -// -// migrate a widget by calling the appropriate startWidget message of the target -// migration service -// -function wmjs_migrate_widget(render, widget) { - if (WidgetManager.upnp) { - var url, ctx, uri; - - url = widget.url; - /*share the widget*/ - uri = UPnP.ShareResource(url, render.HostName); - - ctx = widget.get_context(); - - if (ctx == null) ctx = ""; - log(l_inf, 'Migrating widget ' + url + ' to renderer ' + render.Name + ' as resource ' + uri); - log(l_inf, 'Migration Context ' + ctx); - - // envoyer la methode startWidget sur render - var args = new Array(); - args.push("widgetUrl"); - args.push(uri); - args.push("widgetUUID"); - args.push(null); - args.push("widgetContext"); - args.push(ctx); - log(l_inf, "startWidget "+uri); - log(l_inf, "startWidgetCtx "+ctx); - alert("call StdServ "+render.Name+" "+render.standardService); - var code = render.standardService.CallAction("startWidget", args); - log(l_inf, "return code from standardService.CallAction is "+code); - } -} - -// -// check whether the removed device was a publisher of MPEGUStandardService -// if yes, remove it from the list -// -function wmjs_standard_service_remove(device) { - var service = device.FindService("urn:mpeg-u:service:widget-manager:1"); - if (service != null) { - var i = WidgetManager.MPEGUStandardServiceProviders.indexOf(device); - if (i >= 0) { - log(l_err, "migration service remove "+device.Name); - WidgetManager.MPEGUStandardServiceProviders.splice(i, 1); - } else log(l_err, "Trying to remove a standard service device which was not added first: "+device); - } -} - -// -// add a migration service provider to the list and remember the service in the device -// -function wmjs_standard_service_add(device) { - var service = device.FindService("urn:mpeg-u:service:widget-manager:1"); - if (service != null) { - log(l_err, "migration service add "+device.Name); - WidgetManager.MPEGUStandardServiceProviders.push(device); - device.standardService = service; - alert("add StdServ "+device.Name+" "+device.standardService); - } -} - -// -// get the nth standard service provider (migration service) -// -function wmjs_get_mpegu_service_providers(index) { - if (!WidgetManager.MPEGUStandardServiceProviders) { - log(l_err, "uninitialized MPEGUStandardServiceProviders"); - return null; - } - if (index < 0 || index > WidgetManager.MPEGUStandardServiceProviders.length) { - log(l_err, "index of MPEGUStandardServiceProviders out of bounds:"+index); - return null; - } - return WidgetManager.MPEGUStandardServiceProviders[index]; -} - -function wmjs_create_standard_service() { - //alert("create_standard_service"); - var name = "MPEG-U"; - var option = gpac.get_option('General', 'DeviceName'); - if (option) name = option; - WidgetManager.device = UPnP.CreateDevice("urn:mpeg-u:device:widget-manager:1", name+"@"+gpac.hostname); - WidgetManager.device.enabled = 1; - /* implement the response to a external call (messageOut of another widget) */ - WidgetManager.device.OnAction = wmjs_widget_standard_service_process_action; - log(l_err, 'wmjs_create_standard_service'); - //log(l_inf, 'Service scpd ' + standard_service_scpd); - /* WidgetManager.standardService = */ - var service = WidgetManager.device.SetupService("MPEG-U_Standard_Service", "urn:mpeg-u:service:widget-manager:1", - "urn:mpeg-u:serviceId:widget-manager:1.001", standard_service_scpd); - WidgetManager.device.Start(); - WidgetManager.MPEGUStandardServiceProviders = new Array(); - //alert("create_standard_service end"); -} - -/* generic processing of any action from outside for the standard MPEG-U service */ -function wmjs_widget_standard_service_process_action(action) { - log(l_err, 'wmjs_widget_standard_service_process_action Action ' + action.Name); - /* find the message matching the action in the interface */ - if (action.Name == "startWidget") { - process_startWidget_action(action); - } else if (action.Name == "requestCapabilitiesList"){ - process_requestCapabilitiesList_action(action); - } else if (action.Name == "listWidgets") { - process_listWidgets_action(action); - } else if (action.Name == "getWidget") { - process_getWidget_action(action); - } else { - log(l_inf, 'wmjs_widget_standard_service_process_action Action not found: ' + action.Name); - } -} - -// -// processing of a request to start a widget (push migration or predefined "activateWidgetByUrl") -// -function process_startWidget_action(action) { - log(l_err,"process start widget"); - // get action arguments - var widgetUrl = action.GetArgument("widgetUrl"); - var widgetUUID = action.GetArgument("widgetUUID"); - var widgetContext = action.GetArgument("widgetContext"); - log(l_err,"start:"+widgetUrl+" "+widgetUUID+" "+widgetContext); - // get widget - if (widgetUrl == null && widgetUUID != null) { - log(l_err, "unable to load a widget by UUID: unimplemented"); - action.SendReply(["errorCode", 1]); - return; - } - var wid = WidgetManager.load(widgetUrl, null, widgetContext); - WidgetManager.on_widget_add(wid); - action.SendReply(["errorCode", 0]); -} - -// -// processing of a request for the list of capabilities -// -function process_requestCapabilitiesList_action(action) { - //TODO - alert("UNIMPLEMENTED in mpegu-core.js: request capabilities list"); -} - -// -// processing of a request for the list of widgets (prelude to a pull migration) -// -function process_listWidgets_action(action) { - log(l_err,"process list widgets"); - // list widget - var count = WidgetManager.num_widgets, i, r1 = "", r2 = "", includeSpace = false; - for (i = 0; i < count; i++) { - var wid = WidgetManager.get(i); - if (wid.activated) { - if (includeSpace) { - r1 += " "; - } else { - includeSpace = true; - } - r1 += i+1; - r2 += wid.name.replace(whiteSpaceRegExp, '_')+" "; - } - } - alert("sendReply widgetCodes=|"+r1+"| widgetNames=|"+r2+"|"); - action.SendReply(["widgetCodes", r1, "widgetNames", r2]); -} - -// -// processing of a pull migration request -// -function process_getWidget_action(action) { - log(l_deb, "process get widget "+action+" "+action.Name); - // get action arguments - var widgetCode = action.GetArgument("widgetCode"); - log(l_deb, "get:"+widgetCode); - // get widget - var wid = WidgetManager.get(parseInt(widgetCode) - 1); - var url, ctx, uri; - url = wid.url; - /*share the widget*/ - uri = UPnP.ShareResource(url); - ctx = wid.get_context(); - if (ctx == null) ctx = ""; - log(l_inf, 'sendReply widget ' + url + ' as resource ' + uri); - log(l_inf, 'with context ' + ctx); - var args = new Array(); - args.push("errorCode"); - args.push(0); - args.push("widgetUrl"); - args.push(uri); - args.push("widgetUUID"); - args.push(null); - args.push("widgetContext"); - args.push(ctx); - action.SendReply(args); - WidgetManager.on_widget_remove(wid); -} - -// -// end of migration service -// - -/* - INTERFACE PUBLISHING AS UPNP SERVICES ROUTINES - - This implementation supports publishing a widget interface in the network as a UPnP service. This is done - by generating on the fly a new device associated with a widget, and one UPnP service per widget interface. - The UPnP service description (SCPD) is generated on the fly from the interface description - */ - -function wmjs_make_interface_scpd(widget, ifce) { - log(l_deb, "wmjs_make_interface_scpd"); - var variables = '', actions = '', vars, j, msg, k, param, numstatevar = 0; - /*do actions*/ - for (j = 0; j < ifce.num_messages; j++) { - msg = ifce.get_message(j); - actions += '<action><name>' + msg.name + '</name><argumentList>'; - for (k = 0; k < msg.num_params; k++) { - param = msg.get_param(k); - actions += '<argument><name>' + param.name + '</name><direction>' + (param.is_input ? 'in' : 'out'); - actions += '</direction><relatedStateVariable>v' + numstatevar + '</relatedStateVariable></argument>'; - numstatevar++; - } - actions += '</argumentList></action>'; - } - /*do variables*/ - for (k = 0; k < numstatevar; k++) { - variables += '<stateVariable><name>v' + k + '</name><dataType>string</dataType></stateVariable>'; - } - return header + actions + middler + variables + footer; -} - -/* generic processing of any action from outside */ -function wmjs_widget_upnp_process_action(action) { - log(l_err, 'wmjs_widget_upnp_process_action Action ' + action.Name + ' invoked on ' + action.Service.ifce.type); - var i, ai, args, msg, has_output = false; - /* find the message matching the action in the interface */ - msg = null; - for (i = 0; i < action.Service.ifce.num_messages; i++) { - msg = action.Service.ifce.get_message(i); - if (msg.name == action.Name) break; - msg = null; - } - if (msg == null) { - log(l_inf, 'wmjs_widget_upnp_process_action Action not found: ' + action.Name + ' invoked on ' + action.Service.name); - return; - } - args = new Array(); - ai = 0; - /*assign action for any async callback from the scene (cf wmjs_upnp_action_response)*/ - action.Service.action = action; - /* for each param in the found message */ - for (i = 0; i < msg.num_params; i++) { - var param = msg.get_param(i); - /* only process input params */ - if (!param.is_input) { - has_output = true; - continue; - } - if (msg.has_script_input) { - /* input param is scripted, store argument value in args array */ - args[ai] = action.GetArgument(param.name); - } else { - /* input param is not scripted but declarative, store argument value directly in scene tree */ - this.widget.set_input(param, action.GetArgument(param.name)); - } - ai++; - } - if (msg.has_input_action) { - /* message is not scripted, call input action */ - this.widget.call_input_action(msg); - } else if (msg.has_script_input) { - /* message is scripted, call the script function specified in inputAction */ - this.widget.call_input_script(msg, args); - } - if (!has_output) { - log(l_inf, 'wmjs_widget_upnp_process_action sending empty reply'); - action.SendReply(); - action.Service.action = null; - } -} - -function wmjs_upnp_event_sender(service, widget, msg) { - return function(value) { - log(l_deb, 'wmjs_upnp_event_sender/function ' + service.ifce.type + " " + widget.name + " " + msg.name); - var i, pi, param_count = msg.num_params; - var args = new Array(); - pi = 0; - for (i = 0; i < param_count; i++) { - var param = msg.get_param(i); - if (param.is_input) continue; - args[pi] = param.name; - args[pi + 1] = widget.get_param_value(param); - pi += 2; - } - log(l_inf, 'sending UPnP event ' + msg.name); - service.CallAction(msg.name, args); - }; -} - -function wmjs_upnp_action_response(service, widget, msg) { - return function(value) { - if (service.action == null) { - // TODO this code avoids the bug that this function is called twice: find out why it is called twice! - log(l_inf, 'wmjs_upnp_action_response/function DUPL(return) ' + service.ifce.type + " '" + widget.name + "' " + msg.name); - return; - } - var i, pi, param_count = msg.num_params; - var args = new Array(); - pi = 0; - for (i = 0; i < param_count; i++) { - var param = msg.get_param(i); - if (param.is_input) continue; - args[pi] = param.name; - args[pi + 1] = widget.get_param_value(param); - pi += 2; - } - log(l_inf, 'UPnP sending reply on action ' + service.action + ': ' + service.ifce.type + " '" + widget.name + "' " + msg.name); - service.action.SendReply(args); - service.action = null; - }; -} - - -function wmjs_upnp_action_response_script(service) { - return function() { - if (service.action == null) { - // this code avoids the bug that this function is called twice: find out why it is called twice! - return; - } - var i, pi, ai, param_count; - var args = new Array(); - var msgHandler = arguments[0]; - var msg = service.ifce.get_message(msgHandler.msgName); - - pi = 0; - ai = 1; - for (i = 0; i < param_count; i++) { - var param = msg.get_param(i); - if (param.is_input) continue; - args[pi] = param.name; - args[pi + 1] = arguments[ai]; - pi += 2; - ai++; - } - log(l_inf, 'UPnP sending reply on action ' + service.action); - service.action.SendReply(args); - service.action = null; - }; -} - - -function wmjs_create_upnp_service(widget, ifce) { - var i, service, scpd, start_device = 0; - var name; - - log(l_deb, 'widget device : ' + widget.device); - - /* at least one interface is a provider, so create a device - service or device names SHALL NOT CONTAIN SPACES*/ - name = widget.name.replace(whiteSpaceRegExp, '_'); - if (!widget.device) { - //log(l_inf,'creating device'); - widget.device = UPnP.CreateDevice("urn:mpeg-u:device:provider-" + name + ":1", name); - /* remember the widget in the device */ - widget.device.widget = widget; - widget.device.enabled = 1; - start_device = 1; - /* implement the response to a external call (messageOut of another widget) */ - widget.device.OnAction = wmjs_widget_upnp_process_action; - } - - /*service has already been created*/ - if (typeof(ifce.started) != 'undefined') return; - - log(l_inf, 'wmjs_create_upnp_service'); - scpd = wmjs_make_interface_scpd(widget, ifce); - //log(l_inf, 'Service scpd ' + scpd); - service = widget.device.SetupService(name, ifce.type, ifce.type + ".001", scpd); - service.ifce = ifce; - - /* for each message in a provider interface */ - for (i = 0; i < ifce.num_messages; i++) { - msg = ifce.get_message(i); - /* if there is an output_trigger, a reply may be triggered after a call */ - if (msg.has_output_trigger) { - if (msg.is_input) { - /* output in an input message => this is a reply */ - var fun_name1 = 'respond_' + msg.name; - widget[fun_name1] = wmjs_upnp_action_response(service, widget, msg); - wmjs_bind_output_trigger(widget, msg, widget[fun_name1], service); - } else { - /* output in an output message => this is an event */ - var fun_name2 = 'send_event_' + msg.name; - widget[fun_name2] = wmjs_upnp_event_sender(service, widget, msg); - wmjs_bind_output_trigger(widget, msg, widget[fun_name2], service); - } - } - /*if message is input, a reply may be sent*/ - else if (msg.is_input) { - var j, has_out; - has_out = 0; - for (j = 0; j < msg.num_params; j++) { - var param = msg.get_param(j); - if (param.is_input) continue; - has_out = 1; - break; - } - if (has_out) { - ifce.invokeReply = wmjs_upnp_action_response_script(service); - } - } - } - ifce.started = true; - - if (start_device) { - //log(l_inf,"device start"); - widget.device.Start(); - } -} - - -/* - END OF INTERFACE PUBLISHING AS UPNP SERVICES ROUTINES - */ - -/********************************************************* - Start of implementation of core:in and core:out interfaces - *********************************************************/ - -coreIn = null, coreOut = null; - -// -// function defining messages for the core:* interfaces implemented by the WM -// -function defineMessage(name, direction, executeFunction, params1, params2) { - var msg = new Object(); - msg.name = name; - msg.is_input = !direction; // the standard defines the point of view of the widget, not that of the WM - msg.num_params = 0; - // the executeFunction is the function implemented by widman.js and - // which passes the buck to a function of the widget manager, if there is one - if (executeFunction != null) msg.execute = executeFunction; - // in a messageOut, params1 contains outputs and params2 contains inputs - // in a messageIn, params1 contains inputs and params2 contains outputs - if (direction) { - if (params1 != null) { - msg.paramsOut = params1; - msg.num_params += params1.length; - } - if (params2 != null) { - msg.paramsIn = params2; - msg.num_params += params2.length; - } - } else { - if (params1 != null) { - msg.paramsIn = params1; - msg.num_params += params1.length; - } - if (params2 != null) { - msg.paramsOut = params2; - msg.num_params += params2.length; - } - } - //alert("Message defined: "+msg.name+' '+msg.num_params+' '+msg.is_input+' '+ - // (msg.paramsIn != null ? msg.paramsIn.length : 0)+' '+ - // (msg.paramsOut != null ? msg.paramsOut.length : 0)); - return msg; -} - -// -// function defining the parameter lists for messages -// the direction of a parameter is implicit in its position in the paramsIn or paramsOut of a message -// -function defineParams() { - var params = new Array(); - var i = 0; - for (; i < arguments.length; i++) { - params[i] = arguments[i]; - } - return params; -} - -// -// get message by name in a core interface (core:in or core:out -// -function getMessage(core, s) { - var i = 0; - for (; i < core.length; i++) { - if (core[i].name == s) return core[i]; - } - return null; -} - -// -// get a parameter from a message by name -// -function hasParam(msg, name) { - var i = 0; - if (msg.paramsIn) { - for (i = 0; i < msg.paramsIn.length; i++) { - if (msg.paramsIn[i] == name) return true; - } - } - if (msg.paramsOut) { - for (i = 0; i < msg.paramsOut.length; i++) { - if (msg.paramsOut[i] == name) return true; - } - } - return false; -} - -// -// get a parameter from a message by index -// -/*function getParam(msg, i) { - if (!msg.is_input) { - if (msg.paramsIn) { - if (i < msg.paramsIn.length) { - return msg.paramsIn[i]; - } else { - i -= msg.paramsIn.length; - } - } - if (msg.paramsOut) { - if (i < msg.paramsOut.length) { - return msg.paramsOut[i]; - } - } - } else { - if (msg.paramsOut) { - if (i < msg.paramsOut.length) { - return msg.paramsOut[i]; - } else { - i -= msg.paramsOut.length; - } - } - if (msg.paramsIn) { - if (i < msg.paramsIn.length) { - return msg.paramsIn[i]; - } - } - } - return null; -}*/ - -// -// get a parameter from a message by index -// -function getInputParam(msg, i) { - if (!msg.is_input) { - if (msg.paramsIn) { - if (i < msg.paramsIn.length) { - return msg.paramsIn[i]; - } else { - return null; - } - } - } else { - if (msg.paramsOut) { - if (i < msg.paramsOut.length) { - return null; - } else { - i -= msg.paramsOut.length; - } - } - if (msg.paramsIn) { - if (i < msg.paramsIn.length) { - return msg.paramsIn[i]; - } - } - } - return null; -} - -// -// reconstruct the direction of a parameter of a message by its position -// -function paramDirection(msg, name) { - var i = 0; - if (msg.paramsIn) { - for (i = 0; i < msg.paramsIn.length; i++) { - if (msg.paramsIn[i] == name) return true; - } - } - if (msg.paramsOut) { - for (i = 0; i < msg.paramsOut.length; i++) { - if (msg.paramsOut[i] == name) return false; - } - } - return false; -} - -function initCore() { - /* - Methods implementing messageIn of the core interfaces - In these methods, this is the message and args is the list of arguments of the message - widman.js, as the common part of all widget managers, does not implement these methods directly - but passes the buck to specific WM implementations. - In specific WM implementation, an initializer function should contain - WidgetManager.coreOutSetSize = function (...) {...}; - or similar. - */ - WidgetManager.coreOutSetSize = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.setSize" + argsString); - }; - - WidgetManager.coreOutShow = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.show" + argsString); - }; - - WidgetManager.coreOutHide = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.hide" + argsString); - }; - - WidgetManager.coreOutRequestActivate = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.requestActivate" + argsString); - }; - - WidgetManager.coreOutRequestDeactivate = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.requestDeactivate" + argsString); - }; - - WidgetManager.coreOutShowNotification = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.showNotification" + argsString); - }; - - WidgetManager.coreOutPlaceComponent = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.placeComponent" + argsString); - }; - - WidgetManager.coreOutGetAttention = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.getAttention" + argsString); - }; - WidgetManager.coreOutInstallWidget = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.installWidget" + argsString); - }; - WidgetManager.coreOutMigrateComponent = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.migrateComponent" + argsString); - }; - WidgetManager.coreOutRequestMigrationTargets = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.requestMigrationTargets" + argsString); - }; - WidgetManager.coreOutActivateTemporaryWidget = function(wid, args) { - var i = 0, argsString = ""; - for (; i < args.length; i++) argsString += " " + args[i]; - log(l_deb, "*** defCoreOutImpl.activateTemporaryWidget" + argsString); - }; - /* - Define the core:* interfaces that the widget manager implements and provides to widgets - The structure of messages is simplified. - messageIn have first an array of paramsIn, then an array of paramsOut for a reply - messageOut have first an array of paramsOut, then an array of paramsIn for reply - Because of this simplification, getParam and defineMessage are dependent on the direction of the message - The direction of a parameter is implicit in the fact that it is stored in paramsIn or paramsOut of the message - */ - coreIn = new Array(); - coreOut = new Array(); - coreIn[0] = defineMessage("setSize", true, null, defineParams("width", "height", "dpi")); - coreIn.setSizeMessage = coreIn[0]; - coreIn[1] = defineMessage("show", true, null); - coreIn.showMessage = coreIn[1]; - coreIn[2] = defineMessage("hide", true, null); - coreIn.hideMessage = coreIn[2]; - coreIn[3] = defineMessage("activate", true, null); - coreIn.activateMessage = coreIn[3]; - coreIn[4] = defineMessage("deactivate", true, null); - coreIn.deactivateMessage = coreIn[4]; - coreIn.type = "urn:mpeg:mpegu:schema:widgets:core:in:2010"; - coreOut[0] = defineMessage("setSize", false, coreOutSetSize, defineParams("width", "height")); - coreOut.setSizeMessage = coreOut[0]; - coreOut[1] = defineMessage("show", false, coreOutShow); - coreOut.showMessage = coreOut[1]; - coreOut[2] = defineMessage("hide", false, coreOutHide); - coreOut.hideMessage = coreOut[2]; - coreOut[3] = defineMessage("requestActivate", false, coreOutRequestActivate, null, - defineParams("returnCode")); - coreOut.requestActivateMessage = coreOut[3]; - coreOut[4] = defineMessage("requestDeactivate", false, coreOutRequestDeactivate, null, - defineParams("returnCode")); - coreOut.requestDeactivateMessage = coreOut[4]; - coreOut[5] = defineMessage("showNotification", false, coreOutShowNotification, - defineParams("message"), defineParams("returnCode")); - coreOut.showNotificationMessage = coreOut[5]; - coreOut[6] = defineMessage("placeComponent", false, coreOutPlaceComponent, - defineParams("componentID", "x", "y", "w", "h", "z-index", "transparency"), - defineParams("returnCode")); - coreOut.placeComponentMessage = coreOut[6]; - coreOut[7] = defineMessage("getAttention", false, coreOutGetAttention, - null, defineParams("returnCode")); - coreOut.getAttentionMessage = coreOut[7]; - coreOut[8] = defineMessage("installWidget", false, coreOutInstallWidget, - defineParams("url"), defineParams("returnCode")); - coreOut.installWidgetMessage = coreOut[8]; - coreOut[9] = defineMessage("migrateComponent", false, coreOutMigrateComponent, - defineParams("componentId", "targetCode"), defineParams("returnCode")); - coreOut.migrateComponentMessage = coreOut[9]; - coreOut[10] = defineMessage("requestMigrationTargets", false, coreOutRequestMigrationTargets, - null, defineParams("targetCodes", "targetNames", "targetDescriptions")); - coreOut.requestMigrationTargetsMessage = coreOut[10]; - coreOut[11] = defineMessage("activateTemporaryWidget", false, coreOutActivateTemporaryWidget, - defineParams("url"), defineParams("returnCode")); - coreOut.activateTemporaryWidget = coreOut[11]; - coreOut.type = "urn:mpeg:mpegu:schema:widgets:core:out:2010"; -} - -function coreOutRequestMigrationTargets(wid, args) { - WidgetManager.coreOutRequestMigrationTargets(wid, args); -} - -function coreOutSetSize(wid, args) { - WidgetManager.coreOutSetSize(wid, args); -} - -function coreOutShow(wid, args) { - WidgetManager.coreOutShow(wid, args); -} - -function coreOutHide(wid, args) { - WidgetManager.coreOutHide(wid, args); -} - -function coreOutRequestActivate(wid, args) { - WidgetManager.coreOutRequestActivate(wid, args); -} - -function coreOutRequestDeactivate(wid, args) { - WidgetManager.coreOutRequestDeactivate(wid, args); -} - -function coreOutShowNotification(wid, args) { - WidgetManager.coreOutShowNotification(wid, args); -} - -function coreOutPlaceComponent(wid, args) { - WidgetManager.coreOutPlaceComponent(wid, args); -} - -function coreOutGetAttention(wid, args) { - WidgetManager.coreOutGetAttention(wid, args); -} - -function coreOutInstallWidget(wid, args) { - WidgetManager.coreOutInstallWidget(wid, args); -} - -function coreOutActivateTemporaryWidget(wid, args) { - WidgetManager.coreOutActivateTemporaryWidget(wid, args); -} - -function coreOutMigrateComponent(wid, args) { - WidgetManager.coreOutMigrateComponent(wid, args); -} - -/* - Methods of binding and callback of core:* interfaces - */ -function wmjs_interface_invoke_callback_core(wid_src, ifce_dst, is_reply) { - log(l_inf, "wmjs_interface_invoke_callback_core '" + ifce_dst.type + "' - reply " + is_reply); - return function() { - var i, ai = 0, param_count, msgHandler, msg_src, msg_dst; - var args = new Array(); - msgHandler = arguments[0]; - /*get msg from source interface (this object)*/ - msg_src = this.get_message(msgHandler.msgName); - msg_dst = getMessage(ifce_dst, msgHandler.msgName); - //var argstring = ""; - //for (i = 0; i < msg_dst.num_params; i++) argstring += " "+getParam(msg_dst, i); - //log(l_inf, argstring); - //log(l_inf, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on core.' + msg_dst.name + " nbpar:"+msg_src.num_params); - param_count = msg_src.num_params; - for (i = 0; i < param_count; i++) { - var param = getInputParam(msg_dst, i); - if (param == null) continue; - args[ai] = arguments[ai+1]; - ai++; - } - log(l_inf, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on core.' + msg_dst.name + " nb:"+ai); - // call the method that implements the core:* message - msg_dst.execute(wid_src, args); - }; -} - -// function invokeReply for a reply from within a coreOut message -function wmjs_core_out_invoke_reply() { - var i, ai, param_count, is_script, msg_src, msg_dst, wid_dst; - var args = new Array(); - is_script = 0; - msg_src = arguments[0]; - msg_dst = arguments[1]; - wid_dst = arguments[2]; - log(l_inf, 'coreOut/invokeReply ' + msg_src.name + ' on core.' + msg_dst.name + ' to ' +wid_dst.name+ " nb:"+ai); - if (msg_dst.has_script_input) is_script = 1; - param_count = msg_src.num_params; - ai = 3; - for (i = 0; i < param_count; i++) { - var param = msg_dst.get_param(i); - if (! param.is_input) continue; - if (is_script) { - args[ai - 3] = arguments[ai]; - } else { - wid_dst.set_input(param, arguments[ai]); - } - ai++; - } - if (msg_dst.has_input_action) { - wid_dst.call_input_action(msg_dst); - } else if (is_script) { - wid_dst.call_input_script(msg_dst, args); - } -} - -// get an interface by type in WidgetManager, since getInterfaceHandlersByType is not accessible -function getInterfaceByType(widget, type) { - for (var i = 0; i < widget.num_interfaces; i++) { - var ifce = widget.get_interface(i); - if (ifce.type == type) return ifce; - } - return null; -} - -function wmjs_bind_interface_to_core_service(wid, ifce) { - if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:in:2010") { - // core:in - return wmjs_bind_interface_to_core_service1(wid, ifce, coreIn); - } else if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:out:2010") { - // core:out - return wmjs_bind_interface_to_core_service1(wid, ifce, coreOut); - } - // not an interface to core services - return false; -} - -function wmjs_bind_interface_to_core_service1(wid, ifce, core) { - // loop on the messages to check if they match - log(l_inf, 'Bind interface to core service ' + wid.name + " " + ifce.type); - var set_bind = 0, nb_ok, j, k, a_msg; - for (j = 0; j < ifce.num_messages; j++) { - var msg = ifce.get_message(j); - // does the other interface have this message - a_msg = getMessage(core, msg.name); - if (!a_msg) { - // no, it does not have this message, so leave - log(l_inf, 'No core message for ' + msg.name); - continue; - } - // the messages have matching names, check direction - if (msg.is_input == a_msg.is_input) { - log(l_inf, 'core message for ' + msg.name + ' is not in direction ' + (msg.is_input ? 'output' : 'input')); - continue; - } - // the messages have matching names and directions, check params - if (msg.num_params != a_msg.num_params) { - log(l_war, 'core message ' + msg.name + ' does not have the same number of parameters ' - + msg.num_params + ' ' + a_msg.num_params); - var paramstring = ""; - for (k = 0; k < msg.num_params; k++) { - par = msg.get_param(k); - paramstring += " " + par.name; - } - log(l_deb, paramstring); - continue; - } - /*check all params*/ - nb_ok = 0; - for (k = 0; k < msg.num_params; k++) { - par = msg.get_param(k); - //log(l_inf, " "+par.name+" "+hasParam(a_msg, par.name)+" "+par.is_input+" "+paramDirection(a_msg, par.name)); - if (hasParam(a_msg, par.name) != null && par.is_input != paramDirection(a_msg, par.name)) nb_ok ++; - } - if (nb_ok != msg.num_params) { - log(l_war, 'core message ' + msg.name + ' does not have the same input/output parameters '+nb_ok+" "+msg.num_params); - continue; - } - set_bind ++; - // the messages match - log(l_inf, 'Binding ' + wid.name + '.' + msg.name + ' to core.' + a_msg.name); - /*OK let's bind this action: we only need to assign the output trigger, the input - action will be called from the other widget*/ - if (msg.has_output_trigger) { - wmjs_bind_output_trigger(wid, msg, wmjs_output_trigger_callback_core(msg, wid, a_msg), WidgetManager); - } - } - if (!set_bind) return false; - /*create callback for programmatic action triggers*/ - ifce.invoke = wmjs_interface_invoke_callback_core(wid, core, 0); - // ifce.invokeReply = wmjs_interface_invoke_callback_core(wid, core, 1); - wid.bind_interface(ifce, null, 'localhost'); - return true; -} - -function wmjs_output_trigger_callback_core(msg_out, wid_src, msg_in) { - log(l_deb, "wmjs_output_trigger_callback_core"); - return function() { - log(l_deb, "wmjs_output_trigger_callback_core/function '" + wid_src.name + "'"); - var param_count = msg_out.num_params; - var args = new Array(); - var ai = 0, i; - log(l_inf, 'Invoking Widget(' + wid_src.name + ').' + msg_out.name); - for (i = 0; i < param_count; i++) { - var param = msg_out.get_param(i); - if (param.is_input) continue; - args[ai] = wid_src.get_param_value(param); - ai++; - } - msg_in.execute(wid_src, args); - }; -} - - -// -// send a core:in message with no parameter -// -function wmjs_corein_message() { - if (arguments.length < 2) return; - var widget = arguments[0]; - var message = arguments[1]; - - for (var i=0; i<widget.num_interfaces; i++) { - var ifce = widget.get_interface(i); - if (ifce.type != 'urn:mpeg:mpegu:schema:widgets:core:in:2010') continue; - - for (var j=0; j<ifce.num_messages; j++) { - var msg = ifce.get_message(j); - if (msg.name == message) { - if (msg.has_script_input) { - var jsargs = new Array(); - /*for each input descibed in the manifest, get the input script value and stack it in the argument list*/ - for (var k=0; k<msg.num_params; k++) { - par = msg.get_param(k); - if (!par.is_input) continue; - for (var l=2; l<arguments.length; l+=2) { - if (arguments[l]==par.name) { - jsargs.push(arguments[l+1]); - break; - } - } - } - widget.call_input_script(msg, jsargs); - } else if (msg.has_input_action) { - /*for each input descibed in the manifest, set the widget input value*/ - for (var k=0; k<msg.num_params; k++) { - par = msg.get_param(k); - if (!par.is_input) continue; - for (var l=2; l<arguments.length; l+=2) { - if (arguments[l]==par.name) { - widget.set_input(par, arguments[l+1]); - break; - } - } - } - widget.call_input_action(msg); - } - } - } - } -} - -/* - End of implementation of core:in and core:out interfaces - */
View file
gpac-1.0.0.tar.gz/share/gui/mpegu-wm.js
Deleted
@@ -1,1723 +0,0 @@ -//This software module was originally developed by Telecom Paris in the -//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard. -// -//This software module is an implementation of a part of one or -//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets -//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets -//(ISO/IEC 23007-1) free license to this software module or modifications -//thereof for use in hardware or software products claiming conformance to -//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software -//module in hardware or software products are advised that its use may -//infringe existing patents. -//The original developer of this software module and his/her company, the -//subsequent editors and their companies, and ISO/IEC have no liability -//for use of this software module or modifications thereof in an implementation. -//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming -//products. -//Telecom Paris retains full right to use the code for his/her own purpose, -//assign or donate the code to a third party and to inhibit third parties from -//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products. -// -//This copyright notice must be included in all copies or derivative works. -// -//Copyright (c) 2009. -// -///////////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////////////////// -// -// Authors: -// Jean Le Feuvre, (c) 2007-2010 Telecom Paris -// -///////////////////////////////////////////////////////////////////////////////// - -// 01122011 AMD1 startWidget implemented -// TODO AMD1 listWidgets getWidget requestCapabilitiesList - -//Initialize the main UI script -function initialize() { - //var icon; - var i, count, wid; - - gpac.caption = 'MPEG-U @ Osmo4'; - - display_width = parseInt(gpac.get_option('Widgets', 'LastWMWidth')); - display_height = parseInt(gpac.get_option('Widgets', 'LastWMHeight')); - - if (display_width && display_height) { - gpac.set_size(display_width, display_height); - } else { - display_width = gpac.get_screen_width(); - display_height = gpac.get_screen_height(); - } - - //request event listeners on the window - GPAC specific extensions !!! - root.addEventListener('resize', on_resize, 0); - root.addEventListener('zoom', on_zoom, 0); - root.addEventListener('scroll', on_scroll, 0); - - widget_default_size = 200; - scene_width = 0; - - wctl_iconsize = new SFVec2f(24, 24); - icon_size = 48; - dock_height = 48; - info_height = 32; - toggle_bar_height = 16; - screen_dpi = gpac.get_horizontal_dpi(); - - widget_remote_candidate = null; - has_upnp = eval("(typeof(UPnP) != 'undefined');"); - if (has_upnp) { - UPnP.onMediaRendererAdd = onMediaRendererAdd; - UPnP.onMediaConnect = onMediaConnect; - UPnP.BindRenderer(); - upnp_renders = null; - } - - /*setup dock*/ - widget_screen_visible = false; - - /*widget subtree*/ - widget_display = new SFNode('Transform2D'); - ui_root.children[0] = widget_display; - - /*widget manager page*/ - widget_screen = new SFNode('Layer2D'); - ui_root.children[1] = widget_screen; - - /*all other UI elements subtree*/ - dlg_display = new SFNode('Transform2D'); - ui_root.children[2] = dlg_display; - - infobar = text_label('', 'MIDDLE'); - ui_root.children[3] = infobar; - - /*our dock*/ - dock = new SFNode('Transform2D'); - ui_root.children[4] = dock; - - /*init the widget manager*/ - Browser.loadScript('mpegu-core.js', true); - log_level = l_inf; - widget_manager_init(); - - WidgetManager.on_widget_remove = widget_remove; - WidgetManager.on_widget_add = widget_insert; - WidgetManager.coreOutSetSize = widget_request_size; - WidgetManager.coreOutShow = widget_request_show; - WidgetManager.coreOutHide = widget_request_hide; - WidgetManager.coreOutRequestActivate = widget_request_activate; - WidgetManager.coreOutRequestDeactivate = widget_request_deactivate; - WidgetManager.coreOutShowNotification = widget_request_notification; - WidgetManager.coreOutPlaceComponent = widget_place_component; - WidgetManager.coreOutGetAttention = widget_request_attention; - WidgetManager.coreOutInstallWidget = widget_install_widget; - WidgetManager.coreOutMigrateComponent = widget_migrate_component; - WidgetManager.coreOutRequestMigrationTargets = widget_request_migration_targets; - - nb_widgets_on_screen = 0; - first_visible_widget = 0; - setup_icons(); - - /*restore our widgets*/ - widgets_init(); - - //let's do the layout - layout(); -} - -function new_timeout(time) -{ - var obj = new SFNode('TimeSensor'); - - obj.cycleInterval = time; - obj.start = function(when) { - var t = this.getTime(); - this.startTime = when + this.getTime(); - }; - obj.stop = function(when) { - this.stopTime = when + this.getTime(); - }; - obj.on_event = null; - obj.event = function(val) { - if (this.on_event) this.on_event(val); - }; - Browser.addRoute(obj, 'fraction_changed', obj, obj.event); - return obj; -} - -function rectangle() -{ - var obj = new SFNode('Shape'); - - obj.appearance = new SFNode('Appearance'); - obj.appearance.material = new SFNode('Material2D'); - obj.appearance.material.filled = TRUE; - obj.appearance.material.emissiveColor = new SFColor(0.7, 0.7, 0.8); - obj.appearance.material.lineProps = new SFNode('LineProperties'); - obj.appearance.material.lineProps.width = 2; - obj.appearance.material.lineProps.lineColor = new SFColor(0, 0, 0); - - obj.geometry = new SFNode('Curve2D'); - obj.geometry.point = new SFNode('Coordinate2D'); - temp = obj.geometry.type; - temp[0] = 7; - temp[1] = 1; - temp[2] = 7; - temp[3] = 1; - temp[4] = 7; - temp[5] = 1; - temp[6] = 7; - temp[7] = 6;/*close*/ - - obj.set_size = function(w, h) { - var hw, hh, rx, ry; - var temp; - hw = w/2; - hh = h/2; - - /*compute default rx/ry*/ - ry = rx = 10; - if ( (2*rx>=hw) || (2*ry>=hh)) rx = ry = 6; - - temp = this.geometry.point.point; - temp[0] = new SFVec2f(hw-rx, hh); - temp[1] = new SFVec2f(hw, hh);/*bezier ctrl point*/ - temp[2] = new SFVec2f(hw, hh-ry); - temp[3] = new SFVec2f(hw, -hh+ry); - temp[4] = new SFVec2f(hw, -hh);/*bezier control point*/ - temp[5] = new SFVec2f(hw-rx, -hh); - temp[6] = new SFVec2f(-hw+rx, -hh); - temp[7] = new SFVec2f(-hw, -hh);/*bezier control point*/ - temp[8] = new SFVec2f(-hw, -hh+ry); - temp[9] = new SFVec2f(-hw, hh-ry); - temp[10] = new SFVec2f(-hw, hh);/*bezier control point*/ - temp[11] = new SFVec2f(-hw+rx, hh); - }; - obj.set_color = function(r, g, b) { - this.appearance.material.emissiveColor.r = r; - this.appearance.material.emissiveColor.g = g; - this.appearance.material.emissiveColor.b = b; - }; - return obj; -} - -function icon_button(url, label, no_back) -{ - var obj = new SFNode('Transform2D'); - obj.children[0] = new SFNode('Transform2D'); - obj.children[0].scale.x = 0; - obj.children[0].children[0] = rectangle(); - - obj.children[1] = new SFNode('Layer2D'); - obj.children[1].size.x = icon_size; - obj.children[1].size.y = icon_size; - obj.children[1].children[0] = new SFNode('Inline'); - obj.children[1].children[0].url[0] = url; - - obj.touch = new SFNode('TouchSensor'); - obj.children[1].children[1] = obj.touch; - obj.button_click = NULL; - obj.down = false; - obj.over = false; - obj.on_active = function(value) { - if (value) { - this.down = true; - } else { - if (this.down && this.over && this.button_click) this.button_click(); - this.down = false; - } - }; - obj.button_over = on_icon_over; - obj.on_over = function(value) { - this.over = value; - if (!no_back) - this.children[0].scale.x = value ? 1 : 0; - if (this.button_over) this.button_over(value); - }; - Browser.addRoute(obj.touch, 'isOver', obj, obj.on_over); - Browser.addRoute(obj.touch, 'isActive', obj, obj.on_active); - obj.label = label; - obj.hide = function() { this.scale.x = this.scale.y = 0;}; - obj.show = function() { this.scale.x = this.scale.y = 1;}; - obj.set_size = function(x, y) { - this.children[0].children[0].set_size(x, y); - this.children[1].size.x = x; - this.children[1].size.y = y; - }; - return obj; -} - -function text_label(label, justify) -{ - var obj = new SFNode('Transform2D'); - obj.children[0] = new SFNode('Shape'); - obj.children[0].appearance = new SFNode('Appearance'); - obj.children[0].appearance.material = new SFNode('Material2D'); - obj.children[0].appearance.material.filled = TRUE; - obj.children[0].appearance.material.emissiveColor = new SFColor(0, 0, 0); - obj.children[0].geometry = new SFNode('Text'); - obj.children[0].geometry.string[0] = label; - obj.children[0].geometry.fontStyle = new SFNode('FontStyle'); - obj.children[0].geometry.fontStyle.justify[0] = justify; - obj.children[0].geometry.fontStyle.justify[1] = 'MIDDLE'; - obj.children[0].geometry.fontStyle.size = 20; - obj.set_label = function(value) { - this.children[0].geometry.string[0] = value; - }; - return obj; -} - - -function text_rect(label) -{ - var obj = new SFNode('Transform2D'); - obj.children[0] = rectangle(); - obj.children[0].set_color(0.7, 0.7, 0.8); - - obj.children[1] = new SFNode('Shape'); - obj.children[1].appearance = new SFNode('Appearance'); - obj.children[1].appearance.material = new SFNode('Material2D'); - obj.children[1].appearance.material.filled = TRUE; - obj.children[1].appearance.material.emissiveColor = new SFColor(0, 0, 0); - obj.children[1].geometry = new SFNode('Text'); - obj.children[1].geometry.string[0] = label; - obj.children[1].geometry.fontStyle = new SFNode('FontStyle'); - obj.children[1].geometry.fontStyle.justify[0] = 'MIDDLE'; - obj.children[1].geometry.fontStyle.justify[1] = 'MIDDLE'; - obj.children[1].geometry.fontStyle.size = 20; - obj.children[2] = new SFNode('TouchSensor'); - - obj.set_size = function(w, h) { - this.children[0].set_size(w, h); - }; - - - obj.over = false; - obj.on_over = function(value) { - this.children[0].set_color(0.7, value ? 0.5 : 0.7, 0.8); - this.over = value; - }; - Browser.addRoute(obj.children[2], 'isOver', obj, obj.on_over); - - obj.down = false; - obj.button_click = null; - obj.on_active = function(value) { - if (value) { - this.down = true; - } else { - if (this.down && this.over && this.button_click) this.button_click(); - this.down = false; - } - }; - Browser.addRoute(obj.children[2], 'isActive', obj, obj.on_active); - - return obj; -} - -function new_widget_control(widget) -{ - var obj = new SFNode('Transform2D'); - - obj.children[0] = new SFNode('Transform2D'); - - obj.children[0].children[0] = rectangle(); - - obj.children[0].children[1] = new SFNode('TouchSensor'); - - - obj.component_bound=false; - obj.show_ctrl = true; - obj.onClick = function(value) { - if (!value) return; - this.show_ctrl = !this.show_ctrl; - if (this.show_ctrl) { - var i, comps, idx; - this.children[0].children[0].appearance.material.transparency = 0; - this.children[1].scale.x = 1; - this.children[3].scale.x = 1; - - for (i=0; i<widget_display.children.length; i++) { - if (widget_display.children[i]==this) continue; - if (widget_display.children[i].show_ctrl) { - widget_display.children[i].onClick(true); - } - } - //widget is a component, do not push on top but hide some controls - if (widget.is_component) { - if (this.component_bound) { - this.children[1].children[0].hide(); //close - this.children[1].children[1].hide(); //remove - this.children[1].children[4].hide(); //resize - } - return; - } - //otherwise push widget on top - idx=0; - widget_display.removeChildren[idx++] = this; - widget_display.addChildren[idx++] = this; - //and push components - comps = widget.components; - for (i=0; i<comps.length; i++) { - if (comps[i].widget_control.component_bound) { - widget_display.removeChildren[idx++] = comps[i].widget_control; - widget_display.addChildren[idx++] = comps[i].widget_control; - } - } - - } else { - this.children[0].children[0].appearance.material.transparency = 1; - this.children[1].scale.x = 0; - this.children[3].scale.x = 0; - } - }; - Browser.addRoute(obj.children[0].children[1], 'isActive', obj, obj.onClick); - - obj.children[1] = new SFNode('Transform2D'); - obj.children[1].children[0] = icon_button('icons/process-stop.svg', 'Close', 0); - obj.children[1].children[0].button_click = function() { - if (widget.discardable) widget_remove(widget); - else widget_close(widget, 0); - }; - - obj.children[1].children[1] = icon_button('icons/user-trash.svg', 'Uninstall', 0); - obj.children[1].children[1].button_click = function() { widget_remove(widget); } - - obj.children[1].children[2] = icon_button('icons/applications-internet.svg', 'Push to remote display', 0); - obj.children[1].children[2].button_click = function() { - if (has_upnp && UPnP.MediaRenderersCount) { - widget_remote_candidate = widget; - on_upnpopen(); - } - }; - - obj.children[1].children[3] = icon_button('icons/dialog-information.svg', 'Widget Information', 0); - obj.children[1].children[3].button_click = function() { - display_widget_info(widget); - }; - - obj.children[1].children[4] = icon_button('icons/media-record.svg', 'Resize', 1); - obj.children[1].children[4].children[1].children[2] = new SFNode('PlaneSensor2D'); - obj.children[1].children[4].children[1].children[2].maxPosition = new SFVec2f(-1, -1); - - obj.prev_x=0; - obj.prev_y=0; - obj.onSize = function(value) { - if (widget.width + 2*(value.x - this.prev_x)<0) return; - if (widget.height + 2*(this.prev_y-value.y)<0) return; - - widget.width += 2*(value.x - this.prev_x); - this.prev_x = value.x; - widget.height += 2*(this.prev_y - value.y); - this.prev_y = value.y; - this.set_size(widget.width, widget.height); - }; - Browser.addRoute(obj.children[1].children[4].children[1].children[2], 'translation_changed', obj, obj.onSize); - - obj.children[2] = new SFNode('Layer2D'); - obj.inline = new SFNode('Inline'); - obj.children[2].children[0] = obj.inline; - - - obj.children[3] = new SFNode('Transform2D'); - obj.children[3].children[0] = new SFNode('Shape'); - obj.children[3].children[0].appearance = new SFNode('Appearance'); - obj.children[3].children[0].appearance.material = new SFNode('Material2D'); - obj.children[3].children[0].appearance.material.filled = TRUE; - obj.children[3].children[0].appearance.material.transparency = 0.5; - obj.children[3].children[0].appearance.material.emissiveColor = new SFColor(0.6, 0.6, 0.6); - obj.children[3].children[0].geometry = new SFNode('Rectangle'); - obj.children[3].children[0].geometry.size = new SFVec2f(50, 50); - obj.children[3].children[1] = new SFNode('PlaneSensor2D'); - obj.children[3].children[1].maxPosition = new SFVec2f(-1, -1); - obj.children[3].children[1].offset = new SFVec2f(widget.x, widget.y); - obj.onMove = function(value) { - if (this.maximized) return; - this.translation = value; - widget.x = value.x; - widget.y = value.y; - this.refresh_layout(false, null); - }; - Browser.addRoute(obj.children[3].children[1], 'translation_changed', obj, obj.onMove); - - obj.children[3].children[2] = new SFNode('TouchSensor'); - obj.last_ts = 0; - obj.onMaximize = function(value, timestamp) { - if (!value) return; - if (timestamp - this.last_ts < 0.5) { - if (this.maximized) { - this.maximized = false; - this.translation.x = widget.x; - this.translation.y = widget.y; - this.set_size(this.prev_width, this.prev_height); - } else { - this.maximized = true; - this.prev_width = widget.width; - this.prev_height = widget.height; - this.translation.x = 0; - this.translation.y = -info_height; - this.set_size(display_width, display_height - 2*info_height); - } - } - this.last_ts = timestamp; - }; - Browser.addRoute(obj.children[3].children[2], 'isActive', obj, obj.onMaximize); - - obj.set_size = function(w, h) { - var i, x, s; - s = 24; - this.children[2].size.x = w; - this.children[2].size.y = h; - - this.children[1].children[0].translation.y = this.children[1].children[1].translation.y = this.children[1].children[2].translation.y = this.children[1].children[3].translation.y = this.children[1].children[4].translation.y = h/2 + s/2; - - this.children[0].children[0].set_size(w+s, h+s); - this.children[3].children[0].geometry.size.x = w; - this.children[3].children[0].geometry.size.y = h; - - this.children[1].children[0].set_size(s, s); - this.children[1].children[1].set_size(s, s); - this.children[1].children[2].set_size(s, s); - this.children[1].children[3].set_size(s, s); - this.children[1].children[4].set_size(s, s); - this.children[1].children[0].translation.x = -w/2; - this.children[1].children[1].translation.x = -w/4; - this.children[1].children[2].translation.x = 0; - this.children[1].children[3].translation.x = w/4; - this.children[1].children[4].translation.x = w/2; - - //set widget input params - widget.width = w; - widget.height = h; - widget.set_input('width', w); - widget.set_input('height', h); - this.refresh_layout(true, null); - //call core:in - WidgetManager.corein_message(widget, 'setSize', 'width', w, 'height', w, 'dpi', screen_dpi); - }; - obj.refresh_layout = function(send_resize, comp_target) { - var i; - var x, y, w, h, scale_x, scale_y; - var comps; - - /*local to subscene transformation not known*/ - if (!this.sub_w) return; - if (!this.sub_h) return; - - comps = widget.components; - for (i=0; i<comps.length; i++) { - var comp = comps[i]; - if (!comp.widget_control.component_bound) continue; - - //compute scale from Widget Manager coord system to widget internal coordinate system - scale_x = this.sub_vp_w / this.sub_w; - scale_y = this.sub_vp_h / this.sub_h; - - w = comp.widget_control.place_w * scale_x; - h = comp.widget_control.place_h * scale_y; - - x = this.translation.x - widget.width/2 + this.sub_vp_x + comp.widget_control.place_x * scale_x + w/2; - comp.widget_control.translation.x = x; - - y = widget.height/2 + this.translation.y - h/2 - this.sub_vp_y - comp.widget_control.place_y * scale_y; - comp.widget_control.translation.y = y; - - if (send_resize || (comp_target==comp)) - comp.widget_control.set_size(w, h); - } - }; - - obj.hide = function() { - this.scale.x = 0; - WidgetManager.corein_message(widget, 'hide'); - }; - obj.show = function() { - this.scale.x = 1; - WidgetManager.corein_message(widget, 'show'); - }; - - obj.show_remote = function () { - if (WidgetManager.upnp && UPnP.MediaRenderersCount) { - this.children[1].children[2].show(); - } else { - this.children[1].children[2].hide(); - } - }; - obj.show_remove = function(show) { - if (show) this.children[1].children[1].show(); - else this.children[1].children[1].hide(); - }; - - obj.flash = function() { - var time = new_timeout(0.25); - time.loop = true; - time.ctrl = this; - time.on_event = function(val) { - var scale = (val<0.5) ? 1+val : 2-val; - this.ctrl.scale.x = this.ctrl.scale.y = scale; - }; - time.stop(1); - time.start(0); - }; - obj.maximized = false; - obj.show_remote(); - obj.onClick(true); - return obj; -} - - - -function on_icon_over(value) -{ - infobar.set_label(value ? this.label : ''); -} - -function display_widget_info(wid) -{ - var info_dlg = new SFNode('Transform2D'); - var i, j, k, info; - var y, txt, pref; - - infobar.set_label('Widget ' + wid.name + ' Information'); - - info = text_rect('Close'); - info_dlg.children[0] = info; - info.button_click = function() { - dlg_display.children.length = 0; - widget_display.scale.x = 1; - infobar.set_label(''); - layout(); - }; - - info = text_rect('Widget Metadata'); - info_dlg.children[info_dlg.children.length] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - info.children[i++] = text_label('id: ' + wid.identifier + ' - shortname: '+wid.shortName + ' - name: '+wid.name, 'BEGIN'); - info.children[i++] = text_label('version: '+wid.version, 'BEGIN'); - info.children[i++] = text_label('content type: ' + wid.mainMimeType + ' - content encoding: '+wid.mainEncoding, 'BEGIN'); - info.children[i++] = text_label('default size: Width = ' + wid.defaultWidth + ' Height = '+wid.defaultHeight, 'BEGIN'); - info.children[i++] = text_label('license: '+wid.license, 'BEGIN'); - info.children[i++] = text_label('license ref: '+wid.licenseHref, 'BEGIN'); - info.children[i++] = text_label('description: '+wid.description, 'BEGIN'); - info.children[i++] = text_label('author name: '+wid.authorName + ' (mail: '+wid.authorEmail+')', 'BEGIN'); - info.children[i++] = text_label('author href: '+wid.authorHref, 'BEGIN'); - info.children[i++] = text_label('view modes: '+wid.viewmodes, 'BEGIN'); - info.children[i++] = text_label('UUID: '+wid.uuid, 'BEGIN'); - info.children[i++] = text_label('Discardable: '+wid.discardable, 'BEGIN'); - info.children[i++] = text_label('Muliple Instances: '+wid.discardable, 'BEGIN'); - var icons = wid.icons; - for (j=0; j<icons.length; j++) { - info.children[i++] = text_label('icon #'+(j+1)+': ' + icons[j].src, 'BEGIN'); - } - - info = text_rect('Widget Manager Info'); - info_dlg.children[info_dlg.children.length] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - info.children[i++] = text_label('nb instances: '+wid.num_instances + ' nb components: '+wid.num_components, 'BEGIN' ); - info.children[i++] = text_label('Permanently installed: '+wid.permanent + ' - is component: '+wid.is_component, 'BEGIN' ); - if (wid.is_component) { - info.children[i++] = text_label('parent widget name' + wid.parent.name, 'BEGIN'); - } - if (wid.originating_device_ip) { - info.children[i++] = text_label('Widget was pushed from device IP '+wid.originating_device_ip, 'BEGIN' ); - } - info.children[i++] = text_label('Section name in GPAC config file: '+wid.section, 'BEGIN' ); - info.children[i++] = text_label('UA Locale: ' + gpac.get_option('core', 'lang'), 'BEGIN'); - info.children[i++] = text_label('widget src: ' + wid.url , 'BEGIN'); - info.children[i++] = text_label('config src: ' + wid.manifest , 'BEGIN'); - info.children[i++] = text_label('content src : '+wid.localizedSrc, 'BEGIN' ); - - pref = wid.features; - info = text_rect('Features (' + pref.length + ')' ); - info_dlg.children[info_dlg.children.length] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - for (j=0; j<pref.length; j++) { - info.children[i++] = text_label('Feature #'+(j+1)+' name=\''+pref[j].name+'\' required=\''+pref[j].required+'\'', 'BEGIN'); - } - - - pref = wid.preferences; - info = text_rect('Preferences ('+pref.length+')'); - info_dlg.children[info_dlg.children.length] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - for (j=0; j<pref.length; j++) { - var val = pref[j].value; - if (val == '') val = gpac.get_option(wid.section, pref[j].name); - info.children[i++] = text_label('Preference #'+(j+1)+' name=\''+pref[j].name+'\' value=\''+val+'\' readOnly=\''+pref[j].readonly +'\'', 'BEGIN'); - } - - info = text_rect('Migration Context', 'BEGIN'); - info_dlg.children[info_dlg.children.length] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - txt=wid.get_context(); - while (1) { - var idx = txt.indexOf('\n', 0); - if (idx>0) { - info.children[i++] = text_label(txt.substring(0, idx), 'BEGIN'); - txt = txt.substring(idx+1, txt.length); - } else { - info.children[i++] = text_label(txt, 'BEGIN'); - break; - } - } - - info_dlg.ifce_idx = info_dlg.children.length; - info = text_rect('Interfaces (count: ' + wid.num_interfaces + ' - bound: ' + wid.num_bound_interfaces+')', 'BEGIN'); - info_dlg.children[info_dlg.ifce_idx] = info; - info.visible = false; - info.button_click = function() { - this.visible = !this.visible; - layout(); - }; - i=3; - for (j=0; j<wid.num_interfaces; j++) { - var idx; - var ifce = wid.get_interface(j); - var item = text_rect('Interface #' + (j+1) + ' type: '+ifce.type); - info.children[i++] = item; - item.visible = false; - item.button_click = function() { - this.visible = !this.visible; - layout(); - }; - idx=3; - item.children[idx++] = text_label('Multiple Binding: '+ifce.multipleBinding + ' - Service provider: '+ ifce.serviceProvider + ' - bound: ' + wid.is_interface_bound(ifce) , 'BEGIN'); - for (k=0; k<ifce.num_messages; k++) { - var string, l; - var msg = ifce.get_message(k); - string = ' Message #'+ (k+1) + ': ' + msg.name + '('; - for (l=0; l<msg.num_params; l++) { - par = msg.get_param(l); - string += (par.is_input ? 'in' : 'out') + ':' +par.name + ' '; - } - string += ')'; - item.children[idx++] = text_label(string, 'BEGIN'); - } - } - - info_dlg.set_size = function(w, h) { - var i, j, y, dy; - y = h/2 - 20; - - for (i=0; i<this.children.length; i++) { - var item = this.children[i]; - item.translation.x = 0; - item.translation.y = y; - item.set_size(w, 20); - y -= 20; - if (!i) continue; - - dy = 0; - for (j=3; j<item.children.length; j++) { - if (item.visible) { - item.children[j].scale.x = 1; - dy -= 20; - item.children[j].translation.y = dy; - if (i<this.ifce_idx) { - item.children[j].translation.x = -w/2+10; - } else { - item.children[j].set_size(w-20, 20); - var ddy=0; - var k, sitem; - sitem = item.children[j]; - for (k=3; k<sitem.children.length; k++) { - if (item.children[j].visible) { - sitem.children[k].scale.x = 1; - sitem.children[k].translation.x = -w/2+10; - ddy -= 20; - sitem.children[k].translation.y = ddy; - } else { - sitem.children[k].scale.x = 0; - } - } - dy+=ddy; - } - } else { - item.children[j].scale.x = 0; - } - } - y += dy; - } - }; - - dlg_display.children[0] = info_dlg; - widget_display.scale.x = 0; - layout(); -} - - -function widget_insert(widget) -{ - /*insert the widget icon*/ - if (widget.permanent && !widget.is_component) - insert_widget_icon(widget, 0); - - /*and load the widget - comment this line to disable auto load of widget*/ - widget_launch(widget); -} - -function setup_icons() -{ - var icon; - - //Widgets Icon - icon = icon_button('icons/applications-system.svg', 'Available Widgets', 0); - icon.button_click = function () { - widget_screen_visible = !widget_screen_visible; - layout(); - }; - dock.children[0] = icon; - - //Get Widget Icon - icon = icon_button('icons/document-save.svg', 'Get Widget', 0); - icon.button_click = function () { - widget_get(); - }; - dock.children[1] = icon; - - //Widgets add Icon - icon = icon_button('icons/list-add.svg', 'Add Widgets', 0); - icon.button_click = function () { - widget_browse(); - }; - dock.children[2] = icon; - - - icon = icon_button('icons/user-trash.svg', 'Remove all widgets', 0); - icon.button_click = function () { - while (1) { - var wid = WidgetManager.get(0); - if (wid==null) break; - widget_close(wid, 1); - } - widget_screen.children.length = 0; - layout(); - }; - dock.children[3] = icon; - - //exit Icon - icon = icon_button('icons/emblem-unreadable.svg', 'Exit', 0); - icon.button_click = function() { gpac.exit(); }; - dock.children[4] = icon; -} - - - -/*dock layout*/ -function dock_layout() { - var i; - - dock.translation.y = (dock_height - display_height)/2; - infobar.translation.y = display_height/2 - info_height/2; - - num_in_dock = dock.children.length; - tot_len = num_in_dock*icon_size; - - if (tot_len>display_width) { - start_x = (icon_size-display_width)/2; - } else { - start_x = (icon_size-tot_len)/2; - } - /*translate / size all items in the dock*/ - for (i=0;i<num_in_dock; i++) { - dock.children[i].set_size(icon_size, icon_size); - dock.children[i].translation.x = start_x + i*icon_size; - } -} - -function widget_screen_layout(dir) -{ - var count, i, start_x, start_y, spread_x, nb_wid_h, nb_wid_v, nb_wid; - - if (!widget_screen_visible) { - widget_screen.size.x = 0; - widget_screen.size.y = 0; - return; - } - - widget_screen.size.x = display_width; - widget_screen.size.y = display_height; - - start_x = (icon_size/2-display_width)/2; - start_y = (display_height-icon_size/2)/2 - info_height; - start_x = (icon_size-display_width)/2; - start_y = (display_height-icon_size)/2 - icon_size/2 - info_height; - - count = widget_screen.children.length; - if (first_visible_widget<0) first_visible_widget=0; - - for (i=0; i<count; i++) { - var wid = widget_screen.children[i]; - wid.hide(); - } - - nb_wid_h = Math.floor(display_width / icon_size); - if (!nb_wid_h) nb_wid_h=1; - - nb_wid_v = Math.floor((display_height-dock_height-icon_size) / icon_size); - if (!nb_wid_v) nb_wid_v=1; - - spread_x = (display_width / nb_wid_h) - icon_size; - start_x += spread_x/2; - - nb_wid = (nb_wid_h*nb_wid_v); - if (dir<0) { - first_visible_widget -= nb_wid; - if (first_visible_widget < 0) first_visible_widget = 0; - } - else if (dir>0) { - first_visible_widget += nb_wid; - } - - for (i=0; i<count; i++) { - var wid; - if (i +first_visible_widget >= count) { - break; - } - wid = widget_screen.children[i +first_visible_widget]; - wid.show(); - wid.set_size(icon_size, icon_size); - wid.translation.x = start_x; - wid.translation.y = start_y; - start_x += icon_size + spread_x; - if (start_x + icon_size / 2 >= display_width/2) { - start_x = (icon_size-display_width)/2 + spread_x/2; - start_y -= icon_size; - } - nb_widgets_on_screen = i+1; - if (start_y - icon_size < (dock_height-display_height)/2) { - i++; - break; - } - } -} - -//performs layout on all contents -function layout() { - var i, list, start_x; - - gpac.set_option('Widgets', 'LastWMWidth', '' + display_width); - gpac.set_option('Widgets', 'LastWMHeight', '' + display_height); - - - if (WidgetManager.num_widgets) { - dock.children[0].show(); - } else { - dock.children[0].hide(); - } - if (dlg_display.children.length) { - widget_display.scale.x = 0; - widget_screen_visible = false; - } - //layout all icons in the dock - dock_layout(); - widget_screen_layout(0); - - if (dlg_display.children.length) { - list = dlg_display.children; - for (i=0; i<list.length; i++) { - var dlg = list[i]; - if (typeof (dlg.set_size) != 'undefined') dlg.set_size(display_width, display_height-icon_size-info_height); - dlg.translation.y = (icon_size-info_height)/2; - } - } - else if (widget_screen_visible) { - widget_display.scale.x = 0; - } else { - widget_display.scale.x = 1; - list = widget_display.children; - for (i=0; i<list.length; i++) { - var widctrl = list[i]; - if (widctrl.maximized) { - widctrl.translation.y = - info_height; - widctrl.set_size(display_width, display_height - 2*info_height); - } - } - } -} - -//resize event callback -function on_resize(evt) { - display_width = evt.width; - display_height = evt.height; - layout(); -} -//zoom event callback -function on_zoom(evt) { - display_width = evt.width; - display_height = evt.height; - layout(); -} -//scroll event callback -function on_scroll(evt) { - layout(); -} - -//starts a widget -function on_widget_launch() { - if (this.widget.visible) { - var awid; - if (!this.widget.multipleInstances) return; - awid = WidgetManager.open(this.widget.manifest, null); - widget_launch(awid); - } else { - widget_launch(this.widget); - } -} - -function widget_get_icon(widget) -{ - var icon = 'icons/process-stop.svg'; - var preferredIconType = '.svg'; - for (var i = 0; i < widget.icons.length; i++) { - icon = widget.icons[i].relocated_src; - if (widget.icons[i].relocated_src.indexOf(preferredIconType) > 0) { - break; - } - } - return icon; -} - -//initialize GPAC widget manager and load all widgets -function widgets_init() { - - count = WidgetManager.num_widgets; - for (i=0; i<count; i++) { - wid = WidgetManager.get(i); - if (wid == null) continue; - wid.device = null; - wid.device_ip = null; - if (wid.in_panel == true) { - icon = icon_button(widget_get_icon(wid), wid.name, 0); - icon.tooltip = wid.name; - icon.widget = wid; - icon.button_click = on_widget_launch; - - wid.icon_dock = icon; - widget_screen.children[widget_screen.children.length] = wid.icon_dock; - } - if (wid.visible) { - widget_launch(wid); - } - } -} - -function on_widget_size(value) { - //remember variables - this.width = value.x; - this.height = value.y; - //and set widget input params - this.set_input('width', value.x); - this.set_input('height', value.y); -} - -function on_widget_move(value) { - this.x = value.x; - this.y = value.y; -} - -//widget close function -function widget_close(widget, force_remove) -{ - var is_comp = widget.is_component; - if (widget.visible) { - widget.visible = false; - WidgetManager.corein_message(widget, 'hide'); - WidgetManager.corein_message(widget, 'deactivate'); - widget.deactivate(); - widget.scene_container.removeChildren[0] = widget.widget_control; - /*force disconnect of main resource - we do this because we are not sure when the widget_control will be destroyed due to JS GC*/ - widget.widget_control.inline.url.length = 0; - } - if (!is_comp && (!widget.permanent || force_remove)) { - WidgetManager.unload(widget, false); - } -} - -function on_widget_close(value) { - widget_close(this, 0); -} - -//widget remove function (close and unregister) -function widget_remove(wid) { - if (typeof(wid.icon_dock) != 'undefined') - widget_screen.removeChildren[0] = wid.icon_dock; - widget_close(wid, 0); - layout(); -} - -function on_widget_control(value) -{ - var i, count; - if (!value) return; - count = this.scene_container.children.length; - for (i=0; i<count; i++) { - if (this.scene_container.children[i] == this.widget_control) { - this.scene_container.removeChildren[0] = this.widget_control; - this.scene_container.children[this.scene_container.children.length] = this.widget_control; - return; - } - } -} - -//widget launcher function -function widget_launch(wid) { - var widg_ctrl; - - //assign default size to the widget - if (wid.width == undefined) { - wid.width = wid.defaultWidth; - if (wid.width == 0) wid.width = widget_default_size; - } - if (wid.height == undefined) { - wid.height = wid.defaultHeight; - if (wid.height == 0) wid.height = widget_default_size; - } - if (wid.x== undefined) wid.x = 0; - if (wid.y== undefined) wid.y = 0; - - widg_ctrl = new_widget_control(wid); - widg_ctrl.component_bound = false; - - wid.visible = true; - - widg_ctrl.set_size(wid.width, wid.height); - widg_ctrl.translation.x = wid.x; - widg_ctrl.translation.y = wid.y; - - wid.widget_control = widg_ctrl; - wid.scene_container = widget_display; - - widg_ctrl.show_remove( (!wid.discardable && wid.icon_dock) ? 1 : 0); - - widg_ctrl.sub_width = 0; - widg_ctrl.sub_height = 0; - widg_ctrl.sub_x = 0; - widg_ctrl.sub_y = 0; - widg_ctrl.sub_vp_w = 0; - widg_ctrl.sub_vp_h = 0; - - widg_ctrl.inline.addEventListener('gpac_vp_changed', - function(evt) { - widg_ctrl.sub_vp_w = evt.width; - widg_ctrl.sub_vp_h = evt.height; - widg_ctrl.sub_vp_x = evt.offset_x; - widg_ctrl.sub_vp_y = evt.offset_y; - widg_ctrl.sub_w = evt.vp_width; - widg_ctrl.sub_h = evt.vp_height; - widg_ctrl.refresh_layout(true, null); - }, - 0); - - /*this will setup the scene graph for the widget in order to filter input and output communication pins*/ - wid.activate(widg_ctrl.inline); - - widg_ctrl.inline.url[0] = wid.main; - widget_display.addChildren[0] = widg_ctrl; - - /*send notifications once the widget scene is loaded*/ - wid.on_load = function () { - WidgetManager.corein_message(this, 'activate'); - WidgetManager.corein_message(this, 'show'); - WidgetManager.corein_message(this, 'setSize', 'width', 50, 'height', 50, 'dpi', 96); - }; - - if (widget_screen_visible) { - widget_screen_visible = 0; - layout(); - } - // - if (log_level > l_inf) { - var i = 0; - alert(">>>>>>>>>>>>> "+wid.name+" interfaces:"); - for (;i < wid.num_interfaces; i++) { - alert(""+wid.get_interface(i).type); - } - } - // -} - - -//core out install widget implementation JCD -function widget_install_widget(widget, args) -{ - var uri = args[0], j; - var count = WidgetManager.num_widgets; - for (j=0; j<count; j++) { - var wid = WidgetManager.get(j); - if (wid.url==uri) break; - } - if (j==count) { - new_wid = WidgetManager.open(uri, null); - if (new_wid!=null) { - insert_widget_icon(new_wid, 1); - } - } -} - -//core out migrate component implementation JCD -function widget_migrate_component(widget, args) -{ - if (has_upnp && UPnP.MediaRenderersCount) { - widget_remote_candidate = widget.get_component(args[0]); - if (widget_remote_candidate==null) { - log(l_err, 'Component '+args[0]+' cannot be found in widget '+widget.name); - return; - } - if (args.length > 1 && args[1] != null) { - var render = WidgetManager.MPEGUStandardServiceProviders[parseInt(args[1])]; - WidgetManager.migrate_widget(render, widget_remote_candidate); - widget_close(widget_remote_candidate, 0); - widget_remote_candidate = null; - } else { - on_upnpopen(); - } - } -} - -// core out request migration targets JCD -function widget_request_migration_targets(wid, args) -{ - var count = WidgetManager.MPEGUStandardServiceProviders.length, - codes = new Array(), names = new Array(), descriptions = new Array(), i; - for (i = 0; i < count; i++) { - var render = WidgetManager.MPEGUStandardServiceProviders[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); - } - -} - -function widget_request_size(widget, args) -{ - if (args.length==2) { - w = (typeof args[0] == 'string') ? parseInt(args[0]) : args[0]; - h = (typeof args[1] == 'string') ? parseInt(args[1]) : args[1]; - widget.widget_control.set_size(w, h); - } -} - -function widget_request_show(widget, args) -{ - widget.widget_control.show(); -} - -function widget_request_hide(widget, args) -{ - widget.widget_control.hide(); -} - -function widget_request_activate(widget, args) -{ - if (!widget.visible) - widget_launch(widget); -} - -function widget_request_deactivate(widget, args) -{ - if (widget.visible) - widget_close(widget, 0); -} - -function widget_request_attention(widget, args) -{ - if (widget.visible) { - widget_display.removeChildren[0] = widget.widget_control; - widget_display.addChildren[0] = widget.widget_control; - widget.widget_control.flash(); - } -} - -function widget_request_notification(widget, args) -{ - var notif = text_rect(''); - notif.children[1].geometry.string[0] = 'Notification from widget'; - notif.children[1].geometry.string[1] = ' '+widget.name; - notif.children[1].geometry.string[2] = ' '; - notif.children[1].geometry.string[3] = args[0]; - dlg_display.children[0] = notif; - notif.set_size(320, 240); - notif.button_click = function() { - dlg_display.removeChildren[0] = this; - } -} - -function widget_place_component(widget, args) -{ - var comp = widget.get_component(args[0]); - - if (comp==null) { - log(l_err, 'Component '+args[0]+' cannot be found in widget '+widget.name); - return; - } - comp.widget_control.place_x = args[1]; - comp.widget_control.place_y = args[2]; - comp.widget_control.place_w = args[3]; - comp.widget_control.place_h = args[4]; - comp.widget_control.place_z = args[5]; - comp.widget_control.component_bound = true; - widget.widget_control.refresh_layout(false, comp); -} - - - -function insert_widget_icon(new_wid, no_layout) { - var icon; - icon = icon_button(widget_get_icon(new_wid), new_wid.name, 0); - icon.tooltip = new_wid.name; - new_wid.in_panel = true; - new_wid.visible = false; - new_wid.icon_dock = icon; - icon.button_click = on_widget_launch; - icon.widget = new_wid; - widget_screen.addChildren[0] = new_wid.icon_dock; - if (!no_layout) layout(); -} - -function scan_directory(dir) -{ - var i, j, count, list, new_wid, uri; - list = gpac.enum_directory(dir, '.xml;.wgt;.mgt', 0); - for (i=0; i<list.length; i++) { - uri = list[i].path + list[i].name; - if (list[i].directory) { - scan_directory(uri); - } else { - count = WidgetManager.num_widgets; - for (j=0; j<count; j++) { - var wid = WidgetManager.get(j); - if (wid.url==uri) break; - } - if (j==count) { - new_wid = WidgetManager.open(uri, null); - if (new_wid!=null) { - insert_widget_icon(new_wid, 1); - } - } - } - } -} - -function widget_browse() -{ - filebrowse = new SFNode('Transform2D'); - infobar.set_label('Select widget'); - dlg_display.children[0] = filebrowse; - - filebrowse.children[0] = icon_button('icons/emblem-unreadable.svg', 'Close', 0); - filebrowse.children[0].button_click = function() { - dlg_display.children.length = 0; - widget_display.scale.x = 1; - layout(); - } - - filebrowse.children[1] = icon_button('icons/go-previous.svg', 'Previous', 0); - filebrowse.children[1].filebrowse = filebrowse; - filebrowse.children[1].button_click = function () { this.filebrowse.layout(0) }; - - filebrowse.children[2] = icon_button('icons/go-next.svg', 'Next', 0); - filebrowse.children[2].filebrowse = filebrowse; - filebrowse.children[2].button_click = function () { this.filebrowse.layout(1) }; - - filebrowse.children[3] = icon_button('icons/go-up.svg', 'Up', 0); - filebrowse.children[3].filebrowse = filebrowse; - filebrowse.children[3].button_click = function () { this.filebrowse.browse(true) }; - - filebrowse.children[4] = icon_button('icons/Folder.svg', 'Scan Directory', 0); - filebrowse.children[4].filebrowse = filebrowse; - filebrowse.children[4].button_click = function () { - scan_directory(this.filebrowse.directory); - WidgetManager.last_widget_dir = this.filebrowse.directory; - dlg_display.children.length = 0; - widget_display.scale.x = 0; - widget_screen_visible = true; - layout(); - } - filebrowse.children[5] = text_label('', 'BEGIN'); - filebrowse.set_label = function(label) { - filebrowse.children[5].set_label(label); - } - filebrowse.nb_tools = filebrowse.children.length; - - filebrowse.browse = function(go_up) { - this.list = gpac.enum_directory(this.directory, '*.xml;*.wgt;*.mgt', go_up); - if (this.list.length) { - this.directory = this.list[0].path; - this.set_label(this.directory); - } else { - this.set_label(''); - } - this.first = 0; - this.layout(0); - } - filebrowse.layout = function(type) { - var w, h, i, y; - this.children.length = this.nb_tools; - - this.children[1].hide(); - this.children[2].hide(); - if (this.directory == '') - this.children[3].hide(); - else - this.children[3].show(); - - if (type==0) { - this.first -= this.nb_items; - if (this.first<0) this.first = 0; - } - else if (type) { - this.first += this.nb_items; - if (this.first + this.nb_items > this.list.length) this.first = this.list.length - this.nb_items; - } - if (this.first) this.children[1].show(); - if (this.first+this.nb_items < this.list.length) this.children[2].show(); - - for (i=0; i<this.nb_items; i++) { - var item; - if (i+this.first>=this.list.length) break; - item = text_rect(this.list[i+this.first].name); - item.path = this.list[i+this.first].path; - item.name = this.list[i+this.first].name; - item.directory = this.list[i+this.first].directory; - item.filebrowse = this; - item.button_click = function() { - if (this.directory) { - this.filebrowse.directory = this.path + this.name; - this.filebrowse.browse(false); - } else { - var value = this.path + this.name; - dlg_display.children.length = 0; - widget_display.scale.x = 1; - widget_screen_visible = true; - layout(); - - var new_wid = WidgetManager.open(value, null); - if (new_wid==null) return; - - WidgetManager.last_widget_dir = this.filebrowse.directory; - insert_widget_icon(new_wid, 0); - } - } - this.children[this.nb_tools+i] = item; - } - this.set_size(this.width, this.height); - } - - - filebrowse.set_size = function(w, h) { - var i, x, y, isize, nbi; - isize = 24; - if (w>display_width - isize) w = display_width - isize; - - this.width = w; - this.height = h; - - i = 1; - while ((i+1)*isize <= h - isize) i++; - - if (i != this.nb_items) { - this.nb_items = i; - this.layout(0); - return; - } - x = -w/2 + isize/2; - y = h/2 - isize/2; - - for (i=0;i<this.nb_tools;i++) { - if (this.nb_tools>i+1) { - this.children[i].set_size(isize, isize); - } - this.children[i].translation.x = x; - this.children[i].translation.y = y; - x += isize; - } - y-=isize; - while (i<this.children.length) { - this.children[i].set_size(w, isize); - this.children[i].translation.x = 0; - this.children[i].translation.y = y; - y-=isize; - i++; - } - } - filebrowse.nb_items = 0; - filebrowse.directory = WidgetManager.last_widget_dir; - filebrowse.browse(0); - - widget_display.scale.x = 0; - layout(); -} - -function onMediaRendererAdd(name, uuid, is_add) -{ - var i, count; - - count = WidgetManager.num_widgets; - for (i=0; i<count; i++) { - wid = WidgetManager.get(i); - if (wid == null) continue; - if (!wid.widget_control) continue; - wid.widget_control.show_remote(); - } - - if (upnp_renders) upnp_renders.refresh(); -} - -function on_upnpopen() -{ - upnp_renders = new SFNode('Transform2D'); - upnp_renders.nb_items = 0; - upnp_renders.refresh = function () { - var i, count, render, item, start_y, w; - this.children.length = 0; - count = WidgetManager.MPEGUStandardServiceProviders.length; - if (count+1>this.nb_items) count = this.nb_items-1; - - item = text_rect('Close'); - item.button_click = function() { - dlg_display.children.length = 0; - upnp_renders=null; - widget_display.scale.x = 1; - infobar.set_label(''); - } - this.children[this.children.length] = item; - - for (i=0; i<count; i++) { - render = WidgetManager.MPEGUStandardServiceProviders[i]; - item = text_rect(render.Name); - item.render = render; - - item.button_click = function() { - dlg_display.children.length = 0; - upnp_renders=null; - widget_display.scale.x = 1; - infobar.set_label(''); - - WidgetManager.migrate_widget(this.render, widget_remote_candidate); - widget_close(widget_remote_candidate, 0); - widget_remote_candidate = null; - } - this.children[this.children.length] = item; - } - this.set_size(this.width, this.height); - } - - upnp_renders.set_size = function (w, h) { - var i, count, start_y, w; - - this.width = w<300 ? w : 300; - this.height = h; - - i = 1; - while ((i+1)*icon_size <= h - icon_size) i++; - if (i != this.nb_items) { - this.nb_items = i; - this.refresh(); - return; - } - count = this.children.length; - start_y = this.height/2 - icon_size - 4; - for (i=0; i<count; i++) { - this.children[i].set_size(this.width, icon_size); - this.children[i].translation.y = start_y; - start_y-=icon_size+2; - } - } - - infobar.set_label('Select remote display'); - dlg_display.children[0] = upnp_renders; - widget_display.scale.x = 0; - layout(); -} - - -function onMediaConnect(url, src_ip) -{ - if (WidgetManager.probe(url)) { - var new_wid = WidgetManager.open(url, src_ip); - if (new_wid==null) { - return; - } - widget_insert(new_wid); - } -} - -// widget get: UI for listWidgets and getWidget -// added by Jean-Claude Dufourd, modeled on filebrowse -function widget_get() { - alert("widget_get"); - widgetbrowse = new SFNode('Transform2D'); - infobar.set_label('Select widget manager'); - dlg_display.children[0] = widgetbrowse; - - widgetbrowse.children[0] = icon_button('icons/emblem-unreadable.svg', 'Close', 0); - widgetbrowse.children[0].button_click = function() { - dlg_display.children.length = 0; - widget_display.scale.x = 1; - layout(); - }; - - widgetbrowse.children[1] = text_label('', 'BEGIN'); - widgetbrowse.set_label = function(label) { - widgetbrowse.children[1].set_label(label); - }; - - widgetbrowse.nb_tools = widgetbrowse.children.length; - - // this function builds the whole UI the first time - widgetbrowse.layout = function() { - alert("widgetbrowse.layout"); - var w, h, i, y; - this.children.length = this.nb_tools; - for (i = 0; i < this.nb_items; i++) { - var item; - if (i >= this.list.length) { - break; - } - item = text_rect(this.list[i].Name); - item.wm = this.list[i]; - item.widgetbrowse = this; - item.button_click = function() { - alert("click to select wm: "+this.wm.Name); - this.widgetbrowse.wm = this.wm; - this.wm.standardService.SetActionListener("listWidgets", get_widget_callback(this.wm, this.widgetbrowse), true); - this.wm.standardService.CallAction("listWidgets", new Array()); - }; - this.children[this.nb_tools + i] = item; - } - this.set_size(this.width, this.height); - }; - - widgetbrowse.set_size = function(w, h) { - alert("widgetbrowse.set_size "+w+" "+h); - var i, x, y, isize, nbi; - isize = 24; - if (w > display_width - isize) { - w = display_width - isize; - } - this.width = w; - this.height = h; - i = 1; - while ((i + 1) * isize <= h - isize) { - i++; - } - if (i != this.nb_items) { - this.nb_items = i; - this.layout(0); - return; - } - x = -w / 2 + isize / 2; - y = h / 2 - isize / 2; - for (i = 0; i < this.nb_tools; i++) { - if (this.nb_tools > i + 1) { - this.children[i].set_size(isize, isize); - } - this.children[i].translation.x = x; - this.children[i].translation.y = y; - x += isize; - } - y -= isize; - while (i < this.children.length) { - this.children[i].set_size(w, isize); - this.children[i].translation.x = 0; - this.children[i].translation.y = y; - y -= isize; - i++; - } - }; - - widgetbrowse.nb_items = WidgetManager.MPEGUStandardServiceProviders.length; - widgetbrowse.list = WidgetManager.MPEGUStandardServiceProviders; - widgetbrowse.set_label('Select Widget Manager'); - widgetbrowse.layout(0); - widget_display.scale.x = 0; - layout(); -} - -function get_widget_callback(device, widgetbrowse) { - alert("get_widget_callback "+device.Name+" "+widgetbrowse); - return function() { - // 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("callback |"+act1+"| |"+act2+"|"); - widgetbrowse.set_label("Select Widget"); - var w, h, i, y; - act1 = act1.split(" "); - act2 = act2.split(" "); - widgetbrowse.children.length = widgetbrowse.nb_tools; - for (i = 0; i < act2.length; i++) { - if (act1[i]=="" || act2[i]=="") continue; - var item = text_rect(act2[i]); - item.widgetCode = act1[i]; - item.widgetName = act2[i]; - item.widgetbrowse = widgetbrowse; - item.button_click = function() { - alert("selected widget: "+this.widgetName); - dlg_display.children.length = 0; - widget_display.scale.x = 1; - widget_screen_visible = true; - layout(); - var arr = new Array(); - arr[0] = "widgetCode"; - arr[1] = this.widgetCode; - this.widgetbrowse.wm.standardService.SetActionListener("getWidget", get_widget_callback2, true); - this.widgetbrowse.wm.standardService.CallAction("getWidget", arr); - }; - widgetbrowse.children[this.nb_tools + i] = item; - } - widgetbrowse.set_size(widgetbrowse.width, widgetbrowse.height); - } -} - -function get_widget_callback2() { - // msgHandler is the first argument, the next arguments are from the reply to listWidgets - alert("callback2-1"); - var act = arguments[0]; - var act1 = act.GetArgumentValue("widgetUrl"); - var act2 = act.GetArgumentValue("widgetContext"); - alert("callback2-2 " + act1 + " " + act2); - var wid = WidgetManager.load(act1, null, act2); - WidgetManager.on_widget_add(wid); -}
View file
gpac-1.0.0.tar.gz/share/gui/tv_wm_gui.js
Deleted
@@ -1,485 +0,0 @@ -var movie1 = "../widgets/media/local_video/movies/Clovis Cornillac.mp4"; -var movie2 = "../widgets/media/local_video/movies/Airheads2001_edit.mp4"; -var movie3 = "../widgets/media/local_video/movies/CH Video - Alberto Alessi.mp4"; -var movie4 = "../widgets/media/local_video/movies/Crossing2001_edit.mp4"; -var movie5 = "../widgets/media/local_video/movies/EnemyAtT2001_512kb.mp4"; -var movie6 = "../widgets/media/local_video/movies/KAMI2001_512kb.mp4"; -var movie7 = "../widgets/media/local_video/movies/PipeDrea2001_512kb.mp4"; -var movie8 = "../widgets/media/local_video/movies/LAUTRETE2001_512kb.mp4"; -var movie9 = "../widgets/media/local_video/movies/Unexpect2001_512kb.mp4"; -var movie0 = "../widgets/media/local_video/movies/Animatrix_The_Second_Renaissance_l.mp4"; - -var xlinkns = 'http://www.w3.org/1999/xlink'; - -/* override the print function to use SVG alert */ -print = alert; - -/******************************************************************************* - *Global elements referenced in this script - ******************************************************************************/ - -/* Root of the SVG document presenting the widgets, the dock ...*/ -var root; -/* The dock element presents the widget icons or simplified representations */ -var dock; -/* The movie element presents the media content, widgets are added on top of it */ -var movie; -/* The widget_display element contains the full representation of all activated widgets, it is on top of the movie element */ -var widget_display; -/* The display element contains things to be displayed on top of the widgets */ -var display; - - -function create_icon(url, short_name) { - var icon_g; - icon_g = document.createElement('g'); - icon_g.short_name = short_name; - - var back_rect; - back_rect = document.createElement('rect'); - back_rect.setAttribute('fill', 'url(#inactiveGradient)'); - back_rect.setAttribute('rx', 5); - back_rect.setAttribute('stroke', 'black'); - back_rect.setAttribute('stroke-width', 1); - icon_g.appendChild(back_rect); - - var icon; - icon = document.createElement('animation'); - icon.setAttributeNS(xlinkns ,'href', url); - icon_g.appendChild(icon); - - var text; - text = document.createElement('textArea'); - text.setAttribute('fill', 'white'); - text.textContent = short_name; - icon_g.appendChild(text); - - return icon_g; -} - -function set_icon_active(icon, value) { - var back_rect; - back_rect = icon.firstElementChild; - if (!value) back_rect.setAttribute('fill', 'url(#inactiveGradient)'); - else back_rect.setAttribute('fill', 'url(#activeGradient)'); -} - -function set_icon_visible(icon, value) { - if (value) icon.setAttribute('display', 'inline'); - else icon.setAttribute('display', 'none'); -} - -function set_icon_position(icon, x, y) { - icon.setAttribute('transform', 'translate('+x+','+y+')'); -} - -function set_icon_size(icon, w, h) { - var back_rect = icon.firstElementChild; - back_rect.setAttribute('width', w); - back_rect.setAttribute('height', h); - - var anim = back_rect.nextElementSibling; - anim.setAttribute('x', 5*w/8); - anim.setAttribute('y', -10); - anim.setAttribute('width', 1.2*h); - anim.setAttribute('height', 1.2*h); - - var tA = anim.nextElementSibling; - tA.setAttribute('x', icon_spacing); - tA.setAttribute('y', 5); - tA.setAttribute('height', h); - if (w > 100) { - tA.setAttribute('font-size', h/3); - tA.setAttribute('width', w/1.8); - } else { - tA.setAttribute('font-size', h/5); - tA.setAttribute('width', 4*w/8); - } -} - -function add_widget_to_dock(wid) { - var wid_icon_url = null; - var icon; - var preferredIconType = '.svg'; - for (var i = 0; i < wid.icons.length; i++) { - wid_icon_url = wid.icons[i].relocated_src; - if (wid.icons[i].relocated_src.indexOf(preferredIconType) > 0) { - break; - } - } - if (wid_icon_url == null) wid_icon_url = 'icons\\applications-system.svg'; - //alert(wid_icon_url); - icon = create_icon(wid_icon_url, wid.name); - icon.widget = wid; - set_icon_visible(icon, false); - dock.appendChild(icon); - wid.icon_dock = icon; -} - - -function resize() { - /*dummy values, assign upon window resize event*/ - alert('Size:'+root.viewport.width+'x'+root.viewport.height); - display_width = root.viewport.width;//gpac.get_screen_width(); - display_height = root.viewport.height;//gpac.get_screen_height(); - - nb_icon_max = 4; - if (display_width > 800) { - out_spacing = 30; - icon_spacing = 10; - } else { - out_spacing = 10; - icon_spacing = 4; - } - dock_width = display_width; - icon_width = (dock_width-((nb_icon_max-1)*icon_spacing+2*out_spacing))/nb_icon_max; - - dock_height = display_height/10; - icon_height = dock_height+4; - - movie.setAttribute('width', display_width); - if (is_dock_visible) { - movie.setAttribute('height', display_height - dock_height); - } else { - movie.setAttribute('height', display_height); - } - - dock.setAttribute('transform', 'translate(0, '+(display_height-dock_height)+')'); - - var dock_back = dock.firstElementChild.firstElementChild; - dock_back.setAttribute('x', 0); - dock_back.setAttribute('y', 0); - dock_back.setAttribute('height', dock_height); - dock_back.setAttribute('width', dock_width); - - var left_arrow = dock_back.nextElementSibling; - left_arrow.setAttribute('x', 0); - left_arrow.setAttribute('y', 0); - left_arrow.setAttribute('height', dock_height - 5); - left_arrow.setAttribute('width', out_spacing); - - var right_arrow = left_arrow.nextElementSibling; - right_arrow.setAttribute('x', dock_width-out_spacing); - right_arrow.setAttribute('y', 0); - right_arrow.setAttribute('height', dock_height-5); - right_arrow.setAttribute('width', out_spacing); - - dock_layout(); - alert('ok'); -} - -/******************************************************************************* - * Global Initialization function, called when the SVG document is loaded - * Initializes global variables (elements) - * Finds the available widgets and add them to the dock - ******************************************************************************/ -function initialize() { - /* root of the SVG document presenting the widgets, the dock ...*/ - root = document.documentElement; - - /* The dock presents the widget icons or simplified representations */ - dock = document.getElementById('dock'); - - /* The movie element presents the media content, widgets are added on top of it */ - movie = document.getElementById('movie'); - - /* The widget display element contains the full representation of all activated widgets, it is on top of the movie_inline element */ - widget_display = document.getElementById('widget_display'); - - /* The display element contains things to be displayed on top of the widgets */ - display = document.getElementById('display'); - - is_dock_visible = false; - if (!is_dock_visible) dock.setAttribute('display', 'none'); - - activate = new Array(); - selected_widget_index = 0; - first_displayed_widget_index = 0; - nb_widgets_visible = 0; - current_widget_pos = 0; - next_widget_pos = 0; - vertical_spacing = 10; - vertical_offset = 0; - - /* if the WidgetManager object is not defined (this is a GPAC extension), we define a dummy one to enable debugging in Opera for example */ - if (typeof WidgetManager == 'undefined') { - WidgetManager = new Object; - WidgetManager.initialize = function () {} - WidgetManager.num_widgets = 8; - WidgetManager.get = function(i) { - var wid = new Object; - if (i < 2) { - wid.icon = 'widgets/clock/appointment-new.svg'; - wid.main = 'widgets/clock/appointment-new.svg'; - wid.name = 'Clock'; - wid.visible = false; - wid.x = 0; - wid.y = 0; - wid.width = 100; - wid.height = 100; - } else { - wid.icon = 'icons/audio-volume-high.svg'; - wid.main = 'icons/audio-volume-high.svg'; - wid.name = 'Music'; - wid.visible = false; - wid.x = 0; - wid.y = 0; - wid.width = 100; - wid.height = 100; - } - return wid; - } - WidgetManager.unload = function (wid) {} - } - - /* Setup the GPAC Widget Manager - this will also scan the available widgets */ - widget_manager_init(); - - /* scan all the widgets from the widget manager, create an iconic view, set its size, add it to the dock element but make it invisible */ - var i; - nb_widgets = WidgetManager.num_widgets; - for (i=0; i<nb_widgets; i++) { - var wid = WidgetManager.get(i); - if (wid == null) continue; - add_widget_to_dock(wid); - activate[i] = true; - } - - //resize(); - - root.addEventListener('keyup', on_key_up, false); - - /* register the callback to be notified of incoming widgets */ - has_upnp = (typeof UPnP != 'undefined'); - alert('has upnp:'+ has_upnp); - if (has_upnp) { - /* setting the callback to allow other devices to push their widgets */ - UPnP.onMediaConnect = onMediaConnect; - UPnP.onMediaStop = onMediaStop; - UPnP.onMediaPause = onMediaPause; - UPnP.onMediaPlay = onMediaPlay; - /* Tell GPAC that the calls to the main Renderer (like open, ...) must be forwared to this scene */ - UPnP.BindRenderer(); - } - -} - -function dock_layout() { - - alert('dock layout first='+ first_displayed_widget_index+ '/' + nb_widgets+' active='+selected_widget_index); - var i; - var docFirstIcon = dock.firstElementChild.nextElementSibling; - /* for all icons before the first visible, make them invisible */ - var child = docFirstIcon; - i = 0; - while (child && i < first_displayed_widget_index) { - set_icon_visible(child, false); - alert('setting child '+i+' invisible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); - child = child.nextElementSibling; - i++; - } - - /* for all icons from the first visible, make them visible and set their position - and for all the icons after the max number of icons, make them invisible */ - i = first_displayed_widget_index; - var start_x = out_spacing; - while (child && i < nb_widgets) { - if (i >= (first_displayed_widget_index+nb_icon_max)) { - set_icon_visible(child, false); - alert('setting child '+i+' invisible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); - } else { - var offset_x = start_x + (i-first_displayed_widget_index)*(icon_width+icon_spacing); - set_icon_visible(child, true); - if (i == selected_widget_index) set_icon_active(child, true); - else set_icon_active(child, false); - set_icon_size(child, icon_width, icon_height); - set_icon_position(child, offset_x, dock_height-icon_height); -// alert('setting child '+i+' visible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); - } - child = child.nextElementSibling; - i++; - } -} - -function focusNextWidget() { - alert('next'); - if (selected_widget_index < nb_widgets - 1) selected_widget_index++; - if (selected_widget_index > first_displayed_widget_index + nb_icon_max -1 && first_displayed_widget_index + nb_icon_max < nb_widgets) first_displayed_widget_index++; - dock_layout(); -} - -function focusPrevWidget() { - alert('prev'); - if (selected_widget_index > 0) selected_widget_index--; - if (first_displayed_widget_index > selected_widget_index && first_displayed_widget_index > 0) first_displayed_widget_index--; - - dock_layout(); -} - -function on_key_up(evt) { - alert(evt.keyIdentifier + ' released '+evt.keyCode); - if (evt.keyIdentifier == 'Right' || evt.keyCode == 39) { - focusNextWidget(); - } else if (evt.keyIdentifier == 'Left' || evt.keyCode == 37) { - focusPrevWidget(); - } else if (evt.keyIdentifier == 'Up') { - vertical_offset += root.viewport.width / 3; - widget_display.setAttribute('transform', 'translate(0,'+vertical_offset+')'); - } else if (evt.keyIdentifier == 'Down') { - vertical_offset -= root.viewport.width / 3; - widget_display.setAttribute('transform', 'translate(0,'+vertical_offset+')'); - } else if (evt.keyIdentifier == 'Enter') { - if (is_dock_visible) { - if (activate[selected_widget_index]) { - widget_launch(WidgetManager.get(selected_widget_index), widget_display); - activate[selected_widget_index] = false; - nb_widgets_visible++; - if (nb_widgets_visible == 1) { - } - } else { - widget_close(WidgetManager.get(selected_widget_index)); - activate[selected_widget_index] = true; - nb_widgets_visible--; - if (nb_widgets_visible == 0) { - - } - } - } - } else if (evt.keyIdentifier == 'F1') { - dock_toggle_visible(); - } else if (evt.keyIdentifier == 'U+0030') { - movie.setAttributeNS(xlinkns, 'href', movie0); - } else if (evt.keyIdentifier == 'U+0031') { - movie.setAttributeNS(xlinkns, 'href', movie1); - } else if (evt.keyIdentifier == 'U+0032') { - movie.setAttributeNS(xlinkns, 'href', movie2); - } else if (evt.keyIdentifier == 'U+0033') { - movie.setAttributeNS(xlinkns, 'href', movie3); - } else if (evt.keyIdentifier == 'U+0034') { - movie.setAttributeNS(xlinkns, 'href', movie4); - } else if (evt.keyIdentifier == 'U+0035') { - movie.setAttributeNS(xlinkns, 'href', movie5); - } else if (evt.keyIdentifier == 'U+0036') { - movie.setAttributeNS(xlinkns, 'href', movie6); - } else if (evt.keyIdentifier == 'U+0037') { - movie.setAttributeNS(xlinkns, 'href', movie7); - } else if (evt.keyIdentifier == 'U+0038') { - movie.setAttributeNS(xlinkns, 'href', movie8); - } else if (evt.keyIdentifier == 'U+0039') { - movie.setAttributeNS(xlinkns, 'href', movie9); - } -} - -function widget_close(widget) { - alert('widget_close:'+widget.name); - if (typeof widget.deactivate != 'undefined') { - widget.deactivate(); - } else { - wid.visible = false; - } - next_widget_pos -= widget.height + vertical_spacing; - widget.scene_container.removeChild(widget.widget_control); - /*force disconnect of main resource - we do this because we are not sure when the widget_control will be destroyed due to JS GC*/ - widget.widget_control.firstElementChild.setAttributeNS(xlinkns, 'href', ''); - //widget.widget_control.firstElementChild.removeAttributeNS(xlinkns, 'href'); -} - -/* todo ...*/ -function widget_remove(wid) -{ - WidgetManager.unload(wid); -} - -/* Function that starts to present the Widget Full representation */ -function widget_launch(wid, scene_container) { - alert('widget_launch:'+wid.name); - - var widg_ctrl, anim; - - //assign default size to the widget - wid.width = root.viewport.width / 3; - wid.height = root.viewport.width / 3; - - var w = wid.width; - var h = wid.height; - alert('w '+w + ' h '+h); - - widg_ctrl = document.createElement('g'); - widg_ctrl.wid = wid; -// widg_ctrl.setAttribute('transform', 'translate('+(nb_widgets_visible>=2?600:0)+','+400*nb_widgets_visible+')'); -// var y = (nb_widgets_visible%2)*310; -// var x = ((nb_widgets_visible - nb_widgets_visible%2)/2*310); - var x = 0; - var y = next_widget_pos; - next_widget_pos += h+vertical_spacing; - - alert('x:'+x+', y:' +y); - widg_ctrl.setAttribute('transform', 'translate('+x+','+y+')'); - - anim = document.createElement('animation'); - anim.setAttributeNS(xlinkns, 'href', wid.main); - anim.setAttribute('width', w); - anim.setAttribute('height', h); - anim.setAttribute('preserveAspectRatio', 'xMidYMid'); - - widg_ctrl.appendChild(anim); - - wid.widget_control = widg_ctrl; - wid.scene_container = scene_container; - /*this will setup the scene graph for the widget in order to filter input and output communication pins*/ - wid.on_load = function() { - alert('wid.on_load:'+this.name); - WidgetManager.bind(this); - } - wid.activate(anim); - scene_container.appendChild(widg_ctrl); -} - -function dock_toggle_visible() { - if (is_dock_visible) { - dock.setAttribute('display', 'none'); - movie.setAttribute('height', display_height); - is_dock_visible = false; - } else { - dock.setAttribute('display', 'inline'); - is_dock_visible = true; - movie.setAttribute('height', display_height - dock_height); - } -} - - -function onMediaConnect(url, src_ip) -{ - alert('onMediaConnect :\"'+url+'\"'); - - if (WidgetManager.probe(url) ) { - var new_wid = WidgetManager.open(url, src_ip); - if (new_wid==null) return; - - add_widget_to_dock(new_wid); - for (var i = nb_widgets; i < WidgetManager.num_widgets; i++) { - activate[i] = true; - } - nb_widgets = WidgetManager.num_widgets; - dock_layout(); - } else { - alert('invalid widget extension'); - /* TODO if this is not a widget url, we should probably change the movie being played */ - } -} - -function onMediaStop() -{ - alert('Media Stop'); - movie.endElement(); -} -function onMediaPause() -{ - alert('Media pause'); - movie.pauseElement(); -} -function onMediaPlay() -{ - alert('Media Play'); - movie.resumeElement(); -}
View file
gpac-1.0.0.tar.gz/.gitignore -> gpac-1.0.1.tar.gz/.gitignore
Changed
@@ -60,12 +60,12 @@ *.so *.dylib *.dll -*.lai -*.la -*.a +*.lai +*.la +*.a *.lib -*.exe -*.out +*.exe +*.out *.app *.apk *.dmg @@ -76,7 +76,7 @@ .deps/ .dep -#GPAC specific +#GPAC specific config.h include/gpac/revision.h include/gpac/revision.h.new @@ -85,6 +85,7 @@ config.mak configure-stamp gpac.pc +share/gpac.desktop tests/external_media/ tests/results/ tests/hash_refs/
View file
gpac-1.0.0.tar.gz/Changelog -> gpac-1.0.1.tar.gz/Changelog
Changed
@@ -1,3 +1,16 @@ +10/09/2020: GPAC 1.0.1 +This release fixes build and installation issues in 1.0.0, as well as various bugs introduced during the migration to the filters architecture. + +It also adds several small features: +- better ttml import +- better support for MPEGH audio +- support fur DASH UTCTiming +- manifest generation from pre-fragmented DASH/HLS mp4 +- speed optimization in isobmf reading (normal and fragmented) +- improved JS API for the filter session +- core tools exposed as JS module (file io, bitstream, etc ...) +- android fixes + 16/06/2020: GPAC 1.0 - Complete rewrite of GPAC streaming core: * addition of a filter-based architecture, used by MP4Client and MP4Box.
View file
gpac-1.0.0.tar.gz/Makefile -> gpac-1.0.1.tar.gz/Makefile
Changed
@@ -79,7 +79,7 @@ @cd $(SRC_PATH)/share/doc/man && MP4Box -genman && MP4Client -genman && gpac -genman test_suite: - @cd $(SRC_PATH)/testsuite && ./make_tests.sh + @cd $(SRC_PATH)/testsuite && ./make_tests.sh -precommit -p=0 lcov_clean: lcov --directory . --zerocounters @@ -112,41 +112,38 @@ install: $(INSTALL) -d "$(DESTDIR)$(prefix)" - $(INSTALL) -d "$(DESTDIR)$(prefix)/$(libdir)" + + $(MAKE) install-lib + $(INSTALL) -d "$(DESTDIR)$(prefix)/bin" $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/gpac$(EXE_SUFFIX) "$(DESTDIR)$(prefix)/bin" -ifeq ($(DISABLE_ISOFF), no) +ifeq ($(DISABLE_ISOFF),no) if [ -f bin/gcc/MP4Box$(EXE_SUFFIX) ] ; then \ $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/MP4Box$(EXE_SUFFIX) "$(DESTDIR)$(prefix)/bin" ; \ fi endif -ifneq ($(MP4BOX_STATIC), yes) -ifeq ($(DISABLE_PLAYER), no) +ifneq ($(MP4BOX_STATIC),yes) +ifeq ($(DISABLE_PLAYER),no) if [ -f bin/gcc/MP4Client$(EXE_SUFFIX) ] ; then \ $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/MP4Client$(EXE_SUFFIX) "$(DESTDIR)$(prefix)/bin" ; \ fi endif endif - if [ -d $(DESTDIR)$(prefix)/$(libdir)/pkgconfig ] ; then \ - $(INSTALL) $(INSTFLAGS) -m 644 gpac.pc "$(DESTDIR)$(prefix)/$(libdir)/pkgconfig" ; \ - fi - $(INSTALL) -d "$(DESTDIR)$(moddir)" + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(lib_dir)/$(moddir)" ifneq ($(MP4BOX_STATIC),yes) - $(INSTALL) bin/gcc/gm_*$(DYN_LIB_SUFFIX) "$(DESTDIR)$(moddir)" || true - $(INSTALL) bin/gcc/gf_*$(DYN_LIB_SUFFIX) "$(DESTDIR)$(moddir)" || true - #rm -f $(DESTDIR)$(moddir)/libgpac$(DYN_LIB_SUFFIX) - #rm -f $(DESTDIR)$(moddir)/nposmozilla$(DYN_LIB_SUFFIX) + $(INSTALL) bin/gcc/gm_*$(DYN_LIB_SUFFIX) "$(DESTDIR)$(prefix)/$(lib_dir)/$(moddir)" || true + $(INSTALL) bin/gcc/gf_*$(DYN_LIB_SUFFIX) "$(DESTDIR)$(prefix)/$(lib_dir)/$(moddir)" || true ifeq ($(CONFIG_OPENHEVC),yes) - cp -a bin/gcc/libopenhevc* $(DESTDIR)$(prefix)/$(libdir)/ || true + cp -a bin/gcc/libopenhevc* $(DESTDIR)$(prefix)/$(lib_dir)/ || true endif - $(MAKE) installdylib + endif - $(INSTALL) -d "$(DESTDIR)$(mandir)" - $(INSTALL) -d "$(DESTDIR)$(mandir)/man1" - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/mp4box.1 $(DESTDIR)$(mandir)/man1/ - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/mp4client.1 $(DESTDIR)$(mandir)/man1/ - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/gpac.1 $(DESTDIR)$(mandir)/man1/ - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/gpac-filters.1 $(DESTDIR)$(mandir)/man1/ + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(man_dir)" + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(man_dir)/man1" + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/mp4box.1 $(DESTDIR)$(prefix)/$(man_dir)/man1/ + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/mp4client.1 $(DESTDIR)$(prefix)/$(man_dir)/man1/ + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/gpac.1 $(DESTDIR)$(prefix)/$(man_dir)/man1/ + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/doc/man/gpac-filters.1 $(DESTDIR)$(prefix)/$(man_dir)/man1/ $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac" $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac/res" $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac/gui" @@ -154,7 +151,6 @@ $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac/gui/extensions" $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac/shaders" $(INSTALL) -d "$(DESTDIR)$(prefix)/share/gpac/scripts" - $(INSTALL) -d "$(DESTDIR)$(prefix)/include" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/res/gpac.mp4 $(DESTDIR)$(prefix)/share/gpac/res/ $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/res/gpac_cfg_test.mp4 $(DESTDIR)$(prefix)/share/gpac/res/ $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/res/gpac.png $(DESTDIR)$(prefix)/share/gpac/res/ @@ -164,19 +160,13 @@ $(INSTALL) -d "$(DESTDIR)$(prefix)/share/pixmaps" $(INSTALL) -d "$(DESTDIR)$(prefix)/share/applications" -ifeq ($(IS_DEB_MAKE),undefined) - ln -sf $(DESTDIR)$(prefix)/share/gpac/res/gpac.png $(DESTDIR)/usr/share/pixmaps/gpac.png - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gpac.desktop "$(DESTDIR)/usr/share/applications/" -else - dh_link $(DESTDIR)$(prefix)/share/gpac/res/gpac.png $(DESTDIR)$(prefix)/share/pixmaps/gpac.png + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/res/gpac.png "$(DESTDIR)$(prefix)/share/pixmaps/" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gpac.desktop "$(DESTDIR)$(prefix)/share/applications/" endif -endif $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gui/gui.bt "$(DESTDIR)$(prefix)/share/gpac/gui/" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gui/gui.js "$(DESTDIR)$(prefix)/share/gpac/gui/" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gui/gwlib.js "$(DESTDIR)$(prefix)/share/gpac/gui/" - $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/gui/mpegu-core.js "$(DESTDIR)$(prefix)/share/gpac/gui/" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/scripts/webvtt-renderer.js "$(DESTDIR)$(prefix)/share/gpac/scripts/" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/share/scripts/ttml-renderer.js "$(DESTDIR)$(prefix)/share/gpac/scripts/" @@ -185,35 +175,33 @@ cp $(SRC_PATH)/share/gui/icons/* "$(DESTDIR)$(prefix)/share/gpac/gui/icons/" cp -R $(SRC_PATH)/share/gui/extensions/* "$(DESTDIR)$(prefix)/share/gpac/gui/extensions/" cp $(SRC_PATH)/share/shaders/* "$(DESTDIR)$(prefix)/share/gpac/shaders/" - cp -R $(SRC_PATH)/include/* "$(DESTDIR)$(prefix)/include/" else cp --no-preserve=mode,ownership,timestamp $(SRC_PATH)/share/gui/icons/* $(DESTDIR)$(prefix)/share/gpac/gui/icons/ cp -R --no-preserve=mode,ownership,timestamp $(SRC_PATH)/share/gui/extensions/* $(DESTDIR)$(prefix)/share/gpac/gui/extensions/ cp --no-preserve=mode,ownership,timestamp $(SRC_PATH)/share/shaders/* $(DESTDIR)$(prefix)/share/gpac/shaders/ - cp -R --no-preserve=mode,ownership,timestamp $(SRC_PATH)/include/* $(DESTDIR)$(prefix)/include/ endif lninstall: $(INSTALL) -d "$(DESTDIR)$(prefix)" - $(INSTALL) -d "$(DESTDIR)$(prefix)/$(libdir)" + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(lib_dir)" $(INSTALL) -d "$(DESTDIR)$(prefix)/bin" ln -sf $(BUILD_PATH)/bin/gcc/gpac$(EXE_SUFFIX) $(DESTDIR)$(prefix)/bin/gpac$(EXE_SUFFIX) -ifeq ($(DISABLE_ISOFF), no) +ifeq ($(DISABLE_ISOFF),no) ln -sf $(BUILD_PATH)/bin/gcc/MP4Box$(EXE_SUFFIX) $(DESTDIR)$(prefix)/bin/MP4Box$(EXE_SUFFIX) endif ifneq ($(MP4BOX_STATIC),yes) -ifeq ($(DISABLE_PLAYER), no) +ifeq ($(DISABLE_PLAYER),no) ln -sf $(BUILD_PATH)/bin/gcc/MP4Client$(EXE_SUFFIX) $(DESTDIR)$(prefix)/bin/MP4Client$(EXE_SUFFIX) endif endif ifeq ($(CONFIG_DARWIN),yes) - ln -s $(BUILD_PATH)/bin/gcc/libgpac$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) - ln -sf $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_MAJOR)$(DYN_LIB_SUFFIX) - ln -sf $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX) + ln -s $(BUILD_PATH)/bin/gcc/libgpac$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) + ln -sf $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_MAJOR)$(DYN_LIB_SUFFIX) + ln -sf $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX) else - ln -s $(BUILD_PATH)/bin/gcc/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) - ln -sf $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so.$(VERSION_MAJOR) - ln -sf $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so + ln -s $(BUILD_PATH)/bin/gcc/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) + ln -sf $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.so.$(VERSION_MAJOR) + ln -sf $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.so ln -s $(SRC_PATH)/share/ $(DESTDIR)$(prefix)/share/gpac ln -sf $(DESTDIR)$(prefix)/share/gpac/res/gpac.png $(DESTDIR)/usr/share/pixmaps/gpac.png @@ -227,71 +215,91 @@ uninstall: $(MAKE) -C applications uninstall - rm -rf $(DESTDIR)$(moddir) - rm -rf $(DESTDIR)$(prefix)/$(libdir)/libgpac* -ifeq ($(CONFIG_WIN32),yes) - rm -rf "$(DESTDIR)$(prefix)/bin/libgpac*" -endif - rm -rf $(DESTDIR)$(prefix)/$(libdir)/pkgconfig/gpac.pc + $(MAKE) uninstall-lib + rm -rf $(DESTDIR)$(prefix)/$(lib_dir)/$(moddir) rm -rf $(DESTDIR)$(prefix)/bin/MP4Box rm -rf $(DESTDIR)$(prefix)/bin/MP4Client - rm -rf $(DESTDIR)$(mandir)/man1/mp4box.1 - rm -rf $(DESTDIR)$(mandir)/man1/mp4client.1 - rm -rf $(DESTDIR)$(mandir)/man1/gpac.1 - rm -rf $(DESTDIR)$(mandir)/man1/gpac-filters.1 + rm -rf $(DESTDIR)$(prefix)/bin/gpac + rm -rf $(DESTDIR)$(prefix)/$(man_dir)/man1/mp4box.1 + rm -rf $(DESTDIR)$(prefix)/$(man_dir)/man1/mp4client.1 + rm -rf $(DESTDIR)$(prefix)/$(man_dir)/man1/gpac.1 + rm -rf $(DESTDIR)$(prefix)/$(man_dir)/man1/gpac-filters.1 rm -rf $(DESTDIR)$(prefix)/share/gpac - rm -rf $(DESTDIR)/usr/share/pixmaps/gpac.png - rm -rf $(DESTDIR)/usr/share/applications/gpac.desktop - rm -rf $(DESTDIR)$(prefix)/include/gpac + rm -rf $(DESTDIR)$(prefix)/share/pixmaps/gpac.png + rm -rf $(DESTDIR)$(prefix)/share/applications/gpac.desktop + installdylib: ifneq ($(MP4BOX_STATIC),yes) + + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(lib_dir)" + ifeq ($(CONFIG_WIN32),yes) - $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac.dll.a $(DESTDIR)$(prefix)/$(libdir) + $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac.dll.a $(DESTDIR)$(prefix)/$(lib_dir) $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac.dll $(DESTDIR)$(prefix)/bin else + ifeq ($(DEBUGBUILD),no) $(STRIP) -S bin/gcc/libgpac$(DYN_LIB_SUFFIX) endif + ifeq ($(CONFIG_DARWIN),yes) - $(INSTALL) -m 755 bin/gcc/libgpac$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) - ln -sf libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION_MAJOR)$(DYN_LIB_SUFFIX) - ln -sf libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX) + $(INSTALL) -m 755 bin/gcc/libgpac$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) + ln -sf libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.$(VERSION_MAJOR)$(DYN_LIB_SUFFIX) + ln -sf libgpac.$(VERSION_SONAME)$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX) else - $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) - ln -sf libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so.$(VERSION_MAJOR) - ln -sf libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so + $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) + ln -sf libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.so.$(VERSION_MAJOR) + ln -sf libgpac$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(lib_dir)/libgpac.so ifeq ($(DESTDIR)$(prefix),$(prefix)) ldconfig || true endif endif + endif + +endif + + +uninstalldylib: + rm -rf $(DESTDIR)$(prefix)/$(lib_dir)/libgpac* +ifeq ($(CONFIG_WIN32),yes) + rm -rf "$(DESTDIR)$(prefix)/bin/libgpac*" endif install-lib: - mkdir -p "$(DESTDIR)$(prefix)/include/gpac" + $(INSTALL) -d "$(DESTDIR)$(prefix)/include/gpac" + $(INSTALL) -d "$(DESTDIR)$(prefix)/include/gpac/internal" + $(INSTALL) -d "$(DESTDIR)$(prefix)/include/gpac/modules" + $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/include/gpac/*.h "$(DESTDIR)$(prefix)/include/gpac" - mkdir -p "$(DESTDIR)$(prefix)/include/gpac/internal" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/include/gpac/internal/*.h "$(DESTDIR)$(prefix)/include/gpac/internal" - mkdir -p "$(DESTDIR)$(prefix)/include/gpac/modules" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/include/gpac/modules/*.h "$(DESTDIR)$(prefix)/include/gpac/modules" - $(INSTALL) $(INSTFLAGS) -m 644 config.h "$(DESTDIR)$(prefix)/include/gpac/configuration.h" -ifeq ($(GPAC_ENST), yes) - mkdir -p "$(DESTDIR)$(prefix)/include/gpac/enst" + + $(INSTALL) $(INSTFLAGS) -m 644 config.h "$(DESTDIR)$(prefix)/include/gpac/configuration.h" || true + +ifeq ($(GPAC_ENST),yes) + $(INSTALL) -d "$(DESTDIR)$(prefix)/include/gpac/enst" $(INSTALL) $(INSTFLAGS) -m 644 $(SRC_PATH)/include/gpac/enst/*.h "$(DESTDIR)$(prefix)/include/gpac/enst" endif - mkdir -p "$(DESTDIR)$(prefix)/$(libdir)" - $(INSTALL) $(INSTFLAGS) -m 644 "./bin/gcc/libgpac_static.a" "$(DESTDIR)$(prefix)/$(libdir)" - if [ -d $(DESTDIR)$(prefix)/$(libdir)/pkgconfig ] ; then \ - $(INSTALL) $(INSTFLAGS) -m 644 gpac.pc "$(DESTDIR)$(prefix)/$(libdir)/pkgconfig" ; \ - fi + + $(INSTALL) -d "$(DESTDIR)$(prefix)/$(lib_dir)" + $(INSTALL) $(INSTFLAGS) -m 644 "./bin/gcc/libgpac_static.a" "$(DESTDIR)$(prefix)/$(lib_dir)" || true + + $(INSTALL) -d $(DESTDIR)$(prefix)/$(lib_dir)/pkgconfig + $(INSTALL) $(INSTFLAGS) -m 644 gpac.pc "$(DESTDIR)$(prefix)/$(lib_dir)/pkgconfig" + $(MAKE) installdylib + uninstall-lib: - rm -rf "$(prefix)/include/gpac/internal" - rm -rf "$(prefix)/include/gpac/modules" - rm -rf "$(prefix)/include/gpac/enst" - rm -rf "$(prefix)/include/gpac" + rm -rf "$(DESTDIR)$(prefix)/include/gpac/internal" + rm -rf "$(DESTDIR)$(prefix)/include/gpac/modules" + rm -rf "$(DESTDIR)$(prefix)/include/gpac/enst" + rm -rf "$(DESTDIR)$(prefix)/include/gpac" + rm -f "$(DESTDIR)$(prefix)/$(lib_dir)/libgpac_static.a" + rm -f "$(DESTDIR)$(prefix)/$(lib_dir)/pkgconfig/gpac.pc" + $(MAKE) uninstalldylib ifeq ($(CONFIG_DARWIN),yes) dmg: @@ -336,13 +344,13 @@ @echo "dmg: creates DMG package file for OSX" endif ifeq ($(CONFIG_LINUX),yes) - @echo "deb: creates DEB package file for debian based systems" + @echo "deb: creates DEB package file for debian based systems" endif @echo @echo "install-lib: install gpac library (dyn and static) and headers <gpac/*.h>, <gpac/modules/*.h> and <gpac/internal/*.h>" @echo "uninstall-lib: uninstall gpac library (dyn and static) and headers" @echo - @echo "tests: run all tests. For more info, check gpac/regression_tests/test_suite_make.sh -h" + @echo "test_suite: run all tests. For more info, check https://github.com/gpac/testsuite" @echo @echo "doc: build libgpac documentation in gpac/doc" @echo "man: build gpac man files in gpac/doc/man (must have latest build binaries installed)" @@ -350,4 +358,5 @@ @echo "lcov: generate lcov files" @echo "lcov_clean: clean all lcov/gcov files" + -include .depend
View file
gpac-1.0.0.tar.gz/README.md -> gpac-1.0.1.tar.gz/README.md
Changed
@@ -14,16 +14,17 @@ [![Tests](https://tests.gpac.io/testres/badge/tests/macos)](https://tests.gpac.io/) [![Build Status](https://tests.gpac.io/testres/badge/build/ios)](https://buildbot.gpac.io/#/grid?branch=master) - [![Build Status](https://tests.gpac.io/testres/badge/build/android)](https://buildbot.gpac.io/#/grid?branch=master) [![Coverage](https://tests.gpac.io/testres/badge/cov/linux64?branch=master)](https://tests.gpac.io/testres/) [![Coverage](https://tests.gpac.io/testres/badge/covfn/linux64?branch=master)](https://tests.gpac.io/testres/) ![License](https://img.shields.io/badge/license-LGPL-blue.svg) +[![OpenHub](https://www.openhub.net/p/gpac/widgets/project_thin_badge.gif)](https://www.openhub.net/p/gpac) + # GPAC Introduction -Current version: 1.0.0 +Current version: 1.0.1 GPAC is an open-source multimedia framework focused on modularity and standards compliance. GPAC provides tools to process, inspect, package, stream playback and interact with media content. Such content can be any combination of audio, video, subtitles, metadata, scalable graphics, encrypted media, 2D/3D graphics and ECMAScript. @@ -33,6 +34,10 @@ GPAC is distributed under the LGPL v2.1 or later, and is also available, for most of it, under a [commercial license](https://www.gpac-licensing.com). +Please cite our work in your research: +- GPAC Filters: https://doi.org/10.1145/3339825.3394929 +- GPAC: https://doi.org/10.1145/1291233.1291452 + # Features GPAC can process, analyse, package, stream, encode, decode and playback a wide variety of contents. Selected feature list:
View file
gpac-1.0.0.tar.gz/applications/Makefile -> gpac-1.0.1.tar.gz/applications/Makefile
Changed
@@ -6,11 +6,11 @@ APPDIRS+=mp4box else -ifeq ($(DISABLE_PLAYER), no) +ifeq ($(DISABLE_PLAYER),no) APPDIRS+=mp4client endif -ifeq ($(DISABLE_ISOFF), no) +ifeq ($(DISABLE_ISOFF),no) APPDIRS+=mp4box endif @@ -24,7 +24,7 @@ endif #disable due to version incompatibilities -ifeq ($(USE_WXWIDGETS), yes) +ifeq ($(USE_WXWIDGETS),yes) #APPDIRS+=osmo4_wx #V4STUDIODIR=V4Studio #INSTDIRS+=osmo4_wx
View file
gpac-1.0.0.tar.gz/applications/deprecated/mp42ts/Makefile -> gpac-1.0.1.tar.gz/applications/deprecated/mp42ts/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -28,7 +28,7 @@ include ../../static.mak #FIXME we have to disable AAC+bifs support in mp42ts since it reuses things from aac_in already in libgpac ... -ifeq ($(STATIC_MODULES), yes) +ifeq ($(STATIC_MODULES),yes) CFLAGS+=-DGPAC_DISABLE_PLAYER endif
View file
gpac-1.0.0.tar.gz/applications/deprecated/old_arch/dashcast/Makefile -> gpac-1.0.1.tar.gz/applications/deprecated/old_arch/dashcast/Makefile
Changed
@@ -6,17 +6,17 @@ LINKFLAGS=$(GPAC_SH_FLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(GPACREADONLY), yes) +ifeq ($(GPACREADONLY),yes) CFLAGS+=-DGPAC_READ_ONLY endif @@ -53,7 +53,7 @@ LINKFLAGS+=-lswresample endif -ifeq ($(CONFIG_DARWIN), yes) +ifeq ($(CONFIG_DARWIN),yes) #fixme - use proper detection of libavdevice dependencies #LINKFLAGS+=-lavfilter -lswresample -lbz2 endif
View file
gpac-1.0.0.tar.gz/applications/deprecated/old_arch/mp42avi/Makefile -> gpac-1.0.1.tar.gz/applications/deprecated/old_arch/mp42avi/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/deprecated/old_arch/osmo4_wx/Makefile -> gpac-1.0.1.tar.gz/applications/deprecated/old_arch/osmo4_wx/Makefile
Changed
@@ -4,17 +4,17 @@ CFLAGS= $(CXXFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(GPACREADONLY), yes) +ifeq ($(GPACREADONLY),yes) CFLAGS+=-DGPAC_READ_ONLY endif @@ -34,7 +34,7 @@ else SCENEGRAPH_CFLAGS+=$(JS_FLAGS) ifeq ($(CONFIG_JS),local) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes endif LINKFLAGS+=$(JS_LIBS) endif
View file
gpac-1.0.0.tar.gz/applications/deprecated/old_arch/osmozilla/Makefile -> gpac-1.0.1.tar.gz/applications/deprecated/old_arch/osmozilla/Makefile
Changed
@@ -6,7 +6,7 @@ USER_NAME=root else USER_NAME=$(shell whoami) -ifeq ($(USER_NAME), root) +ifeq ($(USER_NAME),root) else MOZILLA_DIR=local endif @@ -14,12 +14,12 @@ CFLAGS=$(CXXFLAGS) $(XUL_CFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -72,8 +72,8 @@ endif install: -ifeq ($(MOZILLA_DIR), local) -ifeq ($(USER_NAME), root) +ifeq ($(MOZILLA_DIR),local) +ifeq ($(USER_NAME),root) @echo "*** Root cannot install local mozilla plugins! ***" @echo "*** Exit root mode and reinstall mozilla plugin! ***" else @@ -87,8 +87,8 @@ endif uninstall: -ifeq ($(MOZILLA_DIR), local) -ifeq ($(USER_NAME), root) +ifeq ($(MOZILLA_DIR),local) +ifeq ($(USER_NAME),root) else rm -rf "$(HOME)/.mozilla/plugins/$(LIB)" rm -rf "$(HOME)/.mozilla/components/nposmozilla.xpt"
View file
gpac-1.0.0.tar.gz/applications/generators/MPEG4/Makefile -> gpac-1.0.1.tar.gz/applications/generators/MPEG4/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/generators/Makefile -> gpac-1.0.1.tar.gz/applications/generators/Makefile
Changed
@@ -2,9 +2,9 @@ GENDIRS=MPEG4 X3D -ifeq ($(HAS_LIBXML2), yes) +ifeq ($(HAS_LIBXML2),yes) #sorry minGW friends, I can't get a stable libxml2 to compile ... -ifeq ($(CONFIG_WIN32), yes) +ifeq ($(CONFIG_WIN32),yes) else GENDIRS+=SVG endif
View file
gpac-1.0.0.tar.gz/applications/generators/SVG/Makefile -> gpac-1.0.1.tar.gz/applications/generators/SVG/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/generators/WebGLGen/Makefile -> gpac-1.0.1.tar.gz/applications/generators/WebGLGen/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/generators/X3D/Makefile -> gpac-1.0.1.tar.gz/applications/generators/X3D/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/gpac/Makefile -> gpac-1.0.1.tar.gz/applications/gpac/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/gpac/main.c -> gpac-1.0.1.tar.gz/applications/gpac/main.c
Changed
@@ -55,8 +55,6 @@ FILE *sidebar_md=NULL; static FILE *helpout = NULL; -static void gpac_rmt_user_callback(void *udta, const char* text); - static const char *auto_gen_md_warning = "<!-- automatically generated - do not edit, patch gpac/applications/gpac/main.c -->\n"; //uncomment to check argument description matches our conventions - see filter.h @@ -70,6 +68,7 @@ static Bool print_filters(int argc, char **argv, GF_FilterSession *session, GF_SysArgMode argmode); static void dump_all_props(void); +static void dump_all_colors(void); static void dump_all_codec(GF_FilterSession *session); static void write_filters_options(GF_FilterSession *fsess); static void write_core_options(); @@ -141,6 +140,10 @@ "This will extract the URL and options.\n" "Note: one trick to avoid the escape sequence is to declare the URLs option at the end, eg `f1:opt1=foo:url=http://bar`, provided you have only one URL parameter to specify on the filter.\n" "\n" +"It is possible to disable option parsing (for string options) by duplicating the seperator.\n" +"EX filter::opt1=UDP://IP:PORT/:someopt=VAL::opt2=VAL2\n" +"This will pass `UDP://IP:PORT/:someopt=VAL` to `opt1` without inspecting it, and `VAL2` to `opt2`.\n" +" \n" "A filter may be assigned a name (for inspection purposes) using `:N=name` option. This name is not used in link resolution and may be changed at runtime by the filter instance.\n" "## Source and Sink filters\n" "Source and sink filters do not need to be addressed by the filter name, specifying `src=` or `dst=` instead is enough. " @@ -218,6 +221,7 @@ "- name#P4CC=VAL: accepts only PIDs with property matching `VAL`.\n" "- name#PName=VAL: same as above, using the builtin name corresponding to the property.\n" "- name#AnyName=VAL: same as above, using the name of a non built-in property.\n" +"- name#Name=OtherPropName: compares the value with the value of another property of the PID. The matching will fail if the value to compare to is not present or different from the value to check. The property to compare with shall be a built-in property.\n" "If the property is not defined on the PID, the property is matched. Otherwise, its value is checked against the given value.\n" "\n" "The following modifiers for comparisons are allowed (for both `P4CC=`, `PName=` and `AnyName=`):\n" @@ -240,6 +244,8 @@ "This indicates to connect to `vout` only PIDs with `Width` property equal to `640`.\n" "EX src=vid.mp4 @#Width-640 vout\n" "This indicates to connect to `vout` only PIDs with `Width` property less than `640`\n" +"EX src=vid.mp4 @#ID=ItemID#ItemNumber=1 vout\n" +"This will connect to `vout` only PID with an ID property equal to ItemID property (keep items, discard tracks) and an Item number of 1 (first item).\n" "\n" "Multiple fragment can be specified to check for multiple PID properties.\n" "EX src=vid.mp4 @#Width=640#Height+380 vout\n" @@ -560,7 +566,7 @@ GF_DEF_ARG("o", "dst", "specify an output file - see [filters help (-h doc)](filters_general)", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("ib", NULL, "specify an input file to wrap as GF_FileIO object (testing of GF_FileIO)", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT), GF_DEF_ARG("ob", NULL, "specify an output file to wrap as GF_FileIO object (testing of GF_FileIO)", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT), - GF_DEF_ARG("h", "help,-ha,-hx,-hh", "print help. Use `-help` or `-h` for basic options, `-ha` for advanced options, `-hx` for expert options and `-hh` for all.\nNote: The `@` character can be used in place of the `*` character.\n String parameter can be:\n"\ + GF_DEF_ARG("h", "help,-ha,-hx,-hh", "print help. Use `-help` or `-h` for basic options, `-ha` for advanced options, `-hx` for expert options and `-hh` for all. \nNote: The `@` character can be used in place of the `*` character. String parameter can be:\n"\ "- empty: print command line options help\n"\ "- doc: print the general filter info\n"\ "- alias: print the gpac alias syntax\n"\ @@ -573,13 +579,15 @@ "- filters:*: print name of all available filters, including meta filters\n"\ "- codecs: print the supported builtin codecs\n"\ "- props: print the supported builtin PID and packet properties\n"\ - "- links: print possible connections between each supported filters.\n"\ + "- colors: print the builtin color names and their values\n"\ + "- links: print possible connections between each supported filters\n"\ "- links FNAME: print sources and sinks for filter `FNAME` (either builtin or JS filter)\n"\ - "- FNAME: print filter `FNAME` info (multiple FNAME can be given).\n" - " - For meta-filters, use `FNAME:INST`, eg `ffavin:avfoundation`.\n" - " - Use `*` to print info on all filters (__big output!__), `*:*` to print info on all filters including meta filter instances (__really big output!__).\n" - " - By default only basic filter options and description are shown. Use `-ha` to show advanced options capabilities, `-hx` for expert options, `-hh` for all options and filter capabilities including on filters disabled in this build.\n"\ - "- FNAME.OPT: print option `OPT` in filter `FNAME`" + "- FNAME: print filter `FNAME` info (multiple FNAME can be given)\n" + " - For meta-filters, use `FNAME:INST`, eg `ffavin:avfoundation`\n" + " - Use `*` to print info on all filters (__big output!__), `*:*` to print info on all filters including meta filter instances (__really big output!__)\n" + " - By default only basic filter options and description are shown. Use `-ha` to show advanced options capabilities, `-hx` for expert options, `-hh` for all options and filter capabilities including on filters disabled in this build\n"\ + "- FNAME.OPT: print option `OPT` in filter `FNAME`\n" + "- OPT: look in filter names and options for `OPT` and suggest possible matches if none found. Use `-hx` to look for keyword in all option descriptions\n" , NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("p", NULL, "use indicated profile for the global GPAC config. If not found, config file is created. If a file path is indicated, this will load profile from that file. Otherwise, this will create a directory of the specified name and store new config there. Reserved name `0` means a new profile, not stored to disk. Appending `:reload` to the profile name will force recreating a new configuration file", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_ADVANCED), @@ -587,6 +595,7 @@ GF_DEF_ARG("aliasdoc", NULL, "assign documentation for a given alias (optional). Can be specified several times", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_ADVANCED), GF_DEF_ARG("uncache", NULL, "revert all items in GPAC cache directory to their original name and server path", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_ADVANCED), + GF_DEF_ARG("js", NULL, "specify javascript file to use as controller of filter session", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT), GF_DEF_ARG("wc", NULL, "write all core options in the config file unless already set", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT), GF_DEF_ARG("we", NULL, "write all file extensions in the config file unless already set (useful to change some default file extensions)", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT), @@ -613,9 +622,10 @@ " - an option using a single `-` indicates an option of gpac (see %s) or of libgpac (see %s)\n" " - an option using `--` indicates a global filter option, for example `--block_size=1000` (see %s)\n" " - an option using `-+` indicates a global meta-filter filter (eg FFMPEG) option, for example `-+profile=Baseline` (see %s)\n" - "\n " - "Options do not require any specific order, and may be present anywhere, including between link statements or filter declarations.\n" - "boolean values do not need any value specified. Other types shall be formatted as `opt=val`, except [-i](), `-src`, [-o](), `-dst` and [-h]() options.\n\n" + " \n" + "Filter declaration order may impact the link resolver which will try linking in declaration order. Most of the time for simple graphs, this has no impact. However, for complex graphs with no link declarations, this can lead to different results. \n" + "Options do not require any specific order, and may be present anywhere, including between link statements or filter declarations. \n" + "Boolean values do not need any value specified. Other types shall be formatted as `opt=val`, except [-i](), `-src`, [-o](), `-dst` and [-h]() options.\n\n" "The possible options for gpac are:\n\n", (gen_doc==1) ? "[gpac -h doc](filters_general#filter-declaration-filter)" : "`gpac -h doc`", (gen_doc==1) ? "[gpac -h doc](filters_general#expliciting-links-between-filters-link)" : "`gpac -h doc`", @@ -650,7 +660,7 @@ gpac_alias_help(GF_ARGMODE_BASE); } - gf_sys_format_help(helpout, help_flags, "\ngpac - GPAC command line filter engine - version %s\n%s\n", gf_gpac_version(), gf_gpac_copyright() ); + gf_sys_format_help(helpout, help_flags, "\ngpac - GPAC command line filter engine - version %s\n%s\n", gf_gpac_version(), gf_gpac_copyright_cite() ); } } @@ -667,7 +677,7 @@ "By default the configuration file only holds a few system specific options and directories. It is possible to serialize " "the entire set of options to the configuration file, using [-wc](GPAC) [-wf](GPAC). This should be avoided as the resulting " "configuration file size will be quite large, hence larger memory usage for the applications.\n" -"The options specified in the configuration file may be overriden by the values in __restrict.cfg__ file located in GPAC share system directory (e.g. /usr/share/gpac), " +"The options specified in the configuration file may be overridden by the values in __restrict.cfg__ file located in GPAC share system directory (e.g. /usr/share/gpac), " "if present; this allows enforcing system-wide configuration values.\n" "Note: The methods describe in this section apply to any application in GPAC transferring their arguments " "to libgpac. This is the case for __gpac__, __MP4Box__, __MP4Client/Osmo4__.\n" @@ -696,7 +706,11 @@ "Meta-filter options can be set in the same way using the syntax `-+OPT_NAME=VAL`.\n" "EX -+profile=Baseline -i file.cmp -o dump.264\n" "This is equivalent to specifying `-o dump.264:profile=Baseline`.\n" - +" \n" +"For both syntax, it is possible to specify the filter registry name of the option, using `--FNAME@OPTNAME=VAL`.\n" +"In this case the option will only be set for filters which are instances of registry FNAME. This is used when several registries use same option names.\n" +"EX --flist@timescale=100 -i plist1 -i plist2 -o live.mpd\n" +"This will set the timescale option on the playlists filters but not on the dasher filter.\n" }; #endif @@ -1363,7 +1377,7 @@ } if (!found && is_help) { const char *doc_helps[] = { - "log", "core", "modules", "doc", "alias", "props", "cfg", "prompt", "codecs", "links", "bin", "filters", "filters:*", "filters:@", NULL + "log", "core", "modules", "doc", "alias", "props", "colors", "cfg", "prompt", "codecs", "links", "bin", "filters", "filters:*", "filters:@", NULL }; i=0; while (doc_helps[i]) { @@ -1512,6 +1526,7 @@ GF_Err e=GF_OK; int i; const char *profile=NULL; + const char *session_js=NULL; u32 sflags=0; Bool override_seps=GF_FALSE; Bool write_profile=GF_FALSE; @@ -1633,6 +1648,9 @@ } else if (!strcmp(argv[i+1], "props")) { dump_all_props(); gpac_exit(0); + } else if (!strcmp(argv[i+1], "colors")) { + dump_all_colors(); + gpac_exit(0); } else if (!strcmp(argv[i+1], "cfg")) { gpac_config_help(); gpac_exit(0); @@ -1840,6 +1858,8 @@ } else if (!strcmp(arg, "-k")) { enable_prompt = GF_TRUE; + } else if (!strcmp(arg, "-js")) { + session_js = arg_val; } else if (!strcmp(arg, "-r")) { enable_reports = 2; if (arg_val && !strlen(arg_val)) { @@ -1927,7 +1947,13 @@ goto exit; } - gf_sys_profiler_set_callback(NULL, gpac_rmt_user_callback); + if (session_js) { + e = gf_fs_load_script(session, session_js); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Failed to load JS for session: %s\n", gf_error_to_string(e) )); + goto exit; + } + } //all good to go, load filters has_xopt = GF_FALSE; @@ -2053,9 +2079,9 @@ gf_list_add(loaded_filters, filter); } - if (!gf_list_count(loaded_filters)) { + if (!gf_list_count(loaded_filters) && !session_js) { if (nothing_to_do && !gen_doc) { - GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Nothing to do, check usage \"gpac -h\"\ngpac - GPAC command line filter engine - version %s\n%s\n", gf_gpac_version(), gf_gpac_copyright())); + GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Nothing to do, check usage \"gpac -h\"\ngpac - GPAC command line filter engine - version %s\n%s\n", gf_gpac_version(), gf_gpac_copyright_cite())); e = GF_BAD_PARAM; } else { e = GF_EOS; @@ -2218,6 +2244,16 @@ // if (a->flags & GF_FS_ARG_META) gf_sys_format_help(helpout, help_flags, ", meta"); gf_sys_format_help(helpout, help_flags | GF_PRINTARG_OPT_DESC, "): %s\n", a->arg_desc); + //check syntax + if (gen_doc) { + GF_GPACArg _a; + memset(&_a, 0, sizeof(GF_GPACArg)); + _a.name = a->arg_name; + _a.description = a->arg_desc; + _a.flags = GF_ARG_HINT_HIDE; + gf_sys_print_arg(NULL, 0, &_a, ""); + } + if (a->min_max_enum && strchr(a->min_max_enum, '|')) gf_sys_format_help(helpout, help_flags, "\n"); } @@ -2522,10 +2558,28 @@ gf_sys_format_help(helpout, help_flags, "\n"); } +static Bool strstr_nocase(const char *text, const char *subtext, u32 subtext_len) +{ + if (!*text || !subtext || !subtext_len) + return GF_FALSE; + + while (*text) { + if (tolower(*text) == *subtext) { + if (!strnicmp(text, subtext, subtext_len)) + return GF_TRUE; + + } + text++; + } + return GF_FALSE; +} + static Bool print_filters(int argc, char **argv, GF_FilterSession *session, GF_SysArgMode argmode) { Bool found = GF_FALSE; char *fname = NULL; + char *l_fname = NULL; + u32 lf_len = 0; u32 i, count = gf_fs_filters_registers_count(session); if (!gen_doc && list_filters) gf_sys_format_help(helpout, help_flags, "Listing %d supported filters%s:\n", count, (list_filters==2) ? " including meta-filters" : ""); @@ -2614,6 +2668,12 @@ if (!print_filter_info) return GF_FALSE; if (gen_doc) return GF_FALSE; + if (argmode==GF_ARGMODE_EXPERT) { + l_fname = gf_strdup(fname); + strlwr(l_fname); + lf_len = (u32) strlen(l_fname); + } + for (i=0; i<count; i++) { u32 j=0; const GF_FilterRegister *reg = gf_fs_get_filter_register(session, i); @@ -2622,14 +2682,28 @@ const GF_FilterArgs *arg = ®->args[j]; if (!arg || !arg->arg_name) break; j++; - if (strcmp(arg->arg_name, fname)) continue; - if (!found) { - GF_LOG(GF_LOG_WARNING, GF_LOG_APP, ("No such filter \"%s\" but found filters with matching options:\n", fname)); - found = GF_TRUE; + if (argmode==GF_ARGMODE_EXPERT) { + if (!arg->arg_desc || !strstr_nocase(arg->arg_desc, l_fname, lf_len)) continue; + if (!found) { + GF_LOG(GF_LOG_WARNING, GF_LOG_APP, ("\"%s\" is mentionned in the following filters options:\n", fname)); + found = GF_TRUE; + } + gf_sys_format_help(helpout, help_flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s.%s \n", reg->name, arg->arg_name); +#if 0 + + } else { + if (strcmp(arg->arg_name, fname)) continue; + if (!found) { + GF_LOG(GF_LOG_WARNING, GF_LOG_APP, ("No such filter \"%s\" but found filters with matching options:\n", fname)); + found = GF_TRUE; + } + gf_sys_format_help(helpout, help_flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s.%s: %s\n", reg->name, arg->arg_name, arg->arg_desc); +#endif } - gf_sys_format_help(helpout, help_flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s.%s: %s\n", reg->name, arg->arg_name, arg->arg_desc); } } + if (l_fname) gf_free(l_fname); + if (found) return GF_TRUE; @@ -2797,7 +2871,18 @@ gf_sys_format_help(helpout, help_flags | GF_PRINTARG_NL_TO_BR, ".TP\n.B %s\n%s\n", name, desc); idx++; } - }} + } +} +#include <gpac/color.h> +static void dump_all_colors(void) +{ + u32 i=0; + GF_Color color; + const char *name; + while (gf_color_enum(&i, &color, &name)) { + gf_sys_format_help(helpout, help_flags|GF_PRINTARG_HIGHLIGHT_FIRST, "%s: 0x%08X\n", name, color); + } +} static void dump_all_codec(GF_FilterSession *session) { @@ -3266,6 +3351,8 @@ #include <gpac/mpegts.h> #include <gpac/rtp_streamer.h> #include <gpac/internal/odf_dev.h> +#include <gpac/internal/media_dev.h> +#include <gpac/internal/isomedia_dev.h> #endif static u32 gpac_unit_tests(GF_MemTrackerType mem_track) { @@ -3400,7 +3487,7 @@ gf_htonl(0xAABBCCDD); gf_ntohl(0xAABBCCDD); gf_htons(0xAABB); - gf_tohs(0xAABB); + gf_ntohs(0xAABB); gf_errno_str(-1); /* these two lock the bash shell in test mode @@ -3423,6 +3510,8 @@ u32 size; sprintf(url, "gmem://%p", &b); + gf_sys_profiler_set_callback(NULL, NULL); + gf_blob_get_data(url, &data, &size); if (!data || strcmp((char *)data, "test")) { GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[CoreUnitTests] blob url parsing fail\n")); @@ -3623,6 +3712,34 @@ gf_odf_get_text_config(NULL, 0, 0, txtc); gf_odf_dump_txtcfg(txtc, NULL, 0, GF_FALSE); gf_odf_desc_del((GF_Descriptor *) txtc); + + //stuff only used by vtbdec + gf_media_hevc_read_pps_bs(NULL, NULL); + gf_media_hevc_read_sps_bs(NULL, NULL); + gf_media_hevc_read_vps_bs(NULL, NULL); + gf_mpegv12_get_config(NULL, 0, NULL); + + //hinting stuff + GF_HintPacket *hpck = gf_isom_hint_pck_new(GF_ISOM_BOX_TYPE_RTCP_STSD); + gf_isom_hint_pck_length(hpck); + gf_isom_hint_pck_size(hpck); + GF_BitStream *hbs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + gf_isom_hint_pck_write(hpck, hbs); + u8 *hbuf; + u32 hsize; + gf_bs_get_content(hbs, &hbuf, &hsize); + gf_bs_del(hbs); + hbs = gf_bs_new(hbuf, hsize, GF_BITSTREAM_READ); + gf_isom_hint_pck_read(hpck, hbs); + gf_bs_del(hbs); + gf_free(hbuf); + gf_isom_hint_pck_del(hpck); + + gf_isom_last_error(NULL); + gf_isom_get_media_time(NULL, 0, 0, NULL); + gf_isom_get_sample_description_index(NULL, 0, 0); + + #endif return 0; } @@ -3920,9 +4037,3 @@ all_gfio_defined = NULL; } - -static void gpac_rmt_user_callback(void *udta, const char* text) -{ - fprintf(stderr, "Remotery says: %s\n", text); - gf_sys_profiler_send("{ \"type\": \"chat\", \"value\": \"Got it !\"}"); -}
View file
gpac-1.0.0.tar.gz/applications/mp4box/Makefile -> gpac-1.0.1.tar.gz/applications/mp4box/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/mp4box/filedump.c -> gpac-1.0.1.tar.gz/applications/mp4box/filedump.c
Changed
@@ -897,7 +897,8 @@ s64 cts; u64 dts, offset; u32 isLeading, dependsOn, dependedOn, redundant; - Bool is_rap, has_roll; + Bool is_rap; + GF_ISOSampleRollType roll_type; s32 roll_distance; u32 index; GF_ISOSample *samp = gf_isom_get_sample_info(file, i+1, j+1, &index, &offset); @@ -906,7 +907,7 @@ continue; } gf_isom_get_sample_flags(file, i+1, j+1, &isLeading, &dependsOn, &dependedOn, &redundant); - gf_isom_get_sample_rap_roll_info(file, i+1, j+1, &is_rap, &has_roll, &roll_distance); + gf_isom_get_sample_rap_roll_info(file, i+1, j+1, &is_rap, &roll_type, &roll_distance); dts = samp->DTS; cts = dts + (s32) samp->CTS_Offset; fprintf(dump, "Sample %d\tDTS "LLU"\tCTS "LLD"\t%d\t%d", j+1, dts, cts, samp->dataLength, samp->IsRAP); @@ -914,7 +915,7 @@ if (!skip_offset) fprintf(dump, "\t"LLU, offset); - fprintf(dump, "\t%d\t%d\t%d\t%d\t%d\t%d\t%d", isLeading, dependsOn, dependedOn, redundant, is_rap, has_roll, roll_distance); + fprintf(dump, "\t%d\t%d\t%d\t%d\t%d\t%d\t%d", isLeading, dependsOn, dependedOn, redundant, is_rap, roll_type, roll_distance); if (cts< (s64) dts) { if (has_cts_offset==2) { @@ -1469,10 +1470,11 @@ sap_type = samp->IsRAP; if (!sap_type) { - Bool is_rap, has_roll; + Bool is_rap; + GF_ISOSampleRollType roll_type; s32 roll_dist; - gf_isom_get_sample_rap_roll_info(file, track, i+1, &is_rap, &has_roll, &roll_dist); - if (has_roll) sap_type = SAP_TYPE_4; + gf_isom_get_sample_rap_roll_info(file, track, i+1, &is_rap, &roll_type, &roll_dist); + if (roll_type) sap_type = SAP_TYPE_4; else if (is_rap) sap_type = SAP_TYPE_3; } @@ -1622,7 +1624,8 @@ } //get the movie SDP gf_isom_sdp_get(file, &sdp, &size); - fprintf(dump, "%s", sdp); + if (sdp && size) + fprintf(dump, "%s", sdp); fprintf(dump, "\r\n"); //then tracks @@ -1857,13 +1860,17 @@ } -GF_Err dump_isom_chapters(GF_ISOFile *file, char *inName, Bool is_final_name, Bool dump_ogg) +GF_Err dump_isom_chapters(GF_ISOFile *file, char *inName, Bool is_final_name, u32 dump_mode) { FILE *t; u32 i, count; u32 chap_tk = 0; count = gf_isom_get_chapter_count(file, 0); + if (dump_mode==2) dump_mode = GF_TEXTDUMPTYPE_OGG_CHAP; + else if (dump_mode==3) dump_mode = GF_TEXTDUMPTYPE_ZOOM_CHAP; + else dump_mode = GF_TEXTDUMPTYPE_TTXT_CHAP; + if (!count) { for (i=0; i<gf_isom_get_track_count(file); i++) { if (gf_isom_get_reference_count(file, i+1, GF_ISOM_REF_CHAP)) { @@ -1876,8 +1883,8 @@ return GF_OK; } - fprintf(stderr, "Chapter track found, dumping to ttxt\n"); - dump_isom_timed_text(file, gf_isom_get_track_id(file, chap_tk), inName, is_final_name, GF_FALSE, GF_TEXTDUMPTYPE_TTXT); + fprintf(stderr, "Chapter track found, dumping\n"); + dump_isom_timed_text(file, gf_isom_get_track_id(file, chap_tk), inName, is_final_name, GF_FALSE, dump_mode); return GF_OK; } @@ -1885,10 +1892,12 @@ char szName[1024]; strcpy(szName, inName); if (!is_final_name) { - if (dump_ogg) { + if (dump_mode==GF_TEXTDUMPTYPE_OGG_CHAP) { + strcat(szName, ".txt"); + } else if (dump_mode==GF_TEXTDUMPTYPE_ZOOM_CHAP) { strcat(szName, ".txt"); } else { - strcat(szName, ".chap"); + strcat(szName, ".ttxt"); } } t = gf_fopen(szName, "wt"); @@ -1897,19 +1906,33 @@ t = stdout; } + if (dump_mode==GF_TEXTDUMPTYPE_TTXT_CHAP) { + fprintf(t, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + fprintf(t, "<TextStream version=\"1.1\">\n"); + fprintf(t, "<TextStreamHeader width=\"0\" height=\"0\" layer=\"0\" translation_x=\"0\" translation_y=\"0\">\n"); + fprintf(t, "<TextSampleDescription horizontalJustification=\"left\" backColor=\"0 0 0\" scroll=\"None\"/>\n"); + fprintf(t, "</TextStreamHeader>\n"); + } + for (i=0; i<count; i++) { + char szDur[20]; u64 chapter_time; const char *name; gf_isom_get_chapter(file, 0, i+1, &chapter_time, &name); - if (dump_ogg) { - char szDur[20]; + if (dump_mode==GF_TEXTDUMPTYPE_OGG_CHAP) { fprintf(t, "CHAPTER%02d=%s\n", i+1, format_duration(chapter_time, 1000, szDur)); fprintf(t, "CHAPTER%02dNAME=%s\n", i+1, name); - } else { + } else if (dump_mode==GF_TEXTDUMPTYPE_ZOOM_CHAP) { chapter_time /= 1000; fprintf(t, "AddChapterBySecond("LLD",%s)\n", chapter_time, name); + } else { + fprintf(t, "<TextSample sampleTime=\"%s\" sampleDescriptionIndex=\"1\" xml:space=\"preserve\">%s</TextSample>\n" + , format_duration(chapter_time, 1000, szDur), name); } } + if (dump_mode==GF_TEXTDUMPTYPE_TTXT_CHAP) { + fprintf(t, "</TextStream>\n"); + } if (inName) gf_fclose(t); return GF_OK; } @@ -2060,6 +2083,7 @@ Bool is_od_track = 0; u32 trackNum, i, j, max_rate, rate, ts, mtype, msub_type, timescale, sr, nb_ch, count, alt_group, nb_groups, nb_edits, cdur, csize, bps; u64 time_slice, dur, size; + s32 cts_shift; GF_ESD *esd; char szDur[50]; char *lang; @@ -2080,10 +2104,18 @@ fprintf(stderr, "Media Duration %s - ", format_duration(gf_isom_get_media_duration(file, trackNum), timescale, szDur)); fprintf(stderr, "Indicated Duration %s\n", format_duration(gf_isom_get_media_original_duration(file, trackNum), timescale, szDur)); + if (gf_isom_check_data_reference(file, trackNum, 1) != GF_OK) { + fprintf(stderr, "Track uses external data reference not supported by GPAC!\n"); + } + nb_edits = gf_isom_get_edits_count(file, trackNum); if (nb_edits) fprintf(stderr, "Track has %d edit lists: track duration is %s\n", nb_edits, format_duration(gf_isom_get_track_duration(file, trackNum), gf_isom_get_timescale(file), szDur)); + cts_shift = gf_isom_get_composition_offset_shift(file, trackNum); + if (cts_shift) + fprintf(stderr, "Track composition offset shift (negative CTS offset): %d\n", cts_shift); + if (gf_isom_is_track_in_root_od(file, trackNum) ) fprintf(stderr, "Track is present in Root OD\n"); if (!gf_isom_is_track_enabled(file, trackNum)) fprintf(stderr, "Track is disabled\n"); gf_isom_get_media_language(file, trackNum, &lang); @@ -2105,10 +2137,20 @@ } if (gf_isom_is_track_fragmented(file, trackID) ) { + u32 defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess; + u8 defaultPadding; + u16 defaultDegradationPriority; u32 frag_samples; u64 frag_duration; gf_isom_get_fragmented_samples_info(file, trackID, &frag_samples, &frag_duration); fprintf(stderr, "Fragmented track: %d samples - Media Duration %s\n", frag_samples, format_duration(frag_duration, timescale, szDur)); + + gf_isom_get_fragment_defaults(file, trackNum, &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority); + + fprintf(stderr, "Fragment sample defaults: duration %d size %d stsd %d sync %d padding %d degradation_priority %d\n", + defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, + (u32) defaultPadding, (u32) defaultDegradationPriority + ); } if (!gf_isom_is_self_contained(file, trackNum, 1)) { @@ -2591,7 +2633,11 @@ } else if(gf_isom_is_cenc_media(file, trackNum, 1)) { gf_isom_get_cenc_info(file, trackNum, 1, NULL, &scheme_type, &version, &IV_size); fprintf(stderr, "\n*Encrypted stream - CENC scheme %s (version: major=%u, minor=%u)\n", gf_4cc_to_str(scheme_type), (version&0xFFFF0000)>>16, version&0xFFFF); - if (IV_size) fprintf(stderr, "Initialization Vector size: %d bits\n", IV_size*8); + if (IV_size) + fprintf(stderr, "Initialization Vector size: %d bits\n", IV_size*8); + if (gf_isom_cenc_is_pattern_mode(file, trackNum, 1)) + fprintf(stderr, "Pattern mode enabled\n"); + } else if(gf_isom_is_adobe_protection_media(file, trackNum, 1)) { gf_isom_get_adobe_protection_info(file, trackNum, 1, NULL, &scheme_type, &version, NULL); fprintf(stderr, "\n*Encrypted stream - Adobe protection scheme %s (version %d)\n", gf_4cc_to_str(scheme_type), version); @@ -2773,6 +2819,35 @@ } else { fprintf(stderr, "Unknown Metadata Stream\n"); } + } else if ((msub_type == GF_ISOM_SUBTYPE_MH3D_MHA1) || (msub_type == GF_ISOM_SUBTYPE_MH3D_MHA2)) { + fprintf(stderr, "\tMPEG-H Audio stream - Sample Rate %d - %d channel(s) %d bps\n", sr, nb_ch, (u32) bps); + esd = gf_media_map_esd(file, trackNum, 1); + if (!esd || !esd->decoderConfig || !esd->decoderConfig->decoderSpecificInfo + || !esd->decoderConfig->decoderSpecificInfo->data || (esd->decoderConfig->decoderSpecificInfo->dataLength<5) + ) { + fprintf(stderr, "\tInvalid MPEG-H audio config\n"); + } else { + fprintf(stderr, "\tProfileLevelIndication: %02X\n", esd->decoderConfig->decoderSpecificInfo->data[1]); + } + if (esd) gf_odf_desc_del((GF_Descriptor *)esd); + } else if ((msub_type == GF_ISOM_SUBTYPE_MH3D_MHM1) || (msub_type == GF_ISOM_SUBTYPE_MH3D_MHM2)) { + fprintf(stderr, "\tMPEG-H AudioMux stream - Sample Rate %d - %d channel(s) %d bps\n", sr, nb_ch, (u32) bps); + esd = gf_media_map_esd(file, trackNum, 1); + if (!esd || !esd->decoderConfig || !esd->decoderConfig->decoderSpecificInfo + || !esd->decoderConfig->decoderSpecificInfo->data) { + GF_ISOSample *samp = gf_isom_get_sample(file, trackNum, 1, NULL); + if (samp) { + s32 PL = gf_mpegh_get_mhas_pl(samp->data, samp->dataLength); + if (PL>=0) + fprintf(stderr, "\tProfileLevelIndication: %02X\n", PL); + gf_isom_sample_del(&samp); + } + } else if (esd->decoderConfig->decoderSpecificInfo->dataLength<5) { + fprintf(stderr, "\tInvalid MPEG-H audio config\n"); + } else { + fprintf(stderr, "\tProfileLevelIndication: %02X\n", esd->decoderConfig->decoderSpecificInfo->data[1]); + } + if (esd) gf_odf_desc_del((GF_Descriptor *)esd); } else { GF_GenericSampleDescription *udesc = gf_isom_get_generic_sample_description(file, trackNum, 1); if (udesc) { @@ -2849,6 +2924,7 @@ fprintf(stderr, "\tNo sync sample found\n"); break; } + fprintf(stderr, "\tMax sample duration: %d / %d\n", gf_isom_get_max_sample_delta(file, trackNum), timescale); if (!full_dump) { fprintf(stderr, "\n"); @@ -2937,42 +3013,6 @@ } } -static const char* ID3v1Genres[] = { - "Blues", "Classic Rock", "Country", "Dance", "Disco", - "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", - "New Age", "Oldies", "Other", "Pop", "R&B", - "Rap", "Reggae", "Rock", "Techno", "Industrial", - "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", - "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", - "Fusion", "Trance", "Classical", "Instrumental", "Acid", - "House", "Game", "Sound Clip", "Gospel", "Noise", - "AlternRock", "Bass", "Soul", "Punk", "Space", - "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", - "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", - "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", - "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", - "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", - "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", - "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", - "Folk", "Folk/Rock", "National Folk", "Swing", -}; -static const char *id3_get_genre(u32 tag) -{ - if ((tag>0) && (tag <= (sizeof(ID3v1Genres)/sizeof(const char *)) )) { - return ID3v1Genres[tag-1]; - } - return "Unknown"; -} -u32 id3_get_genre_tag(const char *name) -{ - u32 i, count = sizeof(ID3v1Genres)/sizeof(const char *); - if (!name) return 0; - for (i=0; i<count; i++) { - if (!stricmp(ID3v1Genres[i], name)) return i+1; - } - return 0; -} - void DumpMovieInfo(GF_ISOFile *file) { GF_InitialObjectDescriptor *iod; @@ -3080,7 +3120,6 @@ if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_ARTIST, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tArtist: %s\n", tag); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_ALBUM, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tAlbum: %s\n", tag); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_COMMENT, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tComment: %s\n", tag); - if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACK, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrack: %d / %d\n", tag[3], tag[5]); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_COMPOSER, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tComposer: %s\n", tag); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_WRITER, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tWriter: %s\n", tag); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_ALBUM_ARTIST, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tAlbum Artist: %s\n", tag); @@ -3089,7 +3128,7 @@ if (tag[0]) { fprintf(stderr, "\tGenre: %s\n", tag); } else { - fprintf(stderr, "\tGenre: %s\n", id3_get_genre(((u8*)tag)[1])); + fprintf(stderr, "\tGenre: %s\n", gf_id3_get_genre(((u8*)tag)[1])); } } if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_COMPILATION, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tCompilation: %s\n", tag[0] ? "Yes" : "No"); @@ -3106,7 +3145,13 @@ fprintf(stderr, "\tTempo (BPM): %d\n", tag[1]); } } - if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACKNUMBER, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrackNumber: %d / %d\n", (0xff00 & (tag[2]<<8)) | (0xff & tag[3]), (0xff00 & (tag[4]<<8)) | (0xff & tag[5])); + if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACKNUMBER, &tag, &tag_len)==GF_OK) { + if (tag[0]) { + fprintf(stderr, "\tTrackNumber: %s\n", tag); + } else { + fprintf(stderr, "\tTrackNumber: %d / %d\n", (0xff00 & (tag[2]<<8)) | (0xff & tag[3]), (0xff00 & (tag[4]<<8)) | (0xff & tag[5])); + } + } if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACK, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrack: %s\n", tag); if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_GROUP, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tGroup: %s\n", tag); @@ -3360,6 +3405,10 @@ GF_M2TS_Demuxer *ts; FILE *src; + if (!prog_num && !out_name) { + fprintf(stderr, "No program number nor output filename specified. No timestamp file will be generated."); + } + src = gf_fopen(mpeg2ts_file, "rb"); if (!src) { fprintf(stderr, "Cannot open %s: no such file\n", mpeg2ts_file);
View file
gpac-1.0.0.tar.gz/applications/mp4box/fileimport.c -> gpac-1.0.1.tar.gz/applications/mp4box/fileimport.c
Changed
@@ -228,6 +228,42 @@ chap_duration = ref_duration - chap_duration; gf_isom_set_last_sample_duration(file, track, (u32) chap_duration); } +#ifdef GPAC_ENABLE_COVERAGE + if (gf_sys_is_cov_mode()) { + u8 NbBits; + u32 switchGroupID, nb_crit, size, reserved; + u8 priority; + Bool discardable; + GF_AudioChannelLayout layout; + gf_isom_get_sample_size(file, track, 1); + gf_isom_get_sample_dts(file, track, 1); + gf_isom_get_sample_from_dts(file, track, 0); + gf_isom_set_sample_padding(file, track, 0); + gf_isom_has_padding_bits(file, track); + gf_isom_get_sample_padding_bits(file, track, 1, &NbBits); + gf_isom_keep_utc_times(file, 1); +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + gf_isom_set_single_moof_mode(file, GF_TRUE); + gf_isom_reset_sample_count(NULL); + gf_isom_set_traf_mss_timeext(NULL, 0, 0, 0); + gf_isom_get_next_moof_number(NULL); + gf_isom_set_fragment_reference_time(NULL, 0, 0, 0); +#endif + //this one is not tested in master due to old-arch compat, to remove when we enable tests without old-arch + gf_isom_get_audio_layout(file, track, 1, &layout); + + gf_isom_get_track_switch_parameter(file, track, 1, &switchGroupID, &nb_crit); + gf_isom_sample_has_subsamples(file, track, 1, 0); + gf_isom_sample_get_subsample(file, track, 1, 0, 1, &size, &priority, &reserved, &discardable); +#ifndef GPAC_DISABLE_ISOM_HINTING + gf_isom_hint_blank_data(NULL, 0, 0); + gf_isom_hint_sample_description_data(NULL, 0, 0, 1, 0, 0, 0); + gf_isom_get_payt_info(NULL, 0, 0, NULL); +#endif + gf_isom_estimate_size(file); + + } +#endif } GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, GF_Fraction force_fps, u32 frames_per_sample, GF_FilterSession *fsess, char **mux_args_if_first_pass, u32 tk_idx) @@ -1190,6 +1226,7 @@ //TODO - merge, temporal sublayers } } +#ifndef GPAC_DISABLE_HEVC if (check_track_for_hevc) { if (split_tile_mode) { e = gf_media_split_hevc_tiles(dest, split_tile_mode - 1); @@ -1201,6 +1238,7 @@ if (e) goto exit; } } +#endif if (tc_fps_num) { u32 desc_index=0; @@ -1285,6 +1323,27 @@ } +static Bool on_split_event(void *_udta, GF_Event *evt) +{ + Double progress; + u32 *prev_progress = (u32 *)_udta; + if (!_udta) return GF_FALSE; + if (evt->type != GF_EVENT_PROGRESS) return GF_FALSE; + if (!evt->progress.total) return GF_FALSE; + + progress = (Double) (100*evt->progress.done) / evt->progress.total; + if ((u32) progress==*prev_progress) + return GF_FALSE; + + *prev_progress = (u32) progress; +#ifndef GPAC_DISABLE_LOG + GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Spliting: % 2.2f %%\r", progress)); +#else + fprintf(stderr, "Spliting: % 2.2f %%\r", progress); +#endif + return GF_FALSE; +} + GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u64 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start_time, Bool adjust_split_end, char *outName, const char *tmpdir, Bool force_rap_split, const char *split_range_str) { Bool chunk_extraction, rap_split, split_until_end; @@ -1294,6 +1353,7 @@ char *filter_args = NULL; GF_FilterSession *fs; GF_Filter *src, *reframe, *dst; + u32 progress = (u32) -1; chunk_extraction = (chunk_start>=0) ? GF_TRUE : GF_FALSE; if (split_range_str) @@ -1408,6 +1468,22 @@ //link reframer to dst gf_filter_set_source(dst, reframe, NULL); + if (!gf_sys_is_test_mode() +#ifndef GPAC_DISABLE_LOG + && (gf_log_get_tool_level(GF_LOG_APP)!=GF_LOG_QUIET) +#endif + && !gf_sys_is_quiet() + ) { + gf_fs_enable_reporting(fs, GF_TRUE); + gf_fs_set_ui_callback(fs, on_split_event, &progress); + } +#ifdef GPAC_ENABLE_COVERAGE + else if (gf_sys_is_cov_mode()) { + on_split_event(NULL, NULL); + } +#endif //GPAC_ENABLE_COVERAGE + + e = gf_fs_run(fs); if (e>=GF_OK) { e = gf_fs_get_last_connect_error(fs); @@ -1662,6 +1738,7 @@ Bool use_ts_dur = 1; Bool merge_edits = 0; Bool new_track = 0; + u32 dst_tk_sample_entry = 0; mtype = gf_isom_get_media_type(orig, i+1); switch (mtype) { case GF_ISOM_MEDIA_HINT: @@ -1672,6 +1749,7 @@ case GF_ISOM_MEDIA_SUBT: case GF_ISOM_MEDIA_MPEG_SUBT: case GF_ISOM_MEDIA_SCENE: + case GF_ISOM_MEDIA_TIMECODE: use_ts_dur = 0; case GF_ISOM_MEDIA_AUDIO: case GF_ISOM_MEDIA_VISUAL: @@ -1713,6 +1791,7 @@ subtype_src=GF_ISOM_SUBTYPE_HVC1; if (subtype_dst != subtype_src) { + dst_tk_sample_entry = dst_tk; dst_tk = 0; } } @@ -1728,6 +1807,7 @@ gf_isom_get_visual_info(dest, j+1, 1, &w, &h); if ((ow==w) && (oh==h)) { dst_tk = j+1; + dst_tk_sample_entry = 0; break; } } @@ -1751,16 +1831,21 @@ } if (lang_dst==lang_src) { dst_tk = j+1; + dst_tk_sample_entry = 0; break; } } else { dst_tk = j+1; + dst_tk_sample_entry = 0; break; } } } } + if (dst_tk_sample_entry) + dst_tk = dst_tk_sample_entry; + if (dst_tk) { u32 found_dst_tk = dst_tk; u32 stype = gf_isom_get_media_subtype(dest, dst_tk, 1); @@ -1805,6 +1890,22 @@ } } + if (dst_tk_sample_entry && !dst_tk) { + u32 k, nb_sample_desc = gf_isom_get_sample_description_count(orig, i+1); + dst_tk = dst_tk_sample_entry; + fprintf(stderr, "Multiple sample entry required, merging\n"); + for (k=0; k<nb_sample_desc; k++) { + u32 sdesc_idx; + e = gf_isom_clone_sample_description(dest, dst_tk, orig, i+1, k+1, NULL, NULL, &sdesc_idx); + if (e) goto err_exit; + //remember idx of first new added sample desc + if (!k) + dst_tk_sample_entry = sdesc_idx-1; + } + } else { + dst_tk_sample_entry = 0; + } + /*looks like a new track*/ if (!dst_tk) { fprintf(stderr, "No suitable destination track found - creating new one (type %s)\n", gf_4cc_to_str(mtype)); @@ -1886,11 +1987,11 @@ samp->CTS_Offset = (u32) (samp->CTS_Offset * ts_scale); if (gf_isom_is_self_contained(orig, i+1, di)) { - e = gf_isom_add_sample(dest, dst_tk, di, samp); + e = gf_isom_add_sample(dest, dst_tk, di + dst_tk_sample_entry, samp); } else { u64 offset; GF_ISOSample *s = gf_isom_get_sample_info(orig, i+1, j+1, &di, &offset); - e = gf_isom_add_sample_reference(dest, dst_tk, di, samp, offset); + e = gf_isom_add_sample_reference(dest, dst_tk, di + dst_tk_sample_entry, samp, offset); gf_isom_sample_del(&s); } if (samp->nb_pack) @@ -1926,8 +2027,7 @@ /*convert from media time to track time*/ u32 movts_dst = gf_isom_get_timescale(dest); u32 trackts_dst = gf_isom_get_media_timescale(dest, dst_tk); - /*convert from orig to dst time scale*/ - movts_dst = (u32) (movts_dst * ts_scale); + u32 trackts_orig = gf_isom_get_media_timescale(orig, i+1); /*get the first edit normal mode and add the new track dur*/ for (j=nb_edits; j>0; j--) { @@ -1939,19 +2039,18 @@ Double prev_dur = (Double) (s64) dest_track_dur_before_cat; Double dur = (Double) (s64) gf_isom_get_media_duration(orig, i+1); - dur *= movts_dst; - dur /= trackts_dst; - prev_dur *= movts_dst; - prev_dur /= trackts_dst; - /*safety test: some files have broken edit lists. If no more than 2 entries, check that the segment duration is less or equal to the movie duration*/ - if (prev_dur < segmentDuration) { - fprintf(stderr, "Warning: suspicious edit list entry found: duration %g sec but longest track duration before cat is %g - fixing it\n", (Double) (s64) segmentDuration/1000.0, prev_dur/1000); + if (prev_dur * movts_dst < segmentDuration * trackts_dst) { + fprintf(stderr, "Warning: suspicious edit list entry found: duration %g sec but longest track duration before cat is %g - fixing it\n", (Double) (s64) segmentDuration/movts_dst, prev_dur/trackts_dst); segmentDuration = (dest_track_dur_before_cat - mediaTime) * movts_dst; segmentDuration /= trackts_dst; } + //express original dur in new timescale + dur /= trackts_orig; + dur *= movts_dst; + segmentDuration += (u64) (s64) dur; gf_isom_modify_edit(dest, dst_tk, j, segmentDuration, mediaTime, editMode); break; @@ -2012,6 +2111,23 @@ gf_media_update_bitrate(dest, dst_tk); } + for (i = 0; i < gf_isom_get_track_count(dest); ++i) { + if (gf_isom_get_media_type(dest, i+1) == GF_ISOM_MEDIA_TIMECODE) { + u32 video_ref = 0; + for (j = 0; j < gf_isom_get_track_count(dest); ++j) { + if (gf_isom_is_video_handler_type(gf_isom_get_media_type(dest, j+1))) { + video_ref = j+1; + break; + } + } + if (video_ref) { + u64 video_ref_dur = gf_isom_get_media_duration(dest, video_ref); + u32 last_sample_dur = gf_isom_get_sample_duration(dest, i+1, gf_isom_get_sample_count(dest, i+1)); + u64 dur = video_ref_dur - gf_isom_get_media_duration(dest, i+1) + last_sample_dur; + gf_isom_set_last_sample_duration(dest, i+1, (u32)dur); + } + } + } gf_set_progress("Appending", nb_samp, nb_samp); /*check brands*/ @@ -2750,7 +2866,7 @@ e = gf_isom_add_meta_item(file, 1, 0, 1, NULL, isom_src, 0, 0, NULL, NULL, NULL, NULL, NULL); if (e) goto exit; } - e = gf_isom_set_meta_xml(file, 1, 0, file_name, !ascii); + e = gf_isom_set_meta_xml(file, 1, 0, file_name, NULL, 0, !ascii); if (e) goto exit; skip_chars = (u32) strlen(root_dir);
View file
gpac-1.0.0.tar.gz/applications/mp4box/main.c -> gpac-1.0.1.tar.gz/applications/mp4box/main.c
Changed
@@ -107,7 +107,7 @@ fprintf(stderr, "MP4Box - GPAC version %s\n" "%s\n" "GPAC Configuration: " GPAC_CONFIGURATION "\n" - "Features: %s %s\n", gf_gpac_version(), gf_gpac_copyright(), gf_sys_features(GF_FALSE), gf_sys_features(GF_TRUE)); + "Features: %s %s\n", gf_gpac_version(), gf_gpac_copyright_cite(), gf_sys_features(GF_FALSE), gf_sys_features(GF_TRUE)); } GF_GPACArg m4b_gen_args[] = @@ -178,8 +178,8 @@ "- refTrack=ID: ID of the track used as a group reference. If not set, the track will belong to the same group as the " "previous trackID specified. If 0 or no previous track specified, a new alternate group will be created\n" "- switchID=ID: ID of the switch group to create. If 0, a new ID will be computed for you. If <0, disables SwitchGroup\n" - "- criteria=string: list of space-separated 4CCs.\n" - "- trackID=ID: ID of the track to add to this group.\n" + "- criteria=string: list of space-separated 4CCs\n" + "- trackID=ID: ID of the track to add to this group\n" " \n" "Warning: Options modify state as they are parsed, `trackID=1:criteria=lang:trackID=2` is different from `criteria=lang:trackID=1:trackID=2`" "\n", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_ADVANCED), @@ -237,7 +237,7 @@ GF_GPACArg m4b_dash_args[] = { - GF_DEF_ARG("mpd", NULL, "convert given HLS or smooth manifest (local or remote http) to MPD.\nWarning: This is not compatible with other DASH options and does not convert associated segments", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("mpd", NULL, "convert given HLS or smooth manifest (local or remote http) to MPD. \nWarning: This is not compatible with other DASH options and does not convert associated segments", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("dash", "-dash-strict", "create DASH from input files with given segment (subsegment for onDemand profile) duration in ms", NULL, NULL, GF_ARG_DOUBLE, 0), GF_DEF_ARG("dash-live", NULL, "generate a live DASH session using the given segment duration in ms; using `-dash-live=F`will also write the live context to `F`. MP4Box will run the live session until `q` is pressed or a fatal error occurs", NULL, NULL, GF_ARG_DOUBLE, 0), GF_DEF_ARG("ddbg-live", NULL, "same as [-dash-live]() without time regulation for debug purposes", NULL, NULL, GF_ARG_DOUBLE, 0), @@ -250,20 +250,20 @@ GF_DEF_ARG("rap", NULL, "ensure that segments begin with random access points, segment durations might vary depending on the source encoding", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("frag-rap", NULL, "ensure that all fragments begin with random access points (duration might vary depending on the source encoding)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("segment-name", NULL, "set the segment name for generated segments. If not set (default), segments are concatenated in output file except in `live` profile where `dash_%%s`. Supported replacement strings are:\n" - "- $Number[%%0Nd]$ is replaced by the segment number, possibly prefixed with 0.\n" - "- $RepresentationID$ is replaced by representation name.\n" - "- $Time$ is replaced by segment start time.\n" - "- $Bandwidth$ is replaced by representation bandwidth.\n" - "- $Init=NAME$ is replaced by NAME for init segment, ignored otherwise. May occur multiple times.\n" - "- $Index=NAME$ is replaced by NAME for index segments, ignored otherwise. May occur multiple times.\n" - "- $Path=PATH$ is replaced by PATH when creating segments, ignored otherwise. May occur multiple times.\n" - "- $Segment=NAME$ is replaced by NAME for media segments, ignored for init segments. May occur multiple times", NULL, NULL, GF_ARG_STRING, 0), + "- $Number[%%0Nd]$ is replaced by the segment number, possibly prefixed with 0\n" + "- $RepresentationID$ is replaced by representation name\n" + "- $Time$ is replaced by segment start time\n" + "- $Bandwidth$ is replaced by representation bandwidth\n" + "- $Init=NAME$ is replaced by NAME for init segment, ignored otherwise\n" + "- $Index=NAME$ is replaced by NAME for index segments, ignored otherwise\n" + "- $Path=PATH$ is replaced by PATH when creating segments, ignored otherwise\n" + "- $Segment=NAME$ is replaced by NAME for media segments, ignored for init segments", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("segment-ext", NULL, "set the segment extension, `null` means no extension", "m4s", NULL, GF_ARG_STRING, 0), GF_DEF_ARG("init-segment-ext", NULL, "set the segment extension for init, index and bitstream switching segments, `null` means no extension\n", "mp4", NULL, GF_ARG_STRING, 0), GF_DEF_ARG("segment-timeline", NULL, "use `SegmentTimeline` when generating segments", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("segment-marker `MARK`", NULL, "add a box of type `MARK` (4CC) at the end of each DASH segment", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("insert-utc", NULL, "insert UTC clock at the beginning of each ISOBMF segment", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("base-url", NULL, "set Base url at MPD level. Can be used several times.\nWarning: this does not modify generated files location", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("base-url", NULL, "set Base url at MPD level. Can be used several times. \nWarning: this does not modify generated files location", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("mpd-title", NULL, "set MPD title", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("mpd-source", NULL, "set MPD source", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("mpd-info-url", NULL, "set MPD info url", NULL, NULL, GF_ARG_STRING, 0), @@ -280,7 +280,7 @@ GF_DEF_ARG("ast-offset", NULL, "specify MPD AvailabilityStartTime offset in ms if positive, or availabilityTimeOffset of each representation if negative", "0", NULL, GF_ARG_INT, 0), GF_DEF_ARG("dash-scale", NULL, "specify that timing for [-dash]() and [-frag]() are expressed in given timexale (units per seconds)", NULL, NULL, GF_ARG_INT, 0), GF_DEF_ARG("mem-frags", NULL, "fragmentation happens in memory rather than on disk before flushing to disk", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("pssh=", NULL, "set pssh store mode.\n" + GF_DEF_ARG("pssh", NULL, "set pssh store mode\n" "- v: initial movie\n" "- f: movie fragments\n" "- m: MPD\n" @@ -288,15 +288,15 @@ "- mf, fm: in movie fragments and MPD", NULL, "v|f|m|mv|vm|mf|fm", GF_ARG_INT, 0), GF_DEF_ARG("sample-groups-traf", NULL, "store sample group descriptions in traf (duplicated for each traf). If not set, sample group descriptions are stored in the initial movie", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("mvex-after-traks", NULL, "store `mvex` box after `trak` boxes within the moov box. If not set, `mvex` is before", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("sdtp-traf", NULL, "use `sdtp` box in `traf` (Smooth-like).\n" + GF_DEF_ARG("sdtp-traf", NULL, "use `sdtp` box in `traf` (Smooth-like)\n" "- no: do not use sdtp\n" "- sdtp: use sdtp box to indicate sample dependencies and don't write info in trun sample flags\n" "- both: use sdtp box to indicate sample dependencies and also write info in trun sample flags\n", NULL, "no|sdtp|both", GF_ARG_INT, 0), GF_DEF_ARG("no-cache", NULL, "disable file cache for dash inputs", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("no-loop", NULL, "disable looping content in live mode and uses period switch instead", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("hlsc", NULL, "insert UTC in variant playlists for live HLS", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("bound", NULL, "enable video segmentation with same method as audio (i.e.: always try to split before or at the segment boundary - not after)", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("closest", NULL, "enable video segmentation closest to the segment boundary (before or after)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("bound", NULL, "segmentation will always try to split before or at, but never after, the segment boundary", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("closest", NULL, "segmentation will use the closest frame to the segment boundary (before or after)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("subsegs-per-sidx", NULL, "set the number of subsegments to be written in each SIDX box\n" "- 0: a single SIDX box is used per segment\n" @@ -380,13 +380,13 @@ GF_GPACArg m4b_imp_args[] = { GF_DEF_ARG("add", NULL, "add given file tracks to file. Multiple inputs can be specified using `+`, eg `-add url1+url2", NULL, NULL, GF_ARG_STRING, 0), - GF_DEF_ARG("cat", NULL, "concatenate given file samples to file, creating tracks if needed. Multiple inputs can be specified using `+`(eg `-cat url1+url2).\nNote: Note: This aligns initial timestamp of the file to be concatenated", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("cat", NULL, "concatenate given file samples to file, creating tracks if needed. Multiple inputs can be specified using `+`(eg `-cat url1+url2). \nNote: This aligns initial timestamp of the file to be concatenated", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("catx", NULL, "same as [-cat]() but new tracks can be imported before concatenation by specifying `+ADD_COMMAND` where `ADD_COMMAND` is a regular [-add]() syntax", NULL, NULL, GF_ARG_STRING, 0), - GF_DEF_ARG("catpl", NULL, "concatenate files listed in the given playlist file (one file per line, lines starting with # are comments).\nNote: Each listed file is concatenated as if called with -cat", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("catpl", NULL, "concatenate files listed in the given playlist file (one file per line, lines starting with # are comments). \nNote: Each listed file is concatenated as if called with -cat", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("unalign-cat", NULL, "do not attempt to align timestamps of samples inbetween tracks", NULL, NULL, GF_ARG_STRING, 0), - GF_DEF_ARG("force-cat", NULL, "skip media configuration check when concatenating file.\nWarning: THIS MAY BREAK THE CONCATENATED TRACK(S)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("force-cat", NULL, "skip media configuration check when concatenating file. \nWarning: THIS MAY BREAK THE CONCATENATED TRACK(S)", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("keep-sys", NULL, "keep all MPEG-4 Systems info when using [-add]() and [-cat]() (only used when adding IsoMedia files)", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("dref", NULL, "keep media data in original file using `data referencing`. The resulting file only contains the meta-data of the presentation (frame sizes, timing, etc...) and references media data in the original file. This is extremely useful when developping content, since importing and storage of the MP4 file is much faster and the resulting file much smaller.\nNote: Data referencing may fail on some files because it requires the framed data (eg an IsoMedia sample) to be continuous in the original file, which is not always the case depending on the original interleaving or bitstream format (__AVC__ or __HEVC__ cannot use this option)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("dref", NULL, "keep media data in original file using `data referencing`. The resulting file only contains the meta-data of the presentation (frame sizes, timing, etc...) and references media data in the original file. This is extremely useful when developping content, since importing and storage of the MP4 file is much faster and the resulting file much smaller. \nNote: Data referencing may fail on some files because it requires the framed data (eg an IsoMedia sample) to be continuous in the original file, which is not always the case depending on the original interleaving or bitstream format (__AVC__ or __HEVC__ cannot use this option)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("no-drop", NULL, "force constant FPS when importing AVI video", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("packed", NULL, "force packed bitstream when importing raw MPEG-4 part 2 Advanced Simple Profile", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("sbr", NULL, "backward compatible signaling of AAC-SBR", NULL, NULL, GF_ARG_BOOL, 0), @@ -394,168 +394,183 @@ GF_DEF_ARG("ps", NULL, "backward compatible signaling of AAC-PS", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("psx", NULL, "non-backward compatible signaling of AAC-PS", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("ovsbr", NULL, "oversample SBR import (SBR AAC, PS AAC and oversampled SBR cannot be detected at import time)", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("fps", NULL, "force frame rate for video and SUB subtitles import to the given value, expressed as a number or as `timescale-increment`.\nNote: For raw H263 import, default FPS is `15`, otherwise `25`\nWarning: This is ignored for ISOBMFF import, use `:rescale` option for that", "25", NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("fps", NULL, "force frame rate for video and SUB subtitles import to the given value, expressed as a number or as `timescale-increment`. \nNote: For raw H263 import, default FPS is `15`, otherwise `25`. This is ignored for ISOBMFF import, use `:rescale` option for that", "25", NULL, GF_ARG_STRING, 0), GF_DEF_ARG("mpeg4", NULL, "force MPEG-4 sample descriptions when possible. For AAC, forces MPEG-4 AAC signaling even if MPEG-2", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("agg", NULL, "aggregate N audio frames in 1 sample (3GP media only).\nNote: Maximum value is 15", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("agg", NULL, "aggregate N audio frames in 1 sample (3GP media only, maximum value is 15)", NULL, NULL, GF_ARG_INT, 0), {0} }; -void PrintImportUsage() -{ - u32 i=0; - gf_sys_format_help(helpout, help_flags, "# Importing Options\n" - "# File importing\n" - "Syntax is [-add]() / [-cat]() `filename[#FRAGMENT][:opt1...:optN=val]`\n" - "This process will create the destination file if not existing, and add the track(s) to it. If you wish to always create a new destination file, add [-new](MP4B_GEN).\n" - "The supported input media types depend on your installation, check [filters documentation](Filters) for more info.\n" - " \n" - "To select a desired media track, the following syntax is used:\n" - "- `-add inputFile#video`: adds the first video track in `inputFile`.\n" - "- `-add inputFile#audio`: adds the first audio track in `inputFile`.\n" - "- `-add inputFile#trackID=ID` or `-add inputFile#ID`: adds the specified track. For IsoMedia files, ID is the track ID. For other media files, ID is the value indicated by `MP4Box -info inputFile`.\n" - " \n" - "By default all imports are performed sequentially, and final interleaving is done at the end; this however requires a temporary file holding input isobmf file (if any) and added files before creating the final output. Since this can become quite large, it is possible to add media to a new file without temporary storage, using [-flat]() option, but this disables media interleaving.\n" - " \n" - "If you wish to create an interleaved new file with no temporary storage, use the [-newfs]() option. The interleaving might not be as precise as when using [-new]() since it is dependent on muxer input scheduling (each execution might lead to a slightly different result). \n" - " - Some muxing options (marked with `*` below) will be activated for all inputs (i.e. in this mode, it is not possible to import one AVC track with `xps_inband` and another without).\n" - " - Some muxing options (marked as `!` below) cannot be used in this mode as they require temporary storage for file edition.\n" - " - Usage of [-cat]() is possible in this mode, but concatenated sources will not be interleaved in the output . If you wish to perforom more complex cat/add operations without temp file, use the [gpac application](Filters).\n" - " \n" - "MP4Box can import a desired amount of the input file rather than the whole file. To do this, use the syntax `-add inputFile:dur=N`, where N is the number of seconds you wish to import from input. MP4Box cannot start importing from a random point in the input, it always import from the begining.\n" - "Note: When importing SRT or SUB files, MP4Box will choose default layout options to make the subtitle appear at the bottom of the video. You SHOULD NOT import such files before any video track is added to the destination file, otherwise the results will likelly not be useful (default SRT/SUB importing uses default serif font, fontSize 18 and display size 400x60). Check [TTXT doc](Subtitling-with-GPAC) for more details.\n" - " \n" - "When importing several tracks/sources in one pass, all options will be applied if relevant to each source. These options are set for all imported streams. If you need to specify these options par stream, set per-file options using the syntax `-add stream[:opt1:...:optN]`.\n" - " \n" - "" - "Allowed per-file options:\n" - "- #video, #audio: base import for most AV files\n" - "- #trackID=ID: track import for IsoMedia and other files\n" - "- #pid=ID: stream import from MPEG-2 TS\n" - "- :dur=D: `*` import only the specified duration from the media. D can be:\n" + +static GF_GPACArg ImportFileOpts [] = { + GF_DEF_ARG("dur", NULL, "`X` import only the specified duration from the media. Value can be:\n" " - positive float: specifies duration in seconds\n" " - fraction: specifies duration as NUM/DEN fraction\n" - " - negative integer: specifies duration in number of coded frames\n" - "- :lang=LAN: set imported media language code\n" - "- :delay=delay_ms: set imported media initial delay in ms\n" - "- :par=PAR: set visual pixel aspect ratio (see [-par](MP4B_GEN) )\n" - "- :clap=CLAP: set visual clean aperture (see [-clap](MP4B_GEN) )\n" - "- :mx=MX: sets track matrix (see [-mx](MP4B_GEN) )\n" - "- :name=NAME: set track handler name\n" - "- :ext=EXT: override file extension when importing\n" - "- :hdlr=code: set track handler type to the given code point (4CC)\n" - "- :disable: imported track(s) will be disabled\n" - "- :group=G: add the track as part of the G alternate group. If G is 0, the first available GroupID will be picked.\n" - "- :fps=VAL: same as [-fps]()\n" - "- :rap: `!` import only RAP samples\n" - "- :refs: `!` import only reference pictures\n" - "- :trailing: keep trailing 0-bytes in AVC/HEVC samples\n" - "- :agg=VAL: `*` same as [-agg]()\n" - "- :dref: `*` same as [-dref]()\n" - "- :keep_refs: keeps track reference when importing a single track\n" - "- :nodrop: same as [-nodrop]()\n" - "- :packed: `*` same as [-packed]()\n" - "- :sbr: same as [-sbr]()\n" - "- :sbrx: same as [-sbrx]()\n" - "- :ovsbr: same as [-ovsbr]()\n" - "- :ps: same as [-ps]()\n" - "- :psx: same as [-psx]()\n" - "- :asemode=MODE: `*` set the mode to create the AudioSampleEntry\n" + " - negative integer: specifies duration in number of coded frames", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("lang", NULL, "set imported media language code", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("delay", NULL, "set imported media initial delay in ms", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("par", NULL, "set visual pixel aspect ratio (see [-par](MP4B_GEN) )", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("clap", NULL, "set visual clean aperture (see [-clap](MP4B_GEN) )", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("mx", NULL, "set track matrix (see [-mx](MP4B_GEN) )", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("name", NULL, "set track handler name", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("ext", NULL, "override file extension when importing", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("hdlr", NULL, "set track handler type to the given code point (4CC)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("disable", NULL, "disable imported track(s)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("group", NULL, "add the track as part of the G alternate group. If G is 0, the first available GroupID will be picked", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("fps", NULL, "same as [-fps]()", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("rap", NULL, "`D` import only RAP samples", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("refs", NULL, "`D` import only reference pictures", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("trailing", NULL, "keep trailing 0-bytes in AVC/HEVC samples", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("agg", NULL, "`X` same as [-agg]()", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("dref", NULL, "`X` same as [-dref]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("keep_refs", NULL, "keep track reference when importing a single track", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("nodrop", NULL, "same as [-nodrop]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("packed", NULL, "`X` same as [-packed]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("sbr", NULL, "same as [-sbr]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("sbrx", NULL, "same as [-sbrx]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("ovsbr", NULL, "same as [-ovsbr]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("ps", NULL, "same as [-ps]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("psx", NULL, "same as [-psx]()", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("asemode", NULL, "`X` set the mode to create the AudioSampleEntry. Value can be:\n" " - v0-bs: use MPEG AudioSampleEntry v0 and the channel count from the bitstream (even if greater than 2) - default\n" " - v0-2: use MPEG AudioSampleEntry v0 and the channel count is forced to 2\n" " - v1: use MPEG AudioSampleEntry v1 and the channel count from the bitstream\n" - " - v1-qt: use QuickTime Sound Sample Description Version 1 and the channel count from the bitstream (even if greater than 2). This will also trigger using alis data references instead of url, even for non-audio tracks\n" - "- :audio_roll=N: add a roll sample group with roll_distance `N`\n" - "- :mpeg4: `*` same as [-mpeg4]() option\n" - "- :nosei: discard all SEI messages during import\n" - "- :svc: import SVC/LHVC with explicit signaling (no AVC base compatibility)\n" - "- :nosvc: discard SVC/LHVC data when importing\n" - "- :svcmode=MODE: `!` set SVC/LHVC import mode\n" + " - v1-qt: use QuickTime Sound Sample Description Version 1 and the channel count from the bitstream (even if greater than 2). This will also trigger using alis data references instead of url, even for non-audio tracks", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("audio_roll", NULL, "add a roll sample group with roll_distance `N`", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("mpeg4", NULL, "`X` same as [-mpeg4]() option", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("nosei", NULL, "discard all SEI messages during import", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("svc", NULL, "import SVC/LHVC with explicit signaling (no AVC base compatibility)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("nosvc", NULL, "discard SVC/LHVC data when importing", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("svcmode", NULL, "`D` set SVC/LHVC import mode. Value can be:\n" " - split: each layer is in its own track\n" " - merge: all layers are merged in a single track\n" " - splitbase: all layers are merged in a track, and the AVC base in another\n" " - splitnox: each layer is in its own track, and no extractors are written\n" - " - splitnoxib: each layer is in its own track, no extractors are written, using inband param set signaling\n" - "- :temporal: `!` set HEVC/LHVC temporal sublayer import mode\n" + " - splitnoxib: each layer is in its own track, no extractors are written, using inband param set signaling", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("temporal", NULL, "`D` set HEVC/LHVC temporal sublayer import mode. Value can be:\n" " - split: each sublayer is in its own track\n" " - splitbase: all sublayers are merged in a track, and the HEVC base in another\n" - " - splitnox: each layer is in its own track, and no extractors are written\n" - "- :subsamples: add SubSample information for AVC+SVC\n" - "- :deps: import sample dependency information for AVC and HEVC\n" - "- :ccst: add default HEIF ccst box to visual sample entry\n" - "- :forcesync: force non IDR samples with I slices to be marked as sync points (AVC GDR)\n" - "Warning: RESULTING FILE IS NOT COMPLIANT WITH THE SPEC but will fix seeking in most players\n" - "- :xps_inband: `*` set xPS inband for AVC/H264 and HEVC (for reverse operation, re-import from raw media)\n" - "- :xps_inbandx: `*` same as xps_inband and also keep first xPS in sample desciption\n" - "- :au_delim: keep AU delimiter NAL units in the imported file\n" - "- :max_lid=N: set HEVC max layer ID to be imported to `N` (by default imports all layers)\n" - "- :max_tid=N: set HEVC max temporal ID to be imported to `N` (by default imports all temporal sublayers)\n" - "- :tiles: add HEVC tiles signaling and NALU maps without splitting the tiles into different tile tracks\n" - "- :split_tiles: `!` split HEVC tiles into different tile tracks, one tile (or all tiles of one slice) per track.\n" - "- :negctts: use negative CTS-DTS offsets (ISO4 brand)\n" - "- :chap: specify the track is a chapter track\n" - "- :chapter=NAME: add a single chapter (old nero format) with given name lasting the entire file\n" - "- :chapfile=file: adds a chapter file (old nero format)\n" - "- :layout=WxHxXxY: specify the track layout\n" + " - splitnox: each layer is in its own track, and no extractors are written", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("subsamples", NULL, "add SubSample information for AVC+SVC", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("deps", NULL, "import sample dependency information for AVC and HEVC", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("ccst", NULL, "add default HEIF ccst box to visual sample entry", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("forcesync", NULL, "force non IDR samples with I slices to be marked as sync points (AVC GDR)\n" + "Warning: RESULTING FILE IS NOT COMPLIANT WITH THE SPEC but will fix seeking in most players", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("xps_inband", NULL, "`X` set xPS inband for AVC/H264 and HEVC (for reverse operation, re-import from raw media)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("xps_inbandx", NULL, "`X` same as xps_inband and also keep first xPS in sample desciption", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("au_delim", NULL, "keep AU delimiter NAL units in the imported file", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("max_lid", NULL, "set HEVC max layer ID to be imported to `N` (by default imports all layers)", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("max_tid", NULL, "set HEVC max temporal ID to be imported to `N` (by default imports all temporal sublayers)", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("tiles", NULL, "add HEVC tiles signaling and NALU maps without splitting the tiles into different tile tracks", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("split_tiles", NULL, "`D` split HEVC tiles into different tile tracks, one tile (or all tiles of one slice) per track", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("negctts", NULL, "use negative CTS-DTS offsets (ISO4 brand)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("chap", NULL, "specify the track is a chapter track", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("chapter", NULL, "add a single chapter (old nero format) with given name lasting the entire file", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("chapfile", NULL, "add a chapter file (old nero format)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("layout", NULL, "specify the track layout as WxHxXxY\n" " - if W (resp H) = 0: the max width (resp height) of the tracks in the file are used\n" " - if Y=-1: the layout is moved to the bottom of the track area\n" - " - X and Y can be omitted: `:layout=WxH`\n" - "- :rescale=TS: force media timescale to TS !! changes the media duration\n" - "- :timescale=TS: set imported media timescale to TS.\n" - "- :moovts=TS: set movie timescale to TS. A negative value picks the media timescale of the first track imported.\n" - "- :noedit: `*` do not set edit list when importing B-frames video tracks\n" - "- :rvc=FILENAME: set RVC configuration for the media\n" - "- :fmt=FORMAT: override format detection with given format (cf BT/XMTA doc)\n" - "- :profile=INT: override AVC profile\n" - "- :level=INT: override AVC level\n" - "- :novpsext: remove VPS extensions from HEVC VPS\n" - "- :keepav1t: keep AV1 temporal delimiter OBU in samples, might help if source file had losses\n" - "- :font=name: specify font name for text import (default `Serif`)\n" - "- :size=s: specify font size for text import (default `18`)\n" - "- :text_layout=WxHxXxY: specify the track text layout\n" - " - if W (resp H) = 0: the max width (resp height) of the tracks in the file are used.\n" + " - X and Y can be omitted: `:layout=WxH`", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("rescale", NULL, "force media timescale to TS !! changes the media duration", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("timescale", NULL, "set imported media timescale to TS", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("moovts", NULL, "set movie timescale to TS. A negative value picks the media timescale of the first track imported", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("noedit", NULL, "`X` do not set edit list when importing B-frames video tracks", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("rvc", NULL, "set RVC configuration for the media", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("fmt", NULL, "override format detection with given format (cf BT/XMTA doc)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("profile", NULL, "override AVC profile", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("level", NULL, "override AVC level", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("novpsext", NULL, "remove VPS extensions from HEVC VPS", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("keepav1t", NULL, "keep AV1 temporal delimiter OBU in samples, might help if source file had losses", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("font", NULL, "specify font name for text import (default `Serif`)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("size", NULL, "specify font size for text import (default `18`)", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("text_layout", NULL, "specify the track text layout as WxHxXxY\n" + " - if W (resp H) = 0: the max width (resp height) of the tracks in the file are used\n" " - if Y=-1: the layout is moved to the bottom of the track area\n" - " - X and Y can be omitted: `:layout=WxH`\n" - "- :swf-global: all SWF defines are placed in first scene replace rather than when needed\n" - "- :swf-no-ctrl: use a single stream for movie control and dictionary (this will disable ActionScript)\n" - "- :swf-no-text: remove all SWF text\n" - "- :swf-no-font: remove all embedded SWF Fonts (local playback host fonts used)\n" - "- :swf-no-line: remove all lines from SWF shapes\n" - "- :swf-no-grad: remove all gradients from SWF shapes\n" - "- :swf-quad: use quadratic bezier curves instead of cubic ones\n" - "- :swf-xlp: support for lines transparency and scalability\n" - "- :swf-ic2d: use indexed curve 2D hardcoded proto\n" - "- :swf-same-app: appearance nodes are reused\n" - "- :swf-flatten=ang: complementary angle below which 2 lines are merged, `0` means no flattening\n" - "- :kind=schemeURI=value: set kind for the track\n" - "- :txtflags=flags: set display flags (hexa number) of text track\n" - "- :txtflags+=flags: add display flags (hexa number) to text track\n" - "- :txtflags-=flags: remove display flags (hexa number) from text track\n" - "- :rate=VAL: force average rate and max rate to VAL (in bps) in btrt box. If 0, removes btrt box\n" - "- :stz2: use compact size table (for low-bitrates)\n" - "- :bitdepth=VAL: set bit depth to VAL for imported video content (default is 24)\n" - "- :colr=OPT: set color profile for imported video content (see ISO/IEC 23001-8). `OPT` is formatted as:\n" + " - X and Y can be omitted: `:layout=WxH`", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("swf-global", NULL, "all SWF defines are placed in first scene replace rather than when needed", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-no-ctrl", NULL, "use a single stream for movie control and dictionary (this will disable ActionScript)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-no-text", NULL, "remove all SWF text", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-no-font", NULL, "remove all embedded SWF Fonts (local playback host fonts used)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-no-line", NULL, "remove all lines from SWF shapes", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-no-grad", NULL, "remove all gradients from SWF shapes", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-quad", NULL, "use quadratic bezier curves instead of cubic ones", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-xlp", NULL, "support for lines transparency and scalability", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-ic2d", NULL, "use indexed curve 2D hardcoded proto", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-same-app", NULL, "appearance nodes are reused", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("swf-flatten", NULL, "complementary angle below which 2 lines are merged, `0` means no flattening", NULL, NULL, GF_ARG_DOUBLE, 0), + GF_DEF_ARG("kind", NULL, "set kind for the track as `schemeURI=value`", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("txtflags", NULL, "set display flags (hexa number) of text track. Use `txtflags+=FLAGS` to add flags and `txtflags-=FLAGS` to remove flags", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("rate", NULL, "force average rate and max rate to VAL (in bps) in btrt box. If 0, removes btrt box", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("stz2", NULL, "use compact size table (for low-bitrates)", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("bitdepth", NULL, "set bit depth to VAL for imported video content (default is 24)", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("colr", NULL, "set color profile for imported video content (see ISO/IEC 23001-8). Value is formatted as:\n" " - nclc,p,t,m: with p colour primary, t transfer characteristics and m matrix coef\n" " - nclx,p,t,m,r: same as `nclx` with r full range flag\n" " - prof,path: with path indicating the file containing the ICC color profile\n" - " - rICC,path: with path indicating the file containing the restricted ICC color profile\n" - "- :dv-profile=VAL: set the Dolby Vision profile\n" - "- :tc=VAL: inject a single QT timecode. `VAL` is formated as:\n" + " - rICC,path: with path indicating the file containing the restricted ICC color profile", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("dv-profile", NULL, "set the Dolby Vision profile", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("tc", NULL, "inject a single QT timecode. Value is formated as:\n" " - [d]FPS[/FPS_den],h,m,s,f[,framespertick]: optional drop flag, framerate (integer or fractional), hours, minutes, seconds and frame number\n" " - : `d` is an optional flag used to indicate that the counter is in drop-frame format\n" - " - : the `framespertick` is optional and defaults to round(framerate); it indicates the number of frames per counter tick\n" - "- :lastsampdur[=VAL]\" sets duration of the last sample. `VAL` is formated as:\n" + " - : the `framespertick` is optional and defaults to round(framerate); it indicates the number of frames per counter tick", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("lastsampdur", NULL, "set duration of the last sample. Value is formated as:\n" " - no value: use the previous sample duration\n" " - integer: indicate the duration in milliseconds\n" - " - N/D: indicate the duration as fractional second\n" - "- :fstat: print filter session stats after import\n" - "- :fgraph: print filter session graph after import\n" - "- :sopt:[OPTS]: set `OPTS` as additional arguments to source filter. `OPTS` can be any usual filter argument, see [filter doc `gpac -h doc`](Filters)\n" - "- :dopt:[OPTS]: `*` set `OPTS` as additional arguments to [destination filter](mp4mx). OPTS can be any usual filter argument, see [filter doc `gpac -h doc`](Filters)\n" - "- @@f1[:args][@@fN:args]: set a filter chain to insert before the muxer. Each filter in the chain is formatted as a regular filter, see [filter doc `gpac -h doc`](Filters). If several filters are set, they will be chained in the given order. The last filter shall not have any Filter ID specified\n" - "\n" + " - N/D: indicate the duration as fractional second", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("fstat", NULL, "print filter session stats after import", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("fgraph", NULL, "print filter session graph after import", NULL, NULL, GF_ARG_BOOL, 0), + {"sopt:[OPTS]", NULL, "set `OPTS` as additional arguments to source filter. `OPTS` can be any usual filter argument, see [filter doc `gpac -h doc`](Filters)"}, + {"dopt:[OPTS]", NULL, "`X` set `OPTS` as additional arguments to [destination filter](mp4mx). OPTS can be any usual filter argument, see [filter doc `gpac -h doc`](Filters)"}, + {"@@f1[:args][@@fN:args]", NULL, "set a filter chain to insert before the muxer. Each filter in the chain is formatted as a regular filter, see [filter doc `gpac -h doc`](Filters). If several filters are set, they will be chained in the given order. The last filter shall not have any Filter ID specified"}, + {0} +}; + +void PrintImportUsage() +{ + u32 i; + + gf_sys_format_help(helpout, help_flags, "# Importing Options\n" + "# File importing\n" + "Syntax is [-add]() / [-cat]() `filename[#FRAGMENT][:opt1...:optN=val]`\n" + "This process will create the destination file if not existing, and add the track(s) to it. If you wish to always create a new destination file, add [-new](MP4B_GEN).\n" + "The supported input media types depend on your installation, check [filters documentation](Filters) for more info.\n" + " \n" + "To select a desired media track from a source, a fragment identifier '#' can be specified, bfore any other options. The following syntax is used:\n" + "- `#video`: adds the first video track found in source\n" + "- `#audio`: adds the first audio track found in source\n" + "- `#auxv`: adds the first auxiliary video track found in source\n" + "- `#pict`: adds the first picture track found in source\n" + "- `#trackID=ID` or `#ID`: adds the specified track. For IsoMedia files, ID is the track ID. For other media files, ID is the value indicated by `MP4Box -info inputFile`\n" + "- `#pid=ID`: number of desired PID for MPEG-2 TS sources\n" + "- `#prog_id=ID`: number of desired program for MPEG-2 TS sources\n" + "- `#program=NAME`: name of desired program for MPEG-2 TS sources\n" + " \n" + "By default all imports are performed sequentially, and final interleaving is done at the end; this however requires a temporary file holding original ISOBMF file (if any) and added files before creating the final output. Since this can become quite large, it is possible to add media to a new file without temporary storage, using [-flat](MP4B_GEN) option, but this disables media interleaving.\n" + " \n" + "If you wish to create an interleaved new file with no temporary storage, use the [-newfs](MP4B_GEN) option. The interleaving might not be as precise as when using [-new]() since it is dependent on muxer input scheduling (each execution might lead to a slightly different result). Additionally in this mode: \n" + " - Some muxing options (marked with `X` below) will be activated for all inputs (e.g it is not possible to import one AVC track with `xps_inband` and another without).\n" + " - Some muxing options (marked as `D` below) cannot be used as they require temporary storage for file edition.\n" + " - Usage of [-cat]() is possible, but concatenated sources will not be interleaved in the output. If you wish to perforom more complex cat/add operations without temp file, use the [gpac application](Filters).\n" + " \n" + "Note: MP4Box cannot start importing from a random point in the input, it always import from the begining. If you wish to import from another point in the source, use the [gpac application](Filters).\n" + " \n" + "Note: When importing SRT or SUB files, MP4Box will choose default layout options to make the subtitle appear at the bottom of the video. You SHOULD NOT import such files before any video track is added to the destination file, otherwise the results will likelly not be useful (default SRT/SUB importing uses default serif font, fontSize 18 and display size 400x60). For more details, check [TTXT doc](Subtitling-with-GPAC).\n" + " \n" + "When importing several tracks/sources in one pass, all options will be applied if relevant to each source. These options are set for all imported streams. If you need to specify these options par stream, set per-file options using the syntax `-add stream[:opt1:...:optN]`. Allowed per-file options:\n\n" + ); + + i=0; + while (ImportFileOpts[i].name) { + GF_GPACArg *arg = &ImportFileOpts[i]; + i++; + gf_sys_print_arg(helpout, help_flags | GF_PRINTARG_NO_DASH, arg, "mp4box-import"); + } + + gf_sys_format_help(helpout, help_flags, "\n" "Note: `sopt`, `dopt` and `@@f` must be placed after all other options.\n" "# Global import options\n" ); + + i=0; while (m4b_imp_args[i].name) { GF_GPACArg *arg = &m4b_imp_args[i]; i++; @@ -567,9 +582,9 @@ { GF_DEF_ARG("mp4", NULL, "specify input file is for encoding", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("def", NULL, "encode DEF names in BIFS", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("sync", NULL, "force BIFS sync sample generation every given time in ms.\nNote: cannot be used with [-shadow]()", NULL, NULL, GF_ARG_INT, 0), - GF_DEF_ARG("shadow", NULL, "force BIFS sync shadow sample generation every given time in ms.\nNote: cannot be used with [-sync]()", NULL, NULL, GF_ARG_INT, 0), - GF_DEF_ARG("log", NULL, "generate scene codec log file if available", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("sync", NULL, "force BIFS sync sample generation every given time in ms (cannot be used with [-shadow]() )", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("shadow", NULL, "force BIFS sync shadow sample generation every given time in ms (cannot be used with [-sync]() )", NULL, NULL, GF_ARG_INT, 0), + GF_DEF_ARG("sclog", NULL, "generate scene codec log file if available", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("ms", NULL, "import tracks from the given file", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("ctx-in", NULL, "specify initial context (MP4/BT/XMT) file for chunk processing. Input file must be a commands-only file", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("ctx-out", NULL, "specify storage of updated context (MP4/BT/XMT) file for chunk processing, optional", NULL, NULL, GF_ARG_STRING, 0), @@ -634,7 +649,7 @@ GF_GPACArg m4b_hint_args[] = { GF_DEF_ARG("hint", NULL, "hint the file for RTP/RTSP", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("hint", NULL, "specify RTP MTU (max size) in bytes (this includes 12 bytes RTP header)", "1450", NULL, GF_ARG_INT, 0), + GF_DEF_ARG("mtu", NULL, "specify RTP MTU (max size) in bytes (this includes 12 bytes RTP header)", "1450", NULL, GF_ARG_INT, 0), GF_DEF_ARG("copy", NULL, "copy media data to hint track rather than reference (speeds up server but takes much more space)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("multi `[maxptime]`", NULL, "enable frame concatenation in RTP packets if possible (with max duration 100 ms or `maxptime` ms if given)", NULL, NULL, GF_ARG_INT, 0), GF_DEF_ARG("rate", NULL, "specify rtp rate in Hz when no default for payload", "90000", NULL, GF_ARG_INT, 0), @@ -642,6 +657,7 @@ GF_DEF_ARG("latm", NULL, "force MPG4-LATM transport for AAC streams", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("static", NULL, "enable static RTP payload IDs whenever possible (by default, dynamic payloads are always used)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("add-sdp", NULL, "add given SDP string to hint track (`tkID:string`) or movie (`string`)", NULL, NULL, GF_ARG_STRING, 0), + GF_DEF_ARG("no-offset", NULL, "signal no random offset for sequence number and timestamp (support will depend on server)", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("unhint", NULL, "remove all hinting information from file", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("group-single", NULL, "put all tracks in a single hint group", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("ocr", NULL, "force all MPEG-4 streams to be synchronized (MPEG-4 Systems only)", NULL, NULL, GF_ARG_BOOL, 0), @@ -740,8 +756,9 @@ GF_DEF_ARG("dsapp", NULL, "same as [-dsap]() but only print presentation time", NULL, NULL, GF_ARG_INT, 0), GF_DEF_ARG("dcr", NULL, "dump ISMACryp samples structure to XML output", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("dump-cover", NULL, "extract cover art", NULL, NULL, GF_ARG_BOOL, 0), - GF_DEF_ARG("dump-chap", NULL, "extract chapter file", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("dump-chap", NULL, "extract chapter file as TTXT format", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("dump-chap-ogg", NULL, "extract chapter file as OGG format", NULL, NULL, GF_ARG_BOOL, 0), + GF_DEF_ARG("dump-chap-zoom", NULL, "extract chapter file as zoom format", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("dump-udta `[tkID:]4cc`", NULL, "extract udta for the given 4CC. If `tkID` is given, dumps from UDTA of the given track ID, otherwise moov is used", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("mergevtt", NULL, "merge vtt cues while dumping", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("ttxt", NULL, "convert input subtitle to GPAC TTXT format if no parameter. Otherwise, dump given text track to GPAC TTXT format", NULL, NULL, GF_ARG_INT, 0), @@ -903,7 +920,7 @@ void PrintCoreUsage() { gf_sys_format_help(helpout, help_flags, "# libgpac core options\n"); - gf_sys_print_core_help(NULL, 0, GF_ARGMODE_ALL, 0); + gf_sys_print_core_help(helpout, 0, GF_ARGMODE_ALL, 0); } GF_GPACArg m4b_usage_args[] = @@ -922,10 +939,12 @@ "- format: supported formats help\n" "- live: BIFS streamer help\n" "- core: libgpac core options\n" - "- all: all options are printed\n" + "- all: print all the above help screens\n" + "- opts: print all options\n" "- VAL: search for option named `VAL` (without `-` or `--`) in MP4Box, libgpac core and all filters\n" , NULL, NULL, GF_ARG_STRING, 0), - + GF_DEF_ARG("hx", NULL, "look for given string in all possible options" + , NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("nodes", NULL, "list supported MPEG4 nodes", NULL, NULL, GF_ARG_BOOL, 0), GF_DEF_ARG("node", NULL, "get given MPEG4 node syntax and QP infolist", NULL, NULL, GF_ARG_STRING, 0), GF_DEF_ARG("xnodes", NULL, "list supported X3D nodes", NULL, NULL, GF_ARG_BOOL, 0), @@ -955,51 +974,98 @@ } } -static u32 PrintHelpForArgs(char *arg_name, GF_GPACArg *args, Bool exact_match) +enum +{ + SEARCH_ARG_EXACT, + SEARCH_ARG_CLOSE, + SEARCH_DESC, +}; + +static Bool strstr_nocase(const char *text, const char *subtext, u32 subtext_len) +{ + if (!*text || !subtext || !subtext_len) + return GF_FALSE; + + while (*text) { + if (tolower(*text) == *subtext) { + if (!strnicmp(text, subtext, subtext_len)) + return GF_TRUE; + + } + text++; + } + return GF_FALSE; +} + +static u32 PrintHelpForArgs(char *arg_name, GF_GPACArg *args, u32 search_type) { u32 res=0; u32 i=0; + u32 alen = (u32) strlen(arg_name); while (args[i].name) { + u32 flags=0; GF_GPACArg *arg = &args[i]; GF_GPACArg an_arg; - if (exact_match && strcmp(arg_name, arg->name)) { + Bool do_match = GF_FALSE; + + if (args==ImportFileOpts) { + flags = GF_PRINTARG_COLON; + if (!strncmp(arg_name, arg->name, alen) && ((arg->name[alen]==0) || (arg->name[alen]=='='))) + do_match = GF_TRUE; + } + else if (!strcmp(arg_name, arg->name)) + do_match = GF_TRUE; + else if ((alen < (u32) strlen(arg->name)) && (arg->name[alen]==' ') && !strncmp(arg_name, arg->name, alen)) + do_match = GF_TRUE; + + if (arg_name[0] == '@') + do_match = GF_TRUE; + + if ((search_type==SEARCH_ARG_EXACT) && !do_match) { + i++; + continue; + } + if ((search_type==SEARCH_ARG_CLOSE) && !gf_sys_word_match(arg_name, arg->name)) { i++; continue; } - if (!exact_match && !gf_sys_word_match(arg_name, arg->name)) { + if ((search_type==SEARCH_DESC) && !strstr_nocase(arg->description, arg_name, alen)) { i++; continue; } + an_arg = *arg; - if (!exact_match) { + if (search_type!=SEARCH_ARG_EXACT) { an_arg.description = NULL; an_arg.type = GF_ARG_BOOL; } - gf_sys_print_arg(helpout, 0, &an_arg, ""); + gf_sys_print_arg(helpout, flags, &an_arg, ""); res++; i++; } return res; } -static Bool PrintHelpArg(char *arg_name, Bool exact_match, GF_FilterSession *fs) +static Bool PrintHelpArg(char *arg_name, u32 search_type, GF_FilterSession *fs) { Bool first=GF_TRUE; GF_GPACArg an_arg; u32 i, count; u32 res = 0; - res += PrintHelpForArgs(arg_name, m4b_gen_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_dash_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_imp_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_senc_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_crypt_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_hint_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_extr_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_dump_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_meta_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_swf_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_liveenc_args, exact_match); - res += PrintHelpForArgs(arg_name, m4b_usage_args, exact_match); - res += PrintHelpForArgs(arg_name, (GF_GPACArg *) gf_sys_get_options(), exact_match); + u32 alen = (u32) strlen(arg_name); + res += PrintHelpForArgs(arg_name, m4b_gen_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_dash_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_imp_args, search_type); + res += PrintHelpForArgs(arg_name, ImportFileOpts, search_type); + res += PrintHelpForArgs(arg_name, m4b_senc_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_crypt_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_hint_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_extr_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_dump_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_meta_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_swf_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_liveenc_args, search_type); + res += PrintHelpForArgs(arg_name, m4b_usage_args, search_type); + res += PrintHelpForArgs(arg_name, (GF_GPACArg *) gf_sys_get_options(), search_type); if (!fs) return res; @@ -1014,11 +1080,16 @@ const GF_FilterArgs *arg = ®->args[j]; if (!arg || !arg->arg_name) break; j++; - if (exact_match && strcmp(arg->arg_name, arg_name)) continue; - if (!exact_match && !gf_sys_word_match(arg->arg_name, arg_name)) continue; + if ((search_type==SEARCH_ARG_EXACT) && strcmp(arg->arg_name, arg_name)) continue; + + if ((search_type==SEARCH_ARG_CLOSE) && !gf_sys_word_match(arg->arg_name, arg_name)) continue; + + if (search_type==SEARCH_DESC) { + if (!strstr_nocase(arg->arg_desc, arg_name, alen)) continue; + } an_arg.name = arg->arg_name; - if (exact_match) { + if (search_type==SEARCH_ARG_EXACT) { an_arg.description = arg->arg_desc; switch (arg->arg_type) { case GF_PROP_BOOL: @@ -1060,7 +1131,7 @@ return GF_FALSE; } -static void PrintHelp(char *arg_name) +static void PrintHelp(char *arg_name, Bool search_desc, Bool no_match) { GF_FilterSession *fs; Bool res; @@ -1070,12 +1141,20 @@ if (arg_name[0]=='-') arg_name++; - res = PrintHelpArg(arg_name, GF_TRUE, fs); - if (!res) { - GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Option -%s unknown, please check usage.\n", arg_name)); - GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Possible options are:\n")); + if (search_desc) { + char *_arg_name = gf_strdup(arg_name); + strlwr(_arg_name); + GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Possible options mentionning `%s`:\n", arg_name)); + PrintHelpArg(_arg_name, SEARCH_DESC, fs); + gf_free(_arg_name); + } else { + res = no_match ? GF_FALSE : PrintHelpArg(arg_name, SEARCH_ARG_EXACT, fs); + if (!res) { + GF_LOG(GF_LOG_ERROR, GF_LOG_APP, ("Option -%s unknown, please check usage.\n", arg_name)); + GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Possible options are:\n")); - PrintHelpArg(arg_name, GF_FALSE, fs); + PrintHelpArg(arg_name, SEARCH_ARG_CLOSE, fs); + } } if (fs) gf_fs_del(fs); @@ -1121,7 +1200,7 @@ /*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, Bool single_group) +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, Bool hint_no_offset) { GF_ESD *esd; GF_InitialObjectDescriptor *iod; @@ -1255,6 +1334,10 @@ } continue; } + + if (hint_no_offset) + gf_hinter_track_force_no_offsets(hinter); + bw = gf_hinter_track_get_bandwidth(hinter); tot_bw += bw; flags = gf_hinter_track_get_flags(hinter); @@ -2379,8 +2462,8 @@ #endif Double mpd_live_duration = 0; Bool HintIt, needSave, FullInter, Frag, HintInter, dump_rtp, regular_iod, remove_sys_tracks, remove_hint, remove_root_od; -Bool print_sdp, open_edit, dump_cr, force_ocr, encode, do_log, dump_srt, dump_ttxt, do_saf, dump_m2ts, dump_cart, do_hash, verbose, force_cat, align_cat, pack_wgt, single_group, clean_groups, dash_live, no_fragments_defaults, single_traf_per_moof, tfdt_per_traf, hls_clock, do_mpd_rip, merge_vtt_cues, compress_moov, get_nb_tracks; -char *inName, *outName, *mediaSource, *tmpdir, *input_ctx, *output_ctx, *drm_file, *avi2raw, *cprt, *chap_file, *pes_dump, *itunes_tags, *pack_file, *raw_cat, *seg_name, *dash_ctx_file, *compress_top_boxes, *high_dynamc_range_filename, *use_init_seg, *box_patch_filename; +Bool print_sdp, open_edit, dump_cr, force_ocr, encode, do_scene_log, dump_srt, dump_ttxt, do_saf, dump_m2ts, dump_cart, do_hash, verbose, force_cat, align_cat, pack_wgt, single_group, clean_groups, dash_live, no_fragments_defaults, single_traf_per_moof, tfdt_per_traf, hls_clock, do_mpd_rip, merge_vtt_cues, compress_moov, get_nb_tracks; +static char *inName, *outName, *mediaSource, *tmpdir, *input_ctx, *output_ctx, *drm_file, *avi2raw, *cprt, *chap_file, *pes_dump, *itunes_tags, *pack_file, *raw_cat, *seg_name, *dash_ctx_file, *compress_top_boxes, *high_dynamc_range_filename, *use_init_seg, *box_patch_filename; u32 track_dump_type, dump_isom, dump_timestamps, dump_nal_type; GF_ISOTrackID trackID; u32 do_flat, box_patch_trackID=0, print_info; @@ -2408,7 +2491,8 @@ Bool chunk_mode = GF_FALSE; #endif #ifndef GPAC_DISABLE_ISOM_HINTING -Bool HintCopy = 0; +Bool HintCopy = GF_FALSE; +Bool hint_no_offset = GF_FALSE; u32 MTUSize = 1450; #endif #ifndef GPAC_DISABLE_CORE_TOOLS @@ -2589,6 +2673,7 @@ remove_hint = 1; } else if (!stricmp(arg, "-copy")) HintCopy = 1; + else if (!stricmp(arg, "-no-offset")) hint_no_offset = GF_TRUE; else if (!stricmp(arg, "-tight")) { FullInter = 1; open_edit = GF_TRUE; @@ -3115,8 +3200,8 @@ else if (!stricmp(arg, "-saf")) { do_saf = GF_TRUE; } - else if (!stricmp(arg, "-log")) { - do_log = GF_TRUE; + else if (!stricmp(arg, "-sclog")) { + do_scene_log = GF_TRUE; } #ifndef GPAC_DISABLE_MPD else if (!stricmp(arg, "-mpd")) { @@ -3418,6 +3503,8 @@ return 1; } else if (!stricmp(arg, "-h")) { + gf_sys_set_args(argc, (const char**) argv); + if (i + 1 == (u32)argc) PrintUsage(); else if (!strcmp(argv[i + 1], "general")) PrintGeneralUsage(); else if (!strcmp(argv[i + 1], "extract")) PrintExtractUsage(); @@ -3431,7 +3518,7 @@ else if (!strcmp(argv[i + 1], "meta")) PrintMetaUsage(); else if (!strcmp(argv[i + 1], "swf")) PrintSWFUsage(); #if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_SENG) - else if (!strcmp(argv[i + 1], "rtp")) fprintf(stderr, "RTP streaming deprecated in MP4Box, use gpac applications\n"); + else if (!strcmp(argv[i + 1], "rtp")) fprintf(stderr, "RTP streaming deprecated in MP4Box, use gpac application\n"); else if (!strcmp(argv[i + 1], "live")) PrintLiveUsage(); #endif else if (!strcmp(argv[i + 1], "core")) PrintCoreUsage(); @@ -3450,11 +3537,18 @@ PrintLiveUsage(); #endif PrintCoreUsage(); + } else if (!strcmp(argv[i + 1], "opts")) { + PrintHelp("@", GF_FALSE, GF_FALSE); } else { - PrintHelp(argv[i+1]); + PrintHelp(argv[i+1], GF_FALSE, GF_FALSE); } return 1; } + else if (!stricmp(arg, "-hx")) { + if (i + 1 == (u32)argc) PrintUsage(); + else PrintHelp(argv[i+1], GF_TRUE, GF_FALSE); + return 1; + } else if (!strcmp(arg, "-genmd")) { help_flags = GF_PRINTARG_MD | GF_PRINTARG_IS_APP; helpout = gf_fopen("mp4box-gen-opts.md", "w"); @@ -3566,7 +3660,7 @@ else if (!live_scene) { u32 res = gf_sys_is_gpac_arg(arg); if (res==0) { - PrintHelp(arg); + PrintHelp(arg, GF_FALSE, GF_TRUE); return 2; } else if (res==2) { i++; @@ -3798,6 +3892,7 @@ else if (!stricmp(arg, "-dump-cover")) dump_cart = 1; else if (!stricmp(arg, "-dump-chap")) dump_chap = 1; else if (!stricmp(arg, "-dump-chap-ogg")) dump_chap = 2; + else if (!stricmp(arg, "-dump-chap-zoom")) dump_chap = 3; else if (!stricmp(arg, "-hash")) do_hash = GF_TRUE; else if (!strnicmp(arg, "-comp", 5)) { CHECK_NEXT_ARG @@ -4341,7 +4436,7 @@ split_size = 0; movie_time = 0; dump_nal = dump_saps = dump_saps_mode = force_new = 0; - FullInter = HintInter = encode = do_log = old_interleave = do_saf = do_hash = verbose = do_mpd_rip = merge_vtt_cues = get_nb_tracks = GF_FALSE; + FullInter = HintInter = encode = do_scene_log = old_interleave = do_saf = do_hash = verbose = do_mpd_rip = merge_vtt_cues = get_nb_tracks = GF_FALSE; #ifndef GPAC_DISABLE_SCENE_DUMP dump_mode = GF_SM_DUMP_NONE; #endif @@ -4412,7 +4507,7 @@ if (argc < 2) { fprintf(stderr, "Not enough arguments - check usage with -h\n" "MP4Box - GPAC version %s\n" - "%s\n", gf_gpac_version(), gf_gpac_copyright()); + "%s\n", gf_gpac_version(), gf_gpac_copyright_cite()); gf_sys_close(); return 0; } @@ -4791,9 +4886,30 @@ char *src = argv[i+1]; while (src) { - char *sep = strchr(src, '+'); - if (sep) { + char *loc_src = src; + char *sep = NULL; + while (1) { + char *opt_sep; + sep = strchr(loc_src, '+'); + if (!sep) break; + sep[0] = 0; + if (strstr(src, "://")) + break; + + opt_sep = gf_url_colon_suffix(src); + if (opt_sep) + opt_sep[0] = 0; + if (gf_file_exists(src)) { + if (opt_sep) + opt_sep[0] = ':'; + break; + } + if (opt_sep) + opt_sep[0] = ':'; + + sep[0] = '+'; + loc_src = sep+1; } e = import_file(file, src, import_flags, import_fps, agg_samples, fs, (fs && (ipass==0)) ? &margs : NULL, tk_idx); @@ -4909,7 +5025,7 @@ else if (encode) { #if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT) FILE *logs = NULL; - if (do_log) { + if (do_scene_log) { char alogfile[GF_MAX_PATH]; strcpy(alogfile, inName); if (strchr(alogfile, '.')) { @@ -5342,7 +5458,7 @@ conv_type = GF_ISOM_CONV_TYPE_IPOD; else if (!stricmp(szExt, ".psp")) conv_type = GF_ISOM_CONV_TYPE_PSP; - else if (!stricmp(szExt, ".mov")) + else if (!stricmp(szExt, ".mov") || !stricmp(szExt, ".qt")) conv_type = GF_ISOM_CONV_TYPE_MOV; //remove extension from outfile @@ -5406,7 +5522,7 @@ #ifndef GPAC_DISABLE_SCENE_DUMP if (dump_mode != GF_SM_DUMP_NONE) { - e = dump_isom_scene(inName, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE, dump_mode, do_log, no_odf_conf); + e = dump_isom_scene(inName, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE, dump_mode, do_scene_log, no_odf_conf); if (e) goto err_exit; } #endif @@ -5473,13 +5589,13 @@ #endif if (dump_cart) dump_isom_cover_art(file, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE); - if (dump_chap) dump_isom_chapters(file, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE,(dump_chap==2) ? 1 : 0); + if (dump_chap) dump_isom_chapters(file, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE, dump_chap); if (dump_udta_type) dump_isom_udta(file, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE, dump_udta_type, dump_udta_track); if (dump_iod) { GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *)gf_isom_get_root_od(file); if (!iod) { - fprintf(stderr, "File %s has no IOD", inName); + fprintf(stderr, "File %s has no IOD\n", inName); } else { char szName[GF_MAX_PATH+10]; FILE *iodf; @@ -5645,7 +5761,7 @@ break; case META_ACTION_SET_XML: case META_ACTION_SET_BINARY_XML: - e = gf_isom_set_meta_xml(file, meta->root_meta, tk, meta->szPath, (meta->act_type==META_ACTION_SET_BINARY_XML) ? 1 : 0); + e = gf_isom_set_meta_xml(file, meta->root_meta, tk, meta->szPath, NULL, 0, (meta->act_type==META_ACTION_SET_BINARY_XML) ? 1 : 0); needSave = GF_TRUE; break; case META_ACTION_REM_XML: @@ -6077,14 +6193,17 @@ case GF_ISOM_ITUNE_COVER_ART: { u8 *d=NULL; + e = GF_OK; if (val) { char *ext; - gf_file_load_data(val, (u8 **) &d, &tlen); + e = gf_file_load_data(val, (u8 **) &d, &tlen); ext = strrchr(val, '.'); if (!stricmp(ext, ".png")) tlen |= 0x80000000; } - e = gf_isom_apple_set_tag(file, GF_ISOM_ITUNE_COVER_ART, d, tlen); + if (!e) + e = gf_isom_apple_set_tag(file, GF_ISOM_ITUNE_COVER_ART, d, tlen); + if (d) gf_free(d); } break; @@ -6093,7 +6212,7 @@ break; case GF_ISOM_ITUNE_GENRE: { - u8 _v = id3_get_genre_tag(val); + u8 _v = gf_id3_get_genre_tag(val); if (_v) { gf_isom_apple_set_tag(file, itag, NULL, _v); } else { @@ -6259,7 +6378,7 @@ if (force_ocr) SetupClockReferences(file); fprintf(stderr, "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, single_group); + e = HintFile(file, MTUSize, max_ptime, rtp_rate, hint_flags, HintCopy, HintInter, regular_iod, single_group, hint_no_offset); if (e) goto err_exit; needSave = GF_TRUE; if (print_sdp) dump_isom_sdp(file, dump_std ? NULL : (outName ? outName : outfile), outName ? GF_TRUE : GF_FALSE);
View file
gpac-1.0.0.tar.gz/applications/mp4client/Makefile -> gpac-1.0.1.tar.gz/applications/mp4client/Makefile
Changed
@@ -6,17 +6,17 @@ LINKFLAGS=$(GPAC_SH_FLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(GPACREADONLY), yes) +ifeq ($(GPACREADONLY),yes) CFLAGS+=-DGPAC_READ_ONLY endif
View file
gpac-1.0.0.tar.gz/applications/mp4client/main.c -> gpac-1.0.1.tar.gz/applications/mp4client/main.c
Changed
@@ -291,7 +291,7 @@ "For more info on GPAC configuration, use `gpac ` [-h](GPAC) `bin` \n \n" "# Options \n \n", (help_flags == GF_PRINTARG_MD) ? GPAC_VERSION : gf_gpac_version(), - gf_gpac_copyright() + gf_gpac_copyright_cite() ); } @@ -950,11 +950,6 @@ case GF_EVENT_METADATA: ResetCaption(); break; - - case GF_EVENT_RELOAD: - if (is_connected) - reload = 1; - break; case GF_EVENT_DROPFILE: { u32 i, pos; @@ -1197,7 +1192,7 @@ PrintHelp(); return 0; } else if (!strcmp(arg, "-hc")) { - fprintf(stderr, "libgpac options:\n"); + fprintf(helpout, "libgpac options:\n"); gf_sys_print_core_help(helpout, help_flags, GF_ARGMODE_ALL, 0); return 0; }
View file
gpac-1.0.0.tar.gz/applications/osmo4_android_studio/app/src/main/java/com/gpac/Osmo4/GPACInstance.java -> gpac-1.0.1.tar.gz/applications/osmo4_android_studio/app/src/main/java/com/gpac/Osmo4/GPACInstance.java
Changed
@@ -65,12 +65,12 @@ StringBuilder sb = new StringBuilder(); final String[] toLoad = { "GLESv2", "log",//$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ "jpegdroid", "javaenv", //$NON-NLS-1$ //$NON-NLS-2$ - "mad", "editline", "ft2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - "js_osmo", "openjpeg", "png", "z", //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ - "stlport_shared", "stdc++", "faad", "gpac", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ - /*"gm_droid_cam",*/ "gm_droid_mpegv","gm_mediacodec_dec", //$NON-NLS-1$ //$NON-NLS-2$ - "avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice", - "gpacWrapper" }; // //$NON-NLS-1$ //$NON-NLS-2$ + "mad", "ft2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + "openjpeg", "png", "z", //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ + "stlport_shared", "stdc++", "faad", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + "avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice", + "gpacWrapper", "gpac", + "gm_droid_mpegv" }; // //$NON-NLS-1$ //$NON-NLS-2$ HashMap<String, Throwable> exceptions = new HashMap<String, Throwable>(); for (String s : toLoad) { try {
View file
gpac-1.0.0.tar.gz/applications/osmo4_android_studio/app/src/main/java/com/gpac/Osmo4/GpacCallback.java -> gpac-1.0.1.tar.gz/applications/osmo4_android_studio/app/src/main/java/com/gpac/Osmo4/GpacCallback.java
Changed
@@ -153,55 +153,61 @@ GF_LOG_CONTAINER(2), /** Log message from the network/service stack (messages & co) */ GF_LOG_NETWORK(3), + /** Log message from the network/service stack (messages & co) */ + GF_LOG_HTTP(4), /** Log message from the RTP/RTCP stack (TS info) and packet structure & hinting (debug) */ - GF_LOG_RTP(4), + GF_LOG_RTP(5), /** Log message from authoring subsystem (file manip, import/export) */ - GF_LOG_AUTHOR(5), + GF_LOG_AUTHOR(6), /** Log message from the sync layer of the terminal */ - GF_LOG_SYNC(6), + GF_LOG_SYNC(7), /** Log message from a codec */ - GF_LOG_CODEC(7), + GF_LOG_CODEC(8), /** Log message from any XML parser (context loading, etc) */ - GF_LOG_PARSER(8), + GF_LOG_PARSER(9), /** Log message from the terminal/compositor, indicating media object state */ - GF_LOG_MEDIA(9), + GF_LOG_MEDIA(10), /** Log message from the scene graph/scene manager (handling of nodes and attribute modif, DOM core) */ - GF_LOG_SCENE(10), + GF_LOG_SCENE(11), /** Log message from the scripting engine */ - GF_LOG_SCRIPT(11), + GF_LOG_SCRIPT(12), /** Log message from event handling */ - GF_LOG_INTERACT(12), + GF_LOG_INTERACT(13), /** Log message from compositor */ - GF_LOG_COMPOSE(13), + GF_LOG_COMPOSE(14), /** Log for video object cache */ - GF_LOG_CACHE(14), + GF_LOG_CACHE(15), /** Log message from multimedia I/O devices (audio/video input/output, ...) */ - GF_LOG_MMIO(15), + GF_LOG_MMIO(16), /** Log for runtime info (times, memory, CPU usage) */ - GF_LOG_RTI(16), + GF_LOG_RTI(17), /** Log for SMIL timing and animation */ - GF_LOG_SMIL(17), + GF_LOG_SMIL(18), /** Log for memory tracker */ - GF_LOG_MEMORY(18), + GF_LOG_MEMORY(19), /** Log for audio compositor */ - GF_LOG_AUDIO(19), + GF_LOG_AUDIO(20), /** generic Log for modules */ - GF_LOG_MODULE(20), + GF_LOG_MODULE(21), /** * Log for GPAC mutexes and threads (Very verbose at DEBUG) * */ - GF_LOG_MUTEX(21), + GF_LOG_MUTEX(22), /*! Log for threads and condition */ - GF_LOG_CONDITION(22), - /*! Log for all HTTP streaming */ - GF_LOG_DASH(23), - /*! Log for all messages coming from GF_Terminal or script alert()*/ - GF_LOG_CONSOLE(24), - /*! Log for all messages coming the application, not used by libgpac or the modules*/ - GF_LOG_APP(25), - /*! Log for all messages coming from the scheduler */ - GF_LOG_SCHEDULER(26), + GF_LOG_CONDITION(23), + /*! Log for all HTTP streaming */ + GF_LOG_DASH(24), + /*! Log for all filter engine */ + GF_LOG_FILTER(25), + /*! Log for all filter scheduler */ + GF_LOG_SCHEDULER(26), + /*! Log for ATSC3 demux */ + GF_LOG_ATSC(27), + /*! Log for all messages coming from GF_Terminal or script alert()*/ + GF_LOG_CONSOLE(28), + /*! Log for all messages coming the application, not used by libgpac or the modules*/ + GF_LOG_APP(29), /** * Unknown Log subsystem */
View file
gpac-1.0.0.tar.gz/applications/osmo4_android_studio/app/src/main/jni/wrapper.cpp -> gpac-1.0.1.tar.gz/applications/osmo4_android_studio/app/src/main/jni/wrapper.cpp
Changed
@@ -246,7 +246,7 @@ m_mx = NULL; mainJavaEnv = NULL; - debug_f = 0; + log_file = NULL; m_window = NULL; m_session = NULL; @@ -266,6 +266,8 @@ JavaEnvTh * env = getEnv(); if (env && env->cbk_obj) env->env->DeleteGlobalRef(env->cbk_obj); + if (log_file) gf_fclose(log_file); + log_file = NULL; Shutdown(); debug_log("~CNativeWrapper() : DONE\n"); } @@ -436,6 +438,7 @@ if (!self) goto displayInAndroidlogs; +#if 0 { JavaEnvTh *env = self->getEnv(); jstring msg; @@ -449,6 +452,15 @@ env->env->PopLocalFrame(NULL); return; } + +#else + if (self->log_file) { + vfprintf(self->log_file, fmt, list); + fflush(self->log_file); + } +#endif + + displayInAndroidlogs: { /* When no callback is properly set, we use direct logging */ @@ -701,6 +713,7 @@ gf_log_set_callback(this, on_gpac_log); opt = gf_opts_get_key("core", "log-file"); if (opt) { +#if 0 JavaEnvTh *env = getEnv(); if (env && env->cbk_setLogFile) { env->env->PushLocalFrame(1); @@ -708,6 +721,9 @@ env->env->CallVoidMethod(env->cbk_obj, env->cbk_setLogFile, js); env->env->PopLocalFrame(NULL); } +#else + log_file = gf_fopen(opt, "wt"); +#endif } gf_mx_v(m_mx); @@ -877,20 +893,11 @@ void CNativeWrapper::step(void * env, void * bitmap) { m_window = env; m_session = bitmap; - //debug_log("Step ..."); - if (!m_term) { - debug_log("step(): No m_term found."); - return; - } else if (!m_term->compositor) - debug_log("step(): No compositor found."); - else if (!m_term->compositor->video_out) - debug_log("step(): No video_out found"); - else if (!m_term->compositor->video_out->Setup) - debug_log("step(): No video_out->Setup found"); - else { - m_term->compositor->frame_draw_type = GF_SC_DRAW_FRAME; - gf_term_process_step(m_term); + m_term->compositor->frame_draw_type = GF_SC_DRAW_FRAME; + while (!gf_term_process_step(m_term)) { + debug_log("step(): nothing drawn, retrying\n"); } + debug_log("step(): frame drawn\n"); } //-----------------------------------------------------
View file
gpac-1.0.0.tar.gz/applications/osmo4_android_studio/app/src/main/jni/wrapper.h -> gpac-1.0.1.tar.gz/applications/osmo4_android_studio/app/src/main/jni/wrapper.h
Changed
@@ -51,10 +51,6 @@ //#define GPAC_FONT_DIR "/system/fonts/" #define GPAC_FONT_DIR m_font_dir -#define DEBUG_MODE 1 -//#define DEBUG_FILE "/data/osmo/osmo_debug.txt" -#define DEBUG_FILE m_debug_filename - // keyboard code #define ANDROID_KEYCODE int #define ANDROID_KEYCODE_0 7 @@ -181,6 +177,8 @@ GF_SystemRTInfo m_rti; int do_log; + FILE *log_file; + private: char m_cfg_dir[GF_MAX_PATH]; char m_modules_dir[GF_MAX_PATH]; @@ -224,9 +222,6 @@ static void Osmo4_progress_cbk(const void *usr, const char *title, u64 done, u64 total); private: -#ifdef DEBUG_MODE - FILE *debug_f; -#endif void debug_log(const char* msg); };
View file
gpac-1.0.0.tar.gz/applications/osmo4_ios/osmo4ios-Info.plist -> gpac-1.0.1.tar.gz/applications/osmo4_ios/osmo4ios-Info.plist
Changed
@@ -35,7 +35,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>1.0.0</string> + <string>1.0.1</string> <key>CFBundleSignature</key> <string>gpac</string> <key>CFBundleVersion</key>
View file
gpac-1.0.0.tar.gz/applications/testapps/atscdmx/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/atscdmx/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/bmp4demux/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/bmp4demux/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/broadcaster/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/broadcaster/Makefile
Changed
@@ -8,12 +8,12 @@ APPNAME=broadcaster -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/fmp4demux/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/fmp4demux/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/hevcbench/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/hevcbench/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" $(SDL_CFLAGS) $(OGL_INCLS) $(OHEVC_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/loadcompare/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/loadcompare/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/mpedemux/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/mpedemux/Makefile
Changed
@@ -4,22 +4,22 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif #file format is read-only -ifeq ($(GPACREADONLY), yes) +ifeq ($(GPACREADONLY),yes) CFLAGS+= -DGPAC_READ_ONLY endif -ifeq ($(DISABLE_SVG), yes) +ifeq ($(DISABLE_SVG),yes) CFLAGS+=-DGPAC_DISABLE_SVG endif
View file
gpac-1.0.0.tar.gz/applications/testapps/segmp4demux/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/segmp4demux/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/ts2hds/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/ts2hds/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/applications/testapps/udptsseg/Makefile -> gpac-1.0.1.tar.gz/applications/testapps/udptsseg/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -42,7 +42,7 @@ else SCENEGRAPH_CFLAGS+=$(JS_FLAGS) ifeq ($(CONFIG_JS),local) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes endif LINKFLAGS+=$(JS_LIBS) endif
View file
gpac-1.0.0.tar.gz/build/android/jni/libgpac/Android.mk -> gpac-1.0.1.tar.gz/build/android/jni/libgpac/Android.mk
Changed
@@ -149,6 +149,7 @@ ../../../../src/filter_core/filter_queue.c \ ../../../../src/filter_core/filter_register.c \ ../../../../src/filter_core/filter_session.c \ + ../../../../src/filter_core/filter_session_js.c \ ../../../../src/filters/bsrw.c \ ../../../../src/filters/compose.c \ ../../../../src/filters/dasher.c \ @@ -295,6 +296,7 @@ ../../../../src/isomedia/stbl_write.c \ ../../../../src/isomedia/track.c \ ../../../../src/isomedia/tx3g.c \ + ../../../../src/jsmods/core.c \ ../../../../src/jsmods/evg.c \ ../../../../src/jsmods/scene_js.c \ ../../../../src/jsmods/storage.c \
View file
gpac-1.0.0.tar.gz/build/android/jni/libgpac/config.h -> gpac-1.0.1.tar.gz/build/android/jni/libgpac/config.h
Changed
@@ -1,13 +1,10 @@ -/* Automatically generated by configure */ + #ifndef GF_CONFIG_H #define GF_CONFIG_H #define GPAC_CONFIG_LINUX 1 - -#define GPAC_HAS_SPIDERMONKEY 1 - -//#define GPAC_STANDALONE_RENDER_2D 1 - +#define GPAC_HAS_QJS 1 +#define GPAC_HAS_MEDIACODEC #define GPAC_HAS_JPEG 1 #define GPAC_HAS_JP2 1 #define GPAC_HAS_PNG 1
View file
gpac-1.0.0.tar.gz/build/msvc14/libgpac.vcxproj -> gpac-1.0.1.tar.gz/build/msvc14/libgpac.vcxproj
Changed
@@ -364,6 +364,7 @@ <ClCompile Include="..\..\src\filter_core\filter_queue.c" /> <ClCompile Include="..\..\src\filter_core\filter_register.c" /> <ClCompile Include="..\..\src\filter_core\filter_session.c" /> + <ClCompile Include="..\..\src\filter_core\filter_session_js.c" /> <ClCompile Include="..\..\src\ietf\rtcp.c" /> <ClCompile Include="..\..\src\ietf\rtp.c" /> <ClCompile Include="..\..\src\ietf\rtp_depacketizer.c" /> @@ -404,6 +405,7 @@ <ClCompile Include="..\..\src\isomedia\stbl_write.c" /> <ClCompile Include="..\..\src\isomedia\track.c" /> <ClCompile Include="..\..\src\isomedia\tx3g.c" /> + <ClCompile Include="..\..\src\jsmods\core.c" /> <ClCompile Include="..\..\src\jsmods\evg.c" /> <ClCompile Include="..\..\src\jsmods\scene_js.c" /> <ClCompile Include="..\..\src\jsmods\storage.c" />
View file
gpac-1.0.0.tar.gz/build/msvc14/libgpac.vcxproj.filters -> gpac-1.0.1.tar.gz/build/msvc14/libgpac.vcxproj.filters
Changed
@@ -1157,6 +1157,9 @@ <ClCompile Include="..\..\src\filter_core\filter_session.c"> <Filter>filter_core</Filter> </ClCompile> + <ClCompile Include="..\..\src\filter_core\filter_session_js.c"> + <Filter>filter_core</Filter> + </ClCompile> <ClCompile Include="..\..\src\filters\compose.c"> <Filter>filters</Filter> </ClCompile> @@ -1505,6 +1508,9 @@ <ClCompile Include="..\..\src\jsmods\xhr.c"> <Filter>jsmods</Filter> </ClCompile> + <ClCompile Include="..\..\src\jsmods\core.c"> + <Filter>jsmods</Filter> + </ClCompile> <ClCompile Include="..\..\src\scenegraph\dom_js.c"> <Filter>scenegraph</Filter> </ClCompile>
View file
gpac-1.0.0.tar.gz/build/xcode/gpac.xcodeproj/project.pbxproj -> gpac-1.0.1.tar.gz/build/xcode/gpac.xcodeproj/project.pbxproj
Changed
@@ -200,6 +200,7 @@ 9239B8D6207369E5005F7264 /* enc_jpg.c in Sources */ = {isa = PBXBuildFile; fileRef = 9239B8D5207369E5005F7264 /* enc_jpg.c */; }; 9239B8D82073AFEF005F7264 /* enc_png.c in Sources */ = {isa = PBXBuildFile; fileRef = 9239B8D72073AFEF005F7264 /* enc_png.c */; }; 923C337D234794F2001CED08 /* evg.c in Sources */ = {isa = PBXBuildFile; fileRef = 923C337C234794F2001CED08 /* evg.c */; }; + 923E3FE624B7316F0022660A /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = 923E3FE524B7316F0022660A /* core.c */; }; 923E89CB20B6F04600F299B2 /* g_crypt_openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = 923E89C620B6F04600F299B2 /* g_crypt_openssl.c */; }; 923E89CC20B6F04600F299B2 /* tiny_aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 923E89C720B6F04600F299B2 /* tiny_aes.h */; }; 923E89CD20B6F04600F299B2 /* g_crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 923E89C820B6F04600F299B2 /* g_crypt.c */; }; @@ -207,6 +208,7 @@ 923E89CF20B6F04600F299B2 /* g_crypt_tinyaes.c in Sources */ = {isa = PBXBuildFile; fileRef = 923E89CA20B6F04600F299B2 /* g_crypt_tinyaes.c */; }; 923E89D020B6F2D300F299B2 /* filter_props.c in Sources */ = {isa = PBXBuildFile; fileRef = 92F8D4721F71642E00616F7C /* filter_props.c */; }; 923EB53223D1B78D00E1FFA1 /* libbf.c in Sources */ = {isa = PBXBuildFile; fileRef = 923EB53123D1B78D00E1FFA1 /* libbf.c */; }; + 9246EE7524A0DA2700F72EAD /* filter_session_js.c in Sources */ = {isa = PBXBuildFile; fileRef = 9246EE7424A0DA2700F72EAD /* filter_session_js.c */; }; 92493D8020E2A64000203C2C /* crypt_tools.c in Sources */ = {isa = PBXBuildFile; fileRef = 92493D7F20E2A64000203C2C /* crypt_tools.c */; }; 92493D8220E2A81700203C2C /* crypt_tools.h in Headers */ = {isa = PBXBuildFile; fileRef = 92493D8120E2A81700203C2C /* crypt_tools.h */; }; 924E805D206D357A00AB580F /* reframe_rawvid.c in Sources */ = {isa = PBXBuildFile; fileRef = 924E805C206D357A00AB580F /* reframe_rawvid.c */; }; @@ -852,12 +854,14 @@ 9239B8D5207369E5005F7264 /* enc_jpg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = enc_jpg.c; path = filters/enc_jpg.c; sourceTree = "<group>"; }; 9239B8D72073AFEF005F7264 /* enc_png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = enc_png.c; path = filters/enc_png.c; sourceTree = "<group>"; }; 923C337C234794F2001CED08 /* evg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = evg.c; path = jsmods/evg.c; sourceTree = "<group>"; }; + 923E3FE524B7316F0022660A /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = core.c; path = jsmods/core.c; sourceTree = "<group>"; }; 923E89C620B6F04600F299B2 /* g_crypt_openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = g_crypt_openssl.c; path = crypto/g_crypt_openssl.c; sourceTree = "<group>"; }; 923E89C720B6F04600F299B2 /* tiny_aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tiny_aes.h; path = crypto/tiny_aes.h; sourceTree = "<group>"; }; 923E89C820B6F04600F299B2 /* g_crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = g_crypt.c; path = crypto/g_crypt.c; sourceTree = "<group>"; }; 923E89C920B6F04600F299B2 /* tiny_aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tiny_aes.c; path = crypto/tiny_aes.c; sourceTree = "<group>"; }; 923E89CA20B6F04600F299B2 /* g_crypt_tinyaes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = g_crypt_tinyaes.c; path = crypto/g_crypt_tinyaes.c; sourceTree = "<group>"; }; 923EB53123D1B78D00E1FFA1 /* libbf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libbf.c; path = quickjs/libbf.c; sourceTree = "<group>"; }; + 9246EE7424A0DA2700F72EAD /* filter_session_js.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filter_session_js.c; path = filter_core/filter_session_js.c; sourceTree = "<group>"; }; 92493D7F20E2A64000203C2C /* crypt_tools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crypt_tools.c; sourceTree = "<group>"; }; 92493D8120E2A81700203C2C /* crypt_tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crypt_tools.h; path = ../include/gpac/crypt_tools.h; sourceTree = "<group>"; }; 924E805C206D357A00AB580F /* reframe_rawvid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = reframe_rawvid.c; path = filters/reframe_rawvid.c; sourceTree = "<group>"; }; @@ -1939,9 +1943,10 @@ 92D6C5982343BEC600262217 /* jsmods */ = { isa = PBXGroup; children = ( - 9273463223506D370081AF74 /* storage.c */, + 923E3FE524B7316F0022660A /* core.c */, 923C337C234794F2001CED08 /* evg.c */, 92D6C5992343BED700262217 /* scene_js.c */, + 9273463223506D370081AF74 /* storage.c */, 929383A22355A6EF00AAAFA8 /* WebGL */, 92D6C59A2343BED700262217 /* xhr.c */, ); @@ -1968,6 +1973,7 @@ 9234CF3C1FD7E00700CCDFA1 /* filter_register.c */, 92F8D4741F71642E00616F7C /* filter_session.c */, 92F8D4751F71642E00616F7C /* filter_session.h */, + 9246EE7424A0DA2700F72EAD /* filter_session_js.c */, 92F8D4761F71642E00616F7C /* filter.c */, ); name = filter_core; @@ -2540,6 +2546,7 @@ 92061A851FE0484600B5C464 /* reframer.c in Sources */, 9201010C18D5A444003D1ACA /* rtp_pck_mpeg12.c in Sources */, 92B9A5821F8660D700A24FE4 /* hc_flash_shape.c in Sources */, + 9246EE7524A0DA2700F72EAD /* filter_session_js.c in Sources */, 9201010D18D5A444003D1ACA /* rtp_pck_mpeg4.c in Sources */, 92D6C59C2343BED700262217 /* xhr.c in Sources */, 92B9A5C11F86ACDF00A24FE4 /* dec_opensvc.c in Sources */, @@ -2820,6 +2827,7 @@ 920101BA18D5A445003D1ACA /* path2d.c in Sources */, 920101BB18D5A445003D1ACA /* path2d_stroker.c in Sources */, 920101BD18D5A445003D1ACA /* sha1.c in Sources */, + 923E3FE624B7316F0022660A /* core.c in Sources */, 9206823420EA96AA0041169F /* mux_gsf.c in Sources */, 920101C018D5A445003D1ACA /* token.c in Sources */, 92B9A5A91F8660D700A24FE4 /* bindable.c in Sources */,
View file
gpac-1.0.0.tar.gz/build/xcode/gpac4ios.xcodeproj/project.pbxproj -> gpac-1.0.1.tar.gz/build/xcode/gpac4ios.xcodeproj/project.pbxproj
Changed
@@ -351,11 +351,13 @@ 92334CDB2333AB9A00DA6051 /* libregexp.c in Sources */ = {isa = PBXBuildFile; fileRef = 92334CCA2333AB9A00DA6051 /* libregexp.c */; }; 92334CDD2333AB9A00DA6051 /* quickjs.h in Headers */ = {isa = PBXBuildFile; fileRef = 92334CCC2333AB9A00DA6051 /* quickjs.h */; }; 923EB53423D1B87E00E1FFA1 /* libbf.c in Sources */ = {isa = PBXBuildFile; fileRef = 923EB53323D1B87E00E1FFA1 /* libbf.c */; }; + 9246EE7724A1240600F72EAD /* filter_session_js.c in Sources */ = {isa = PBXBuildFile; fileRef = 9246EE7624A1240600F72EAD /* filter_session_js.c */; }; 925730A21A0916D20057FF04 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 925730A11A0916D20057FF04 /* libiconv.dylib */; }; 925730A41A0916DB0057FF04 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 925730A31A0916DB0057FF04 /* libbz2.dylib */; }; 925FF2A51ABC53F30085B04C /* odf_parse_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 925FF2A31ABC53F30085B04C /* odf_parse_common.h */; }; 925FF2A61ABC53F30085B04C /* smjs_api.h in Headers */ = {isa = PBXBuildFile; fileRef = 925FF2A41ABC53F30085B04C /* smjs_api.h */; }; 925FF2A71ABC55030085B04C /* os_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 71CCF2361277045100339E12 /* os_file.c */; }; + 9262B10C24B7791B009B059D /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = 9262B10B24B7791B009B059D /* core.c */; }; 92734635235084A50081AF74 /* storage.c in Sources */ = {isa = PBXBuildFile; fileRef = 92734634235084A50081AF74 /* storage.c */; }; 9274295A24647B98009ADD8D /* bsrw.c in Sources */ = {isa = PBXBuildFile; fileRef = 9274295924647B98009ADD8D /* bsrw.c */; }; 9280E7251DD23FFE001E6441 /* iTunesArtwork in Resources */ = {isa = PBXBuildFile; fileRef = 9236FDEF1DD23F1400B3E86F /* iTunesArtwork */; }; @@ -934,10 +936,12 @@ 92334CCC2333AB9A00DA6051 /* quickjs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quickjs.h; path = ../../src/quickjs/quickjs.h; sourceTree = "<group>"; }; 9236FDEF1DD23F1400B3E86F /* iTunesArtwork */ = {isa = PBXFileReference; lastKnownFileType = file; name = iTunesArtwork; path = ../../applications/osmo4_ios/Resources/iTunesArtwork; sourceTree = "<group>"; }; 923EB53323D1B87E00E1FFA1 /* libbf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libbf.c; path = ../../src/quickjs/libbf.c; sourceTree = "<group>"; }; + 9246EE7624A1240600F72EAD /* filter_session_js.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filter_session_js.c; path = ../../src/filter_core/filter_session_js.c; sourceTree = "<group>"; }; 925730A11A0916D20057FF04 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; 925730A31A0916DB0057FF04 /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = usr/lib/libbz2.dylib; sourceTree = SDKROOT; }; 925FF2A31ABC53F30085B04C /* odf_parse_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = odf_parse_common.h; sourceTree = "<group>"; }; 925FF2A41ABC53F30085B04C /* smjs_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smjs_api.h; sourceTree = "<group>"; }; + 9262B10B24B7791B009B059D /* core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = core.c; path = ../../src/jsmods/core.c; sourceTree = "<group>"; }; 92734634235084A50081AF74 /* storage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = storage.c; path = ../../src/jsmods/storage.c; sourceTree = "<group>"; }; 9274295924647B98009ADD8D /* bsrw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bsrw.c; path = ../../src/filters/bsrw.c; sourceTree = "<group>"; }; 9281B62E21C92D00006B0FD5 /* gui */ = {isa = PBXFileReference; lastKnownFileType = folder; name = gui; path = ../../share/gui; sourceTree = "<group>"; }; @@ -1798,6 +1802,7 @@ 92D6C5A32343BF5000262217 /* jsmods */ = { isa = PBXGroup; children = ( + 9262B10B24B7791B009B059D /* core.c */, 929867782357A0DA008A2CC6 /* webgl.h */, 9210BA1C234A909400ED2DFF /* evg.c */, 92D6C5A52343BF6A00262217 /* scene_js.c */, @@ -1846,6 +1851,7 @@ 92EB6D6420E4E17F00A97A49 /* filter_register.c */, 92EB6D6220E4E17F00A97A49 /* filter_session.c */, 92EB6D6520E4E17F00A97A49 /* filter_session.h */, + 9246EE7624A1240600F72EAD /* filter_session_js.c */, 92EB6D5F20E4E17F00A97A49 /* filter.c */, ); name = filter_core; @@ -2405,6 +2411,7 @@ 71CCF2B21277045100339E12 /* hint_track.c in Sources */, 92EB6D6720E4E17F00A97A49 /* filter.c in Sources */, 92EB6E1220E4E19700A97A49 /* reframe_h263.c in Sources */, + 9262B10C24B7791B009B059D /* core.c in Sources */, 71CCF2B31277045100339E12 /* hinting.c in Sources */, 71CCF2B41277045100339E12 /* drm_sample.c in Sources */, 92EB6DCD20E4E19700A97A49 /* reframe_nalu.c in Sources */, @@ -2425,6 +2432,7 @@ 92EB6DE020E4E19700A97A49 /* write_nhml.c in Sources */, 92EB6DD420E4E19700A97A49 /* inspect.c in Sources */, 71CCF2BD1277045100339E12 /* sample_descs.c in Sources */, + 9246EE7724A1240600F72EAD /* filter_session_js.c in Sources */, 71CCF2BE1277045100339E12 /* stbl_read.c in Sources */, 71CCF2BF1277045100339E12 /* stbl_write.c in Sources */, 71CCF2C01277045100339E12 /* track.c in Sources */,
View file
gpac-1.0.0.tar.gz/configure -> gpac-1.0.1.tar.gz/configure
Changed
@@ -947,6 +947,35 @@ CFLAGS="$CFLAGS -DGPAC_NO_STDATOMIC" fi + +cat > $TMPC << EOF +#include <stdint.h> +int main(void) { + int i4 = 4; + __int64_t i8 = 8; + __sync_add_and_fetch(&i4, 12); + __sync_add_and_fetch(&i8, 12); +} +EOF +has_builtinatomic="no" +if docc ; then + has_builtinatomic="yes" +else +cat > $TMPC << EOF +#include <stdint.h> +int main(void) { + int i4 = 4; + __int64_t i8 = 8; + __atomic_add_fetch(&i4, 12, __ATOMIC_SEQ_CST); + __atomic_add_fetch(&i8, 12, __ATOMIC_SEQ_CST); +} +EOF + if docc -latomic ; then + CFLAGS="$CFLAGS -DGPAC_NEED_LIBATOMIC" + LDFLAGS="$LDFLAGS -latomic" + fi +fi + #look for JPEG support cat > $TMPC << EOF #include <stdio.h> @@ -2216,7 +2245,7 @@ #man dir if test x"$mandir" = x""; then - mandir="${prefix}/share/man" + mandir="share/man" fi if test "$static_mp4box" = "yes"; then @@ -2688,9 +2717,7 @@ echo "prefix=$prefix" >> config.mak echo "DESTDIR=$DESTDIR" >> config.mak -echo "moddir=$prefix/$libdir/gpac" >> config.mak -echo "moddir_path=$prefix/$libdir/gpac" >> config.mak -echo "mandir=$mandir" >> config.mak +echo "moddir=gpac" >> config.mak echo "tinygl_target_bin_dir=$target_bin_dir" >> config.mak echo "MAKE=$make" >> config.mak @@ -2715,7 +2742,15 @@ echo "CXXFLAGS=$CXXFLAGS" >> config.mak echo "LDFLAGS=$LDFLAGS" >> config.mak echo "SHFLAGS=$SHFLAGS" >> config.mak -echo "libdir=$libdir" >> config.mak + +pf="$prefix/" +lib_dir=${libdir#"$pf"} +echo "lib_dir=$lib_dir" >> config.mak + +pf="$prefix/" +man_dir=${mandir#"$pf"} +echo "man_dir=$man_dir" >> config.mak + echo "STATIC_MODULES=$static_modules" >> config.mak @@ -3243,4 +3278,30 @@ generate_pkgconfig > gpac.pc + +generate_gpacdesktop () { + echo "[Desktop Entry]" + echo "Version=1.0" + echo "Name=MP4Client" + echo "Comment=GPAC Media Player" + echo "GenericName=Media Player" + echo "Keywords=Media Player" + echo "Exec=MP4Client -gui %u" + echo "Terminal=false" + echo "X-MultipleArgs=false" + echo "Type=Application" + echo "Icon=$prefix/share/pixmaps/gpac.png" + echo "Categories=AudioVideo" + echo "MimeType=text/text;text/xml;application/xhtml+xml;application/xml;image/jpeg;image/png;video/webm;video/mp4;video/mpeg;audio/mp4;audio/mpeg;x-scheme-handler/rtsp;x-scheme-handler/rtp;x-scheme-handler/atsc" + echo "StartupNotify=true" + echo "Actions=new-window" + echo "" + echo "[Desktop Action new-window]" + echo "Name=Open a New Window" + echo "Exec=MP4Client" + echo "" +} + +generate_gpacdesktop > "$source_path/share/gpac.desktop" + echo "Done - type 'make help' for make info, 'make' to build"
View file
gpac-1.0.0.tar.gz/debian/changelog -> gpac-1.0.1.tar.gz/debian/changelog
Changed
@@ -1,4 +1,4 @@ -gpac (1.0.0) stable; urgency=low +gpac (1.0.1) stable; urgency=low * Initial release - see https://github.com/gpac/gpac/releases for more details
View file
gpac-1.0.0.tar.gz/debian/rules -> gpac-1.0.1.tar.gz/debian/rules
Changed
@@ -20,6 +20,7 @@ CFLAGS = -Wall -g LDFLAGS= --as-needed IS_DEB_MAKE=1 +export IS_DEB_MAKE CC:=ccache $(CC) CXX:=ccache $(CXX) @@ -36,7 +37,7 @@ chmod 755 configure ./configure --host=$(DEB_HOST_GNU_TYPE) --prefix=/usr \ - --build=$(DEB_BUILD_GNU_TYPE) --mandir=\$${prefix}/share/man \ + --build=$(DEB_BUILD_GNU_TYPE) \ --extra-cflags="$(CFLAGS)" --cc="$(CC)" CXX="$(CXX)" touch $@ @@ -68,7 +69,7 @@ dh_installdirs $(MAKE) install prefix=$(CURDIR)/debian/tmp/usr \ - moddir=$(CURDIR)/debian/tmp/usr/lib/gpac moddir_path=/usr/lib/gpac + moddir=gpac $(MAKE) install-lib prefix=$(CURDIR)/debian/tmp/usr
View file
gpac-1.0.0.tar.gz/gpac.spec -> gpac-1.0.1.tar.gz/gpac.spec
Changed
@@ -1,11 +1,11 @@ # $Id: gpac.spec,v 1.5 2008-12-02 18:04:42 jeanlf Exp $ Summary: Framework for production, encoding, delivery and interactive playback of multimedia content Name: gpac -Version: 1.0.0 -Release: 1.0.0 +Version: 1.0.1 +Release: 1.0.1 License: LGPL Group: Applications/Multimedia -Source0: gpac-1.0.0.tar.gz +Source0: gpac-1.0.1.tar.gz%{?_with_amr:Source1:http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-700.zip} URL: http://gpac.io/ BuildRoot: %{_tmppath}/%{name}-root Requires: SDL @@ -25,7 +25,9 @@ %{!?_without_mad:BuildRequires: libmad-devel} %{!?_without_xvid:BuildRequires: xvidcore-devel} %{!?_without_ffmpeg:BuildRequires: ffmpeg-devel} -%{!?_without_jack:BuildRequires: libjack-devel} +%{!?_without_jack:BuildRequires: jack-audio-connection-kit} + +%global debug_package %{nil} %description @@ -40,7 +42,8 @@ Available rpmbuild rebuild options : ---without : freetype faad a52 jpeg png mad xvid ffmpeg +--without : freetype faad a52 jpeg png mad xvid ffmpeg jack + %prep %setup -q -n gpac @@ -63,13 +66,14 @@ %files %defattr(-, root, root) -%doc AUTHORS BUGS Changelog COPYING README.md TODO +# %doc Changelog COPYING README.md %{_bindir}/* %{_libdir}/* -%{_mandir}/man1/* +%{_includedir}/* +%{_datadir}/* %changelog -* Jun 16 2020 Jean Le Feuvre +* Fri Sep 4 2020 Jean Le Feuvre - GPAC 1.0 release * Fri Jul 3 2015 Jean Le Feuvre - Changed to README.md
View file
gpac-1.0.0.tar.gz/include/gpac/Remotery.h -> gpac-1.0.1.tar.gz/include/gpac/Remotery.h
Changed
@@ -41,7 +41,6 @@ #ifndef RMT_INCLUDED_H #define RMT_INCLUDED_H - //! @cond Doxygen_Suppress // Set to 0 to not include any bits of Remotery in your build @@ -121,7 +120,7 @@ // Platform identification #if defined(_WINDOWS) || defined(_WIN32) #define RMT_PLATFORM_WINDOWS -#elif defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) #define RMT_PLATFORM_LINUX #define RMT_PLATFORM_POSIX #elif defined(__APPLE__) @@ -332,6 +331,12 @@ #define rmt_LogText(text) \ RMT_OPTIONAL(RMT_ENABLED, _rmt_LogText(text)) +#define rmt_EnableSampling(enable) \ + RMT_OPTIONAL(RMT_ENABLED, _rmt_EnableSampling(enable)) + +#define rmt_SamplingEnabled() \ + RMT_OPTIONAL(RMT_ENABLED, _rmt_SamplingEnabled()) + #define rmt_BeginCPUSample(name, flags) \ RMT_OPTIONAL(RMT_ENABLED, { \ static rmtU32 rmt_sample_hash_##name = 0; \ @@ -357,7 +362,7 @@ typedef void (*rmtInputHandlerPtr)(const char* text, void* context); -/*! Struture to fill in to modify Remotery default settings*/ +// Struture to fill in to modify Remotery default settings typedef struct rmtSettings { // Which port to listen for incoming connections on @@ -404,7 +409,7 @@ } rmtSettings; -/*! Structure to fill in when binding CUDA to Remotery*/ +// Structure to fill in when binding CUDA to Remotery typedef struct rmtCUDABind { // The main context that all driver functions apply before each call @@ -627,6 +632,8 @@ RMT_API void _rmt_LogText(rmtPStr text); RMT_API void _rmt_BeginCPUSample(rmtPStr name, rmtU32 flags, rmtU32* hash_cache); RMT_API void _rmt_EndCPUSample(void); +RMT_API void _rmt_EnableSampling(rmtBool enable); +RMT_API rmtBool _rmt_SamplingEnabled(); #if RMT_USE_CUDA RMT_API void _rmt_BindCUDA(const rmtCUDABind* bind);
View file
gpac-1.0.0.tar.gz/include/gpac/avparse.h -> gpac-1.0.1.tar.gz/include/gpac/avparse.h
Changed
@@ -383,6 +383,22 @@ #endif /*!defined(GPAC_DISABLE_AV_PARSERS) && !defined (GPAC_DISABLE_OGG)*/ +/*! reads escaped value according to usac/mpegh +\param bs bitstream object +\param nBits1 first number of bits +\param nBits2 second number of bits +\param nBits3 third number set of bits +\return value read +*/ +u64 gf_mpegh_escaped_value(GF_BitStream *bs, u32 nBits1, u32 nBits2, u32 nBits3); + +/*! parse profile and level from a MHAS payload +\param ptr the MHAS payhload +\param size size of the MHAS payhload +\return the MHAS profile found, or -1 of not found +*/ +s32 gf_mpegh_get_mhas_pl(u8 *ptr, u32 size); + /*! reads a 32 bit sync safe integer of id3v2 from a bitstream object \param bs the bitstream object to use - has to be positioned on the start if an id3v2 size field \return the id3v2 size field read
View file
gpac-1.0.0.tar.gz/include/gpac/bitstream.h -> gpac-1.0.1.tar.gz/include/gpac/bitstream.h
Changed
@@ -390,6 +390,16 @@ \param value the integer value to write */ void gf_bs_write_u32_le(GF_BitStream *bs, u32 value); + +/*! +\brief little endian large integer writing + +Writes an integer on 64 bits in little-endian order. +\param bs the target bitstream +\param value the integer value to write + */ +void gf_bs_write_u64_le(GF_BitStream *bs, u64 value); + /*! \brief little endian short writing @@ -595,22 +605,6 @@ GF_Err gf_bs_insert_data(GF_BitStream *bs, u8 *data, u32 size, u64 offset); /*! -\brief Inserts a data block, moving bytes to the end - - -Inserts a data block at a given position, pushing all bytes after the insertion point to the end of the stream. - This does NOT work if \ref gf_bs_enable_emulation_byte_removal or \ref gf_bs_new_cbk where used. - The position after the call will be the same as before the call. If the position is not the end of the bitstream - all bytes after the position will be lost. -\param bs the target bitstream -\param data block to insert -\param size size of the block to insert -\param offset insertion offset from bitstream start -\return error code if any - */ -GF_Err gf_bs_insert_data(GF_BitStream *bs, u8 *data, u32 size, u64 offset); - -/*! \brief Sets cookie Sets a 64 bit cookie (integer, pointer) on the bitstream, returning the current cookie value
View file
gpac-1.0.0.tar.gz/include/gpac/color.h -> gpac-1.0.1.tar.gz/include/gpac/color.h
Changed
@@ -160,6 +160,14 @@ */ const char *gf_color_get_name(GF_Color col); +/*! Enumerates built-in colors +\param idx index of color to query, incremented by one on success +\param color set to color value, can be NULL +\param color_name set to color name, can be NULL +\return GF_TRUE if sucess, GF_FALSE otherwise +*/ +Bool gf_color_enum(u32 *idx, GF_Color *color, const char **color_name); + /*! Inits a color matrix to identity \param _this the target color matrix to initialize*/ void gf_cmx_init(GF_ColorMatrix *_this); @@ -213,6 +221,17 @@ */ GF_Color gf_cmx_apply(GF_ColorMatrix *_this, GF_Color col); +/*!\brief color matrix transform + +Transforms a color with a given color matrix +\param _this color matrix to use. +\param a alpha to transform (in/out) +\param r red to transform (in/out) +\param g green to transform (in/out) +\param b blue to transform (in/out) +*/ +void gf_cmx_apply_argb(GF_ColorMatrix *_this, u8 *a, u8 *r, u8 *g, u8 *b); + /*!\brief color matrix transform on wide pixel (16 bit per component) Transforms a color with a given color matrix
View file
gpac-1.0.0.tar.gz/include/gpac/constants.h -> gpac-1.0.1.tar.gz/include/gpac/constants.h
Changed
@@ -506,6 +506,11 @@ GF_CODECID_VP9 = GF_4CC('V','P','0','9'), GF_CODECID_VP10 = GF_4CC('V','P','1','0'), + /*MPEG-H audio*/ + GF_CODECID_MPHA = GF_4CC('m','p','h','a'), + /*MPEG-H mux audio*/ + GF_CODECID_MHAS = GF_4CC('m','h','a','s'), + /*QT ProRes*/ GF_CODECID_APCH = GF_4CC( 'a', 'p', 'c', 'h' ), GF_CODECID_APCO = GF_4CC( 'a', 'p', 'c', 'o' ), @@ -516,6 +521,7 @@ GF_CODECID_TMCD = GF_4CC('t','m','c','d'), + GF_CODECID_FFMPEG = GF_4CC('F','F','I','D'), //fake codec IDs for RTP @@ -1105,83 +1111,160 @@ /*! ID3v2 tags*/ typedef enum { - ID3V2_FRAME_AENC = GF_4CC('A','E','N','C'), - ID3V2_FRAME_APIC = GF_4CC('A','P','I','C'), - ID3V2_FRAME_COMM = GF_4CC('C','O','M','M'), - ID3V2_FRAME_COMR = GF_4CC('C','O','M','R'), - ID3V2_FRAME_ENCR = GF_4CC('E','N','C','R'), - ID3V2_FRAME_EQUA = GF_4CC('E','Q','U','A'), - ID3V2_FRAME_ETCO = GF_4CC('E','T','C','O'), - ID3V2_FRAME_GEOB = GF_4CC('G','E','O','B'), - ID3V2_FRAME_GRID = GF_4CC('G','R','I','D'), - ID3V2_FRAME_IPLS = GF_4CC('I','P','L','S'), - ID3V2_FRAME_LINK = GF_4CC('L','I','N','K'), - ID3V2_FRAME_MCDI = GF_4CC('M','C','D','I'), - ID3V2_FRAME_MLLT = GF_4CC('M','L','L','T'), - ID3V2_FRAME_OWNE = GF_4CC('O','W','N','E'), - ID3V2_FRAME_PRIV = GF_4CC('P','R','I','V'), - ID3V2_FRAME_PCNT = GF_4CC('P','C','N','T'), - ID3V2_FRAME_POPM = GF_4CC('P','O','P','M'), - ID3V2_FRAME_POSS = GF_4CC('P','O','S','S'), - ID3V2_FRAME_RBUF = GF_4CC('R','B','U','F'), - ID3V2_FRAME_RVAD = GF_4CC('R','V','A','D'), - ID3V2_FRAME_RVRB = GF_4CC('R','V','R','B'), - ID3V2_FRAME_SYLT = GF_4CC('S','Y','L','T'), - ID3V2_FRAME_SYTC = GF_4CC('S','Y','T','C'), - ID3V2_FRAME_TALB = GF_4CC('T','A','L','B'), - ID3V2_FRAME_TBPM = GF_4CC('T','B','P','M'), - ID3V2_FRAME_TCOM = GF_4CC('T','C','O','M'), - ID3V2_FRAME_TCON = GF_4CC('T','C','O','N'), - ID3V2_FRAME_TCOP = GF_4CC('T','C','O','P'), - ID3V2_FRAME_TDAT = GF_4CC('T','D','A','T'), - ID3V2_FRAME_TDLY = GF_4CC('T','D','L','Y'), - ID3V2_FRAME_TDRC = GF_4CC('T','D','R','C'), - ID3V2_FRAME_TENC = GF_4CC('T','E','N','C'), - ID3V2_FRAME_TEXT = GF_4CC('T','E','X','T'), - ID3V2_FRAME_TFLT = GF_4CC('T','F','L','T'), - ID3V2_FRAME_TIME = GF_4CC('T','I','M','E'), - ID3V2_FRAME_TIT1 = GF_4CC('T','I','T','1'), - ID3V2_FRAME_TIT2 = GF_4CC('T','I','T','2'), - ID3V2_FRAME_TIT3 = GF_4CC('T','I','T','3'), - ID3V2_FRAME_TKEY = GF_4CC('T','K','E','Y'), - ID3V2_FRAME_TLAN = GF_4CC('T','L','A','N'), - ID3V2_FRAME_TLEN = GF_4CC('T','L','E','N'), - ID3V2_FRAME_TMED = GF_4CC('T','M','E','D'), - ID3V2_FRAME_TOAL = GF_4CC('T','O','A','L'), - ID3V2_FRAME_TOFN = GF_4CC('T','O','F','N'), - ID3V2_FRAME_TOLY = GF_4CC('T','O','L','Y'), - ID3V2_FRAME_TOPE = GF_4CC('T','O','P','E'), - ID3V2_FRAME_TORY = GF_4CC('T','O','R','Y'), - ID3V2_FRAME_TOWN = GF_4CC('T','O','W','N'), - ID3V2_FRAME_TPE1 = GF_4CC('T','P','E','1'), - ID3V2_FRAME_TPE2 = GF_4CC('T','P','E','2'), - ID3V2_FRAME_TPE3 = GF_4CC('T','P','E','3'), - ID3V2_FRAME_TPE4 = GF_4CC('T','P','E','4'), - ID3V2_FRAME_TPOS = GF_4CC('T','P','E','5'), - ID3V2_FRAME_TPUB = GF_4CC('T','P','U','B'), - ID3V2_FRAME_TRCK = GF_4CC('T','R','C','K'), - ID3V2_FRAME_TRDA = GF_4CC('T','R','D','A'), - ID3V2_FRAME_TRSN = GF_4CC('T','R','S','N'), - ID3V2_FRAME_TRSO = GF_4CC('T','R','S','O'), - ID3V2_FRAME_TSIZ = GF_4CC('T','S','I','Z'), - ID3V2_FRAME_TSRC = GF_4CC('T','S','R','C'), - ID3V2_FRAME_TSSE = GF_4CC('T','S','S','E'), - ID3V2_FRAME_TYER = GF_4CC('T','Y','E','R'), - ID3V2_FRAME_TXXX = GF_4CC('T','X','X','X'), - ID3V2_FRAME_UFID = GF_4CC('U','F','I','D'), - ID3V2_FRAME_USER = GF_4CC('U','S','E','R'), - ID3V2_FRAME_USLT = GF_4CC('U','S','L','T'), - ID3V2_FRAME_WCOM = GF_4CC('W','C','O','M'), - ID3V2_FRAME_WCOP = GF_4CC('W','C','O','P'), - ID3V2_FRAME_WOAF = GF_4CC('W','O','A','F'), - ID3V2_FRAME_WOAR = GF_4CC('W','O','A','R'), - ID3V2_FRAME_WOAS = GF_4CC('W','O','A','S'), - ID3V2_FRAME_WORS = GF_4CC('W','O','R','S'), - ID3V2_FRAME_WPAY = GF_4CC('W','P','A','Y'), - ID3V2_FRAME_WPUB = GF_4CC('W','P','U','B'), - ID3V2_FRAME_WXXX = GF_4CC('W','X','X','X') + GF_ID3V2_FRAME_AENC = GF_4CC('A','E','N','C'), + GF_ID3V2_FRAME_APIC = GF_4CC('A','P','I','C'), + GF_ID3V2_FRAME_COMM = GF_4CC('C','O','M','M'), + GF_ID3V2_FRAME_COMR = GF_4CC('C','O','M','R'), + GF_ID3V2_FRAME_ENCR = GF_4CC('E','N','C','R'), + GF_ID3V2_FRAME_EQUA = GF_4CC('E','Q','U','A'), + GF_ID3V2_FRAME_ETCO = GF_4CC('E','T','C','O'), + GF_ID3V2_FRAME_GEOB = GF_4CC('G','E','O','B'), + GF_ID3V2_FRAME_GRID = GF_4CC('G','R','I','D'), + GF_ID3V2_FRAME_IPLS = GF_4CC('I','P','L','S'), + GF_ID3V2_FRAME_LINK = GF_4CC('L','I','N','K'), + GF_ID3V2_FRAME_MCDI = GF_4CC('M','C','D','I'), + GF_ID3V2_FRAME_MLLT = GF_4CC('M','L','L','T'), + GF_ID3V2_FRAME_OWNE = GF_4CC('O','W','N','E'), + GF_ID3V2_FRAME_PRIV = GF_4CC('P','R','I','V'), + GF_ID3V2_FRAME_PCNT = GF_4CC('P','C','N','T'), + GF_ID3V2_FRAME_POPM = GF_4CC('P','O','P','M'), + GF_ID3V2_FRAME_POSS = GF_4CC('P','O','S','S'), + GF_ID3V2_FRAME_RBUF = GF_4CC('R','B','U','F'), + GF_ID3V2_FRAME_RVAD = GF_4CC('R','V','A','D'), + GF_ID3V2_FRAME_RVRB = GF_4CC('R','V','R','B'), + GF_ID3V2_FRAME_SYLT = GF_4CC('S','Y','L','T'), + GF_ID3V2_FRAME_SYTC = GF_4CC('S','Y','T','C'), + GF_ID3V2_FRAME_TALB = GF_4CC('T','A','L','B'), + GF_ID3V2_FRAME_TBPM = GF_4CC('T','B','P','M'), + GF_ID3V2_FRAME_TCMP = GF_4CC('T','C','M','P'), + GF_ID3V2_FRAME_TCOM = GF_4CC('T','C','O','M'), + GF_ID3V2_FRAME_TCON = GF_4CC('T','C','O','N'), + GF_ID3V2_FRAME_TCOP = GF_4CC('T','C','O','P'), + GF_ID3V2_FRAME_TDAT = GF_4CC('T','D','A','T'), + GF_ID3V2_FRAME_TDLY = GF_4CC('T','D','L','Y'), + GF_ID3V2_FRAME_TDRC = GF_4CC('T','D','R','C'), + GF_ID3V2_FRAME_TENC = GF_4CC('T','E','N','C'), + GF_ID3V2_FRAME_TEXT = GF_4CC('T','E','X','T'), + GF_ID3V2_FRAME_TFLT = GF_4CC('T','F','L','T'), + GF_ID3V2_FRAME_TIME = GF_4CC('T','I','M','E'), + GF_ID3V2_FRAME_TIT1 = GF_4CC('T','I','T','1'), + GF_ID3V2_FRAME_TIT2 = GF_4CC('T','I','T','2'), + GF_ID3V2_FRAME_TIT3 = GF_4CC('T','I','T','3'), + GF_ID3V2_FRAME_TKEY = GF_4CC('T','K','E','Y'), + GF_ID3V2_FRAME_TLAN = GF_4CC('T','L','A','N'), + GF_ID3V2_FRAME_TLEN = GF_4CC('T','L','E','N'), + GF_ID3V2_FRAME_TMED = GF_4CC('T','M','E','D'), + GF_ID3V2_FRAME_TOAL = GF_4CC('T','O','A','L'), + GF_ID3V2_FRAME_TOFN = GF_4CC('T','O','F','N'), + GF_ID3V2_FRAME_TOLY = GF_4CC('T','O','L','Y'), + GF_ID3V2_FRAME_TOPE = GF_4CC('T','O','P','E'), + GF_ID3V2_FRAME_TORY = GF_4CC('T','O','R','Y'), + GF_ID3V2_FRAME_TOWN = GF_4CC('T','O','W','N'), + GF_ID3V2_FRAME_TPE1 = GF_4CC('T','P','E','1'), + GF_ID3V2_FRAME_TPE2 = GF_4CC('T','P','E','2'), + GF_ID3V2_FRAME_TPE3 = GF_4CC('T','P','E','3'), + GF_ID3V2_FRAME_TPE4 = GF_4CC('T','P','E','4'), + GF_ID3V2_FRAME_TPOS = GF_4CC('T','P','E','5'), + GF_ID3V2_FRAME_TPUB = GF_4CC('T','P','U','B'), + GF_ID3V2_FRAME_TRCK = GF_4CC('T','R','C','K'), + GF_ID3V2_FRAME_TRDA = GF_4CC('T','R','D','A'), + GF_ID3V2_FRAME_TRSN = GF_4CC('T','R','S','N'), + GF_ID3V2_FRAME_TRSO = GF_4CC('T','R','S','O'), + GF_ID3V2_FRAME_TSIZ = GF_4CC('T','S','I','Z'), + GF_ID3V2_FRAME_TSRC = GF_4CC('T','S','R','C'), + GF_ID3V2_FRAME_TSSE = GF_4CC('T','S','S','E'), + GF_ID3V2_FRAME_TYER = GF_4CC('T','Y','E','R'), + GF_ID3V2_FRAME_TXXX = GF_4CC('T','X','X','X'), + GF_ID3V2_FRAME_UFID = GF_4CC('U','F','I','D'), + GF_ID3V2_FRAME_USER = GF_4CC('U','S','E','R'), + GF_ID3V2_FRAME_USLT = GF_4CC('U','S','L','T'), + GF_ID3V2_FRAME_WCOM = GF_4CC('W','C','O','M'), + GF_ID3V2_FRAME_WCOP = GF_4CC('W','C','O','P'), + GF_ID3V2_FRAME_WOAF = GF_4CC('W','O','A','F'), + GF_ID3V2_FRAME_WOAR = GF_4CC('W','O','A','R'), + GF_ID3V2_FRAME_WOAS = GF_4CC('W','O','A','S'), + GF_ID3V2_FRAME_WORS = GF_4CC('W','O','R','S'), + GF_ID3V2_FRAME_WPAY = GF_4CC('W','P','A','Y'), + GF_ID3V2_FRAME_WPUB = GF_4CC('W','P','U','B'), + GF_ID3V2_FRAME_WXXX = GF_4CC('W','X','X','X'), } GF_ID3v2FrameType; +/*! tag base types*/ +enum +{ + /*! tag is a string*/ + GF_ITAG_STR=0, + /*! tag is an int*/ + GF_ITAG_INT, + /*! tag is a fraction*/ + GF_ITAG_FRAC, + /*! tag is a boolean*/ + GF_ITAG_BOOL, + /*! tag is a string but name is matched as substring*/ + GF_ITAG_SUBSTR, +}; +/*! finds a tag by its ID3 value + \param id3tag ID3 tag value + \return corresponding tag index, -1 if not found +*/ +s32 gf_itags_find_by_id3tag(u32 id3tag); + +/*! finds a tag by its itunes value + \param itag itunes tag value + \return corresponding tag index, -1 if not found +*/ +s32 gf_itags_find_by_itag(u32 itag); + +/*! finds a tag by its name + \param tag_name tag name + \return corresponding tag index, -1 if not found +*/ +s32 gf_itags_find_by_name(const char *tag_name); + +/*! gets tag associated type + \param tag_idx tag index + \return corresponding tag type, 0 if error +*/ +u32 gf_itags_get_type(u32 tag_idx); + +/*! gets tag associated name + \param tag_idx tag index + \return corresponding tag name, NULL if error +*/ +const char *gf_itags_get_name(u32 tag_idx); + +/*! gets tag associated itunes tag + \param tag_idx tag index + \return corresponding itunes tag, 0 if error +*/ +u32 gf_itags_get_itag(u32 tag_idx); + +/*! gets tag associated id3 tag + \param tag_idx tag index + \return corresponding id3 tag, 0 if error +*/ +u32 gf_itags_get_id3tag(u32 tag_idx); + +/*! enumerates tags + \param tag_idx tag index, increased at each call + \param itag set to itunes tag value - may be NULL + \param id3tag set to ID3 tag value - may be NULL + \param type set to tag type - may be NULL + \return tag name, NULL if error +*/ +const char *gf_itags_enum_tags(u32 *tag_idx, u32 *itag, u32 *id3tag, u32 *type); + +/*! gets genre name by genre tag +\param tag genre tag (from 1 to max number of ID3 genres) +\return genre name, NULL if not found*/ +const char *gf_id3_get_genre(u32 tag); + +/*! gets genre tag by genre name +\param name genre name +\return genre tag, 0 if not found*/ +u32 gf_id3_get_genre_tag(const char *name); + + /*! meta types from box_code_meta.c - fileimport.c */ enum {
View file
gpac-1.0.0.tar.gz/include/gpac/crypt_tools.h -> gpac-1.0.1.tar.gz/include/gpac/crypt_tools.h
Changed
@@ -176,7 +176,7 @@ { /*! list of track infos*/ GF_List *tcis; - /*! global for all tracks unless overriden*/ + /*! global for all tracks unless overridden*/ u32 def_crypt_type; /*! indicates a common key is used*/ Bool has_common_key;
View file
gpac-1.0.0.tar.gz/include/gpac/download.h -> gpac-1.0.1.tar.gz/include/gpac/download.h
Changed
@@ -172,6 +172,8 @@ /*file is stored in memory, and the cache name is set to gpac://%u@%p, where %d is the size in bytes and %d is the the pointer to the memory. Memory cached files are destroyed upon downloader destruction*/ GF_NETIO_SESSION_MEMORY_CACHE = 1<<4, + /*! do not delete files after download*/ + GF_NETIO_SESSION_KEEP_CACHE = 1<<5, } GF_NetIOFlags;
View file
gpac-1.0.0.tar.gz/include/gpac/events.h -> gpac-1.0.1.tar.gz/include/gpac/events.h
Changed
@@ -127,7 +127,7 @@ /*GF_EVENT_SIZE*/ u8 type; /*width and height*/ - u16 width, height; + u32 width, height; } GF_EventSize; /*! Video setup (2D or 3D) event @@ -138,7 +138,7 @@ /*GF_EVENT_VIDEO_SETUP*/ u8 type; /*width and height of visual surface to allocate*/ - u16 width, height; + u32 width, height; /*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)*/ @@ -370,6 +370,22 @@ Bool activate; } GF_EventSensorRequest; + +/*! Clipboard + event proc return value: true if text has been set for COPY, ignored otherwise +*/ +typedef struct +{ + /*GF_EVENT_MESSAGE*/ + u8 type; + /* + - const char * for PASTE_TEXT + - char * for COPY_TEXT, must be freed by caller + */ + char *text; +} GF_EventClipboard; + + /*! Event object*/ typedef union { @@ -396,6 +412,7 @@ GF_EventOpenFile open_file; GF_EventAddonConnect addon_connect; GF_EventSensorRequest activate_sensor; + GF_EventClipboard clipboard; } GF_Event; /*! @} */
View file
gpac-1.0.0.tar.gz/include/gpac/events_constants.h -> gpac-1.0.1.tar.gz/include/gpac/events_constants.h
Changed
@@ -196,11 +196,9 @@ */ GF_EVENT_SCENE_SIZE, GF_EVENT_SHOWHIDE, /*window show/hide (minimized or other). */ - GF_EVENT_SHOWHIDE_NOTIF, /*window has been show/hide (minimized or other). This is 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_MOVE_NOTIF, /*move window*/ GF_EVENT_REFRESH, /*window needs repaint (whenever needed, eg restore, hide->show, background refresh, paint)*/ GF_EVENT_QUIT, /*app is being closed - associated structure is evt.message to carry any potential reason for quiting*/ /*video hw setup message: @@ -243,6 +241,7 @@ GF_EVENT_TEXT_EDITING_START, GF_EVENT_TEXT_EDITING_END, + //fire when quality change is detected by compositor GF_EVENT_QUALITY_SWITCHED, //fire when timeshift depth changes GF_EVENT_TIMESHIFT_DEPTH, @@ -256,8 +255,6 @@ GF_EVENT_ADDON_DETECTED, - GF_EVENT_RELOAD, - GF_EVENT_SENSOR_ORIENTATION, GF_EVENT_SENSOR_REQUEST, } GF_EventType;
View file
gpac-1.0.0.tar.gz/include/gpac/filters.h -> gpac-1.0.1.tar.gz/include/gpac/filters.h
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2017-2019 + * Copyright (c) Telecom ParisTech 2017-2020 * All rights reserved * * This file is part of GPAC / filters sub-project @@ -485,6 +485,10 @@ GF_FS_STATS_FILTER_MUX, /*! raw output (file, socket, pipe) filter type*/ GF_FS_STATS_FILTER_RAWOUT, + /*! media sink (video out, audio out, ...) filter type*/ + GF_FS_STATS_FILTER_MEDIA_SINK, + /*! media source (capture audio or video ...) filter type*/ + GF_FS_STATS_FILTER_MEDIA_SOURCE, } GF_FSFilterType; /*! Filter statistics object*/ @@ -542,9 +546,13 @@ u32 stream_type; /*!set to codecid of output PID if single output, GF_CODECID_NONE otherwise*/ u32 codecid; + /*! timestamp and timescale of last packet emitted on output pids*/ + GF_Fraction64 last_ts_sent; + /*! timestamp and timescale of last packet droped on input pids*/ + GF_Fraction64 last_ts_drop; } GF_FilterStats; -/*! Gets number of active filters in the session +/*! Gets statistics for a given filter index in the session \param session filter session \param idx index of filter to query \param stats statistics for filter @@ -581,9 +589,16 @@ \param val value of filter option to update \param propagate_mask propagation flags - 0 means no propagation */ - void gf_fs_send_update(GF_FilterSession *session, const char *fid, GF_Filter *filter, const char *name, const char *val, GF_EventPropagateType propagate_mask); + +/*! Loads JS script for filter session +\param session filter session +\param jsfile path to local JS script file to use +\return error if any +*/ +GF_Err gf_fs_load_script(GF_FilterSession *session, const char *jsfile); + /*! @} */ @@ -818,6 +833,8 @@ GF_PROP_PID_ID = GF_4CC('P','I','D','I'), GF_PROP_PID_ESID = GF_4CC('E','S','I','D'), GF_PROP_PID_ITEM_ID = GF_4CC('I','T','I','D'), + GF_PROP_PID_ITEM_NUM = GF_4CC('I','T','I','X'), + GF_PROP_PID_TRACK_NUM = GF_4CC('P','I','D','X'), GF_PROP_PID_SERVICE_ID = GF_4CC('P','S','I','D'), GF_PROP_PID_CLOCK_ID = GF_4CC('C','K','I','D'), GF_PROP_PID_DEPENDENCY_ID = GF_4CC('D','P','I','D'), @@ -981,8 +998,10 @@ GF_PROP_PID_XLINK = GF_4CC('X','L','N','K'), GF_PROP_PID_CLAMP_DUR = GF_4CC('D','C','M','D'), GF_PROP_PID_HLS_PLAYLIST = GF_4CC('H','L','V','P'), + GF_PROP_PID_HLS_GROUPID = GF_4CC('H','L','G','I'), GF_PROP_PID_DASH_CUE = GF_4CC('D','C','U','E'), GF_PROP_PID_DASH_SEGMENTS = GF_4CC('D','C','N','S'), + GF_PROP_PID_CODEC = GF_4CC('C','O','D','S'), GF_PROP_PID_SINGLE_SCALE = GF_4CC('D','S','T','S'), GF_PROP_PID_UDP = GF_4CC('P','U','D','P'), @@ -995,7 +1014,7 @@ GF_PROP_PID_COLR_CHROMALOC = GF_4CC('C','L','O','C'), GF_PROP_PID_COLR_SPACE = GF_4CC('C','S','P','C'), GF_PROP_PID_SRC_MAGIC = GF_4CC('P','S','M','G'), - GF_PROP_PID_TRACK_INDEX = GF_4CC('T','I','D','X'), + GF_PROP_PID_MUX_INDEX = GF_4CC('T','I','D','X'), GF_PROP_NO_TS_LOOP = GF_4CC('N','T','S','L'), GF_PROP_PCK_FRAG_START = GF_4CC('P','F','R','B'), GF_PROP_PCK_FRAG_RANGE = GF_4CC('P','F','R','R'), @@ -2043,10 +2062,11 @@ \param filter the target filter \param url url of source to connect to, with optional arguments. \param parent_url url of parent if any +\param inherit_args if GF_TRUE, the source to connect will inherit arguments of the target filter's destination \param err return code - can be NULL \return the new source filter instance or NULL if error */ -GF_Filter *gf_filter_connect_source(GF_Filter *filter, const char *url, const char *parent_url, GF_Err *err); +GF_Filter *gf_filter_connect_source(GF_Filter *filter, const char *url, const char *parent_url, Bool inherit_args, GF_Err *err); /*! Connects a destination to this filter \param filter the target filter @@ -2214,6 +2234,15 @@ */ GF_Err gf_filter_reconnect_output(GF_Filter *filter); + +/*! Indicates that the filter accept and can process events coming from outside the filter chain, typically used by application firing events. + The event is sent on the process_event function with no associated PID. +\param filter the target filter +\param enable_events if GF_TRUE, the filter is considered an event target +\return error if any +*/ +GF_Err gf_filter_set_event_target(GF_Filter *filter, Bool enable_events); + /*! Looks for a built-in property value marked as informative on a filter on all PIDs (inputs and output) This is a recursive call on both input and ouput chain. There is no guarantee that a queried property will still be valid at the setter side upon returning the call, the setter could have @@ -2553,6 +2582,21 @@ */ Bool gf_filter_is_alias(GF_Filter *filter); +/*! checks if the given filter is in the chain ending up at parent +\param parent end of filter chain to check +\param filter target filter to check +\return GF_TRUE if filter is present in the parent chain, GF_FALSE otherwise +*/ +Bool gf_filter_in_parent_chain(GF_Filter *parent, GF_Filter *filter); + + +/*! Gets statistics for filter +\param filter filter session +\param stats statistics for filter +\return error code if any +*/ +GF_Err gf_filter_get_stats(GF_Filter *filter, GF_FilterStats *stats); + /*! @} */ @@ -2894,8 +2938,7 @@ */ GF_Err gf_filter_pid_copy_properties(GF_FilterPid *dst_pid, GF_FilterPid *src_pid); -/*! Push a new set of properties on destination PID, using all properties from source PID. -Old properties of the destination are first copied to the new property set before copying the ones from the source PID, potentially filtering them. +/*! Push a new set of properties on destination PID, using all properties from source PID, potentially filtering them. Currently defined properties are not reseted. \param dst_pid the destination filter PID \param src_pid the source filter PID \param filter_prop callback filtering function @@ -3480,8 +3523,10 @@ GF_FILTER_SAP_2, /*! open gop */ GF_FILTER_SAP_3, - /*! GDR */ + /*! roll period (GDR or audio roll) - roll distance must be indicated in packet */ GF_FILTER_SAP_4, + /*! Audio preroll period - roll distance must be indicated in packet */ + GF_FILTER_SAP_4_PROL } GF_FilterSAPType; /*! Sets packet SAP type
View file
gpac-1.0.0.tar.gz/include/gpac/internal/avilib.h -> gpac-1.0.1.tar.gz/include/gpac/internal/avilib.h
Changed
@@ -234,6 +234,9 @@ void* extradata; unsigned int extradata_size; + + // add a new riff chunk after this amount of bytes + u64 new_riff_threshold; } avi_t; #define AVI_MODE_WRITE 0 @@ -306,7 +309,7 @@ #define IBM_FORMAT_ALAW (0x0102) #define IBM_FORMAT_ADPCM (0x0103) -avi_t* AVI_open_output_file(char * filename); +avi_t* AVI_open_output_file(char * filename, u64 opendml_threshold); void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); void AVI_set_audio(avi_t *AVI, int channels, int rate, int bits, int format, int mp3rate); int AVI_write_frame(avi_t *AVI, u8 *data, int bytes, int keyframe);
View file
gpac-1.0.0.tar.gz/include/gpac/internal/compositor_dev.h -> gpac-1.0.1.tar.gz/include/gpac/internal/compositor_dev.h
Changed
@@ -1343,7 +1343,7 @@ #ifndef GPAC_DISABLE_SVG -GF_Err gf_term_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl); +GF_Err gf_sc_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl); Fixed gf_sc_svg_convert_length_to_display(GF_Compositor *sr, SVG_Length *length); char *gf_scene_resolve_xlink(GF_Node *node, char *the_url); #endif @@ -1742,8 +1742,12 @@ /*list of M_KeyNavigator nodes*/ GF_List *keynavigators; + + /*list of attached Inline nodes*/ + GF_List *attached_inlines; #endif + Bool disable_hitcoord_notif; u32 addon_position, addon_size_factor; @@ -1798,7 +1802,7 @@ /*selects given ODM for dynamic scenes*/ void gf_scene_select_object(GF_Scene *scene, GF_ObjectManager *odm); /*restarts dynamic scene from given time: scene graph is not reseted, objects are just restarted -instead of closed and reopened. If a media control is present on inline, from_time is overriden by MC range*/ +instead of closed and reopened. If a media control is present on inline, from_time is overridden by MC range*/ void gf_scene_restart_dynamic(GF_Scene *scene, s64 from_time, Bool restart_only, Bool disable_addon_check); void gf_scene_insert_pid(GF_Scene *scene, GF_SceneNamespace *sns, GF_FilterPid *pid, Bool is_in_iod); @@ -2310,7 +2314,7 @@ Bool config_changed; /*currently valid properties of the object*/ - u32 width, height, stride, pixel_ar, pixelformat; + u32 width, height, stride, pixel_ar, pixelformat, bitrate; Bool is_flipped; u32 sample_rate, num_channels, afmt, bytes_per_sec; u64 channel_config;
View file
gpac-1.0.0.tar.gz/include/gpac/internal/isomedia_dev.h -> gpac-1.0.1.tar.gz/include/gpac/internal/isomedia_dev.h
Changed
@@ -1818,7 +1818,7 @@ typedef struct { GF_ISOM_FULL_BOX - u32 sampleCount; + u32 sampleCount, sample_alloc; /*each dep type is packed on 1 byte*/ u8 *sample_info; } GF_SampleDependencyTypeBox; @@ -1948,7 +1948,8 @@ u32 currentEntryIndex; Bool no_sync_found; - Bool skip_sample_groups; + + u32 r_last_chunk_num, r_last_sample_num, r_last_offset_in_chunk; } GF_SampleTableBox; GF_Err stbl_AppendTrafMap(GF_SampleTableBox *stbl, Bool is_seg_start, u64 seg_start_offset, u64 frag_start_offset, u8 *moof_template, u32 moof_template_size, u64 sidx_start, u64 sidx_end); @@ -1966,7 +1967,6 @@ GF_Err stbl_SetDependencyType(GF_SampleTableBox *stbl, u32 sampleNumber, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant); GF_Err stbl_AppendDependencyType(GF_SampleTableBox *stbl, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant); -GF_Err stbl_AddDependencyType(GF_SampleTableBox *stbl, u32 sampleNumber, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant); typedef struct { @@ -2560,13 +2560,29 @@ typedef struct { + u32 Duration; + u32 size; + u32 flags; + s32 CTS_Offset; + + /*internal*/ + u32 SAP_type; + u64 dts; + u32 nb_pack; +} GF_TrunEntry; + + +typedef struct +{ GF_ISOM_FULL_BOX u32 sample_count; /*the following are optional fields */ /* unsigned for version 0 */ s32 data_offset; + + u32 nb_samples, sample_alloc; /*can be empty*/ - GF_List *entries; + GF_TrunEntry *samples; /*only for trun, ignored for ctrn*/ u32 first_sample_flags; @@ -2598,19 +2614,6 @@ u32 gf_isom_ctrn_field_size_bits(u32 field_idx); #endif -typedef struct -{ - u32 Duration; - u32 size; - u32 flags; - s32 CTS_Offset; - - /*internal*/ - u32 SAP_type; - u64 dts; - u32 nb_pack; -} GF_TrunEntry; - #endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ @@ -3607,8 +3610,6 @@ /*regular file IO*/ #define GF_ISOM_DATA_FILE 0x01 -/*File Mapping object, read-only mode on complete files (no download)*/ -#define GF_ISOM_DATA_FILE_MAPPING 0x02 /*External file object. Needs implementation*/ #define GF_ISOM_DATA_FILE_EXTERN 0x03 /*regular memory IO*/ @@ -3681,11 +3682,6 @@ GF_DataMap *gf_isom_fdm_new_temp(const char *sTempPath); #endif -/*file-mapping, read only*/ -GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode); -void gf_isom_fmo_del(GF_FileMappingDataMap *ptr); -u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, u8 *buffer, u32 bufferLength, u64 fileOffset); - #ifndef GPAC_DISABLE_ISOM_WRITE u64 gf_isom_datamap_get_offset(GF_DataMap *map); GF_Err gf_isom_datamap_add_data(GF_DataMap *ptr, u8 *data, u32 dataSize); @@ -3981,14 +3977,14 @@ GF_Err stbl_AddRedundant(GF_SampleTableBox *stbl, u32 sampleNumber); /*REMOVE functions*/ -GF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 LastAUDefDuration); -GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber); -GF_Err stbl_RemoveSize(GF_SampleTableBox *stbl, u32 sampleNumber); -GF_Err stbl_RemoveChunk(GF_SampleTableBox *stbl, u32 sampleNumber); +GF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples, u32 LastAUDefDuration); +GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples); +GF_Err stbl_RemoveSize(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples); +GF_Err stbl_RemoveChunk(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples); GF_Err stbl_RemoveRAP(GF_SampleTableBox *stbl, u32 sampleNumber); GF_Err stbl_RemoveShadow(GF_SampleTableBox *stbl, u32 sampleNumber); GF_Err stbl_RemovePaddingBits(GF_SampleTableBox *stbl, u32 SampleNumber); -GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber); +GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber, u32 nb_samples); GF_Err stbl_RemoveSubSample(GF_SampleTableBox *stbl, u32 SampleNumber); GF_Err stbl_RemoveSampleGroup(GF_SampleTableBox *stbl, u32 SampleNumber); @@ -4040,7 +4036,6 @@ void AV1_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *av1, GF_MediaBox *mdia); void AV1_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *av1); GF_Err reftype_AddRefTrack(GF_TrackReferenceTypeBox *ref, GF_ISOTrackID trackID, u16 *outRefIndex); -GF_XMLBox *gf_isom_get_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool *is_binary); Bool gf_isom_cenc_has_saiz_saio_track(GF_SampleTableBox *stbl, u32 scheme_type); #ifndef GPAC_DISABLE_ISOM_FRAGMENTS @@ -4318,7 +4313,6 @@ #ifndef GPAC_DISABLE_VTT -GF_Err gf_isom_update_webvtt_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, const char *config); GF_ISOSample *gf_isom_webvtt_to_sample(void *samp); typedef struct
View file
gpac-1.0.0.tar.gz/include/gpac/isomedia.h -> gpac-1.0.1.tar.gz/include/gpac/isomedia.h
Changed
@@ -194,7 +194,6 @@ GF_ISOM_MEDIA_JPEG = GF_4CC( 'j', 'p', 'e', 'g' ), GF_ISOM_MEDIA_JP2 = GF_4CC( 'j', 'p', '2', ' ' ), GF_ISOM_MEDIA_PNG = GF_4CC( 'p', 'n', 'g', ' ' ), - GF_ISOM_MEDIA_TMCD = GF_4CC( 't', 'm', 'c', 'd' ), }; @@ -454,6 +453,19 @@ }; +/*! sample roll information type*/ +typedef enum +{ + /*! no roll info associated*/ + GF_ISOM_SAMPLE_ROLL_NONE=0, + /*! roll info describes a roll operation*/ + GF_ISOM_SAMPLE_ROLL, + /*! roll info describes an audio preroll*/ + GF_ISOM_SAMPLE_PREROLL, + /*! roll info describes audio preroll but is not set for this sample*/ + GF_ISOM_SAMPLE_PREROLL_NONE +} GF_ISOSampleRollType; + #ifndef GPAC_DISABLE_ISOM #include <gpac/mpeg4_odf.h> @@ -619,11 +631,6 @@ */ Bool gf_isom_is_JPEG2000(GF_ISOFile *isom_file); -/*! gets file size of an ISO file -\param isom_file the target ISO file -\return the file size in bytes -*/ -u64 gf_isom_get_file_size(GF_ISOFile *isom_file); /*! checks if a given four character code matches a known video handler type (vide, auxv, pict, ...) \param mtype the four character code to check @@ -1533,6 +1540,7 @@ \param isom_file the target ISO file \param trace the file object to dump to \param skip_init does not dump init segment structure +\param skip_samples does not dump sample tables \return error if any */ GF_Err gf_isom_dump(GF_ISOFile *isom_file, FILE *trace, Bool skip_init, Bool skip_samples); @@ -2223,7 +2231,7 @@ \param dv_profile the Dolby Vision profile \return error if any */ -GF_Err gf_isom_set_dolby_vision_profile(GF_ISOFile* isom_file, u32 trackNumber, u32 StreamDescriptionIndex, u32 dv_profile); +GF_Err gf_isom_set_dolby_vision_profile(GF_ISOFile* isom_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 dv_profile); /*! sets image sequence coding constraints (mostly used for HEIF image files) @@ -2519,11 +2527,6 @@ */ u32 gf_isom_get_mpeg4_subtype(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleDescriptionIndex); -/*! checks if files has root OD/IOD or not -\param isom_file the target ISO file -\return GF_TRUE if the file has a root OD or IOD */ -Bool gf_isom_has_root_od(GF_ISOFile *isom_file); - /*! fetches the root OD of a file (can be NULL, OD or IOD, you have to check its tag) \param isom_file the target ISO file \return the OD/IOD if any. Caller must destroy the descriptor @@ -2534,7 +2537,7 @@ \param isom_file the target ISO file \param disable if TRUE, ODs and ESDs will not be converted */ -void gf_isom_disable_odf_conversion(GF_ISOFile *movie, Bool disable); +void gf_isom_disable_odf_conversion(GF_ISOFile *isom_file, Bool disable); /*! checks the presence of a track in rood OD/IOD \param isom_file the target ISO file @@ -3035,7 +3038,7 @@ \param sampleDescriptionIndex the target sample description index \return the DOVI config - user is responsible for deleting it */ -GF_DOVIDecoderConfigurationRecord* gf_isom_dovi_config_get(GF_ISOFile* isom_file, u32 trackNumber, u32 DescriptionIndex); +GF_DOVIDecoderConfigurationRecord* gf_isom_dovi_config_get(GF_ISOFile* isom_file, u32 trackNumber, u32 sampleDescriptionIndex); /*! checks if some tracks in file needs layer reconstruction \param isom_file the target ISO file @@ -3076,6 +3079,12 @@ */ GF_ISONaluExtractMode gf_isom_get_nalu_extract_mode(GF_ISOFile *isom_file, u32 trackNumber); +/*! gets the composition offset shift if any for track using negative ctts +\param isom_file the target ISO file +\param trackNumber the target track +\return the composition offset shift or 0 +*/ +s32 gf_isom_get_composition_offset_shift(GF_ISOFile *isom_file, u32 trackNumber); #ifndef GPAC_DISABLE_ISOM_WRITE /*! creates a new AVC sample description @@ -3418,7 +3427,7 @@ \param dsi_size set to the size of the OPUS decoder config \return error if any */ -GF_Err gf_isom_opus_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, u8 **dsi, u32 *dsi_size); +GF_Err gf_isom_opus_config_get(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleDescriptionIndex, u8 **dsi, u32 *dsi_size); #ifndef GPAC_DISABLE_ISOM_WRITE @@ -3533,8 +3542,21 @@ */ void gf_isom_set_single_moof_mode(GF_ISOFile *isom_file, Bool mode); -GF_Err gf_isom_get_file_offset_for_time(GF_ISOFile *movie, Double start_time, u64 *max_offset); -GF_Err gf_isom_get_sidx_duration(GF_ISOFile *movie, u64 *sidx_dur, u32 *sidx_timescale); +/*! gets closest file offset for the given time, when the file uses an segment index (sidx) +\param isom_file the target ISO file +\param start_time the start time in seconds +\param offset set to the file offset of the segment containing the desired time +\return error if any +*/ +GF_Err gf_isom_get_file_offset_for_time(GF_ISOFile *isom_file, Double start_time, u64 *offset); + +/*! gets sidx duration, when the file uses an segment index (sidx) +\param isom_file the target ISO file +\param sidx_dur set to the total duration documented in the segment index +\param sidx_timescale set timescale used to represent the duration in the segment index +\return error if any +*/ +GF_Err gf_isom_get_sidx_duration(GF_ISOFile *isom_file, u64 *sidx_dur, u32 *sidx_timescale); /*! refreshes a fragmented file @@ -4019,12 +4041,6 @@ */ GF_Err gf_isom_flush_fragments(GF_ISOFile *isom_file, Bool last_segment); -/*! gets name of current segment (or last segment if called between close_segment and start_segment) -\param isom_file the target ISO file -\return associated file name of the segment -*/ -const char *gf_isom_get_segment_name(GF_ISOFile *isom_file); - /*! sets fragment prft box info, written just before the moof \param isom_file the target ISO file \param reference_track_ID the ID of the track used as a reference for media timestamps @@ -4064,6 +4080,7 @@ */ GF_Err gf_isom_setup_track_fragment_template(GF_ISOFile *isom_file, GF_ISOTrackID TrackID, u8 *boxes, u32 boxes_size, u8 force_traf_flags); +#ifdef GF_ENABLE_CTRN /*! enables track fragment inheriting from a given traf. This shall only be set when the inherited traf shares exactly the same syntax except the sample sizes, this library does not compute which sample values can be inherited @@ -4074,6 +4091,7 @@ \return error if any */ GF_Err gf_isom_enable_traf_inherit(GF_ISOFile *isom_file, GF_ISOTrackID TrackID, GF_ISOTrackID BaseTrackID); +#endif /*! Track fragment options*/ typedef enum @@ -4166,15 +4184,17 @@ \return error if any */ GF_Err gf_isom_clone_pssh(GF_ISOFile *dst_file, GF_ISOFile *src_file, Bool in_moof); + + /*! sets roll information for a sample in a track fragment \param isom_file the target ISO file \param trackID the ID of the target track \param sample_number the sample number of the last sample -\param is_roll set to GF_TRUE to indicate the sample is a roll sample, GF_FALSE otherwise +\param roll_type indicate the sample roll type \param roll_distance set to the roll distance for a roll sample \return error if any */ -GF_Err gf_isom_fragment_set_sample_roll_group(GF_ISOFile *isom_file, GF_ISOTrackID trackID, u32 sample_number, Bool is_roll, s16 roll_distance); +GF_Err gf_isom_fragment_set_sample_roll_group(GF_ISOFile *isom_file, GF_ISOTrackID trackID, u32 sample_number, GF_ISOSampleRollType roll_type, s16 roll_distance); /*! sets rap information for a sample in a track fragment \param isom_file the target ISO file @@ -4501,11 +4521,17 @@ /*! dump as TTXT XML*/ GF_TEXTDUMPTYPE_TTXT = 0, /*! dump as TTXT XML with box */ - GF_TEXTDUMPTYPE_TTXT_BOXES = 1, + GF_TEXTDUMPTYPE_TTXT_BOXES, /*! dump as SRT*/ - GF_TEXTDUMPTYPE_SRT = 2, + GF_TEXTDUMPTYPE_SRT, /*! dump as SVG*/ - GF_TEXTDUMPTYPE_SVG = 3, + GF_TEXTDUMPTYPE_SVG, + /*! dump as TTXT chapters (omits empty text samples)*/ + GF_TEXTDUMPTYPE_TTXT_CHAP, + /*! dump as OGG chapters*/ + GF_TEXTDUMPTYPE_OGG_CHAP, + /*! dump as Zoom chapters*/ + GF_TEXTDUMPTYPE_ZOOM_CHAP } GF_TextDumpType; /*! dumps a text track to a file \param isom_file the target ISO file @@ -4561,14 +4587,6 @@ \return error if any */ GF_Err gf_isom_new_webvtt_description(GF_ISOFile *isom_file, u32 trackNumber, const char *URLname, const char *URNname, u32 *outDescriptionIndex, const char *config); -/*! updates a WebVTT sample description -\param isom_file the target ISO file -\param trackNumber the target track -\param sampleDescriptionIndex the target sample description index to update -\param config the WebVTT configuration string -\return error if any -*/ -GF_Err gf_isom_update_webvtt_description(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleDescriptionIndex, const char *config); #endif /*! gets WebVTT config for a sample description @@ -4603,15 +4621,6 @@ */ GF_Err gf_isom_new_stxt_description(GF_ISOFile *isom_file, u32 trackNumber, u32 type, const char *mime, const char *encoding, const char *config, u32 *outDescriptionIndex); -/*! updates simple streaming text config -\param isom_file the target ISO file -\param trackNumber the target track -\param encoding the text encoding, if any -\param config the configuration string, if any -\param sampleDescriptionIndex the target sample description index -\return error if any -*/ -GF_Err gf_isom_update_stxt_description(GF_ISOFile *isom_file, u32 trackNumber, const char *encoding, const char *config, u32 sampleDescriptionIndex); #endif // GPAC_DISABLE_ISOM_WRITE /*! gets XML streaming text config for a sample description @@ -4805,6 +4814,15 @@ \return error if any */ GF_Err gf_isom_text_sample_write_bs(const GF_TextSample *tx_samp, GF_BitStream *bs); + + +/*! formats sample as a regular GF_ISOSample. +The resulting sample will always be marked as random access +\param tx_samp the target text sample +\return the corresponding serialized ISO sample +*/ +GF_ISOSample *gf_isom_text_to_sample(const GF_TextSample *tx_samp); + /*! gets the serialized size of the text sample \param tx_samp the target text sample \return the serialized size @@ -4930,12 +4948,6 @@ \return a newly allocated ISMA sample with the parsed data */ GF_ISMASample *gf_isom_ismacryp_sample_from_data(u8 *data, u32 dataLength, Bool use_selective_encryption, u8 KI_length, u8 IV_length); -/*! rewrites ISMA sample as an ISO sample -\param s the ISMA sample to rewrite -\param dest the destination ISO sample -\return error if any -*/ -GF_Err gf_isom_ismacryp_sample_to_sample(const GF_ISMASample *s, GF_ISOSample *dest); /*! decodes ISMACryp sample based on sample and its descrition index \param isom_file the target ISO file @@ -5040,13 +5052,6 @@ } GF_CENCSampleAuxInfo; #ifndef GPAC_DISABLE_ISOM_WRITE -/*! removes protection info (does not perform decryption), for ISMA, OMA and CENC of a sample description -\param isom_file the target ISO file -\param trackNumber the target track -\param sampleDescriptionIndex the sample description index -\return error if any -*/ -GF_Err gf_isom_remove_track_protection(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleDescriptionIndex); /*! creates ISMACryp protection info for a sample description \param isom_file the target ISO file @@ -5166,18 +5171,6 @@ */ GF_Err gf_cenc_set_pssh(GF_ISOFile *isom_file, bin128 systemID, u32 version, u32 KID_count, bin128 *KID, u8 *data, u32 len, Bool use_piff); -/*! removes CENC SAI size info -\param isom_file the target ISO file -\param trackNumber the target track -\return error if any -*/ -GF_Err gf_isom_remove_cenc_saiz(GF_ISOFile *isom_file, u32 trackNumber); -/*! removes CENC SAI offset info -\param isom_file the target ISO file -\param trackNumber the target track -\return error if any -*/ -GF_Err gf_isom_remove_cenc_saio(GF_ISOFile *isom_file, u32 trackNumber); /*! removes CENC senc box info \param isom_file the target ISO file \param trackNumber the target track @@ -5190,11 +5183,6 @@ \return error if any */ GF_Err gf_isom_remove_samp_group_box(GF_ISOFile *isom_file, u32 trackNumber); -/*! removes CENC PSSH box -\param isom_file the target ISO file -\return error if any -*/ -GF_Err gf_isom_remove_pssh_box(GF_ISOFile *isom_file); #endif //GPAC_DISABLE_ISOM_WRITE @@ -5232,11 +5220,6 @@ */ GF_Err gf_isom_set_adobe_protection(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 scheme_type, u32 scheme_version, Bool is_selective_enc, char *metadata, u32 len); -/*! removes the IPMPX tools from files -\param isom_file the target ISO file -*/ -void gf_isom_ipmpx_remove_tool_list(GF_ISOFile *isom_file); - #endif /*GPAC_DISABLE_ISOM_WRITE*/ /*! checks of sample description is protected with CENC @@ -5330,16 +5313,6 @@ */ GF_Err gf_isom_get_pssh_info(GF_ISOFile *isom_file, u32 pssh_index, bin128 SystemID, u32 *version, u32 *KID_count, const bin128 **KIDs, const u8 **private_data, u32 *private_data_size); -/*! gets serialized PSS -\param isom_file the target ISO file -\param pssh_index 1-based index of PSSH to query, see \ref gf_isom_get_pssh_count -\param pssh_data set to a newly allocated buffer containing serialized PSSH - shall be freeed by caller -\param pssh_size set to the size of the allocated buffer -\return error if any -*/ -GF_Err gf_isom_get_pssh(GF_ISOFile *isom_file, u32 pssh_index, u8 **pssh_data, u32 *pssh_size); - - #ifndef GPAC_DISABLE_ISOM_DUMP /*! dumps ismacrypt protection of sample descriptions to xml trace \param isom_file the target ISO file @@ -5550,25 +5523,17 @@ */ GF_Err gf_isom_remove_meta_xml(GF_ISOFile *isom_file, Bool root_meta, u32 track_num); -/*! sets meta XML data from file - erase any previously (Binary)XML info +/*! sets meta XML data from file or memory - erase any previously (Binary)XML info \param isom_file the target ISO file \param root_meta if GF_TRUE uses meta at the file, otherwise uses meta at the movie level if track number is 0 \param track_num if GF_TRUE and root_meta is GF_FALSE, uses meta at the track level -\param XMLFileName the XML file to import as XML item +\param XMLFileName the XML file to import as XML item, or NULL if data is specified +\param data buffer containing XML data, or NULL if file is specified +\param data_size size of buffer in bytes, ignored if file is specified \param IsBinaryXML indicates if the content of the XML file is binary XML (BIM) or not \return error if any */ -GF_Err gf_isom_set_meta_xml(GF_ISOFile *isom_file, Bool root_meta, u32 track_num, char *XMLFileName, Bool IsBinaryXML); -/*! set meta XML data from memory - erase any previously (Binary)XML info -\param isom_file the target ISO file -\param root_meta if GF_TRUE uses meta at the file, otherwise uses meta at the movie level if track number is 0 -\param track_num if GF_TRUE and root_meta is GF_FALSE, uses meta at the track level -\param data buffer containing XML data -\param data_size size of buffer in bytes -\param IsBinaryXML indicates if the content of the buffer is binary XML (BIM) or not -\return error if any -*/ -GF_Err gf_isom_set_meta_xml_memory(GF_ISOFile *isom_file, Bool root_meta, u32 track_num, u8 *data, u32 data_size, Bool IsBinaryXML); +GF_Err gf_isom_set_meta_xml(GF_ISOFile *isom_file, Bool root_meta, u32 track_num, char *XMLFileName, unsigned char *data, u32 data_size, Bool IsBinaryXML); /*! gets next available item ID in a meta \param isom_file the target ISO file @@ -5722,6 +5687,7 @@ GF_ISOM_ITUNE_ENCODER = GF_4CC( 0xA9, 'e', 'n', 'c' ), GF_ISOM_ITUNE_ALBUM_ARTIST = GF_4CC( 'a', 'A', 'R', 'T' ), GF_ISOM_ITUNE_GAPLESS = GF_4CC( 'p', 'g', 'a', 'p' ), + GF_ISOM_ITUNE_CONDUCTOR = GF_4CC( 0xA9, 'c', 'o', 'n' ), } GF_ISOiTunesTag; /*! gets the given itunes tag info. @@ -5832,6 +5798,16 @@ @{ */ +/*! gets serialized subsample info for the sample +The buffer is formatted as N times [(u32)flags(u32)sub_size(u32)codec_param(u8)priority(u8) discardable] +If several subsample info are present, they are gathered by flags + +\param isom_file the target ISO file +\param trackNumber the target track +\param sampleNumber the target sample number +\param osize set to output buffer size +\return the serialized buffer, or NULL oif no associated subsample*/ +u8 *gf_isom_sample_get_subsamples_buffer(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleNumber, u32 *osize); /*! checks if a sample has subsample information \param isom_file the target ISO file @@ -5930,10 +5906,10 @@ \param trackNumber the target track \param sampleNumber the target sample number \param is_rap set to GF_TRUE if sample is a rap (open gop), GF_FALSE otherwise -\param has_roll set to GF_TRUE of sample has roll information, GF_FALSE otherwise +\param has_roll set to GF_ISOM_SAMPLE_ROLL if sample has roll information, GF_ISOM_SAMPLE_PREROLL if sample has preroll information, GF_ISOM_SAMPLE_ROLL_NONE otherwise \param roll_distance if sample has roll information, set to roll distance \return error if any*/ -GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleNumber, Bool *is_rap, Bool *has_roll, s32 *roll_distance); +GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleNumber, Bool *is_rap, GF_ISOSampleRollType *roll_type, s32 *roll_distance); /*! returns opaque data of sample group \param isom_file the target ISO file @@ -5988,11 +5964,11 @@ \param isom_file the target ISO file \param trackNumber the target track \param sampleNumber the target sample number -\param is_roll indicates that the sample is a roll recovery point +\param roll_type indicates the sample roll recovery type \param roll_distance indicates the roll distance before a correct decoding is produced \return error if any */ -GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleNumber, Bool is_roll, s16 roll_distance); +GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *isom_file, u32 trackNumber, u32 sampleNumber, GF_ISOSampleRollType roll_type, s16 roll_distance); /*! sets encryption group for a sample number \param isom_file the target ISO file
View file
gpac-1.0.0.tar.gz/include/gpac/main.h -> gpac-1.0.1.tar.gz/include/gpac/main.h
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2017-2019 + * Copyright (c) Telecom ParisTech 2017-2020 * All rights reserved * * This file is part of GPAC @@ -190,6 +190,10 @@ GF_PRINTARG_IS_APP = 1<<3, /*! insert an extra '-' at the begining*/ GF_PRINTARG_ADD_DASH = 1<<4, + /*! do not insert '-' before arg name*/ + GF_PRINTARG_NO_DASH = 1<<5, + /*! insert '-: before arg name*/ + GF_PRINTARG_COLON = 1<<6, /*! the generation is for markdown*/ GF_PRINTARG_MD = 1<<16, /*! the generation is for man pages*/
View file
gpac-1.0.0.tar.gz/include/gpac/media_tools.h -> gpac-1.0.1.tar.gz/include/gpac/media_tools.h
Changed
@@ -760,7 +760,7 @@ GF_Err gf_dasher_add_base_url(GF_DASHSegmenter *dasher, const char *base_url); /*! - Enable URL template - - may be overriden by the current profile + Enable URL template - - may be overridden by the current profile \param dasher the DASH segmenter object \param enable enable usage of URL template \param default_template template for the segment name @@ -772,7 +772,7 @@ GF_Err gf_dasher_enable_url_template(GF_DASHSegmenter *dasher, Bool enable, const char *default_template, const char *default_extension, const char *default_init_extension); /*! - Enable Segment Timeline template - may be overriden by the current profile + Enable Segment Timeline template - may be overridden by the current profile \param dasher the DASH segmenter object \param enable enable or disable \return error code if any @@ -780,7 +780,7 @@ GF_Err gf_dasher_enable_segment_timeline(GF_DASHSegmenter *dasher, Bool enable); /*! - Enables single segment - may be overriden by the current profile + Enables single segment - may be overridden by the current profile \param dasher the DASH segmenter object \param enable enable or disable \return error code if any @@ -789,7 +789,7 @@ GF_Err gf_dasher_enable_single_segment(GF_DASHSegmenter *dasher, Bool enable); /*! - Enable single file (with multiple segments) - may be overriden by the current profile + Enable single file (with multiple segments) - may be overridden by the current profile \param dasher the DASH segmenter object \param enable enable or disable \return error code if any @@ -797,7 +797,7 @@ GF_Err gf_dasher_enable_single_file(GF_DASHSegmenter *dasher, Bool enable); /*! - Sets bitstream switching mode - may be overriden by the current profile + Sets bitstream switching mode - may be overridden by the current profile \param dasher the DASH segmenter object \param bitstream_switching mode to use for bitstream switching \return error code if any @@ -1232,6 +1232,13 @@ u32 gf_hinter_track_get_bandwidth(GF_RTPHinter *tkHinter); /*! + Force file to use no random offsets for sequence number and time, if supported by server +\param tkHinter track hinter object +\return error if any +*/ +GF_Err gf_hinter_track_force_no_offsets(GF_RTPHinter *tkHinter); + +/*! Gets track hinter flags \param tkHinter track hinter object \return hint flags for this object
View file
gpac-1.0.0.tar.gz/include/gpac/mpd.h -> gpac-1.0.1.tar.gz/include/gpac/mpd.h
Changed
@@ -324,6 +324,14 @@ /*! Macro for common attributes and elements (representation, AdaptationSet, Preselection, ...) +not yet implemented; + GF_List *inband_event_stream; \ + GF_List *switching; \ + GF_List *random_access; \ + GF_List *group_labels; \ + GF_List *labels; \ + GF_List *content_popularity; \ + MANDATORY: mime_type codecs @@ -343,11 +351,14 @@ Double max_playout_rate; \ Bool coding_dependency; \ GF_MPD_ScanType scan_type; \ + u32 selection_priority; \ + char *tag; \ GF_List *frame_packing; \ GF_List *audio_channels; \ GF_List *content_protection; \ GF_List *essential_properties; \ GF_List *supplemental_properties; \ + GF_List *producer_reference_time; \ GF_List *isobmf_tracks; \ /*! common attributes*/ @@ -356,6 +367,33 @@ GF_MPD_COMMON_ATTRIBUTES_ELEMENTS } GF_MPD_CommonAttributes; +/*! type of reference clock */ +typedef enum +{ + GF_MPD_PRODUCER_REF_ENCODER = 0, + GF_MPD_PRODUCER_REF_CAPTURED, + GF_MPD_PRODUCER_REF_APPLICATION, +} GF_MPD_ProducerRefType; + +/*! producer reference time*/ +typedef struct { + /*! ID of producer */ + u32 ID; + /*! is timing inband (prft in segment) */ + Bool inband; + /*! clock type*/ + GF_MPD_ProducerRefType type; + /*! scheme for application ref type*/ + char *scheme; + /*! wallclock time as UTC timestamp*/ + char *wallclock; + /*! presentation time in timescale of the Representation*/ + u64 presentation_time; + /*! UTC timing desc if any/*/ + GF_MPD_Descriptor *utc_timing; +} GF_MPD_ProducerReferenceTime; + + /*! SubRepresentation*/ typedef struct { /*! inherits common attributes*/ @@ -471,6 +509,8 @@ u32 moof_sn_inc; /*! ID of last dynamic period in manifest*/ u32 last_dyn_period_id; + /*! one subdur was forced on this rep due to looping*/ + Bool subdur_forced; } GF_DASH_SegmenterContext; /*! Segment context - GPAC internal, used to produce HLS manifests and segment lists/timeline*/ @@ -553,6 +593,9 @@ u32 nb_chan; /*! video FPS - HLS only*/ Double fps; + /*! groupID (for HLS)*/ + const char *groupID; + /*! user assigned m3u8 name for this representation*/ const char *m3u8_name; /*! generated m3u8 name if no user-assigned one*/ @@ -740,6 +783,11 @@ /*! set during parsing, to set during authoring, won't be freed by GPAC*/ const char *xml_namespace; + /*! UTC timing desc if any/*/ + GF_List *utc_timings; + + /* internal variables for dasher*/ + /*! dasher init NTP clock in ms - GPAC internal*/ u64 gpac_init_ntp_ms; /*! dasher next generation time NTP clock in ms - GPAC internal*/ @@ -790,6 +838,13 @@ \param root the DOM description of the segment URL */ void gf_mpd_parse_segment_url(GF_List *container, GF_XMLNode *root); + +/*! parses a xsDateTime +\param attr the date time value +\return value as UTC timestamp +*/ +u64 gf_mpd_parse_date(const char * const attr); + /*! frees a GF_MPD_URL structure (type-casted to void *) \param _item the target GF_MPD_URL */
View file
gpac-1.0.0.tar.gz/include/gpac/mpeg4_odf.h -> gpac-1.0.1.tar.gz/include/gpac/mpeg4_odf.h
Changed
@@ -1466,8 +1466,7 @@ GF_DOVIDecoderConfigurationRecord *gf_odf_dovi_cfg_read_bs(GF_BitStream *bs); /*! writes DolbyVision config to buffer \param cfg the DolbyVision config to write -\param outData set to an allocated encoded buffer - it is the caller responsability to free this -\param outSize set to the encoded buffer size +\param bs the bitstream object in which to write the config \return error if any */ GF_Err gf_odf_dovi_cfg_write_bs(GF_DOVIDecoderConfigurationRecord *cfg, GF_BitStream *bs);
View file
gpac-1.0.0.tar.gz/include/gpac/mpegts.h -> gpac-1.0.1.tar.gz/include/gpac/mpegts.h
Changed
@@ -586,6 +586,7 @@ /*! MPEG-2 TS demuxer TEMI location*/ typedef struct { + u32 pid; u32 timeline_id; //for now we only support one URL announcement const char *external_URL; @@ -597,6 +598,7 @@ /*! MPEG-2 TS demuxer TEMI timecode*/ typedef struct { + u32 pid; u32 timeline_id; u32 media_timescale; u64 media_timestamp; @@ -698,6 +700,7 @@ GF_SLConfig *slcfg; \ s16 component_tag; \ void *user; \ + GF_List *props; \ u64 first_dts; \ u32 service_id; @@ -1107,7 +1110,7 @@ */ void gf_m2ts_demux_del(GF_M2TS_Demuxer *demux); -/*! resets all parsers (PES, sections) of the demultiplexer +/*! resets all parsers (PES, sections) of the demultiplexer and trash any pending data in the demux input \param demux the target MPEG-2 TS demultiplexer */ void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *demux); @@ -1152,7 +1155,7 @@ /*! flushes all streams in the mux. This is used to flush internal demultiplexer buffers on end of stream \param demux the target MPEG-2 demultiplexer */ -void gf_m2ts_flush_all(GF_M2TS_Demuxer *ts); +void gf_m2ts_flush_all(GF_M2TS_Demuxer *demux); /*! MPEG-2 TS packet header*/ @@ -1641,11 +1644,13 @@ /*! min initial DTS of all streams*/ u64 initial_ts; /*! indicates that min initial DTS of all streams is set*/ - Bool initial_ts_set; + u32 initial_ts_set; /*! if set, injects a PCR offset*/ Bool pcr_init_time_set; /*! PCR offset to inject*/ - u32 pcr_offset; + u64 pcr_offset; + /*! Forced value of first packet CTS*/ + u64 force_first_pts; /*! indicates the initial discontinuity flag should be set on first packet of all streams*/ Bool initial_disc_set; /*! MPEG-4 IOD for 4on2*/ @@ -1660,8 +1665,6 @@ char *name; /*! program provider (for SDT)*/ char *provider; - /*! maximum delay of all streams (in stream timescale)*/ - s32 max_media_skip; /*! CTS offset in 90khz*/ u32 cts_offset; }; @@ -1786,9 +1789,10 @@ \param mpeg4_signaling type of MPEG-4 signaling used \param pmt_version initial version of the PMT \param initial_disc if GF_TRUE, signals packet discontinuity on the first packet of eact stream in the program +\param force_first_pts if not 0, the first PTS written in the program will have the indicated value (in 90khz) \return a TS multiplexer program */ -GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_number, u32 pmt_pid, u32 pmt_refresh_rate, u32 pcr_offset, u32 mpeg4_signaling, u32 pmt_version, Bool initial_disc); +GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_number, u32 pmt_pid, u32 pmt_refresh_rate, u64 pcr_offset, u32 mpeg4_signaling, u32 pmt_version, Bool initial_disc, u64 force_first_pts); /*! adds a stream to a program \param program the target program \param ifce the stream interface object for packet and properties query
View file
gpac-1.0.0.tar.gz/include/gpac/network.h -> gpac-1.0.1.tar.gz/include/gpac/network.h
Changed
@@ -203,7 +203,7 @@ \param val short integrer to convert \return converted integer */ -u16 gf_tohs(u16 val); +u16 gf_ntohs(u16 val); /*! @} */
View file
gpac-1.0.0.tar.gz/include/gpac/scene_manager.h -> gpac-1.0.1.tar.gz/include/gpac/scene_manager.h
Changed
@@ -66,7 +66,7 @@ /*! Scene manager AU flags*/ enum { - /*AU is RAP - random access indication - may be overriden by encoder*/ + /*AU is RAP - random access indication - may be overridden by encoder*/ GF_SM_AU_RAP = 1, /*AU will not be aggregated (only used by scene engine)*/ GF_SM_AU_NOT_AGGREGATED = 1<<1,
View file
gpac-1.0.0.tar.gz/include/gpac/scenegraph_vrml.h -> gpac-1.0.1.tar.gz/include/gpac/scenegraph_vrml.h
Changed
@@ -464,12 +464,12 @@ addChildren: chain containing nodes to add passed as eventIn - handled internally through ROUTE void (*on_addChildren)(GF_Node *pNode): add feventIn signaler - this is handled internally by the scene_graph and SHALL -NOT BE OVERRIDEN since it takes care of node(s) routing +NOT BE overridden since it takes care of node(s) routing removeChildren: chain containing nodes to remove passed as eventIn - handled internally through ROUTE void (*on_removeChildren)(GF_Node *pNode): remove eventIn signaler - this is handled internally by the scene_graph and SHALL -NOT BE OVERRIDEN since it takes care of node(s) routing +NOT BE overridden since it takes care of node(s) routing children: list of children SFNodes */
View file
gpac-1.0.0.tar.gz/include/gpac/setup.h -> gpac-1.0.1.tar.gz/include/gpac/setup.h
Changed
@@ -509,11 +509,11 @@ #endif /*! macro for cross-platform formatting of s64 integers in logs and printf routines*/ -#define LLD "%"LLD_SUF +#define LLD "%" LLD_SUF /*! macro for cross-platform formatting of u64 integers in logs and printf routines*/ -#define LLU "%"LLU_SUF +#define LLU "%" LLU_SUF /*! macro for cross-platform formatting of u64 integers as hexadecimal in logs and printf routines*/ -#define LLX "%"LLX_SUF +#define LLX "%" LLX_SUF #if !defined(GF_EXPORT)
View file
gpac-1.0.0.tar.gz/include/gpac/thread.h -> gpac-1.0.1.tar.gz/include/gpac/thread.h
Changed
@@ -65,28 +65,56 @@ //atomic ref_count++ / ref_count-- #if defined(WIN32) || defined(_WIN32_WCE) -#include <Windows.h> -#include <WinBase.h> +#include <windows.h> +#include <winbase.h> +/*! atomic integer increment */ #define safe_int_inc(__v) InterlockedIncrement((int *) (__v)) +/*! atomic integer decrement */ #define safe_int_dec(__v) InterlockedDecrement((int *) (__v)) - +/*! atomic integer addition */ #define safe_int_add(__v, inc_val) InterlockedAdd((int *) (__v), inc_val) +/*! atomic integer substraction */ #define safe_int_sub(__v, dec_val) InterlockedAdd((int *) (__v), -dec_val) - +/*! atomic large integer addition */ #define safe_int64_add(__v, inc_val) InterlockedAdd64((LONG64 *) (__v), inc_val) +/*! atomic large integer substraction */ #define safe_int64_sub(__v, dec_val) InterlockedAdd64((LONG64 *) (__v), -dec_val) #else +#ifdef GPAC_NEED_LIBATOMIC + +/*! atomic integer increment */ +#define safe_int_inc(__v) __atomic_add_fetch((int *) (__v), 1, __ATOMIC_SEQ_CST) +/*! atomic integer decrement */ +#define safe_int_dec(__v) __atomic_sub_fetch((int *) (__v), 1, __ATOMIC_SEQ_CST) +/*! atomic integer addition */ +#define safe_int_add(__v, inc_val) __atomic_add_fetch((int *) (__v), inc_val, __ATOMIC_SEQ_CST) +/*! atomic integer substraction */ +#define safe_int_sub(__v, dec_val) __atomic_sub_fetch((int *) (__v), dec_val, __ATOMIC_SEQ_CST) +/*! atomic large integer addition */ +#define safe_int64_add(__v, inc_val) __atomic_add_fetch((int64_t *) (__v), inc_val, __ATOMIC_SEQ_CST) +/*! atomic large integer substraction */ +#define safe_int64_sub(__v, dec_val) __atomic_sub_fetch((int64_t *) (__v), dec_val, __ATOMIC_SEQ_CST) + +#else + +/*! atomic integer increment */ #define safe_int_inc(__v) __sync_add_and_fetch((int *) (__v), 1) +/*! atomic integer decrement */ #define safe_int_dec(__v) __sync_sub_and_fetch((int *) (__v), 1) - +/*! atomic integer addition */ #define safe_int_add(__v, inc_val) __sync_add_and_fetch((int *) (__v), inc_val) +/*! atomic integer substraction */ #define safe_int_sub(__v, dec_val) __sync_sub_and_fetch((int *) (__v), dec_val) - +/*! atomic large integer addition */ #define safe_int64_add(__v, inc_val) __sync_add_and_fetch((int64_t *) (__v), inc_val) +/*! atomic large integer substraction */ #define safe_int64_sub(__v, dec_val) __sync_sub_and_fetch((int64_t *) (__v), dec_val) + +#endif //GPAC_NEED_LIBATOMIC + #endif @@ -348,4 +376,3 @@ #endif /*_GF_THREAD_H_*/ -
View file
gpac-1.0.0.tar.gz/include/gpac/tools.h -> gpac-1.0.1.tar.gz/include/gpac/tools.h
Changed
@@ -398,7 +398,7 @@ const char *gf_sys_features(Bool disabled); /*! callback function for remotery profiler - \param udta user data passed by \ref gf_sys_set_profiler_callback + \param udta user data passed by \ref gf_sys_profiler_set_callback \param text string sent by webbrowser client */ typedef void (*gf_rmt_user_callback)(void *udta, const char* text); @@ -417,6 +417,14 @@ */ GF_Err gf_sys_profiler_send(const char *msg); +/*! Enables sampling times in RMT + \param enable if GF_TRUE, sampling will be enabled, otherwise disabled*/ +void gf_sys_profiler_enable_sampling(Bool enable); + +/*! Checks if sampling is enabled in RMT. Sampling is by default enabled when enabling remotery + \return GF_TRUE if sampling is enabled, GF_FALSE otherwise*/ +Bool gf_sys_profiler_sampling_enabled(); + /*! GPAC Log tools \hideinitializer @@ -795,6 +803,15 @@ */ char gf_prompt_get_char(); +/*! +\brief Get prompt terminal size + +Gets the stdin prompt size (columns and rows) +\param width set to number of rows in the terminal +\param height set to number of columns in the terminal +\return error if any +*/ +GF_Err gf_prompt_get_size(u32 *width, u32 *height); /*! \brief turns prompt echo on/off @@ -899,6 +916,15 @@ u64 gf_net_get_utc(); /*! +\brief converts an ntp timestamp into UTC time in milliseconds + +Converts NTP 64-bit timestamp to UTC clock in milliseconds +\u64 ntp NTP timestamp +\return UTC time in milliseconds + */ +u64 gf_net_ntp_to_utc(u64 ntp); + +/*! \brief parses date Parses date and gets UTC value for this date. Date format is an XSD dateTime format or any of the supported formats from HTTP 1.1: @@ -1602,7 +1628,6 @@ */ GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *out_size); -#ifndef GPAC_DISABLE_ZLIB /** Compresses a data buffer in place using zlib/deflate. Buffer may be reallocated in the process. \param data pointer to the data buffer to be compressed @@ -1610,10 +1635,10 @@ \param out_size pointer for output buffer size \param data_offset offset in source buffer - the input payload size is data_len - data_offset \param skip_if_larger if GF_TRUE, will not override source buffer if compressed version is larger than input data +\param out_comp_data if not NULL, the compressed result is set in this pointer rather than doing inplace compression \return error if any */ -GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *out_size, u8 data_offset, Bool skip_if_larger); -#endif /*GPAC_DISABLE_ZLIB*/ +GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *out_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data); /** Decompresses a data buffer using zlib/deflate.
View file
gpac-1.0.0.tar.gz/include/gpac/version.h -> gpac-1.0.1.tar.gz/include/gpac/version.h
Changed
@@ -42,11 +42,11 @@ * SONAME versions must be digits (not strings) */ /*! Macro giving GPAC version name expressed as a printable string*/ -#define GPAC_VERSION "1.0.0" +#define GPAC_VERSION "1.0.1" /*! ABI Major number of libgpac */ #define GPAC_VERSION_MAJOR 10 /*! ABI Minor number of libgpac */ -#define GPAC_VERSION_MINOR 0 +#define GPAC_VERSION_MINOR 1 /*! ABI Micro number of libgpac */ #define GPAC_VERSION_MICRO 0 @@ -60,6 +60,11 @@ */ const char *gf_gpac_copyright(); +/*! gets GPAC copyright + citations DOI +\return GPAC copyright +*/ +const char *gf_gpac_copyright_cite(); + /*! @} */ #endif //_GF_VERSION_H
View file
gpac-1.0.0.tar.gz/modules/Makefile -> gpac-1.0.1.tar.gz/modules/Makefile
Changed
@@ -6,7 +6,7 @@ #disabled for now #netctrl -ifneq ($(CONFIG_ZLIB), no) +ifneq ($(CONFIG_ZLIB),no) #disabled for now #PLUGDIRS+=widgetman ifeq ($(DISABLE_VRML),no) @@ -19,28 +19,28 @@ endif -ifeq ($(CONFIG_FT), no) +ifeq ($(CONFIG_FT),no) else PLUGDIRS+=ft_font endif -ifeq ($(CONFIG_FREENECT), no) +ifeq ($(CONFIG_FREENECT),no) else #PLUGDIRS+=freenect endif -ifeq ($(CONFIG_ALSA), yes) +ifeq ($(CONFIG_ALSA),yes) PLUGDIRS+=alsa endif -ifeq ($(CONFIG_JACK), yes) +ifeq ($(CONFIG_JACK),yes) PLUGDIRS+=jack endif -ifeq ($(CONFIG_SDL), yes) +ifeq ($(CONFIG_SDL),yes) PLUGDIRS+=sdl_out endif -ifeq ($(CONFIG_PULSEAUDIO), yes) +ifeq ($(CONFIG_PULSEAUDIO),yes) PLUGDIRS+=pulseaudio endif @@ -74,7 +74,7 @@ #if static modules are used, disable all previous modules (built-in in libgpac) -ifeq ($(STATIC_MODULES), yes) +ifeq ($(STATIC_MODULES),yes) PLUGDIRS= endif @@ -84,7 +84,7 @@ #PLUGDIRS+=platinum #endif -ifeq ($(DISABLE_PLAYER), yes) +ifeq ($(DISABLE_PLAYER),yes) PLUGDIRS= endif
View file
gpac-1.0.0.tar.gz/modules/alsa/Makefile -> gpac-1.0.1.tar.gz/modules/alsa/Makefile
Changed
@@ -5,12 +5,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) $(OSS_CFLAGS) LDFLAGS+=$(OSS_LDFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/dec_openhevc/Makefile -> gpac-1.0.1.tar.gz/modules/dec_openhevc/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) $(OHEVC_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -25,7 +25,7 @@ SRCS=$(SRC_PATH)/src/filters/dec_openhevc.c -ifeq ($(CONFIG_WIN32), yes) +ifeq ($(CONFIG_WIN32),yes) else EXTRALIBS+=-ldl endif
View file
gpac-1.0.0.tar.gz/modules/dektec_out/Makefile -> gpac-1.0.1.tar.gz/modules/dektec_out/Makefile
Changed
@@ -4,21 +4,21 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(ENABLE_JOYSTICK), yes) +ifeq ($(ENABLE_JOYSTICK),yes) CFLAGS+=-DENABLE_JOYSTICK endif -ifeq ($(ENABLE_JOYSTICK_NO_CURSOR), yes) +ifeq ($(ENABLE_JOYSTICK_NO_CURSOR),yes) CFLAGS+=-DENABLE_JOYSTICK_NO_CURSOR endif
View file
gpac-1.0.0.tar.gz/modules/demo_is/Makefile -> gpac-1.0.1.tar.gz/modules/demo_is/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/audio_filter/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/audio_filter/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/avcap/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/avcap/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(CXXFLAGS) -I"$(SRC_PATH)/include" $(AVCAP_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/ffmpeg_in/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/ffmpeg_in/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-fPIC $(OPTFLAGS) -Wno-deprecated-declarations -I"$(SRC_PATH)/include" $(ffmpeg_cflags) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -37,19 +37,19 @@ endif #old ffmpeg lib -ifeq ($(CONFIG_FFMPEG_OLD), yes) +ifeq ($(CONFIG_FFMPEG_OLD),yes) CFLAGS+=-DFFMPEG_OLD_HEADERS -I/usr/include else LINKFLAGS+=-lswscale endif #local ffmpeg lib -ifeq ($(CONFIG_FFMPEG), local) +ifeq ($(CONFIG_FFMPEG),local) LOCAL_LIB=-L../../extra_lib/lib/gcc CFLAGS+= -I"$(LOCAL_INC_PATH)" endif -ifeq ($(CONFIG_ZLIB), local) +ifeq ($(CONFIG_ZLIB),local) LOCAL_LIB=-L../../extra_lib/lib/gcc endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/freenect/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/freenect/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(CXXFLAGS) -I"$(SRC_PATH)/include" -DGPAC_HAVE_CONFIG_H -I../.. $(FREENECT_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -17,7 +17,7 @@ LINKLIBS= -ifeq ($(CONFIG_FREENECT), local) +ifeq ($(CONFIG_FREENECT),local) LINKLIBS+=-L../../extra_lib/lib/gcc CFLAGS+= -I"$(LOCAL_INC_PATH)" endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/hyb_in/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/hyb_in/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/libplayer/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/libplayer/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/mse_in/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/mse_in/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -w -I"$(SRC_PATH)/include" -Wall -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g -DDEBUG LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -19,11 +19,11 @@ else CFLAGS+=$(JS_FLAGS) ifeq ($(CONFIG_JS),local) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes LOCAL_LIB+=-L../../extra_lib/lib/gcc endif ifeq ($(CONFIG_JS),prefix) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes LOCAL_LIB+=-L$(prefix)/$(libdir) endif LINKLIBS+= $(JS_LIBS)
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/netctrl/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/netctrl/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/opencv_is/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/opencv_is/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/osd/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/osd/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/platinum/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/platinum/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(CXXFLAGS) -I"$(SRC_PATH)/include" -I$(SRC_PATH)/extra_lib/include/platinum/ -DGPAC_HAVE_CONFIG_H -I../.. -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -24,7 +24,7 @@ else CFLAGS+= $(JS_FLAGS) ifeq ($(CONFIG_JS),local) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes LOCAL_LIB+=-L../../extra_lib/lib/gcc else LINKLIBS+= $(JS_LIBS) @@ -39,7 +39,7 @@ LINKLIBS+= -lwsock32 -lws2_32 -static-libstdc++ -static-libgcc endif -ifeq ($(CONFIG_DARWIN), yes) +ifeq ($(CONFIG_DARWIN),yes) LDFLAGS+=-framework Foundation endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/psvr/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/psvr/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/rvc_dec/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/rvc_dec/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I$(SRC_PATH)/include -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/ui_rec/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/ui_rec/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/widgetman/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/widgetman/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -20,7 +20,7 @@ #common objects OBJS=widgetman.o unzip.o widget.o wgt_load.o -ifeq ($(CONFIG_ZLIB), local) +ifeq ($(CONFIG_ZLIB),local) CFLAGS+=-I"$(LOCAL_INC_PATH)/zlib" LOCAL_LIB+= -L../../extra_lib/lib/gcc endif @@ -30,7 +30,7 @@ CFLAGS+=$(JS_FLAGS) ifeq ($(CONFIG_JS),local) # if local it is staticly linked with libgpac -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes LOCAL_LIB+= -L../../extra_lib/lib/gcc else LINKLIBS+= $(JS_LIBS)
View file
gpac-1.0.0.tar.gz/modules/deprecated/old_arch/wiiis/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/old_arch/wiiis/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/deprecated/oss_audio/Makefile -> gpac-1.0.1.tar.gz/modules/deprecated/oss_audio/Makefile
Changed
@@ -5,22 +5,22 @@ CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" $(OSS_CFLAGS) LDFLAGS+=$(OSS_LDFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(OSS_INC_TYPE), yes) +ifeq ($(OSS_INC_TYPE),yes) else CFLAGS+=-DOSS_FIX_INC endif -ifeq ($(TARGET_ARCH_ARMV4L), yes) +ifeq ($(TARGET_ARCH_ARMV4L),yes) CFLAGS+=-DFORCE_SR_LIMIT endif
View file
gpac-1.0.0.tar.gz/modules/directfb_out/Makefile -> gpac-1.0.1.tar.gz/modules/directfb_out/Makefile
Changed
@@ -5,12 +5,12 @@ CFLAGS=-I"$(SRC_PATH)/include" -I$(DIRECTFB_INC_PATH) $(OPTFLAGS) LDFLAGS+=$(DIRECTFB_LIB) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/dx_hw/Makefile -> gpac-1.0.1.tar.gz/modules/dx_hw/Makefile
Changed
@@ -5,17 +5,17 @@ #DIRECTSOUND_VERSION is needed for GCC compil.. CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -w -DDIRECTSOUND_VERSION=0x0500 -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif -ifeq ($(DX_PATH), system) +ifeq ($(DX_PATH),system) LDFLAGS_DX=-ldsound -ldxguid -lddraw -lole32 -lgdi32 -lopengl32 else CFLAGS+= -I$(DX_PATH)/include
View file
gpac-1.0.0.tar.gz/modules/dx_hw/dx_video.c -> gpac-1.0.1.tar.gz/modules/dx_hw/dx_video.c
Changed
@@ -472,8 +472,14 @@ { RECT rc; DDCONTEXT - dd->os_hwnd = (HWND) os_handle; + if (dd->cur_hwnd) { + if (!(init_flags & GF_TERM_INIT_HIDE)) { + ShowWindow(dd->cur_hwnd, SW_SHOW); + } + return GF_OK; + } + dd->os_hwnd = (HWND) os_handle; DD_SetupWindow(dr, init_flags); /*fatal error*/ if (!dd->os_hwnd) return GF_IO_ERR;
View file
gpac-1.0.0.tar.gz/modules/dx_hw/dx_window.c -> gpac-1.0.1.tar.gz/modules/dx_hw/dx_window.c
Changed
@@ -243,14 +243,14 @@ case WM_SIZE: /*always notify GPAC since we're not sure the owner of the window is listening to these events*/ if (wParam==SIZE_MINIMIZED) { - evt.type = GF_EVENT_SHOWHIDE_NOTIF; + evt.type = GF_EVENT_SHOWHIDE; evt.show.show_type = 0; ctx->hidden = GF_TRUE; vout->on_event(vout->evt_cbk_hdl, &evt); } else { if (ctx->hidden && wParam==SIZE_RESTORED) { ctx->hidden = GF_FALSE; - evt.type = GF_EVENT_SHOWHIDE_NOTIF; + evt.type = GF_EVENT_SHOWHIDE; evt.show.show_type = 1; vout->on_event(vout->evt_cbk_hdl, &evt); } @@ -261,7 +261,7 @@ } break; case WM_MOVE: - evt.type = GF_EVENT_MOVE_NOTIF; + evt.type = GF_EVENT_MOVE; evt.move.x = LOWORD(lParam); evt.move.y = HIWORD(lParam); vout->on_event(vout->evt_cbk_hdl, &evt); @@ -298,7 +298,7 @@ if (!ctx->on_secondary_screen && ctx->fullscreen && (LOWORD(wParam)==WA_INACTIVE) && (hWnd==ctx->fs_hwnd) ) { - evt.type = GF_EVENT_SHOWHIDE_NOTIF; + evt.type = GF_EVENT_SHOWHIDE; vout->on_event(vout->evt_cbk_hdl, &evt); } /*fallthrough*/ @@ -515,11 +515,11 @@ LPTSTR lptstrCopy = (wchar_t *) GlobalLock(hglbCopy); evt.type = GF_EVENT_PASTE_TEXT; /* TODO: Convert to UTF-8 */ - evt.message.message = lptstrCopy; + evt.clipboard.text = lptstrCopy; #else LPTSTR lptstrCopy = (char *)GlobalLock(hglbCopy); evt.type = GF_EVENT_PASTE_TEXT; - evt.message.message = lptstrCopy; + evt.clipboard.text = lptstrCopy; #endif ret = vout->on_event(vout->evt_cbk_hdl, &evt); GlobalUnlock(hglbCopy); @@ -529,7 +529,7 @@ } else if (ctx->ctrl_down && (evt.type==GF_EVENT_KEYUP) && (evt.key.key_code==GF_KEY_C)) { evt.type = GF_EVENT_COPY_TEXT; - if ((vout->on_event(vout->evt_cbk_hdl, &evt)==GF_TRUE) && evt.message.message) { + if ((vout->on_event(vout->evt_cbk_hdl, &evt)==GF_TRUE) && evt.clipboard.text) { size_t len; HGLOBAL hglbCopy; LPTSTR lptstrCopy; @@ -537,23 +537,24 @@ if (!OpenClipboard(ctx->cur_hwnd)) break; EmptyClipboard(); - len = strlen(evt.message.message); + len = strlen(evt.clipboard.text); if (!len) break; hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(char)); #ifdef UNICODE /* TODO fix encoding*/ lptstrCopy = (wchar_t *)GlobalLock(hglbCopy); - memcpy(lptstrCopy, evt.message.message, len * sizeof(char)); + memcpy(lptstrCopy, evt.clipboard.text, len * sizeof(char)); lptstrCopy[len] = 0; #else lptstrCopy = (char *) GlobalLock(hglbCopy); - memcpy(lptstrCopy, evt.message.message, len * sizeof(char)); + memcpy(lptstrCopy, evt.clipboard.text, len * sizeof(char)); lptstrCopy[len] = 0; #endif GlobalUnlock(hglbCopy); SetClipboardData(CF_TEXT, hglbCopy); CloseClipboard(); + gf_free(evt.clipboard.text); break; } }
View file
gpac-1.0.0.tar.gz/modules/ft_font/Makefile -> gpac-1.0.1.tar.gz/modules/ft_font/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) $(FT_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/jack/Makefile -> gpac-1.0.1.tar.gz/modules/jack/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) $(OSS_CFLAGS) -Wno-deprecated-declarations -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/pulseaudio/Makefile -> gpac-1.0.1.tar.gz/modules/pulseaudio/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/sdl_out/Makefile -> gpac-1.0.1.tar.gz/modules/sdl_out/Makefile
Changed
@@ -4,19 +4,19 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) $(SDL_CFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif LINKFLAGS=-L../../bin/gcc -lgpac $(SDL_LIBS) -ifeq ($(CONFIG_DARWIN), yes) +ifeq ($(CONFIG_DARWIN),yes) LINKFLAGS+=-framework OpenGL endif
View file
gpac-1.0.0.tar.gz/modules/sdl_out/video.c -> gpac-1.0.1.tar.gz/modules/sdl_out/video.c
Changed
@@ -831,15 +831,26 @@ break; case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_SHOWN: - case SDL_WINDOWEVENT_MOVED: gpac_evt.type = GF_EVENT_REFRESH; dr->on_event(dr->evt_cbk_hdl, &gpac_evt); break; + case SDL_WINDOWEVENT_MOVED: + gpac_evt.type = GF_EVENT_MOVE; + gpac_evt.move.x = sdl_evt.window.data1; + gpac_evt.move.y = sdl_evt.window.data2; + dr->on_event(dr->evt_cbk_hdl, &gpac_evt); + break; case SDL_WINDOWEVENT_CLOSE: memset(&gpac_evt, 0, sizeof(GF_Event)); gpac_evt.type = GF_EVENT_QUIT; dr->on_event(dr->evt_cbk_hdl, &gpac_evt); return GF_FALSE; + case SDL_WINDOWEVENT_MINIMIZED: + memset(&gpac_evt, 0, sizeof(GF_Event)); + gpac_evt.type = GF_EVENT_SHOWHIDE; + gpac_evt.show.show_type = 0; + dr->on_event(dr->evt_cbk_hdl, &gpac_evt); + return GF_FALSE; } break; #else @@ -896,7 +907,7 @@ #endif -#if (SDL_MAJOR_VERSION>=1) && (SDL_MINOR_VERSION>=3) +#if SDL_VERSION_ATLEAST(2,0,0) if ((gpac_evt.type==GF_EVENT_KEYUP) && (gpac_evt.key.key_code==GF_KEY_V) #if defined(__DARWIN__) || defined(__APPLE__) @@ -905,13 +916,10 @@ && ctx->ctrl_down #endif ) { -#if defined(__DARWIN__) || defined(__APPLE__) -#else gpac_evt.type = GF_EVENT_PASTE_TEXT; - gpac_evt.message.message = (const char *) SDL_GetClipboardText(); + gpac_evt.clipboard.text = (char *) SDL_GetClipboardText(); dr->on_event(dr->evt_cbk_hdl, &gpac_evt); - SDL_free((char *) gpac_evt.message.message); -#endif + SDL_free(gpac_evt.clipboard.text); } else if ((gpac_evt.type==GF_EVENT_KEYUP) && (gpac_evt.key.key_code==GF_KEY_C) #if defined(__DARWIN__) || defined(__APPLE__) @@ -921,11 +929,10 @@ #endif ) { gpac_evt.type = GF_EVENT_COPY_TEXT; -#if defined(__DARWIN__) || defined(__APPLE__) -#else - if (dr->on_event(dr->evt_cbk_hdl, &gpac_evt)==GF_TRUE) - SDL_SetClipboardText((char *)gpac_evt.message.message ); -#endif + if (dr->on_event(dr->evt_cbk_hdl, &gpac_evt) && gpac_evt.clipboard.text) { + SDL_SetClipboardText(gpac_evt.clipboard.text ); + gf_free(gpac_evt.clipboard.text); + } } #endif @@ -1000,6 +1007,13 @@ dr->on_event(dr->evt_cbk_hdl, &gpac_evt); break; + case SDL_DROPFILE: + gpac_evt.type = GF_EVENT_DROPFILE; + gpac_evt.open_file.nb_files = 1; + gpac_evt.open_file.files = &sdl_evt.drop.file; + dr->on_event(dr->evt_cbk_hdl, &gpac_evt); + + #endif } @@ -1072,16 +1086,27 @@ GF_Err SDLVid_Setup(struct _video_out *dr, void *os_handle, void *os_display, u32 init_flags) { + Bool show_window = GF_TRUE; SDLVID(); /*we don't allow SDL hack, not stable enough*/ //if (os_handle) SDLVid_SetHack(os_handle, 1); ctx->os_handle = os_handle; - ctx->is_init = GF_FALSE; - ctx->output_3d = GF_FALSE; + if (!ctx->is_init) { + ctx->output_3d = GF_FALSE; + show_window = GF_TRUE; + } + ctx->force_alpha = (init_flags & GF_TERM_WINDOW_TRANSPARENT) ? GF_TRUE : GF_FALSE; ctx->hidden = (init_flags & GF_TERM_INIT_HIDE) ? GF_TRUE : GF_FALSE; + if (!ctx->hidden && show_window) { +#if SDL_VERSION_ATLEAST(2,0,0) + SDL_ShowWindow(ctx->screen); +#else +#endif + } + if (!SDLOUT_InitSDL()) return GF_IO_ERR;
View file
gpac-1.0.0.tar.gz/modules/validator/Makefile -> gpac-1.0.1.tar.gz/modules/validator/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/wav_out/Makefile -> gpac-1.0.1.tar.gz/modules/wav_out/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -DDISABLE_WAVE_EX -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif
View file
gpac-1.0.0.tar.gz/modules/x11_out/Makefile -> gpac-1.0.1.tar.gz/modules/x11_out/Makefile
Changed
@@ -4,12 +4,12 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -Wno-deprecated-declarations -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif @@ -17,28 +17,28 @@ CFLAGS+=-I"$(SRC_PATH)/include" -ifeq ($(X11_INC_PATH), ) +ifeq ($(X11_INC_PATH),) else CFLAGS+=-I$(X11_INC_PATH) endif -ifeq ($(X11_LIB_PATH), ) +ifeq ($(X11_LIB_PATH),) else EXTRALIBS+=-L$(X11_LIB_PATH) endif -ifeq ($(USE_X11_XV), yes) +ifeq ($(USE_X11_XV),yes) CFLAGS+=-DGPAC_HAS_X11_XV EXTRALIBS+=-lXv endif -ifeq ($(USE_X11_SHM), yes) +ifeq ($(USE_X11_SHM),yes) CFLAGS+=-DGPAC_HAS_X11_SHM EXTRALIBS+=-lXext endif -ifeq ($(HAS_OPENGL), yes) -ifeq ($(GPAC_USE_TINYGL), yes) +ifeq ($(HAS_OPENGL),yes) +ifeq ($(GPAC_USE_TINYGL),yes) else CFLAGS+=$(OGL_INCLS) EXTRALIBS+=$(OGL_LIBS)
View file
gpac-1.0.0.tar.gz/modules/x11_out/x11_out.c -> gpac-1.0.1.tar.gz/modules/x11_out/x11_out.c
Changed
@@ -549,7 +549,7 @@ xWindow->w_height = evt.size.height = xevent.xconfigure.height; vout->on_event(vout->evt_cbk_hdl, &evt); } else { - evt.type = GF_EVENT_MOVE_NOTIF; + evt.type = GF_EVENT_MOVE; evt.move.x = xevent.xconfigure.x; evt.move.y = xevent.xconfigure.y; vout->on_event(vout->evt_cbk_hdl, &evt); @@ -619,7 +619,7 @@ memcpy(text, data, nb_bytes); text[nb_bytes] = 0; evt.type = GF_EVENT_PASTE_TEXT; - evt.message.message = (const char *) text; + evt.clipboard.text = text; vout->on_event(vout->evt_cbk_hdl, &evt); gf_free(text); } @@ -631,9 +631,9 @@ Atom clipb_atom = XInternAtom(xWindow->display, "CLIPBOARD", 0); evt.type = GF_EVENT_COPY_TEXT; if (vout->on_event(vout->evt_cbk_hdl, &evt)==GF_TRUE) { - const char *txt = evt.message.message; - if (txt) { - XChangeProperty(xWindow->display, DefaultRootWindow(xWindow->display), XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, (const unsigned char *)txt, strlen(txt)); + if (evt.clipboard.text) { + XChangeProperty(xWindow->display, DefaultRootWindow(xWindow->display), XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, (const unsigned char *)evt.clipboard.text, strlen(evt.clipboard.text)); + gf_free(evt.clipboard.text); } if ((clipb_atom != None) && XGetSelectionOwner(xWindow->display, clipb_atom) != the_window) { @@ -975,10 +975,14 @@ case GF_EVENT_SET_GL: if (!xWindow->output_3d) return GF_OK; +#ifdef GPAC_HAS_OPENGL if ( ! glXMakeCurrent(xWindow->display, xWindow->fullscreen ? xWindow->full_wnd : xWindow->wnd, xWindow->glx_context) ) { GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Cannot make context current\n")); return GF_IO_ERR; } +#else + return GF_NOT_SUPPORTED; +#endif break; } } else { @@ -1498,6 +1502,13 @@ xWindow->par_wnd = (Window) os_handle; xWindow->init_flags = flags; + //window already setup and this restup asks for visible, show window + if (xWindow->wnd) { + if (!(xWindow->init_flags & GF_TERM_INIT_HIDE)) { + XMapWindow (xWindow->display, (Window) xWindow->wnd); + } + } + /*OSMOZILLA HACK*/ if (os_display) xWindow->no_select_input = 1;
View file
gpac-1.0.0.tar.gz/packagers/win32_64/nsis/gpac_installer.nsi -> gpac-1.0.1.tar.gz/packagers/win32_64/nsis/gpac_installer.nsi
Changed
@@ -1,6 +1,6 @@ ;-------------------------------- ;General -!define GPAC_VERSION 1.0.0 +!define GPAC_VERSION 1.0.1 !include default.out !define GPAC_ROOT ..\..\.. @@ -255,6 +255,17 @@ File "${GPAC_BIN}\libcryptoMD.dll" File "${GPAC_BIN}\libsslMD.dll" + File "${GPAC_BIN}\avcodec-*.dll" + File "${GPAC_BIN}\avdevice-*.dll" + File "${GPAC_BIN}\avfilter-*.dll" + File "${GPAC_BIN}\avformat-*.dll" + File "${GPAC_BIN}\avutil-*.dll" + File "${GPAC_BIN}\swresample-*.dll" + File "${GPAC_BIN}\swscale-*.dll" + File "${GPAC_BIN}\postproc-*.dll" + File "${GPAC_BIN}\libx264-*.dll" + File "${GPAC_BIN}\OpenSVCDecoder.dll" + ;create default cache SetOutPath $INSTDIR\cache @@ -275,18 +286,6 @@ File "${GPAC_BIN}\gm_dx_hw.dll" - File "${GPAC_BIN}\avcodec-*.dll" - File "${GPAC_BIN}\avdevice-*.dll" - File "${GPAC_BIN}\avfilter-*.dll" - File "${GPAC_BIN}\avformat-*.dll" - File "${GPAC_BIN}\avutil-*.dll" - File "${GPAC_BIN}\swresample-*.dll" - File "${GPAC_BIN}\swscale-*.dll" - File "${GPAC_BIN}\postproc-*.dll" - File "${GPAC_BIN}\libx264-*.dll" - - File "${GPAC_BIN}\OpenSVCDecoder.dll" - ;copy GUI SetOutPath $INSTDIR\share File "${GPAC_ROOT}\share\default.cfg" @@ -298,7 +297,7 @@ File "${GPAC_ROOT}\share\gui\gui.bt" File "${GPAC_ROOT}\share\gui\gui.js" File "${GPAC_ROOT}\share\gui\gwlib.js" - File "${GPAC_ROOT}\share\gui\mpegu-core.js" +; File "${GPAC_ROOT}\share\gui\mpegu-core.js" SetOutPath $INSTDIR\share\gui\icons File /r /x .git ${GPAC_ROOT}\share\gui\icons\* SetOutPath $INSTDIR\share\gui\extensions
View file
gpac-1.0.1.tar.gz/share/deprecated
Added
+(directory)
View file
gpac-1.0.1.tar.gz/share/deprecated/iphone_wm_gui.js
Added
@@ -0,0 +1,1651 @@ +// 01122011 AMD1 startWidget listWidgets getWidget implemented +/* wrapper as a module + 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"); + } + display_width = parseInt(scene.get_option('General', 'LastWidth')); + display_height = parseInt(scene.get_option('General', 'LastHeight')); + alert("display "+display_width+" "+display_height); + if (!scene.fullscreen && display_width && display_height) { + scene.set_size(display_width, display_height); + } + 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 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); + } +} + +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.SetActionListener("getWidget", get_widget_callback2, true); + device.standardService.CallAction("getWidget", args); + } + target_widgets.register(root); + } +} + +function get_widget_callback2() { + // msgHandler is the first argument, the next arguments are from the reply to listWidgets + alert("callback2-1"); + var act = arguments[0]; + var act1 = act.GetArgumentValue("widgetUrl"); + var act2 = act.GetArgumentValue("widgetContext"); + alert("callback2-2 " + act1 + " " + act2); + var wid = WidgetManager.load(act1, null, act2); + WidgetManager.on_widget_add(wid); +} + +// +// 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', null)); + 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() { document.getElementById("canc").setAttribute("fill", "red"); }, false); + obj.addEventListener('mouseout', function() { document.getElementById("canc").setAttribute("fill", "black"); }, false); + obj.addEventListener('click', function() { upnp_renders.on_select(-1); }, false); + selector.register = function(disp) { + disp.appendChild(this); + }; + selector.unregister = function(disp) { + disp.removeChild(this); + }; + return selector; +} + +// +// 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', null)); + 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() { document.getElementById("cance").setAttribute("fill", "red"); }, false); + obj.addEventListener('mouseout', function() { document.getElementById("cance").setAttribute("fill", "black"); }, false); + obj.addEventListener('click', function() { target_widgets.on_select(-1); }, false); + selector.register = function(disp) { + disp.appendChild(this); + }; + selector.unregister = function(disp) { + disp.removeChild(this); + }; + return selector; +} + +function sw4(si) { + return function() { upnp_renders.on_select(si); }; +} + +function sw5(si) { + return function() { target_widgets.on_select(si); }; +} + +// +// 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")); + } +} + +// +// 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(scene.get_option('Widgets', 'LastWMWidth')); + var display_height = parseInt(scene.get_option('Widgets', 'LastWMHeight')); + if (display_width && display_height) { + scene.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 + } +} + +// +// 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'); + homebar.setAttribute('display', 'none'); + execbar.setAttribute('display', 'inline'); + arrows.setAttribute('display', 'none'); + arrowsW.setAttribute('display', 'inline'); + widgetAddList.setAttribute('display', 'none'); + return true; +} + +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); +} + +// +// 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; +} + +// +// 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; + scene.set_option("Widgets", "LastWMWidth", '' + previousWidth); + scene.set_option("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; + } + } + 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); +} + +// 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); + } + } +} + +// +// 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); + } +} + +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'); + 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 + //should do: 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; + } +} + +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); + } +} + +// +// 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; +} + +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; + } + widget_add(w); + adjustWhereWidgets(false); + w.permanent = false; + } +} + +// +// file list vars +// +var 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, 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 (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; + } + 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 = Sys.enum_directory(Sys.last_wdir, "", false); + fillWidgetAddList(flag); +} + +// +// go to parent directory +// +function flUpDir(evt) { + var s = Sys.last_wdir; + if (l_inf <= log_level) { + alert("[UI] lwd:" + Sys.last_wdir); + } + var index = s.lastIndexOf("\\"); + if (index != -1) { + Sys.last_wdir = s.substring(0, index); + refillWidgetAddList(isThisAScan); + } else { + index = s.lastIndexOf("/"); + if (index != -1) { + Sys.last_wdir = s.substring(0, index); + refillWidgetAddList(isThisAScan); + } else { + Sys.last_wdir = "/"; + refillWidgetAddList(isThisAScan); + } + } +} + +// +// go to a named directory +// +function flGoTo(newDir) { + //alert("goto "+newDir); + var s = Sys.last_wdir; + if (s == "/") { + Sys.last_wdir = newDir; + } else { + var c = s.charAt(s.length - 1); + if (c != '\\' && c != '/') { + s += "/"; + } + Sys.last_wdir = s + newDir; + } + //alert(Sys.last_wdir); + 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); +} + +// +// 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); + } +} + +// +// scan the current directory recursively for widgets, clean up and return to home page +// +function flScanDir(evt) { + scan_directory(Sys.last_wdir); + 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 = Sys.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); + } + } + } + } +} + +// +// 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 = Sys.last_wdir; + } else { + widgetAddList.appendChild(use("cartouche")); + document.getElementById("dir").textContent = Sys.last_wdir; + } + // 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(Sys.last_wdir + '/' + 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, null); + }; +} + +// // // // // // // // // // // // // // // +// 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; +} + +// +// 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; +} + +// +// 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; +} + +// +// 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.io/svg-extensions', 'use-as-primary', 'false'); + } + return child; +} + +// +// create use +// +function use(uri) { + var child = document.createElement('use'); + child.setAttributeNS(xlinkns, 'href', '#' + uri); + return child; +} + +// +// 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); +} + +// +// substitute for the useful predefined function endsWith +// +function endsWith(s1, s2) { + return s1.toLowerCase().substring(s1.length - s2.length) == s2; +} + +/* wrapper as a module + // 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, + get_widget_callback2: get_widget_callback2 + } + + }());*/ + +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); +}
View file
gpac-1.0.1.tar.gz/share/deprecated/iphone_wm_gui.svg
Added
@@ -0,0 +1,552 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" + xmlns:gpac-ext='http://gpac.io/svg-extensions' + width="571.35199" xmlns:ev="http://www.w3.org/2001/xml-events" height="462.51999" viewBox="0 0 320 600"> + <!-- + This is a Widget Manager creating an iPhone-style UI. + A certain number of widgets are installed, and their icons are visible on the home page. + If the home page is full, arrows appear at the bottom to get to the other pages of icons. + There is a companion file rifuim.js with the script that adapts this SVG to the size of the screen + --> + <defs id="mainDefs"> + <rect id="lightRect" width="80" height="80" fill="rgb(50,50,50)" stroke="none"/> + <rect id="darkRect" width="80" height="80" fill="rgb(40,40,40)" stroke="none"/> + <g id="odd"> + <use xlink:href="#lightRect"/> + <use xlink:href="#darkRect" x="80"/> + </g> + <g id="even"> + <use xlink:href="#darkRect"/> + <use xlink:href="#lightRect" x="80"/> + </g> + <animation id='go-up' xlink:href='icons/go-up.svg' width='25' height='25'/> + <animation id='go-previous' xlink:href='icons/go-previous.svg' width='25' height='25'/> + <animation id='go-next' xlink:href='icons/go-next.svg' width='25' height='25'/> + <animation id='go-jump' xlink:href='icons/go-jump.svg' width='25' height='25'/> + <animation id='folder' xlink:href='icons/folder.svg' width='25' height='25'/> + <animation id='new' xlink:href='icons/document-new.svg' width='25' height='25'/> + <g id="cartouche"> + <g transform="translate(0,0)"> + <use xlink:href="#go-up"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flUpDir();</handler> + </rect> + </g> + <g transform="translate(25,0)"> + <use xlink:href="#go-previous"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flPrevFiles();</handler> + </rect> + </g> + <g transform="translate(50,0)"> + <use xlink:href="#go-next"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flNextFiles();</handler> + </rect> + </g> + <g transform="translate(75,0)"> + <text id="dir" fill="black" font-family="Comic Sans MS" font-size="15" x="0" y="17"/> + </g> + </g> + <g id="cartoucheflag"> + <g transform="translate(0,0)"> + <use xlink:href="#go-up"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flUpDir();</handler> + </rect> + </g> + <g transform="translate(25,0)"> + <use xlink:href="#go-previous"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flPrevFiles();</handler> + </rect> + </g> + <g transform="translate(50,0)"> + <use xlink:href="#go-next"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flNextFiles();</handler> + </rect> + </g> + <g transform="translate(75,0)"> + <use xlink:href="#go-jump"/> + <rect pointer-events="all" width="25" height="25" fill="none" stroke="none"> + <handler ev:event="click">flScanDir();</handler> + </rect> + </g> + <g transform="translate(100,0)"> + <text id="dirflag" fill="black" font-family="Comic Sans MS" font-size="15" x="0" y="17"/> + </g> + </g> + <g id="fileMenuElement0"> + <use id="fileMenuElement0u"/> + <rect id="fileMenuElement0r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement0t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement0r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement0r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement1"> + <use id="fileMenuElement1u"/> + <rect id="fileMenuElement1r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement1t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement1r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement1r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement2"> + <use id="fileMenuElement2u"/> + <rect id="fileMenuElement2r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement2t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement2r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement2r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement3"> + <use id="fileMenuElement3u"/> + <rect id="fileMenuElement3r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement3t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement3r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement3r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement4"> + <use id="fileMenuElement4u"/> + <rect id="fileMenuElement4r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement4t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement4r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement4r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement5"> + <use id="fileMenuElement5u"/> + <rect id="fileMenuElement5r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement5t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement5r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement5r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement6"> + <use id="fileMenuElement6u"/> + <rect id="fileMenuElement6r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement6t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement6r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement6r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement7"> + <use id="fileMenuElement7u"/> + <rect id="fileMenuElement7r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement7t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement7r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement7r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement8"> + <use id="fileMenuElement8u"/> + <rect id="fileMenuElement8r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement8t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement8r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement8r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement9"> + <use id="fileMenuElement9u"/> + <rect id="fileMenuElement9r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement9t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement9r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement9r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement10"> + <use id="fileMenuElement10u"/> + <rect id="fileMenuElement10r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement10t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement10r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement10r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement11"> + <use id="fileMenuElement11u"/> + <rect id="fileMenuElement11r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement11t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement11r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement11r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement12"> + <use id="fileMenuElement12u"/> + <rect id="fileMenuElement12r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement12t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement12r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement12r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement13"> + <use id="fileMenuElement13u"/> + <rect id="fileMenuElement13r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement13t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement13r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement13r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement14"> + <use id="fileMenuElement14u"/> + <rect id="fileMenuElement14r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement14t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement14r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement14r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement15"> + <use id="fileMenuElement15u"/> + <rect id="fileMenuElement15r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement15t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement15r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement15r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement16"> + <use id="fileMenuElement16u"/> + <rect id="fileMenuElement16r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement16t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement16r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement16r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement17"> + <use id="fileMenuElement17u"/> + <rect id="fileMenuElement17r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement17t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement17r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement17r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement18"> + <use id="fileMenuElement18u"/> + <rect id="fileMenuElement18r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement18t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement18r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement18r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement19"> + <use id="fileMenuElement19u"/> + <rect id="fileMenuElement19r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement19t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement19r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement19r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement20"> + <use id="fileMenuElement20u"/> + <rect id="fileMenuElement20r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement20t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement20r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement20r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement21"> + <use id="fileMenuElement21u"/> + <rect id="fileMenuElement21r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement21t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement21r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement21r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement22"> + <use id="fileMenuElement22u"/> + <rect id="fileMenuElement22r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement22t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement22r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement22r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement23"> + <use id="fileMenuElement23u"/> + <rect id="fileMenuElement23r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement23t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement23r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement23r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement24"> + <use id="fileMenuElement24u"/> + <rect id="fileMenuElement24r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement24t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement24r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement24r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement25"> + <use id="fileMenuElement25u"/> + <rect id="fileMenuElement25r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement25t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement25r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement25r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement26"> + <use id="fileMenuElement26u"/> + <rect id="fileMenuElement26r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement26t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement26r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement26r").setAttribute("fill", "rgb(245,245,245)");</handler> + </g> + <g id="fileMenuElement27"> + <use id="fileMenuElement27u"/> + <rect id="fileMenuElement27r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement27t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement27r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement27r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement28"> + <use id="fileMenuElement28u"/> + <rect id="fileMenuElement28r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement28t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement28r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement28r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement29"> + <use id="fileMenuElement29u"/> + <rect id="fileMenuElement29r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement29t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement29r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement29r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement30"> + <use id="fileMenuElement30u"/> + <rect id="fileMenuElement30r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement30t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement30r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement30r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement31"> + <use id="fileMenuElement31u"/> + <rect id="fileMenuElement31r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement31t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement31r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement31r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement32"> + <use id="fileMenuElement32u"/> + <rect id="fileMenuElement32r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement32t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement32r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement32r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement33"> + <use id="fileMenuElement33u"/> + <rect id="fileMenuElement33r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement33t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement33r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement33r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement34"> + <use id="fileMenuElement34u"/> + <rect id="fileMenuElement34r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement34t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement34r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement34r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement35"> + <use id="fileMenuElement35u"/> + <rect id="fileMenuElement35r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement35t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement35r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement35r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement36"> + <use id="fileMenuElement36u"/> + <rect id="fileMenuElement36r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement36t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement36r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement36r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement37"> + <use id="fileMenuElement37u"/> + <rect id="fileMenuElement37r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement37t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement37r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement37r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement38"> + <use id="fileMenuElement38u"/> + <rect id="fileMenuElement38r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement38t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement38r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement38r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement39"> + <use id="fileMenuElement39u"/> + <rect id="fileMenuElement39r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement39t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement39r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement39r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement40"> + <use id="fileMenuElement40u"/> + <rect id="fileMenuElement40r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement40t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement40r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement40r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement41"> + <use id="fileMenuElement41u"/> + <rect id="fileMenuElement41r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement41t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement41r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement41r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement42"> + <use id="fileMenuElement42u"/> + <rect id="fileMenuElement42r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement42t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement42r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement42r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement43"> + <use id="fileMenuElement43u"/> + <rect id="fileMenuElement43r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement43t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement43r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement43r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement44"> + <use id="fileMenuElement44u"/> + <rect id="fileMenuElement44r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement44t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement44r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement44r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement45"> + <use id="fileMenuElement45u"/> + <rect id="fileMenuElement45r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement45t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement45r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement45r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement46"> + <use id="fileMenuElement46u"/> + <rect id="fileMenuElement46r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement46t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement46r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement46r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement47"> + <use id="fileMenuElement47u"/> + <rect id="fileMenuElement47r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement47t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement47r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement47r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement48"> + <use id="fileMenuElement48u"/> + <rect id="fileMenuElement48r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement48t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement48r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement48r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + <g id="fileMenuElement49"> + <use id="fileMenuElement49u"/> + <rect id="fileMenuElement49r" x="25" y="0" width="550" height="20" fill="rgb(245,245,245)" stroke="none"/> + <text id="fileMenuElement49t" fill="gray" font-family="Comic Sans MS" font-size="20" x="30" y="17"/> + <handler ev:event="mouseover">document.getElementById("fileMenuElement49r").setAttribute("fill", "black");</handler> + <handler ev:event="mouseout">document.getElementById("fileMenuElement49r").setAttribute("fill", "rgb(245,245,245)");</handler> + <handler ev:event="click">;</handler> + </g> + </defs> + <rect id="frame" width="320" height="600" rx="15" fill="black" stroke="black"/> + <!--text id="help" fill="rgb(90,90,120)" font-size="12" x="20" y="15">right click on home removes current widget</text--> + <g id="execbar" display="none"> + <g id="remoting" transform="translate(18, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Push</text> + <handler ev:event="click">on_widget_remote();</handler> + </g> + <g id="kill" transform="translate(55, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">KillW</text> + <handler ev:event="click">on_kill_widget();</handler> + </g> + <text id="widgetName" fill="white" font-family="Comic Sans MS" font-size="20" x="110" y="35">widgetName</text> + </g> + <g id="homebar" display="inline"> + <g id="adding" transform="translate(18, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Add</text> + <handler ev:event="click">on_widget_add_menu();</handler> + </g> + <g id="removing" transform="translate(55, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="10" x="2" y="12">Reset</text> + <handler ev:event="click">on_clean_up();</handler> + </g> + <g id="dirscan" transform="translate(92, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="30" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">Scan</text> + <handler ev:event="click">on_dir_scan();</handler> + </g> + <g id="get" transform="translate(130, 22)"> + <rect rx="8" ry="8" fill="rgb(140,140,50)" width="36" height="16"/> + <text fill="black" font-family="Comic Sans MS" font-size="12" x="2" y="12">GetW</text> + <handler ev:event="click">on_get_widget();</handler> + </g> + </g> + <rect id="screen" width="320" height="480" fill="white" stroke="black" x="0" y="60"/> + + <g id="homepage" transform="translate(0, 60)"> + <rect id="gridback" width="320" height="480" fill="rgb(40,40,40)" stroke="black"/> + <g id="grid"> + <use xlink:href="#odd" transform="translate(0, 0)"/> + <use xlink:href="#even" transform="translate(0, 80)"/> + </g> + <g id="icons" transform="translate(0,0)"> + </g> + </g> + + <g transform="translate(0,60)"> + <g id="widget"> + </g> + </g> + + <g transform="translate(0,60)"> + <g id="widgetAddList"/> + </g> + + + <g id="commands" transform="translate(0, 540)"> + <g id="homeButton" transform="translate(160,30)"> + <circle r="20" fill="rgb(40,40,40)" stroke="yellow"/> + <rect width="18" height="18" x="-9" y="-9" fill="none" stroke="yellow"/> + <handler ev:event="click">home_button(evt);</handler> + </g> + <g id="arrows"> + <g id="left" display="none" transform="translate(10, 10)"> + <animation xlink:href="icons/left_arrow.svg" width="40" height="40"/> + <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> + <handler ev:event="click">left_button();</handler> + </g> + <g id="right" display="none" transform="translate(270, 10)"> + <animation xlink:href="icons/right_arrow.svg" width="40" height="40"/> + <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> + <handler ev:event="click">right_button();</handler> + </g> + </g> + <g id="arrowsW"> + <g id="leftW" display="none" transform="translate(10, 10)"> + <animation xlink:href="icons/go-previous.svg" width="40" height="40"/> + <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> + <handler ev:event="click">left_buttonW();</handler> + </g> + <g id="rightW" display="none" transform="translate(270, 10)"> + <animation xlink:href="icons/go-next.svg" width="40" height="40"/> + <rect width="40" height="40" fill="none" stroke="none" pointer-events="all"/> + <handler ev:event="click">right_buttonW();</handler> + </g> + </g> + </g> + <rect id="rightCut" width="1000" height="600" x="321" y="0" fill="white" stroke="none"/> + <rect id="leftCut" width="1000" height="600" x="-1001" y="0" fill="white" stroke="none"/> + <rect id="frame2" width="320" height="600" rx="15" fill="none" stroke="black"/> + <script xlink:href="mpegu-core.js"/> + <script xlink:href="iphone_wm_gui.js"/> + <handler ev:event="resize">resize();</handler> + <animateColor id="getAttention" attributeName="fill" xlink:href="#frame" begin="indefinite" dur="1" from="red" + to="black" restart="always" fill="freeze"/> +</svg>
View file
gpac-1.0.1.tar.gz/share/deprecated/mpegu-core.js
Added
@@ -0,0 +1,1794 @@ +//This software module was originally developed by Telecom Paris in the +//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard. +// +//This software module is an implementation of a part of one or +//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets +//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets +//(ISO/IEC 23007-1) free license to this software module or modifications +//thereof for use in hardware or software products claiming conformance to +//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software +//module in hardware or software products are advised that its use may +//infringe existing patents. +//The original developer of this software module and his/her company, the +//subsequent editors and their companies, and ISO/IEC have no liability +//for use of this software module or modifications thereof in an implementation. +//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming +//products. +//Telecom Paris retains full right to use the code for his/her own purpose, +//assign or donate the code to a third party and to inhibit third parties from +//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products. +// +//This copyright notice must be included in all copies or derivative works. +// +//Copyright (c) 2009. +// +///////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////// +// +// Authors: +// Jean Le Feuvre, Telecom Paris +// Jean-Claude Dufourd, Telecom Paris +// +///////////////////////////////////////////////////////////////////////////////// + +// 01122011 AMD1 startWidget listWidgets getWidget implemented + +/* + The widget manager in MPEG-U reference software is implemented in 2 parts: + - a native GPAC module called gm_widgetman implementing + * W3C widget loading (download, unzip, manifest parsing) + * W3C Widget APIs + * MPEG Widgets interfaces, messages and parameters listing + + - a script module (this file) implementing + * MPEG Widget interface binding with UPnP services (UPnP is implemented in another module) + * MPEG Widget interface binding with other local widgets + * MPEG Widget discovery through UPnP devices announcement. The discovery is done by setting the device presentationURL to the widget URL + + + A typical user of the widget manager will therefore see the following interfaces: + +interface WidgetManager { + readonly unsigned integer num_widgets; + string last_widget_dir; + + Widget open(string url, string source_ip); + void bind(Widget wid); + Widget get(unsigned int idx); + void unload(Widget wid); + void migrate_widget(upnp_renderer, widget); + void corein_message(widget, msg_name, arg1name, arg1val, ....); + + //callback functions for the GUI to be notifed of widgets added / removed when UPnP devices are appearing/disappearing + void on_widget_add(widget); + void on_widget_remove(widget); + + //callback functions for core:out + void coreOutSetSize(wid, args); + void coreOutShow(wid, args); + void coreOutHide(wid, args); + void coreOutRequestActivate(wid, args); + void coreOutRequestDeactivate(wid, args); + void coreOutShowNotification(wid, args); + void coreOutPlaceComponent(wid, args); + void coreOutGetAttention(wid, args); + + } + + +interface Widget { + //exported meta-data from MPEG-U Manifest + readonly string mainEncoding; + readonly string mainMimeType; + readonly integer defaultWidth; + readonly integer defaultHeight; + + readonly Array icons; + readonly Array features; + readonly Array preferences; + + + readonly string identifier; + readonly string name; + readonly string shortName; + readonly string authorName; + readonly string authorEmail; + readonly string authorHref; + readonly string description; + readonly string viewmodes; + readonly string licence; + readonly string licenceHref; + readonly string version; + readonly string uuid; + readonly boolean discardable; + readonly boolean multipleInstances; + + //widget-manager specific data + readonly string manifest; + readonly string main; + readonly string localizedSrc; + readonly Array components; //array of widget objects used as component + boolean permanent; + readonly boolean is_component; + readonly Widget parent; + readonly boolean activated; + readonly string section; + readonly integer num_section; + readonly integer num_interfaces; + readonly integer num_bound_interfaces; + readonly integer num_components; + + + device = local UPnP device created in order to publish interfaces of this widget as upnp services + originating_device = the device who sent the widget, either through migration or device discovery (presentationURL) + originating_device_ip = the IP of the device who sent the widget + + + + void activate(Element node_with_ref_to_main); + void deactivate(); + } + +interface Icon { + readonly string src; + readonly string relocated_src; + readonly integer width; + readonly integer height; +} + +interface Preference { + readonly string name; + readonly string value; + readonly boolean readonly; +} + +interface Features { + readonly string name; + readonly boolean required; + readonly Array params +} + +interface FeatureParam { + readonly string name; + readonly string value; +} + */ + +/*log function*/ +function log(lev, str) { + if (lev <= log_level) alert('[WM] ' + str); +} + +/*log levels*/ +l_err = 0; +l_war = 1; +l_inf = 2; +l_deb = 3; + +/*default log level*/ +log_level = l_deb; + +whiteSpaceRegExp = new RegExp(' ', 'g'); + +/*initializes the widget manager*/ +function widget_manager_init() { + log(l_inf, 'Initializing MPEG-U Widgets'); + /*if UPnP is enabled, override the deviceAdd callback*/ + WidgetManager.upnp = false; + WidgetManager.migrate_widget = wmjs_migrate_widget; + WidgetManager.probe = wmjs_probe_widget; + WidgetManager.open = wmjs_open_widget; + WidgetManager.bind = wmjs_bind_widget; + + WidgetManager.on_widget_add = wmjs_on_widget_add; + WidgetManager.on_widget_remove = wmjs_on_widget_remove; + + WidgetManager.check_bindings = wmjs_bind_widgets; + WidgetManager.unbind_widget = wmjs_unbind_widget; + WidgetManager.corein_message = wmjs_corein_message; + + WidgetManager.get_mpegu_service_providers = wmjs_get_mpegu_service_providers; + WidgetManager.initialize(); + + if (typeof(UPnP) != 'undefined') { + WidgetManager.upnp = true; + log(l_inf, 'Enabling Widget UPnP Discovery') + UPnP.onDeviceAdd = wmjs_on_device_add; + log(l_inf, 'Creating the standard MPEG-U Service') + wmjs_create_standard_service(); + } + log(l_inf, 'MPEG-U Widgets successfully initialized'); + initCore(); +} + +function wmjs_on_widget_add(widget) {} + +function wmjs_on_widget_remove(widget) {} + +function wmjs_probe_widget(url) { + if ((url.lastIndexOf('.wgt') >= 0) || (url.lastIndexOf('.mgt') >= 0) || (url.lastIndexOf('.xml') >= 0)) return 1; + return 0; +} + +function wmjs_bind_output_trigger(widget, msg, callback, udta) +{ + var res = widget.bind_output_trigger(msg, callback, udta); + if (!res) { + log(l_err, 'Cannot bind output trigger of message '+msg.name+' in widget '+widget.name); + } +} + +function wmjs_open_widget(url, src_ip, parent_widget) { + log(l_deb, "wmjs_open_widget"); + var wid; + if (arguments.length>=3) { + wid = WidgetManager.load(url, parent_widget); + } else { + wid = WidgetManager.load(url); + } + if (wid == null) { + log(l_err, 'File ' + url + ' is not a valid widget'); + return null; + } + wid.device = null; + wid.originating_device = null; + wid.originating_device_ip = null; + if (src_ip) { + wid.permanent = false; + wid.originating_device_ip = src_ip; + log(l_inf, 'Widget received - ip ' + wid.originating_device_ip); + } else { + wid.permanent = true; + wid.originating_device_ip = null; + } + return wid; +} + +/*performs an unbind check on all widgets*/ +function wmjs_unbind_widget(widget) { + var i, count, wid, ifce_count, j; + log(l_inf, 'wmjs_unbind_widget ' + widget.name); + + if (WidgetManager.upnp && widget.device) { + UPnP.DeleteDevice(widget.device); + widget.device = null; + } + + count = WidgetManager.num_widgets; + ifce_count = widget.num_interfaces; + for (i = 0; i < count; i++) { + wid = WidgetManager.get(i); + if (!wid) continue; + if (wid == widget) continue; + if (!wid.activated) continue; + + for (j = 0; j < ifce_count; j++) { + var an_ifce = widget.get_interface(j); + wid.unbind_interface(an_ifce, widget); + } + } + wmjs_bind_widgets(); +} + + +/*performs a bind check on all widgets*/ +function wmjs_bind_widgets() { + log(l_deb, 'wmjs_bind_widgets'); + var i, wid, count; + count = WidgetManager.num_widgets; + for (i = 0; i < count; i++) { + wid = WidgetManager.get(i); + if (!wid) continue; + if (!wid.activated) continue; + WidgetManager.bind(wid); + } +} + + +/*performs a bind on the given widget*/ +function wmjs_bind_widget(wid) { + var i, j, ifce_count, device, service, msg, do_bind; + + if (!wid.activated) { + log(l_inf, 'widget not activated - cannot bind'); + return; + } + ifce_count = wid.num_interfaces; + + log(l_inf, 'Binding widget ' + wid.name + ' - Nb Interfaces ' + ifce_count); + + /*browse all interfaces and locate services*/ + for (i = 0; i < ifce_count; i++) { + var ifce = wid.get_interface(i); + log(l_inf, 'Binding interface ' + ifce.type); + + /*look for a core:* service for this interface and setup*/ + if (wmjs_bind_interface_to_core_service(wid, ifce)) { + continue; + } + /*if our widget is already bound to this widget, skip it*/ + if (!ifce.multipleBinding && wid.is_interface_bound(ifce)) { + log(l_deb, 'Widget ' + wid.name + ' interface ' + ifce.type + ' already bound'); + continue; + } + /*if the widget is the provider of the service, create the service*/ + if (ifce.serviceProvider) { + log(l_inf, 'widget is a service provider'); + if (WidgetManager.upnp) wmjs_create_upnp_service(wid, ifce); + continue; + } + /*look for a UPnP service for this interface and setup*/ + if (WidgetManager.upnp && wmjs_bind_interface_to_upnp(wid, ifce)) { + continue; + } + /*look for a local service for this interface*/ + if (wmjs_bind_interface_to_local(wid, ifce)) { + continue; + } + /*no service found*/ + log(l_inf, 'Cannot find service for widget ' + wid.name + ' interface ' + ifce.type); + } +} + +/*called when a new UPnP device has been added or removed in the network*/ +function wmjs_on_device_add(device, is_add) { + log(l_deb, 'wmjs_on_device_add'); + if (!is_add) { + //TODO JCD: this is wrong, sometimes a device is not "is_add" but is not to be removed either + /*log(l_inf, 'Device Removed ' + device.Name); + wmjs_standard_service_remove(device); + wmjs_unbind_upnp_device(device); + if (device.widget != null) { + log(l_inf, 'Widget Removed ' + device.widget.name); + WidgetManager.on_widget_remove(device.widget); + device.widget.originating_device = null; + device.widget = null; + } + WidgetManager.check_bindings();*/ + return; + } + log(l_inf, 'Device Added ' + device.Name + ' URL ' + device.PresentationURL); + wmjs_standard_service_add(device); + WidgetManager.check_bindings(); + /*look for a presentation url - if not given or not identifying a widget, don't do anything*/ + var url = device.PresentationURL; + if (!url || (url == '')) return; + if (! WidgetManager.probe(url)) return; + /*OK load the widget*/ + var widget = WidgetManager.load(url); + widget.newBorn = true; + if (widget == null) { + log(l_err, 'File ' + url + ' is not a valid widget'); + return; + } + widget.originating_device = device; + device.widget = widget; + /*indicate our widget is not to be stored*/ + widget.permanent = false; + WidgetManager.on_widget_add(widget); +} + + +/* + LOCAL INTERFACE BINDING ROUTINES + + In this implementation, widgets-to-widget communication in the same widget manager are called "local" communications. + The implementation do not rely on any service description for that and directly matches the widgets interfaces + */ + +function wmjs_output_trigger_callback_local(msg_out, wid_src, msg_in, wid_dst) { + log(l_deb, "wmjs_output_trigger_callback_local"); + return function(value) { + log(l_deb, "wmjs_output_trigger_callback_local/function " + value + " '" + wid_src.name + "'" + wid_dst.name + "'"); + var param_count = msg_out.num_params; + var args = new Array(); + var is_script = 0; + var ai = 0, i; + if (msg_in.has_script_input) is_script = 1; + log(l_inf, 'Invoking Widget(' + wid_src.name + ').' + msg_out.name); + for (i = 0; i < param_count; i++) { + var param = msg_out.get_param(i); + if (param.is_input) continue; + + if (is_script) { + args[ai] = wid_src.get_param_value(param); + ai++; + } else { + wid_dst.set_input(msg_in.get_param(param.name), wid_src.get_param_value(param)); + } + } + log(l_inf, 'Calling Widget(' + wid_dst.name + ').' + msg_in.name); + + if (msg_in.has_input_action) { + wid_dst.call_input_action(msg_in); + } else if (is_script) { + wid_dst.call_input_script(msg_in, args); + } + }; +} + + +function wmjs_interface_invoke_callback_local(wid_dst, ifce_dst, is_reply) { + log(l_deb, "wmjs_interface_invoke_callback_local '" + wid_dst.name + "' '" + ifce_dst.type + "' - reply " + is_reply); + return function() { + log(l_deb, "wmjs_interface_invoke_callback_local/function '" + wid_dst.name + "' '" + ifce_dst.type + "' - reply " + is_reply); + var j, i, ai, param_count, msgHandler, msg_src, msg_dst, is_script; + var args = new Array(); + is_script = 0; + msgHandler = arguments[0]; + /*get msg from source interface (this object)*/ + msg_src = this.get_message(msgHandler.msgName); + // JCD: take into account message repetition, if any + for (j = 0; j < ifce_dst.num_messages; j++) { + msg_dst = ifce_dst.get_message(j); + if (msg_dst.name == msgHandler.msgName) { + log(l_deb, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on ' + wid_dst.name + '.' + msg_dst.name); + if (msg_dst.has_script_input) is_script = 1; + param_count = msg_src.num_params; + ai = 1; + for (i = 0; i < param_count; i++) { + var param = msg_dst.get_param(i); + if (! param.is_input) continue; + if (is_script) { + args[ai - 1] = arguments[ai]; + } else { + wid_dst.set_input(param, arguments[ai]); + } + ai++; + } + if (msg_dst.has_input_action) { + wid_dst.call_input_action(msg_dst); + } else if (is_script) { + wid_dst.call_input_script(msg_dst, args); + } + } + } + }; +} + +/* + END OF LOCAL INTERFACE BINDING ROUTINES + */ + + +function wmjs_bind_interface_to_local(wid, ifce) { + log(l_deb, "wmjs_bind_interface_to_local '" + wid.name + "' " + ifce.type); + var i, count, count2, j, a_ifce, a_msg, par, a_par, k, nb_ok, ret, set_bind, a_wid; + count = WidgetManager.num_widgets; + ret = false; + // this is the main loop to try to bind a widget to any other + for (i = 0; i < count; i++) { + a_wid = WidgetManager.get(i); + if (!a_wid) continue; + if (a_wid == wid) continue; + if (!a_wid.activated) continue; + count2 = a_wid.num_interfaces; + // now that we know this is a valid widget and not the same as wid + // loop on all its interfaces to find one of the right type + for (j = 0; j < count2; j++) { + a_ifce = a_wid.get_interface(j); + if (a_ifce.type == ifce.type) break; + } + if (j == count2) continue; + + /*if our widget is already bound to this widget (multiple binding==true) or to any widget (multiple binding==false), skip it*/ + if (wid.is_interface_bound(ifce, ifce.multipleBinding ? a_wid : null)) { + log(l_inf, 'Widget ' + wid.name + ' interface ' + ifce.type + ' is already bound'); + continue; + } + /*if our widget is already bound to this widget (multiple binding==true) or to any widget (multiple binding==false), skip it*/ + if (a_wid.is_interface_bound(a_ifce, a_ifce.multipleBinding ? wid : null)) { + log(l_inf, 'Widget ' + a_wid.name + ' interface ' + a_ifce.type + ' is already bound'); + continue; + } + + set_bind = 0; + // we have found an interface of the right type in the other widget + log(l_inf, 'Checking local widget ' + a_wid.name + ' for interface ' + ifce.type); + // loop on the messages to check if they match + for (j = 0; j < ifce.num_messages; j++) { + var msg = ifce.get_message(j), l; + //if (msg.is_input) continue; // JCD: remove test + // does the other interface have this message + // JCD: remove next line and take repetition of messages into account + // a_msg = a_ifce.get_message(msg.name); + for (l = 0; l < a_ifce.num_messages; l++) { + a_msg = a_ifce.get_message(l); + //alert(msg.name+" "+a_msg.name); + if (a_msg.name == msg.name) { + // the messages have matching names, check direction + if (msg.is_input == a_msg.is_input) { + log(l_inf, 'Local widget message for ' + msg.name + ' is not in direction ' + (msg.is_input ? 'output' : 'input')); + continue; + } + // the messages have matching names and directions, check params + if (msg.num_params != a_msg.num_params) { + log(l_war, 'Local widget message ' + msg.name + ' does not have the same number of parameters'); + continue; + } + /*check all params*/ + nb_ok = 0; + for (k = 0; k < msg.num_params; k++) { + par = msg.get_param(k); + a_par = a_msg.get_param(par.name); + if (a_par != null && par.is_input != a_par.is_input) nb_ok ++; + } + if (nb_ok != msg.num_params) { + log(l_war, 'Local widget message ' + msg.name + ' does not have the same input/output parameters'); + continue; + } + set_bind ++; + // the messages match + log(l_inf, 'Binding ' + wid.name + '.' + msg.name + ' to ' + a_wid.name + '.' + a_msg.name); + /*OK let's bind this action: we only need to assign the output trigger, the input action will be called from the other widget*/ + if (msg.has_output_trigger) { + wmjs_bind_output_trigger(wid, msg, wmjs_output_trigger_callback_local(msg, wid, a_msg, a_wid), a_wid); + } + /*OK let's bind this action: we only need to assign the output trigger, the input action will be called from the other widget*/ + if (a_msg.has_output_trigger) { + wmjs_bind_output_trigger(a_wid, a_msg, wmjs_output_trigger_callback_local(a_msg, a_wid, msg, wid), wid); + } + } + } + } + if (!set_bind) continue; + + /*create callback for programmatic action triggers*/ + ifce.invoke = wmjs_interface_invoke_callback_local(a_wid, a_ifce, 0); + ifce.invokeReply = wmjs_interface_invoke_callback_local(a_wid, a_ifce, 1); + /*create callback for programmatic action triggers*/ + a_ifce.invoke = wmjs_interface_invoke_callback_local(wid, ifce, 0); + a_ifce.invokeReply = wmjs_interface_invoke_callback_local(wid, ifce, 1); + a_wid.bind_interface(a_ifce, wid, 'localhost'); + wid.bind_interface(ifce, a_wid, 'localhost'); + ret = true; + } + return ret; +} + + +/* + INTERFACE BINDING TO UPNP SERVICES ROUTINES + + This implemntation supports binding interfaces to existing UPnP services + */ + +/*create a listener function for input parameters*/ +function wmjs_upnp_action_listener(widget, par, msg) { + log(l_deb, "wmjs_upnp_action_listener '" + widget.name + "' " + (par != null ? par.name : 'noPar') + " " + (msg != null ? msg.name : 'noMsg')); + return function(value) { + log(l_deb, "wmjs_upnp_action_listener/function '" + widget.name + "' " + (par != null ? par.name : 'noPar') + " " + + (msg != null ? msg.name : 'noMsg') + " " + value); + if (par != null) widget.set_input(par, value); + if (msg != null) widget.call_input_action(msg); + } +} + +/*create a listener function for input parameters*/ +function wmjs_upnp_action_listener_script(widget, msg) { + log(l_deb, 'wmjs_upnp_action_listener_script'); + return function() { + var i, count, act, par, rval, msgHandler, args; + act = arguments[0]; + log(l_deb, 'wmjs_upnp_action_listener_script/function:nb args ' + arguments.length); + msgHandler = arguments[1]; + log(l_deb, 'wmjs_upnp_action_listener_script/function:msgh ' + msgHandler); + args = new Array(); + count = msg.num_params; + for (i = 0; i < count; i++) { + par = msg.get_param(i); + if (!par.is_input) continue; + rval = act.GetArgumentValue(par.name); + if (par.script_type == 'number') { + args.push(parseInt(rval)); + } else if (par.script_type == 'boolean') { + args.push(rval == 'true'); + } else { + args.push(rval); + } + } + msgHandler.onInvokeReply(args); + } +} + + +/**/ +function wmjs_output_trigger_callback_upnp(service, widget, msg) { + log(l_deb, 'wmjs_output_trigger_callback_upnp'); + return function(value) { + log(l_deb, 'wmjs_output_trigger_callback_upnp/function ' + value); + var i, pi, param_count = msg.num_params; + var args = new Array(); + pi = 0; + for (i = 0; i < param_count; i++) { + var param = msg.get_param(i); + if (param.is_input) continue; + args[pi] = param.name; + args[pi + 1] = widget.get_param_value(param); + pi += 2; + } + log(l_inf, 'Calling UPnP Action ' + msg.name + " " + param_count); + service.CallAction(msg.name, args); + }; +} + + +/*create the action callback*/ +function wmjs_message_setup_upnp(widget, service, msg) { + log(l_deb, 'wmjs_message_setup_upnp ' + msg.name); + /*first let's browse all the message params*/ + var rad, i, param_count, has_script_input; + has_script_input = false; + param_count = msg.num_params; + for (i = 0; i < param_count; i++) { + var param = msg.get_param(i); + /*interface not valid for this service*/ + if (!service.HasAction(msg.name, param.name)) { + if (!param.is_input) { + log(l_war, 'Output param ' + param.name + ' not found in action - cannot bind action'); + return false; + } + continue; + } + /*this is a service -> widget param */ + if (param.is_input) { + if (msg.has_input_action) { + service.SetActionListener(msg.name, wmjs_upnp_action_listener(widget, param, null), param.name); + } else { + has_script_input = true; + // todo: pas vrai d'apres JCD + } + } + /*this is a widget -> service param , used in callback function*/ + } + /*assign the output trigger*/ + if (msg.has_output_trigger) { + var fun_name = 'call_' + msg.name; + widget[fun_name] = wmjs_output_trigger_callback_upnp(service, widget, msg); + wmjs_bind_output_trigger(widget, msg, widget[fun_name], service); + } + /*assign the input action*/ + if (msg.has_input_action) { + service.SetActionListener(msg.name, wmjs_upnp_action_listener(widget, null, msg)); + } else if (has_script_input) { + service.SetActionListener(msg.name, wmjs_upnp_action_listener_script(widget, msg), true); + } + return true; +} + + +function wmjs_interface_invoke_callback_upnp(service) { + log(l_deb, 'wmjs_interface_invoke_callback_upnp'); + return function() { + log(l_deb, 'wmjs_interface_invoke_callback_upnp/function'); + var args = new Array(); + var i, pi, ai, param_count, msg, ifce_msg; + + msg = arguments[0]; + ifce_msg = this.get_message(msg.msgName); + param_count = ifce_msg.num_params; + log(l_inf, 'UPnP invoke action ' + ifce_msg.name + ' - ' + msg.msgName); + + pi = 0; + ai = 1; + for (i = 0; i < param_count; i++) { + var param = ifce_msg.get_param(i); + if (param.is_input) continue; + + args[pi] = param.name; + args[pi + 1] = arguments[ai]; + pi += 2; + ai++; + } + service.CallAction(msg.msgName, args, msg); + }; +} + + +function wmjs_bind_interface_to_upnp(wid, ifce) { + log(l_deb, "wmjs_bind_interface_to_upnp"); + var do_bind, is_upnp = false; + var service = null; + + if (wid.originating_device) { + service = wid.originating_device.FindService(ifce.type); + } else if (wid.originating_device_ip) { + service = UPnP.FindService(wid.originating_device_ip, ifce.type); + } else { + var j, dev_count = UPnP.DevicesCount; + log(l_deb, 'wmjs_bind_interface_to_upnp nb ' + dev_count); + for (j = 0; j < dev_count; j++) { + device = UPnP.GetDevice(j); + log(l_deb, "wmjs_bind_interface_to_upnp " + device.Name + ' - type: ' + ifce.type); + /*do we have a UPnP service with the same interface type ?*/ + service = device.FindService(ifce.type); + + /*our widget is not bound to this service*/ + if (service) { + if (!wid.is_interface_bound(ifce, service)) break; + service = null; + is_upnp = true; + } + } + } + if (!service) return is_upnp; + + /*our widget is already bound to this service*/ + if (wid.is_interface_bound(ifce, service)) { + log(l_inf, 'Found UPnP Service for interface ' + ifce.type); + return true; + } + + log(l_inf, 'Found UPnP Service for interface ' + ifce.type); + do_bind = 0; + for (j = 0; j < ifce.num_messages; j++) { + var msg = ifce.get_message(j); + /*if we have a state variable in the service with the same name as the pin, bind it*/ + if (service.HasStateVariable(msg.name)) { + var param = msg.get_param(0); + if (param && (param.name == msg.name)) { + /*set listeners for declarative action triggers*/ + log(l_deb, 'Found UPnP state variable for message ' + msg.name); + service.SetStateVariableListener(wmjs_upnp_action_listener(wid, param, msg), param.name); + do_bind = 1; + } + } + /*if we have an action in the service with the same name as the pin, bind it*/ + else if (service.HasAction(msg.name)) { + /*set listeners for declarative action triggers*/ + log(l_deb, 'Found UPnP action for message ' + msg.name); + wmjs_message_setup_upnp(wid, service, msg); + do_bind = 1; + } + /*NOTE: UPnP actions are only messageOut, messageIn are UPnP events and don't have output paramaters. We therefore never need to setup + the invokeReply callback for interfaces matching UPnP services. !! This is not true for UPnP services created to publish an interface, eg serviceProvider="true".*/ + } + if (do_bind) { + /*create callback for programmatic action triggers*/ + log(l_inf, 'Binding widget ' + wid.name + ' interface ' + ifce.type + ' to host ' + service.Hostname); + ifce.invoke = wmjs_interface_invoke_callback_upnp(service); + /*bind interface*/ + wid.bind_interface(ifce, service, service.Hostname); + } + return true; +} + +function wmjs_unbind_upnp_device(device) +{ + var i, count, j, ifce_count; + count = WidgetManager.num_widgets; + + for (i = 0; i < count; i++) { + wid = WidgetManager.get(i); + if (!wid) continue; + if (!wid.activated) continue; + + ifce_count = wid.num_interfaces; + for (j = 0; j < ifce_count; j++) { + var ifce = wid.get_interface(j); + /*do we have a UPnP service with the same interface type ?*/ + var service = device.FindService(ifce.type); + if (!service) continue; + + /*unbind this interface*/ + if (wid.is_interface_bound(ifce, service)) { + wid.unbind_interface(ifce, service); + } + } + } +} + +/* + END OF INTERFACE BINDING TO UPNP SERVICES ROUTINES + */ + +// +// section on widget migration +// + +header = '<scpd xmlns="urn:schemas-upnp-org:service-1-0"><specVersion><major>1</major><minor>0</minor></specVersion><actionList>'; +middler = '</actionList><serviceStateTable>'; +footer = '</serviceStateTable></scpd>'; +standard_service_scpd = header+'<action><name>startWidget</name><argumentList><argument><name>widgetUrl</name><direction>in</direction><relatedStateVariable>s1</relatedStateVariable></argument><argument><name>widgetUUID</name><direction>in</direction><relatedStateVariable>s2</relatedStateVariable></argument><argument><name>widgetContext</name><direction>in</direction><relatedStateVariable>s3</relatedStateVariable></argument><argument><name>errorCode</name><direction>out</direction><relatedStateVariable>s4</relatedStateVariable></argument></argumentList></action>'; +{ + standard_service_scpd += '<action><name>requestCapabilitiesList</name><argumentList><argument><name>capabilitiesType</name><direction>out</direction><relatedStateVariable>s5</relatedStateVariable></argument><argument><name>capabilities</name><direction>out</direction><relatedStateVariable>s6</relatedStateVariable></argument></argumentList></action>'; + standard_service_scpd += '<action><name>listWidgets</name><argumentList><argument><name>widgetCodes</name><direction>out</direction><relatedStateVariable>s7</relatedStateVariable></argument><argument><name>widgetNames</name><direction>out</direction><relatedStateVariable>s8</relatedStateVariable></argument><argument><name>widgetIdentifiers</name><direction>out</direction><relatedStateVariable>s9</relatedStateVariable></argument></argumentList></action>'; + standard_service_scpd += '<action><name>getWidget</name><argumentList><argument><name>widgetCode</name><direction>in</direction><relatedStateVariable>s10</relatedStateVariable></argument><argument><name>errorCode</name><direction>out</direction><relatedStateVariable>s11</relatedStateVariable></argument>'; + standard_service_scpd += '<argument><name>widgetUrl</name><direction>out</direction><relatedStateVariable>s41</relatedStateVariable></argument><argument><name>widgetUUID</name><direction>out</direction><relatedStateVariable>s42</relatedStateVariable></argument><argument><name>widgetContext</name><direction>out</direction><relatedStateVariable>s43</relatedStateVariable></argument></argumentList></action>'; + standard_service_scpd += middler+'<stateVariable><name>s1</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s2</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s3</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s4</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s5</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s6</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s7</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s8</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s9</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s10</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s11</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s41</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s42</name><dataType>string</dataType></stateVariable>'; + standard_service_scpd += '<stateVariable><name>s43</name><dataType>string</dataType></stateVariable>'+footer; +} + +// +// migrate a widget by calling the appropriate startWidget message of the target +// migration service +// +function wmjs_migrate_widget(render, widget) { + if (WidgetManager.upnp) { + var url, ctx, uri; + + url = widget.url; + /*share the widget*/ + uri = UPnP.ShareResource(url, render.HostName); + + ctx = widget.get_context(); + + if (ctx == null) ctx = ""; + log(l_inf, 'Migrating widget ' + url + ' to renderer ' + render.Name + ' as resource ' + uri); + log(l_inf, 'Migration Context ' + ctx); + + // envoyer la methode startWidget sur render + var args = new Array(); + args.push("widgetUrl"); + args.push(uri); + args.push("widgetUUID"); + args.push(null); + args.push("widgetContext"); + args.push(ctx); + log(l_inf, "startWidget "+uri); + log(l_inf, "startWidgetCtx "+ctx); + alert("call StdServ "+render.Name+" "+render.standardService); + var code = render.standardService.CallAction("startWidget", args); + log(l_inf, "return code from standardService.CallAction is "+code); + } +} + +// +// check whether the removed device was a publisher of MPEGUStandardService +// if yes, remove it from the list +// +function wmjs_standard_service_remove(device) { + var service = device.FindService("urn:mpeg-u:service:widget-manager:1"); + if (service != null) { + var i = WidgetManager.MPEGUStandardServiceProviders.indexOf(device); + if (i >= 0) { + log(l_err, "migration service remove "+device.Name); + WidgetManager.MPEGUStandardServiceProviders.splice(i, 1); + } else log(l_err, "Trying to remove a standard service device which was not added first: "+device); + } +} + +// +// add a migration service provider to the list and remember the service in the device +// +function wmjs_standard_service_add(device) { + var service = device.FindService("urn:mpeg-u:service:widget-manager:1"); + if (service != null) { + log(l_err, "migration service add "+device.Name); + WidgetManager.MPEGUStandardServiceProviders.push(device); + device.standardService = service; + alert("add StdServ "+device.Name+" "+device.standardService); + } +} + +// +// get the nth standard service provider (migration service) +// +function wmjs_get_mpegu_service_providers(index) { + if (!WidgetManager.MPEGUStandardServiceProviders) { + log(l_err, "uninitialized MPEGUStandardServiceProviders"); + return null; + } + if (index < 0 || index > WidgetManager.MPEGUStandardServiceProviders.length) { + log(l_err, "index of MPEGUStandardServiceProviders out of bounds:"+index); + return null; + } + return WidgetManager.MPEGUStandardServiceProviders[index]; +} + +function wmjs_create_standard_service() { + //alert("create_standard_service"); + var name = "MPEG-U"; + var option = scene.get_option('General', 'DeviceName'); + if (option) name = option; + WidgetManager.device = UPnP.CreateDevice("urn:mpeg-u:device:widget-manager:1", name+"@"+Sys.hostname); + WidgetManager.device.enabled = 1; + /* implement the response to a external call (messageOut of another widget) */ + WidgetManager.device.OnAction = wmjs_widget_standard_service_process_action; + log(l_err, 'wmjs_create_standard_service'); + //log(l_inf, 'Service scpd ' + standard_service_scpd); + /* WidgetManager.standardService = */ + var service = WidgetManager.device.SetupService("MPEG-U_Standard_Service", "urn:mpeg-u:service:widget-manager:1", + "urn:mpeg-u:serviceId:widget-manager:1.001", standard_service_scpd); + WidgetManager.device.Start(); + WidgetManager.MPEGUStandardServiceProviders = new Array(); + //alert("create_standard_service end"); +} + +/* generic processing of any action from outside for the standard MPEG-U service */ +function wmjs_widget_standard_service_process_action(action) { + log(l_err, 'wmjs_widget_standard_service_process_action Action ' + action.Name); + /* find the message matching the action in the interface */ + if (action.Name == "startWidget") { + process_startWidget_action(action); + } else if (action.Name == "requestCapabilitiesList"){ + process_requestCapabilitiesList_action(action); + } else if (action.Name == "listWidgets") { + process_listWidgets_action(action); + } else if (action.Name == "getWidget") { + process_getWidget_action(action); + } else { + log(l_inf, 'wmjs_widget_standard_service_process_action Action not found: ' + action.Name); + } +} + +// +// processing of a request to start a widget (push migration or predefined "activateWidgetByUrl") +// +function process_startWidget_action(action) { + log(l_err,"process start widget"); + // get action arguments + var widgetUrl = action.GetArgument("widgetUrl"); + var widgetUUID = action.GetArgument("widgetUUID"); + var widgetContext = action.GetArgument("widgetContext"); + log(l_err,"start:"+widgetUrl+" "+widgetUUID+" "+widgetContext); + // get widget + if (widgetUrl == null && widgetUUID != null) { + log(l_err, "unable to load a widget by UUID: unimplemented"); + action.SendReply(["errorCode", 1]); + return; + } + var wid = WidgetManager.load(widgetUrl, null, widgetContext); + WidgetManager.on_widget_add(wid); + action.SendReply(["errorCode", 0]); +} + +// +// processing of a request for the list of capabilities +// +function process_requestCapabilitiesList_action(action) { + //TODO + alert("UNIMPLEMENTED in mpegu-core.js: request capabilities list"); +} + +// +// processing of a request for the list of widgets (prelude to a pull migration) +// +function process_listWidgets_action(action) { + log(l_err,"process list widgets"); + // list widget + var count = WidgetManager.num_widgets, i, r1 = "", r2 = "", includeSpace = false; + for (i = 0; i < count; i++) { + var wid = WidgetManager.get(i); + if (wid.activated) { + if (includeSpace) { + r1 += " "; + } else { + includeSpace = true; + } + r1 += i+1; + r2 += wid.name.replace(whiteSpaceRegExp, '_')+" "; + } + } + alert("sendReply widgetCodes=|"+r1+"| widgetNames=|"+r2+"|"); + action.SendReply(["widgetCodes", r1, "widgetNames", r2]); +} + +// +// processing of a pull migration request +// +function process_getWidget_action(action) { + log(l_deb, "process get widget "+action+" "+action.Name); + // get action arguments + var widgetCode = action.GetArgument("widgetCode"); + log(l_deb, "get:"+widgetCode); + // get widget + var wid = WidgetManager.get(parseInt(widgetCode) - 1); + var url, ctx, uri; + url = wid.url; + /*share the widget*/ + uri = UPnP.ShareResource(url); + ctx = wid.get_context(); + if (ctx == null) ctx = ""; + log(l_inf, 'sendReply widget ' + url + ' as resource ' + uri); + log(l_inf, 'with context ' + ctx); + var args = new Array(); + args.push("errorCode"); + args.push(0); + args.push("widgetUrl"); + args.push(uri); + args.push("widgetUUID"); + args.push(null); + args.push("widgetContext"); + args.push(ctx); + action.SendReply(args); + WidgetManager.on_widget_remove(wid); +} + +// +// end of migration service +// + +/* + INTERFACE PUBLISHING AS UPNP SERVICES ROUTINES + + This implementation supports publishing a widget interface in the network as a UPnP service. This is done + by generating on the fly a new device associated with a widget, and one UPnP service per widget interface. + The UPnP service description (SCPD) is generated on the fly from the interface description + */ + +function wmjs_make_interface_scpd(widget, ifce) { + log(l_deb, "wmjs_make_interface_scpd"); + var variables = '', actions = '', vars, j, msg, k, param, numstatevar = 0; + /*do actions*/ + for (j = 0; j < ifce.num_messages; j++) { + msg = ifce.get_message(j); + actions += '<action><name>' + msg.name + '</name><argumentList>'; + for (k = 0; k < msg.num_params; k++) { + param = msg.get_param(k); + actions += '<argument><name>' + param.name + '</name><direction>' + (param.is_input ? 'in' : 'out'); + actions += '</direction><relatedStateVariable>v' + numstatevar + '</relatedStateVariable></argument>'; + numstatevar++; + } + actions += '</argumentList></action>'; + } + /*do variables*/ + for (k = 0; k < numstatevar; k++) { + variables += '<stateVariable><name>v' + k + '</name><dataType>string</dataType></stateVariable>'; + } + return header + actions + middler + variables + footer; +} + +/* generic processing of any action from outside */ +function wmjs_widget_upnp_process_action(action) { + log(l_err, 'wmjs_widget_upnp_process_action Action ' + action.Name + ' invoked on ' + action.Service.ifce.type); + var i, ai, args, msg, has_output = false; + /* find the message matching the action in the interface */ + msg = null; + for (i = 0; i < action.Service.ifce.num_messages; i++) { + msg = action.Service.ifce.get_message(i); + if (msg.name == action.Name) break; + msg = null; + } + if (msg == null) { + log(l_inf, 'wmjs_widget_upnp_process_action Action not found: ' + action.Name + ' invoked on ' + action.Service.name); + return; + } + args = new Array(); + ai = 0; + /*assign action for any async callback from the scene (cf wmjs_upnp_action_response)*/ + action.Service.action = action; + /* for each param in the found message */ + for (i = 0; i < msg.num_params; i++) { + var param = msg.get_param(i); + /* only process input params */ + if (!param.is_input) { + has_output = true; + continue; + } + if (msg.has_script_input) { + /* input param is scripted, store argument value in args array */ + args[ai] = action.GetArgument(param.name); + } else { + /* input param is not scripted but declarative, store argument value directly in scene tree */ + this.widget.set_input(param, action.GetArgument(param.name)); + } + ai++; + } + if (msg.has_input_action) { + /* message is not scripted, call input action */ + this.widget.call_input_action(msg); + } else if (msg.has_script_input) { + /* message is scripted, call the script function specified in inputAction */ + this.widget.call_input_script(msg, args); + } + if (!has_output) { + log(l_inf, 'wmjs_widget_upnp_process_action sending empty reply'); + action.SendReply(); + action.Service.action = null; + } +} + +function wmjs_upnp_event_sender(service, widget, msg) { + return function(value) { + log(l_deb, 'wmjs_upnp_event_sender/function ' + service.ifce.type + " " + widget.name + " " + msg.name); + var i, pi, param_count = msg.num_params; + var args = new Array(); + pi = 0; + for (i = 0; i < param_count; i++) { + var param = msg.get_param(i); + if (param.is_input) continue; + args[pi] = param.name; + args[pi + 1] = widget.get_param_value(param); + pi += 2; + } + log(l_inf, 'sending UPnP event ' + msg.name); + service.CallAction(msg.name, args); + }; +} + +function wmjs_upnp_action_response(service, widget, msg) { + return function(value) { + if (service.action == null) { + // TODO this code avoids the bug that this function is called twice: find out why it is called twice! + log(l_inf, 'wmjs_upnp_action_response/function DUPL(return) ' + service.ifce.type + " '" + widget.name + "' " + msg.name); + return; + } + var i, pi, param_count = msg.num_params; + var args = new Array(); + pi = 0; + for (i = 0; i < param_count; i++) { + var param = msg.get_param(i); + if (param.is_input) continue; + args[pi] = param.name; + args[pi + 1] = widget.get_param_value(param); + pi += 2; + } + log(l_inf, 'UPnP sending reply on action ' + service.action + ': ' + service.ifce.type + " '" + widget.name + "' " + msg.name); + service.action.SendReply(args); + service.action = null; + }; +} + + +function wmjs_upnp_action_response_script(service) { + return function() { + if (service.action == null) { + // this code avoids the bug that this function is called twice: find out why it is called twice! + return; + } + var i, pi, ai, param_count; + var args = new Array(); + var msgHandler = arguments[0]; + var msg = service.ifce.get_message(msgHandler.msgName); + + pi = 0; + ai = 1; + for (i = 0; i < param_count; i++) { + var param = msg.get_param(i); + if (param.is_input) continue; + args[pi] = param.name; + args[pi + 1] = arguments[ai]; + pi += 2; + ai++; + } + log(l_inf, 'UPnP sending reply on action ' + service.action); + service.action.SendReply(args); + service.action = null; + }; +} + + +function wmjs_create_upnp_service(widget, ifce) { + var i, service, scpd, start_device = 0; + var name; + + log(l_deb, 'widget device : ' + widget.device); + + /* at least one interface is a provider, so create a device - service or device names SHALL NOT CONTAIN SPACES*/ + name = widget.name.replace(whiteSpaceRegExp, '_'); + if (!widget.device) { + //log(l_inf,'creating device'); + widget.device = UPnP.CreateDevice("urn:mpeg-u:device:provider-" + name + ":1", name); + /* remember the widget in the device */ + widget.device.widget = widget; + widget.device.enabled = 1; + start_device = 1; + /* implement the response to a external call (messageOut of another widget) */ + widget.device.OnAction = wmjs_widget_upnp_process_action; + } + + /*service has already been created*/ + if (typeof(ifce.started) != 'undefined') return; + + log(l_inf, 'wmjs_create_upnp_service'); + scpd = wmjs_make_interface_scpd(widget, ifce); + //log(l_inf, 'Service scpd ' + scpd); + service = widget.device.SetupService(name, ifce.type, ifce.type + ".001", scpd); + service.ifce = ifce; + + /* for each message in a provider interface */ + for (i = 0; i < ifce.num_messages; i++) { + msg = ifce.get_message(i); + /* if there is an output_trigger, a reply may be triggered after a call */ + if (msg.has_output_trigger) { + if (msg.is_input) { + /* output in an input message => this is a reply */ + var fun_name1 = 'respond_' + msg.name; + widget[fun_name1] = wmjs_upnp_action_response(service, widget, msg); + wmjs_bind_output_trigger(widget, msg, widget[fun_name1], service); + } else { + /* output in an output message => this is an event */ + var fun_name2 = 'send_event_' + msg.name; + widget[fun_name2] = wmjs_upnp_event_sender(service, widget, msg); + wmjs_bind_output_trigger(widget, msg, widget[fun_name2], service); + } + } + /*if message is input, a reply may be sent*/ + else if (msg.is_input) { + var j, has_out; + has_out = 0; + for (j = 0; j < msg.num_params; j++) { + var param = msg.get_param(j); + if (param.is_input) continue; + has_out = 1; + break; + } + if (has_out) { + ifce.invokeReply = wmjs_upnp_action_response_script(service); + } + } + } + ifce.started = true; + + if (start_device) { + //log(l_inf,"device start"); + widget.device.Start(); + } +} + + +/* + END OF INTERFACE PUBLISHING AS UPNP SERVICES ROUTINES + */ + +/********************************************************* + Start of implementation of core:in and core:out interfaces + *********************************************************/ + +coreIn = null, coreOut = null; + +// +// function defining messages for the core:* interfaces implemented by the WM +// +function defineMessage(name, direction, executeFunction, params1, params2) { + var msg = new Object(); + msg.name = name; + msg.is_input = !direction; // the standard defines the point of view of the widget, not that of the WM + msg.num_params = 0; + // the executeFunction is the function implemented by widman.js and + // which passes the buck to a function of the widget manager, if there is one + if (executeFunction != null) msg.execute = executeFunction; + // in a messageOut, params1 contains outputs and params2 contains inputs + // in a messageIn, params1 contains inputs and params2 contains outputs + if (direction) { + if (params1 != null) { + msg.paramsOut = params1; + msg.num_params += params1.length; + } + if (params2 != null) { + msg.paramsIn = params2; + msg.num_params += params2.length; + } + } else { + if (params1 != null) { + msg.paramsIn = params1; + msg.num_params += params1.length; + } + if (params2 != null) { + msg.paramsOut = params2; + msg.num_params += params2.length; + } + } + //alert("Message defined: "+msg.name+' '+msg.num_params+' '+msg.is_input+' '+ + // (msg.paramsIn != null ? msg.paramsIn.length : 0)+' '+ + // (msg.paramsOut != null ? msg.paramsOut.length : 0)); + return msg; +} + +// +// function defining the parameter lists for messages +// the direction of a parameter is implicit in its position in the paramsIn or paramsOut of a message +// +function defineParams() { + var params = new Array(); + var i = 0; + for (; i < arguments.length; i++) { + params[i] = arguments[i]; + } + return params; +} + +// +// get message by name in a core interface (core:in or core:out +// +function getMessage(core, s) { + var i = 0; + for (; i < core.length; i++) { + if (core[i].name == s) return core[i]; + } + return null; +} + +// +// get a parameter from a message by name +// +function hasParam(msg, name) { + var i = 0; + if (msg.paramsIn) { + for (i = 0; i < msg.paramsIn.length; i++) { + if (msg.paramsIn[i] == name) return true; + } + } + if (msg.paramsOut) { + for (i = 0; i < msg.paramsOut.length; i++) { + if (msg.paramsOut[i] == name) return true; + } + } + return false; +} + +// +// get a parameter from a message by index +// +/*function getParam(msg, i) { + if (!msg.is_input) { + if (msg.paramsIn) { + if (i < msg.paramsIn.length) { + return msg.paramsIn[i]; + } else { + i -= msg.paramsIn.length; + } + } + if (msg.paramsOut) { + if (i < msg.paramsOut.length) { + return msg.paramsOut[i]; + } + } + } else { + if (msg.paramsOut) { + if (i < msg.paramsOut.length) { + return msg.paramsOut[i]; + } else { + i -= msg.paramsOut.length; + } + } + if (msg.paramsIn) { + if (i < msg.paramsIn.length) { + return msg.paramsIn[i]; + } + } + } + return null; +}*/ + +// +// get a parameter from a message by index +// +function getInputParam(msg, i) { + if (!msg.is_input) { + if (msg.paramsIn) { + if (i < msg.paramsIn.length) { + return msg.paramsIn[i]; + } else { + return null; + } + } + } else { + if (msg.paramsOut) { + if (i < msg.paramsOut.length) { + return null; + } else { + i -= msg.paramsOut.length; + } + } + if (msg.paramsIn) { + if (i < msg.paramsIn.length) { + return msg.paramsIn[i]; + } + } + } + return null; +} + +// +// reconstruct the direction of a parameter of a message by its position +// +function paramDirection(msg, name) { + var i = 0; + if (msg.paramsIn) { + for (i = 0; i < msg.paramsIn.length; i++) { + if (msg.paramsIn[i] == name) return true; + } + } + if (msg.paramsOut) { + for (i = 0; i < msg.paramsOut.length; i++) { + if (msg.paramsOut[i] == name) return false; + } + } + return false; +} + +function initCore() { + /* + Methods implementing messageIn of the core interfaces + In these methods, this is the message and args is the list of arguments of the message + widman.js, as the common part of all widget managers, does not implement these methods directly + but passes the buck to specific WM implementations. + In specific WM implementation, an initializer function should contain + WidgetManager.coreOutSetSize = function (...) {...}; + or similar. + */ + WidgetManager.coreOutSetSize = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.setSize" + argsString); + }; + + WidgetManager.coreOutShow = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.show" + argsString); + }; + + WidgetManager.coreOutHide = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.hide" + argsString); + }; + + WidgetManager.coreOutRequestActivate = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.requestActivate" + argsString); + }; + + WidgetManager.coreOutRequestDeactivate = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.requestDeactivate" + argsString); + }; + + WidgetManager.coreOutShowNotification = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.showNotification" + argsString); + }; + + WidgetManager.coreOutPlaceComponent = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.placeComponent" + argsString); + }; + + WidgetManager.coreOutGetAttention = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.getAttention" + argsString); + }; + WidgetManager.coreOutInstallWidget = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.installWidget" + argsString); + }; + WidgetManager.coreOutMigrateComponent = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.migrateComponent" + argsString); + }; + WidgetManager.coreOutRequestMigrationTargets = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.requestMigrationTargets" + argsString); + }; + WidgetManager.coreOutActivateTemporaryWidget = function(wid, args) { + var i = 0, argsString = ""; + for (; i < args.length; i++) argsString += " " + args[i]; + log(l_deb, "*** defCoreOutImpl.activateTemporaryWidget" + argsString); + }; + /* + Define the core:* interfaces that the widget manager implements and provides to widgets + The structure of messages is simplified. + messageIn have first an array of paramsIn, then an array of paramsOut for a reply + messageOut have first an array of paramsOut, then an array of paramsIn for reply + Because of this simplification, getParam and defineMessage are dependent on the direction of the message + The direction of a parameter is implicit in the fact that it is stored in paramsIn or paramsOut of the message + */ + coreIn = new Array(); + coreOut = new Array(); + coreIn[0] = defineMessage("setSize", true, null, defineParams("width", "height", "dpi")); + coreIn.setSizeMessage = coreIn[0]; + coreIn[1] = defineMessage("show", true, null); + coreIn.showMessage = coreIn[1]; + coreIn[2] = defineMessage("hide", true, null); + coreIn.hideMessage = coreIn[2]; + coreIn[3] = defineMessage("activate", true, null); + coreIn.activateMessage = coreIn[3]; + coreIn[4] = defineMessage("deactivate", true, null); + coreIn.deactivateMessage = coreIn[4]; + coreIn.type = "urn:mpeg:mpegu:schema:widgets:core:in:2010"; + coreOut[0] = defineMessage("setSize", false, coreOutSetSize, defineParams("width", "height")); + coreOut.setSizeMessage = coreOut[0]; + coreOut[1] = defineMessage("show", false, coreOutShow); + coreOut.showMessage = coreOut[1]; + coreOut[2] = defineMessage("hide", false, coreOutHide); + coreOut.hideMessage = coreOut[2]; + coreOut[3] = defineMessage("requestActivate", false, coreOutRequestActivate, null, + defineParams("returnCode")); + coreOut.requestActivateMessage = coreOut[3]; + coreOut[4] = defineMessage("requestDeactivate", false, coreOutRequestDeactivate, null, + defineParams("returnCode")); + coreOut.requestDeactivateMessage = coreOut[4]; + coreOut[5] = defineMessage("showNotification", false, coreOutShowNotification, + defineParams("message"), defineParams("returnCode")); + coreOut.showNotificationMessage = coreOut[5]; + coreOut[6] = defineMessage("placeComponent", false, coreOutPlaceComponent, + defineParams("componentID", "x", "y", "w", "h", "z-index", "transparency"), + defineParams("returnCode")); + coreOut.placeComponentMessage = coreOut[6]; + coreOut[7] = defineMessage("getAttention", false, coreOutGetAttention, + null, defineParams("returnCode")); + coreOut.getAttentionMessage = coreOut[7]; + coreOut[8] = defineMessage("installWidget", false, coreOutInstallWidget, + defineParams("url"), defineParams("returnCode")); + coreOut.installWidgetMessage = coreOut[8]; + coreOut[9] = defineMessage("migrateComponent", false, coreOutMigrateComponent, + defineParams("componentId", "targetCode"), defineParams("returnCode")); + coreOut.migrateComponentMessage = coreOut[9]; + coreOut[10] = defineMessage("requestMigrationTargets", false, coreOutRequestMigrationTargets, + null, defineParams("targetCodes", "targetNames", "targetDescriptions")); + coreOut.requestMigrationTargetsMessage = coreOut[10]; + coreOut[11] = defineMessage("activateTemporaryWidget", false, coreOutActivateTemporaryWidget, + defineParams("url"), defineParams("returnCode")); + coreOut.activateTemporaryWidget = coreOut[11]; + coreOut.type = "urn:mpeg:mpegu:schema:widgets:core:out:2010"; +} + +function coreOutRequestMigrationTargets(wid, args) { + WidgetManager.coreOutRequestMigrationTargets(wid, args); +} + +function coreOutSetSize(wid, args) { + WidgetManager.coreOutSetSize(wid, args); +} + +function coreOutShow(wid, args) { + WidgetManager.coreOutShow(wid, args); +} + +function coreOutHide(wid, args) { + WidgetManager.coreOutHide(wid, args); +} + +function coreOutRequestActivate(wid, args) { + WidgetManager.coreOutRequestActivate(wid, args); +} + +function coreOutRequestDeactivate(wid, args) { + WidgetManager.coreOutRequestDeactivate(wid, args); +} + +function coreOutShowNotification(wid, args) { + WidgetManager.coreOutShowNotification(wid, args); +} + +function coreOutPlaceComponent(wid, args) { + WidgetManager.coreOutPlaceComponent(wid, args); +} + +function coreOutGetAttention(wid, args) { + WidgetManager.coreOutGetAttention(wid, args); +} + +function coreOutInstallWidget(wid, args) { + WidgetManager.coreOutInstallWidget(wid, args); +} + +function coreOutActivateTemporaryWidget(wid, args) { + WidgetManager.coreOutActivateTemporaryWidget(wid, args); +} + +function coreOutMigrateComponent(wid, args) { + WidgetManager.coreOutMigrateComponent(wid, args); +} + +/* + Methods of binding and callback of core:* interfaces + */ +function wmjs_interface_invoke_callback_core(wid_src, ifce_dst, is_reply) { + log(l_inf, "wmjs_interface_invoke_callback_core '" + ifce_dst.type + "' - reply " + is_reply); + return function() { + var i, ai = 0, param_count, msgHandler, msg_src, msg_dst; + var args = new Array(); + msgHandler = arguments[0]; + /*get msg from source interface (this object)*/ + msg_src = this.get_message(msgHandler.msgName); + msg_dst = getMessage(ifce_dst, msgHandler.msgName); + //var argstring = ""; + //for (i = 0; i < msg_dst.num_params; i++) argstring += " "+getParam(msg_dst, i); + //log(l_inf, argstring); + //log(l_inf, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on core.' + msg_dst.name + " nbpar:"+msg_src.num_params); + param_count = msg_src.num_params; + for (i = 0; i < param_count; i++) { + var param = getInputParam(msg_dst, i); + if (param == null) continue; + args[ai] = arguments[ai+1]; + ai++; + } + log(l_inf, (is_reply ? 'invokeReply ' : 'invoke ') + msg_src.name + ' on core.' + msg_dst.name + " nb:"+ai); + // call the method that implements the core:* message + msg_dst.execute(wid_src, args); + }; +} + +// function invokeReply for a reply from within a coreOut message +function wmjs_core_out_invoke_reply() { + var i, ai, param_count, is_script, msg_src, msg_dst, wid_dst; + var args = new Array(); + is_script = 0; + msg_src = arguments[0]; + msg_dst = arguments[1]; + wid_dst = arguments[2]; + log(l_inf, 'coreOut/invokeReply ' + msg_src.name + ' on core.' + msg_dst.name + ' to ' +wid_dst.name+ " nb:"+ai); + if (msg_dst.has_script_input) is_script = 1; + param_count = msg_src.num_params; + ai = 3; + for (i = 0; i < param_count; i++) { + var param = msg_dst.get_param(i); + if (! param.is_input) continue; + if (is_script) { + args[ai - 3] = arguments[ai]; + } else { + wid_dst.set_input(param, arguments[ai]); + } + ai++; + } + if (msg_dst.has_input_action) { + wid_dst.call_input_action(msg_dst); + } else if (is_script) { + wid_dst.call_input_script(msg_dst, args); + } +} + +// get an interface by type in WidgetManager, since getInterfaceHandlersByType is not accessible +function getInterfaceByType(widget, type) { + for (var i = 0; i < widget.num_interfaces; i++) { + var ifce = widget.get_interface(i); + if (ifce.type == type) return ifce; + } + return null; +} + +function wmjs_bind_interface_to_core_service(wid, ifce) { + if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:in:2010") { + // core:in + return wmjs_bind_interface_to_core_service1(wid, ifce, coreIn); + } else if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:out:2010") { + // core:out + return wmjs_bind_interface_to_core_service1(wid, ifce, coreOut); + } + // not an interface to core services + return false; +} + +function wmjs_bind_interface_to_core_service1(wid, ifce, core) { + // loop on the messages to check if they match + log(l_inf, 'Bind interface to core service ' + wid.name + " " + ifce.type); + var set_bind = 0, nb_ok, j, k, a_msg; + for (j = 0; j < ifce.num_messages; j++) { + var msg = ifce.get_message(j); + // does the other interface have this message + a_msg = getMessage(core, msg.name); + if (!a_msg) { + // no, it does not have this message, so leave + log(l_inf, 'No core message for ' + msg.name); + continue; + } + // the messages have matching names, check direction + if (msg.is_input == a_msg.is_input) { + log(l_inf, 'core message for ' + msg.name + ' is not in direction ' + (msg.is_input ? 'output' : 'input')); + continue; + } + // the messages have matching names and directions, check params + if (msg.num_params != a_msg.num_params) { + log(l_war, 'core message ' + msg.name + ' does not have the same number of parameters ' + + msg.num_params + ' ' + a_msg.num_params); + var paramstring = ""; + for (k = 0; k < msg.num_params; k++) { + par = msg.get_param(k); + paramstring += " " + par.name; + } + log(l_deb, paramstring); + continue; + } + /*check all params*/ + nb_ok = 0; + for (k = 0; k < msg.num_params; k++) { + par = msg.get_param(k); + //log(l_inf, " "+par.name+" "+hasParam(a_msg, par.name)+" "+par.is_input+" "+paramDirection(a_msg, par.name)); + if (hasParam(a_msg, par.name) != null && par.is_input != paramDirection(a_msg, par.name)) nb_ok ++; + } + if (nb_ok != msg.num_params) { + log(l_war, 'core message ' + msg.name + ' does not have the same input/output parameters '+nb_ok+" "+msg.num_params); + continue; + } + set_bind ++; + // the messages match + log(l_inf, 'Binding ' + wid.name + '.' + msg.name + ' to core.' + a_msg.name); + /*OK let's bind this action: we only need to assign the output trigger, the input + action will be called from the other widget*/ + if (msg.has_output_trigger) { + wmjs_bind_output_trigger(wid, msg, wmjs_output_trigger_callback_core(msg, wid, a_msg), WidgetManager); + } + } + if (!set_bind) return false; + /*create callback for programmatic action triggers*/ + ifce.invoke = wmjs_interface_invoke_callback_core(wid, core, 0); + // ifce.invokeReply = wmjs_interface_invoke_callback_core(wid, core, 1); + wid.bind_interface(ifce, null, 'localhost'); + return true; +} + +function wmjs_output_trigger_callback_core(msg_out, wid_src, msg_in) { + log(l_deb, "wmjs_output_trigger_callback_core"); + return function() { + log(l_deb, "wmjs_output_trigger_callback_core/function '" + wid_src.name + "'"); + var param_count = msg_out.num_params; + var args = new Array(); + var ai = 0, i; + log(l_inf, 'Invoking Widget(' + wid_src.name + ').' + msg_out.name); + for (i = 0; i < param_count; i++) { + var param = msg_out.get_param(i); + if (param.is_input) continue; + args[ai] = wid_src.get_param_value(param); + ai++; + } + msg_in.execute(wid_src, args); + }; +} + + +// +// send a core:in message with no parameter +// +function wmjs_corein_message() { + if (arguments.length < 2) return; + var widget = arguments[0]; + var message = arguments[1]; + + for (var i=0; i<widget.num_interfaces; i++) { + var ifce = widget.get_interface(i); + if (ifce.type != 'urn:mpeg:mpegu:schema:widgets:core:in:2010') continue; + + for (var j=0; j<ifce.num_messages; j++) { + var msg = ifce.get_message(j); + if (msg.name == message) { + if (msg.has_script_input) { + var jsargs = new Array(); + /*for each input descibed in the manifest, get the input script value and stack it in the argument list*/ + for (var k=0; k<msg.num_params; k++) { + par = msg.get_param(k); + if (!par.is_input) continue; + for (var l=2; l<arguments.length; l+=2) { + if (arguments[l]==par.name) { + jsargs.push(arguments[l+1]); + break; + } + } + } + widget.call_input_script(msg, jsargs); + } else if (msg.has_input_action) { + /*for each input descibed in the manifest, set the widget input value*/ + for (var k=0; k<msg.num_params; k++) { + par = msg.get_param(k); + if (!par.is_input) continue; + for (var l=2; l<arguments.length; l+=2) { + if (arguments[l]==par.name) { + widget.set_input(par, arguments[l+1]); + break; + } + } + } + widget.call_input_action(msg); + } + } + } + } +} + +/* + End of implementation of core:in and core:out interfaces + */
View file
gpac-1.0.1.tar.gz/share/deprecated/mpegu-wm.bt
Changed
(renamed from share/gui/mpegu-wm.bt)
View file
gpac-1.0.1.tar.gz/share/deprecated/mpegu-wm.js
Added
@@ -0,0 +1,1723 @@ +//This software module was originally developed by Telecom Paris in the +//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard. +// +//This software module is an implementation of a part of one or +//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets +//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets +//(ISO/IEC 23007-1) free license to this software module or modifications +//thereof for use in hardware or software products claiming conformance to +//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software +//module in hardware or software products are advised that its use may +//infringe existing patents. +//The original developer of this software module and his/her company, the +//subsequent editors and their companies, and ISO/IEC have no liability +//for use of this software module or modifications thereof in an implementation. +//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming +//products. +//Telecom Paris retains full right to use the code for his/her own purpose, +//assign or donate the code to a third party and to inhibit third parties from +//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products. +// +//This copyright notice must be included in all copies or derivative works. +// +//Copyright (c) 2009. +// +///////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////// +// +// Authors: +// Jean Le Feuvre, (c) 2007-2010 Telecom Paris +// +///////////////////////////////////////////////////////////////////////////////// + +// 01122011 AMD1 startWidget implemented +// TODO AMD1 listWidgets getWidget requestCapabilitiesList + +//Initialize the main UI script +function initialize() { + //var icon; + var i, count, wid; + + scene.caption = 'MPEG-U @ Osmo4'; + + display_width = parseInt(scene.get_option('Widgets', 'LastWMWidth')); + display_height = parseInt(scene.get_option('Widgets', 'LastWMHeight')); + + if (display_width && display_height) { + scene.set_size(display_width, display_height); + } else { + display_width = scene.screen_width; + display_height = scene.screen_height; + } + + //request event listeners on the window - GPAC specific extensions !!! + root.addEventListener('resize', on_resize, 0); + root.addEventListener('zoom', on_zoom, 0); + root.addEventListener('scroll', on_scroll, 0); + + widget_default_size = 200; + scene_width = 0; + + wctl_iconsize = new SFVec2f(24, 24); + icon_size = 48; + dock_height = 48; + info_height = 32; + toggle_bar_height = 16; + screen_dpi = scene.get_horizontal_dpi(); + + widget_remote_candidate = null; + has_upnp = eval("(typeof(UPnP) != 'undefined');"); + if (has_upnp) { + UPnP.onMediaRendererAdd = onMediaRendererAdd; + UPnP.onMediaConnect = onMediaConnect; + UPnP.BindRenderer(); + upnp_renders = null; + } + + /*setup dock*/ + widget_screen_visible = false; + + /*widget subtree*/ + widget_display = new SFNode('Transform2D'); + ui_root.children[0] = widget_display; + + /*widget manager page*/ + widget_screen = new SFNode('Layer2D'); + ui_root.children[1] = widget_screen; + + /*all other UI elements subtree*/ + dlg_display = new SFNode('Transform2D'); + ui_root.children[2] = dlg_display; + + infobar = text_label('', 'MIDDLE'); + ui_root.children[3] = infobar; + + /*our dock*/ + dock = new SFNode('Transform2D'); + ui_root.children[4] = dock; + + /*init the widget manager*/ + Browser.loadScript('mpegu-core.js', true); + log_level = l_inf; + widget_manager_init(); + + WidgetManager.on_widget_remove = widget_remove; + WidgetManager.on_widget_add = widget_insert; + WidgetManager.coreOutSetSize = widget_request_size; + WidgetManager.coreOutShow = widget_request_show; + WidgetManager.coreOutHide = widget_request_hide; + WidgetManager.coreOutRequestActivate = widget_request_activate; + WidgetManager.coreOutRequestDeactivate = widget_request_deactivate; + WidgetManager.coreOutShowNotification = widget_request_notification; + WidgetManager.coreOutPlaceComponent = widget_place_component; + WidgetManager.coreOutGetAttention = widget_request_attention; + WidgetManager.coreOutInstallWidget = widget_install_widget; + WidgetManager.coreOutMigrateComponent = widget_migrate_component; + WidgetManager.coreOutRequestMigrationTargets = widget_request_migration_targets; + + nb_widgets_on_screen = 0; + first_visible_widget = 0; + setup_icons(); + + /*restore our widgets*/ + widgets_init(); + + //let's do the layout + layout(); +} + +function new_timeout(time) +{ + var obj = new SFNode('TimeSensor'); + + obj.cycleInterval = time; + obj.start = function(when) { + var t = this.getTime(); + this.startTime = when + this.getTime(); + }; + obj.stop = function(when) { + this.stopTime = when + this.getTime(); + }; + obj.on_event = null; + obj.event = function(val) { + if (this.on_event) this.on_event(val); + }; + Browser.addRoute(obj, 'fraction_changed', obj, obj.event); + return obj; +} + +function rectangle() +{ + var obj = new SFNode('Shape'); + + obj.appearance = new SFNode('Appearance'); + obj.appearance.material = new SFNode('Material2D'); + obj.appearance.material.filled = TRUE; + obj.appearance.material.emissiveColor = new SFColor(0.7, 0.7, 0.8); + obj.appearance.material.lineProps = new SFNode('LineProperties'); + obj.appearance.material.lineProps.width = 2; + obj.appearance.material.lineProps.lineColor = new SFColor(0, 0, 0); + + obj.geometry = new SFNode('Curve2D'); + obj.geometry.point = new SFNode('Coordinate2D'); + temp = obj.geometry.type; + temp[0] = 7; + temp[1] = 1; + temp[2] = 7; + temp[3] = 1; + temp[4] = 7; + temp[5] = 1; + temp[6] = 7; + temp[7] = 6;/*close*/ + + obj.set_size = function(w, h) { + var hw, hh, rx, ry; + var temp; + hw = w/2; + hh = h/2; + + /*compute default rx/ry*/ + ry = rx = 10; + if ( (2*rx>=hw) || (2*ry>=hh)) rx = ry = 6; + + temp = this.geometry.point.point; + temp[0] = new SFVec2f(hw-rx, hh); + temp[1] = new SFVec2f(hw, hh);/*bezier ctrl point*/ + temp[2] = new SFVec2f(hw, hh-ry); + temp[3] = new SFVec2f(hw, -hh+ry); + temp[4] = new SFVec2f(hw, -hh);/*bezier control point*/ + temp[5] = new SFVec2f(hw-rx, -hh); + temp[6] = new SFVec2f(-hw+rx, -hh); + temp[7] = new SFVec2f(-hw, -hh);/*bezier control point*/ + temp[8] = new SFVec2f(-hw, -hh+ry); + temp[9] = new SFVec2f(-hw, hh-ry); + temp[10] = new SFVec2f(-hw, hh);/*bezier control point*/ + temp[11] = new SFVec2f(-hw+rx, hh); + }; + obj.set_color = function(r, g, b) { + this.appearance.material.emissiveColor.r = r; + this.appearance.material.emissiveColor.g = g; + this.appearance.material.emissiveColor.b = b; + }; + return obj; +} + +function icon_button(url, label, no_back) +{ + var obj = new SFNode('Transform2D'); + obj.children[0] = new SFNode('Transform2D'); + obj.children[0].scale.x = 0; + obj.children[0].children[0] = rectangle(); + + obj.children[1] = new SFNode('Layer2D'); + obj.children[1].size.x = icon_size; + obj.children[1].size.y = icon_size; + obj.children[1].children[0] = new SFNode('Inline'); + obj.children[1].children[0].url[0] = url; + + obj.touch = new SFNode('TouchSensor'); + obj.children[1].children[1] = obj.touch; + obj.button_click = NULL; + obj.down = false; + obj.over = false; + obj.on_active = function(value) { + if (value) { + this.down = true; + } else { + if (this.down && this.over && this.button_click) this.button_click(); + this.down = false; + } + }; + obj.button_over = on_icon_over; + obj.on_over = function(value) { + this.over = value; + if (!no_back) + this.children[0].scale.x = value ? 1 : 0; + if (this.button_over) this.button_over(value); + }; + Browser.addRoute(obj.touch, 'isOver', obj, obj.on_over); + Browser.addRoute(obj.touch, 'isActive', obj, obj.on_active); + obj.label = label; + obj.hide = function() { this.scale.x = this.scale.y = 0;}; + obj.show = function() { this.scale.x = this.scale.y = 1;}; + obj.set_size = function(x, y) { + this.children[0].children[0].set_size(x, y); + this.children[1].size.x = x; + this.children[1].size.y = y; + }; + return obj; +} + +function text_label(label, justify) +{ + var obj = new SFNode('Transform2D'); + obj.children[0] = new SFNode('Shape'); + obj.children[0].appearance = new SFNode('Appearance'); + obj.children[0].appearance.material = new SFNode('Material2D'); + obj.children[0].appearance.material.filled = TRUE; + obj.children[0].appearance.material.emissiveColor = new SFColor(0, 0, 0); + obj.children[0].geometry = new SFNode('Text'); + obj.children[0].geometry.string[0] = label; + obj.children[0].geometry.fontStyle = new SFNode('FontStyle'); + obj.children[0].geometry.fontStyle.justify[0] = justify; + obj.children[0].geometry.fontStyle.justify[1] = 'MIDDLE'; + obj.children[0].geometry.fontStyle.size = 20; + obj.set_label = function(value) { + this.children[0].geometry.string[0] = value; + }; + return obj; +} + + +function text_rect(label) +{ + var obj = new SFNode('Transform2D'); + obj.children[0] = rectangle(); + obj.children[0].set_color(0.7, 0.7, 0.8); + + obj.children[1] = new SFNode('Shape'); + obj.children[1].appearance = new SFNode('Appearance'); + obj.children[1].appearance.material = new SFNode('Material2D'); + obj.children[1].appearance.material.filled = TRUE; + obj.children[1].appearance.material.emissiveColor = new SFColor(0, 0, 0); + obj.children[1].geometry = new SFNode('Text'); + obj.children[1].geometry.string[0] = label; + obj.children[1].geometry.fontStyle = new SFNode('FontStyle'); + obj.children[1].geometry.fontStyle.justify[0] = 'MIDDLE'; + obj.children[1].geometry.fontStyle.justify[1] = 'MIDDLE'; + obj.children[1].geometry.fontStyle.size = 20; + obj.children[2] = new SFNode('TouchSensor'); + + obj.set_size = function(w, h) { + this.children[0].set_size(w, h); + }; + + + obj.over = false; + obj.on_over = function(value) { + this.children[0].set_color(0.7, value ? 0.5 : 0.7, 0.8); + this.over = value; + }; + Browser.addRoute(obj.children[2], 'isOver', obj, obj.on_over); + + obj.down = false; + obj.button_click = null; + obj.on_active = function(value) { + if (value) { + this.down = true; + } else { + if (this.down && this.over && this.button_click) this.button_click(); + this.down = false; + } + }; + Browser.addRoute(obj.children[2], 'isActive', obj, obj.on_active); + + return obj; +} + +function new_widget_control(widget) +{ + var obj = new SFNode('Transform2D'); + + obj.children[0] = new SFNode('Transform2D'); + + obj.children[0].children[0] = rectangle(); + + obj.children[0].children[1] = new SFNode('TouchSensor'); + + + obj.component_bound=false; + obj.show_ctrl = true; + obj.onClick = function(value) { + if (!value) return; + this.show_ctrl = !this.show_ctrl; + if (this.show_ctrl) { + var i, comps, idx; + this.children[0].children[0].appearance.material.transparency = 0; + this.children[1].scale.x = 1; + this.children[3].scale.x = 1; + + for (i=0; i<widget_display.children.length; i++) { + if (widget_display.children[i]==this) continue; + if (widget_display.children[i].show_ctrl) { + widget_display.children[i].onClick(true); + } + } + //widget is a component, do not push on top but hide some controls + if (widget.is_component) { + if (this.component_bound) { + this.children[1].children[0].hide(); //close + this.children[1].children[1].hide(); //remove + this.children[1].children[4].hide(); //resize + } + return; + } + //otherwise push widget on top + idx=0; + widget_display.removeChildren[idx++] = this; + widget_display.addChildren[idx++] = this; + //and push components + comps = widget.components; + for (i=0; i<comps.length; i++) { + if (comps[i].widget_control.component_bound) { + widget_display.removeChildren[idx++] = comps[i].widget_control; + widget_display.addChildren[idx++] = comps[i].widget_control; + } + } + + } else { + this.children[0].children[0].appearance.material.transparency = 1; + this.children[1].scale.x = 0; + this.children[3].scale.x = 0; + } + }; + Browser.addRoute(obj.children[0].children[1], 'isActive', obj, obj.onClick); + + obj.children[1] = new SFNode('Transform2D'); + obj.children[1].children[0] = icon_button('icons/process-stop.svg', 'Close', 0); + obj.children[1].children[0].button_click = function() { + if (widget.discardable) widget_remove(widget); + else widget_close(widget, 0); + }; + + obj.children[1].children[1] = icon_button('icons/user-trash.svg', 'Uninstall', 0); + obj.children[1].children[1].button_click = function() { widget_remove(widget); } + + obj.children[1].children[2] = icon_button('icons/applications-internet.svg', 'Push to remote display', 0); + obj.children[1].children[2].button_click = function() { + if (has_upnp && UPnP.MediaRenderersCount) { + widget_remote_candidate = widget; + on_upnpopen(); + } + }; + + obj.children[1].children[3] = icon_button('icons/dialog-information.svg', 'Widget Information', 0); + obj.children[1].children[3].button_click = function() { + display_widget_info(widget); + }; + + obj.children[1].children[4] = icon_button('icons/media-record.svg', 'Resize', 1); + obj.children[1].children[4].children[1].children[2] = new SFNode('PlaneSensor2D'); + obj.children[1].children[4].children[1].children[2].maxPosition = new SFVec2f(-1, -1); + + obj.prev_x=0; + obj.prev_y=0; + obj.onSize = function(value) { + if (widget.width + 2*(value.x - this.prev_x)<0) return; + if (widget.height + 2*(this.prev_y-value.y)<0) return; + + widget.width += 2*(value.x - this.prev_x); + this.prev_x = value.x; + widget.height += 2*(this.prev_y - value.y); + this.prev_y = value.y; + this.set_size(widget.width, widget.height); + }; + Browser.addRoute(obj.children[1].children[4].children[1].children[2], 'translation_changed', obj, obj.onSize); + + obj.children[2] = new SFNode('Layer2D'); + obj.inline = new SFNode('Inline'); + obj.children[2].children[0] = obj.inline; + + + obj.children[3] = new SFNode('Transform2D'); + obj.children[3].children[0] = new SFNode('Shape'); + obj.children[3].children[0].appearance = new SFNode('Appearance'); + obj.children[3].children[0].appearance.material = new SFNode('Material2D'); + obj.children[3].children[0].appearance.material.filled = TRUE; + obj.children[3].children[0].appearance.material.transparency = 0.5; + obj.children[3].children[0].appearance.material.emissiveColor = new SFColor(0.6, 0.6, 0.6); + obj.children[3].children[0].geometry = new SFNode('Rectangle'); + obj.children[3].children[0].geometry.size = new SFVec2f(50, 50); + obj.children[3].children[1] = new SFNode('PlaneSensor2D'); + obj.children[3].children[1].maxPosition = new SFVec2f(-1, -1); + obj.children[3].children[1].offset = new SFVec2f(widget.x, widget.y); + obj.onMove = function(value) { + if (this.maximized) return; + this.translation = value; + widget.x = value.x; + widget.y = value.y; + this.refresh_layout(false, null); + }; + Browser.addRoute(obj.children[3].children[1], 'translation_changed', obj, obj.onMove); + + obj.children[3].children[2] = new SFNode('TouchSensor'); + obj.last_ts = 0; + obj.onMaximize = function(value, timestamp) { + if (!value) return; + if (timestamp - this.last_ts < 0.5) { + if (this.maximized) { + this.maximized = false; + this.translation.x = widget.x; + this.translation.y = widget.y; + this.set_size(this.prev_width, this.prev_height); + } else { + this.maximized = true; + this.prev_width = widget.width; + this.prev_height = widget.height; + this.translation.x = 0; + this.translation.y = -info_height; + this.set_size(display_width, display_height - 2*info_height); + } + } + this.last_ts = timestamp; + }; + Browser.addRoute(obj.children[3].children[2], 'isActive', obj, obj.onMaximize); + + obj.set_size = function(w, h) { + var i, x, s; + s = 24; + this.children[2].size.x = w; + this.children[2].size.y = h; + + this.children[1].children[0].translation.y = this.children[1].children[1].translation.y = this.children[1].children[2].translation.y = this.children[1].children[3].translation.y = this.children[1].children[4].translation.y = h/2 + s/2; + + this.children[0].children[0].set_size(w+s, h+s); + this.children[3].children[0].geometry.size.x = w; + this.children[3].children[0].geometry.size.y = h; + + this.children[1].children[0].set_size(s, s); + this.children[1].children[1].set_size(s, s); + this.children[1].children[2].set_size(s, s); + this.children[1].children[3].set_size(s, s); + this.children[1].children[4].set_size(s, s); + this.children[1].children[0].translation.x = -w/2; + this.children[1].children[1].translation.x = -w/4; + this.children[1].children[2].translation.x = 0; + this.children[1].children[3].translation.x = w/4; + this.children[1].children[4].translation.x = w/2; + + //set widget input params + widget.width = w; + widget.height = h; + widget.set_input('width', w); + widget.set_input('height', h); + this.refresh_layout(true, null); + //call core:in + WidgetManager.corein_message(widget, 'setSize', 'width', w, 'height', w, 'dpi', screen_dpi); + }; + obj.refresh_layout = function(send_resize, comp_target) { + var i; + var x, y, w, h, scale_x, scale_y; + var comps; + + /*local to subscene transformation not known*/ + if (!this.sub_w) return; + if (!this.sub_h) return; + + comps = widget.components; + for (i=0; i<comps.length; i++) { + var comp = comps[i]; + if (!comp.widget_control.component_bound) continue; + + //compute scale from Widget Manager coord system to widget internal coordinate system + scale_x = this.sub_vp_w / this.sub_w; + scale_y = this.sub_vp_h / this.sub_h; + + w = comp.widget_control.place_w * scale_x; + h = comp.widget_control.place_h * scale_y; + + x = this.translation.x - widget.width/2 + this.sub_vp_x + comp.widget_control.place_x * scale_x + w/2; + comp.widget_control.translation.x = x; + + y = widget.height/2 + this.translation.y - h/2 - this.sub_vp_y - comp.widget_control.place_y * scale_y; + comp.widget_control.translation.y = y; + + if (send_resize || (comp_target==comp)) + comp.widget_control.set_size(w, h); + } + }; + + obj.hide = function() { + this.scale.x = 0; + WidgetManager.corein_message(widget, 'hide'); + }; + obj.show = function() { + this.scale.x = 1; + WidgetManager.corein_message(widget, 'show'); + }; + + obj.show_remote = function () { + if (WidgetManager.upnp && UPnP.MediaRenderersCount) { + this.children[1].children[2].show(); + } else { + this.children[1].children[2].hide(); + } + }; + obj.show_remove = function(show) { + if (show) this.children[1].children[1].show(); + else this.children[1].children[1].hide(); + }; + + obj.flash = function() { + var time = new_timeout(0.25); + time.loop = true; + time.ctrl = this; + time.on_event = function(val) { + var scale = (val<0.5) ? 1+val : 2-val; + this.ctrl.scale.x = this.ctrl.scale.y = scale; + }; + time.stop(1); + time.start(0); + }; + obj.maximized = false; + obj.show_remote(); + obj.onClick(true); + return obj; +} + + + +function on_icon_over(value) +{ + infobar.set_label(value ? this.label : ''); +} + +function display_widget_info(wid) +{ + var info_dlg = new SFNode('Transform2D'); + var i, j, k, info; + var y, txt, pref; + + infobar.set_label('Widget ' + wid.name + ' Information'); + + info = text_rect('Close'); + info_dlg.children[0] = info; + info.button_click = function() { + dlg_display.children.length = 0; + widget_display.scale.x = 1; + infobar.set_label(''); + layout(); + }; + + info = text_rect('Widget Metadata'); + info_dlg.children[info_dlg.children.length] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + info.children[i++] = text_label('id: ' + wid.identifier + ' - shortname: '+wid.shortName + ' - name: '+wid.name, 'BEGIN'); + info.children[i++] = text_label('version: '+wid.version, 'BEGIN'); + info.children[i++] = text_label('content type: ' + wid.mainMimeType + ' - content encoding: '+wid.mainEncoding, 'BEGIN'); + info.children[i++] = text_label('default size: Width = ' + wid.defaultWidth + ' Height = '+wid.defaultHeight, 'BEGIN'); + info.children[i++] = text_label('license: '+wid.license, 'BEGIN'); + info.children[i++] = text_label('license ref: '+wid.licenseHref, 'BEGIN'); + info.children[i++] = text_label('description: '+wid.description, 'BEGIN'); + info.children[i++] = text_label('author name: '+wid.authorName + ' (mail: '+wid.authorEmail+')', 'BEGIN'); + info.children[i++] = text_label('author href: '+wid.authorHref, 'BEGIN'); + info.children[i++] = text_label('view modes: '+wid.viewmodes, 'BEGIN'); + info.children[i++] = text_label('UUID: '+wid.uuid, 'BEGIN'); + info.children[i++] = text_label('Discardable: '+wid.discardable, 'BEGIN'); + info.children[i++] = text_label('Muliple Instances: '+wid.discardable, 'BEGIN'); + var icons = wid.icons; + for (j=0; j<icons.length; j++) { + info.children[i++] = text_label('icon #'+(j+1)+': ' + icons[j].src, 'BEGIN'); + } + + info = text_rect('Widget Manager Info'); + info_dlg.children[info_dlg.children.length] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + info.children[i++] = text_label('nb instances: '+wid.num_instances + ' nb components: '+wid.num_components, 'BEGIN' ); + info.children[i++] = text_label('Permanently installed: '+wid.permanent + ' - is component: '+wid.is_component, 'BEGIN' ); + if (wid.is_component) { + info.children[i++] = text_label('parent widget name' + wid.parent.name, 'BEGIN'); + } + if (wid.originating_device_ip) { + info.children[i++] = text_label('Widget was pushed from device IP '+wid.originating_device_ip, 'BEGIN' ); + } + info.children[i++] = text_label('Section name in GPAC config file: '+wid.section, 'BEGIN' ); + info.children[i++] = text_label('UA Locale: ' + scene.get_option('core', 'lang'), 'BEGIN'); + info.children[i++] = text_label('widget src: ' + wid.url , 'BEGIN'); + info.children[i++] = text_label('config src: ' + wid.manifest , 'BEGIN'); + info.children[i++] = text_label('content src : '+wid.localizedSrc, 'BEGIN' ); + + pref = wid.features; + info = text_rect('Features (' + pref.length + ')' ); + info_dlg.children[info_dlg.children.length] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + for (j=0; j<pref.length; j++) { + info.children[i++] = text_label('Feature #'+(j+1)+' name=\''+pref[j].name+'\' required=\''+pref[j].required+'\'', 'BEGIN'); + } + + + pref = wid.preferences; + info = text_rect('Preferences ('+pref.length+')'); + info_dlg.children[info_dlg.children.length] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + for (j=0; j<pref.length; j++) { + var val = pref[j].value; + if (val == '') val = scene.get_option(wid.section, pref[j].name); + info.children[i++] = text_label('Preference #'+(j+1)+' name=\''+pref[j].name+'\' value=\''+val+'\' readOnly=\''+pref[j].readonly +'\'', 'BEGIN'); + } + + info = text_rect('Migration Context', 'BEGIN'); + info_dlg.children[info_dlg.children.length] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + txt=wid.get_context(); + while (1) { + var idx = txt.indexOf('\n', 0); + if (idx>0) { + info.children[i++] = text_label(txt.substring(0, idx), 'BEGIN'); + txt = txt.substring(idx+1, txt.length); + } else { + info.children[i++] = text_label(txt, 'BEGIN'); + break; + } + } + + info_dlg.ifce_idx = info_dlg.children.length; + info = text_rect('Interfaces (count: ' + wid.num_interfaces + ' - bound: ' + wid.num_bound_interfaces+')', 'BEGIN'); + info_dlg.children[info_dlg.ifce_idx] = info; + info.visible = false; + info.button_click = function() { + this.visible = !this.visible; + layout(); + }; + i=3; + for (j=0; j<wid.num_interfaces; j++) { + var idx; + var ifce = wid.get_interface(j); + var item = text_rect('Interface #' + (j+1) + ' type: '+ifce.type); + info.children[i++] = item; + item.visible = false; + item.button_click = function() { + this.visible = !this.visible; + layout(); + }; + idx=3; + item.children[idx++] = text_label('Multiple Binding: '+ifce.multipleBinding + ' - Service provider: '+ ifce.serviceProvider + ' - bound: ' + wid.is_interface_bound(ifce) , 'BEGIN'); + for (k=0; k<ifce.num_messages; k++) { + var string, l; + var msg = ifce.get_message(k); + string = ' Message #'+ (k+1) + ': ' + msg.name + '('; + for (l=0; l<msg.num_params; l++) { + par = msg.get_param(l); + string += (par.is_input ? 'in' : 'out') + ':' +par.name + ' '; + } + string += ')'; + item.children[idx++] = text_label(string, 'BEGIN'); + } + } + + info_dlg.set_size = function(w, h) { + var i, j, y, dy; + y = h/2 - 20; + + for (i=0; i<this.children.length; i++) { + var item = this.children[i]; + item.translation.x = 0; + item.translation.y = y; + item.set_size(w, 20); + y -= 20; + if (!i) continue; + + dy = 0; + for (j=3; j<item.children.length; j++) { + if (item.visible) { + item.children[j].scale.x = 1; + dy -= 20; + item.children[j].translation.y = dy; + if (i<this.ifce_idx) { + item.children[j].translation.x = -w/2+10; + } else { + item.children[j].set_size(w-20, 20); + var ddy=0; + var k, sitem; + sitem = item.children[j]; + for (k=3; k<sitem.children.length; k++) { + if (item.children[j].visible) { + sitem.children[k].scale.x = 1; + sitem.children[k].translation.x = -w/2+10; + ddy -= 20; + sitem.children[k].translation.y = ddy; + } else { + sitem.children[k].scale.x = 0; + } + } + dy+=ddy; + } + } else { + item.children[j].scale.x = 0; + } + } + y += dy; + } + }; + + dlg_display.children[0] = info_dlg; + widget_display.scale.x = 0; + layout(); +} + + +function widget_insert(widget) +{ + /*insert the widget icon*/ + if (widget.permanent && !widget.is_component) + insert_widget_icon(widget, 0); + + /*and load the widget - comment this line to disable auto load of widget*/ + widget_launch(widget); +} + +function setup_icons() +{ + var icon; + + //Widgets Icon + icon = icon_button('icons/applications-system.svg', 'Available Widgets', 0); + icon.button_click = function () { + widget_screen_visible = !widget_screen_visible; + layout(); + }; + dock.children[0] = icon; + + //Get Widget Icon + icon = icon_button('icons/document-save.svg', 'Get Widget', 0); + icon.button_click = function () { + widget_get(); + }; + dock.children[1] = icon; + + //Widgets add Icon + icon = icon_button('icons/list-add.svg', 'Add Widgets', 0); + icon.button_click = function () { + widget_browse(); + }; + dock.children[2] = icon; + + + icon = icon_button('icons/user-trash.svg', 'Remove all widgets', 0); + icon.button_click = function () { + while (1) { + var wid = WidgetManager.get(0); + if (wid==null) break; + widget_close(wid, 1); + } + widget_screen.children.length = 0; + layout(); + }; + dock.children[3] = icon; + + //exit Icon + icon = icon_button('icons/emblem-unreadable.svg', 'Exit', 0); + icon.button_click = function() { scene.exit(); }; + dock.children[4] = icon; +} + + + +/*dock layout*/ +function dock_layout() { + var i; + + dock.translation.y = (dock_height - display_height)/2; + infobar.translation.y = display_height/2 - info_height/2; + + num_in_dock = dock.children.length; + tot_len = num_in_dock*icon_size; + + if (tot_len>display_width) { + start_x = (icon_size-display_width)/2; + } else { + start_x = (icon_size-tot_len)/2; + } + /*translate / size all items in the dock*/ + for (i=0;i<num_in_dock; i++) { + dock.children[i].set_size(icon_size, icon_size); + dock.children[i].translation.x = start_x + i*icon_size; + } +} + +function widget_screen_layout(dir) +{ + var count, i, start_x, start_y, spread_x, nb_wid_h, nb_wid_v, nb_wid; + + if (!widget_screen_visible) { + widget_screen.size.x = 0; + widget_screen.size.y = 0; + return; + } + + widget_screen.size.x = display_width; + widget_screen.size.y = display_height; + + start_x = (icon_size/2-display_width)/2; + start_y = (display_height-icon_size/2)/2 - info_height; + start_x = (icon_size-display_width)/2; + start_y = (display_height-icon_size)/2 - icon_size/2 - info_height; + + count = widget_screen.children.length; + if (first_visible_widget<0) first_visible_widget=0; + + for (i=0; i<count; i++) { + var wid = widget_screen.children[i]; + wid.hide(); + } + + nb_wid_h = Math.floor(display_width / icon_size); + if (!nb_wid_h) nb_wid_h=1; + + nb_wid_v = Math.floor((display_height-dock_height-icon_size) / icon_size); + if (!nb_wid_v) nb_wid_v=1; + + spread_x = (display_width / nb_wid_h) - icon_size; + start_x += spread_x/2; + + nb_wid = (nb_wid_h*nb_wid_v); + if (dir<0) { + first_visible_widget -= nb_wid; + if (first_visible_widget < 0) first_visible_widget = 0; + } + else if (dir>0) { + first_visible_widget += nb_wid; + } + + for (i=0; i<count; i++) { + var wid; + if (i +first_visible_widget >= count) { + break; + } + wid = widget_screen.children[i +first_visible_widget]; + wid.show(); + wid.set_size(icon_size, icon_size); + wid.translation.x = start_x; + wid.translation.y = start_y; + start_x += icon_size + spread_x; + if (start_x + icon_size / 2 >= display_width/2) { + start_x = (icon_size-display_width)/2 + spread_x/2; + start_y -= icon_size; + } + nb_widgets_on_screen = i+1; + if (start_y - icon_size < (dock_height-display_height)/2) { + i++; + break; + } + } +} + +//performs layout on all contents +function layout() { + var i, list, start_x; + + scene.set_option('Widgets', 'LastWMWidth', '' + display_width); + scene.set_option('Widgets', 'LastWMHeight', '' + display_height); + + + if (WidgetManager.num_widgets) { + dock.children[0].show(); + } else { + dock.children[0].hide(); + } + if (dlg_display.children.length) { + widget_display.scale.x = 0; + widget_screen_visible = false; + } + //layout all icons in the dock + dock_layout(); + widget_screen_layout(0); + + if (dlg_display.children.length) { + list = dlg_display.children; + for (i=0; i<list.length; i++) { + var dlg = list[i]; + if (typeof (dlg.set_size) != 'undefined') dlg.set_size(display_width, display_height-icon_size-info_height); + dlg.translation.y = (icon_size-info_height)/2; + } + } + else if (widget_screen_visible) { + widget_display.scale.x = 0; + } else { + widget_display.scale.x = 1; + list = widget_display.children; + for (i=0; i<list.length; i++) { + var widctrl = list[i]; + if (widctrl.maximized) { + widctrl.translation.y = - info_height; + widctrl.set_size(display_width, display_height - 2*info_height); + } + } + } +} + +//resize event callback +function on_resize(evt) { + display_width = evt.width; + display_height = evt.height; + layout(); +} +//zoom event callback +function on_zoom(evt) { + display_width = evt.width; + display_height = evt.height; + layout(); +} +//scroll event callback +function on_scroll(evt) { + layout(); +} + +//starts a widget +function on_widget_launch() { + if (this.widget.visible) { + var awid; + if (!this.widget.multipleInstances) return; + awid = WidgetManager.open(this.widget.manifest, null); + widget_launch(awid); + } else { + widget_launch(this.widget); + } +} + +function widget_get_icon(widget) +{ + var icon = 'icons/process-stop.svg'; + var preferredIconType = '.svg'; + for (var i = 0; i < widget.icons.length; i++) { + icon = widget.icons[i].relocated_src; + if (widget.icons[i].relocated_src.indexOf(preferredIconType) > 0) { + break; + } + } + return icon; +} + +//initialize GPAC widget manager and load all widgets +function widgets_init() { + + count = WidgetManager.num_widgets; + for (i=0; i<count; i++) { + wid = WidgetManager.get(i); + if (wid == null) continue; + wid.device = null; + wid.device_ip = null; + if (wid.in_panel == true) { + icon = icon_button(widget_get_icon(wid), wid.name, 0); + icon.tooltip = wid.name; + icon.widget = wid; + icon.button_click = on_widget_launch; + + wid.icon_dock = icon; + widget_screen.children[widget_screen.children.length] = wid.icon_dock; + } + if (wid.visible) { + widget_launch(wid); + } + } +} + +function on_widget_size(value) { + //remember variables + this.width = value.x; + this.height = value.y; + //and set widget input params + this.set_input('width', value.x); + this.set_input('height', value.y); +} + +function on_widget_move(value) { + this.x = value.x; + this.y = value.y; +} + +//widget close function +function widget_close(widget, force_remove) +{ + var is_comp = widget.is_component; + if (widget.visible) { + widget.visible = false; + WidgetManager.corein_message(widget, 'hide'); + WidgetManager.corein_message(widget, 'deactivate'); + widget.deactivate(); + widget.scene_container.removeChildren[0] = widget.widget_control; + /*force disconnect of main resource - we do this because we are not sure when the widget_control will be destroyed due to JS GC*/ + widget.widget_control.inline.url.length = 0; + } + if (!is_comp && (!widget.permanent || force_remove)) { + WidgetManager.unload(widget, false); + } +} + +function on_widget_close(value) { + widget_close(this, 0); +} + +//widget remove function (close and unregister) +function widget_remove(wid) { + if (typeof(wid.icon_dock) != 'undefined') + widget_screen.removeChildren[0] = wid.icon_dock; + widget_close(wid, 0); + layout(); +} + +function on_widget_control(value) +{ + var i, count; + if (!value) return; + count = this.scene_container.children.length; + for (i=0; i<count; i++) { + if (this.scene_container.children[i] == this.widget_control) { + this.scene_container.removeChildren[0] = this.widget_control; + this.scene_container.children[this.scene_container.children.length] = this.widget_control; + return; + } + } +} + +//widget launcher function +function widget_launch(wid) { + var widg_ctrl; + + //assign default size to the widget + if (wid.width == undefined) { + wid.width = wid.defaultWidth; + if (wid.width == 0) wid.width = widget_default_size; + } + if (wid.height == undefined) { + wid.height = wid.defaultHeight; + if (wid.height == 0) wid.height = widget_default_size; + } + if (wid.x== undefined) wid.x = 0; + if (wid.y== undefined) wid.y = 0; + + widg_ctrl = new_widget_control(wid); + widg_ctrl.component_bound = false; + + wid.visible = true; + + widg_ctrl.set_size(wid.width, wid.height); + widg_ctrl.translation.x = wid.x; + widg_ctrl.translation.y = wid.y; + + wid.widget_control = widg_ctrl; + wid.scene_container = widget_display; + + widg_ctrl.show_remove( (!wid.discardable && wid.icon_dock) ? 1 : 0); + + widg_ctrl.sub_width = 0; + widg_ctrl.sub_height = 0; + widg_ctrl.sub_x = 0; + widg_ctrl.sub_y = 0; + widg_ctrl.sub_vp_w = 0; + widg_ctrl.sub_vp_h = 0; + + widg_ctrl.inline.addEventListener('gpac_vp_changed', + function(evt) { + widg_ctrl.sub_vp_w = evt.width; + widg_ctrl.sub_vp_h = evt.height; + widg_ctrl.sub_vp_x = evt.offset_x; + widg_ctrl.sub_vp_y = evt.offset_y; + widg_ctrl.sub_w = evt.vp_width; + widg_ctrl.sub_h = evt.vp_height; + widg_ctrl.refresh_layout(true, null); + }, + 0); + + /*this will setup the scene graph for the widget in order to filter input and output communication pins*/ + wid.activate(widg_ctrl.inline); + + widg_ctrl.inline.url[0] = wid.main; + widget_display.addChildren[0] = widg_ctrl; + + /*send notifications once the widget scene is loaded*/ + wid.on_load = function () { + WidgetManager.corein_message(this, 'activate'); + WidgetManager.corein_message(this, 'show'); + WidgetManager.corein_message(this, 'setSize', 'width', 50, 'height', 50, 'dpi', 96); + }; + + if (widget_screen_visible) { + widget_screen_visible = 0; + layout(); + } + // + if (log_level > l_inf) { + var i = 0; + alert(">>>>>>>>>>>>> "+wid.name+" interfaces:"); + for (;i < wid.num_interfaces; i++) { + alert(""+wid.get_interface(i).type); + } + } + // +} + + +//core out install widget implementation JCD +function widget_install_widget(widget, args) +{ + var uri = args[0], j; + var count = WidgetManager.num_widgets; + for (j=0; j<count; j++) { + var wid = WidgetManager.get(j); + if (wid.url==uri) break; + } + if (j==count) { + new_wid = WidgetManager.open(uri, null); + if (new_wid!=null) { + insert_widget_icon(new_wid, 1); + } + } +} + +//core out migrate component implementation JCD +function widget_migrate_component(widget, args) +{ + if (has_upnp && UPnP.MediaRenderersCount) { + widget_remote_candidate = widget.get_component(args[0]); + if (widget_remote_candidate==null) { + log(l_err, 'Component '+args[0]+' cannot be found in widget '+widget.name); + return; + } + if (args.length > 1 && args[1] != null) { + var render = WidgetManager.MPEGUStandardServiceProviders[parseInt(args[1])]; + WidgetManager.migrate_widget(render, widget_remote_candidate); + widget_close(widget_remote_candidate, 0); + widget_remote_candidate = null; + } else { + on_upnpopen(); + } + } +} + +// core out request migration targets JCD +function widget_request_migration_targets(wid, args) +{ + var count = WidgetManager.MPEGUStandardServiceProviders.length, + codes = new Array(), names = new Array(), descriptions = new Array(), i; + for (i = 0; i < count; i++) { + var render = WidgetManager.MPEGUStandardServiceProviders[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); + } + +} + +function widget_request_size(widget, args) +{ + if (args.length==2) { + w = (typeof args[0] == 'string') ? parseInt(args[0]) : args[0]; + h = (typeof args[1] == 'string') ? parseInt(args[1]) : args[1]; + widget.widget_control.set_size(w, h); + } +} + +function widget_request_show(widget, args) +{ + widget.widget_control.show(); +} + +function widget_request_hide(widget, args) +{ + widget.widget_control.hide(); +} + +function widget_request_activate(widget, args) +{ + if (!widget.visible) + widget_launch(widget); +} + +function widget_request_deactivate(widget, args) +{ + if (widget.visible) + widget_close(widget, 0); +} + +function widget_request_attention(widget, args) +{ + if (widget.visible) { + widget_display.removeChildren[0] = widget.widget_control; + widget_display.addChildren[0] = widget.widget_control; + widget.widget_control.flash(); + } +} + +function widget_request_notification(widget, args) +{ + var notif = text_rect(''); + notif.children[1].geometry.string[0] = 'Notification from widget'; + notif.children[1].geometry.string[1] = ' '+widget.name; + notif.children[1].geometry.string[2] = ' '; + notif.children[1].geometry.string[3] = args[0]; + dlg_display.children[0] = notif; + notif.set_size(320, 240); + notif.button_click = function() { + dlg_display.removeChildren[0] = this; + } +} + +function widget_place_component(widget, args) +{ + var comp = widget.get_component(args[0]); + + if (comp==null) { + log(l_err, 'Component '+args[0]+' cannot be found in widget '+widget.name); + return; + } + comp.widget_control.place_x = args[1]; + comp.widget_control.place_y = args[2]; + comp.widget_control.place_w = args[3]; + comp.widget_control.place_h = args[4]; + comp.widget_control.place_z = args[5]; + comp.widget_control.component_bound = true; + widget.widget_control.refresh_layout(false, comp); +} + + + +function insert_widget_icon(new_wid, no_layout) { + var icon; + icon = icon_button(widget_get_icon(new_wid), new_wid.name, 0); + icon.tooltip = new_wid.name; + new_wid.in_panel = true; + new_wid.visible = false; + new_wid.icon_dock = icon; + icon.button_click = on_widget_launch; + icon.widget = new_wid; + widget_screen.addChildren[0] = new_wid.icon_dock; + if (!no_layout) layout(); +} + +function scan_directory(dir) +{ + var i, j, count, list, new_wid, uri; + list = Sys.enum_directory(dir, '.xml;.wgt;.mgt', 0); + for (i=0; i<list.length; i++) { + uri = list[i].path + list[i].name; + if (list[i].directory) { + scan_directory(uri); + } else { + count = WidgetManager.num_widgets; + for (j=0; j<count; j++) { + var wid = WidgetManager.get(j); + if (wid.url==uri) break; + } + if (j==count) { + new_wid = WidgetManager.open(uri, null); + if (new_wid!=null) { + insert_widget_icon(new_wid, 1); + } + } + } + } +} + +function widget_browse() +{ + filebrowse = new SFNode('Transform2D'); + infobar.set_label('Select widget'); + dlg_display.children[0] = filebrowse; + + filebrowse.children[0] = icon_button('icons/emblem-unreadable.svg', 'Close', 0); + filebrowse.children[0].button_click = function() { + dlg_display.children.length = 0; + widget_display.scale.x = 1; + layout(); + } + + filebrowse.children[1] = icon_button('icons/go-previous.svg', 'Previous', 0); + filebrowse.children[1].filebrowse = filebrowse; + filebrowse.children[1].button_click = function () { this.filebrowse.layout(0) }; + + filebrowse.children[2] = icon_button('icons/go-next.svg', 'Next', 0); + filebrowse.children[2].filebrowse = filebrowse; + filebrowse.children[2].button_click = function () { this.filebrowse.layout(1) }; + + filebrowse.children[3] = icon_button('icons/go-up.svg', 'Up', 0); + filebrowse.children[3].filebrowse = filebrowse; + filebrowse.children[3].button_click = function () { this.filebrowse.browse(true) }; + + filebrowse.children[4] = icon_button('icons/Folder.svg', 'Scan Directory', 0); + filebrowse.children[4].filebrowse = filebrowse; + filebrowse.children[4].button_click = function () { + scan_directory(this.filebrowse.directory); + WidgetManager.last_widget_dir = this.filebrowse.directory; + dlg_display.children.length = 0; + widget_display.scale.x = 0; + widget_screen_visible = true; + layout(); + } + filebrowse.children[5] = text_label('', 'BEGIN'); + filebrowse.set_label = function(label) { + filebrowse.children[5].set_label(label); + } + filebrowse.nb_tools = filebrowse.children.length; + + filebrowse.browse = function(go_up) { + this.list = Sys.enum_directory(this.directory, '*.xml;*.wgt;*.mgt', go_up); + if (this.list.length) { + this.directory = this.list[0].path; + this.set_label(this.directory); + } else { + this.set_label(''); + } + this.first = 0; + this.layout(0); + } + filebrowse.layout = function(type) { + var w, h, i, y; + this.children.length = this.nb_tools; + + this.children[1].hide(); + this.children[2].hide(); + if (this.directory == '') + this.children[3].hide(); + else + this.children[3].show(); + + if (type==0) { + this.first -= this.nb_items; + if (this.first<0) this.first = 0; + } + else if (type) { + this.first += this.nb_items; + if (this.first + this.nb_items > this.list.length) this.first = this.list.length - this.nb_items; + } + if (this.first) this.children[1].show(); + if (this.first+this.nb_items < this.list.length) this.children[2].show(); + + for (i=0; i<this.nb_items; i++) { + var item; + if (i+this.first>=this.list.length) break; + item = text_rect(this.list[i+this.first].name); + item.path = this.list[i+this.first].path; + item.name = this.list[i+this.first].name; + item.directory = this.list[i+this.first].directory; + item.filebrowse = this; + item.button_click = function() { + if (this.directory) { + this.filebrowse.directory = this.path + this.name; + this.filebrowse.browse(false); + } else { + var value = this.path + this.name; + dlg_display.children.length = 0; + widget_display.scale.x = 1; + widget_screen_visible = true; + layout(); + + var new_wid = WidgetManager.open(value, null); + if (new_wid==null) return; + + WidgetManager.last_widget_dir = this.filebrowse.directory; + insert_widget_icon(new_wid, 0); + } + } + this.children[this.nb_tools+i] = item; + } + this.set_size(this.width, this.height); + } + + + filebrowse.set_size = function(w, h) { + var i, x, y, isize, nbi; + isize = 24; + if (w>display_width - isize) w = display_width - isize; + + this.width = w; + this.height = h; + + i = 1; + while ((i+1)*isize <= h - isize) i++; + + if (i != this.nb_items) { + this.nb_items = i; + this.layout(0); + return; + } + x = -w/2 + isize/2; + y = h/2 - isize/2; + + for (i=0;i<this.nb_tools;i++) { + if (this.nb_tools>i+1) { + this.children[i].set_size(isize, isize); + } + this.children[i].translation.x = x; + this.children[i].translation.y = y; + x += isize; + } + y-=isize; + while (i<this.children.length) { + this.children[i].set_size(w, isize); + this.children[i].translation.x = 0; + this.children[i].translation.y = y; + y-=isize; + i++; + } + } + filebrowse.nb_items = 0; + filebrowse.directory = WidgetManager.last_widget_dir; + filebrowse.browse(0); + + widget_display.scale.x = 0; + layout(); +} + +function onMediaRendererAdd(name, uuid, is_add) +{ + var i, count; + + count = WidgetManager.num_widgets; + for (i=0; i<count; i++) { + wid = WidgetManager.get(i); + if (wid == null) continue; + if (!wid.widget_control) continue; + wid.widget_control.show_remote(); + } + + if (upnp_renders) upnp_renders.refresh(); +} + +function on_upnpopen() +{ + upnp_renders = new SFNode('Transform2D'); + upnp_renders.nb_items = 0; + upnp_renders.refresh = function () { + var i, count, render, item, start_y, w; + this.children.length = 0; + count = WidgetManager.MPEGUStandardServiceProviders.length; + if (count+1>this.nb_items) count = this.nb_items-1; + + item = text_rect('Close'); + item.button_click = function() { + dlg_display.children.length = 0; + upnp_renders=null; + widget_display.scale.x = 1; + infobar.set_label(''); + } + this.children[this.children.length] = item; + + for (i=0; i<count; i++) { + render = WidgetManager.MPEGUStandardServiceProviders[i]; + item = text_rect(render.Name); + item.render = render; + + item.button_click = function() { + dlg_display.children.length = 0; + upnp_renders=null; + widget_display.scale.x = 1; + infobar.set_label(''); + + WidgetManager.migrate_widget(this.render, widget_remote_candidate); + widget_close(widget_remote_candidate, 0); + widget_remote_candidate = null; + } + this.children[this.children.length] = item; + } + this.set_size(this.width, this.height); + } + + upnp_renders.set_size = function (w, h) { + var i, count, start_y, w; + + this.width = w<300 ? w : 300; + this.height = h; + + i = 1; + while ((i+1)*icon_size <= h - icon_size) i++; + if (i != this.nb_items) { + this.nb_items = i; + this.refresh(); + return; + } + count = this.children.length; + start_y = this.height/2 - icon_size - 4; + for (i=0; i<count; i++) { + this.children[i].set_size(this.width, icon_size); + this.children[i].translation.y = start_y; + start_y-=icon_size+2; + } + } + + infobar.set_label('Select remote display'); + dlg_display.children[0] = upnp_renders; + widget_display.scale.x = 0; + layout(); +} + + +function onMediaConnect(url, src_ip) +{ + if (WidgetManager.probe(url)) { + var new_wid = WidgetManager.open(url, src_ip); + if (new_wid==null) { + return; + } + widget_insert(new_wid); + } +} + +// widget get: UI for listWidgets and getWidget +// added by Jean-Claude Dufourd, modeled on filebrowse +function widget_get() { + alert("widget_get"); + widgetbrowse = new SFNode('Transform2D'); + infobar.set_label('Select widget manager'); + dlg_display.children[0] = widgetbrowse; + + widgetbrowse.children[0] = icon_button('icons/emblem-unreadable.svg', 'Close', 0); + widgetbrowse.children[0].button_click = function() { + dlg_display.children.length = 0; + widget_display.scale.x = 1; + layout(); + }; + + widgetbrowse.children[1] = text_label('', 'BEGIN'); + widgetbrowse.set_label = function(label) { + widgetbrowse.children[1].set_label(label); + }; + + widgetbrowse.nb_tools = widgetbrowse.children.length; + + // this function builds the whole UI the first time + widgetbrowse.layout = function() { + alert("widgetbrowse.layout"); + var w, h, i, y; + this.children.length = this.nb_tools; + for (i = 0; i < this.nb_items; i++) { + var item; + if (i >= this.list.length) { + break; + } + item = text_rect(this.list[i].Name); + item.wm = this.list[i]; + item.widgetbrowse = this; + item.button_click = function() { + alert("click to select wm: "+this.wm.Name); + this.widgetbrowse.wm = this.wm; + this.wm.standardService.SetActionListener("listWidgets", get_widget_callback(this.wm, this.widgetbrowse), true); + this.wm.standardService.CallAction("listWidgets", new Array()); + }; + this.children[this.nb_tools + i] = item; + } + this.set_size(this.width, this.height); + }; + + widgetbrowse.set_size = function(w, h) { + alert("widgetbrowse.set_size "+w+" "+h); + var i, x, y, isize, nbi; + isize = 24; + if (w > display_width - isize) { + w = display_width - isize; + } + this.width = w; + this.height = h; + i = 1; + while ((i + 1) * isize <= h - isize) { + i++; + } + if (i != this.nb_items) { + this.nb_items = i; + this.layout(0); + return; + } + x = -w / 2 + isize / 2; + y = h / 2 - isize / 2; + for (i = 0; i < this.nb_tools; i++) { + if (this.nb_tools > i + 1) { + this.children[i].set_size(isize, isize); + } + this.children[i].translation.x = x; + this.children[i].translation.y = y; + x += isize; + } + y -= isize; + while (i < this.children.length) { + this.children[i].set_size(w, isize); + this.children[i].translation.x = 0; + this.children[i].translation.y = y; + y -= isize; + i++; + } + }; + + widgetbrowse.nb_items = WidgetManager.MPEGUStandardServiceProviders.length; + widgetbrowse.list = WidgetManager.MPEGUStandardServiceProviders; + widgetbrowse.set_label('Select Widget Manager'); + widgetbrowse.layout(0); + widget_display.scale.x = 0; + layout(); +} + +function get_widget_callback(device, widgetbrowse) { + alert("get_widget_callback "+device.Name+" "+widgetbrowse); + return function() { + // 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("callback |"+act1+"| |"+act2+"|"); + widgetbrowse.set_label("Select Widget"); + var w, h, i, y; + act1 = act1.split(" "); + act2 = act2.split(" "); + widgetbrowse.children.length = widgetbrowse.nb_tools; + for (i = 0; i < act2.length; i++) { + if (act1[i]=="" || act2[i]=="") continue; + var item = text_rect(act2[i]); + item.widgetCode = act1[i]; + item.widgetName = act2[i]; + item.widgetbrowse = widgetbrowse; + item.button_click = function() { + alert("selected widget: "+this.widgetName); + dlg_display.children.length = 0; + widget_display.scale.x = 1; + widget_screen_visible = true; + layout(); + var arr = new Array(); + arr[0] = "widgetCode"; + arr[1] = this.widgetCode; + this.widgetbrowse.wm.standardService.SetActionListener("getWidget", get_widget_callback2, true); + this.widgetbrowse.wm.standardService.CallAction("getWidget", arr); + }; + widgetbrowse.children[this.nb_tools + i] = item; + } + widgetbrowse.set_size(widgetbrowse.width, widgetbrowse.height); + } +} + +function get_widget_callback2() { + // msgHandler is the first argument, the next arguments are from the reply to listWidgets + alert("callback2-1"); + var act = arguments[0]; + var act1 = act.GetArgumentValue("widgetUrl"); + var act2 = act.GetArgumentValue("widgetContext"); + alert("callback2-2 " + act1 + " " + act2); + var wid = WidgetManager.load(act1, null, act2); + WidgetManager.on_widget_add(wid); +}
View file
gpac-1.0.1.tar.gz/share/deprecated/mpegu-wm.xmt
Changed
(renamed from share/gui/mpegu-wm.xmt)
View file
gpac-1.0.1.tar.gz/share/deprecated/tv_wm_gui.js
Added
@@ -0,0 +1,485 @@ +var movie1 = "../widgets/media/local_video/movies/Clovis Cornillac.mp4"; +var movie2 = "../widgets/media/local_video/movies/Airheads2001_edit.mp4"; +var movie3 = "../widgets/media/local_video/movies/CH Video - Alberto Alessi.mp4"; +var movie4 = "../widgets/media/local_video/movies/Crossing2001_edit.mp4"; +var movie5 = "../widgets/media/local_video/movies/EnemyAtT2001_512kb.mp4"; +var movie6 = "../widgets/media/local_video/movies/KAMI2001_512kb.mp4"; +var movie7 = "../widgets/media/local_video/movies/PipeDrea2001_512kb.mp4"; +var movie8 = "../widgets/media/local_video/movies/LAUTRETE2001_512kb.mp4"; +var movie9 = "../widgets/media/local_video/movies/Unexpect2001_512kb.mp4"; +var movie0 = "../widgets/media/local_video/movies/Animatrix_The_Second_Renaissance_l.mp4"; + +var xlinkns = 'http://www.w3.org/1999/xlink'; + +/* override the print function to use SVG alert */ +print = alert; + +/******************************************************************************* + *Global elements referenced in this script + ******************************************************************************/ + +/* Root of the SVG document presenting the widgets, the dock ...*/ +var root; +/* The dock element presents the widget icons or simplified representations */ +var dock; +/* The movie element presents the media content, widgets are added on top of it */ +var movie; +/* The widget_display element contains the full representation of all activated widgets, it is on top of the movie element */ +var widget_display; +/* The display element contains things to be displayed on top of the widgets */ +var display; + + +function create_icon(url, short_name) { + var icon_g; + icon_g = document.createElement('g'); + icon_g.short_name = short_name; + + var back_rect; + back_rect = document.createElement('rect'); + back_rect.setAttribute('fill', 'url(#inactiveGradient)'); + back_rect.setAttribute('rx', 5); + back_rect.setAttribute('stroke', 'black'); + back_rect.setAttribute('stroke-width', 1); + icon_g.appendChild(back_rect); + + var icon; + icon = document.createElement('animation'); + icon.setAttributeNS(xlinkns ,'href', url); + icon_g.appendChild(icon); + + var text; + text = document.createElement('textArea'); + text.setAttribute('fill', 'white'); + text.textContent = short_name; + icon_g.appendChild(text); + + return icon_g; +} + +function set_icon_active(icon, value) { + var back_rect; + back_rect = icon.firstElementChild; + if (!value) back_rect.setAttribute('fill', 'url(#inactiveGradient)'); + else back_rect.setAttribute('fill', 'url(#activeGradient)'); +} + +function set_icon_visible(icon, value) { + if (value) icon.setAttribute('display', 'inline'); + else icon.setAttribute('display', 'none'); +} + +function set_icon_position(icon, x, y) { + icon.setAttribute('transform', 'translate('+x+','+y+')'); +} + +function set_icon_size(icon, w, h) { + var back_rect = icon.firstElementChild; + back_rect.setAttribute('width', w); + back_rect.setAttribute('height', h); + + var anim = back_rect.nextElementSibling; + anim.setAttribute('x', 5*w/8); + anim.setAttribute('y', -10); + anim.setAttribute('width', 1.2*h); + anim.setAttribute('height', 1.2*h); + + var tA = anim.nextElementSibling; + tA.setAttribute('x', icon_spacing); + tA.setAttribute('y', 5); + tA.setAttribute('height', h); + if (w > 100) { + tA.setAttribute('font-size', h/3); + tA.setAttribute('width', w/1.8); + } else { + tA.setAttribute('font-size', h/5); + tA.setAttribute('width', 4*w/8); + } +} + +function add_widget_to_dock(wid) { + var wid_icon_url = null; + var icon; + var preferredIconType = '.svg'; + for (var i = 0; i < wid.icons.length; i++) { + wid_icon_url = wid.icons[i].relocated_src; + if (wid.icons[i].relocated_src.indexOf(preferredIconType) > 0) { + break; + } + } + if (wid_icon_url == null) wid_icon_url = 'icons\\applications-system.svg'; + //alert(wid_icon_url); + icon = create_icon(wid_icon_url, wid.name); + icon.widget = wid; + set_icon_visible(icon, false); + dock.appendChild(icon); + wid.icon_dock = icon; +} + + +function resize() { + /*dummy values, assign upon window resize event*/ + alert('Size:'+root.viewport.width+'x'+root.viewport.height); + display_width = root.viewport.width;//scene.screen_width; + display_height = root.viewport.height;//scene.screen_height; + + nb_icon_max = 4; + if (display_width > 800) { + out_spacing = 30; + icon_spacing = 10; + } else { + out_spacing = 10; + icon_spacing = 4; + } + dock_width = display_width; + icon_width = (dock_width-((nb_icon_max-1)*icon_spacing+2*out_spacing))/nb_icon_max; + + dock_height = display_height/10; + icon_height = dock_height+4; + + movie.setAttribute('width', display_width); + if (is_dock_visible) { + movie.setAttribute('height', display_height - dock_height); + } else { + movie.setAttribute('height', display_height); + } + + dock.setAttribute('transform', 'translate(0, '+(display_height-dock_height)+')'); + + var dock_back = dock.firstElementChild.firstElementChild; + dock_back.setAttribute('x', 0); + dock_back.setAttribute('y', 0); + dock_back.setAttribute('height', dock_height); + dock_back.setAttribute('width', dock_width); + + var left_arrow = dock_back.nextElementSibling; + left_arrow.setAttribute('x', 0); + left_arrow.setAttribute('y', 0); + left_arrow.setAttribute('height', dock_height - 5); + left_arrow.setAttribute('width', out_spacing); + + var right_arrow = left_arrow.nextElementSibling; + right_arrow.setAttribute('x', dock_width-out_spacing); + right_arrow.setAttribute('y', 0); + right_arrow.setAttribute('height', dock_height-5); + right_arrow.setAttribute('width', out_spacing); + + dock_layout(); + alert('ok'); +} + +/******************************************************************************* + * Global Initialization function, called when the SVG document is loaded + * Initializes global variables (elements) + * Finds the available widgets and add them to the dock + ******************************************************************************/ +function initialize() { + /* root of the SVG document presenting the widgets, the dock ...*/ + root = document.documentElement; + + /* The dock presents the widget icons or simplified representations */ + dock = document.getElementById('dock'); + + /* The movie element presents the media content, widgets are added on top of it */ + movie = document.getElementById('movie'); + + /* The widget display element contains the full representation of all activated widgets, it is on top of the movie_inline element */ + widget_display = document.getElementById('widget_display'); + + /* The display element contains things to be displayed on top of the widgets */ + display = document.getElementById('display'); + + is_dock_visible = false; + if (!is_dock_visible) dock.setAttribute('display', 'none'); + + activate = new Array(); + selected_widget_index = 0; + first_displayed_widget_index = 0; + nb_widgets_visible = 0; + current_widget_pos = 0; + next_widget_pos = 0; + vertical_spacing = 10; + vertical_offset = 0; + + /* if the WidgetManager object is not defined (this is a GPAC extension), we define a dummy one to enable debugging in Opera for example */ + if (typeof WidgetManager == 'undefined') { + WidgetManager = new Object; + WidgetManager.initialize = function () {} + WidgetManager.num_widgets = 8; + WidgetManager.get = function(i) { + var wid = new Object; + if (i < 2) { + wid.icon = 'widgets/clock/appointment-new.svg'; + wid.main = 'widgets/clock/appointment-new.svg'; + wid.name = 'Clock'; + wid.visible = false; + wid.x = 0; + wid.y = 0; + wid.width = 100; + wid.height = 100; + } else { + wid.icon = 'icons/audio-volume-high.svg'; + wid.main = 'icons/audio-volume-high.svg'; + wid.name = 'Music'; + wid.visible = false; + wid.x = 0; + wid.y = 0; + wid.width = 100; + wid.height = 100; + } + return wid; + } + WidgetManager.unload = function (wid) {} + } + + /* Setup the GPAC Widget Manager - this will also scan the available widgets */ + widget_manager_init(); + + /* scan all the widgets from the widget manager, create an iconic view, set its size, add it to the dock element but make it invisible */ + var i; + nb_widgets = WidgetManager.num_widgets; + for (i=0; i<nb_widgets; i++) { + var wid = WidgetManager.get(i); + if (wid == null) continue; + add_widget_to_dock(wid); + activate[i] = true; + } + + //resize(); + + root.addEventListener('keyup', on_key_up, false); + + /* register the callback to be notified of incoming widgets */ + has_upnp = (typeof UPnP != 'undefined'); + alert('has upnp:'+ has_upnp); + if (has_upnp) { + /* setting the callback to allow other devices to push their widgets */ + UPnP.onMediaConnect = onMediaConnect; + UPnP.onMediaStop = onMediaStop; + UPnP.onMediaPause = onMediaPause; + UPnP.onMediaPlay = onMediaPlay; + /* Tell GPAC that the calls to the main Renderer (like open, ...) must be forwared to this scene */ + UPnP.BindRenderer(); + } + +} + +function dock_layout() { + + alert('dock layout first='+ first_displayed_widget_index+ '/' + nb_widgets+' active='+selected_widget_index); + var i; + var docFirstIcon = dock.firstElementChild.nextElementSibling; + /* for all icons before the first visible, make them invisible */ + var child = docFirstIcon; + i = 0; + while (child && i < first_displayed_widget_index) { + set_icon_visible(child, false); + alert('setting child '+i+' invisible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); + child = child.nextElementSibling; + i++; + } + + /* for all icons from the first visible, make them visible and set their position + and for all the icons after the max number of icons, make them invisible */ + i = first_displayed_widget_index; + var start_x = out_spacing; + while (child && i < nb_widgets) { + if (i >= (first_displayed_widget_index+nb_icon_max)) { + set_icon_visible(child, false); + alert('setting child '+i+' invisible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); + } else { + var offset_x = start_x + (i-first_displayed_widget_index)*(icon_width+icon_spacing); + set_icon_visible(child, true); + if (i == selected_widget_index) set_icon_active(child, true); + else set_icon_active(child, false); + set_icon_size(child, icon_width, icon_height); + set_icon_position(child, offset_x, dock_height-icon_height); +// alert('setting child '+i+' visible'+(i == selected_widget_index ? '*' :' ')+ ' '+child.getAttribute('transform')); + } + child = child.nextElementSibling; + i++; + } +} + +function focusNextWidget() { + alert('next'); + if (selected_widget_index < nb_widgets - 1) selected_widget_index++; + if (selected_widget_index > first_displayed_widget_index + nb_icon_max -1 && first_displayed_widget_index + nb_icon_max < nb_widgets) first_displayed_widget_index++; + dock_layout(); +} + +function focusPrevWidget() { + alert('prev'); + if (selected_widget_index > 0) selected_widget_index--; + if (first_displayed_widget_index > selected_widget_index && first_displayed_widget_index > 0) first_displayed_widget_index--; + + dock_layout(); +} + +function on_key_up(evt) { + alert(evt.keyIdentifier + ' released '+evt.keyCode); + if (evt.keyIdentifier == 'Right' || evt.keyCode == 39) { + focusNextWidget(); + } else if (evt.keyIdentifier == 'Left' || evt.keyCode == 37) { + focusPrevWidget(); + } else if (evt.keyIdentifier == 'Up') { + vertical_offset += root.viewport.width / 3; + widget_display.setAttribute('transform', 'translate(0,'+vertical_offset+')'); + } else if (evt.keyIdentifier == 'Down') { + vertical_offset -= root.viewport.width / 3; + widget_display.setAttribute('transform', 'translate(0,'+vertical_offset+')'); + } else if (evt.keyIdentifier == 'Enter') { + if (is_dock_visible) { + if (activate[selected_widget_index]) { + widget_launch(WidgetManager.get(selected_widget_index), widget_display); + activate[selected_widget_index] = false; + nb_widgets_visible++; + if (nb_widgets_visible == 1) { + } + } else { + widget_close(WidgetManager.get(selected_widget_index)); + activate[selected_widget_index] = true; + nb_widgets_visible--; + if (nb_widgets_visible == 0) { + + } + } + } + } else if (evt.keyIdentifier == 'F1') { + dock_toggle_visible(); + } else if (evt.keyIdentifier == 'U+0030') { + movie.setAttributeNS(xlinkns, 'href', movie0); + } else if (evt.keyIdentifier == 'U+0031') { + movie.setAttributeNS(xlinkns, 'href', movie1); + } else if (evt.keyIdentifier == 'U+0032') { + movie.setAttributeNS(xlinkns, 'href', movie2); + } else if (evt.keyIdentifier == 'U+0033') { + movie.setAttributeNS(xlinkns, 'href', movie3); + } else if (evt.keyIdentifier == 'U+0034') { + movie.setAttributeNS(xlinkns, 'href', movie4); + } else if (evt.keyIdentifier == 'U+0035') { + movie.setAttributeNS(xlinkns, 'href', movie5); + } else if (evt.keyIdentifier == 'U+0036') { + movie.setAttributeNS(xlinkns, 'href', movie6); + } else if (evt.keyIdentifier == 'U+0037') { + movie.setAttributeNS(xlinkns, 'href', movie7); + } else if (evt.keyIdentifier == 'U+0038') { + movie.setAttributeNS(xlinkns, 'href', movie8); + } else if (evt.keyIdentifier == 'U+0039') { + movie.setAttributeNS(xlinkns, 'href', movie9); + } +} + +function widget_close(widget) { + alert('widget_close:'+widget.name); + if (typeof widget.deactivate != 'undefined') { + widget.deactivate(); + } else { + wid.visible = false; + } + next_widget_pos -= widget.height + vertical_spacing; + widget.scene_container.removeChild(widget.widget_control); + /*force disconnect of main resource - we do this because we are not sure when the widget_control will be destroyed due to JS GC*/ + widget.widget_control.firstElementChild.setAttributeNS(xlinkns, 'href', ''); + //widget.widget_control.firstElementChild.removeAttributeNS(xlinkns, 'href'); +} + +/* todo ...*/ +function widget_remove(wid) +{ + WidgetManager.unload(wid); +} + +/* Function that starts to present the Widget Full representation */ +function widget_launch(wid, scene_container) { + alert('widget_launch:'+wid.name); + + var widg_ctrl, anim; + + //assign default size to the widget + wid.width = root.viewport.width / 3; + wid.height = root.viewport.width / 3; + + var w = wid.width; + var h = wid.height; + alert('w '+w + ' h '+h); + + widg_ctrl = document.createElement('g'); + widg_ctrl.wid = wid; +// widg_ctrl.setAttribute('transform', 'translate('+(nb_widgets_visible>=2?600:0)+','+400*nb_widgets_visible+')'); +// var y = (nb_widgets_visible%2)*310; +// var x = ((nb_widgets_visible - nb_widgets_visible%2)/2*310); + var x = 0; + var y = next_widget_pos; + next_widget_pos += h+vertical_spacing; + + alert('x:'+x+', y:' +y); + widg_ctrl.setAttribute('transform', 'translate('+x+','+y+')'); + + anim = document.createElement('animation'); + anim.setAttributeNS(xlinkns, 'href', wid.main); + anim.setAttribute('width', w); + anim.setAttribute('height', h); + anim.setAttribute('preserveAspectRatio', 'xMidYMid'); + + widg_ctrl.appendChild(anim); + + wid.widget_control = widg_ctrl; + wid.scene_container = scene_container; + /*this will setup the scene graph for the widget in order to filter input and output communication pins*/ + wid.on_load = function() { + alert('wid.on_load:'+this.name); + WidgetManager.bind(this); + } + wid.activate(anim); + scene_container.appendChild(widg_ctrl); +} + +function dock_toggle_visible() { + if (is_dock_visible) { + dock.setAttribute('display', 'none'); + movie.setAttribute('height', display_height); + is_dock_visible = false; + } else { + dock.setAttribute('display', 'inline'); + is_dock_visible = true; + movie.setAttribute('height', display_height - dock_height); + } +} + + +function onMediaConnect(url, src_ip) +{ + alert('onMediaConnect :\"'+url+'\"'); + + if (WidgetManager.probe(url) ) { + var new_wid = WidgetManager.open(url, src_ip); + if (new_wid==null) return; + + add_widget_to_dock(new_wid); + for (var i = nb_widgets; i < WidgetManager.num_widgets; i++) { + activate[i] = true; + } + nb_widgets = WidgetManager.num_widgets; + dock_layout(); + } else { + alert('invalid widget extension'); + /* TODO if this is not a widget url, we should probably change the movie being played */ + } +} + +function onMediaStop() +{ + alert('Media Stop'); + movie.endElement(); +} +function onMediaPause() +{ + alert('Media pause'); + movie.pauseElement(); +} +function onMediaPlay() +{ + alert('Media Play'); + movie.resumeElement(); +}
View file
gpac-1.0.1.tar.gz/share/deprecated/tv_wm_gui.svg
Changed
(renamed from share/gui/tv_wm_gui.svg)
View file
gpac-1.0.0.tar.gz/share/doc/configuration.html -> gpac-1.0.1.tar.gz/share/doc/configuration.html
Changed
@@ -9,7 +9,7 @@ <p style="text-align: center; Font-Size: 24pt"> <br/> <b>GPAC Configuration file documentation -<br/>GPAC Version 1.0.0</b> +<br/>GPAC Version 1.0.1</b> </p> <br/><br/>
View file
gpac-1.0.0.tar.gz/share/doc/doxyfile -> gpac-1.0.1.tar.gz/share/doc/doxyfile
Changed
@@ -776,7 +776,7 @@ # Note: If this tag is empty the current directory is searched. #for some weird reason on OSX enumeration does not work properly, add IDL files by hand -INPUT=../../include/gpac/ ../../README.md ../../share/doc/idl/jsf.idl ../../share/doc/idl/xhr.idl ../../share/doc/idl/evg.idl ../../share/doc/idl/scenejs.idl ../../share/doc/idl/storage.idl ../../share/doc/idl/webgl.idl +INPUT=../../include/gpac/ ../../README.md ../../share/doc/idl/core.idl ../../share/doc/idl/jsf.idl ../../share/doc/idl/xhr.idl ../../share/doc/idl/evg.idl ../../share/doc/idl/scenejs.idl ../../share/doc/idl/storage.idl ../../share/doc/idl/webgl.idl ../../share/doc/idl/filtersession.idl # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
View file
gpac-1.0.1.tar.gz/share/doc/idl/core.idl
Added
@@ -0,0 +1,762 @@ +/* +\file +\brief silence ! +*/ + +typedef char *DOMString; + +/*! + +\defgroup core_grp JS Core API for libgpac +\ingroup jsapi_grp +\brief JavaScript API for libgpac core tools. + +This section documents the JavaScript API used to query and control libgpac. + +Errors are handled through exceptions. + +@{ + +*/ + +/*! global context property representing the one and only JSGPACCoreSystem object attached to the loaded script*/ +attribute JSGPACCoreSystem Sys; + + +/*!\brief JSGPACCoreSystem API + +The JSGPACCoreSystem interface has a single instance exposed to the script under the name "Sys". +It implements binding to the underlying instance of libgpac. +*/ +interface JSGPACCoreSystem { + +/*! launch arguments*/ +attribute Array args; + +/*! run garbage collection*/ +void gc(); + +/*! marks an argument as used (for argument tracking at prompt) +\param arg_idx index of argument to mark as used +\param arg_used if true, argument is marked as used +*/ +void set_arg_used(unsigned int arg_idx, boolean arg_used); + +/*! gets string for error +\param e the error code +\return the corresponding string*/ +DOMString error_string(GF_Err e); + + +/*! returns character input from prompt, or null if no input (this will be moved soon to core API) +\return input char, or NULL if no input +*/ +DOMString prompt_input(); + + +/*! wait character input from prompt and returns it +\return string entered at prompt +*/ +DOMString prompt_string(); + +/*! sets prompt echo off (input characters not visible) or on - see \ref gf_prompt_set_echo_off +\param echo_off if true, echo is disabled +*/ +void prompt_echo_off(boolean echo_off); + +/*! sets stderr color and other code for upcoming strings - see \ref gf_sys_set_console_code +\param code code to set +*/ +void prompt_code(unsigned long code); + + +/*! gets stdin terminal size - see \ref gf_prompt_get_size +\return terminal size object, or null if not available +*/ +WinRect prompt_size(); + +/*! enumerate directories +\param dir the directory to enumerate +\param filter the filter for file extensions. If "dir", only enumerate directories +\param go_up if true, enumerate parent directory or root (/). +\return array of FileInformation interface*/ +Array enum_directory(DOMString dir, optional DOMString filter=null, optional DOMString filter=null, optional bool go_up=false); + + +/*! get system clock in milliseconds - see \ref gf_sys_clock +\return clock value +*/ +unsigned long clock_ms(); + +/*! get system clock in microseconds - see \ref gf_sys_clock_high_res +\return clock value +*/ +unsigned long long clock_us(); + +/*! convert a 4CC code to its string representation - see \ref gf_4cc_to_str +\param value the 4CC code to convert +\return string representation +*/ +DOMString fcc_to_str(unsigned long value); + +/*! inits random number - see \ref gf_rand_init +\param reset if true, resets the random seed +*/ +void rand_init(optional boolean reset=false); + +/*! gets a random number - see \ref gf_rand +\return random 32 bit value +*/ +unsigned long rand(); + +/*! gets a random number +\return random 64 bit value +*/ +unsigned long long rand64(); + +/*! gets an environment variable +\param var_name environment variable name +\return environment variable value, or null if variable is not defined +*/ +DOMString getenv(DOMString var_name); + +/*! gets UTC clock - see \ref gf_net_get_utc +\return UTC 64 bit timestamp +*/ +unsigned long long get_utc(); + +/*! gets UTC timestamp for a given date - see \ref gf_net_get_utc_ts +\param year date's year +\param month date's month of the year +\param day date's day of the week +\param hour date's hours +\param min date's minutes +\param sec date's seconds +\return UTC 64 bit timestamp +*/ +unsigned long long get_utc(); + + +/*! gets UTC clock from a date - see \ref gf_net_parse_date +\param date date string +\return UTC 64 bit timestamp corresponding to the date +*/ +unsigned long long get_utc(DOMString date); + +/*! gets CRC32 of an arraybuffer - see \ref gf_crc_32 +\param abuf array buffer +\return CRC32 of the data +*/ +unsigned long crc32(ArrayBuffer abuf); + +/*! gets SHA1 digest of an arraybuffer - see \ref gf_sha1_file +\param fname name of file to hash +\return ArrayBuffer containing SHA1 of the file data +*/ +ArrayBuffer sha1(DOMString fname); + +/*! gets SHA1 digest of a file - see \ref gf_sha1_csum +\param abuf array buffer +\return ArrayBuffer containing SHA1 of the data +*/ +ArrayBuffer sha1(ArrayBuffer abuf); + +/*! loads file content into an array buffer - see \ref gf_file_load_data +\param fname name of file to load +\return ArrayBuffer containing data of the file +*/ +ArrayBuffer load_file(DOMString fname); + +/*! compress using deflate() an array buffer +\param in_data input data to compress +\return ArrayBuffer containing compressed data +*/ +ArrayBuffer compress(ArrayBuffer in_data); + +/*! decompress using inflate() an array buffer +\param in_data input data to decompress +\return ArrayBuffer containing decompressed data +*/ +ArrayBuffer decompress(ArrayBuffer in_data); + + +/*! removes directory - cf \ref gf_rmdir +\param dirname name of directory +*/ +void rmdir(DOMString dirname); + +/*! creates directory - cf \ref gf_mkdir +\param dirname name of directory +*/ +void mkdir(DOMString dirname); + +/*! checks if directory exists - cf \ref gf_dir_exists +\param dirname name of directory +\return true if directory exists +*/ +boolean dir_exists(DOMString dirname); + +/*! remove files in directory - cf \ref gf_cleanup_dir +\param dirname name of directory +*/ +void dir_clean(DOMString dirname); + +/*! get basename of file or dir - cf \ref gf_file_basename +\param filename name of file +\return file basename +*/ +DOMString basename(DOMString filename); + +/*! get file extension - cf \ref gf_file_ext_start +\param filename name of file +\return file extension or null if none +*/ +DOMString file_ext(DOMString filename); + +/*! check if file exists - cf \ref gf_file_exists +\param filename name of file +\return true if directory exists +*/ +boolean file_exists(DOMString filename); + +/*! deletes a file - cf \ref gf_file_delete +\param filename name of file +*/ +void del(DOMString filename); + +/*! get file modification time - cf \ref gf_file_modification_time +\param filename name of file +\return file modification time +*/ +unsigned long long mod_time(DOMString filename); + +/*! get file modification time - cf \ref gf_file_modification_time +\param filename name of file +\param newname new name of the file +*/ +void move(DOMString filename, DOMString newname); + + +/*! get option from GPAC config - cf \ref gf_opts_get_key +\param secname name of section +\param keyname name of key +\return value of key or null if no key +*/ +DOMString get_opt(DOMString secname, DOMString keyname); + +/*! get option from GPAC config - cf \ref gf_opts_get_key +\param secname name of section +\param keyname name of key +\param value new value of key or null to remove key +*/ +void set_opt(DOMString secname, DOMString keyname, optional DOMString value=null); + +/*! discard all changes in GPAC config - see \ref gf_opts_discard_changes*/ +void discard_opts(); + +/*! encodes an arraybuffer to a base64 string +\param in_data input buffer +\return encoded string*/ +DOMString base64enc(ArrayBuffer in_data); + +/*! decodes a base64 string to an arraybuffer +\param in_data input encoded string +\return output decoded buffer*/ +ArrayBuffer base64enc(DOMString in_data); + +/*! encodes an arraybuffer to a base16 string +\param in_data input buffer +\return encoded string*/ +DOMString base16enc(ArrayBuffer in_data); + +/*! decodes a base16 string to an arraybuffer +\param in_data input encoded string +\return output decoded buffer*/ +ArrayBuffer base16enc(DOMString in_data); + +/*! converts 32 bit value from host to network byte order +\param value value to convert +\return converted value +*/ +unsigned long htonl(unsigned long value); + +/*! converts 16 bit value from host to network byte order +\param value value to convert +\return converted value +*/ +unsigned long htons(unsigned long value); + +/*! converts 32 bit value from network to host byte order +\param value value to convert +\return converted value +*/ +unsigned long ntohl(unsigned long value); + +/*! converts 16 bit value from network to host byte order +\param value value to convert +\return converted value +*/ +unsigned long ntohs(unsigned long value); + +/*! number of cores */ +attribute readonly unsigned long nb_cores; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long sampling_period_duration; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long total_cpu_time; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long process_cpu_time; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long total_cpu_time_diff; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long process_cpu_time_diff; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long cpu_idle_time; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long total_cpu_usage; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long process_cpu_usage; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long pid; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long thread_count; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long long process_memory; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long long physical_memory; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long long physical_memory_avail; + +/*! see \ref GF_SystemRTInfo */ +attribute readonly unsigned long long gpac_memory; + +/*! last working directory */ +attribute DOMString last_wdir; + +/*! indicates if running on battery or with power charge*/ +readonly attribute boolean batteryOn; + +/*! indicates if battery is charging*/ +readonly attribute boolean batteryCharging; + +/*! battery percent (0 to 100)*/ +readonly attribute unsigned long batteryPercent; + +/*! estimated battery lifetime - see \ref gf_sys_get_battery_state*/ +readonly attribute unsigned long batteryLifeTime; + +/*! estimated battery lifetime in full charge - see \ref gf_sys_get_battery_state*/ +readonly attribute unsigned long batteryFullLifeTime; + +/*! host name*/ +readonly DOMString hostname; + +/*! test mode - see \ref gf_sys_is_test_mode */ +readonly boolean test_mode; + +/*! old arch compatibility mode - see \ref gf_sys_old_arch_compat */ +readonly boolean old_arch; + +/*! check if logs use color - see \ref gf_log_use_color */ +readonly boolean log_color; + + +/*! quiet mode - see \ref gf_sys_is_quiet */ +readonly boolean quiet; + +/*! timezone - see \ref gf_net_get_timezone */ +readonly signed int timezone; + +/*! number of opened file handles - see \ref gf_file_handles_count */ +readonly unsigned int nb_files_open; + + +/*! default cache directory - see \ref gf_get_default_cache_directory */ +readonly DOMString cache_dir; + +/*! default shared directory (containing gui, shaders, etc) - see \ref gf_opts_default_shared_directory */ +readonly DOMString shared_dir; + +/*! GPAC version string */ +readonly DOMString version; + +/*! GPAC full version string, including GIT rev */ +readonly DOMString version_full; + +/*! GPAC copyright string */ +readonly DOMString copyright; + +/*! GPAC version major */ +readonly unsigned long version_major; + +/*! GPAC version minor */ +readonly unsigned long version_minor; + +/*! GPAC version micro */ +readonly unsigned long version_micro; + + +}; + +/*! object used for terminal size info - cannot be created through constructor*/ +interface WinRect { +/*! width of terminal in characters*/ +attribute readonly unsigned long w; + +/*! height of terminal in characters*/ +attribute readonly unsigned long h; +}; + + +/*! object used for file enumeration - cannot be created through constructor*/ +interface FileInformation { + /*! file name*/ + DOMString name; + /*! file path*/ + DOMString path; + /*! true if directory*/ + boolean directory; + /*! true if drive root (local HDD, USB or other mount points)*/ + boolean drive; + /*! true if hidden file*/ + boolean hidden; + /*! true if system file*/ + boolean system; + /*! file size in bytes*/ + unsigned long long size; + /*! last modification UTC time*/ + unsigned long long last_modified; +}; + +/*! SHA1 hasher object*/ +interface SHA1 { + /*! constructor*/ + SHA1(); + /*! push data to hasher - see \ref gf_sha1_update + \param buffer data to be hashed*/ + void push(ArrayBuffer buffer); + /*! get final hash - the hash context is reset after this call - see \ref gf_sha1_finish + \return the hash message*/ + ArrayBuffer get(); +}; + + +/*! FILE object*/ +interface File { + +/*! constructor for a temporary file*/ +File(); + +/*! constructor for a file - see \ref gf_fopen +\param name name of file to open +\param mode read/write mode, same as fopen +\param parent_fileio parent GF_FileIO name - see \ref gf_fopen_ex +*/ +File(DOMString name, DOMString mode, optional DOMString parent_fileio=null); + +/*! flush file - see \ref gf_fflush*/ +void flush(); + +/*! close file, underlying FILE object is destroyed and any futher calls to the file object will fail - see \ref gf_fclose*/ +void close(); + + +/*! read bytes in an array buffer - see \ref gf_fread +\param buf array buffer to read bytes into +\param nb_bytes number of bytes to read - if 0, uses array buffer size. If more than array buffer size, truncated to array buffer size +\return the number of bytes read +*/ +unsigned long read(ArrayBuffer buf, optional unsigned long nb_bytes=0); + +/*! get a string from a file, stopping at first new line character found - see \ref gf_fgets +\return string read +*/ +DOMString gets(); + +/*! read a character from file - see \ref gf_fgetc +\return string containing a single character +*/ +DOMString getc(DOMString char); + + +/*! write bytes of an array buffer to file - see \ref gf_fwrite +\param buf array buffer to read bytes from +\param nb_bytes number of bytes to write - if 0, uses array buffer size. If more than array buffer size, truncated to array buffer size +\return the number of bytes written +*/ +unsigned long write(ArrayBuffer buf, optional unsigned long nb_bytes=0); + +/*! put string to file - see \ref gf_fputs +\param string string to write +*/ +void puts(DOMString string); + +/*! put character to file - see \ref gf_fputc +\param value character to write (only first char of string is used) +*/ +void putc(DOMString value); + +/*! put character to file - see \ref gf_fputc +\param value integer value to write +*/ +void putc(unsigned long value); + +/*! read/write position in file - see \ref gf_ftell and \ref gf_fseek*/ +attribute unsigned long long pos; + +/*! EOF flag on file - see \ref gf_feof */ +attribute readonly boolean eof; + +/*! error code on file, 0 if no error - see \ref gf_ferror */ +attribute readonly unsigned long error; + +/*! file size - see \ref gf_fsize */ +attribute readonly unsigned long long size; + +/*! set to true if file is a GFIO wrapper - see \ref gf_fileio_check */ +attribute readonly boolean gfio; + +}; + + +/*! Bitstream object*/ +interface Bitstream { + +/*! constructor for a dynamic allocated write bitstream*/ +Bitstream(); + +/*! constructor for a static allocated bitstream +\param buffer the array buffer to use for bitstream operations +\param write_mode if set to true, the bitstream is created in write mode, otherwise in read mode +*/ +Bitstream(ArrayBuffer buffer, optional boolean write_mode=false); + + +/*! constructor for a bitstream wrapping a file - see \ref gf_bs_from_file +\param file the File object to use for bitstream operations +\param write_mode if set to true, the bitstream is created in write mode, otherwise in read mode. This mode shall be compatible with the file open mode +*/ +Bitstream(File file, optional boolean write_mode=false); + +/*! get 8-bits unsigned integer, byte-aligned +\return value read*/ +unsigned long get_u8(); + +/*! get 8-bits signed integer, byte-aligned +\return value read*/ +unsigned long get_s8(); + +/*! get 16-bits unsigned integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_u16(); + +/*! get 16-bits unsigned integer, byte-aligned, little-endian +\return value read*/ +unsigned long get_u16_le(); + +/*! get 16-bits signed integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_s16(); + +/*! get 24-bits unsigned integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_u24(); + +/*! get 32-bits unsigned integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_u32(); + +/*! get 32-bits unsigned integer, byte-aligned, little-endian +\return value read*/ +unsigned long get_u32_le(); + +/*! get 32-bits signed integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_s32(); + +/*! get 64-bits unsigned integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_u64(); + +/*! get 64-bits unsigned integer, byte-aligned, little-endian +\return value read*/ +unsigned long get_u64_le(); + +/*! get 64-bits signed integer, byte-aligned, big-endian +\return value read*/ +unsigned long get_s64(); + +/*! get n-bits unsigned integer, big-endian +\param nb_bits number of bits to read +\return value read*/ +unsigned long get_bits(unsigned long nb_bits); + +/*! get float 32 bits value +\return value read*/ +double get_float(); + +/*! get float 64 bits value +\return value read*/ +double get_double(); + +/*! reads bytes in an array buffer +\param buffer target read buffer +\param nb_bytes number of bytes to read - if 0, uses array buffer size. If more than array buffer size, truncated to array buffer size +\return number of bytes read*/ +unsigned long get_data(ArrayBuffer buffer, optional unsigned long nb_bytes=0); + +/*! write 8-bit unsigned value +\param value value to write*/ +void put_u8(unsigned long value); + +/*! write 8-bit signed value +\param value value to write*/ +void put_s8(signed long value); + +/*! write 16-bit unsigned value, big-endian +\param value value to write*/ +void put_u16(unsigned long value); + +/*! write 8-bit unsigned value, little-endian +\param value value to write*/ +void put_u16_le(unsigned long value); + +/*! write 16-bit signed value, big-endian +\param value value to write*/ +void put_s16(signed long value); + +/*! write 24-bit unsigned value +\param value value to write*/ +void put_u24(unsigned long value); + +/*! write 32-bit unsigned value, big-endian +\param value value to write*/ +void put_u32(unsigned long value); + +/*! write 32-bit unsigned value, little-endian +\param value value to write*/ +void put_u32_le(unsigned long value); + +/*! write 32-bit signed value, big-endian +\param value value to write*/ +void put_s32(signed long value); + +/*! write 64-bit unsigned value, big-endian +\param value value to write*/ +void put_u64(unsigned long long value); + +/*! write 64-bit unsigned value, little-endian +\param value value to write*/ +void put_u64_le(unsigned long long value); + +/*! write 64-bit signed value, big-endian +\param value value to write*/ +void put_s64(signed long long value); + +/*! write n-bit unsigned value +\param value value to write +\param nb_bits number of bits to use when writing +*/ +void put_bits(unsigned long long value, unsigned long nb_bits); + +/*! write 32-bit float value +\param value value to write*/ +void put_float(double value); + +/*! write 64-bit float value +\param value value to write*/ +void put_double(double value); + +/*! write data +\param buffer source of data to write +\param nb_bytes number of bytes to write - if 0, uses array buffer size. If more than array buffer size, truncated to array buffer size +\return number of bytes written +*/ +unsigned long put_data(ArrayBuffer buffer, optional unsigned long nb_bytes=0); + +/*! write 64-bit float value +\param buffer buffer to write +\param nb_bytes number of bytes to write - if 0, uses array buffer size. If more than array buffer size, truncated to array buffer size +\param offset byte offset at which data must be inserted +*/ +void insert_data(ArrayBuffer buffer, optional unsigned long nb_bytes=0, optional unsigned long offset=0); + + +/*! check if bitsream is byte-aligned - see \ref gf_bs_is_align +\return true if aligned*/ +boolean is_align(); + +/*! set bitsream byte-aligned - see \ref gf_bs_align*/ +void align(); + +/*! truncate bitsream - see \ref gf_bs_truncate*/ +void truncate(); + +/*! get content of the bitstream - see \ref gf_bs_get_content +\return ArrayBuffer containing the bitstream content*/ +ArrayBuffer get_content(); + +/*! transfer bitstream into another - see \ref gf_bs_transfer +\param src_bs source bitstream for bytes to transfer +\param keep_src if true, the source bitstream will not be reset +*/ +void transfer(Bitstream *src_bs, optional boolean keep_src=false); + +/*! peek bits without changing bitstream state - see \ref gf_bs_peek_bits +\param nb_bits the number of bits to peek +\param byte_offset the position of the first byte after the current position to start peek +\return value peeked*/ +unsigned long peek(unsigned long nb_bits, optional unsigned long byte_offset=0); + +/*! skips given amount of bytes +\param nb_bytes number of bytes to skip*/ +void skip(unsigned long nb_bytes); + +/*! flush underlying file object if any*/ +void flush(); + +/*! enable emulation preventio byte removal - see \ref gf_bs_enable_emulation_byte_removal +\param enable if true, EPB is removed in read operations*/ +void epb_mode(boolean enable); + +/*! position of bitstream - see \ref gf_bs_get_position and \ref gf_bs_seek*/ +attribute unsigned long long pos; + +/*! check if bytes are available for read/write - see \ref gf_bs_available */ +attribute readonly unsigned long long available; + +/*! size of bitstream - see \ref gf_bs_get_size */ +attribute readonly unsigned long long size; + +/*! bit offset in bitstream - see \ref gf_bs_get_bit_offset */ +attribute readonly unsigned long bit_offset; + +/*! bit position in bitstream - see \ref gf_bs_get_bit_position */ +attribute readonly unsigned long bit_position; + +/*! bit available till end of byte - see \ref gf_bs_bits_available */ +attribute readonly unsigned long bits_available; + +/*! gets refreshed size of bitstream - see \ref gf_bs_get_refreshed_size */ +attribute readonly unsigned long long refreshed_size; + +} + + + + +/*! @} */ +
View file
gpac-1.0.1.tar.gz/share/doc/idl/filtersession.idl
Added
@@ -0,0 +1,278 @@ +/* +\file +\brief silence ! +*/ + +typedef char *DOMString; + +/*! + +\defgroup fsess_grp JS FilterSession API +\ingroup jsapi_grp +\brief JavaScript API for FilterSession. + +This section documents the JavaScript API used to query the filter session. + +Errors are handled through exceptions. + +@{ + +*/ + +/*! global context property representing the one and only JSFilterSession object attached to the loaded script*/ +attribute JSFilterSession session; + +/*! global context function for printing +\param log the string to write +*/ +void print(DOMString log); +/*! global context function for printing +\param log_level the log level to use: GF_LOG_DEBUG, GF_LOG_INFO, GF_LOG_WARNING, GF_LOG_ERROR. The special value -2 means print as gf_sys_format_help without highlight, the special value -1 means print as gf_sys_format_help with hightlight of first) +\param log_str the string to write +*/ +void print(long log_level, DOMString log_str); + + +/*!\brief JSFilterSession API + +The JSFilterSession interface has a single instance exposed to the script under the name "session". +It implements binding to the underlying filter session object, see \ref GF_FilterSession. +*/ +interface JSFilterSession { + + +/*! posts a task to the main scheduler - see \ref gf_fs_post_user_task +\param task_callback the callback function to use. This callback functions has no parameters, and returns false or an exception to abort the task, true to reschedule the task immediately or a reschedule time in milliseconds +\param task_name optional value giving a label for the task +*/ +void post_task(function task_callback, optional DOMString task_name=null); + +/*! aborts the filter session - see \ref gf_fs_abort +\param do_flush if true, wait for all packets currently pending to be processed before closing the session +*/ +void abort(optional boolean do_flush=false); + +/*! locks the filter session - see \ref gf_fs_lock_filters. When the session is locked, tasks are suspended and filters cannot be destroyed. +The session only needs to be locked when enumerating filters +\param do_lock if true, locks the session, otherwise unlocks it +*/ +void lock_filters(boolean do_lock); + +/*! returns the JSFSFilter object for the given index. +\param index index of filter to query. This index is only valid when session is locked +\return the filter object, null if none found +*/ +JSFSFilter get_filter(unsigned long index); + +/*! returns the JSFSFilter object for a given filter \ref iname. +\param iname the iname of filter to query +\return the filter object, null if none found +*/ +JSFSFilter get_filter(unsigned long index); + +/*! sends the given string to the remotery client(s) +\param command the command to send +\return error code if any +*/ +void rmt_send(DOMString command); + +/*! sets callback function to use when processing remotery client request +\param callback the callback function to call. This function takes one parameter which is the text being received +\return error code if any +*/ +void rmt_set_fun(function callback); + +/*! inserts a filter in graph +\param filter_to_add string describin the filter to add, can be in the form "src=" for sources, "dst=" for sinks or regular string for filters. +\param link_from filter used as source for the created filters - see \ref gf_filter_set_source +\param link_args arguments for the link (used to assign new filter SID - see \ref gf_filter_set_source +\return new filter created +*/ +JSFSFilter add_filter(DOMString filter_to_add, optional JSFSFilter link_from=null, optional DOMString link_args=null); + +/*! sets callback function to get notifications upon each new filter creation. The callback function is passed a single parameter, the filter object*/ +void set_new_filter_fun(function callback); + +/*! sets callback function to get notifications upon each filter destruction. The callback function is passed a single parameter, the filter object*/ +void set_del_filter_fun(function callback); + +/*! sets callback function to get events being sent back to application (see \ref gf_fs_set_ui_callback). The callback function will have a single parameter set, an event instance of FilterEvent interface. The return value of the function should be as indicated for each event type*/ +boolean set_event_fun(function callback); + +/*! fires a given event on all registered user event if no filter is specified, or on the filter +\param evt the event to send +\param filter the filter to send the event to +\param upstream if filter is not null, indicates whether the event shall be sent upstream (towards the sink) or downstream (towards the destination) +\return true if event was fired, false if no event target was found or if the filter is not an event target*/ +boolean fire_event(FilterEvent evt, optional JSFSFilter *filter=null, optional boolean upstream=false); + +/*! enables session reporting - see \ref gf_fs_enable_reporting. +\param enable enables reporting if true*/ +void reporting(boolean enable); + +/*! number of filters in the session - see \ref gf_fs_get_filters_count. +This number is only valid when session is locked*/ +attribute long nb_filters; + +/*! check if the calling task is the last task in the session - see \ref gf_fs_is_last_task*/ +readonly attribute boolean last_task; + +/*! max capped HTTP download rate - used for DASH simulations mostly*/ +attribute unsigned long http_max_bitrate; + +/*! current http download rate averaged on all active resources*/ +readonly attribute unsigned long http_bitrate; + +}; + + +/*!\brief JSFSFilter API + +The JSFSFilter interface provides tools to query and update filters in a session. +It implements binding to the underlying filter object, see \ref GF_Filter. +*/ +interface JSFSFilter { +/*! filter name - may be changed at run-time by the filter*/ +attribute readonly DOMString name; +/*! filter ID - cannot be modified by filter, but may be null*/ +attribute readonly DOMString ID; +/*! filter registry name */ +attribute readonly DOMString type; +/*! number of input PIDs for the filter*/ +attribute readonly unsigned long nb_ipid; +/*! number of output PIDs for the filter*/ +attribute readonly unsigned long nb_opid; +/*! status string of the filter, or null*/ +attribute readonly DOMString status; +/*! set to true if the filter is an alias filter (should be ignored)*/ +attribute readonly boolean alias; +/*! set to the arguments passed to the filter, null if none*/ +attribute readonly DOMString args; +/*! set to true if filter was dynamically loaded during graph resolution, false if filter was explicetly loaded by user/app*/ +attribute readonly boolean dynamic; +/*! set to true if filter is done processing and will soon be removed*/ +attribute readonly boolean done; +/*! time in microseconds the filter has been running*/ +attribute readonly unsigned long long time; +/*! number of input packets received*/ +attribute readonly unsigned long long pck_done; +/*! number of input bytes received*/ +attribute readonly unsigned long long bytes_done; +/*! number of packets sent*/ +attribute readonly unsigned long long pck_sent; +/*! number of frame interfaces packets sent*/ +attribute readonly unsigned long long pck_ifce_sent; +/*! number of bytes sent*/ +attribute readonly unsigned long long bytes_sent; +/*! number of tasks executed*/ +attribute readonly unsigned long tasks; +/*! number of errors*/ +attribute readonly unsigned long errors; +/*! set to true if report has been updated since last query*/ +attribute readonly boolean report_updated; +/*! class of filter, can be "rawin", "demuxer", "decoder", "encoder", "muxer", "rawout", "mediasink", "mediasource", "unknown"*/ +attribute readonly DOMString class; +/*! stream type (audio, visual, ...)*/ +attribute readonly DOMString streamtype; +/*! codec name or null if unknown*/ +attribute readonly DOMString codec; +/*! internal name - this can only be set and modified by this JS and allows for filter identification from JS*/ +attribute DOMString iname; +/*! set to true if filter accepts user events*/ +attribute boolean event_target; + +/*! set to max timestamp of last packet sent by the filter, or null if not available*/ +attribute boolean last_ts_sent; + +/*! set to max timestamp of last packet dropped by the filter, or null if not available*/ +attribute boolean last_ts_drop; + +/*! Checks if a filter is valid or if it has been destroyed. Any query on a destroyed filter will raise an exception. +\return true if the filter has been destroyed, false otherwise*/ +boolean is_destroyed(); + +/*! Gets properties on input pid +\param idx the index of the input pid to query +\param name name of the property to query +\return property value, or null if not found +*/ +FilterProperty ipid_props(unsigned long idx, DOMString name); + +/*! Enumerates properties on input pid +\param idx the index of the input pid to query +\param fun_callback function called for each property in the input pid. The function has three parameters: name (DOMString), type (DOMString), value (FilterProperty) +*/ +void ipid_props(unsigned long idx, function fun_callback); + +/*! Gets properties on output pid +\param idx the index of the output pid to query +\param name name of the property to query +\return property value, or null if not found +*/ +FilterProperty opid_props(unsigned long idx, DOMString name); + +/*! Enumerates properties on output pid +\param idx the index of the output pid to query +\param fun_callback function called for each property in the output pid. The function has three parameters: name (DOMString), type (DOMString), value (FilterProperty) +*/ +void opid_props(unsigned long idx, function fun_callback); + +/*! Gets source filter for an input pid +\param idx the index of the input pid to query +\return input filter or null +*/ +JSFSFilter ipid_source(unsigned long idx); + +/*! Gets destination filter(s) for an output pid +\param idx the index of the output pid to query +\return array of output filters +*/ +Array opid_sinks(unsigned long idx); + +/*! Gets all arguments (options) of the filter +\param value_only if true, only returns name (DOMString) and value (FilterProperty) of each argument. Otherwise returns the full argument (JSFSFilterArg) +\return array of JSFSFilterArg +*/ +Array all_args(optional boolean value_only=true); + +/*! sends argument update to filter +\param arg_name name of argument to update +\param arg_val value of argument to update +*/ +void update(DOMString arg_name, DOMString arg_val); + +/*! removes filter from graph*/ +void remove(); + +/*! inserts a filter in graph linked to the current filter +\param filter_to_add string describing the filter to add, can be in the form "src=" for sources, "dst=" for sinks or regular string for filters. +\param link_args specify any additional arguments to pass to the SID option of the new filter - see \ref gf_filter_set_source +*/ +void insert(DOMString filter_to_add, optional DOMString link_args=NULL); + +}; + +/*! Object describing a filter argument +*/ +interface JSFSFilterArg { +/*! name*/ +attribute DOMString name; +/*! value*/ +attribute FilterProperty value; +/*! textual description*/ +optional attribute DOMString desc; +/*! min/max/enum value or null*/ +optional attribute DOMString min_max_enum; +/*! default value or null*/ +optional attribute DOMString default; +/*! argument can be updated*/ +optional attribute boolean update; +/*! indicate the UI level of the argument - string can be undefined, "advanced" or "expert"*/ +optional attribute DOMString hint; + +}; + + + +/*! @} */ +
View file
gpac-1.0.0.tar.gz/share/doc/idl/jsf.idl -> gpac-1.0.1.tar.gz/share/doc/idl/jsf.idl
Changed
@@ -132,6 +132,9 @@ readonly attribute unsigned long long clock_hint_mediatime; /*! see \ref gf_filter_connections_pending*/ readonly attribute unsigned long long connections_pending; +/*! internal name - this can only be set and modified by JS API and allows for filter identification from JS*/ +attribute DOMString iname; + /*! sets filter desciption as visible when checking filter info \param description description of filter*/ @@ -148,6 +151,7 @@ /*! adds an argument to the filter. JavaScript Filter arguments can be specified from command line in the same way as reguar filters. The argument is then exposed as a property of the "filter" object of the javascript context. +If the argument name is a wildcard (*), the filter will be forwarded any argument name. \param arg object exposing the same interface as the JSArgDesc interface */ void set_arg(JSArgDesc arg); @@ -240,9 +244,10 @@ /*! adds a source filter in the media session - see \ref gf_filter_connect_source \param source URL of source to load \param parent URL of parent, used as baseURL for the source. May be NULL +\param inherit_args if true, new filter will inherit arguments of this filter's destination \return new loaded source filter or null */ -FilterInstance add_source(DOMString source, optional DOMString parent = null); +FilterInstance add_source(DOMString source, optional DOMString parent = null, optional boolean inherit_args = false); /*! adds a destination filter in the media session - see \ref gf_filter_connect_destination \param destination URL of destination to instantiate @@ -268,7 +273,7 @@ /*! makes the filter prevent EOS queries - see \ref gf_filter_block_eos \param do_block if true, filter input pids cannot be checked for end of stream during EOS queries */ -void prevent_blocking(boolean do_block); +void block_eos(boolean do_block); }; @@ -728,6 +733,8 @@ /*! FilterEvent expose a filter event object, either for processing a received event or triggering a new event. The read access to the members of the structure is cross-checked with the event type and throw an error when attempting to access the wrong field + +When a field is marked as read-only, this means the event cannot be fired, it can only be received. */ interface FilterEvent { @@ -833,7 +840,40 @@ attribute unsigned long hwkey; /*! array of DOMString - see \ref GF_EventOpenFile*/ -attribute Array dropfiles; +attribute readonly Array dropfiles; + +/*! see \ref GF_EventClipboard*/ +attribute DOMString clipboard; + +/*! see \ref GF_EventMultiTouch*/ +attribute float mt_x; +/*! see \ref GF_EventMultiTouch*/ +attribute float mt_y; +/*! see \ref GF_EventMultiTouch*/ +attribute float mt_rotate; +/*! see \ref GF_EventMultiTouch*/ +attribute float mt_pinch; +/*! see \ref GF_EventMultiTouch*/ +attribute float mt_fingers; + +/*! see \ref GF_EventSize*/ +attribute unsigned long width; +/*! see \ref GF_EventSize*/ +attribute unsigned long height; + +/*! see \ref GF_EventShow*/ +attribute unsigned long showtype; + +/*! see \ref GF_EventMove*/ +attribute unsigned long move_x; +/*! see \ref GF_EventMove*/ +attribute unsigned long move_y; +/*! see \ref GF_EventMove*/ +attribute unsigned long move_relative; +/*! see \ref GF_EventMove*/ +attribute unsigned long move_alignx; +/*! see \ref GF_EventMove*/ +attribute unsigned long move_aligny; };
View file
gpac-1.0.0.tar.gz/share/doc/idl/scenejs.idl -> gpac-1.0.1.tar.gz/share/doc/idl/scenejs.idl
Changed
@@ -12,87 +12,81 @@ This section documents the API used to access and control the compositor and scene media objects when using interactive BIFS/VRML/X3D/SVG rendering. This API is not loaded by default when playing a scene and shall be loaded by a scene script using: \code -import {gpac} from 'scenejs' +import {scene} from 'scenejs' \endcode This API cannot be loaded from a JSFilter. -It exports a single object "gpac", instance of JSGPAC class. - +It exports: +- a single object "scene", instance of JSScene class. +- a single object "session", instance of JSFilterSession class. @{ */ -/*! JSGPAC is the interface to compositor*/ -interface JSGPAC { -/*! last working directory */ -attribute DOMString last_working_directory; -/*! indicates if running on battery or with power charge*/ -readonly attribute boolean batteryOn; -/*! indicates if battery is charging*/ -readonly attribute boolean batteryCharging; -/*! battery percent (0 to 100)*/ -readonly attribute unsigned long batteryPercent; -/*! estimated battery lifetime - see \ref gf_sys_get_battery_state*/ -readonly attribute unsigned long batteryLifeTime; -/*! estimated battery lifetime in full charge - see \ref gf_sys_get_battery_state*/ -readonly attribute unsigned long batteryFullLifeTime; -/*! host name*/ -readonly DOMString hostname; +/*! JSScene is the interface to compositor*/ +interface JSScene { + /*! fullscreen status*/ attribute boolean fullscreen; + /*! current working directory*/ readonly DOMString current_path; + /*! audio output volume*/ attribute unsigned long volume; + /*! navigation mode*/ attribute unsigned long navigation; + /*! checks if navigation is off, 2D or 3D mode*/ attribute unsigned long navigation_type; + /*! true if display has hardware yuv 2D blit*/ readonly attribute boolean hardware_yuv; + /*! true if display has hardware rgb 2D blit*/ readonly attribute boolean hardware_rgb; + /*! true if display has hardware rgba 2D blit*/ readonly attribute boolean hardware_rgba; + /*! true if display has hardware stretch blit*/ readonly attribute boolean hardware_stretch; + /*! display width*/ readonly attribute unsigned long screen_width; + /*! display height*/ readonly attribute unsigned long screen_height; -/*! max capped HTTP download rate - used for DASH simulations mostly*/ -attribute unsigned long http_max_bitrate; -/*! current http download rate averaged on all active resources*/ -readonly attribute unsigned long http_bitrate; + /*! current output fps*/ readonly attribute double fps; + /*! desired output fps for animations*/ readonly attribute double sim_fps; + /*! true if display has opengl support*/ readonly attribute boolean has_opengl; -/*! cpu usage*/ -readonly attribute double cpu; -/*! number of cores*/ -readonly attribute unsigned long nb_cores; -/*! system memory*/ -readonly attribute unsigned long system_memory; -/*! memory usage*/ -readonly attribute unsigned long memory; -/*! number of arguments of launch command*/ -readonly attribute unsigned long argc; + /*! window title*/ attribute DOMString caption; + /*! enables or disable focus highlighting*/ attribute boolean focus_highlight; -/*! sceen horizontal dpi*/ + +/*! screen horizontal dpi*/ readonly attribute unsigned long dpi_x; -/*! sceen vertical dpi*/ + +/*! screen vertical dpi*/ readonly attribute unsigned long dpi_y; + /*! sensor active state (gyroscope) */ attribute boolean sensors_active; + /*! compositor zoom factor*/ readonly attribute double zoom; + /*! current text selection*/ readonly attribute DOMString text_selection; @@ -102,6 +96,7 @@ \return the key value */ DOMString get_option(DOMString section, DOMString key); + /*! see \ref gf_opts_get_key_name \param section the section name \param key_idx the key index in the section @@ -109,29 +104,24 @@ */ */ DOMString get_option(DOMString section, unsigned key_idx); + /*! see \ref gf_opts_set_key \param section the section name \param key the key name \param value the key value, null to remove the key */ void set_option(DOMString section, DOMString key, optional DOMString value=null); -/*! get program argument by index -\param idx the argument index -\return the argument*/ -DOMString get_arg(unsigned long idx); -/*! enumerate directories -\param dir the directory to enumerate -\param filter the filter for file extensions. If "dir", only enumerate directories -\param go_up if true, enumerate parent directory or root (/). -\return array of FileInformation interface*/ -Array enum_directory(DOMString dir, optional DOMString filter=null, optional DOMString filter=null, optional bool go_up=false); + + /*! set output window size \param width desired width \param height desired height */ void set_size(unsigned long width, unsigned long height); + /*! post quit message*/ void exit(); + /*! turns 3D rendering on/off \param use_3d if true, uses 3D for all content, otherwise use 3D based on content type */ @@ -143,35 +133,40 @@ \param relative if true, use relative (delta) positioning; otherwise use absolute */ void move_window(unsigned long x, unsigned long y, optional boolean relative=false); + /*! assigns event filter \param filter_event_func the filter event function to use, or null to deactivate event filtering*/ void set_event_filter(GPACEventFilter filter_event_func); + /*! moves focus \param focus "next" for next element in focus ring, "prev" for previous*/ void set_focus(DOMString focus); + /*! sets focus on element \param elt the node on which focus should be set */ void set_focus(Node elt); -/*! gets string for error -\param e the error code -\return the corresponding string*/ -DOMString error_string(GF_Err e); + /*! show or hide virtual keyboard \param do_show if true, show keyboard, otherwise hide it*/ void show_keyboard(boolean do_show); + /*! triggers JS garbage collection pass*/ void trigger_gc(); + /*! gets object manager for the given service URL loaded in the root scene of the compositor \param url url of service for which the object manager is queried \return the object manager, or null if not found*/ MediaObject get_object_manager(DOMString url); + /*! switches quality \param up switches quality up (true) or down (false)*/ void switch_quality(boolean up); + /*! checks if navigation type is supported for the current content \param nav_type the navigation type to check \return true if supported, false otherwise*/ boolean navigation_supported(unsigned long nav_type); + /*! sets default back color of player \param r red component between 0.0 and 1.0 \param g green component between 0.0 and 1.0 @@ -179,10 +174,6 @@ \param a alpha component between 0.0 and 1.0 */ void set_back_color(double r, double g, double b, double a); -/*! allocates a new storage -\param storage_name the storage name -\return the storage object*/ -Storage new_storage(DOMString storage_name); }; @@ -195,25 +186,6 @@ boolean filter_event(GPACEVT evt); }; -/*! object used for file enumeration*/ -interface FileInformation { - /*! file name*/ - DOMString name; - /*! file path*/ - DOMString path; - /*! true if directory*/ - boolean directory; - /*! true if drive root (local HDD, USB or other mount points)*/ - boolean drive; - /*! true if hidden file*/ - boolean hidden; - /*! true if system file*/ - boolean system; - /*! file size in bytes*/ - unsigned long long size; - /*! last modification UTC time*/ - unsigned long long last_modified; -}; /*! interface to user event - see \ref GF_Event*/ interface GPACEVT { @@ -374,6 +346,11 @@ \return the SRD information, or null*/ SRDDesc get_srd(); +/*! checks if the given filter is in parent (down the source) chain of this object. The compositor filter and any filter connected after the compositor are excluded +\param filter the filter to test +\return true if the filter is in the parent chain, false otherwise +*/ +boolean in_parent_chain(JSFSFilter filter); /*! declares an addon \param addon_url URL of addon to insert
View file
gpac-1.0.0.tar.gz/share/doc/man/gpac-filters.1 -> gpac-1.0.1.tar.gz/share/doc/man/gpac-filters.1
Changed
@@ -24,7 +24,7 @@ .br The inspect filter can be used to dump pid and packets. It may also be used to check parts of payload of the packets. The default options inspect only pid changes. .br -The packet inspector can be configured to dump specific properties of packets using -fmt. +The packet inspector can be configured to dump specific properties of packets using .I fmt. .br When the option is not present, all properties are dumped. Otherwise, only properties identified by $TOKEN$ are printed. You may use '$', '@' or '%' for TOKEN separator. TOKEN can be: .br @@ -125,7 +125,7 @@ .SH Options (expert): .LP .br -log (str, default: stderr, minmax: fileName, stderr or stdout, updatable): set inspect log filename +log (str, default: stderr, minmax: fileName, stderr, stdout or null): set inspect log filename .br mode (enum, default: pck): dump mode .br @@ -141,11 +141,11 @@ .br interleave (bool, default: true): dump packets as they are received on each pid. If false, report per pid is generated .br -deep (bool, default: false, updatable): dump packets along with PID state change, implied when -fmt is set +deep (bool, default: false, updatable): dump packets along with PID state change, implied when .I fmt is set .br -props (bool, default: true, updatable): dump packet properties, ignored when -fmt is set (see filter help) +props (bool, default: true, updatable): dump packet properties, ignored when .I fmt is set (see filter help) .br -dump_data (bool, default: false, updatable): enable full data dump (WARNING heavy!), ignored when -fmt is set (see filter help) +dump_data (bool, default: false, updatable): enable full data dump (WARNING heavy!), ignored when .I fmt is set (see filter help) .br fmt (str, updatable): set packet dump format (see filter help) .br @@ -165,7 +165,7 @@ .br analyze (bool, default: false, updatable): analyze sample content (NALU, OBU) .br -xml (bool, default: false, updatable): use xml formatting (implied if (-analyze]() is set) and disable -fmt +xml (bool, default: false, updatable): use xml formatting (implied if (-analyze]() is set) and disable .I fmt .br fftmcd (bool, default: false, updatable): consider timecodes use ffmpeg-compatible signaling rather than QT compliant one .br @@ -179,6 +179,8 @@ .br * network: URL/path dump, cache state, file size properties skipped (used for hashing network results) .br +* netx: same as network but skip track duration and templates (used for hashing progressive load of fmp4) +.br * encode: same as network plus skip decoder config (used for hashing encoding results) .br * encx: same as encode and skip bitrates, media data size and co @@ -203,7 +205,7 @@ .SH Options (expert): .LP .br -log (str, default: stderr, minmax: fileName, stderr or stdout, updatable): set inspect log filename +log (str, default: stderr, minmax: fileName, stderr, stdout or null): set inspect log filename .br mode (enum, default: pck): dump mode .br @@ -219,11 +221,11 @@ .br interleave (bool, default: true): dump packets as they are received on each pid. If false, report per pid is generated .br -deep (bool, default: false, updatable): dump packets along with PID state change, implied when -fmt is set +deep (bool, default: false, updatable): dump packets along with PID state change, implied when .I fmt is set .br -props (bool, default: true, updatable): dump packet properties, ignored when -fmt is set (see filter help) +props (bool, default: true, updatable): dump packet properties, ignored when .I fmt is set (see filter help) .br -dump_data (bool, default: false, updatable): enable full data dump (WARNING heavy!), ignored when -fmt is set (see filter help) +dump_data (bool, default: false, updatable): enable full data dump (WARNING heavy!), ignored when .I fmt is set (see filter help) .br fmt (str, updatable): set packet dump format (see filter help) .br @@ -243,7 +245,7 @@ .br analyze (bool, default: false, updatable): analyze sample content (NALU, OBU) .br -xml (bool, default: false, updatable): use xml formatting (implied if (-analyze]() is set) and disable -fmt +xml (bool, default: false, updatable): use xml formatting (implied if (-analyze]() is set) and disable .I fmt .br fftmcd (bool, default: false, updatable): consider timecodes use ffmpeg-compatible signaling rather than QT compliant one .br @@ -257,6 +259,8 @@ .br * network: URL/path dump, cache state, file size properties skipped (used for hashing network results) .br +* netx: same as network but skip track duration and templates (used for hashing progressive load of fmp4) +.br * encode: same as network plus skip decoder config (used for hashing encoding results) .br * encx: same as encode and skip bitrates, media data size and co @@ -298,9 +302,9 @@ .br It will generate its outputs based on the input video frames and will not process any user event. .br -If no input video frames (e.g. pure BIFS / SVG / VRML), the filter will generate frames based on the -fps, at constant or variable frame rate. +If no input video frames (e.g. pure BIFS / SVG / VRML), the filter will generate frames based on the .I fps, at constant or variable frame rate. .br -It will stop generating frames as soon as all input streams are done, unless extended/reduced by -dur. +It will stop generating frames as soon as all input streams are done, unless extended/reduced by .I dur. .br If audio streams are loaded, an audio output pid is created. .br @@ -312,7 +316,7 @@ .br - rgba when the filter is loaded during a link resolution .br -This can be changed by assigning the -opfmt option. +This can be changed by assigning the .I opfmt option. .br .br @@ -352,7 +356,7 @@ .SH Options (expert): .LP .br -aa (enum, default: all, updatable): set anti-aliasing mode for raster graphics - whether the setting is applied or not depends on the graphics module / graphic card. +aa (enum, default: all, updatable): set anti-aliasing mode for raster graphics; whether the setting is applied or not depends on the graphics module or graphic card .br * none: no anti-aliasing .br @@ -368,7 +372,7 @@ .br hllinew (flt, default: 1.0, updatable): set highlight stroke width .br -sz (bool, default: true, updatable): enable scalable zoom. When scalable zoom is enabled, resizing the output window will also recompute all vectorial objects. Otherwise only the final buffer is stretched. +sz (bool, default: true, updatable): enable scalable zoom. When scalable zoom is enabled, resizing the output window will also recompute all vectorial objects. Otherwise only the final buffer is stretched .br bc (uint, default: 0, updatable): default background color to use when displaying transparent images or video with no scene composition instructions .br @@ -382,7 +386,7 @@ .br fast (bool, default: false, updatable): enable speed optimization - whether the setting is applied or not depends on the graphics module / graphic card .br -bvol (enum, default: no, updatable): draw bounding volume of objects. +bvol (enum, default: no, updatable): draw bounding volume of objects .br * no: disable bounding box .br @@ -402,7 +406,7 @@ .br .br -out8b (bool, default: false, updatable): convert 10-bit video to 8 bit texture before GPU upload. +out8b (bool, default: false, updatable): convert 10-bit video to 8 bit texture before GPU upload .br drop (bool, default: false, updatable): drop late frame when drawing. By default frames are not droped until a heavy desync of 1 sec is observed .br @@ -410,31 +414,31 @@ .br sgaze (bool, default: false, updatable): simulate gaze events through mouse .br -ckey (uint, default: 0, updatable): color key to use in windowless mode (0xFFRRGGBB). GPAC currently does not support true alpha blitting to desktop due to limitations in most windowing toolkit, it therefore uses color keying mechanism. The alpha part of the key is used for global transparency of the output, if supported. +ckey (uint, default: 0, updatable): color key to use in windowless mode (0xFFRRGGBB). GPAC currently does not support true alpha blitting to desktop due to limitations in most windowing toolkit, it therefore uses color keying mechanism. The alpha part of the key is used for global transparency of the output, if supported .br timeout (uint, default: 10000, updatable): timeout in ms after which a source is considered dead .br -fps (frac, default: 30/1, updatable): simulation frame rate when animation-only sources are played (ignored when video is present). +fps (frac, default: 30/1, updatable): simulation frame rate when animation-only sources are played (ignored when video is present) .br -timescale (uint, default: 0, updatable): timescale used for output packets when no input video pid. A value of 0 means fps numerator. +timescale (uint, default: 0, updatable): timescale used for output packets when no input video pid. A value of 0 means fps numerator .br -autofps (bool, default: true): use video input fps for output. If no video or not set, uses -fps. Ignored in player mode +autofps (bool, default: true): use video input fps for output. If no video or not set, uses .I fps. Ignored in player mode .br vfr (bool, default: false): only emit frames when changes are detected. Always true in player mode and when filter is dynamically loaded .br -dur (dbl, default: 0, updatable): duration of generation. Mostly used when no video input is present. Negative values mean number of frames, positive values duration in second, 0 stops as soon as all streams are done. +dur (dbl, default: 0, updatable): duration of generation. Mostly used when no video input is present. Negative values mean number of frames, positive values duration in second, 0 stops as soon as all streams are done .br fsize (bool, default: false, updatable): force the scene to resize to the biggest bitmap available if no size info is given in the BIFS configuration .br mode2d (enum, default: defer, updatable): specify whether immediate drawing should be used or not .br -* immediate: the screen is completely redrawn at each frame (always on if passthrough mode is detected). +* immediate: the screen is completely redrawn at each frame (always on if passthrough mode is detected) .br -* defer: object positioning is tracked from frame to frame and dirty rectangles info is collected in order to redraw the minimal amount of the screen buffer. +* defer: object positioning is tracked from frame to frame and dirty rectangles info is collected in order to redraw the minimal amount of the screen buffer .br * debug: only renders changed areas, reseting other areas .br -Whether the setting is applied or not depends on the graphics module and player mode. +Whether the setting is applied or not depends on the graphics module and player mode .br .br @@ -462,13 +466,13 @@ .br max_vspeed (dbl, default: 4.0, updatable): move to i-frame only decoding if playback speed is greater than sepcified value .br -buf (uint, default: 3000, updatable): playout buffer in ms. Overriden by BufferLenth property of input pid +buf (uint, default: 3000, updatable): playout buffer in ms. overridden by BufferLenth property of input pid .br -rbuf (uint, default: 1000, updatable): rebuffer trigger in ms. Overriden by RebufferLenth property of input pid +rbuf (uint, default: 1000, updatable): rebuffer trigger in ms. overridden by RebufferLenth property of input pid .br -mbuf (uint, default: 3000, updatable): max buffer in ms (must be greater than playout buffer). Overriden by BufferMaxOccupancy property of input pid +mbuf (uint, default: 3000, updatable): max buffer in ms (must be greater than playout buffer). overridden by BufferMaxOccupancy property of input pid .br -ntpsync (uint, default: 0, updatable): ntp resync threshold (drops frame if their NTP is more than the given threshold above local ntp), 0 disables ntp drop +ntpsync (uint, default: 0, updatable): ntp resync threshold in ms (drops frame if their NTP is more than the given threshold above local ntp), 0 disables ntp drop .br nojs (bool, default: false): disable javascript .br @@ -476,17 +480,17 @@ .br ogl (enum, default: auto, updatable): specify 2D rendering mode .br -* auto: automatically decides betwwen on, off and hybrid based on content. +* auto: automatically decides betwwen on, off and hybrid based on content .br -* off: disables OpenGL - 3D will not be rendered. +* off: disables OpenGL; 3D will not be rendered .br -* on: uses OpenGL for all graphics - this will involve polygon tesselation and 2D graphics will not look as nice as 2D mode. +* on: uses OpenGL for all graphics; this will involve polygon tesselation and 2D graphics will not look as nice as 2D mode .br -* hybrid: the compositor performs software drawing of 2D graphics with no textures (better quality) and uses OpenGL for all 2D objects with textures and 3D objects. +* hybrid: the compositor performs software drawing of 2D graphics with no textures (better quality) and uses OpenGL for all 2D objects with textures and 3D objects .br .br -pbo (bool, default: false, updatable): enable PixelBufferObjects to push YUV textures to GPU in OpenGL Mode. This may slightly increase the performances of the playback. +pbo (bool, default: false, updatable): enable PixelBufferObjects to push YUV textures to GPU in OpenGL Mode. This may slightly increase the performances of the playback .br nav (enum, default: none, updatable): override the default navigation mode of MPEG-4/VRML (Walk) and X3D (Examine) .br @@ -518,7 +522,7 @@ .br * no: video is resized to a power of 2 texture when mapping to a shape .br -paa (bool, default: false, updatable): indicate whether polygon antialiasing should be used in full antialiasing mode. If not set, only lines and points antialiasing are used. +paa (bool, default: false, updatable): indicate whether polygon antialiasing should be used in full antialiasing mode. If not set, only lines and points antialiasing are used .br bcull (enum, default: on, updatable): indicate whether backface culling shall be disable or not .br @@ -530,7 +534,7 @@ .br .br -wire (enum, default: none, updatable): wireframe mode. +wire (enum, default: none, updatable): wireframe mode .br * none: objects are drawn as solid .br @@ -568,25 +572,25 @@ .br nbviews (uint, default: 0, updatable): number of views to use in stereo mode .br -stereo (enum, default: none, updatable): stereo output type. If your graphic card does not support OpenGL shaders, only top and side modes will be available. +stereo (enum, default: none, updatable): stereo output type. If your graphic card does not support OpenGL shaders, only top and side modes will be available .br -* side: images are displayed side by side from left to right. +* side: images are displayed side by side from left to right .br -* top: images are displayed from top (laft view) to bottom (right view). +* top: images are displayed from top (laft view) to bottom (right view) .br -* hmd: same as side except that view aspect ratio is not changed. +* hmd: same as side except that view aspect ratio is not changed .br -* ana: standard color anaglyph (red for left view, green and blue for right view) is used (forces views=2). +* ana: standard color anaglyph (red for left view, green and blue for right view) is used (forces views=2) .br -* cols: images are interleaved by columns, left view on even columns and left view on odd columns (forces views=2). +* cols: images are interleaved by columns, left view on even columns and left view on odd columns (forces views=2) .br -* rows: images are interleaved by columns, left view on even rows and left view on odd rows (forces views=2). +* rows: images are interleaved by columns, left view on even rows and left view on odd rows (forces views=2) .br -* spv5: images are interleaved by for SpatialView 5 views display, fullscreen mode (forces views=5). +* spv5: images are interleaved by for SpatialView 5 views display, fullscreen mode (forces views=5) .br -* alio8: images are interleaved by for Alioscopy 8 views displays, fullscreen mode (forces views=8). +* alio8: images are interleaved by for Alioscopy 8 views displays, fullscreen mode (forces views=8) .br -* custom: images are interleaved according to the shader file indicated in -mvshader. The shader is exposed each view as uniform sampler2D gfViewX, where X is the view number starting from the left +* custom: images are interleaved according to the shader file indicated in .I mvshader. The shader is exposed each view as uniform sampler2D gfViewX, where X is the view number starting from the left .br .br @@ -658,7 +662,7 @@ .br noaudio (bool, default: false): disable audio output .br -opfmt (pfmt, default: none, minmax: none,yuv420,yuv420_10,yuv422,yuv422_10,yuv444,yuv444_10,uyvy,vyuy,yuyv,yvyu,nv12,nv21,nv1l,nv2l,yuva,yuvd,yuv444a,grey,algr,gral,rgb4,rgb5,rgb6,rgba,argb,bgra,abgr,rgb,bgr,xrgb,rgbx,xbgr,bgrx,rgbd,rgbds,rgbs,rgbas): pixel format to use for output. Ignored in -player mode +opfmt (pfmt, default: none, minmax: none,yuv420,yuv420_10,yuv422,yuv422_10,yuv444,yuv444_10,uyvy,vyuy,yuyv,yvyu,nv12,nv21,nv1l,nv2l,yuva,yuvd,yuv444a,grey,algr,gral,rgb4,rgb5,rgb6,rgba,argb,bgra,abgr,rgb,bgr,xrgb,rgbx,xbgr,bgrx,rgbd,rgbds,rgbs,rgbas): pixel format to use for output. Ignored in .I player mode .br drv (enum, default: auto): indicate if graphics driver should be used. Ignored in player mode .br @@ -707,7 +711,7 @@ .SH Scalable Tracks .LP .br -When scalable tracks are present in a file, the reader can operate in 3 modes using -smode option: +When scalable tracks are present in a file, the reader can operate in 3 modes using .I smode option: .br * smode=single: resolves all extractors to extract a single bitstream from a scalable set. The highest level is used .br @@ -754,7 +758,7 @@ .br frame_size (uint, default: 1024): frame size for raw audio samples (dispatches frame_size samples per packet) .br -expart (bool, default: true): expose cover art as a dedicated video pid +expart (bool, default: false): expose cover art as a dedicated video pid .br sigfrag (bool, default: false): signal fragment and segment boundaries of source on output packets .br @@ -819,11 +823,11 @@ .br This filter dispatch raw blocks from input file into a filter chain. .br -Block size can be adjusted using -block_size. +Block size can be adjusted using .I block_size. .br -Content format can be forced through -mime and file extension can be changed through -ext. +Content format can be forced through .I mime and file extension can be changed through .I ext. .br -Note: Unless disabled at session level (see -no-probe ), file extensions are usually ignored and format probing is done on the first data block. +Note: Unless disabled at session level (see .I -no-probe ), file extensions are usually ignored and format probing is done on the first data block. .br The special file name null is used for creating a file with no data, needed by some filters such as dasher. .br @@ -883,11 +887,11 @@ .br This filter dispatch raw blocks from a remote HTTP resource into a filter chain. .br -Block size can be adjusted using -block_size, and disk caching policies can be adjusted. +Block size can be adjusted using .I block_size, and disk caching policies can be adjusted. .br -Content format can be forced through -mime and file extension can be changed through -ext. +Content format can be forced through .I mime and file extension can be changed through .I ext. .br -Note: Unless disabled at session level (see -no-probe ), file extensions are usually ignored and format probing is done on the first data block. +Note: Unless disabled at session level (see .I -no-probe ), file extensions are usually ignored and format probing is done on the first data block. .br .br @@ -902,7 +906,7 @@ .br * disk: cache to disk, discard once session is no longer used .br -* disk: cache to disk and keep +* keep: cache to disk and keep .br * mem: stores to memory, discard once session is no longer used .br @@ -1256,7 +1260,7 @@ .br .br -Data format can be specified by setting either -ext or -mime options. If not set, the format will be guessed by probing the first data packet +Data format can be specified by setting either .I ext or .I mime options. If not set, the format will be guessed by probing the first data packet .br .br @@ -1316,7 +1320,7 @@ .br .br -Experimental DVB support for linux, requires a channel config file through -chcfg +Experimental DVB support for linux, requires a channel config file through .I chcfg .br .br @@ -1434,7 +1438,7 @@ .br auto_switch (uint, default: 0): switch quality every N segments, disabled if 0 .br -store (enum, default: mem): enable file caching +segstore (enum, default: mem): enable file caching .br * mem: all files are stored in memory, no disk IO .br @@ -1494,7 +1498,7 @@ .br screen_res (bool, default: yes): use screen resolution in selection phase .br -timeshift (uint, default: 0): set initial timshift in ms (if >0) or in %% of timeshift buffer (if <0) +init_timeshift (uint, default: 0): set initial timshift in ms (if >0) or in per-cent of timeshift buffer (if <0) .br tile_mode (enum, default: none): tile adaptation mode .br @@ -1518,7 +1522,7 @@ .br .br -tiles_rate (uint, default: 100): indicate the amount of bandwidth to use at each quality level. The rate is recursively applied at each level, e.g. if 50%, Level1 gets 50%, level2 gets 25%, ... If 100, automatic rate allocation will be done by maximizing the quality in order of priority. If 0, bitstream will not be smoothed across tiles/qualities, and concurrency may happen between different media. +tiles_rate (uint, default: 100): indicate the amount of bandwidth to use at each quality level. The rate is recursively applied at each level, e.g. if 50%, Level1 gets 50%, level2 gets 25%, ... If 100, automatic rate allocation will be done by maximizing the quality in order of priority. If 0, bitstream will not be smoothed across tiles/qualities, and concurrency may happen between different media .br delay40X (uint, default: 500): delay in millisconds to wait between two 40X on the same segment .br @@ -1538,6 +1542,8 @@ .br split_as (bool, default: no): separate all qualities into different adaptation sets and stream all qualities .br +noseek (bool, default: no): disable seeking of initial segment(s) in dynamic mode (useful when UTC clocks do not match) +.br lowlat (enum, default: early): segment scheduling policy in low latency mode .br * no: disable low latency @@ -1561,7 +1567,7 @@ .br The syntax is available at https://wiki.gpac.io/Common-Encryption .br -The file can be set per PID using the property DecryptInfo (highest priority), CryptInfo (lower priority) or set at the filter level using -cfile (lowest priority). +The file can be set per PID using the property DecryptInfo (highest priority), CryptInfo (lower priority) or set at the filter level using .I cfile (lowest priority). .br When the file is set per PID, the first CryptInfo with the same ID is used, otherwise the first CryptInfo is used. .br @@ -1585,11 +1591,11 @@ .br The syntax is available at https://wiki.gpac.io/Common-Encryption .br -The DRM config file can be set per PID using the property CryptInfo, or set at the filter level using -cfile. +The DRM config file can be set per PID using the property CryptInfo, or set at the filter level using .I cfile. .br When the DRM config file is set per PID, the first CrypTrack in the DRM config file with the same ID is used, otherwise the first CrypTrack is used. .br -If no DRM config file is defined for a given PID, this PID will not be encrypted, or an error will be thrown if -allc is specified. +If no DRM config file is defined for a given PID, this PID will not be encrypted, or an error will be thrown if .I allc is specified. .br .br @@ -1620,7 +1626,7 @@ .br By default all input PIDs with ItemID property set are muxed as items, otherwise they are muxed as tracks. .br -To prevent source items to be muxed as items, use -itemid option from ISOBMF demuxer. +To prevent source items to be muxed as items, use .I -itemid option from ISOBMF demuxer. .br Example .br @@ -1643,11 +1649,11 @@ .SH Storage .LP .br -The -store option allows controling if the file is fragmented ot not, and when not fragmented, how interleaving is done. For cases where disk requirements are tight and fragmentation cannot be used, it is recommended to use either flat or fstart modes. +The .I store option allows controling if the file is fragmented ot not, and when not fragmented, how interleaving is done. For cases where disk requirements are tight and fragmentation cannot be used, it is recommended to use either flat or fstart modes. .br .br -The -vodcache option allows controling how DASH onDemand segments are generated: +The .I vodcache option allows controling how DASH onDemand segments are generated: .br - If set to on, file data is stored to a temporary file on disk and flushed upon completion, no padding is present. .br @@ -1664,7 +1670,7 @@ .br Custom boxes can be specified as box patches: .br -For movie-level patch, the -boxpatch option of the filter should be used. +For movie-level patch, the .I boxpatch option of the filter should be used. .br Per PID box patch can be specified through the PID property boxpatch. .br @@ -1690,10 +1696,25 @@ .br .br +.SH Tagging +.LP +.br +When tagging is enabled, the filter will watch the property CoverArt and all custom properties on incoming pid. +.br +The built-in tag names are album, artist, comment, complilation, composer, year, disk, tool, genre, contentgroup, title, tempo, track, tracknum, writer, encoder, album_artist, gapless, conductor. +.br +Other tag class may be specified using tag_NAME property names, and will be added if .I tags is set to all using: +.br +- NAME as a box 4CC if NAME is four characters long +.br +- the CRC32 of the NAME as a box 4CC if NAME is not four characters long +.br + +.br .SH Notes .LP .br -The filter watches the property FileNumber on incoming packets to create new files or new segments in DASH mode. +The filter watches the property FileNumber on incoming packets to create new files or new segments in DASH mode. .br .br @@ -1706,7 +1727,7 @@ .br dref (bool, default: false): only references data from source file - not compatible with all media sources .br -ctmode (enum, default: edit): set composition offset mode for video tracks. +ctmode (enum, default: edit): set composition offset mode for video tracks .br * edit: uses edit lists to shift first frame to presentation time 0 .br @@ -1722,9 +1743,9 @@ .br importer (bool, default: false): compatibility with old importer, displays import progress .br -pack_nal (bool, default: false): repack NALU size length to minimum possible size for AVC/HEVC/... +pack_nal (bool, default: false): repack NALU size length to minimum possible size for NALU-based video (AVC/HEVC/...) .br -xps_inband (enum, default: no): use inband (in sample data) param set for AVC/HEVC/... +xps_inband (enum, default: no): use inband (in sample data) param set for NALU-based video (AVC/HEVC/...) .br * no: paramater sets are not inband, several sample descriptions might be created .br @@ -1738,7 +1759,7 @@ .br store (enum, default: inter): file storage mode .br -* inter: perform precise interleave of the file using -cdur (requires temporary storage of all media) +* inter: perform precise interleave of the file using .I cdur (requires temporary storage of all media) .br * flat: write samples as they arrive and moov at end (fastest mode) .br @@ -1756,7 +1777,7 @@ .br * 0: no specific interleaving but moov first .br -* negative: defaults to 1.0 unless overriden by storage profile +* negative: defaults to 1.0 unless overridden by storage profile .br moovts (sint, default: 600): timescale to use for movie. A negative value picks the media timescale of the first track added .br @@ -1902,6 +1923,20 @@ .br deps (bool, default: true): add samples dependencies information .br +mfra (bool, default: false): enable movie fragment random access when fragmenting (ignored when dashing) +.br +forcesync (bool, default: false): force all SAP types to be considered sync samples (might produce non-conformant files) +.br +tags (enum, default: strict): tag injection mode +.br +* none: do not inject tags +.br +* strict: only inject recognized itunes tags +.br +* all: inject all possible tags +.br + +.br .br .SH rfqcp @@ -2040,7 +2075,15 @@ .br explicit (bool, default: false): use explicit layered (SVC/LHVC) import .br -strict_poc (bool, default: false): delay frame output of an entire GOP to ensure CTS info is correct when POC suddenly changes +strict_poc (enum, default: off): delay frame output of an entire GOP to ensure CTS info is correct when POC suddenly changes +.br +* off: disable GOP buffering +.br +* on: enable GOP buffering, assuming no error in POC +.br +* error: enable GOP buffering and try to detect lost frames +.br + .br nosei (bool, default: false): remove all sei messages .br @@ -2344,7 +2387,7 @@ .br It can work as a null sink when its destination is null, dropping all input packets. In this case it accepts ANY type of input pid, not just file ones. .br -In regular mode, the filter only accept pid of type file. It will dump to file incomming packets (stream type file), starting a new file for each packet having a frame_start flag set, unless operating in -cat mode. +In regular mode, the filter only accept pid of type file. It will dump to file incomming packets (stream type file), starting a new file for each packet having a frame_start flag set, unless operating in .I cat mode. .br The ouput file name can use gpac templating mechanism, see gpac -h doc.The filter watches the property FileNumber on incoming packets to create new files. .br @@ -2451,7 +2494,7 @@ .SH SAP filtering .LP .br -The filter can remove packets based on their SAP types using -saps option. +The filter can remove packets based on their SAP types using .I saps option. .br For example, this can be used to extract only the key frame (SAP 1,2,3) of a video to create a trick mode version. .br @@ -2460,7 +2503,7 @@ .SH Frame filtering .LP .br -This filter can keep only specific Access Units of the source using -frames option. +This filter can keep only specific Access Units of the source using .I frames option. .br For example, this can be used to extract only specific key frame of a video to create a HEIF collection. .br @@ -2469,7 +2512,7 @@ .SH Frame decoding .LP .br -This filter can force input media streams to be decoded using the -raw option. +This filter can force input media streams to be decoded using the .I raw option. .br Example .br @@ -2495,7 +2538,7 @@ .SH Range extraction .LP .br -The filter can perform time range extraction of the source using -xs and -xe options. +The filter can perform time range extraction of the source using .I xs and .I xe options. .br The formats allowed for times specifiers are: .br @@ -2523,7 +2566,7 @@ .br .br -It is possible to signal range boundaries in output packets using -splitrange. +It is possible to signal range boundaries in output packets using .I splitrange. .br This will expose on the first packet of each range in each pid the following properties: .br @@ -2548,9 +2591,9 @@ .SH Other split actions .LP .br -The filter can perform splitting of the source using -xs option. +The filter can perform splitting of the source using .I xs option. .br -The additional formats allowed for -xs option are: +The additional formats allowed for .I xs option are: .br * 'SAP': split source at each SAP/RAP .br @@ -2562,7 +2605,7 @@ .br .br -Note: In these modes, -splitrange and -xadjust are implicitly set. +Note: In these modes, .I splitrange and .I xadjust are implicitly set. .br .br @@ -2653,7 +2696,7 @@ .br .br -split (bool, default: false): force one file per decoded frame. +split (bool, default: false): force one file per decoded frame .br frame (bool, default: false): force single frame dump with no rewrite. In this mode, all codecids are supported .br @@ -2845,6 +2888,8 @@ .br noraw (bool, default: false): disable raw output in AVI, only compressed ones allowed .br +opendml_size (luint, default: 0): force opendml format when chunks are larger than this amount (0 means 1.9Gb max size in each riff chunk) +.br .br .SH aout @@ -2938,7 +2983,7 @@ .br The window is created unless a window handle (HWND, xWindow, etc) is indicated in the config file ( [Temp]OSWnd=ptr). .br -The output uses GPAC video output module indicated in -drv option or in the config file (see GPAC core help). +The output uses GPAC video output module indicated in .I drv option or in the config file (see GPAC core help). .br The video output module can be further configured (see GPAC core help). .br @@ -2999,9 +3044,9 @@ .br buffer (uint, default: 100): set buffer in ms .br -dumpframes (uintl): ordered list of frames to dump, 1 being first frame - see filter help. Special value 0 means dump all frames. +dumpframes (uintl): ordered list of frames to dump, 1 being first frame - see filter help. Special value 0 means dump all frames .br -out (str, default: dump): radical of dump frame filenames. If no extension is provided, frames are exported as $OUT_%d.PFMT. +out (str, default: dump): radical of dump frame filenames. If no extension is provided, frames are exported as $OUT_%d.PFMT .br .br @@ -3023,7 +3068,7 @@ .br copy (bool, default: false): copy the source pixels. By default the filter will try to forward crop frames by adjusting offsets and strides of the source if possible (window contained in frame) .br -round (enum, default: up): adjust dimension to be a multiple of 2. +round (enum, default: up): adjust dimension to be a multiple of 2 .br * up: up rounding .br @@ -3210,11 +3255,11 @@ .br .br -The resulting file list can be sorted using -fsort. +The resulting file list can be sorted using .I fsort. .br If the sort mode is datex and source files are images or single frame files, the following applies: .br -- options -floop, -revert and -dur are ignored +- options .I floop, .I revert and .I dur are ignored .br - the files are sorted by modification time .br @@ -3235,15 +3280,21 @@ .br The following directives, separated with space or comma, are supported: .br -* repeat=N: repeats N times the content (hence played N+1) +* repeat=N: repeats N times the content (hence played N+1). +.br +* start=T: tries to play the file from start time T seconds (double format only). This may not work with some files/formats not supporting seeking. +.br +* stop=T: stops source playback after T seconds (double format only). This works on any source (implemented independently from seek support). .br -* start=T: tries to play the file from start time T seconds (double format only) +* cat: specifies that the following entry should be concatenated to the previous source rather than opening a new source. This can optionnally specify a byte range if desired, otherwise the full file is concatenated. .br -Warning: This may not work with some files/formats not supporting seeking +* srange=T: when cat is set, indicates the start T (64 bit decimal, default 0) of the byte range from the next entry to concatenate. .br -* stop=T: stops source playback after T seconds (double format only) +* send=T: when cat is set, indicates the end T (64 bit decimal, default 0) of the byte range from the next entry to concatenate. .br -This works on any source (implemented independently from seek support). + +.br +Note: When sources are ISOBMFF files or segments on local storage or GF_FileIO objects, the concatenation will be automatically detected. .br .br @@ -3284,6 +3335,8 @@ .br timescale (uint, default: 0): force output timescale on all pids. 0 uses the timescale of the first pid found .br +ka (uint, default: 0): keep playlist alive (disable loop), waiting the for a new input to be added or #end to end playlist. The value specify the refresh rate in ms +.br fsort (enum, default: no): sort list of files .br * no: no sorting, use default directory enumeration of OS @@ -3311,30 +3364,64 @@ .br For example, default config creates the first program with a PMT PID 100, the first stream will have a PID of 101. .br -Streams are grouped in programs based on input PID property ServiceID if present. If absent, stream will go in the program with service ID as indicated by -sid option. +Streams are grouped in programs based on input PID property ServiceID if present. If absent, stream will go in the program with service ID as indicated by .I sid option. +.br +- .I name option is overridden by input PID property ServiceName. .br --name option is overriden by input PID property ServiceName. +- .I provider option is overridden by input PID property ServiceProvider. .br --provider option is overriden by input PID property ServiceProvider. +- .I pcr_offset option is overridden by input PID property "tsmux:pcr_offset" +.br +- .I first_pts option is overridden by input PID property "tsmux:force_pts" +.br +- .I temi option is overridden by input PID property "tsmux:temi" .br .br .SH Time and External Media Information (TEMI) .LP .br -The -temi option allows specifying a list of URLs or timeline IDs to insert in the program. +The .I temi option allows specifying a list of URLs or timeline IDs to insert in streams of a program. +.br +One or more TEMI timeline can be specified per PID. +.br +The syntax is a comma-separated list of one or more TEMI description. +.br +Each TEMI description is formatted as ID_OR_URL or #OPT1[#OPT2]#ID_OR_URL. Options are: +.br +* S`N`: gives number N indicating the target serviceID +.br +* T`N`: set timescale to use (default: PID timescale) +.br +* D`N`: set delay in ms between two TEMI url descriptors (default 1000) +.br +* O`N`: set offset (max 64 bits) to add to TEMI timecodes (default 0). If timescale is not specified, offset value is in ms, otherwise in timescale units. +.br +* I`N`: set initial value (max 64 bits) of TEMI timecodes. If not set, initial value will match first packet CTS. If timescale is not specified, value is in PID timescale units, otherwise in specified timescale units. .br -Only a single TEMI timeline can be specified per PID. +* P`N`: indicate target PID in program. Possible values are .br -The syntax is a comma-separated list of one or more TEMI description, each of them separated by '#' + * `V`: only insert for video streams. .br -Each TEMI description is formated as #ServiceID#ID_OR_URL, with: + * `A`: only insert for audio streams. .br -* ServiceID: optional, number indicating the target serviceID + * `T`: only insert for text streams. .br -* ID_OR_URL: If numbern indicates the TEMI ID to use for external timeline. Otherwise, gives the URL to insert + * N: only insert for stream with index N (0-based) in the program. .br -Each comma-separated description designs a stream index in the target service. +* L`N`: set 64bit timecode signaling. Possible values are: +.br + * `A`: automatic switch between 32 and 64 bit depending on timecode value (default if not specified). +.br + * `Y`: use 64 bit signaling only. +.br + * `N`: use 32 bit signaling only and wrap around timecode value. +.br +* N: insert NTP timestamp in TEMI timeline descriptor +.br +* ID_OR_URL: If number, indicates the TEMI ID to use for external timeline. Otherwise, gives the URL to insert +.br + .br Example .br @@ -3342,11 +3429,11 @@ .br .br -Iinserts a TEMI URL+timecode in the first stream of all programs. +Inserts a TEMI URL+timecode in the each stream of each program. .br Example .br -temi="url,4" +temi="#P0#url,#P1#4" .br .br @@ -3354,28 +3441,38 @@ .br Example .br -temi="#20#4,#10#URL" +temi="#P0#2,#P0#url,#P1#4" .br .br -Inserts an external TEMI with ID 4 in the first stream of program with ServiceID 20 and a TEMI URL to the second stream of program with ServiceID 10. +Inserts a TEMI with ID 2 and a TEMI URL+timecode in the first stream of all programs, and an external TEMI with ID 4 in the second stream of all programs. .br Example .br -temi="#20#4,,#10#URL" +temi="#S20#4,#S10#URL" .br .br -Inserts an external TEMI with ID 4 in the first stream of program with ServiceID 20 and a TEMI URL to the third stream of program with ServiceID 10 (and nothing on second stream). +Inserts an external TEMI with ID 4 in the each stream of program with ServiceID 20 and a TEMI URL in each stream of program with ServiceID 10. +.br +Example +.br +temi="#N#D500#PV#T30000#4" .br .br +Inserts an external TEMI with ID 4 and timescale 30000, NTP injection and carousel of 500 ms in the video stream of all programs. +.br + +.br +Warning: multipliers (k,m,g) are not supported in TEMI options. +.br .SH Notes .LP .br -In DASH mode, the PCR is always initialized at 0, and -flush_rap is automatically set. +In DASH mode, the PCR is always initialized at 0, and .I flush_rap is automatically set. .br -The filter watches the property FileNumber on incoming packets to create new files or new segments in DASH mode. +The filter watches the property FileNumber on incoming packets to create new files or new segments in DASH mode. .br .br @@ -3394,9 +3491,11 @@ .br pat_rate (uint, default: 200): interval between PAT in ms .br -pcr_offset (uint, default: -1): offset all timestamps from PCR by V, in 90kHz. Default value is computed based on input media +first_pts (luint, default: 0): force PTS value of first packet, in 90kHz .br -mpeg4 (enum, default: none): force usage of MPEG-4 signaling (IOD and SL Config). +pcr_offset (luint, default: -1): offset all timestamps from PCR by V, in 90kHz. Default value is computed based on input media +.br +mpeg4 (enum, default: none): force usage of MPEG-4 signaling (IOD and SL Config) .br * none: disables 4on2 .br @@ -3410,15 +3509,15 @@ .br disc (bool, default: false): set the discontinuity marker for the first packet of each stream .br -repeat_rate (uint, default: 0): interval in ms between two carousel send for MPEG-4 systems. Is overriden by carousel duration PID property if defined +repeat_rate (uint, default: 0): interval in ms between two carousel send for MPEG-4 systems. Is overridden by carousel duration PID property if defined .br -repeat_img (uint, default: 0): interval in ms between resending (as PES) of single-image streams. If 0, image data is sent once only +repeat_img (uint, default: 0): interval in ms between re-sending (as PES) of single-image streams. If 0, image data is sent once only .br max_pcr (uint, default: 100): set max interval in ms between 2 PCR .br nb_pack (uint, default: 4): pack N TS packets in output packets .br -pes_pack (enum, default: audio): set AU to PES packing mode. +pes_pack (enum, default: audio): set AU to PES packing mode .br * audio: will pack only multiple audio AUs in a PES .br @@ -3456,12 +3555,6 @@ .br temi (str): insert TEMI time codes in adaptation field - see filter help .br -temi_delay (uint, default: 1000): set delay in ms between two TEMI url descriptors -.br -temi_offset (uint, default: 0): set offset in ms to add to TEMI timecodes -.br -temi_ntp (bool, default: false): insert NTP timestamp in TEMI timeline descriptor -.br log_freq (uint, default: 500): delay between logs for realtime mux .br latm (bool, default: false): use LATM AAC encapsulation instead of regular ADTS @@ -3488,7 +3581,7 @@ .br - ISOBMFF, MPEG-2 TS, MKV and raw bitstream segment formats .br -- override of profiles and levels in manifest for common codecs (aac, hevc, vp9, av1, aac) +- override of profiles and levels in manifest for codecs .br - most MPEG-DASH profiles .br @@ -3498,9 +3591,9 @@ .br .br -Warning: the filter does not perform any real-time regulation, even in dynamic offering mode. +The filter does perform per-segment real-time regulation using .I sreg. .br -If your inputs are not real-time, insert a reframer before to perform real-time regulation. +If you need per-frame real-time regulation on non-real-time inputs, insert a reframer before to perform real-time regulation. .br Example .br @@ -3550,6 +3643,8 @@ .br * $Init=NAME$: replaced by NAME for init segment, ignored otherwise .br +* $XInit=NAME$: complete replace by NAME for init segment, ignored otherwise +.br * $Index=NAME$: replaced by NAME for index segments, ignored otherwise .br * $Path=PATH$: replaced by PATH when creating segments, ignored otherwise @@ -3564,7 +3659,7 @@ .br .P .B -PID assignment +PID assignment and configuration .br To assign PIDs into periods and adaptation sets and configure the session, the segmenter looks for the following properties on each input pid: .br @@ -3586,13 +3681,13 @@ .br * BUrl: overrides segmenter [-base] with a set of BaseURLs to use for the pid (per representation) .br -* Template: overrides segmenter -template for this PID +* Template: overrides segmenter .I template for this PID .br * DashDur: overrides segmenter segment duration for this PID .br * StartNumber: sets the start number for the first segment in the PID, default is 1 .br -* Non-dash properties: Bitrate, SAR, Language, Width, Height, SampleRate, NumChannels, Language, ID, DependencyID, FPS, Interlaced. These properties are used to setup each representation and can be overriden on input PIDs using the general PID property settings (cf global help). +* Non-dash properties: Bitrate, SAR, Language, Width, Height, SampleRate, NumChannels, Language, ID, DependencyID, FPS, Interlaced, Codec. These properties are used to setup each representation and can be overridden on input PIDs using the general PID property settings (cf global help). .br .br @@ -3698,7 +3793,7 @@ .br The default behavior of the segmenter is to estimate the theoretical start time of each segment based on target segment duration, and start a new segment when a packet with SAP type 1,2,3 or 4 with time greater than the theoretical time is found. .br -This behavior can be changed to find the best SAP packet around a segment theoretical boundary using -sbound: +This behavior can be changed to find the best SAP packet around a segment theoretical boundary using .I sbound: .br * closest mode: the segment will start at the closest SAP of the theoretical boundary .br @@ -3708,9 +3803,9 @@ .br The segmenter can also be configured to: .br -- completely ignore SAP when segmenting using -sap. +- completely ignore SAP when segmenting using .I sap. .br -- ignore SAP on non-video streams when segmenting using -strict_sap. +- ignore SAP on non-video streams when segmenting using .I strict_sap. .br .br @@ -3748,18 +3843,68 @@ .B Manifest Generation only mode .br -The segmenter can try to generate manifests from already fragmented ISOBMFF inputs using -sigfrag. +The segmenter can be used to generate manifests from already fragmented ISOBMFF inputs using .I sigfrag. .br In this case, segment boundaries are attached to each packet starting a segment and used to drive the segmentation. .br -This should only be used with single-track ISOBMFF sources. If onDemand -profile is requested, sources have to be formatted as a DASH self-initializing media segment with the proper sidx. +This can be used with single-track ISOBMFF sources, either single file or multi file. +.br +For single file source: +.br +- if onDemand .I profile is requested, sources have to be formatted as a DASH self-initializing media segment with the proper sidx. .br -This mode automatically disables templates and forces -sseg for all profiles except onDemand ones. +- templates are disabled. +.br +- .I sseg is forced for all profiles except onDemand ones. +.br +For multi files source: +.br +- input shall be a playlist containing the initial file followed by the ordered list of segments. +.br +- if no .I template is provided, the full or main .I profile will be used +.br +* if [-template]() is provided, it shall be correct: the filter will not try to guess one from the input file names and will not validate it either. +.br + .br The manifest generation-only mode supports both MPD and HLS generation. .br .br +Example +.br +-i ondemand_src.mp4 -o dash.mpd:sigfrag:profile=onDemand +.br + +.br +This will generate a DASH manifest for onDemand Profile based on the input file. +.br +Example +.br +-i ondemand_src.mp4 -o dash.m3u8:sigfrag +.br + +.br +This will generate a HLS manifest based on the input file. +.br +Example +.br +-i seglist.txt -o dash.mpd:sigfrag +.br + +.br +This will generate a DASH manifest in Main Profile based on the input files. +.br +Example +.br +-i seglist.txt:Template=$XInit=init$$q1/$Number$ -o dash.mpd:sigfrag:profile=live +.br + +.br +This will generate a DASH manifest in live Profile based on the input files. The input file will contain init.mp4, q1/1.m4s, q1/2.m4s... +.br + +.br .P .B Muxer development considerations @@ -3774,7 +3919,7 @@ .br * IDXName: gives the optional index name (if not present, index shall be in the same file as dash segment). Only used for MPEG-2 TS for now .br - * EODS: property is set on packets with no payload and no timestamp to signal the end of a DASH segment. This is only used when stoping/resuming the segmentation process, in order to flush segments without dispatching an EOS (see -subdur ) + * EODS: property is set on packets with no payload and no timestamp to signal the end of a DASH segment. This is only used when stoping/resuming the segmentation process, in order to flush segments without dispatching an EOS (see .I subdur ) .br - for each segment done, send a downstream event on the first connected PID signaling the size of the segment and the size of its index if any .br @@ -3784,7 +3929,7 @@ .br * noinit: disables output of init segment for the muxer (used to handle bitstream switching with single init in DASH) .br - * frag: indicates muxer shall used fragmented format (used for ISOBMFF mostly) + * frag: indicates muxer shall use fragmented format (used for ISOBMFF mostly) .br * subs_sidx=0: indicates an SIDX shall be generated - only added if not already specified by user .br @@ -3807,7 +3952,7 @@ .SH Options (expert): .LP .br -segdur (dbl, default: 1.0): target segment duration in seconds +segdur (dbl, default: 0.0): target segment duration in seconds. A value less than or equal to 0 means to 1.0 second .br tpl (bool, default: true): use template mode (multiple segment, template URLs) .br @@ -3839,7 +3984,7 @@ .br * yes: inserts NTP at each segment start .br -* keep: leaves input packet NTP untouched. +* keep: leaves input packet NTP untouched .br .br @@ -3847,8 +3992,6 @@ .br m2ts (bool, default: false): generate MPEG-2 TS output .br -forcep (bool, default: false): force profile string for avc/hevc/aac -.br bs_switch (enum, default: def): bitstream switching mode (single init segment) .br * def: resolves to off for onDemand and inband for live @@ -3865,16 +4008,6 @@ .br .br -avcp (str): profile to use for AVC|H264 if no profile could be found. If forcep is set, enforces this profile -.br -hvcp (str): profile to use for HEVC if no profile could be found. If forcep is set, enforces this profile -.br -aacp (str): profile to use for AAC if no profile could be found. If forcep is set, enforces this profile -.br -av1p (str): profile to use for AV1 if no profile could be found. If forcep is set, enforces this profile -.br -vpxp (str): profile to use for VP8/9 if no profile could be found. If forcep is set, enforces this profile -.br template (str): template string to use to generate segment name - see filter help .br segext (str): file extension to use for segments @@ -3899,7 +4032,7 @@ .br asto (dbl, default: 0): availabilityStartTimeOffset to use in seconds. A negative value simply increases the AST, a positive value sets the ASToffset to representations .br -profile (enum, default: auto): target DASH profile. This will set default option values to ensure conformance to the desired profile. For MPEG-2 TS, only main and live are used, others default to main. +profile (enum, default: auto): target DASH profile. This will set default option values to ensure conformance to the desired profile. For MPEG-2 TS, only main and live are used, others default to main .br * auto: turns profile to live for dynamic and full for non-dynamic .br @@ -3973,7 +4106,7 @@ .br tsb (dbl, default: 30): time-shift buffer depth in seconds. A negative value means infinity .br -subdur (dbl, default: 0): maximum duration of the input file to be segmented. This does not change the segment duration, segmentation stops once segments produced exceeded the duration. +subdur (dbl, default: 0): maximum duration of the input file to be segmented. This does not change the segment duration, segmentation stops once segments produced exceeded the duration .br ast (str): set start date (as xs:date, eg YYYY-MM-DDTHH:MM:SSZ) for live mode. Default is now. !! Do not use with multiple periods, nor when DASH duration is not a multiple of GOP size !! .br @@ -3993,7 +4126,7 @@ .br * off: ignore SAP types for PID other than video, enforcing _startsWithSAP=1_ .br -* sig: same as -off but keep _startsWithSAP_ to the true SAP value +* sig: same as .I off but keep _startsWithSAP_ to the true SAP value .br * on: warn if any PID uses SAP 3 or 4 and switch to FULL profile .br @@ -4021,10 +4154,18 @@ .br reschedule (bool, default: false): reschedule sources with no period ID assigned once done (dynamic mode only) .br -sreg (bool, default: false): regulate the session when using subdur to only generate segments from the past up to live edge +sreg (bool, default: false): regulate the session +.br +- when using subdur and context, only generate segments from the past up to live edge +.br +- otherwise in dynamic mode without context, do not generate segments ahead of time .br scope_deps (bool, default: true): scope PID dependencies to be within source. If disabled, PID dependencies will be checked across all input PIDs regardless of their sources .br +utcs (str): URL to use as time server / UTCTiming source. Special value inband enables inband UTC (same as publishTime), special prefix xsd@ uses xsDateTime schemeURI rather than ISO +.br +force_flush (bool, default: false): force generating a single segment for each input. This can be usefull in batch mode when average source duration is known and used as segment duration but actual duration may sometimes be greater +.br .br .SH tileagg @@ -4056,9 +4197,9 @@ .br Warning: Input pipes cannot seek. .br -Data format of the pipe may be specified using extension (either in file name or through -ext) or MIME type through -mime. +Data format of the pipe may be specified using extension (either in file name or through .I ext) or MIME type through .I mime. .br -Note: Unless disabled at session level (see -no-probe ), file extensions are usually ignored and format probing is done on the first data block. +Note: Unless disabled at session level (see .I -no-probe ), file extensions are usually ignored and format probing is done on the first data block. .br .br @@ -4108,13 +4249,13 @@ .br .br -The filter can create the pipe if not found using -mkp. On windows hosts, this will create a pipe server. +The filter can create the pipe if not found using .I mkp. On windows hosts, this will create a pipe server. .br On non windows hosts, the created pipe will delete the pipe file upon filter destruction. .br .br -Input pipes can be setup to run forever using -ka. In this case, any potential pipe close on the writing side and end of stream will only be triggered upon session close. +Input pipes can be setup to run forever using .I ka. In this case, any potential pipe close on the writing side and end of stream will only be triggered upon session close. .br This can be useful to pipe raw streams from different process into gpac: .br @@ -4160,9 +4301,9 @@ .br The assoicated protocol scheme is pipe:// when loaded as a generic output (eg, -o pipe://URL where URL is a relative or absolute pipe name). .br -Data format of the pipe shall be specified using extension (either in filename or through -ext option) or MIME type through -mime +Data format of the pipe shall be specified using extension (either in filename or through .I ext option) or MIME type through .I mime .br -The pipe name indicated in -dst can use template mechanisms from gpac, e.g. dst=pipe_$ServiceID$ +The pipe name indicated in .I dst can use template mechanisms from gpac, e.g. dst=pipe_$ServiceID$ .br .br @@ -4184,7 +4325,7 @@ .br .br -The pipe input can create the pipe if not found using -mkp. On windows hosts, this will create a pipe server. +The pipe input can create the pipe if not found using .I mkp. On windows hosts, this will create a pipe server. .br On non windows hosts, the created pipe will delete the pipe file upon filter destruction. .br @@ -4238,13 +4379,13 @@ .br For header/tunein packets, the first 25 bytes after the header are in the clear (signature,version,IV and pattern). .br -The -IV is constant to avoid packet overhead, randomly generated if not set and sent in the initial stream header. Pattern mode can be used (cf CENC cbcs) to encrypt K block and leave N blocks in the clear. +The .I IV is constant to avoid packet overhead, randomly generated if not set and sent in the initial stream header. Pattern mode can be used (cf CENC cbcs) to encrypt K block and leave N blocks in the clear. .br .br -The header/tunein packet may get quite big when all pid properties are kept. In order to help reduce its size, the -minp option can be used: this will remove all built-in properties marked as dropable (cf property help) as well as all non built-in properties. +The header/tunein packet may get quite big when all pid properties are kept. In order to help reduce its size, the .I minp option can be used: this will remove all built-in properties marked as dropable (cf property help) as well as all non built-in properties. .br -The -skp option may also be used to specify which property to drop: +The .I skp option may also be used to specify which property to drop: .br Example .br @@ -4344,9 +4485,9 @@ .br In server mode, the filter can be instructed to keep running at the end of the stream. .br -In server mode, the default behaviour is to keep input packets when no more clients are connected; this can be adjusted though the -kp option, however there is no realtime regulation of how fast packets are droped. +In server mode, the default behaviour is to keep input packets when no more clients are connected; this can be adjusted though the .I kp option, however there is no realtime regulation of how fast packets are droped. .br -If your sources are not real time, consider adding a real-time scheduler in the chain (cf reframer filter), or set the send -rate option. +If your sources are not real time, consider adding a real-time scheduler in the chain (cf reframer filter), or set the send .I rate option. .br .br @@ -4569,7 +4710,7 @@ .SH Standalone mode .LP .br -In standalone mode, the filter does not produce any output pid and writes received files to the -odir directory. +In standalone mode, the filter does not produce any output pid and writes received files to the .I odir directory. .br Example .br @@ -4613,7 +4754,7 @@ .br ifce (str): default interface to use for multicast. If NULL, the default system interface will be used .br -cache (bool, default: true): indicate the files should populate GPAC HTTP cache - see filter help +gcache (bool, default: true): indicate the files should populate GPAC HTTP cache - see filter help .br tunein (sint, default: -2): service ID to bootstrap on. 0 means tune to no service, -1 tune all services -2 means tune on first service found .br @@ -4623,15 +4764,15 @@ .br kc (bool, default: false): keep corrupted file .br -sr (bool, default: true): skip repeated files - ignored in -cache mode +sr (bool, default: true): skip repeated files - ignored in cache mode .br -stsi (bool, default: false): define one output pid per tsi/serviceID - ignored in -cache mode, see filter help +stsi (bool, default: false): define one output pid per tsi/serviceID - ignored in cache mode, see filter help .br stats (uint, default: 1000): log statistics at the given rate in ms (0 disables stats) .br tsidbg (uint, default: 0): gather only objects with given TSI (debug) .br -max_segs (uint, default: 0): maximum number of segments to keep - ignored in -cache mode +max_segs (uint, default: 0): maximum number of segments to keep - ignored in cache mode .br odir (str): output directory for stand-alone mode - see filter help .br @@ -4653,14 +4794,14 @@ .SH SDP mode .LP .br -When the destination url is an SDP, the filter outputs an SDP on a file pid and streams RTP packets over UDP, starting from the indicated -port. +When the destination url is an SDP, the filter outputs an SDP on a file pid and streams RTP packets over UDP, starting from the indicated .I port. .br .SH Direct RTP mode .LP .br -When the destination url uses the protocol scheme rtp://IP:PORT, the filter does not output any SDP and streams a single input over RTP, using PORT indicated in the destination URL, or the first -port configured. +When the destination url uses the protocol scheme rtp://IP:PORT, the filter does not output any SDP and streams a single input over RTP, using PORT indicated in the destination URL, or the first .I port configured. .br -In this mode, it is usually needed to specify the desired format using -ext or -mime. +In this mode, it is usually needed to specify the desired format using .I ext or .I mime. .br Example .br @@ -4673,7 +4814,7 @@ .SH RTP Packets .LP .br -The RTP packets produced have a maximum payload set by the -mtu option (IP packet will be MTU + 40 bytes of IP+UDP+RTP headers). +The RTP packets produced have a maximum payload set by the .I mtu option (IP packet will be MTU + 40 bytes of IP+UDP+RTP headers). .br The real-time scheduling algorithm works as follows: .br @@ -4683,9 +4824,9 @@ .br - mapping this media time to the system clock .br -- determine the earliest packet to send next on each input pid, adding -delay if any +- determine the earliest packet to send next on each input pid, adding .I delay if any .br -- finally compare the packet mapped timestamp TS to the system clock SC. When TS - SC is less than -tt, the RTP packets for the source packet are sent +- finally compare the packet mapped timestamp TS to the system clock SC. When TS - SC is less than .I tt, the RTP packets for the source packet are sent .br .br @@ -4708,7 +4849,7 @@ .br ifce (str): default network inteface to use .br -payt (uint, default: 96, minmax: 96-127): payload type to use for dynamic configs. +payt (uint, default: 96, minmax: 96-127): payload type to use for dynamic configs .br delay (sint, default: 0): send delay for packet (negative means send earlier) .br @@ -4749,7 +4890,7 @@ .br .br -The filter can work as a simple output filter by specifying the -dst option: +The filter can work as a simple output filter by specifying the .I dst option: .br Example .br @@ -4763,11 +4904,11 @@ .br .br -In this mode, only one session is possible. It is possible to -loop the input source(s). +In this mode, only one session is possible. It is possible to .I loop the input source(s). .br .br -The filter can work as a regular RTSP server by specifying the -mounts option to indicate paths of media file to be served: +The filter can work as a regular RTSP server by specifying the .I mounts option to indicate paths of media file to be served: .br Example .br @@ -4775,7 +4916,7 @@ .br .br -In server mode, it is possible to load any source supported by gpac by setting the option -dynurl. +In server mode, it is possible to load any source supported by gpac by setting the option .I dynurl. .br The expected syntax of the dynamic RTSP URLs is rtsp://servername/?URL1[&URLN] or rtsp://servername/@URL1[@URLN] .br @@ -4789,13 +4930,13 @@ .br The server will resolve this URL in a new session containing streams from myfile.mp4 and streams from pipe mynamepipe. .br -When setting -runfor in server mode, the server will exit at the end of the last session being closed. +When setting .I runfor in server mode, the server will exit at the end of the last session being closed. .br .br -In both modes, clients can setup multicast if the -mcast option is on or mirror. +In both modes, clients can setup multicast if the .I mcast option is on or mirror. .br -When -mcast is set to mirror mode, any DESCRIBE command on a resource already delivered through a multicast session will use that multicast. +When .I mcast is set to mirror mode, any DESCRIBE command on a resource already delivered through a multicast session will use that multicast. .br Consequently, only DESCRIBE methods are processed for such sessions, other methods will return Unauthorized. .br @@ -4822,7 +4963,7 @@ .br ifce (str): default network inteface to use .br -payt (uint, default: 96, minmax: 96-127): payload type to use for dynamic configs. +payt (uint, default: 96, minmax: 96-127): payload type to use for dynamic configs .br mpeg4 (bool, default: false): send all streams using MPEG-4 generic payload format if posible .br @@ -4848,11 +4989,11 @@ .br close (bool, default: true): close RTSP connection after each request, except when RTP over RTSP is used .br -loop (bool, default: true): loop all streams in session (not always possible depending on source type) - see filter help. +loop (bool, default: true): loop all streams in session (not always possible depending on source type) - see filter help .br -dynurl (bool, default: false): allow dynamic service assembly - see filter help. +dynurl (bool, default: false): allow dynamic service assembly - see filter help .br -mcast (enum, default: off): control multicast setup of a session. +mcast (enum, default: off): control multicast setup of a session .br * off: clients are never allowed to create a multicast .br @@ -4887,7 +5028,7 @@ .br The server currently handles GET, HEAD, PUT, POST, DELETE methods. .br -Single or multiple byte ranges are supported for both GET and PUT/POST methods. +Single or multiple byte ranges are supported for both GET and PUT/POST methods, in all server modes. .br - for GET, the resulting body is a single-part body formed by the concatenated byte ranges as requested (no overlap checking). .br @@ -4907,7 +5048,7 @@ .br .br -Listing can be enabled on server using -dlist. +Listing can be enabled on server using .I dlist. .br When disabled, a GET on a directory will fail. .br @@ -4918,9 +5059,9 @@ .SH Simple HTTP server .LP .br -In this mode, the filter doesn't need any input connection and exposes all files in the directories given by -rdirs. +In this mode, the filter doesn't need any input connection and exposes all files in the directories given by .I rdirs. .br -PUT and POST methods are only supported if a write directory is specified by -wdir option. +PUT and POST methods are only supported if a write directory is specified by .I wdir option. .br Example .br @@ -4948,14 +5089,14 @@ .br .br -This sets up a read-write server running on -port 8080. +This sets up a read-write server running on .I port 8080. .br .br .SH HTTP server sink .LP .br -In this mode, the filter will forward input PIDs to connected clients, trashing the data if no client is connected unless -hold is specified. +In this mode, the filter will forward input PIDs to connected clients, trashing the data if no client is connected unless .I hold is specified. .br The filter doesn't use any read directory in this mode. .br @@ -4981,13 +5122,13 @@ .br .br -In this mode, ICECast meta-data can be inserted using -ice. The default inserted values are ice-audio-info, icy-br, icy-pub (set to 1) and icy-name if input ServiceName property is set. +In this mode, ICECast meta-data can be inserted using .I ice. The default inserted values are ice-audio-info, icy-br, icy-pub (set to 1) and icy-name if input ServiceName property is set. .br The server will also look for any property called ice-* on the input pid and inject them. .br Example .br -gpac -i source.mp3:#ice-Genre=CoolRock -o http://IP/live.mp3:ice +gpac -i source.mp3:#ice-Genre=CoolRock -o http://IP/live.mp3 --ice .br .br @@ -5000,26 +5141,36 @@ .br The filter uses a read directory in this mode, which must be writable. .br -Upon client GET request, the server will check if the requested file matches the name of a file currently being written by the server. +Upon client GET request, the server will check if the requested URL matches the name of a file currently being written by the server. +.br +- If so, the server will: +.br + - send the content using HTTP chunk transfer mode, starting with what is already written on disk +.br + - push remaining data to the client as soon as recieved while writing it to disk, until source file is done .br -If so, the server will keep refreshing the source size until the associated input file is closed. +- If not so, the server will simply send the file from the disk as a regular HTTP session, without chunk transfer. +.br + .br This mode is typically used for origin server in HAS sessions where clients may request files while they are being produced (low latency DASH). .br Example .br -gpac -i SOURCE -o http://localhost/live.mpd --rdirs=temp +gpac -i SOURCE reframer:rt=on @ -o http://localhost:8080/live.mpd --rdirs=temp --dmode=dynamic --cdur=0.1 .br .br +In this example, a real-time dynamic DASH session with chunks of 100ms is created, outputing files in temp. A client connecting to the live edge will receive segments as they are produced using HTTP chunk transfer. +.br .br .SH HTTP client sink .LP .br -In this mode, the filter will upload input PIDs data to remote server using PUT (or POST if -post is set). +In this mode, the filter will upload input PIDs data to remote server using PUT (or POST if .I post is set). .br -This mode must be explicitly activated using -hmode. +This mode must be explicitly activated using .I hmode. .br The filter uses no read or write directories in this mode. .br @@ -5029,7 +5180,7 @@ .br .br -In this example, the filter will send PUT methods to the server running on -port 8080 at targethost location (IP address or name). +In this example, the filter will send PUT methods to the server running on .I port 8080 at targethost location (IP address or name). .br .br @@ -5038,7 +5189,7 @@ .br In this mode, the server acts as a source rather than a sink. It declares incoming PUT or POST methods as output PIDs .br -This mode must be explicitly activated using -hmode. +This mode must be explicitly activated using .I hmode. .br The filter uses no read or write directories in this mode, and uploaded data is NOT stored by the server. .br @@ -5055,11 +5206,11 @@ .SH HTTPS server .LP .br -The server can run over TLS (https) for all the server modes. TLS is enabled by specifying -cert and -pkey options. +The server can run over TLS (https) for all the server modes. TLS is enabled by specifying .I cert and .I pkey options. .br Both certificate and key must be in PEM format. .br -Note: the server currently only operates in either HTTPS or HTTP mode and cannot run both modes at the same time. You will need to use two httpout filters for this, one operating in HTTPS and one operating in HTTP. +The server currently only operates in either HTTPS or HTTP mode and cannot run both modes at the same time. You will need to use two httpout filters for this, one operating in HTTPS and one operating in HTTP. .br .br @@ -5096,7 +5247,7 @@ .br hold (bool, default: false): hold packets until one client connects .br -hmode (enum, default: default): filter operation mode, ignored if -wdir is set. See filter help for more details. Mode can be +hmode (enum, default: default): filter operation mode, ignored if .I wdir is set. See filter help for more details. Mode can be .br * default: run in server mode (see filter help) .br @@ -5157,11 +5308,11 @@ .br The filter creates a tiling grid with a single row and as many columns as needed. .br -If -mrows is set and tiles properly align on the final grid, multiple rows will be declared in the PPS. +If .I mrows is set and tiles properly align on the final grid, multiple rows will be declared in the PPS. .br Positioning of tiles can be automatic (implicit) or explicit. .br -The filter will check the SPS and PPS configurations of input PID and warn if they are not aligned but will still process them unless -strict is set. +The filter will check the SPS and PPS configurations of input PID and warn if they are not aligned but will still process them unless .I strict is set. .br The filter assumes that all input PIDs are synchronized (frames share the same timestamp) and will reassemble frames with the same dts. If pids are of unequal duration, the filter will drop frames as soon as one pid is over. .br @@ -5315,7 +5466,7 @@ .br Only the PAT table is rewritten, the CAT table, PMT and all program streams are forwarded as is. .br -In -full mode, global DVB tables of the input multiplex are forwarded to each output mux; otherwise these tables are discarded. +In .I full mode, global DVB tables of the input multiplex are forwarded to each output mux; otherwise these tables are discarded. .br .br @@ -5499,11 +5650,11 @@ .br .br -For bicubic, to tune the shape of the basis function, -p1 tunes f(1) and -p2 f´(1) +For bicubic, to tune the shape of the basis function, .I p1 tunes f(1) and .I p2 f´(1) .br -For gauss -p1 tunes the exponent and thus cutoff frequency +For gauss .I p1 tunes the exponent and thus cutoff frequency .br -For lanczos -p1 tunes the width of the window function +For lanczos .I p1 tunes the width of the window function .br See FFMPEG documentation (https://ffmpeg.org/documentation.html) for more details .br @@ -5539,7 +5690,7 @@ .br See FFMPEG documentation (https://ffmpeg.org/documentation.html) for more details .br -Note: if no codec is explicited through -ffc option and no pixel format is given, codecs will be enumerated to find a matching pixel format. +Note: if no codec is explicited through .I ffc option and no pixel format is given, codecs will be enumerated to find a matching pixel format. .br .br @@ -5583,7 +5734,7 @@ .br .br -Note: Some URL formats may not be sufficient to derive the multiplexing format, you must then use -ffmt to specify the desired format. +Note: Some URL formats may not be sufficient to derive the multiplexing format, you must then use .I ffmt to specify the desired format. .br .br @@ -5638,7 +5789,7 @@ .SH Declaring a filter .LP .br -The filter loads a filter or a filter chain description from the -f option. +The filter loads a filter or a filter chain description from the .I f option. .br Example .br @@ -5648,7 +5799,7 @@ .br .br -Unlike other FFMPEG bindings in GPAC, this filter does not parse other libavfilter options, you must specify them directly in the filter chain, and the -f option will have to be escaped. +Unlike other FFMPEG bindings in GPAC, this filter does not parse other libavfilter options, you must specify them directly in the filter chain, and the .I f option will have to be escaped. .br Example .br @@ -5660,7 +5811,7 @@ .br The filter will automatically create buffer and buffersink AV filters for data exchange between GPAC and libavfilter. .br -The builtin options ( -pfmt, -afmt ...) can be used to configure the buffersink filter to set the output format of the filter. +The builtin options ( .I pfmt, .I afmt ...) can be used to configure the buffersink filter to set the output format of the filter. .br .br @@ -5752,7 +5903,7 @@ .br .br -This filter runs a javascript file specified in -js defining a new JavaScript filter. +This filter runs a javascript file specified in .I js defining a new JavaScript filter. .br .br @@ -5846,7 +5997,7 @@ .br For bug reports, feature requests, more information and source code, visit http://github.com/gpac/gpac .br -build: 1.0.0-rev0-g747808797-master +build: 1.0.1-rev0-g7c36b3027-master .br Copyright: (c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io .br
View file
gpac-1.0.0.tar.gz/share/doc/man/gpac.1 -> gpac-1.0.1.tar.gz/share/doc/man/gpac.1
Changed
@@ -25,11 +25,13 @@ .br - an option using -+ indicates a global meta-filter filter (eg FFMPEG) option, for example -+profile=Baseline (see gpac -h doc) .br - + .br - Options do not require any specific order, and may be present anywhere, including between link statements or filter declarations. +Filter declaration order may impact the link resolver which will try linking in declaration order. Most of the time for simple graphs, this has no impact. However, for complex graphs with no link declarations, this can lead to different results. .br -boolean values do not need any value specified. Other types shall be formatted as opt=val, except -i, -src, -o, -dst and -h options. +Options do not require any specific order, and may be present anywhere, including between link statements or filter declarations. +.br +Boolean values do not need any value specified. Other types shall be formatted as opt=val, except .I -i, -src, .I -o, -dst and .I -h options. .br .br @@ -38,6 +40,16 @@ .br .TP +.B \-mem-track +.br +enable memory tracker +.br +.TP +.B \-mem-track-stack +.br +enable memory tracker with stack dumping +.br +.TP .B \-ltf .br load test-unit filters (used for for unit tests only) @@ -123,11 +135,9 @@ .TP .B \-h,-help,-ha,-hx,-hh (string) .br -print help. Use -help or -h for basic options, -ha for advanced options, -hx for expert options and -hh for all. -.br -Note: The @ character can be used in place of the * character. +print help. Use -help or -h for basic options, -ha for advanced options, -hx for expert options and -hh for all. .br - String parameter can be: +Note: The @ character can be used in place of the * character. String parameter can be: .br * empty: print command line options help .br @@ -141,7 +151,7 @@ .br * cfg: print the GPAC configuration help .br -* prompt: print the GPAC prompt help when running in interactive mode (see -k ) +* prompt: print the GPAC prompt help when running in interactive mode (see .I -k ) .br * modules: print available modules .br @@ -153,20 +163,26 @@ .br * props: print the supported builtin PID and packet properties .br -* links: print possible connections between each supported filters. +* colors: print the builtin color names and their values +.br +* links: print possible connections between each supported filters .br * links FNAME: print sources and sinks for filter FNAME (either builtin or JS filter) .br -* FNAME: print filter FNAME info (multiple FNAME can be given). +* FNAME: print filter FNAME info (multiple FNAME can be given) .br - - For meta-filters, use FNAME:INST, eg ffavin:avfoundation. + - For meta-filters, use FNAME:INST, eg ffavin:avfoundation .br - - Use * to print info on all filters (big output!), *:* to print info on all filters including meta filter instances (really big output!). + - Use * to print info on all filters (big output!), *:* to print info on all filters including meta filter instances (really big output!) .br - - By default only basic filter options and description are shown. Use -ha to show advanced options capabilities, -hx for expert options, -hh for all options and filter capabilities including on filters disabled in this build. + - By default only basic filter options and description are shown. Use -ha to show advanced options capabilities, -hx for expert options, -hh for all options and filter capabilities including on filters disabled in this build .br * FNAME.OPT: print option OPT in filter FNAME .br +* OPT: look in filter names and options for OPT and suggest possible matches if none found. Use -hx to look for keyword in all option descriptions +.br + +.br .TP .B \-p (string) .br @@ -188,6 +204,11 @@ revert all items in GPAC cache directory to their original name and server path .br .TP +.B \-js (string) +.br +specify javascript file to use as controller of filter session +.br +.TP .B \-wc .br write all core options in the config file unless already set @@ -407,7 +428,7 @@ .br GPAC uses a configuration file to modify default options of libgpac and filters. This configuration file is located in $HOME/.gpac/GPAC.cfg. .br -Applications in GPAC can also specify a different configuration file through the -p option to indicate a profile. This allows different configurations for different usages and simplifies command line typing. +Applications in GPAC can also specify a different configuration file through the .I -p option to indicate a profile. This allows different configurations for different usages and simplifies command line typing. .br Example .br @@ -419,9 +440,9 @@ .br The reserved name 0 is used to disable configuration file writing. .br -By default the configuration file only holds a few system specific options and directories. It is possible to serialize the entire set of options to the configuration file, using -wc -wf. This should be avoided as the resulting configuration file size will be quite large, hence larger memory usage for the applications. +By default the configuration file only holds a few system specific options and directories. It is possible to serialize the entire set of options to the configuration file, using .I -wc .I -wf. This should be avoided as the resulting configuration file size will be quite large, hence larger memory usage for the applications. .br -The options specified in the configuration file may be overriden by the values in restrict.cfg file located in GPAC share system directory (e.g. /usr/share/gpac), if present; this allows enforcing system-wide configuration values. +The options specified in the configuration file may be overridden by the values in restrict.cfg file located in GPAC share system directory (e.g. /usr/share/gpac), if present; this allows enforcing system-wide configuration values. .br Note: The methods describe in this section apply to any application in GPAC transferring their arguments to libgpac. This is the case for gpac, MP4Box, MP4Client/Osmo4. .br @@ -453,7 +474,7 @@ .br This will force the rtp input filter to always request RTP over RTSP by default. .br -To generate a configuration file with all filters options serialized, use -wf. +To generate a configuration file with all filters options serialized, use .I -wf. .br .SH Global filter options .LP @@ -490,6 +511,20 @@ .br This is equivalent to specifying -o dump.264:profile=Baseline. .br + +.br +For both syntax, it is possible to specify the filter registry name of the option, using --FNAME@OPTNAME=VAL. +.br +In this case the option will only be set for filters which are instances of registry FNAME. This is used when several registries use same option names. +.br +Example +.br +--flist@timescale=100 -i plist1 -i plist2 -o live.mpd +.br + +.br +This will set the timescale option on the playlists filters but not on the dasher filter. +.br .SH libgpac core options: .LP .br @@ -758,7 +793,7 @@ .TP .B \-hwvmem (Enum, default: auto) .br -specify (2D rendering only) memory type of main video backbuffer. Depending on the scene type, this may drastically change the playback speed. +specify (2D rendering only) memory type of main video backbuffer. Depending on the scene type, this may drastically change the playback speed .br * always: always on hardware .br @@ -814,7 +849,7 @@ .TP .B \-video-output (string) .br -indicate the name of the video output module to use (see gpac -h modules). The reserved name glfbo is used in player mode to draw in the openGL texture identified by -glfbo-txid. In this mode, the application is responsible for sending event to the terminal +indicate the name of the video output module to use (see gpac -h modules). The reserved name glfbo is used in player mode to draw in the openGL texture identified by .I glfbo-txid. In this mode, the application is responsible for sending event to the terminal .br .TP .B \-audio-output (string) @@ -936,9 +971,9 @@ .br .br -You can independently log different tools involved in a session. +You can independently log different tools involved in a session. .br -log_args is formatted as a ':'-separated list of toolX[:toolZ]@levelX +log_args is formatted as a ':'-separated list of toolX[:toolZ]@levelX .br levelX can be one of: .br @@ -1027,7 +1062,7 @@ .br Filters are configurable processing units consuming and producing data packets. These packets are carried between filters through a data channel called pid. A PID is in charge of allocating/tracking data packets, and passing the packets to the destination filter(s). A filter output PID may be connected to zero or more filters. This fan-out is handled internally by GPAC (no such thing as a tee filter in GPAC). .br -Note: When a PID cannot be connected to any filter, a warning is thrown and all packets dispatched on this PID will be destroyed. The session may however still run, unless -full-link is set. +Note: When a PID cannot be connected to any filter, a warning is thrown and all packets dispatched on this PID will be destroyed. The session may however still run, unless .I -full-link is set. .br .br @@ -1039,7 +1074,7 @@ .br .br -Each filter exposes a set of argument to configure itself, using property types and values described as strings formated with separators. This help is given with default separator sets :=#,@ to specify filters, properties and options. Use -seps to change them. +Each filter exposes a set of argument to configure itself, using property types and values described as strings formated with separators. This help is given with default separator sets :=#,@ to specify filters, properties and options. Use .I -seps to change them. .br .SH Property format .LP @@ -1141,6 +1176,18 @@ .br .br +It is possible to disable option parsing (for string options) by duplicating the seperator. +.br +Example +.br +filter::opt1=UDP://IP:PORT/:someopt=VAL::opt2=VAL2 +.br + +.br +This will pass UDP://IP:PORT/:someopt=VAL to opt1 without inspecting it, and VAL2 to opt2. +.br + +.br A filter may be assigned a name (for inspection purposes) using :N=name option. This name is not used in link resolution and may be changed at runtime by the filter instance. .br .P @@ -1348,6 +1395,8 @@ .br * name#AnyName=VAL: same as above, using the name of a non built-in property. .br +* name#Name=OtherPropName: compares the value with the value of another property of the PID. The matching will fail if the value to compare to is not present or different from the value to check. The property to compare with shall be a built-in property. +.br If the property is not defined on the PID, the property is matched. Otherwise, its value is checked against the given value. .br @@ -1420,6 +1469,14 @@ .br This indicates to connect to vout only PIDs with Width property less than 640 .br +Example +.br +src=vid.mp4 @#ID=ItemID#ItemNumber=1 vout +.br + +.br +This will connect to vout only PID with an ID property equal to ItemID property (keep items, discard tracks) and an Item number of 1 (first item). +.br .br Multiple fragment can be specified to check for multiple PID properties. @@ -1455,7 +1512,7 @@ .SH Arguments inheriting .LP .br -Unless explicitly disabled (see -max-chain), the filter engine will resolve implicit or explicit (LINK) connections between filters and will allocate any filter chain required to connect the filters. In doing so, it loads new filters with arguments inherited from both the source and the destination. +Unless explicitly disabled (see .I -max-chain), the filter engine will resolve implicit or explicit (LINK) connections between filters and will allocate any filter chain required to connect the filters. In doing so, it loads new filters with arguments inherited from both the source and the destination. .br Example .br @@ -1697,11 +1754,11 @@ .br * $GSHARE: replaced by system path to GPAC shared directory (e.g. /usr/share) .br -* $GJS: replaced by the first path specified by global config option -js-dirs that contains the file name following the macro, e.g. $GJS/source.js +* $GJS: replaced by the first path specified by global config option .I -js-dirs that contains the file name following the macro, e.g. $GJS/source.js .br -* $GLANG: replaced by the global config language option -lang +* $GLANG: replaced by the global config language option .I -lang .br -* $GUA: replaced by the global config user agent option -user-agent +* $GUA: replaced by the global config user agent option .I -user-agent .br * $GINC(init_val[,inc]): replaced by init_val and increment init_val by inc (positive or negative number, 1 if not specified) each time a new filter using this string is created. .br @@ -1720,7 +1777,7 @@ .SH External filters .LP .br -GPAC comes with a set of built-in filters in libgpac. It may also load external filters in dynamic libraries, located in folders listed in -mod-dirs option. The files shall be named gf_* and shall export a single function returning a filter register - see libgpac documentation for more details. +GPAC comes with a set of built-in filters in libgpac. It may also load external filters in dynamic libraries, located in folders listed in .I -mod-dirs option. The files shall be named gf_* and shall export a single function returning a filter register - see libgpac documentation for more details. .br .br @@ -1868,6 +1925,16 @@ ID of image item in HEIF, same value as ID .br .TP +.B ItemNumber (ITIX,uint, ) +.br +Number (1-based) of image item in HEIF, in order of declaration in file +.br +.TP +.B TrackNumber (PIDX,uint, ) +.br +Number (1-based) of track in order of declaration in file +.br +.TP .B ServiceID (PSID,uint,D ) .br ID of parent service @@ -2478,7 +2545,7 @@ .TP .B SubSampleInfo (SUBS,mem, ) .br -Binary blob describing N subsamples of the sample, formatted as N [(u32)flags(u32)size(u32)reserved(u8)priority(u8) discardable] +Binary blob describing N subsamples of the sample, formatted as N [(u32)flags(u32)size(u32)codec_param(u8)priority(u8) discardable]. Subsamples for a given flag MUST appear in order, however flags can be interleaved .br .TP .B NALUMaxSize (NALS,uint, ) @@ -2666,6 +2733,11 @@ Name of the HLS variant playlist for this media .br .TP +.B HLSGroup (HLGI,str,D ) +.br +Name of HLS Group of a stream +.br +.TP .B DCue (DCUE,str,D ) .br Name of a cue list file for this pid - see dasher help @@ -2676,6 +2748,11 @@ Number of DASH segments defined by the DASH cue info .br .TP +.B Codec (CODS,str,D ) +.br +codec parameter string to force. If starting with '.', appended to ISOBMF code point; otherwise replace the codec string +.br +.TP .B SingleScale (DSTS,bool,D ) .br Indicates the movie header should use the media timescale of the first track added @@ -2721,7 +2798,7 @@ Indicate a magic number to store in the track, only used by importers .br .TP -.B TrackIndex (TIDX,luint,D ) +.B MuxIndex (TIDX,luint,D ) .br Indicate target track index in destination file, stored by lowest value first (not set by demuxers) .br @@ -3569,6 +3646,16 @@ VP10 Video .br .TP +.B mpha +.br +MPEG-H Audio +.br +.TP +.B mhas +.br +MPEG-H AudioMux +.br +.TP .B prores|apch .br ProRes Video 422 HQ @@ -3617,7 +3704,7 @@ .br For bug reports, feature requests, more information and source code, visit http://github.com/gpac/gpac .br -build: 1.0.0-rev0-g747808797-master +build: 1.0.1-rev0-g7c36b3027-master .br Copyright: (c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io .br
View file
gpac-1.0.0.tar.gz/share/doc/man/mp4box.1 -> gpac-1.0.1.tar.gz/share/doc/man/mp4box.1
Changed
@@ -14,13 +14,13 @@ .br MP4Box is a multimedia packager, with a vast number of functionalities: conversion, splitting, hinting, dumping, DASH-ing, encryption and others. .br -MP4Box provides a large set of options, classified by categories (see -h). These options do not follow any particular ordering. +MP4Box provides a large set of options, classified by categories (see .I -h). These options do not follow any particular ordering. .br -MP4Box performs in-place rewrite of IsoMedia files (the input file is overwritten). You can change this behaviour by using the -out option. +MP4Box performs in-place rewrite of IsoMedia files (the input file is overwritten). You can change this behaviour by using the .I out option. .br -MP4Box stores by default the file with 0.5 second interleaving and meta-data (moov...) at the beginning, making it suitable for HTTP streaming. This may however takes longer to store the file, use -flat to change this behaviour. +MP4Box stores by default the file with 0.5 second interleaving and meta-data (moov...) at the beginning, making it suitable for HTTP streaming. This may however takes longer to store the file, use .I flat to change this behaviour. .br -MP4Box usually generates a temporary file when creating a new IsoMedia file. The location of this temporary file is OS-dependent, and it may happen that the drive/partition the temporary file is created on has not enough space or no write access. In such a case, you can specify a temporary file location with -tmp. +MP4Box usually generates a temporary file when creating a new IsoMedia file. The location of this temporary file is OS-dependent, and it may happen that the drive/partition the temporary file is created on has not enough space or no write access. In such a case, you can specify a temporary file location with .I tmp. .br Note: Track operations identify tracks through their ID (usually refered as tkID in the help), not their order. .br @@ -42,6 +42,16 @@ Options: .br .TP +.B \-mem-track +.br +enable memory tracker +.br +.TP +.B \-mem-track-stack +.br +enable memory tracker with stack dumping +.br +.TP .B \-p .br use indicated profile for the global GPAC config. If not found, config file is created. If a file path is indicated, this will load profile from that file. Otherwise, this will create a directory of the specified name and store new config there. Reserved name 0 means a new profile, not stored to disk. Works using -p=NAME or -p NAME @@ -54,7 +64,7 @@ .TP .B \-old-inter (number) .br -same as -inter but wihout drift correction +same as .I inter but wihout drift correction .br .TP .B \-tight (number) @@ -119,7 +129,7 @@ .TP .B \-ismax .br -same as -isma and remove all clock references +same as .I isma and remove all clock references .br .TP .B \-3gp @@ -255,7 +265,7 @@ .TP .B \-itags tag1[:tag2] (string) .br -set iTunes tags to file, see -tag-list +set iTunes tags to file, see .I tag-list .br .TP .B \-tag-list @@ -300,9 +310,9 @@ .br * switchID=ID: ID of the switch group to create. If 0, a new ID will be computed for you. If <0, disables SwitchGroup .br -* criteria=string: list of space-separated 4CCs. +* criteria=string: list of space-separated 4CCs .br -* trackID=ID: ID of the track to add to this group. +* trackID=ID: ID of the track to add to this group .br .br @@ -442,7 +452,7 @@ .TP .B \-avi (int) .br -same as -raw but defaults to QCP file for EVRC/SMV +same as .I raw but defaults to QCP file for EVRC/SMV .br .TP .B \-aviraw (string, values: video|audio) @@ -462,7 +472,7 @@ .TP .B \-raw-layer (int) .br -same as -raw but skips SVC/MVC/LHVC extractors when extracting +same as .I raw but skips SVC/MVC/LHVC extractors when extracting .br .TP .B \-diod @@ -487,7 +497,7 @@ .br * #trackID=N: only use the track ID N from the source file .br -* #N: only use the track ID N from the source file (mapped to -tkid) +* #N: only use the track ID N from the source file (mapped to .I -tkid) .br * #video: only use the first video track from the source file .br @@ -541,7 +551,7 @@ .TP .B \-mpd (string) .br -convert given HLS or smooth manifest (local or remote http) to MPD. +convert given HLS or smooth manifest (local or remote http) to MPD. .br Warning: This is not compatible with other DASH options and does not convert associated segments .br @@ -558,7 +568,7 @@ .TP .B \-ddbg-live (number) .br -same as -dash-live without time regulation for debug purposes +same as .I dash-live without time regulation for debug purposes .br .TP .B \-frag (number) @@ -600,21 +610,21 @@ .br set the segment name for generated segments. If not set (default), segments are concatenated in output file except in live profile where dash_%%s. Supported replacement strings are: .br -- $Number[%%0Nd]$ is replaced by the segment number, possibly prefixed with 0. +- $Number[%%0Nd]$ is replaced by the segment number, possibly prefixed with 0 .br -- $RepresentationID$ is replaced by representation name. +- $RepresentationID$ is replaced by representation name .br -- $Time$ is replaced by segment start time. +- $Time$ is replaced by segment start time .br -- $Bandwidth$ is replaced by representation bandwidth. +- $Bandwidth$ is replaced by representation bandwidth .br -- $Init=NAME$ is replaced by NAME for init segment, ignored otherwise. May occur multiple times. +- $Init=NAME$ is replaced by NAME for init segment, ignored otherwise .br -- $Index=NAME$ is replaced by NAME for index segments, ignored otherwise. May occur multiple times. +- $Index=NAME$ is replaced by NAME for index segments, ignored otherwise .br -- $Path=PATH$ is replaced by PATH when creating segments, ignored otherwise. May occur multiple times. +- $Path=PATH$ is replaced by PATH when creating segments, ignored otherwise .br -- $Segment=NAME$ is replaced by NAME for media segments, ignored for init segments. May occur multiple times +- $Segment=NAME$ is replaced by NAME for media segments, ignored for init segments .br .TP .B \-segment-ext (string, default: m4s) @@ -646,7 +656,7 @@ .TP .B \-base-url (string) .br -set Base url at MPD level. Can be used several times. +set Base url at MPD level. Can be used several times. .br Warning: this does not modify generated files location .br @@ -683,12 +693,12 @@ .TP .B \-last-dynamic (string) .br -same as -dynamic but close the period (insert lmsg brand if needed and update duration) +same as .I dynamic but close the period (insert lmsg brand if needed and update duration) .br .TP .B \-mpd-duration (number, default: 0) .br -set the duration in second of a live session (if 0, you must use -mpd-refresh) +set the duration in second of a live session (if 0, you must use .I mpd-refresh) .br .TP .B \-mpd-refresh (number) @@ -703,7 +713,7 @@ .TP .B \-subdur (int) .br -specify maximum duration in ms of the input file to be dashed in LIVE or context mode. This does not change the segment duration, but stops dashing once segments produced exceeded the duration. If there is not enough samples to finish a segment, data is looped unless -no-loop is used which triggers a period end +specify maximum duration in ms of the input file to be dashed in LIVE or context mode. This does not change the segment duration, but stops dashing once segments produced exceeded the duration. If there is not enough samples to finish a segment, data is looped unless .I no-loop is used which triggers a period end .br .TP .B \-run-for (int) @@ -723,7 +733,7 @@ .TP .B \-dash-scale (int) .br -specify that timing for -dash and -frag are expressed in given timexale (units per seconds) +specify that timing for .I dash and .I frag are expressed in given timexale (units per seconds) .br .TP .B \-mem-frags @@ -731,9 +741,9 @@ fragmentation happens in memory rather than on disk before flushing to disk .br .TP -.B \-pssh= (Enum) +.B \-pssh (Enum) .br -set pssh store mode. +set pssh store mode .br * v: initial movie .br @@ -758,7 +768,7 @@ .TP .B \-sdtp-traf (Enum) .br -use sdtp box in traf (Smooth-like). +use sdtp box in traf (Smooth-like) .br * no: do not use sdtp .br @@ -786,12 +796,12 @@ .TP .B \-bound .br -enable video segmentation with same method as audio (i.e.: always try to split before or at the segment boundary - not after) +segmentation will always try to split before or at, but never after, the segment boundary .br .TP .B \-closest .br -enable video segmentation closest to the segment boundary (before or after) +segmentation will use the closest frame to the segment boundary (before or after) .br .TP .B \-subsegs-per-sidx (int) @@ -1004,17 +1014,17 @@ .TP .B \-dtsx .br -same as -dts but does not print offset +same as .I dts but does not print offset .br .TP .B \-dtsc .br -same as -dts but analyse each sample for duplicated dts/cts (slow !) +same as .I dts but analyse each sample for duplicated dts/cts (slow !) .br .TP .B \-dtsxc .br -same as -dtsc but does not print offset (slow !) +same as .I dtsc but does not print offset (slow !) .br .TP .B \-dnal (int) @@ -1049,22 +1059,22 @@ .TP .B \-dsaps (int) .br -same as -dsap but only print sample number +same as .I dsap but only print sample number .br .TP .B \-dsapc (int) .br -same as -dsap but only print CTS +same as .I dsap but only print CTS .br .TP .B \-dsapd (int) .br -same as -dsap but only print DTS, -dsapp to only print presentation time +same as .I dsap but only print DTS, -dsapp to only print presentation time .br .TP .B \-dsapp (int) .br -same as -dsap but only print presentation time +same as .I dsap but only print presentation time .br .TP .B \-dcr @@ -1079,7 +1089,7 @@ .TP .B \-dump-chap .br -extract chapter file +extract chapter file as TTXT format .br .TP .B \-dump-chap-ogg @@ -1087,6 +1097,11 @@ extract chapter file as OGG format .br .TP +.B \-dump-chap-zoom +.br +extract chapter file as zoom format +.br +.TP .B \-dump-udta [tkID:]4cc (string) .br extract udta for the given 4CC. If tkID is given, dumps from UDTA of the given track ID, otherwise moov is used @@ -1157,57 +1172,64 @@ .SH File importing .LP .br -Syntax is -add / -cat filename[#FRAGMENT][:opt1...:optN=val] +Syntax is .I add / .I cat filename[#FRAGMENT][:opt1...:optN=val] .br -This process will create the destination file if not existing, and add the track(s) to it. If you wish to always create a new destination file, add -new. +This process will create the destination file if not existing, and add the track(s) to it. If you wish to always create a new destination file, add .I -new. .br The supported input media types depend on your installation, check filters documentation for more info. .br .br -To select a desired media track, the following syntax is used: +To select a desired media track from a source, a fragment identifier '#' can be specified, bfore any other options. The following syntax is used: .br -* `-add inputFile#video`: adds the first video track in inputFile. +* `#video`: adds the first video track found in source .br -* `-add inputFile#audio`: adds the first audio track in inputFile. +* `#audio`: adds the first audio track found in source .br -* `-add inputFile#trackID=ID` or `-add inputFile#ID`: adds the specified track. For IsoMedia files, ID is the track ID. For other media files, ID is the value indicated by MP4Box -info inputFile. +* `#auxv`: adds the first auxiliary video track found in source .br - +* `#pict`: adds the first picture track found in source .br -By default all imports are performed sequentially, and final interleaving is done at the end; this however requires a temporary file holding input isobmf file (if any) and added files before creating the final output. Since this can become quite large, it is possible to add media to a new file without temporary storage, using -flat option, but this disables media interleaving. +* `#trackID=ID` or `#ID`: adds the specified track. For IsoMedia files, ID is the track ID. For other media files, ID is the value indicated by MP4Box -info inputFile .br - +* `#pid=ID`: number of desired PID for MPEG-2 TS sources .br -If you wish to create an interleaved new file with no temporary storage, use the -newfs option. The interleaving might not be as precise as when using -new since it is dependent on muxer input scheduling (each execution might lead to a slightly different result). +* `#prog_id=ID`: number of desired program for MPEG-2 TS sources .br - - Some muxing options (marked with * below) will be activated for all inputs (i.e. in this mode, it is not possible to import one AVC track with xps_inband and another without). +* `#program=NAME`: name of desired program for MPEG-2 TS sources .br - - Some muxing options (marked as ! below) cannot be used in this mode as they require temporary storage for file edition. + .br - - Usage of -cat is possible in this mode, but concatenated sources will not be interleaved in the output . If you wish to perforom more complex cat/add operations without temp file, use the gpac application. +By default all imports are performed sequentially, and final interleaving is done at the end; this however requires a temporary file holding original ISOBMF file (if any) and added files before creating the final output. Since this can become quite large, it is possible to add media to a new file without temporary storage, using .I -flat option, but this disables media interleaving. .br .br -MP4Box can import a desired amount of the input file rather than the whole file. To do this, use the syntax -add inputFile:dur=N, where N is the number of seconds you wish to import from input. MP4Box cannot start importing from a random point in the input, it always import from the begining. +If you wish to create an interleaved new file with no temporary storage, use the .I -newfs option. The interleaving might not be as precise as when using .I new since it is dependent on muxer input scheduling (each execution might lead to a slightly different result). Additionally in this mode: +.br + - Some muxing options (marked with X below) will be activated for all inputs (e.g it is not possible to import one AVC track with xps_inband and another without). .br -Note: When importing SRT or SUB files, MP4Box will choose default layout options to make the subtitle appear at the bottom of the video. You SHOULD NOT import such files before any video track is added to the destination file, otherwise the results will likelly not be useful (default SRT/SUB importing uses default serif font, fontSize 18 and display size 400x60). Check TTXT doc for more details. + - Some muxing options (marked as D below) cannot be used as they require temporary storage for file edition. +.br + - Usage of .I cat is possible, but concatenated sources will not be interleaved in the output. If you wish to perforom more complex cat/add operations without temp file, use the gpac application. .br .br -When importing several tracks/sources in one pass, all options will be applied if relevant to each source. These options are set for all imported streams. If you need to specify these options par stream, set per-file options using the syntax -add stream[:opt1:...:optN]. +Note: MP4Box cannot start importing from a random point in the input, it always import from the begining. If you wish to import from another point in the source, use the gpac application. .br .br -Allowed per-file options: +Note: When importing SRT or SUB files, MP4Box will choose default layout options to make the subtitle appear at the bottom of the video. You SHOULD NOT import such files before any video track is added to the destination file, otherwise the results will likelly not be useful (default SRT/SUB importing uses default serif font, fontSize 18 and display size 400x60). For more details, check TTXT doc. .br -* #video, #audio: base import for most AV files + .br -* #trackID=ID: track import for IsoMedia and other files +When importing several tracks/sources in one pass, all options will be applied if relevant to each source. These options are set for all imported streams. If you need to specify these options par stream, set per-file options using the syntax -add stream[:opt1:...:optN]. Allowed per-file options: .br -* #pid=ID: stream import from MPEG-2 TS + .br -* :dur=D: * import only the specified duration from the media. D can be: +.TP +.B dur (int) +.br +X import only the specified duration from the media. Value can be: .br * positive float: specifies duration in seconds .br @@ -1215,55 +1237,130 @@ .br * negative integer: specifies duration in number of coded frames .br -* :lang=LAN: set imported media language code +.TP +.B lang (string) +.br +set imported media language code +.br +.TP +.B delay (int) +.br +set imported media initial delay in ms +.br +.TP +.B par (string) +.br +set visual pixel aspect ratio (see .I -par ) +.br +.TP +.B clap (string) +.br +set visual clean aperture (see .I -clap ) +.br +.TP +.B mx (string) +.br +set track matrix (see .I -mx ) +.br +.TP +.B name (string) +.br +set track handler name +.br +.TP +.B ext (string) +.br +override file extension when importing +.br +.TP +.B hdlr (string) +.br +set track handler type to the given code point (4CC) +.br +.TP +.B disable +.br +disable imported track(s) +.br +.TP +.B group (int) +.br +add the track as part of the G alternate group. If G is 0, the first available GroupID will be picked +.br +.TP +.B fps (string) +.br +same as .I fps +.br +.TP +.B rap .br -* :delay=delay_ms: set imported media initial delay in ms +D import only RAP samples .br -* :par=PAR: set visual pixel aspect ratio (see -par ) +.TP +.B refs .br -* :clap=CLAP: set visual clean aperture (see -clap ) +D import only reference pictures .br -* :mx=MX: sets track matrix (see -mx ) +.TP +.B trailing .br -* :name=NAME: set track handler name +keep trailing 0-bytes in AVC/HEVC samples .br -* :ext=EXT: override file extension when importing +.TP +.B agg (int) .br -* :hdlr=code: set track handler type to the given code point (4CC) +X same as .I agg .br -* :disable: imported track(s) will be disabled +.TP +.B dref .br -* :group=G: add the track as part of the G alternate group. If G is 0, the first available GroupID will be picked. +X same as .I dref .br -* :fps=VAL: same as -fps +.TP +.B keep_refs .br -* :rap: ! import only RAP samples +keep track reference when importing a single track .br -* :refs: ! import only reference pictures +.TP +.B nodrop .br -* :trailing: keep trailing 0-bytes in AVC/HEVC samples +same as .I nodrop .br -* :agg=VAL: * same as -agg +.TP +.B packed +.br +X same as .I packed +.br +.TP +.B sbr +.br +same as .I sbr .br -* :dref: * same as -dref +.TP +.B sbrx .br -* :keep_refs: keeps track reference when importing a single track +same as .I sbrx .br -* :nodrop: same as -nodrop +.TP +.B ovsbr .br -* :packed: * same as -packed +same as .I ovsbr .br -* :sbr: same as -sbr +.TP +.B ps .br -* :sbrx: same as -sbrx +same as .I ps .br -* :ovsbr: same as -ovsbr +.TP +.B psx .br -* :ps: same as -ps +same as .I psx .br -* :psx: same as -psx +.TP +.B asemode (string) .br -* :asemode=MODE: * set the mode to create the AudioSampleEntry +X set the mode to create the AudioSampleEntry. Value can be: .br * v0-bs: use MPEG AudioSampleEntry v0 and the channel count from the bitstream (even if greater than 2) - default .br @@ -1273,17 +1370,35 @@ .br * v1-qt: use QuickTime Sound Sample Description Version 1 and the channel count from the bitstream (even if greater than 2). This will also trigger using alis data references instead of url, even for non-audio tracks .br -* :audio_roll=N: add a roll sample group with roll_distance N +.TP +.B audio_roll (int) .br -* :mpeg4: * same as -mpeg4 option +add a roll sample group with roll_distance N .br -* :nosei: discard all SEI messages during import +.TP +.B mpeg4 .br -* :svc: import SVC/LHVC with explicit signaling (no AVC base compatibility) +X same as .I mpeg4 option .br -* :nosvc: discard SVC/LHVC data when importing +.TP +.B nosei +.br +discard all SEI messages during import +.br +.TP +.B svc +.br +import SVC/LHVC with explicit signaling (no AVC base compatibility) +.br +.TP +.B nosvc .br -* :svcmode=MODE: ! set SVC/LHVC import mode +discard SVC/LHVC data when importing +.br +.TP +.B svcmode (string) +.br +D set SVC/LHVC import mode. Value can be: .br * split: each layer is in its own track .br @@ -1295,7 +1410,10 @@ .br * splitnoxib: each layer is in its own track, no extractors are written, using inband param set signaling .br -* :temporal: ! set HEVC/LHVC temporal sublayer import mode +.TP +.B temporal (string) +.br +D set HEVC/LHVC temporal sublayer import mode. Value can be: .br * split: each sublayer is in its own track .br @@ -1303,39 +1421,87 @@ .br * splitnox: each layer is in its own track, and no extractors are written .br -* :subsamples: add SubSample information for AVC+SVC +.TP +.B subsamples .br -* :deps: import sample dependency information for AVC and HEVC +add SubSample information for AVC+SVC .br -* :ccst: add default HEIF ccst box to visual sample entry +.TP +.B deps +.br +import sample dependency information for AVC and HEVC +.br +.TP +.B ccst +.br +add default HEIF ccst box to visual sample entry +.br +.TP +.B forcesync .br -* :forcesync: force non IDR samples with I slices to be marked as sync points (AVC GDR) +force non IDR samples with I slices to be marked as sync points (AVC GDR) .br Warning: RESULTING FILE IS NOT COMPLIANT WITH THE SPEC but will fix seeking in most players .br -* :xps_inband: * set xPS inband for AVC/H264 and HEVC (for reverse operation, re-import from raw media) +.TP +.B xps_inband +.br +X set xPS inband for AVC/H264 and HEVC (for reverse operation, re-import from raw media) +.br +.TP +.B xps_inbandx +.br +X same as xps_inband and also keep first xPS in sample desciption +.br +.TP +.B au_delim +.br +keep AU delimiter NAL units in the imported file +.br +.TP +.B max_lid (int) +.br +set HEVC max layer ID to be imported to N (by default imports all layers) +.br +.TP +.B max_tid (int) .br -* :xps_inbandx: * same as xps_inband and also keep first xPS in sample desciption +set HEVC max temporal ID to be imported to N (by default imports all temporal sublayers) .br -* :au_delim: keep AU delimiter NAL units in the imported file +.TP +.B tiles .br -* :max_lid=N: set HEVC max layer ID to be imported to N (by default imports all layers) +add HEVC tiles signaling and NALU maps without splitting the tiles into different tile tracks .br -* :max_tid=N: set HEVC max temporal ID to be imported to N (by default imports all temporal sublayers) +.TP +.B split_tiles .br -* :tiles: add HEVC tiles signaling and NALU maps without splitting the tiles into different tile tracks +D split HEVC tiles into different tile tracks, one tile (or all tiles of one slice) per track .br -* :split_tiles: ! split HEVC tiles into different tile tracks, one tile (or all tiles of one slice) per track. +.TP +.B negctts .br -* :negctts: use negative CTS-DTS offsets (ISO4 brand) +use negative CTS-DTS offsets (ISO4 brand) .br -* :chap: specify the track is a chapter track +.TP +.B chap .br -* :chapter=NAME: add a single chapter (old nero format) with given name lasting the entire file +specify the track is a chapter track .br -* :chapfile=file: adds a chapter file (old nero format) +.TP +.B chapter (string) .br -* :layout=WxHxXxY: specify the track layout +add a single chapter (old nero format) with given name lasting the entire file +.br +.TP +.B chapfile (string) +.br +add a chapter file (old nero format) +.br +.TP +.B layout (string) +.br +specify the track layout as WxHxXxY .br * if W (resp H) = 0: the max width (resp height) of the tracks in the file are used .br @@ -1343,75 +1509,161 @@ .br * X and Y can be omitted: :layout=WxH .br -* :rescale=TS: force media timescale to TS !! changes the media duration +.TP +.B rescale (int) +.br +force media timescale to TS !! changes the media duration .br -* :timescale=TS: set imported media timescale to TS. +.TP +.B timescale (int) .br -* :moovts=TS: set movie timescale to TS. A negative value picks the media timescale of the first track imported. +set imported media timescale to TS .br -* :noedit: * do not set edit list when importing B-frames video tracks +.TP +.B moovts (int) .br -* :rvc=FILENAME: set RVC configuration for the media +set movie timescale to TS. A negative value picks the media timescale of the first track imported .br -* :fmt=FORMAT: override format detection with given format (cf BT/XMTA doc) +.TP +.B noedit .br -* :profile=INT: override AVC profile +X do not set edit list when importing B-frames video tracks .br -* :level=INT: override AVC level +.TP +.B rvc (string) .br -* :novpsext: remove VPS extensions from HEVC VPS +set RVC configuration for the media .br -* :keepav1t: keep AV1 temporal delimiter OBU in samples, might help if source file had losses +.TP +.B fmt (string) .br -* :font=name: specify font name for text import (default Serif) +override format detection with given format (cf BT/XMTA doc) .br -* :size=s: specify font size for text import (default 18) +.TP +.B profile (int) .br -* :text_layout=WxHxXxY: specify the track text layout +override AVC profile .br - * if W (resp H) = 0: the max width (resp height) of the tracks in the file are used. +.TP +.B level (int) +.br +override AVC level +.br +.TP +.B novpsext +.br +remove VPS extensions from HEVC VPS +.br +.TP +.B keepav1t +.br +keep AV1 temporal delimiter OBU in samples, might help if source file had losses +.br +.TP +.B font (string) +.br +specify font name for text import (default Serif) +.br +.TP +.B size (int) +.br +specify font size for text import (default 18) +.br +.TP +.B text_layout (string) +.br +specify the track text layout as WxHxXxY +.br + * if W (resp H) = 0: the max width (resp height) of the tracks in the file are used .br * if Y=-1: the layout is moved to the bottom of the track area .br * X and Y can be omitted: :layout=WxH .br -* :swf-global: all SWF defines are placed in first scene replace rather than when needed +.TP +.B swf-global +.br +all SWF defines are placed in first scene replace rather than when needed +.br +.TP +.B swf-no-ctrl +.br +use a single stream for movie control and dictionary (this will disable ActionScript) +.br +.TP +.B swf-no-text +.br +remove all SWF text +.br +.TP +.B swf-no-font +.br +remove all embedded SWF Fonts (local playback host fonts used) +.br +.TP +.B swf-no-line +.br +remove all lines from SWF shapes +.br +.TP +.B swf-no-grad +.br +remove all gradients from SWF shapes +.br +.TP +.B swf-quad +.br +use quadratic bezier curves instead of cubic ones .br -* :swf-no-ctrl: use a single stream for movie control and dictionary (this will disable ActionScript) +.TP +.B swf-xlp .br -* :swf-no-text: remove all SWF text +support for lines transparency and scalability .br -* :swf-no-font: remove all embedded SWF Fonts (local playback host fonts used) +.TP +.B swf-ic2d .br -* :swf-no-line: remove all lines from SWF shapes +use indexed curve 2D hardcoded proto .br -* :swf-no-grad: remove all gradients from SWF shapes +.TP +.B swf-same-app .br -* :swf-quad: use quadratic bezier curves instead of cubic ones +appearance nodes are reused .br -* :swf-xlp: support for lines transparency and scalability +.TP +.B swf-flatten (number) .br -* :swf-ic2d: use indexed curve 2D hardcoded proto +complementary angle below which 2 lines are merged, 0 means no flattening .br -* :swf-same-app: appearance nodes are reused +.TP +.B kind (string) .br -* :swf-flatten=ang: complementary angle below which 2 lines are merged, 0 means no flattening +set kind for the track as schemeURI=value .br -* :kind=schemeURI=value: set kind for the track +.TP +.B txtflags (int) +.br +set display flags (hexa number) of text track. Use txtflags+=FLAGS to add flags and txtflags-=FLAGS to remove flags .br -* :txtflags=flags: set display flags (hexa number) of text track +.TP +.B rate (int) .br -* :txtflags+=flags: add display flags (hexa number) to text track +force average rate and max rate to VAL (in bps) in btrt box. If 0, removes btrt box .br -* :txtflags-=flags: remove display flags (hexa number) from text track +.TP +.B stz2 .br -* :rate=VAL: force average rate and max rate to VAL (in bps) in btrt box. If 0, removes btrt box +use compact size table (for low-bitrates) .br -* :stz2: use compact size table (for low-bitrates) +.TP +.B bitdepth (int) .br -* :bitdepth=VAL: set bit depth to VAL for imported video content (default is 24) +set bit depth to VAL for imported video content (default is 24) .br -* :colr=OPT: set color profile for imported video content (see ISO/IEC 23001-8). OPT is formatted as: +.TP +.B colr (string) +.br +set color profile for imported video content (see ISO/IEC 23001-8). Value is formatted as: .br * nclc,p,t,m: with p colour primary, t transfer characteristics and m matrix coef .br @@ -1421,9 +1673,15 @@ .br * rICC,path: with path indicating the file containing the restricted ICC color profile .br -* :dv-profile=VAL: set the Dolby Vision profile +.TP +.B dv-profile (int) +.br +set the Dolby Vision profile .br -* :tc=VAL: inject a single QT timecode. VAL is formated as: +.TP +.B tc (string) +.br +inject a single QT timecode. Value is formated as: .br * [d]FPS[/FPS_den],h,m,s,f[,framespertick]: optional drop flag, framerate (integer or fractional), hours, minutes, seconds and frame number .br @@ -1431,7 +1689,10 @@ .br * : the framespertick is optional and defaults to round(framerate); it indicates the number of frames per counter tick .br -- :lastsampdur[=VAL]" sets duration of the last sample. VAL is formated as: +.TP +.B lastsampdur (string) +.br +set duration of the last sample. Value is formated as: .br * no value: use the previous sample duration .br @@ -1439,15 +1700,30 @@ .br * N/D: indicate the duration as fractional second .br -* :fstat: print filter session stats after import +.TP +.B fstat +.br +print filter session stats after import +.br +.TP +.B fgraph .br -* :fgraph: print filter session graph after import +print filter session graph after import .br -* :sopt:[OPTS]: set OPTS as additional arguments to source filter. OPTS can be any usual filter argument, see filter doc `gpac -h doc` +.TP +.B sopt:[OPTS] .br -* :dopt:[OPTS]: * set OPTS as additional arguments to destination filter. OPTS can be any usual filter argument, see filter doc `gpac -h doc` +set OPTS as additional arguments to source filter. OPTS can be any usual filter argument, see filter doc `gpac -h doc` .br -* @@f1[:args][@@fN:args]: set a filter chain to insert before the muxer. Each filter in the chain is formatted as a regular filter, see filter doc `gpac -h doc`. If several filters are set, they will be chained in the given order. The last filter shall not have any Filter ID specified +.TP +.B dopt:[OPTS] +.br +X set OPTS as additional arguments to destination filter. OPTS can be any usual filter argument, see filter doc `gpac -h doc` +.br +.TP +.B @@f1[:args][@@fN:args] +.br +set a filter chain to insert before the muxer. Each filter in the chain is formatted as a regular filter, see filter doc `gpac -h doc`. If several filters are set, they will be chained in the given order. The last filter shall not have any Filter ID specified .br .br @@ -1464,19 +1740,19 @@ .TP .B \-cat (string) .br -concatenate given file samples to file, creating tracks if needed. Multiple inputs can be specified using +(eg -cat url1+url2). +concatenate given file samples to file, creating tracks if needed. Multiple inputs can be specified using +(eg -cat url1+url2). .br -Note: Note: This aligns initial timestamp of the file to be concatenated +Note: This aligns initial timestamp of the file to be concatenated .br .TP .B \-catx (string) .br -same as -cat but new tracks can be imported before concatenation by specifying +ADD_COMMAND where ADD_COMMAND is a regular -add syntax +same as .I cat but new tracks can be imported before concatenation by specifying +ADD_COMMAND where ADD_COMMAND is a regular .I add syntax .br .TP .B \-catpl (string) .br -concatenate files listed in the given playlist file (one file per line, lines starting with # are comments). +concatenate files listed in the given playlist file (one file per line, lines starting with # are comments). .br Note: Each listed file is concatenated as if called with -cat .br @@ -1488,19 +1764,19 @@ .TP .B \-force-cat (string) .br -skip media configuration check when concatenating file. +skip media configuration check when concatenating file. .br Warning: THIS MAY BREAK THE CONCATENATED TRACK(S) .br .TP .B \-keep-sys .br -keep all MPEG-4 Systems info when using -add and -cat (only used when adding IsoMedia files) +keep all MPEG-4 Systems info when using .I add and .I cat (only used when adding IsoMedia files) .br .TP .B \-dref .br -keep media data in original file using data referencing. The resulting file only contains the meta-data of the presentation (frame sizes, timing, etc...) and references media data in the original file. This is extremely useful when developping content, since importing and storage of the MP4 file is much faster and the resulting file much smaller. +keep media data in original file using data referencing. The resulting file only contains the meta-data of the presentation (frame sizes, timing, etc...) and references media data in the original file. This is extremely useful when developping content, since importing and storage of the MP4 file is much faster and the resulting file much smaller. .br Note: Data referencing may fail on some files because it requires the framed data (eg an IsoMedia sample) to be continuous in the original file, which is not always the case depending on the original interleaving or bitstream format (AVC or HEVC cannot use this option) .br @@ -1542,11 +1818,9 @@ .TP .B \-fps (string, default: 25) .br -force frame rate for video and SUB subtitles import to the given value, expressed as a number or as timescale-increment. -.br -Note: For raw H263 import, default FPS is 15, otherwise 25 +force frame rate for video and SUB subtitles import to the given value, expressed as a number or as timescale-increment. .br -Warning: This is ignored for ISOBMFF import, use :rescale option for that +Note: For raw H263 import, default FPS is 15, otherwise 25. This is ignored for ISOBMFF import, use :rescale option for that .br .TP .B \-mpeg4 @@ -1556,9 +1830,7 @@ .TP .B \-agg (int) .br -aggregate N audio frames in 1 sample (3GP media only). -.br -Note: Maximum value is 15 +aggregate N audio frames in 1 sample (3GP media only, maximum value is 15) .br .SH Hinting Options .LP @@ -1579,7 +1851,7 @@ hint the file for RTP/RTSP .br .TP -.B \-hint (int, default: 1450) +.B \-mtu (int, default: 1450) .br specify RTP MTU (max size) in bytes (this includes 12 bytes RTP header) .br @@ -1619,6 +1891,11 @@ add given SDP string to hint track (tkID:string) or movie (string) .br .TP +.B \-no-offset +.br +signal no random offset for sequence number and timestamp (support will depend on server) +.br +.TP .B \-unhint .br remove all hinting information from file @@ -1656,7 +1933,7 @@ .TP .B \-iod .br -prevent systems tracks embedding in IOD (MPEG-4 Systems), not compatible with -isma +prevent systems tracks embedding in IOD (MPEG-4 Systems), not compatible with .I isma .br .SH MPEG-4 Scene Encoding Options .LP @@ -1702,19 +1979,15 @@ .TP .B \-sync (int) .br -force BIFS sync sample generation every given time in ms. -.br -Note: cannot be used with -shadow +force BIFS sync sample generation every given time in ms (cannot be used with .I shadow ) .br .TP .B \-shadow (int) .br -force BIFS sync shadow sample generation every given time in ms. -.br -Note: cannot be used with -sync +force BIFS sync shadow sample generation every given time in ms (cannot be used with .I sync ) .br .TP -.B \-log +.B \-sclog .br generate scene codec log file if available .br @@ -1825,13 +2098,13 @@ .TP .B \-add-image (string) .br -add the given file (with parameters) as HEIF image item. Same syntax as -add-item +add the given file (with parameters) as HEIF image item. Same syntax as .I add-item .br -* name=str: see -add-item +* name=str: see .I add-item .br -* id=id: see -add-item +* id=id: see .I add-item .br -* ref=4cc, id: see -add-item +* ref=4cc, id: see .I add-item .br * primary: indicate that this item should be the primary item .br @@ -1847,7 +2120,7 @@ .br * alpha: indicate that the image is an alpha image (should use ref=auxl also) .br -- any other option will be passed as options to the media importer, see -add +- any other option will be passed as options to the media importer, see .I add .br .TP .B \-rem-item item_ID[:tk=tkID] (string) @@ -2035,7 +2308,7 @@ .br For bug reports, feature requests, more information and source code, visit http://github.com/gpac/gpac .br -build: 1.0.0-rev0-g747808797-master +build: 1.0.1-rev0-g7c36b3027-master .br Copyright: (c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io .br
View file
gpac-1.0.0.tar.gz/share/doc/man/mp4client.1 -> gpac-1.0.1.tar.gz/share/doc/man/mp4client.1
Changed
@@ -18,6 +18,16 @@ . .SH OPTIONS .TP +.B \-mem-track +.br +enable memory tracker +.br +.TP +.B \-mem-track-stack +.br +enable memory tracker with stack dumping +.br +.TP .B \-rti (string) .br log run-time info (FPS, CPU, Mem usage) to given file @@ -251,7 +261,7 @@ .br For bug reports, feature requests, more information and source code, visit http://github.com/gpac/gpac .br -build: 1.0.0-rev0-g747808797-master +build: 1.0.1-rev0-g7c36b3027-master .br Copyright: (c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io .br
View file
gpac-1.0.0.tar.gz/share/gui/extensions/H2B2VS/h2b2vs.js -> gpac-1.0.1.tar.gz/share/gui/extensions/H2B2VS/h2b2vs.js
Changed
@@ -44,7 +44,7 @@ case GF_EVENT_MOUSEUP: if (this.uhd_demo_on) { this.uhd_state_on = !this.uhd_state_on; - gpac.switch_quality(this.uhd_state_on); + scene.switch_quality(this.uhd_state_on); return true; } return false; @@ -69,12 +69,12 @@ case GF_EVENT_KEYDOWN: //alert('key is '+evt.keycode + ' hw code is ' + evt.hwkey); - var odm = gpac.get_object_manager(this.scene_url); + var odm = scene.get_object_manager(this.scene_url); if (!odm || odm.main_addon_url) return false; if (evt.keycode == 'F7') { this.uhd_state_on = !this.uhd_state_on; - gpac.switch_quality(this.uhd_state_on); + scene.switch_quality(this.uhd_state_on); return true; } @@ -95,7 +95,7 @@ } /* if (evt.keycode == 'F12') { - gpac.exit(); + scene.exit(); return true; } */ @@ -162,9 +162,9 @@ this.restore_session(); //check our args - var i, argc = gpac.argc; - for (i = 1; i < argc; i++) { - var arg = gpac.get_arg(i); + var i; + for (i = 1; i < Sys.args.length; i++) { + var arg = Sys.args[i]; if (arg == '-demo-uhd') { this.uhd_demo_enabled = true; this.toggle_uhd_demo(true); @@ -244,7 +244,7 @@ wnd.txt3 = gw_new_text(wnd.area, 'User Identifier'); gw_new_separator(wnd.area); wnd.edit = gw_new_text_edit(wnd.area, this.get_option('UserID', 'H2B2VSUser')); - gpac.set_focus(wnd.edit); + scene.set_focus(wnd.edit); wnd.edit.on_text = function (val) { if (val != '') { this.parent.parent.extension.set_option('UserID', val); @@ -261,9 +261,9 @@ wnd.dbg_addon = gw_new_checkbox(wnd.area, 'Debug PVR addon'); wnd.dbg_addon.on_check = function (value) { - gpac.set_option('Compositor', 'dbgpvr', value ? 'yes' : 'no'); + scene.set_option('Compositor', 'dbgpvr', value ? 'yes' : 'no'); } - do_sel = gpac.get_option('Compositor', 'dbgpvr'); + do_sel = scene.get_option('Compositor', 'dbgpvr'); wnd.dbg_addon.set_checked((do_sel == 'yes') ? true : false); gw_new_separator(wnd.area); @@ -319,7 +319,7 @@ refresh_addon: function () { if (this.scene_url) { - var odm = gpac.get_object_manager(this.scene_url); + var odm = scene.get_object_manager(this.scene_url); if (odm) { odm.addon_layout(parseInt(this.get_option('OverlayPosition', '0')), parseInt(this.get_option('OverlaySize', '0'))); } @@ -327,7 +327,7 @@ }, do_activate_addon: function () { - var odm = gpac.get_object_manager(this.scene_url); + var odm = scene.get_object_manager(this.scene_url); if (odm) { odm.enable_addon(this.addon_url); odm.addon_layout(parseInt(this.get_option('OverlayPosition', '0')), parseInt(this.get_option('OverlaySize', '0'))); @@ -335,7 +335,7 @@ }, do_deactivate_addon: function () { - var odm = gpac.get_object_manager(this.scene_url); + var odm = scene.get_object_manager(this.scene_url); if (odm) { odm.enable_addon(this.addon_url, true); }
View file
gpac-1.0.0.tar.gz/share/gui/extensions/about/info.js -> gpac-1.0.1.tar.gz/share/gui/extensions/about/info.js
Changed
@@ -1,7 +1,7 @@ extension = { start: function () { - var str = 'Version ' + gpac.get_option('core', 'version'); + var str = 'Version ' + scene.get_option('core', 'version'); str += '\nMore info: http://gpac.io'; str += '\nDistributed under LGPL v2.1 or any later version'; str += '\n(c) 2002-2020 Telecom Paris';
View file
gpac-1.0.0.tar.gz/share/gui/extensions/player/fileopen.js -> gpac-1.0.1.tar.gz/share/gui/extensions/player/fileopen.js
Changed
@@ -1,7 +1,7 @@ extension.open_local_file = function () { var filebrowse = gw_new_file_dialog(null, 'Open file'); filebrowse.filter = '*'; - filebrowse.browse(gpac.last_working_directory); + filebrowse.browse(Sys.last_wdir); filebrowse.extension = this; this.file_open_dlg = true; @@ -25,7 +25,7 @@ if (value == null) { this.extension.controler.show(); } else { - if (directory) gpac.last_working_directory = directory; + if (directory) Sys.last_wdir = directory; this.extension.set_movie_url(value); } this.file_open_dlg = false; @@ -154,9 +154,9 @@ item.index = hist_idx; item.on_click = function () { var fb_dlg = this.dlg.dlg; - path += '#LIVE360TV'; + path += '#VR'; fb_dlg.extension.set_movie_url(path); - if (directory) gpac.last_working_directory = directory; + if (directory) Sys.last_wdir = directory; fb_dlg.close(); this.dlg.close(); } @@ -184,11 +184,12 @@ popup.edit = gw_new_text_edit(popup.area, ''); popup.edit.dlg = popup; - gpac.set_focus(popup.edit); + scene.set_focus(popup.edit); popup.edit.on_text = function (val) { if (val != '') { this.dlg.dlg.on_browse(val, null); this.dlg.dlg.close(); + this.dlg.dlg = null; } this.dlg.close(); } @@ -203,14 +204,15 @@ popup.set_alpha(1.0); popup.on_close = function () { - this.dlg.enable(); + if (this.dlg) { + this.dlg.enable(); + } } popup.show(); } - filebrowse.on_display_size(gw_display_width, gw_display_height); - if (gpac.hardware_rgba) filebrowse.set_alpha(0.8); + if (scene.hardware_rgba) filebrowse.set_alpha(0.8); this.controler.hide(); filebrowse.show();
View file
gpac-1.0.0.tar.gz/share/gui/extensions/player/player.js -> gpac-1.0.1.tar.gz/share/gui/extensions/player/player.js
Changed
@@ -172,6 +172,13 @@ this.movie.children[0].extension = this; + if (gwskin.mobile_device) { + var size = scene.screen_width; + if (size > scene.screen_height) size = scene.screen_height; + this.def_width = size; + } + + this.movie.children[0].on_scene_size = function (evt) { var ext = this.extension; @@ -181,10 +188,10 @@ //process the error or connect service if (evt.error) { if (ext.test_mode) { - gpac.exit(1); + scene.exit(1); } - var notif = gw_new_message(null, 'Error opening file!', 'Failed to open ' + this.url[0] + '\n\nReason: ' + gpac.error_string(evt.error)); + var notif = gw_new_message(null, 'Error opening file!', 'Failed to open ' + this.url[0] + '\n\nReason: ' + Sys.error_string(evt.error)); notif.show(); var url = ext.movie.children[0].url.length ? ext.movie.children[0].url[0] : ''; @@ -243,14 +250,14 @@ ext.local_url = false; } - ext.root_odm = gpac.get_object_manager(ext.current_url); + ext.root_odm = scene.get_object_manager(ext.current_url); ext.reverse_playback_supported = ext.root_odm.reverse_playback_supported; ext.controler.hide(); var names = ext.current_url.split('/'); if (names.length == 0) names = ext.current_url.split('\\'); - gpac.caption = names.pop(); + scene.caption = names.pop(); ext.add_bookmark(ext.current_url, true); @@ -279,32 +286,32 @@ if (!ext.movie_connected) { ext.movie_connected = true; - gpac.set_3d(evt.type3d ? 1 : 0); + scene.set_3d(evt.type3d ? 1 : 0); ext.controler.play.switch_icon(ext.icon_pause); ext.dynamic_scene = evt.dynamic_scene; //force display size notif on controler to trigger resize of the window ext.controler.on_display_size(ext.controler.width, ext.controler.height); } -// ext.root_odm = gpac.get_object_manager(ext.current_url); +// ext.root_odm = scene.get_object_manager(ext.current_url); ext.set_state(ext.GF_STATE_PLAY); //override scene size info - gpac.set_size(evt.width, evt.height, true); + scene.set_size(evt.width, evt.height, true); - if (!gpac.fullscreen && evt.width && evt.height) { + if (!scene.fullscreen && evt.width && evt.height) { var w, h; w = evt.width; h = evt.height; - if (w > gpac.screen_width) w = gpac.screen_width; - if (h > gpac.screen_height) h = gpac.screen_height; + if (w > scene.screen_width) w = scene.screen_width; + if (h > scene.screen_height) h = scene.screen_height; if (w<this.extension.def_width) w = this.extension.def_width; gwlog(l_deb, 'set output size to ' + w + 'x' + h); - gpac.set_size(w, h); + scene.set_size(w, h); } ext.streamlist_changed(); @@ -648,20 +655,20 @@ wnd.snd_low.add_icon('audio_mute'); wnd.snd_low.on_click = function () { if (this.extension.muted) { - gpac.volume = this.extension.muted; + scene.volume = this.extension.muted; this.extension.muted = 0; this.switch_icon(0); } else { - this.extension.muted = gpac.volume ? gpac.volume : 1; - gpac.volume = 0; + this.extension.muted = scene.volume ? scene.volume : 1; + scene.volume = 0; this.switch_icon(1); } } wnd.snd_ctrl.on_slide = function (value, type) { if (this.extension.muted) this.extension.controler.snd_low.on_click(); - gpac.volume = value; + scene.volume = value; } - wnd.snd_ctrl.set_value(gpac.volume); + wnd.snd_ctrl.set_value(scene.volume); wnd.open = null; if (!gwskin.browser_mode) { @@ -722,13 +729,13 @@ wnd.fullscreen = gw_new_icon(wnd.infobar, 'fullscreen'); wnd.fullscreen.add_icon(gwskin.images.fullscreen_back); wnd.fullscreen.on_click = function () { - gpac.fullscreen = !gpac.fullscreen; + scene.fullscreen = !scene.fullscreen; } - wnd.fullscreen.switch_icon(gpac.fullscreen ? 1 : 0); + wnd.fullscreen.switch_icon(scene.fullscreen ? 1 : 0); if (!gwskin.browser_mode) { wnd.exit = gw_new_icon(wnd.infobar, 'exit'); - wnd.exit.on_click = function () { gpac.exit(); } + wnd.exit.on_click = function () { scene.exit(); } } else { wnd.exit = null; } @@ -744,7 +751,7 @@ if (this.time) this.time.set_size(4 * wnd.time.font_size(), control_icon_size); if (this.snd_ctrl) { this.snd_ctrl.set_size(2 * control_icon_size, control_icon_size / 2, control_icon_size / 3, control_icon_size / 2); - this.snd_ctrl.set_value(gpac.volume); + this.snd_ctrl.set_value(scene.volume); } var speed = this.extension.movie_control.mediaSpeed; @@ -773,14 +780,14 @@ this.on_size(width, height); if (this.fullscreen) - this.fullscreen.switch_icon(gpac.fullscreen ? 1 : 0); + this.fullscreen.switch_icon(scene.fullscreen ? 1 : 0); width -= control_icon_size / 2; min_w = control_icon_size; if (this.time.visible) min_w += this.time.width; if (this.open) min_w += control_icon_size; if (this.home) min_w += control_icon_size; - if (this.exit && gpac.fullscreen) min_w += control_icon_size; + if (this.exit && scene.fullscreen) min_w += control_icon_size; full_w = 0; if (this.snd_low) full_w += control_icon_size; if (this.snd_ctrl) full_w += this.snd_ctrl.width; @@ -794,12 +801,12 @@ full_w += control_icon_size; wnd.navigate.on_click = function () { -// var sensors_active = gpac.sensors_active; -// gpac.sensors_active = !sensors_active; +// var sensors_active = scene.sensors_active; +// scene.sensors_active = !sensors_active; // this.switch_icon(sensors_active ? 1 : 0); this.extension.select_navigation_vr(); } - } else if ( (this.extension.dynamic_scene != 1) && this.extension.movie_connected && (gpac.navigation_type != GF_NAVIGATE_TYPE_NONE)) { + } else if ( (this.extension.dynamic_scene != 1) && this.extension.movie_connected && (scene.navigation_type != GF_NAVIGATE_TYPE_NONE)) { show_navigate = true; full_w += control_icon_size; @@ -868,7 +875,7 @@ time_w = this.media_line.visible ? 2 * control_icon_size : 0; if (this.exit) { - if (gpac.fullscreen) { + if (scene.fullscreen) { this.exit.show(); } else { this.exit.hide(); @@ -931,9 +938,9 @@ wnd.on_display_size = function (width, height) { var h; - if (!gpac.fullscreen) { + if (!scene.fullscreen) { if (width < this.extension.def_width) { - gpac.set_size(this.extension.def_width, height); + scene.set_size(this.extension.def_width, height); return; } } else { @@ -952,9 +959,7 @@ } else h = 1.1 * gwskin.default_icon_height; - this.set_size(this.extension.def_width, h); - this.extension.safe_interact.set_size(gwskin.default_icon_height, gwskin.default_icon_height); this.extension.safe_interact.show(); this.extension.safe_interact.move((-gwskin.default_icon_height+width)/2, (gwskin.default_icon_height-height)/2); @@ -988,16 +993,16 @@ this.init_extension(); //check our args - var i, argc = gpac.argc; + var i; var url_arg = null; - var prog_name = gpac.get_arg(0); + var prog_name = Sys.args[0]; var check_gpac_args = 1; //check mp4client or MP4Client if (prog_name && (prog_name.indexOf('lient')>=0)) check_gpac_args = 0; - for (i = 1; i < argc; i++) { - var arg = gpac.get_arg(i); + for (i = 1; i < Sys.args.length; i++) { + var arg = Sys.args[i]; if (!arg) break; if (check_gpac_args==1) { @@ -1044,7 +1049,7 @@ } else { continue; } - gpac.set_arg_used(i, true); + Sys.set_arg_used(i, true); } gwskin.media_url = ''; @@ -1062,16 +1067,6 @@ return; } this.set_playlist_mode(true); - - /* - var label = ''; - for (i = 1; i < argc; i++) { - label += '#'+i + ': ' + gpac.get_arg(i) + '\n'; - } - var notif = gw_new_message(null, 'GPAC Arguments', label); - notif.show(); - */ - } this.controler.show(); @@ -1080,14 +1075,22 @@ }, coverage_tests: function() { - gpac.trigger_gc(); - gpac.navigation_supported(GF_NAVIGATE_EXAMINE); - gpac.move_window(0,0, true); - gpac.error_string(-1); - gpac.show_keyboard(true); - gpac.switch_quality(true); - var z = gpac.zoom; - z = gpac.text_selection; + scene.trigger_gc(); + scene.navigation_supported(GF_NAVIGATE_EXAMINE); + scene.move_window(0,0, true); + scene.show_keyboard(true); + scene.switch_quality(true); + var z = scene.zoom; + z = scene.text_selection; + + //test filtersession API + let nb_filters = session.nb_filters; + print("init ok, filter: " + nb_filters); + for (let idx=0; idx<nb_filters; idx++) { + let f = session.get_filter(idx); + if (! this.root_odm.in_parent_chain(f)) continue; + print("F#"+(idx+1) + " : " + f.name); + } var m = this.stats_resources[0]; //m.gui.info.on_click(); @@ -1205,7 +1208,7 @@ } } if (this.test_mode && (value>3)) { - gpac.exit(3); + scene.exit(3); } h = Math.floor(value / 3600); @@ -1407,7 +1410,7 @@ this.movie_sensor.url[0] = url; if (this.UPnP_Enabled) UPnP.MovieURL = url; this.movie_connected = (url == '') ? false : true; - gpac.caption = url; + scene.caption = url; this.root_odm = null; this.controler.layout(); @@ -1505,9 +1508,9 @@ }, select_navigation_vr: function () { - var sensors_active = gpac.sensors_active; + var sensors_active = scene.sensors_active; var extension = this; -// gpac.sensors_active = !sensors_active; +// scene.sensors_active = !sensors_active; // this.switch_icon(sensors_active ? 1 : 0); var nb_items = 0; @@ -1522,33 +1525,33 @@ wnd.on_close = function () { this.extension.navigation_wnd = null; } - wnd.add_menu_item(sensors_active ? "Keyboard+mouse" : "Sensors", function () { gpac.sensors_active = !sensors_active; } ); + wnd.add_menu_item(sensors_active ? "Keyboard+mouse" : "Sensors", function () { scene.sensors_active = !sensors_active; } ); if (this.view_stereo==extension.GF_VIEW_MONO) { wnd.add_menu_item("Stereo", function () { extension.view_stereo = extension.GF_VIEW_STEREO; - gpac.set_option("Compositor", "stereo", "hmd"); + scene.set_option("Compositor", "stereo", "hmd"); } ); } else if (this.view_stereo==extension.GF_VIEW_STEREO) { wnd.add_menu_item("Stereo Side", function () { extension.view_stereo = extension.GF_VIEW_STEREO_SIDE; - gpac.set_option("Compositor", "fpack", "side"); - gpac.set_option("Compositor", "stereo", "hmd"); + scene.set_option("Compositor", "fpack", "side"); + scene.set_option("Compositor", "stereo", "hmd"); } ); } else if (this.view_stereo==extension.GF_VIEW_STEREO_SIDE) { wnd.add_menu_item("Stereo Top", function () { extension.view_stereo = extension.GF_VIEW_STEREO_TOP; - gpac.set_option("Compositor", "fpack", "top"); - gpac.set_option("Compositor", "stereo", "hmd"); + scene.set_option("Compositor", "fpack", "top"); + scene.set_option("Compositor", "stereo", "hmd"); } ); } else { wnd.add_menu_item("Mono", function () { extension.view_stereo = extension.GF_VIEW_MONO; - gpac.set_option("Compositor", "fpack", "none"); - gpac.set_option("Compositor", "stereo", "none"); + scene.set_option("Compositor", "fpack", "none"); + scene.set_option("Compositor", "stereo", "none"); } ); } @@ -1560,7 +1563,7 @@ select_navigation_type: function () { var nb_items = 0; - var type = gpac.navigation; + var type = scene.navigation; if (this.navigation_wnd) { this.navigation_wnd.close(); return; @@ -1576,14 +1579,14 @@ wnd.select = function (type) { this.extension.navigation_wnd = null; if (type == 'reset') { - gpac.navigation_type = 0; + scene.navigation_type = 0; } else { - gpac.navigation = type; + scene.navigation = type; } } wnd.make_select_item = function (text, type, current_type) { if (current_type == type) text = '* ' + text; - if (gpac.navigation_supported(type)) { + if (scene.navigation_supported(type)) { wnd.add_menu_item(text, function () { this.select(type); }); } } @@ -1593,7 +1596,7 @@ wnd.make_select_item('Slide', GF_NAVIGATE_SLIDE, type); wnd.make_select_item('Examine', GF_NAVIGATE_EXAMINE, type); - if (gpac.navigation_type == GF_NAVIGATE_TYPE_3D) { + if (scene.navigation_type == GF_NAVIGATE_TYPE_3D) { wnd.make_select_item('Walk', GF_NAVIGATE_WALK, type); wnd.make_select_item('Fly', GF_NAVIGATE_FLY, type); wnd.make_select_item('Pan', GF_NAVIGATE_PAN, type); @@ -1788,10 +1791,10 @@ var t = new Date() stat_obj.time = Math.round(t.getTime() / 1000); - stat_obj.fps = Math.round(100 * gpac.fps) / 100; - stat_obj.cpu = gpac.cpu; - stat_obj.memory = Math.round(100 * gpac.memory / 1000 / 1000) / 100; - stat_obj.http_bandwidth = Math.round(gpac.http_bitrate); + stat_obj.fps = Math.round(100 * scene.fps) / 100; + stat_obj.cpu = Sys.process_cpu_usage; + stat_obj.memory = Math.round(100 * Sys.gpac_memory / 1000 / 1000) / 100; + stat_obj.http_bandwidth = Math.round(session.http_bitrate); stat_obj.bitrate = 0; stat_obj.buffer = 0; stat_obj.ntp_diff = 0;
View file
gpac-1.0.0.tar.gz/share/gui/extensions/player/playlist.js -> gpac-1.0.1.tar.gz/share/gui/extensions/player/playlist.js
Changed
@@ -89,7 +89,7 @@ fb.on_browse = function (value, directory) { this.playlist.show(); plist.add_files(value, false, false); - if (directory) gpac.last_working_directory = directory; + if (directory) Sys.last_wdir = directory; } fb.on_close = function () { @@ -113,7 +113,7 @@ item.set_size(popup.width, gwskin.default_control_height); item.dlg = popup; item.on_click = function() { - var filelist = gpac.enum_directory(path, '*', false); + var filelist = Sys.enum_directory(path, '*', false); item.dlg.fb.playlist.add_files(filelist, false, false); item.dlg.fb.close(); item.dlg.close(); @@ -122,7 +122,7 @@ item.set_size(popup.width, gwskin.default_control_height); item.dlg = popup; item.on_click = function() { - var filelist = gpac.enum_directory(path, '*', false); + var filelist = Sys.enum_directory(path, '*', false); item.dlg.fb.playlist.add_files(filelist, true, false); item.dlg.fb.close(); item.dlg.close(); @@ -200,7 +200,7 @@ obj.name = list[i].name; ar.push(obj); } - if (list.length) gpac.last_working_directory = list[0].path; + if (list.length) Sys.last_wdir = list[0].path; //sort if (!this._sort_type) { @@ -290,8 +290,12 @@ } plist.on_display_size = function (width, height) { - var w = 2*width / 3; - this.set_size(w, 0.8 * height); + if (gwskin.mobile_device) { + this.set_size(width, height); + } else { + var w = 2*width / 3; + this.set_size(w, 0.8 * height); + } } plist.on_display_size(gw_display_width, gw_display_height);
View file
gpac-1.0.0.tar.gz/share/gui/extensions/player/stats.js -> gpac-1.0.1.tar.gz/share/gui/extensions/player/stats.js
Changed
@@ -215,7 +215,12 @@ iw.area = gw_new_text_area(iw, ''); iw.on_display_size = function (width, height) { - var w = 30 * gwskin.default_text_font_size; + var w; + if (gwskin.mobile_device) { + w = width; + } else { + w = 30 * gwskin.default_text_font_size; + } var h = 2 * gwskin.default_icon_height + 11 * gwskin.default_text_font_size; this.set_size(w, h); } @@ -336,8 +341,8 @@ wnd.http_control = gw_new_slider(wnd.area); - if (gpac.http_max_bitrate) { - var br = Math.round(100 * gpac.http_max_bitrate / 1000 / 1000) / 100; + if (session.http_max_bitrate) { + var br = Math.round(100 * session.http_max_bitrate / 1000 / 1000) / 100; if (br > 200) br = 200; if (br <= 1) { v = 30 * br; @@ -350,7 +355,7 @@ } wnd.http_control.set_value(v); - wnd.http_text.set_label('HTTP cap ' + Math.round(gpac.http_max_bitrate / 10000)/100 + ' Mbps'); + wnd.http_text.set_label('HTTP cap ' + Math.round(session.http_max_bitrate / 10000)/100 + ' Mbps'); } else { wnd.http_control.set_value(100); wnd.http_text.set_label('HTTP cap off'); @@ -370,13 +375,13 @@ } if (br == 200) { this.text.set_label('HTTP cap off'); - gpac.http_max_bitrate = Math.round(0); + session.http_max_bitrate = Math.round(0); } else if (br == 0) { this.text.set_label('HTTP disable'); - gpac.http_max_bitrate = -1; + session.http_max_bitrate = -1; } else { this.text.set_label('HTTP cap ' + Math.round(100 * br) / 100 + ' Mbps'); - gpac.http_max_bitrate = Math.round(br * 1000000); + session.http_max_bitrate = Math.round(br * 1000000); } } @@ -434,8 +439,13 @@ var w; var h = 2 * gwskin.default_icon_height; - w = 20 * gwskin.default_text_font_size; - w += 4 * gwskin.default_icon_height; + if (gwskin.mobile_device) { + w = width; + } else { + w = 20 * gwskin.default_text_font_size; + w += 4 * gwskin.default_icon_height; + } + if (this.has_select) w += 6 * gwskin.default_icon_height; @@ -503,9 +513,10 @@ } } - var label = 'Statistics (' + gpac.nb_cores + ' cores - '; - if (gpac.system_memory > 1000000000) label += '' + Math.round(gpac.system_memory / 1000 / 1000 / 1000) + ' GB RAM)'; - else label += '' + Math.round(gpac.system_memory / 1000 / 1000) + ' MB RAM)'; + var label = 'Statistics (' + Sys.nb_cores + ' cores - '; + let mem = Sys.physical_memory; + if (mem > 1000000000) label += '' + Math.round(mem / 1000 / 1000 / 1000) + ' GB RAM)'; + else label += '' + Math.round(mem / 1000 / 1000) + ' MB RAM)'; wnd.set_label(label);
View file
gpac-1.0.0.tar.gz/share/gui/extensions/widget_manager/init.js -> gpac-1.0.1.tar.gz/share/gui/extensions/widget_manager/init.js
Changed
@@ -35,7 +35,7 @@ function scan_directory(dir) { var i, j, count, list, new_wid, uri; - list = gpac.enum_directory(dir, '.xml;.wgt;.mgt', 0); + list = Sys.enum_directory(dir, '.xml;.wgt;.mgt', 0); for (i=0; i<list.length; i++) { uri = list[i].path + list[i].name; if (list[i].directory) { @@ -186,7 +186,7 @@ gw_new_text(info_dlg.area, 'Widget was pushed from device IP '+wid.originating_device_ip, 'text' ); } gw_new_text(info_dlg.area, 'Section name in GPAC config file: '+wid.section, 'text' ); - gw_new_text(info_dlg.area, 'UA Locale: ' + gpac.get_option('core', 'lang'), 'text'); + gw_new_text(info_dlg.area, 'UA Locale: ' + scene.get_option('core', 'lang'), 'text'); gw_new_text(info_dlg.area, 'widget src: ' + wid.url , 'text'); gw_new_text(info_dlg.area, 'config src: ' + wid.manifest , 'text'); gw_new_text(info_dlg.area, 'content src : '+wid.localizedSrc, 'text' ); @@ -208,7 +208,7 @@ info = collapsable_list(info_dlg, 'Preferences'); for (j=0; j<pref.length; j++) { var val = pref[j].value; - if (val == '') val = gpac.get_option(wid.section, pref[j].name); + if (val == '') val = scene.get_option(wid.section, pref[j].name); gw_new_text(info_dlg.area, 'Preference #'+(j+1)+' name=\''+pref[j].name+'\' value=\''+val+'\' readOnly=\''+pref[j].readonly +'\'', 'text'); } info.last_idx = info_dlg.area.get_children().length;
View file
gpac-1.0.0.tar.gz/share/gui/gui.js -> gpac-1.0.1.tar.gz/share/gui/gui.js
Changed
@@ -4,9 +4,12 @@ // Jean Le Feuvre, (c) 2010-2020 Telecom Paris // ///////////////////////////////////////////////////////////////////////////////// -import {gpac} from 'scenejs' +import {scene} from 'scenejs' import {Storage} from 'storage' -globalThis.gpac = gpac; +import {Sys} from 'gpaccore' + +globalThis.scene = scene; +globalThis.Sys = Sys; let all_extensions = []; @@ -82,19 +85,19 @@ //var icon; var i, count, wid; - gpac.caption = 'Osmo4'; + scene.caption = 'Osmo4'; - gw_display_width = parseInt(gpac.get_option('General', 'LastWidth')); - gw_display_height = parseInt(gpac.get_option('General', 'LastHeight')); - if (!gpac.fullscreen && (!gw_display_width || !gw_display_height)) { + gw_display_width = parseInt(scene.get_option('General', 'LastWidth')); + gw_display_height = parseInt(scene.get_option('General', 'LastHeight')); + if (!scene.fullscreen && (!gw_display_width || !gw_display_height)) { gw_display_width = 320; gw_display_height = 240; } - if (!gpac.fullscreen && gw_display_width && gw_display_height) { - gpac.set_size(gw_display_width, gw_display_height); + if (!scene.fullscreen && gw_display_width && gw_display_height) { + scene.set_size(gw_display_width, gw_display_height); } else { - gw_display_width = gpac.screen_width; - gw_display_height = gpac.screen_height; + gw_display_width = scene.screen_width; + gw_display_height = scene.screen_height; } //request event listeners on the window - GPAC specific BIFS extensions !!! We don't allow using the event proc for size events root.addEventListener('resize', on_resize, 0); @@ -126,7 +129,8 @@ /*init all extensions*/ - var list = gpac.enum_directory('extensions', '*', 0); + let path = scene.current_path; + var list = Sys.enum_directory(path + 'extensions', '*', 0); for (i=0; i<list.length; i++) { if (!list[i].directory) continue; @@ -192,13 +196,13 @@ } } - var i, argc = gpac.argc; + var i; - for (i = 1; i < argc; i++) { - var arg = gpac.get_arg(i); + for (i = 1; i < Sys.args.length; i++) { + var arg = Sys.args[i]; if (arg=='-h') { print_help(); - gpac.exit(); + scene.exit(); return; } } @@ -269,19 +273,19 @@ function on_resize(evt) { if ((gw_display_width == evt.width) && (gw_display_height == evt.height)) return; if (evt.width <=100) { - gpac.set_size(100, gw_display_height); + scene.set_size(100, gw_display_height); return; } if (evt.height <=80) { - gpac.set_size(gw_display_width, 40); + scene.set_size(gw_display_width, 40); return; } gw_display_width = evt.width; gw_display_height = evt.height; - if (!gpac.fullscreen) { - gpac.set_option('General', 'LastWidth', '' + gw_display_width); - gpac.set_option('General', 'LastHeight', '' + gw_display_height); + if (!scene.fullscreen) { + scene.set_option('General', 'LastWidth', '' + gw_display_width); + scene.set_option('General', 'LastHeight', '' + gw_display_height); } /* var v = 12;
View file
gpac-1.0.0.tar.gz/share/gui/gwlib.js -> gpac-1.0.1.tar.gz/share/gui/gwlib.js
Changed
@@ -447,9 +447,9 @@ gwskin.enable_background = function(do_enable) { if (do_enable) { - gpac.set_back_color(gwskin.back_color.r, gwskin.back_color.g, gwskin.back_color.b, 1.0); + scene.set_back_color(gwskin.back_color.r, gwskin.back_color.g, gwskin.back_color.b, 1.0); } else { - gpac.set_back_color(0, 0, 0, 1.0); + scene.set_back_color(0, 0, 0, 1.0); } } @@ -966,7 +966,7 @@ } if (typeof (wnd._no_focus) == 'boolean') return; if (gwskin.focus_on) - gpac.set_focus(gw_ui_top_wnd); + scene.set_focus(gw_ui_top_wnd); } gw_ui_root.remove_focus = function(wnd) { @@ -983,7 +983,7 @@ } if (typeof (wnd._no_focus) == 'boolean') return; if (gwskin.focus_on) - gpac.set_focus(gw_ui_top_wnd); + scene.set_focus(gw_ui_top_wnd); } gw_ui_root.add_child = function (child) { @@ -998,31 +998,31 @@ gw_ui_top_wnd = null; gw_event_filters = []; - gpac.set_event_filter(gwlib_filter_event); - gwskin.has_opengl = gpac.has_opengl; + scene.set_event_filter(gwlib_filter_event); + gwskin.has_opengl = scene.has_opengl; - gwskin.browser_mode = (gpac.get_option('Temp', 'BrowserMode') == 'yes') ? true : false; + gwskin.browser_mode = (scene.get_option('Temp', 'BrowserMode') == 'yes') ? true : false; - gpac.focus_highlight = false; + scene.focus_highlight = false; gwskin.disable_transparency = false; //remove window gradients - if (!gwskin.has_opengl && !gpac.hardware_rgba) { + if (!gwskin.has_opengl && !scene.hardware_rgba) { s = gwskin.get_style('window', 'normal'); s.texture = null; gwskin.disable_transparency = true; gwskin.default_window_alpha = 1; } - var device = gpac.get_option('core', 'devclass'); + var device = scene.get_option('core', 'devclass'); if ((device == 'ios') || (device == 'android')) gwskin.mobile_device = true; else gwskin.mobile_device = false; if (gwskin.mobile_device) { - var size = gw_display_width; - if (size> gw_display_height) size = gw_display_height; - gwskin_set_default_control_height(size/3); - gwskin_set_default_icon_height(size/3); + var size = scene.screen_width; + if (size > scene.screen_height) size = scene.screen_height; + gwskin_set_default_control_height(size/6); + gwskin_set_default_icon_height(size/12); } gwskin_set_white_blue(); @@ -1165,7 +1165,7 @@ } } //trigger GC whenever we have closed a child list - gpac.trigger_gc(); + scene.trigger_gc(); } @@ -2115,7 +2115,7 @@ return false; } this._idx = idx; - gpac.set_focus(this.children[idx]); + scene.set_focus(this.children[idx]); return true; } return false; @@ -2236,7 +2236,7 @@ if (dlg.current_focus == -1) { if (type == 'Left') return false; dlg.current_focus = 0; - gpac.set_focus(children[0]); + scene.set_focus(children[0]); return true; } @@ -2246,7 +2246,7 @@ var tr = children[dlg.current_focus].translation.y - children[dlg.current_focus].height / 2; if (dlg.current_focus + 1 == children.length) { dlg.current_focus = orig_focus; - gpac.set_focus(children[dlg.current_focus]); + scene.set_focus(children[dlg.current_focus]); return false; } /*goto right item*/ @@ -2257,7 +2257,7 @@ break; if (dlg.current_focus + 1 == children.length) { dlg.current_focus = orig_focus; - gpac.set_focus(children[dlg.current_focus]); + scene.set_focus(children[dlg.current_focus]); return false; } dlg.current_focus++; @@ -2275,7 +2275,7 @@ var tr = children[dlg.current_focus].translation.y + children[dlg.current_focus].height / 2; if (!dlg.current_focus) { dlg.current_focus = -1; - gpac.set_focus(null); + scene.set_focus(null); return false; } /*goto left item*/ @@ -2371,7 +2371,7 @@ return grid_event_navigate(dlg, children, type); } - gpac.set_focus(children[dlg.current_focus]); + scene.set_focus(children[dlg.current_focus]); return true; } @@ -2431,7 +2431,7 @@ if (this.current_focus >= 0) { if (this.current_focus < child) this.current_focus = child; else if (this.current_focus >= last_child) this.current_focus = last_child - 1; - gpac.set_focus(this._all_children[this.current_focus]); + scene.set_focus(this._all_children[this.current_focus]); } @@ -2903,7 +2903,7 @@ gw_add_child(obj, rect); gw_object_set_hitable(rect); rect.on_down = function (val) { - if (val) gpac.set_focus(this.parent.children[1]); + if (val) scene.set_focus(this.parent.children[1]); } edit = gw_new_text(obj, text_data, 'edit') @@ -3185,10 +3185,10 @@ var idx = 0; while (1) { - var mime = gpac.get_option('MimeTypes', idx); + var mime = scene.get_option('MimeTypes', idx); if (mime == null) break; idx++; - var mime_ext = gpac.get_option('MimeTypes', mime).split('"')[1]; + var mime_ext = scene.get_option('MimeTypes', mime).split('"')[1]; if (!mime_ext.match(reg)) continue; if (mime.indexOf('video') != -1) return gwskin.images.mime_video; @@ -3376,11 +3376,16 @@ } else { if (dir) this.directory = dir; if (up && !this.path) up = false; - filelist = gpac.enum_directory(this.directory, this.filter, up); + filelist = Sys.enum_directory(this.directory, this.filter, up); if (filelist.length) { + let dir_name = filelist[0].path; + dir_name = dir_name.substr(0, dir_name.lastIndexOf("/")); + dir_name = dir_name.split('/').pop(); + if (dir_name.length == 0) dir_name = "/"; + this.directory = filelist[0].path; - this.set_label(this.directory); + this.set_label(dir_name); } else { this.set_label(''); } @@ -3410,7 +3415,8 @@ if ( (!is_listing || (typeof filelist[i].directory == 'boolean')) && (filelist[i].directory || (filelist[i].name.indexOf('.') < 0))) { if (filelist[i].drive) icon_name = gwskin.images.drive; - else icon_name = gwskin.images.folder; + else if (filelist[i].directory) icon_name = gwskin.images.folder; + else icon_name = gwskin.images.mime_generic; } else { icon_name = gw_guess_mime_icon(is_listing ? f_path : f_name); }
View file
gpac-1.0.0.tar.gz/share/scripts/ttml-renderer.js -> gpac-1.0.1.tar.gz/share/scripts/ttml-renderer.js
Changed
@@ -44,7 +44,7 @@ ttml_dbg_msg("TTML Rendered Loaded size: " + width + "x" + height); -//filter-assignable variables - if changing names, also do it in filters/dec_webvtt.c +//filter-assignable variables - if changing names, also do it in filters/dec_ttml.c var xOffset = 5; var yOffset = 5; var fontSize = 20; @@ -79,6 +79,11 @@ ttml_dbg_msg("Creating textArea size " + w + " x " + h + " - xoffset: " + xOffset); t.setAttribute("fill", textColor); + + if (height>=720) { + fontSize = height * 0.05; + } + t.setAttribute("font-size", fontSize); t.setAttribute("font-family", fontFamily); t.setAttribute("text-align", settings.align); @@ -110,11 +115,11 @@ } span.textContent = text; parent.appendChild(span); - ttml_dbg_msg("tspan created "+span + " in " + parent); + ttml_dbg_msg("tspan created "+span + " in " + parent.tagName); return span; } -function parse_sample_settings(ttmldoc, tsample) +function parse_sample_settings(ttmldoc, tsample, reg_id) { ttml_dbg_msg("Parsing sample settings"); var obj = {}; @@ -125,6 +130,28 @@ obj.size *= width/100; obj.align = "center"; + + //todo, parse style and region attributes... +/* + if (reg_id==="") + return obj; + + var region = ttmldoc.getElementById(reg_id); + if (region==null) { + ttml_dbg_msg("region not found: "+reg_id); + return obj; + } + var styles = region.getElementsByTagName("style"); + if (styles.length==0) { + ttml_dbg_msg("region found but no styles"); + return obj; + } + var style = styles.item(0); + var offset = style.getAttribute('offset'); + var extend = style.getAttribute('extent'); + var disp_align = style.getAttribute('displayAlign'); +*/ + return obj; } @@ -189,7 +216,9 @@ { ttml_dbg_msg("TTML sample at " + scene_time + " pck dur " + pck_dur); + sample_end = 0; display_area.textContent = ''; + var body = ttmldoc.getElementsByTagName("body"); var samples = ttmldoc.getElementsByTagName("p"); var styles = {"italic": 0, "underlined": 0, "bold": 0}; @@ -197,6 +226,11 @@ alert("TTML sample has " + samples.length + " defined, only the last sample will be displayed"); } ttml_dbg_msg(samples.length + " text samples"); + var body_region = ""; + if (body.length) { + var b = body.item(0); + body_region = b.getAttribute('region'); + } for (var i=0; i<samples.length; i++) { var sample_start = 0; var s = samples.item(i); @@ -204,20 +238,23 @@ var end = s.getAttribute('end'); var region = s.getAttribute('region'); var id = s.getAttribute('id'); + if (region==="") region = body_region; sample_end = parse_time(end); if (begin) sample_start = parse_time(begin); - ttml_dbg_msg("sample start: " + sample_start + " end: " + sample_end + " region " + region + " id " + id); - - if (sample_start < scene_time) - break; + ttml_dbg_msg("sample start: " + sample_start + " end: " + sample_end + " scenetime: " + scene_time + " region: " + region + " id: " + id); + //we're late but check if sample not over + if (sample_start < scene_time) { +// if (sample_end < scene_time) +// break; + } if (sample_end < scene_time) continue; - var settings = parse_sample_settings(ttmldoc, s); + var settings = parse_sample_settings(ttmldoc, s, region); var tA = create_text_area(settings); push_ttml_text_node(tA, s, styles); } @@ -227,11 +264,14 @@ function on_ttml_clock(scene_time) { + if (!sample_end) return 0; + if (sample_end > scene_time) { - ttml_dbg_msg("not over yet: " + scene_time + " vs last end " + sample_end); + //ttml_dbg_msg("not over yet: " + scene_time + " vs last end " + sample_end); return sample_end - scene_time; } - ttml_dbg_msg("sample is over "); + ttml_dbg_msg("sample is over (end: " + sample_end + " - now: " + scene_time + ")" ); display_area.textContent = ''; + sample_end = 0; return 0; }
View file
gpac-1.0.0.tar.gz/share/vis/Code/Console.js -> gpac-1.0.1.tar.gz/share/vis/Code/Console.js
Changed
@@ -19,9 +19,9 @@ // This accumulates log text as fast as is required this.PageTextBuffer = ""; - this.LastPageTextBufferLen = 0; + this.PageTextUpdatePending = false; this.AppTextBuffer = ""; - this.LastAppTextBufferLen = 0; + this.AppTextUpdatePending = false; // Setup command history control this.CommandHistory = LocalStore.Get("App", "Global", "CommandHistory", [ ]); @@ -37,12 +37,15 @@ this.Server = server; server.SetConsole(this); server.AddMessageHandler("LOGM", Bind(OnLog, this)); + + this.Window.SetOnResize(Bind(OnUserResize, this)); } Console.prototype.Log = function(text) { this.PageTextBuffer = LogText(this.PageTextBuffer, text); + this.PageTextUpdatePending = true; } @@ -52,24 +55,16 @@ this.Window.SetPosition(BORDER, height - BORDER - 200); this.Window.SetSize(width - 2 * BORDER, HEIGHT); - // Place controls - var parent_size = this.Window.Size; - var mid_w = parent_size[0] / 3; - this.UserInput.SetPosition(BORDER, parent_size[1] - 2 * BORDER - 30); - this.UserInput.SetSize(parent_size[0] - 100, 18); - var output_height = this.UserInput.Position[1] - 2 * BORDER; - this.PageContainer.SetPosition(BORDER, BORDER); - this.PageContainer.SetSize(mid_w - 2 * BORDER, output_height); - this.AppContainer.SetPosition(mid_w, BORDER); - this.AppContainer.SetSize(parent_size[0] - mid_w - BORDER, output_height); + ResizeInternals(this); } function OnLog(self, socket, data_view) { - var data_view_reader = new DataViewReader(data_view, 4); - var text = data_view_reader.GetString(); - self.AppTextBuffer = LogText(self.AppTextBuffer, text); + var data_view_reader = new DataViewReader(data_view, 4); + var text = data_view_reader.GetString(); + self.AppTextBuffer = LogText(self.AppTextBuffer, text); + self.AppTextUpdatePending = true; } @@ -97,25 +92,44 @@ return existing_text; } + function OnUserResize(self, evt) + { + ResizeInternals(self); + } + + function ResizeInternals(self) + { + // Place controls + var parent_size = self.Window.Size; + var mid_w = parent_size[0] / 3; + self.UserInput.SetPosition(BORDER, parent_size[1] - 2 * BORDER - 30); + self.UserInput.SetSize(parent_size[0] - 100, 18); + var output_height = self.UserInput.Position[1] - 2 * BORDER; + self.PageContainer.SetPosition(BORDER, BORDER); + self.PageContainer.SetSize(mid_w - 2 * BORDER, output_height); + self.AppContainer.SetPosition(mid_w, BORDER); + self.AppContainer.SetSize(parent_size[0] - mid_w - BORDER, output_height); + } + function UpdateHTML(self) { // Reset the current text buffer as html - if (self.LastPageTextBufferLen != self.PageTextBuffer.length) + if (self.PageTextUpdatePending) { var page_node = self.PageContainer.Node; page_node.innerHTML = self.PageTextBuffer; page_node.scrollTop = page_node.scrollHeight; - self.LastPageTextBufferLen = self.PageTextBuffer.length; + self.PageTextUpdatePending = false; } - if (self.LastAppTextBufferLen != self.AppTextBuffer.length) - { + if (self.AppTextUpdatePending) + { var app_node = self.AppContainer.Node; app_node.innerHTML = self.AppTextBuffer; app_node.scrollTop = app_node.scrollHeight; - self.LastAppTextBufferLen = self.AppTextBuffer.length; + self.AppTextUpdatePending = false; } }
View file
gpac-1.0.0.tar.gz/share/vis/Code/SampleWindow.js -> gpac-1.0.1.tar.gz/share/vis/Code/SampleWindow.js
Changed
@@ -12,11 +12,11 @@ this.XPos = 10 + offset * 410; this.Window = wm.AddWindow(name, 100, 100, 100, 100); - this.Window.Show(); + this.Window.ShowNoAnim(); this.Visible = true; // Create a grid that's indexed by the unique sample ID - this.Grid = this.Window.AddControlNew(new WM.Grid(0, 0, 380, "calc( 100% - 17px )")); + this.Grid = this.Window.AddControlNew(new WM.Grid()); var cell_data = { Name: "Samples",
View file
gpac-1.0.0.tar.gz/share/vis/Code/TimelineWindow.js -> gpac-1.0.1.tar.gz/share/vis/Code/TimelineWindow.js
Changed
@@ -14,7 +14,6 @@ var box_template = "<div class='TimelineBox'></div>"; - function TimelineWindow(wm, settings, server, check_handler) { this.Settings = settings; @@ -33,6 +32,7 @@ // Setup timeline manipulation this.MouseDown = false; + this.LastMouseState = null; this.TimelineMoved = false; this.OnHoverHandler = null; this.OnSelectedHandler = null; @@ -44,6 +44,8 @@ this.TimeRange = new PixelTimeRange(0, 200 * 1000, RowWidth(this)); this.CheckHandler = check_handler; + + this.Window.SetOnResize(Bind(OnUserResize, this)); } @@ -58,30 +60,14 @@ this.OnSelectedHandler = handler; } - TimelineWindow.prototype.WindowResized = function(width, height, top_window) { // Resize window var top = top_window.Position[1] + top_window.Size[1] + 10; this.Window.SetPosition(10, top); - this.Window.SetSize(width - 2 * 10, 200); - - // Resize controls - var parent_size = this.Window.Size; - this.TimelineContainer.SetPosition(BORDER, 10); - this.TimelineContainer.SetSize(parent_size[0] - 2 * BORDER, 160); - - // Resize rows - var row_width = RowWidth(this); - for (var i in this.ThreadRows) - { - var row = this.ThreadRows[i]; - row.SetSize(row_width); - } + this.Window.SetSize(width - 2 * 10, 260); - // Adjust time range to new width - this.TimeRange.SetPixelSpan(row_width); - this.DrawAllRows(); + ResizeInternals(this); } @@ -148,6 +134,31 @@ return self.TimelineContainer.Size[0] - (ROW_START_SIZE + ROW_END_SIZE); } + function OnUserResize(self, evt) + { + ResizeInternals(self); + } + + function ResizeInternals(self) + { + // Resize controls + var parent_size = self.Window.Size; + self.TimelineContainer.SetPosition(BORDER, 10); + self.TimelineContainer.SetSize(parent_size[0] - 2 * BORDER, parent_size[1] - 40); + + // Resize rows + var row_width = RowWidth(self); + for (var i in self.ThreadRows) + { + var row = self.ThreadRows[i]; + row.SetSize(row_width); + } + + // Adjust time range to new width + self.TimeRange.SetPixelSpan(row_width); + self.DrawAllRows(); + } + function OnMouseScroll(self, evt) { @@ -179,6 +190,7 @@ return; self.MouseDown = true; + self.LastMouseState = new Mouse.State(evt); self.TimelineMoved = false; DOM.Event.StopDefaultAction(evt); } @@ -231,7 +243,7 @@ var time_us = self.TimeRange.Start_us + x / self.TimeRange.usPerPixel; // Shift the visible time range with mouse movement - var time_offset_us = mouse_state.PositionDelta[0] / self.TimeRange.usPerPixel; + var time_offset_us = (mouse_state.Position[0] - self.LastMouseState.Position[0]) / self.TimeRange.usPerPixel; if (time_offset_us) { self.TimeRange.SetStart(self.TimeRange.Start_us - time_offset_us); @@ -262,6 +274,8 @@ } } } + + self.LastMouseState = mouse_state; }
View file
gpac-1.0.0.tar.gz/share/vis/Code/TitleWindow.js -> gpac-1.0.1.tar.gz/share/vis/Code/TitleWindow.js
Changed
@@ -18,6 +18,8 @@ this.PauseButton.SetOnClick(Bind(OnPausePressed, this)); server.AddMessageHandler("PING", Bind(OnPing, this)); + + this.Window.SetOnResize(Bind(OnUserResize, this)); } @@ -30,7 +32,17 @@ TitleWindow.prototype.WindowResized = function(width, height) { this.Window.SetSize(width - 2 * 10, 50); - this.PauseButton.SetPosition(width - 80, 5); + ResizeInternals(this); + } + + function OnUserResize(self, evt) + { + ResizeInternals(self); + } + + function ResizeInternals(self) + { + self.PauseButton.SetPosition(self.Window.Size[0] - 60, 5); }
View file
gpac-1.0.0.tar.gz/share/vis/Styles/Remotery.css -> gpac-1.0.1.tar.gz/share/vis/Styles/Remotery.css
Changed
@@ -6,43 +6,12 @@ height: 100%; margin: 0px; - background-color: #AAA; -} - + background-color: #999; -.NoSelect -{ - /* Disable text selection so that it doesn't interfere with faux-button clicking */ - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - /* Stops the text cursor over the label */ - cursor:default; + touch-action: none; } -/* Override default window styles to remove 3D effect */ -.Window -{ - background: #555; - box-shadow: none; - border-radius: 3px; -} -/*.WindowTitleBar -{ - border-bottom: none; - border-radius: 0px; -} -.WindowBody -{ - border-top: none; -}*/ - - /* Override default container style to remove 3D effect */ .Container {
View file
gpac-1.0.0.tar.gz/share/vis/extern/BrowserLib/Core/Code/Core.js -> gpac-1.0.1.tar.gz/share/vis/extern/BrowserLib/Core/Code/Core.js
Changed
@@ -17,4 +17,10 @@ parent_ns = parent_ns[ns_name]; } -} \ No newline at end of file +} + + +function multiline(fn) +{ + return fn.toString().split(/\n/).slice(1, -1).join("\n"); +}
View file
gpac-1.0.0.tar.gz/share/vis/extern/BrowserLib/WindowManager/Code/Grid.js -> gpac-1.0.1.tar.gz/share/vis/extern/BrowserLib/WindowManager/Code/Grid.js
Changed
@@ -210,23 +210,19 @@ </div>"; - function Grid(x, y, width, height) + function Grid() { this.Rows = new WM.GridRows(this); this.Node = DOM.Node.CreateHTML(template_html); this.BodyNode = DOM.Node.FindWithClass(this.Node, "GridBody"); - DOM.Node.SetPosition(this.Node, [ x, y ]); - DOM.Node.SetSize(this.Node, [ width, height ]); - DOM.Event.AddHandler(this.Node, "dblclick", OnDblClick); var mouse_wheel_event = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel"; DOM.Event.AddHandler(this.Node, mouse_wheel_event, Bind(OnMouseScroll, this)); } - function OnDblClick(evt) { // Clicked on a header?
View file
gpac-1.0.0.tar.gz/share/vis/extern/BrowserLib/WindowManager/Code/Window.js -> gpac-1.0.1.tar.gz/share/vis/extern/BrowserLib/WindowManager/Code/Window.js
Changed
@@ -4,15 +4,17 @@ WM.Window = (function() { - var template_html = " \ - <div class='Window'> \ - <div class='WindowTitleBar'> \ - <div class='WindowTitleBarText notextsel' style='float:left'>Window Title Bar</div> \ - <div class='WindowTitleBarClose notextsel' style='float:right'>O</div> \ - </div> \ - <div class='WindowBody'> \ - </div> \ - </div>"; + var template_html = multiline(function(){/* \ + <div class='Window'> + <div class='WindowTitleBar'> + <div class='WindowTitleBarText notextsel' style='float:left'>Window Title Bar</div> + <div class='WindowTitleBarClose notextsel' style='float:right'>✕</div> + </div> + <div class='WindowBody'> + </div> + <div class='WindowResizeHandle notextsel'>⋰</div> + </div> + */}); function Window(manager, title, x, y, width, height, parent_node) @@ -20,6 +22,7 @@ this.Manager = manager; this.ParentNode = parent_node || document.body; this.OnMove = null; + this.OnResize = null; this.Visible = false; this.AnimatedShow = false; @@ -28,6 +31,7 @@ this.TitleBarNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBar"); this.TitleBarTextNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarText"); this.TitleBarCloseNode = DOM.Node.FindWithClass(this.Node, "WindowTitleBarClose"); + this.ResizeHandleNode = DOM.Node.FindWithClass(this.Node, "WindowResizeHandle"); this.BodyNode = DOM.Node.FindWithClass(this.Node, "WindowBody"); // Setup the position and dimensions of the window @@ -40,19 +44,26 @@ // Hook up event handlers DOM.Event.AddHandler(this.Node, "mousedown", Bind(this, "SetTop")); DOM.Event.AddHandler(this.TitleBarNode, "mousedown", Bind(this, "BeginMove")); - DOM.Event.AddHandler(this.TitleBarCloseNode, "mousedown", Bind(this, "Hide")); + DOM.Event.AddHandler(this.ResizeHandleNode, "mousedown", Bind(this, "BeginResize")); + DOM.Event.AddHandler(this.TitleBarCloseNode, "mouseup", Bind(this, "Hide")); // Create delegates for removable handlers this.MoveDelegate = Bind(this, "Move"); - this.EndMoveDelegate = Bind(this, "EndMove"); + this.EndMoveDelegate = Bind(this, "EndMove") + this.ResizeDelegate = Bind(this, "Resize"); + this.EndResizeDelegate = Bind(this, "EndResize"); } - Window.prototype.SetOnMove = function(on_move) { this.OnMove = on_move; } + Window.prototype.SetOnResize = function(on_resize) + { + this.OnResize = on_resize; + } + Window.prototype.Show = function() { @@ -73,9 +84,9 @@ } - Window.prototype.Hide = function() + Window.prototype.Hide = function(evt) { - if (this.Node.parentNode == this.ParentNode) + if (this.Node.parentNode == this.ParentNode && evt.button == 0) { if (this.AnimatedShow) { @@ -218,6 +229,45 @@ DOM.Event.StopDefaultAction(evt); } + + Window.prototype.BeginResize = function(evt) + { + // Calculate offset of the window from the mouse down position + var mouse_pos = DOM.Event.GetMousePosition(evt); + this.MousePosBeforeResize = [ mouse_pos[0], mouse_pos[1] ]; + this.SizeBeforeResize = this.Size; + + // Dynamically add handlers for movement and release + DOM.Event.AddHandler(document, "mousemove", this.ResizeDelegate); + DOM.Event.AddHandler(document, "mouseup", this.EndResizeDelegate); + + DOM.Event.StopDefaultAction(evt); + } + + + Window.prototype.Resize = function(evt) + { + // Use the offset at the beginning of movement to drag the window around + var mouse_pos = DOM.Event.GetMousePosition(evt); + var offset = [ mouse_pos[0] - this.MousePosBeforeResize[0], mouse_pos[1] - this.MousePosBeforeResize[1] ]; + this.SetSize(this.SizeBeforeResize[0] + offset[0], this.SizeBeforeResize[1] + offset[1]); + + if (this.OnResize) + this.OnResize(this, this.Size); + + DOM.Event.StopDefaultAction(evt); + } + + + Window.prototype.EndResize = function(evt) + { + // Remove handlers added during mouse down + DOM.Event.RemoveHandler(document, "mousemove", this.ResizeDelegate); + DOM.Event.RemoveHandler(document, "mouseup", this.EndResizeDelegate); + + DOM.Event.StopDefaultAction(evt); + } + Window.prototype.SetPosition = function(x, y) { @@ -228,6 +278,8 @@ Window.prototype.SetSize = function(w, h) { + w = Math.max(80, w); + h = Math.max(15, h); this.Size = [ w, h ]; DOM.Node.SetSize(this.Node, this.Size); }
View file
gpac-1.0.0.tar.gz/share/vis/extern/BrowserLib/WindowManager/Styles/WindowManager.css -> gpac-1.0.1.tar.gz/share/vis/extern/BrowserLib/WindowManager/Styles/WindowManager.css
Changed
@@ -3,7 +3,12 @@ .notextsel { /* Disable text selection so that it doesn't interfere with button-clicking */ - user-select:none; + user-select: none; + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer */ + -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */ + -webkit-user-select: none; /* Chrome, Safari, and Opera */ + -webkit-touch-callout: none; /* Disable Android and iOS callouts*/ /* Stops the text cursor over the label */ cursor:default; @@ -15,24 +20,75 @@ /* Window Styles */ /* ------------------------------------------------------------------------------------------------------------------ */ - +body +{ + /* Clip contents to browser window without adding scrollbars */ + overflow: hidden; +} .Window { - /* Allows movement of the window to exceed browser region without triggering scroll bars */ - position:fixed; + position:absolute; /* Clip all contents to the window border */ overflow: hidden; - background: #404040; + background: #555; - border-radius: 5px; + /*padding: 0px !important;*/ + + border-radius: 3px; -moz-border-radius: 5px; - -webkit-box-shadow: 3px 3px 3px #111, 1px 1px 1px #606060 inset; - box-shadow: 3px 3px 3px #111, 1px 1px 1px #606060 inset; + -webkit-box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset; + box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset; +} + +/*:root +{ + --SideBarSize: 5px; +} + +.WindowBodyDebug +{ + color: #BBB; + font: 9px Verdana; + white-space: nowrap; +} + +.WindowSizeLeft +{ + position: absolute; + left: 0px; + top: 0px; + width: var(--SideBarSize); + height: 100%; +} +.WindowSizeRight +{ + position: absolute; + left: calc(100% - var(--SideBarSize)); + top:0px; + width: var(--SideBarSize); + height:100%; } +.WindowSizeTop +{ + position: absolute; + left: 0px; + top: 0px; + width: 100%; + height: var(--SideBarSize); +} +.WindowSizeBottom +{ + position: absolute; + left: 0px; + top: calc(100% - var(--SideBarSize)); + width: 100%; + height: var(--SideBarSize); +}*/ + .Window_Transparent { @@ -52,6 +108,7 @@ { height: 17px; cursor: move; + /*overflow: hidden;*/ border-bottom: 1px solid #303030; border-radius: 5px; @@ -61,6 +118,7 @@ { color: #BBB; font: 9px Verdana; + /*white-space: nowrap;*/ padding: 3px; cursor: move; @@ -75,17 +133,32 @@ cursor: default; } -.WindowBody -{ - /* Turns this node into a "positioned node" so that its children can be placed relative to it */ - position: absolute; +.WindowTitleBarClose:hover { + color: #bbb; +} - /* Fill the parent window node */ - width: 100%; - height: 100%; +.WindowResizeHandle +{ + color: #999999; + font: 17px Verdana; + padding: 3px; + cursor: se-resize; + position: absolute; + bottom: -7px; + right: -3px; +} - padding:10px; - border-top: 1px solid #606060; +.WindowBody { + position: absolute; + /* overflow: hidden; */ + display: block; + padding: 10px; + border-top: 1px solid #606060; + top: 18px; + left: 0; + right: 0; + bottom: 0; + height: auto; } @@ -101,6 +174,9 @@ /* Position relative to the parent window */ position: absolute; + /* Clip contents */ + /*overflow: hidden;*/ + background:#2C2C2C; border: 1px black solid; @@ -110,6 +186,39 @@ box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset; } +/*.Panel +{*/ + /* Position relative to the parent window */ + /*position: absolute;*/ + + /* Clip contents */ + /*overflow: hidden; + + background:#2C2C2C; + + border: 1px black solid;*/ + + /* Two inset box shadows to simulate depressing */ + /*-webkit-box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset; + box-shadow: -1px -1px 1px #222 inset, 1px 1px 1px #222 inset;*/ +/*}*/ + + +/* ------------------------------------------------------------------------------------------------------------------ */ +/* Ruler Styles */ +/* ------------------------------------------------------------------------------------------------------------------ */ + + + +/*.Ruler +{ + position: absolute; + + border: dashed 1px; + + opacity: 0.35; +}*/ + /* ------------------------------------------------------------------------------------------------------------------ */ @@ -246,7 +355,7 @@ /* ------------------------------------------------------------------------------------------------------------------ */ -/* Treeview Styles */ +/* Edit Box Styles */ /* ------------------------------------------------------------------------------------------------------------------ */ @@ -429,17 +538,11 @@ /* ------------------------------------------------------------------------------------------------------------------ */ - -.Grid -{ - /* Clip contents */ - overflow: hidden; - - position: relative; - - background: #333; - - border-radius: 2px; +.Grid { + overflow: auto; + background: #333; + height: 100%; + border-radius: 2px; } .GridBody @@ -517,10 +620,7 @@ /* Position relative to the parent window */ position:absolute; - border-radius:6px; - border-color:#000; - border-width:1px; - border-style:solid; + border-radius:4px; /* Padding at the top includes 2px for the text drop-shadow */ padding: 2px 5px 3px 5px; @@ -530,18 +630,18 @@ text-shadow: 1px 1px 1px black; text-align: center; - /* The gradient for the button background */ - background-color:#666; - background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#383838)); - background: -moz-linear-gradient(top, #666, #383838); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666', endColorstr='#383838'); + background-color:#555; /* A box shadow and inset box highlight */ -webkit-box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset; box-shadow: 1px 1px 1px #222, 1px 1px 1px #777 inset; } -.ButtonHeld +.Button:hover { + background-color: #616161; +} + +.Button.ButtonHeld { /* Reset the gradient to a full-colour background */ background:#383838;
View file
gpac-1.0.0.tar.gz/src/Makefile -> gpac-1.0.1.tar.gz/src/Makefile
Changed
@@ -4,67 +4,68 @@ CFLAGS=-I"$(SRC_PATH)/include" $(OPTFLAGS) -ifeq ($(DEBUGBUILD), yes) +ifeq ($(DEBUGBUILD),yes) CFLAGS+=-g LDFLAGS+=-g endif -ifeq ($(GPROFBUILD), yes) +ifeq ($(GPROFBUILD),yes) CFLAGS+=-pg LDFLAGS+=-pg endif ## libgpac objects gathering: src/utils LIBGPAC_UTILS=utils/os_divers.o utils/os_file.o utils/list.o utils/bitstream.o utils/constants.o utils/error.o utils/alloc.o utils/url.o utils/configfile.o utils/gltools.o utils/gzio.o -ifeq ($(DISABLE_CORE_TOOLS), no) +ifeq ($(DISABLE_CORE_TOOLS),no) LIBGPAC_UTILS+=utils/sha1.o utils/base_encoding.o utils/math.o utils/os_net.o utils/os_thread.o utils/os_config_init.o utils/cache.o utils/downloader.o utils/xml_parser.o utils/utf.o utils/token.o utils/color.o utils/Remotery.o endif -ifeq ($(DISABLE_PLAYER), no) -LIBGPAC_UTILS+=utils/os_module.o utils/path2d.o utils/path2d_stroker.o utils/module.o utils/uni_bidi.o utils/unicode.o +ifeq ($(DISABLE_PLAYER),no) +LIBGPAC_UTILS+=utils/uni_bidi.o utils/unicode.o endif +LIBGPAC_UTILS+=utils/os_module.o utils/module.o utils/path2d.o utils/path2d_stroker.o ## libgpac objects gathering: src/ietf LIBGPAC_IETF= -ifeq ($(DISABLE_STREAMING), no) +ifeq ($(DISABLE_STREAMING),no) LIBGPAC_IETF=ietf/rtcp.o ietf/rtp.o ietf/rtp_packetizer.o ietf/rtp_pck_3gpp.o ietf/rtp_pck_mpeg12.o ietf/rtp_pck_mpeg4.o ietf/rtsp_command.o ietf/rtsp_common.o ietf/rtsp_response.o ietf/rtsp_session.o ietf/sdp.o ietf/rtp_depacketizer.o ietf/rtp_streamer.o endif ## libgpac objects gathering: src/bifs LIBGPAC_BIFS= -ifeq ($(DISABLE_BIFS), no) +ifeq ($(DISABLE_BIFS),no) LIBGPAC_BIFS=bifs/arith_decoder.o bifs/bifs_codec.o bifs/bifs_node_tables.o bifs/com_dec.o bifs/com_enc.o bifs/conditional.o bifs/field_decode.o bifs/field_encode.o bifs/memory_decoder.o bifs/predictive_mffield.o bifs/quantize.o bifs/script_dec.o bifs/script_enc.o bifs/unquantize.o endif ## libgpac objects gathering: src/isomedia LIBGPAC_ISOM=isomedia/avc_ext.o isomedia/box_code_3gpp.o isomedia/box_code_apple.o isomedia/box_code_base.o isomedia/box_code_drm.o isomedia/box_code_meta.o isomedia/box_dump.o isomedia/box_funcs.o isomedia/data_map.o isomedia/drm_sample.o isomedia/isom_intern.o isomedia/isom_read.o isomedia/isom_store.o isomedia/isom_write.o isomedia/media.o isomedia/media_odf.o isomedia/meta.o isomedia/movie_fragments.o isomedia/sample_descs.o isomedia/stbl_read.o isomedia/stbl_write.o isomedia/track.o isomedia/tx3g.o isomedia/iff.o -ifeq ($(DISABLE_ISOFF_HINT), no) +ifeq ($(DISABLE_ISOFF_HINT),no) LIBGPAC_ISOM+=isomedia/hint_track.o isomedia/hinting.o endif -ifeq ($(DISABLE_ISOM_ADOBE), no) +ifeq ($(DISABLE_ISOM_ADOBE),no) LIBGPAC_ISOM+=isomedia/box_code_adobe.o endif ## libgpac objects gathering: src/odf LIBGPAC_ODF=odf/desc_private.o odf/descriptors.o odf/odf_code.o odf/odf_codec.o odf/odf_command.o odf/qos.o odf/slc.o -ifeq ($(MINIMAL_OD), no) +ifeq ($(MINIMAL_OD),no) LIBGPAC_ODF+=odf/ipmpx_code.o odf/oci_codec.o -ifeq ($(DISABLE_OD_DUMP), no) +ifeq ($(DISABLE_OD_DUMP),no) LIBGPAC_ODF+=odf/ipmpx_dump.o endif -ifeq ($(DISABLE_OD_PARSE), no) +ifeq ($(DISABLE_OD_PARSE),no) LIBGPAC_ODF+=odf/ipmpx_parse.o endif endif -ifeq ($(DISABLE_OD_DUMP), no) +ifeq ($(DISABLE_OD_DUMP),no) LIBGPAC_ODF+=odf/odf_dump.o endif -ifeq ($(DISABLE_OD_PARSE), no) +ifeq ($(DISABLE_OD_PARSE),no) LIBGPAC_ODF+=odf/odf_parse.o endif @@ -73,7 +74,7 @@ ## libgpac objects gathering: src/crypto LIBGPAC_CRYPTO= -ifeq ($(DISABLE_CRYPTO), no) +ifeq ($(DISABLE_CRYPTO),no) LIBGPAC_CRYPTO+=crypto/g_crypt.o crypto/g_crypt_openssl.o crypto/g_crypt_tinyaes.o crypto/tiny_aes.o endif @@ -82,100 +83,100 @@ ## libgpac objects gathering: src/media tools LIBGPAC_MEDIATOOLS=media_tools/isom_tools.o media_tools/dash_segmenter.o media_tools/av_parsers.o media_tools/atsc_dmx.o -ifeq ($(DISABLE_AV_PARSERS), no) +ifeq ($(DISABLE_AV_PARSERS),no) LIBGPAC_MEDIATOOLS+=media_tools/img.o endif -ifeq ($(DISABLE_MEDIA_IMPORT), no) +ifeq ($(DISABLE_MEDIA_IMPORT),no) LIBGPAC_MEDIATOOLS+=media_tools/media_import.o endif -ifeq ($(DISABLE_M2TS), no) +ifeq ($(DISABLE_M2TS),no) LIBGPAC_MEDIATOOLS+=media_tools/mpegts.o endif -ifeq ($(DISABLE_MPD), no) +ifeq ($(DISABLE_MPD),no) LIBGPAC_MEDIATOOLS+=media_tools/m3u8.o media_tools/mpd.o endif -ifeq ($(DISABLE_DASH_CLIENT), no) +ifeq ($(DISABLE_DASH_CLIENT),no) LIBGPAC_MEDIATOOLS+=media_tools/dash_client.o endif -ifeq ($(DISABLE_MEDIA_EXPORT), no) +ifeq ($(DISABLE_MEDIA_EXPORT),no) LIBGPAC_MEDIATOOLS+=media_tools/media_export.o endif -ifeq ($(DISABLE_M2TS_MUX), no) +ifeq ($(DISABLE_M2TS_MUX),no) LIBGPAC_MEDIATOOLS+=media_tools/m2ts_mux.o endif -ifeq ($(DISABLE_DVBX), no) +ifeq ($(DISABLE_DVBX),no) LIBGPAC_MEDIATOOLS+=media_tools/ait.o media_tools/dsmcc.o media_tools/dvb_mpe.o media_tools/reedsolomon.o endif -ifeq ($(DISABLE_AVILIB), no) +ifeq ($(DISABLE_AVILIB),no) LIBGPAC_MEDIATOOLS+=media_tools/avilib.o endif -ifeq ($(DISABLE_M2PS), no) +ifeq ($(DISABLE_M2PS),no) LIBGPAC_MEDIATOOLS+=media_tools/mpeg2_ps.o endif -ifeq ($(DISABLE_OGG), no) +ifeq ($(DISABLE_OGG),no) LIBGPAC_MEDIATOOLS+=media_tools/gpac_ogg.o endif -ifeq ($(DISABLE_CRYPTO), no) +ifeq ($(DISABLE_CRYPTO),no) LIBGPAC_MEDIATOOLS+=media_tools/crypt_tools.o endif -ifeq ($(DISABLE_ISOFF_HINT), no) +ifeq ($(DISABLE_ISOFF_HINT),no) LIBGPAC_MEDIATOOLS+=media_tools/isom_hinter.o else -ifeq ($(DISABLE_STREAMING), no) +ifeq ($(DISABLE_STREAMING),no) LIBGPAC_MEDIATOOLS+=media_tools/isom_hinter.o endif endif -ifeq ($(DISABLE_SAF), no) +ifeq ($(DISABLE_SAF),no) LIBGPAC_MEDIATOOLS+=media_tools/saf.o endif -ifeq ($(DISABLE_VOBSUB), no) +ifeq ($(DISABLE_VOBSUB),no) LIBGPAC_MEDIATOOLS+=media_tools/vobsub.o endif LIBGPAC_MEDIATOOLS+=media_tools/webvtt.o -LIBGPAC_FILTERS=filter_core/filter_pck.o filter_core/filter_pid.o filter_core/filter_props.o filter_core/filter_queue.o filter_core/filter_session.o filter_core/filter_register.o filter_core/filter.o +LIBGPAC_FILTERS=filter_core/filter_pck.o filter_core/filter_pid.o filter_core/filter_props.o filter_core/filter_queue.o filter_core/filter_session.o filter_core/filter_register.o filter_core/filter.o filter_core/filter_session_js.o LIBGPAC_QUICKJS= -ifeq ($(CONFIG_JS), yes) +ifeq ($(CONFIG_JS),yes) LIBGPAC_QUICKJS=quickjs/cutils.o quickjs/libbf.o quickjs/libregexp.o quickjs/libunicode.o quickjs/quickjs.o -LIBGPAC_QUICKJS+=jsmods/evg.o jsmods/scene_js.o jsmods/storage.o jsmods/webgl.o jsmods/xhr.o +LIBGPAC_QUICKJS+=jsmods/core.o jsmods/evg.o jsmods/scene_js.o jsmods/storage.o jsmods/webgl.o jsmods/xhr.o endif ## libgpac objects gathering: src/scene_manager LIBGPAC_SCENEMANAGER= -ifeq ($(DISABLE_SMGR), no) +ifeq ($(DISABLE_SMGR),no) LIBGPAC_SCENEMANAGER+=scene_manager/scene_manager.o scene_manager/text_to_bifs.o endif -ifeq ($(DISABLE_LOADER_BT), no) +ifeq ($(DISABLE_LOADER_BT),no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_bt.o endif -ifeq ($(DISABLE_LOADER_XMT), no) +ifeq ($(DISABLE_LOADER_XMT),no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_xmt.o endif -ifeq ($(DISABLE_LOADER_ISOFF), no) +ifeq ($(DISABLE_LOADER_ISOFF),no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_isom.o endif -ifeq ($(DISABLE_LOADER_QTVR), no) +ifeq ($(DISABLE_LOADER_QTVR),no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_qt.o endif -ifeq ($(DISABLE_SVG), no) +ifeq ($(DISABLE_SVG),no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_svg.o endif -ifeq ($(DISABLE_LOADER_SWF), no) +ifeq ($(DISABLE_LOADER_SWF),no) LIBGPAC_SCENEMANAGER+=scene_manager/swf_parse.o scene_manager/swf_bifs.o scene_manager/swf_svg.o endif -ifeq ($(DISABLE_SCENE_DUMP), no) +ifeq ($(DISABLE_SCENE_DUMP),no) LIBGPAC_SCENEMANAGER+=scene_manager/scene_dump.o endif -ifeq ($(DISABLE_SCENE_STATS), no) +ifeq ($(DISABLE_SCENE_STATS),no) LIBGPAC_SCENEMANAGER+=scene_manager/scene_stats.o endif -ifeq ($(DISABLE_SENG), no) +ifeq ($(DISABLE_SENG),no) LIBGPAC_SCENEMANAGER+=scene_manager/scene_engine.o endif -ifeq ($(DISABLE_SCENE_ENCODE), no) +ifeq ($(DISABLE_SCENE_ENCODE),no) LIBGPAC_SCENEMANAGER+=scene_manager/encode_isom.o endif @@ -186,19 +187,22 @@ ## libgpac objects gathering: src/compositor LIBGPAC_COMPOSITOR=compositor/audio_input.o compositor/audio_mixer.o compositor/audio_render.o compositor/bindable.o compositor/camera.o compositor/compositor.o compositor/compositor_2d.o compositor/compositor_3d.o compositor/compositor_node_init.o compositor/drawable.o compositor/events.o compositor/font_engine.o compositor/hc_flash_shape.o compositor/hardcoded_protos.o compositor/mesh.o compositor/mesh_collide.o compositor/mesh_tesselate.o compositor/mpeg4_animstream.o compositor/mpeg4_audio.o compositor/mpeg4_background.o compositor/mpeg4_background2d.o compositor/mpeg4_bitmap.o compositor/mpeg4_composite.o compositor/mpeg4_form.o compositor/mpeg4_geometry_2d.o compositor/mpeg4_geometry_3d.o compositor/mpeg4_geometry_ifs2d.o compositor/mpeg4_geometry_ils2d.o compositor/mpeg4_gradients.o compositor/mpeg4_grouping.o compositor/mpeg4_grouping_2d.o compositor/mpeg4_grouping_3d.o compositor/mpeg4_layer_2d.o compositor/mpeg4_layer_3d.o compositor/mpeg4_layout.o compositor/mpeg4_lighting.o compositor/mpeg4_path_layout.o compositor/mpeg4_sensors.o compositor/mpeg4_sound.o compositor/mpeg4_text.o compositor/mpeg4_textures.o compositor/mpeg4_timesensor.o compositor/mpeg4_viewport.o compositor/navigate.o compositor/offscreen_cache.o compositor/svg_base.o compositor/svg_filters.o compositor/svg_font.o compositor/svg_geometry.o compositor/svg_grouping.o compositor/svg_media.o compositor/svg_paint_servers.o compositor/svg_text.o compositor/texturing.o compositor/texturing_gl.o compositor/visual_manager.o compositor/visual_manager_2d.o compositor/visual_manager_2d_draw.o compositor/visual_manager_3d.o compositor/visual_manager_3d_gl.o compositor/x3d_geometry.o compositor/clock.o compositor/mpeg4_inputsensor.o compositor/mpeg4_mediacontrol.o compositor/media_object.o compositor/mpeg4_mediasensor.o compositor/mpeg4_inline.o compositor/scene_ns.o compositor/object_manager.o compositor/scene.o compositor/svg_external.o compositor/scene_node_init.o -ifeq ($(DISABLE_PLAYER), yes) -LIBGPAC_COMPOSITOR= +ifeq ($(DISABLE_PLAYER),yes) +LIBGPAC_COMPOSITOR=compositor/font_engine.o LIBGPAC_TERMINAL= endif -ifeq ($(DISABLE_SCENEGRAPH), yes) -LIBGPAC_SCENE= +ifeq ($(DISABLE_SCENEGRAPH),yes) +LIBGPAC_SCENE=scenegraph/vrml_js.o endif +ifeq ($(DISABLE_EVG),yes) +LIBGPAC_EVG= +endif ## libgpac objects gathering: src/laser LIBGPAC_LASER= -ifeq ($(DISABLE_LASER), no) +ifeq ($(DISABLE_LASER),no) LIBGPAC_LASER=laser/lsr_enc.o laser/lsr_dec.o laser/lsr_tables.o endif @@ -254,7 +258,7 @@ ifneq ($(CONFIG_JP2),no) EXTRALIBS+=$(JP2_LDFLAGS) -ifeq ($(CONFIG_JP2), local) +ifeq ($(CONFIG_JP2),local) CFLAGS+= -DOPJ_STATIC -I"$(LOCAL_INC_PATH)/openjpeg" else CFLAGS+=$(JP2_CFLAGS) @@ -289,11 +293,11 @@ endif LD_SONAME="-Wl,-soname,libgpac.so.$(VERSION_MAJOR)" -ifeq ($(CONFIG_DARWIN), yes) +ifeq ($(CONFIG_DARWIN),yes) LD_SONAME= endif -ifeq ($(CONFIG_SUNOS), yes) +ifeq ($(CONFIG_SUNOS),yes) LD_SONAME="-Wl,-h,$(LIB)" EXTRALIBS+= -lrt endif @@ -363,7 +367,7 @@ endif -ifeq ($(shell fgrep "Libs.private:" ../gpac.pc 1>&2 2> /dev/null ; echo $$?), 1) +ifeq ($(shell fgrep "Libs.private:" ../gpac.pc 1>&2 2> /dev/null ; echo $$?),1) @echo "Libs.private: -lgpac_static $(EXTRALIBS)" >> ../gpac.pc endif
View file
gpac-1.0.0.tar.gz/src/compositor/audio_render.c -> gpac-1.0.1.tar.gz/src/compositor/audio_render.c
Changed
@@ -67,7 +67,13 @@ if (ar->samplerate) { ar->time_at_last_config_sr = ar->current_time_sr * freq / ar->samplerate; } - if (!ar->compositor->abuf) ar->compositor->abuf = 100; + if (!ar->compositor->abuf) { +#ifdef GPAC_CONFIG_ANDROID + ar->compositor->abuf = 200; +#else + ar->compositor->abuf = 100; +#endif + } ar->samplerate = freq; ar->bytes_per_samp = nb_chan * gf_audio_fmt_bit_depth(a_fmt) / 8; ar->bytes_per_second = freq * ar->bytes_per_samp; @@ -191,6 +197,7 @@ { if (Volume>100) Volume=100; if (ar->volume==Volume) return; + ar->volume = Volume; if (ar->aout) gf_filter_pid_set_property(ar->aout, GF_PROP_PID_AUDIO_VOLUME, &PROP_UINT(ar->volume) ); }
View file
gpac-1.0.0.tar.gz/src/compositor/compositor.c -> gpac-1.0.1.tar.gz/src/compositor/compositor.c
Changed
@@ -159,7 +159,7 @@ compositor->msg_type &= ~GF_SR_CFG_INITIAL_RESIZE; } - /*scene size has been overriden*/ + /*scene size has been overridden*/ if (compositor->msg_type & GF_SR_CFG_OVERRIDE_SIZE) { assert(!(compositor->override_size_flags & 2)); compositor->msg_type &= ~GF_SR_CFG_OVERRIDE_SIZE; @@ -268,12 +268,12 @@ GF_FilterFrameInterface *frame_ifce = gf_filter_pck_get_frame_interface(pck); GF_Compositor *compositor = gf_filter_get_udta(filter); if (frame_ifce) { - compositor->frame_ifce.user_data = NULL; if (compositor->fb.video_buffer) { gf_sc_release_screen_buffer(compositor, &compositor->fb); compositor->fb.video_buffer = NULL; } } + compositor->frame_ifce.user_data = NULL; compositor->flush_pending = (compositor->skip_flush!=1) ? GF_TRUE : GF_FALSE; compositor->skip_flush = 0; } @@ -2862,7 +2862,6 @@ compositor->frame_draw_type = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor] Redrawing scene - STB %d\n", compositor->scene_sampled_clock)); - scene_drawn = gf_sc_draw_scene(compositor); #ifndef GPAC_DISABLE_LOG @@ -2877,6 +2876,13 @@ else if (compositor->frame_draw_type) emit_frame = GF_FALSE; else if (compositor->fonts_pending>0) emit_frame = GF_FALSE; else emit_frame = GF_TRUE; + +#ifdef GPAC_CONFIG_ANDROID + if (!emit_frame && scene_drawn) { + compositor->frame_was_produced = GF_TRUE; + } +#endif + } /*and flush*/ #ifndef GPAC_DISABLE_LOG @@ -2896,10 +2902,11 @@ compositor->passthrough_pck = NULL; pck_frame_ts = gf_filter_pck_get_cts(pck); } else { + //assign udta of frame interface event when using shared packet, as it is used to test when frame is released + compositor->frame_ifce.user_data = compositor; if (compositor->video_out==&raw_vout) { pck = gf_filter_pck_new_shared(compositor->vout, compositor->framebuffer, compositor->framebuffer_size, gf_sc_frame_ifce_done); } else { - compositor->frame_ifce.user_data = compositor; compositor->frame_ifce.get_plane = gf_sc_frame_ifce_get_plane; compositor->frame_ifce.get_gl_texture = NULL; #ifndef GPAC_DISABLE_3D @@ -3372,15 +3379,22 @@ } switch (event->type) { case GF_EVENT_SHOWHIDE: + if (!from_user) { + /*switch fullscreen off!!!*/ + compositor->is_hidden = event->show.show_type ? GF_FALSE : GF_TRUE; + break; + } case GF_EVENT_SET_CAPTION: case GF_EVENT_MOVE: + if (!from_user) { + if (compositor->last_had_overlays) { + gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME); + } + break; + } compositor->video_out->ProcessEvent(compositor->video_out, event); break; - case GF_EVENT_MOVE_NOTIF: - if (compositor->last_had_overlays) { - gf_sc_next_frame_state(compositor, GF_SC_DRAW_FRAME); - } break; case GF_EVENT_REFRESH: /*when refreshing a window with overlays we redraw the scene */ @@ -3481,10 +3495,6 @@ gf_sc_input_sensor_string_input(compositor , event->character.unicode_char); return gf_sc_handle_event_intern(compositor, event, from_user); - /*switch fullscreen off!!!*/ - case GF_EVENT_SHOWHIDE_NOTIF: - compositor->is_hidden = event->show.show_type ? GF_FALSE : GF_TRUE; - break; case GF_EVENT_MOUSEMOVE: event->mouse.button = 0; @@ -3497,13 +3507,14 @@ return gf_sc_handle_event_intern(compositor, event, from_user); case GF_EVENT_PASTE_TEXT: - gf_sc_paste_text(compositor, event->message.message); + gf_sc_paste_text(compositor, event->clipboard.text); break; case GF_EVENT_COPY_TEXT: if (gf_sc_has_text_selection(compositor)) { - event->message.message = gf_sc_get_selected_text(compositor); + const char *str = gf_sc_get_selected_text(compositor); + event->clipboard.text = str ? gf_strdup(event->clipboard.text) : NULL; } else { - event->message.message = NULL; + event->clipboard.text = NULL; } break; /*when we process events we don't forward them to the user*/
View file
gpac-1.0.0.tar.gz/src/compositor/font_engine.c -> gpac-1.0.1.tar.gz/src/compositor/font_engine.c
Changed
@@ -85,7 +85,9 @@ while (gf_list_count(font->spans)) { GF_TextSpan *ts = gf_list_get(font->spans, 0); gf_list_rem(font->spans, 0); +#ifndef GPAC_DISABLE_PLAYER gf_node_dirty_set(ts->user, 0, 0); +#endif ts->user=NULL; } gf_list_del(font->spans); @@ -434,6 +436,7 @@ } +#ifndef GPAC_DISABLE_PLAYER typedef struct _span_internal { @@ -454,6 +457,8 @@ #endif } GF_SpanExtensions; +#endif + void gf_font_manager_delete_span(GF_FontManager *fm, GF_TextSpan *span) { @@ -464,6 +469,7 @@ if (span->dy) gf_free(span->dy); if (span->rot) gf_free(span->rot); +#ifndef GPAC_DISABLE_PLAYER if (span->ext) { if (span->ext->path) gf_path_del(span->ext->path); #ifndef GPAC_DISABLE_3D @@ -478,6 +484,8 @@ } gf_free(span->ext); } +#endif + gf_free(span); } @@ -613,6 +621,8 @@ return path; } +#ifndef GPAC_DISABLE_PLAYER + static void span_alloc_extensions(GF_TextSpan *span) { if (span->ext) return; @@ -1489,3 +1499,5 @@ gf_list_add(tr_state->visual->compositor->sensors, gf_list_get(tr_state->vrml_sensors, i)); } } + +#endif // GPAC_DISABLE_PLAYER
View file
gpac-1.0.0.tar.gz/src/compositor/media_object.c -> gpac-1.0.1.tar.gz/src/compositor/media_object.c
Changed
@@ -272,22 +272,33 @@ void gf_mo_update_caps(GF_MediaObject *mo) { + Bool changed = GF_FALSE; const GF_PropertyValue *v, *v2; if (!mo->odm || !mo->odm->pid) return; mo->planar_audio = GF_FALSE; +#define UPDATE_CAP(_code, _field) \ + v = gf_filter_pid_get_property(mo->odm->pid, _code);\ + if (v) {\ + if (mo->_field && (mo->_field != v->value.uint)) changed=GF_TRUE;\ + mo->_field = v->value.uint;\ + }\ + if (mo->odm->type==GF_STREAM_VISUAL) { - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_WIDTH); - if (v) mo->width = v->value.uint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_HEIGHT); - if (v) mo->height = v->value.uint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_STRIDE); - if (v) mo->stride = v->value.uint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_PIXFMT); - if (v) mo->pixelformat = v->value.uint; + + UPDATE_CAP(GF_PROP_PID_WIDTH, width) + UPDATE_CAP(GF_PROP_PID_HEIGHT, height) + UPDATE_CAP(GF_PROP_PID_STRIDE, stride) + UPDATE_CAP(GF_PROP_PID_PIXFMT, pixelformat) + UPDATE_CAP(GF_PROP_PID_BITRATE, bitrate) + v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_SAR); - if (v) mo->pixel_ar = (v->value.frac.num) << 16 | (v->value.frac.den); + if (v) { + u32 n_par = (v->value.frac.num) << 16 | (v->value.frac.den); + if (mo->pixel_ar && (mo->pixel_ar!=n_par)) changed = GF_TRUE; + mo->pixel_ar = n_par; + } v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_SRD); v2 = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_SRD_REF); @@ -333,16 +344,17 @@ } } } else if (mo->odm->type==GF_STREAM_AUDIO) { - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_SAMPLE_RATE); - if (v) mo->sample_rate = v->value.uint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_NUM_CHANNELS); - if (v) mo->num_channels = v->value.uint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_CHANNEL_LAYOUT); - if (v) mo->channel_config = v->value.longuint; - v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_AUDIO_FORMAT); - if (v) mo->afmt = v->value.uint; + UPDATE_CAP(GF_PROP_PID_SAMPLE_RATE, sample_rate) + UPDATE_CAP(GF_PROP_PID_NUM_CHANNELS, num_channels) + UPDATE_CAP(GF_PROP_PID_AUDIO_FORMAT, afmt) else mo->afmt = GF_AUDIO_FMT_S16; + v = gf_filter_pid_get_property(mo->odm->pid, GF_PROP_PID_CHANNEL_LAYOUT); + if (v) { + if (mo->channel_config && (mo->channel_config!=v->value.longuint)) changed = GF_TRUE; + mo->channel_config = v->value.longuint; + } + mo->bytes_per_sec = gf_audio_fmt_bit_depth(mo->afmt) * mo->num_channels * mo->sample_rate / 8; mo->planar_audio = gf_audio_fmt_is_planar(mo->afmt); } else if (mo->odm->type==GF_STREAM_OD) { @@ -356,6 +368,14 @@ } else { GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("Unknwon scene object type %d\n", mo->odm->type)); } + + if (changed) { + GF_Event evt; + GF_Scene *scene = mo->odm->subscene ? mo->odm->subscene : mo->odm->parentscene; + memset(&evt, 0, sizeof(GF_Event)); + evt.type = GF_EVENT_QUALITY_SWITCHED; + gf_sc_send_event(scene->compositor, &evt); + } } static u64 convert_ts_to_ms(GF_MediaObject *mo, u64 ts, u32 timescale, Bool *discard)
View file
gpac-1.0.0.tar.gz/src/compositor/mpeg4_inline.c -> gpac-1.0.1.tar.gz/src/compositor/mpeg4_inline.c
Changed
@@ -72,6 +72,8 @@ /*assign inline scene as private stack of inline node, and remember inline node for event propagation*/ gf_node_set_private((GF_Node *)root, mo->odm->subscene); mo->odm->subscene->object_attached = GF_TRUE; + if (gf_list_find(mo->odm->subscene->attached_inlines, root)<0) + gf_list_add(mo->odm->subscene->attached_inlines, root); /*play*/ gf_mo_play(mo, 0, -1, GF_FALSE); @@ -252,6 +254,8 @@ if (!scene) return; mo = scene->root_od ? scene->root_od->mo : NULL; + gf_list_del_item(scene->attached_inlines, n); + gf_scene_notify_event(scene, GF_EVENT_UNLOAD, n, NULL, GF_OK, GF_TRUE); if (!mo) return; gf_mo_event_target_remove_by_node(mo, n);
View file
gpac-1.0.0.tar.gz/src/compositor/scene.c -> gpac-1.0.1.tar.gz/src/compositor/scene.c
Changed
@@ -324,8 +324,9 @@ tmp->storages = gf_list_new(); tmp->keynavigators = gf_list_new(); - + tmp->attached_inlines = gf_list_new(); #endif + tmp->on_media_event = inline_on_media_event; return tmp; } @@ -391,6 +392,14 @@ gf_list_del(scene->namespaces); } +#ifndef GPAC_DISABLE_VRML + while (gf_list_count(scene->attached_inlines)) { + GF_Node *n_inline = gf_list_pop_back(scene->attached_inlines); + gf_node_set_private(n_inline, NULL); + } + gf_list_del(scene->attached_inlines); +#endif + if (scene->compositor->root_scene == scene) scene->compositor->root_scene = NULL; @@ -917,7 +926,7 @@ OD_ID = gf_mo_get_od_id(url); if (!OD_ID) return NULL; - /*we may have overriden the time lines in parent scene, thus all objects in this scene have the same clock*/ + /*we may have overridden the time lines in parent scene, thus all objects in this scene have the same clock*/ if (scene->root_od->parentscene && scene->root_od->parentscene->force_single_timeline) lock_timelines = GF_TRUE;
View file
gpac-1.0.0.tar.gz/src/compositor/scene_ns.c -> gpac-1.0.1.tar.gz/src/compositor/scene_ns.c
Changed
@@ -556,7 +556,7 @@ if (!parent_url && odm->parentscene && odm->parentscene->root_od->scene_ns) parent_url = odm->parentscene->root_od->scene_ns->url; - odm->scene_ns->source_filter = gf_filter_connect_source(scene->compositor->filter, serviceURL, parent_url, &e); + odm->scene_ns->source_filter = gf_filter_connect_source(scene->compositor->filter, serviceURL, parent_url, GF_FALSE, &e); if (frag) frag[0] = '#'; if (!odm->scene_ns->source_filter) {
View file
gpac-1.0.0.tar.gz/src/compositor/svg_external.c -> gpac-1.0.1.tar.gz/src/compositor/svg_external.c
Changed
@@ -35,7 +35,7 @@ #include <gpac/network.h> GF_EXPORT -GF_Err gf_term_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl) +GF_Err gf_sc_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl) { u32 stream_id = 0; GF_Err e = GF_OK; @@ -113,7 +113,7 @@ memset(&url, 0, sizeof(MFURL)); if (!xlinkp->href) return NULL; - gf_term_get_mfurl_from_xlink(elt, &url); + gf_sc_get_mfurl_from_xlink(elt, &url); while (scene->secondary_resource && scene->root_od->parentscene) scene = scene->root_od->parentscene;
View file
gpac-1.0.0.tar.gz/src/compositor/svg_media.c -> gpac-1.0.1.tar.gz/src/compositor/svg_media.c
Changed
@@ -276,7 +276,7 @@ if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) { if (!stack->txh.stream || gf_mo_url_changed(stack->txh.stream, &stack->txurl)) { - gf_term_get_mfurl_from_xlink(node, &stack->txurl); + gf_sc_get_mfurl_from_xlink(node, &stack->txurl); stack->txh.width = stack->txh.height = 0; /*remove associated audio if any*/ @@ -712,7 +712,7 @@ stack->is_error = GF_FALSE; gf_node_dirty_clear(node, GF_SG_SVG_XLINK_HREF_DIRTY); - gf_term_get_mfurl_from_xlink(node, &(stack->aurl)); + gf_sc_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) ? GF_TRUE : GF_FALSE; @@ -864,7 +864,7 @@ if (all_atts.syncBehavior) lock_timeline = (*all_atts.syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? GF_TRUE : GF_FALSE; - gf_term_get_mfurl_from_xlink(node, &url); + gf_sc_get_mfurl_from_xlink(node, &url); new_res = gf_mo_register(node, &url, lock_timeline, GF_FALSE); gf_sg_mfurl_del(url);
View file
gpac-1.0.0.tar.gz/src/compositor/visual_manager_3d_gl.c -> gpac-1.0.1.tar.gz/src/compositor/visual_manager_3d_gl.c
Changed
@@ -792,6 +792,9 @@ gf_free(pi); return NULL; } + if (pix_fmt == GF_PIXEL_GL_EXTERNAL) { + flags |= GF_GL_IS_ExternalOES; + } pi->fragment = visual_3d_shader_with_flags(visual->compositor->fragshader , GL_FRAGMENT_SHADER, flags, pix_fmt); if (!pi->fragment) { GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to compile fragment shader\n")); @@ -821,6 +824,7 @@ gf_free(pi); return NULL; } + GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor] fragment shader compiled fine\n")); return pi; }
View file
gpac-1.0.0.tar.gz/src/evg/raster_yuv.c -> gpac-1.0.1.tar.gz/src/evg/raster_yuv.c
Changed
@@ -1291,7 +1291,7 @@ #define set_u16_le(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF; ((u8 *)_ptr)[1] = (val&0xFF); } #define set_u16_be(_ptr, val) { *(u16 *) _ptr = (u16) val; } -#define get_u16_le(val, _ptr) { val = ((u32) (*(u8 *) ptr+1)<< 8) | *(u8 *) ptr; } +#define get_u16_le(val, _ptr) { val = ((u32) (*(u8 *) _ptr+1)<< 8) | *(u8 *) _ptr; } #define get_u16_be(val, _ptr) { val = *(u16 *) (_ptr); } #else @@ -1300,7 +1300,7 @@ #define set_u16_be(_ptr, val) { ((u8 *)_ptr)[0] = (val>>8)&0xFF; ((u8 *)_ptr)[1] = (val&0xFF); } #define get_u16_le(val, _ptr) { val = *(u16 *) (_ptr); } -#define get_u16_be(val, _ptr) { val = ((u32) (*(u8 *) ptr)<< 8) | *(u8 *) ptr+1; } +#define get_u16_be(val, _ptr) { val = ((u32) (*(u8 *) _ptr)<< 8) | *(u8 *) _ptr+1; } #endif
View file
gpac-1.0.0.tar.gz/src/export.cpp -> gpac-1.0.1.tar.gz/src/export.cpp
Changed
@@ -56,6 +56,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_sys_is_quiet) ) #pragma comment (linker, EXPORT_SYMBOL(gf_gpac_version) ) #pragma comment (linker, EXPORT_SYMBOL(gf_gpac_copyright) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_gpac_copyright_cite) ) #pragma comment (linker, EXPORT_SYMBOL(gf_sys_features) ) #pragma comment (linker, EXPORT_SYMBOL(gf_sleep) ) @@ -81,6 +82,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_sys_word_match) ) #pragma comment (linker, EXPORT_SYMBOL(gf_sys_profiler_set_callback) ) #pragma comment (linker, EXPORT_SYMBOL(gf_sys_profiler_send) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_sys_profiler_enable_sampling) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_sys_profiler_sampling_enabled) ) #pragma comment (linker, EXPORT_SYMBOL(gf_get_default_cache_directory) ) #pragma comment (linker, EXPORT_SYMBOL(gf_4cc_to_str) ) @@ -137,8 +140,11 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_prompt_has_input) ) #pragma comment (linker, EXPORT_SYMBOL(gf_prompt_get_char) ) #pragma comment (linker, EXPORT_SYMBOL(gf_prompt_set_echo_off) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_prompt_get_size) ) + #pragma comment (linker, EXPORT_SYMBOL(gf_crc_32) ) #pragma comment (linker, EXPORT_SYMBOL(gf_gz_compress_payload) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_gz_compress_payload_ex) ) #pragma comment (linker, EXPORT_SYMBOL(gf_gz_decompress_payload) ) #pragma comment (linker, EXPORT_SYMBOL(gf_lz_compress_payload) ) #pragma comment (linker, EXPORT_SYMBOL(gf_lz_decompress_payload) ) @@ -307,6 +313,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_net_get_ntp_diff_ms) ) #pragma comment (linker, EXPORT_SYMBOL(gf_net_set_ntp_shift) ) #pragma comment (linker, EXPORT_SYMBOL(gf_net_get_utc_ts) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_net_ntp_to_utc) ) + #pragma comment (linker, EXPORT_SYMBOL(gf_errno_str) ) #pragma comment (linker, EXPORT_SYMBOL(gf_blob_get_data) ) @@ -576,6 +584,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_cmx_apply_fixed) ) #pragma comment (linker, EXPORT_SYMBOL(gf_color_parse) ) #pragma comment (linker, EXPORT_SYMBOL(gf_color_get_name) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_color_enum) ) + /*path2d.h exports*/ @@ -708,7 +718,6 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_write) ) #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_box_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_box_del) ) @@ -779,7 +788,6 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_has_time_offset) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_cts_to_dts_shift) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_sync_point_count) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_isom_has_root_od) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_root_od) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_disable_odf_conversion) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_track_in_root_od) ) @@ -889,6 +897,12 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_constant_sample_duration) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_enable_raw_pack) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_track_magic) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_sample_from_dts) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_sample_padding_bits) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_sample_get_subsample) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_sample_has_subsamples) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_sample_get_subsamples_buffer) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_max_sample_delta) ) # ifndef GPAC_DISABLE_ISOM_DUMP #pragma comment (linker, EXPORT_SYMBOL(gf_isom_dump) ) @@ -906,9 +920,22 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_payt_info) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_sdp_get) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_sdp_track_get) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_hinter_track_force_no_offsets) ) + # ifndef GPAC_DISABLE_ISOM_DUMP #pragma comment (linker, EXPORT_SYMBOL(gf_isom_dump_hint_sample) ) #endif + +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_read) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_del) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_new) ) + +#ifndef GPAC_DISABLE_ISOM_WRITE +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_size) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_write) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hint_pck_length) ) +#endif + #endif #ifndef GPAC_DISABLE_ISOM_WRITE @@ -1013,7 +1040,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_text_add_blink) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_text_set_wrap) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_text_set_display_flags) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_isom_remove_track_protection) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_text_to_sample) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_ismacryp_protection) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_change_ismacryp_protection) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_avc_config_new) ) @@ -1035,7 +1062,6 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_remove_meta_item) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_meta_primary_item) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_meta_xml) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_meta_xml_memory) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_meta_add_item_ref) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_iff_create_image_item_from_track) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_remove_meta_xml) ) @@ -1093,7 +1119,6 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_finalize_for_fragment) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_start_fragment) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_flush_fragments) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_segment_name) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_fragment_reference_time) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_traf_mss_timeext) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_fragment_option) ) @@ -1144,7 +1169,6 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_cenc_is_pattern_mode) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_close_fragments) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_bitrate) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_pssh) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_sample_cenc_info_ex) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_hevc_set_tile_config) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_mvc_config_get) ) @@ -1370,19 +1394,24 @@ #ifndef GPAC_DISABLE_HEVC #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_vps) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_vps_ex) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_vps_bs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_sps) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_sps_ex) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_sps_bs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_pps) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_pps_bs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_hevc_get_profile_name) ) #pragma comment (linker, EXPORT_SYMBOL(gf_hevc_get_sps_info_with_state) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_parse_nalu) ) - #endif //GPAC_DISABLE_HEVC + #pragma comment (linker, EXPORT_SYMBOL(gf_media_aom_av1_parse_obu) ) #endif /*GPAC_DISABLE_AV_PARSERS*/ +#pragma comment (linker, EXPORT_SYMBOL(gf_mpegh_get_mhas_pl) ) + #ifndef GPAC_DISABLE_MEDIA_EXPORT #pragma comment (linker, EXPORT_SYMBOL(gf_media_export) ) @@ -2222,6 +2251,18 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_atsc3_set_max_objects_store) ) #pragma comment (linker, EXPORT_SYMBOL(gf_atsc3_dmx_debug_tsi) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_find_by_id3tag) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_find_by_itag) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_find_by_name) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_get_type) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_get_name) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_get_itag) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_get_id3tag) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_itags_enum_tags) ) + +#pragma comment (linker, EXPORT_SYMBOL(gf_id3_get_genre) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_id3_get_genre_tag) ) + #pragma comment (linker, EXPORT_SYMBOL(gf_pixel_fmt_all_names) ) #pragma comment (linker, EXPORT_SYMBOL(gf_pixel_fmt_all_shortnames) ) #pragma comment (linker, EXPORT_SYMBOL(gf_pixel_get_size_info) ) @@ -2269,6 +2310,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_filter_get_arg_str ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_filter_ui_event ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_filter_is_alias ) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_filter_get_stats ) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_filter_in_parent_chain ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_fs_set_max_resolution_chain_length ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_fs_get_max_resolution_chain_length ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_fs_get_last_connect_error ) ) @@ -2278,6 +2321,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_fs_set_ui_callback) ) #pragma comment (linker, EXPORT_SYMBOL(gf_fs_enum_unmapped_options) ) #pragma comment (linker, EXPORT_SYMBOL(gf_fs_send_update) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_fs_load_script) ) + #pragma comment (linker, EXPORT_SYMBOL(gf_filter_reconnect_output) ) #pragma comment (linker, EXPORT_SYMBOL(gf_filter_add_event_listener ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_filter_remove_event_listener ) ) @@ -2453,7 +2498,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_htonl) ) #pragma comment (linker, EXPORT_SYMBOL(gf_htons) ) #pragma comment (linker, EXPORT_SYMBOL(gf_ntohl) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_tohs) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_ntohs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_inline_is_default_viewpoint) ) #pragma comment (linker, EXPORT_SYMBOL(gf_mpegv12_get_config) )
View file
gpac-1.0.0.tar.gz/src/filter_core/filter.c -> gpac-1.0.1.tar.gz/src/filter_core/filter.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2017-2018 + * Copyright (c) Telecom ParisTech 2017-2020 * All rights reserved * * This file is part of GPAC / filters sub-project @@ -42,11 +42,16 @@ const char *gf_fs_path_escape_colon(GF_FilterSession *sess, const char *path) { + const char *res, *arg; if (!path) return NULL; if (sess->sep_args != ':') return strchr(path, sess->sep_args); - return gf_url_colon_suffix(path); + arg = strchr(path, sess->sep_name); + res = gf_url_colon_suffix(path); + if (arg && res && (res > arg)) + res = gf_url_colon_suffix(arg+1); + return res; } static const char *gf_filter_get_args_stripped(GF_FilterSession *fsess, const char *in_args, Bool is_dst) @@ -54,13 +59,20 @@ char szEscape[7]; char *args_striped = NULL; if (in_args) { - char szDst[5]; + char szDst[6]; + const char *key; if (is_dst) { - sprintf(szDst, "dst%c", fsess->sep_name); + key = "dst"; + } else { + key = "src"; + } + if (!strncmp(in_args, key, 3) && (in_args[3]==fsess->sep_name)) { + args_striped = (char *) in_args; } else { - sprintf(szDst, "src%c", fsess->sep_name); + sprintf(szDst, "%c%s%c", fsess->sep_name, key, fsess->sep_name); + args_striped = strstr(in_args, szDst); } - args_striped = strstr(in_args, szDst); + if (args_striped) { args_striped = (char *)gf_fs_path_escape_colon(fsess, args_striped+4); if (args_striped) args_striped ++; @@ -307,6 +319,11 @@ gf_filter_pid_post_init_task(filter, pid); } } + +#ifdef GPAC_HAS_QJS + jsfs_on_filter_created(filter); +#endif + return GF_OK; } @@ -342,6 +359,11 @@ // assert(!filter->swap_pidinst_dst); assert(!filter->swap_pidinst_src); + +#ifdef GPAC_HAS_QJS + jsfs_on_filter_destroyed(filter); +#endif + #ifndef GPAC_DISABLE_3D gf_list_del_item(filter->session->gl_providers, filter); gf_fs_check_gl_provider(filter->session); @@ -436,6 +458,11 @@ if (filter->instance_help) gf_free(filter->instance_help); +#ifdef GPAC_HAS_QJS + if (filter->iname) + gf_free(filter->iname); +#endif + gf_free(filter); } @@ -890,27 +917,38 @@ gf_free(arg); } -static const char *gf_filter_load_arg_config(GF_FilterSession *session, const char *sec_name, const char *arg_name, const char *arg_val) +static const char *gf_filter_load_arg_config(GF_Filter *filter, const char *sec_name, const char *arg_name, const char *arg_val) { Bool gf_sys_has_filter_global_args(); const char *opt; + GF_FilterSession *session = filter->session; //look in global args if (gf_sys_has_filter_global_args()) { u32 alen = (u32) strlen(arg_name); u32 i, nb_args = gf_sys_get_argc(); for (i=0; i<nb_args; i++) { + const char *per_filter; const char *arg = gf_sys_get_arg(i); if (arg[0]!='-') continue; if (arg[1]!='-') continue; - if (!strncmp(arg+2, arg_name, alen)) { + arg += 2; + per_filter = strchr(arg, '@'); + if (per_filter) { + u32 len = (u32) (per_filter - arg); + if (!len || strncmp(filter->freg->name, arg, len)) + continue; + arg += len+1; + } + + if (!strncmp(arg, arg_name, alen)) { u32 len=0; char *sep = strchr(arg, '='); if (sep) { - len = (u32) (sep - (arg+2)); + len = (u32) (sep - (arg)); } else { - len = (u32) strlen(arg+2); + len = (u32) strlen(arg); } if (len != alen) continue; gf_fs_push_arg(session, arg_name, GF_TRUE, 0); @@ -976,10 +1014,20 @@ #define META_MAX_ARG 1000 char szArg[META_MAX_ARG+1]; GF_Err e; + const char *per_filter; const char *sep, *arg = gf_sys_get_arg(i); if (arg[0] != '-') continue; if (arg[1] != '+') continue; arg+=2; + + per_filter = strchr(arg, '@'); + if (per_filter) { + u32 len = (u32) (per_filter - arg); + if (!len || strncmp(filter->freg->name, arg, len)) + continue; + arg += len+1; + } + sep = strchr(arg, '='); memset(&argv, 0, sizeof(GF_PropertyValue)); argv.type = GF_PROP_STRING; @@ -1076,13 +1124,26 @@ || !strncmp(args+4, "rtp://", 6) ) { char *sep2 = sep ? strchr(sep+1, ':') : NULL; - if (sep2) { - u32 port = 0;; - sep2[0] = 0; - if (sscanf(sep+1, "%d", &port)!=1) { - port = 0; + char *sep3 = sep ? strchr(sep+1, '/') : NULL; + if (sep2 && sep3 && (sep2>sep3)) { + sep2 = strchr(sep3, ':'); + } + if (sep2 || sep3 || sep) { + u32 port = 0; + if (sep2) { + sep2[0] = 0; + if (sep3) sep3[0] = 0; } - sep2[0] = ':'; + else if (sep3) sep3[0] = 0; + if (sscanf(sep+1, "%d", &port)==1) { + char szPort[20]; + snprintf(szPort, 20, "%d", port); + if (strcmp(sep+1, szPort)) + port = 0; + } + if (sep2) sep2[0] = ':'; + if (sep3) sep3[0] = '/'; + if (port) sep = sep2; } } @@ -1424,7 +1485,7 @@ continue; } - def_val = gf_filter_load_arg_config(filter->session, szSecName, a->arg_name, a->arg_default_val); + def_val = gf_filter_load_arg_config(filter, szSecName, a->arg_name, a->arg_default_val); if (!def_val) continue; @@ -2831,9 +2892,46 @@ } GF_EXPORT -GF_Filter *gf_filter_connect_source(GF_Filter *filter, const char *url, const char *parent_url, GF_Err *err) +GF_Filter *gf_filter_connect_source(GF_Filter *filter, const char *url, const char *parent_url, Bool inherit_args, GF_Err *err) { - GF_Filter *filter_src = gf_fs_load_source_dest_internal(filter->session, url, NULL, parent_url, err, NULL, filter, GF_TRUE, GF_TRUE, NULL); + GF_Filter *filter_src; + const char *args; + char *full_args = NULL; + if (!filter) { + if (err) *err = GF_BAD_PARAM; + return NULL; + } + args = inherit_args ? gf_filter_get_dst_args(filter) : NULL; + if (args) { + char szSep[10]; + char *loc_args; + u32 len = (u32) strlen(args); + sprintf(szSep, "%cgfloc%c", filter->session->sep_args, filter->session->sep_args); + loc_args = strstr(args, szSep); + if (loc_args) { + len = (u32) (ptrdiff_t) (loc_args - args); + } + if (len) { + gf_dynstrcat(&full_args, url, NULL); + sprintf(szSep, "%cgpac%c", filter->session->sep_args, filter->session->sep_args); + if ((filter->session->sep_args==':') && strstr(url, "://") && !strstr(url, szSep)) { + gf_dynstrcat(&full_args, szSep, NULL); + } else { + sprintf(szSep, "%c", filter->session->sep_args); + gf_dynstrcat(&full_args, szSep, NULL); + } + gf_dynstrcat(&full_args, args, NULL); + sprintf(szSep, "%cgfloc%c", filter->session->sep_args, filter->session->sep_args); + loc_args = strstr(full_args, "gfloc"); + if (loc_args) loc_args[0] = 0; + + url = full_args; + } + } + + filter_src = gf_fs_load_source_dest_internal(filter->session, url, NULL, parent_url, err, NULL, filter, GF_TRUE, GF_TRUE, NULL); + if (full_args) gf_free(full_args); + if (!filter_src) return NULL; if (!filter->source_filters) @@ -2962,7 +3060,7 @@ if (!filter || !link_from) return GF_BAD_PARAM; if (filter == link_from) return GF_OK; //don't allow loops - if (filter_in_parent_chain(filter, link_from)) return GF_BAD_PARAM; + if (gf_filter_in_parent_chain(filter, link_from)) return GF_BAD_PARAM; if (!link_from->id) { gf_filter_assign_id(link_from, NULL); @@ -3459,7 +3557,7 @@ if (strncmp(args + 4, protocol_scheme, len)) continue; if (!expand_proto && (args[len] != ':')) continue; - if (! filter_in_parent_chain(filter, src)) { + if (! gf_filter_in_parent_chain(filter, src)) { u32 j=0; Bool found=GF_FALSE; if (!enum_pids) continue; @@ -3467,7 +3565,7 @@ GF_FilterPid *pid = enum_pids(udta, &j); if (!pid) break; j++; - if ( filter_in_parent_chain(pid->pid->filter, src)) { + if ( gf_filter_in_parent_chain(pid->pid->filter, src)) { found=GF_TRUE; break; } @@ -3745,3 +3843,12 @@ } return GF_OK; } + +GF_EXPORT +GF_Err gf_filter_set_event_target(GF_Filter *filter, Bool enable_events) +{ + if (!filter) return GF_BAD_PARAM; + filter->event_target = enable_events; + return GF_OK; +} +
View file
gpac-1.0.0.tar.gz/src/filter_core/filter_pck.c -> gpac-1.0.1.tar.gz/src/filter_core/filter_pck.c
Changed
@@ -808,6 +808,10 @@ } else if (pck->frame_ifce) { pid->filter->nb_hw_pck_sent++; } + if (pck->info.cts!=GF_FILTER_NO_TS) { + pid->last_ts_sent.num = pck->info.cts; + pid->last_ts_sent.den = pck->pid_props->timescale; + } } cktype = ( pck->info.flags & GF_PCK_CKTYPE_MASK) >> GF_PCK_CKTYPE_POS;
View file
gpac-1.0.0.tar.gz/src/filter_core/filter_pid.c -> gpac-1.0.1.tar.gz/src/filter_core/filter_pid.c
Changed
@@ -1192,7 +1192,7 @@ u32 comp_type=0; Bool is_neg = GF_FALSE; const GF_PropertyEntry *pent; - + const GF_PropertyEntry *pent_val=NULL; *needs_resolve = GF_FALSE; *prop_not_found = GF_FALSE; @@ -1330,7 +1330,18 @@ prop_val.type = GF_PROP_UINT; prop_val.value.uint = gf_codec_parse(psep+1); } else { - prop_val = gf_props_parse_value(pent->prop.type, frag_name, psep+1, NULL, src_pid->filter->session->sep_list); + u32 val_is_prop = gf_props_get_id(psep+1); + if (val_is_prop) { + pent_val = gf_filter_pid_get_property_entry(src_pid, val_is_prop); + if (pent_val) { + prop_val = pent_val->prop; + } else { + *pid_excluded = GF_TRUE; + return GF_FALSE; + } + } else { + prop_val = gf_props_parse_value(pent->prop.type, frag_name, psep+1, NULL, src_pid->filter->session->sep_list); + } } if (!comp_type) { is_equal = gf_props_equal(&pent->prop, &prop_val); @@ -1375,7 +1386,9 @@ break; } } - gf_props_reset_single(&prop_val); + if (!pent_val) + gf_props_reset_single(&prop_val); + if (!is_equal) *pid_excluded = GF_TRUE; return is_equal; @@ -1538,7 +1551,8 @@ return GF_TRUE; } -Bool filter_in_parent_chain(GF_Filter *parent, GF_Filter *filter) +GF_EXPORT +Bool gf_filter_in_parent_chain(GF_Filter *parent, GF_Filter *filter) { u32 i, count; if (parent == filter) return GF_TRUE; @@ -1547,7 +1561,7 @@ if (!count) return GF_FALSE; for (i=0; i<count; i++) { GF_FilterPidInst *pid = gf_list_get(parent->input_pids, i); - if (filter_in_parent_chain(pid->pid->filter, filter)) return GF_TRUE; + if (gf_filter_in_parent_chain(pid->pid->filter, filter)) return GF_TRUE; } return GF_FALSE; } @@ -3245,7 +3259,8 @@ if (sep) sep[0]=0; if (args[0] != filter->session->sep_frag) { - if (gf_file_exists(args)) { + //if arg is not one of our reserved keywords and is a valid file, try to open it + if (strcmp(args, "gpac") && strcmp(args, "gfopt") && strcmp(args, "gfloc") && gf_file_exists(args)) { if (argfile_level<5) { char szLine[2001]; FILE *arg_file = gf_fopen(args, "rt"); @@ -3355,7 +3370,6 @@ if (prop_type==GF_PROP_NAME) { p.type = GF_PROP_STRING; gf_filter_pid_set_property(pid, p4cc, &p); - p.type = GF_PROP_NAME; } else { gf_filter_pid_set_property(pid, p4cc, &p); } @@ -3626,7 +3640,7 @@ filter_dst = gf_list_get(filter->session->filters, i); //source filter if (!filter_dst->freg->configure_pid) continue; - if (filter_dst->finalized || filter_dst->removed || filter_dst->marked_for_removal || filter_dst->no_inputs) continue; + if (filter_dst->finalized || filter_dst->removed || filter_dst->disabled || filter_dst->marked_for_removal || filter_dst->no_inputs) continue; if (filter_dst->target_filter == pid->filter) continue; //we don't allow re-entrant filter registries (eg filter foo of type A output cannot connect to filter bar of type A) @@ -3669,7 +3683,7 @@ u32 j, count2 = gf_list_count(filter_dst->source_filters); for (j=0; j<count2; j++) { GF_Filter *srcf = gf_list_get(filter_dst->source_filters, j); - if (filter_in_parent_chain(pid->filter, srcf)) { + if (gf_filter_in_parent_chain(pid->filter, srcf)) { ignore_source_ids = GF_TRUE; break; } @@ -3730,13 +3744,13 @@ } //walk up through the parent graph and check if this filter is already in. If so don't connect //since we don't allow re-entrant PIDs - if (filter_in_parent_chain(filter, filter_dst) ) { + if (gf_filter_in_parent_chain(filter, filter_dst) ) { GF_LOG(GF_LOG_DEBUG, GF_LOG_FILTER, ("PID %s has filter %s in its parent chain\n", pid->name, filter_dst->name)); continue; } //if the original filter is in the parent chain of this PID's filter, don't connect (equivalent to re-entrant) if (filter_dst->cloned_from) { - if (filter_in_parent_chain(filter, filter_dst->cloned_from) ) { + if (gf_filter_in_parent_chain(filter, filter_dst->cloned_from) ) { GF_LOG(GF_LOG_DEBUG, GF_LOG_FILTER, ("PID %s has the original of cloned filter %s in its parent chain\n", pid->name, filter_dst->name)); continue; } @@ -3744,7 +3758,7 @@ //if the filter is in the parent chain of this PID's original filter, don't connect (equivalent to re-entrant) if (filter->cloned_from) { - if (filter_in_parent_chain(filter->cloned_from, filter_dst) ) { + if (gf_filter_in_parent_chain(filter->cloned_from, filter_dst) ) { GF_LOG(GF_LOG_DEBUG, GF_LOG_FILTER, ("PID %s filter is cloned and has filter %s in its clone parent chain\n", pid->name, filter_dst->name)); continue; } @@ -3987,8 +4001,8 @@ for (k=0; k<gf_list_count(force_link_resolutions); k++) { GF_Filter *dst_link = gf_list_get(force_link_resolutions, k); if (//if forced filter is in parent chain (already connected filters), don't force a link - filter_in_parent_chain(filter_dst, dst_link) - || filter_in_parent_chain(dst_link, filter_dst) + gf_filter_in_parent_chain(filter_dst, dst_link) + || gf_filter_in_parent_chain(dst_link, filter_dst) //if forced filter is in destination of filter (connection pending), don't force a link || (gf_list_find(filter_dst->destination_filters, dst_link)>=0) || (gf_list_find(filter_dst->destination_links, dst_link)>=0) @@ -4696,15 +4710,14 @@ } -static GF_Err gf_filter_pid_merge_properties_internal(GF_FilterPid *dst_pid, GF_FilterPid *src_pid, gf_filter_prop_filter filter_prop, void *cbk, Bool do_copy) +static GF_Err gf_filter_pid_merge_properties_internal(GF_FilterPid *dst_pid, GF_FilterPid *src_pid, gf_filter_prop_filter filter_prop, void *cbk, Bool is_merge) { GF_PropertyMap *dst_props, *src_props, *old_dst_props=NULL; - if (PID_IS_INPUT(dst_pid)) { GF_LOG(GF_LOG_ERROR, GF_LOG_FILTER, ("Attempt to reset all properties on input PID in filter %s - ignoring\n", dst_pid->filter->name)); return GF_BAD_PARAM; } - if (do_copy) { + if (is_merge) { gf_mx_p(src_pid->filter->tasks_mx); old_dst_props = gf_list_last(dst_pid->properties); gf_mx_v(src_pid->filter->tasks_mx); @@ -4717,7 +4730,6 @@ GF_LOG(GF_LOG_WARNING, GF_LOG_FILTER, ("No properties for destination pid in filter %s, ignoring reset\n", dst_pid->filter->name)); return GF_OUT_OF_MEM; } - src_pid = src_pid->pid; //our list is not thread-safe, so we must lock the filter when destroying the props //otherwise gf_list_last() (this caller) might use the last entry while another threads sets this last entry to NULL @@ -4730,11 +4742,15 @@ } if (src_pid->name && !old_dst_props) gf_filter_pid_set_name(dst_pid, src_pid->name); - - gf_props_reset(dst_props); - if (old_dst_props) { - GF_Err e = gf_props_merge_property(dst_props, old_dst_props, NULL, NULL); - if (e) return e; + + if (!is_merge) { + gf_props_reset(dst_props); + } else { + //we created a new map + if (old_dst_props && (old_dst_props!=dst_props)) { + GF_Err e = gf_props_merge_property(dst_props, old_dst_props, NULL, NULL); + if (e) return e; + } } return gf_props_merge_property(dst_props, src_props, filter_prop, cbk); } @@ -5103,6 +5119,11 @@ pid = pid->pid; gf_filter_pidinst_update_stats(pidinst, pck); + if (pck->info.cts!=GF_FILTER_NO_TS) { + pidinst->last_ts_drop.num = pck->info.cts; + pidinst->last_ts_drop.den = pck->pid_props->timescale; + } + //make sure we lock the tasks mutex before getting the packet count, otherwise we might end up with a wrong number of packets //if one thread (the caller here) consumes one packet while the dispatching thread is still upddating the state for that pid @@ -5268,7 +5289,11 @@ props = gf_list_last(pid->pid->properties); gf_mx_v(pid->filter->tasks_mx); } else { - props = check_new_pid_props(pid, GF_FALSE); + //props = check_new_pid_props(pid, GF_FALSE); + + gf_mx_p(pid->filter->tasks_mx); + props = gf_list_last(pid->properties); + gf_mx_v(pid->filter->tasks_mx); } if (!props) { GF_LOG(GF_LOG_WARNING, GF_LOG_FILTER, ("No properties for pid in filter %s, ignoring enum\n", pid->filter->name)); @@ -5926,8 +5951,10 @@ if (evt->base.on_pid) { safe_int_inc(&evt->base.on_pid->filter->num_events_queued); } - - gf_fs_post_task(filter->session, gf_filter_pid_send_event_downstream, filter, evt->base.on_pid, "downstream_event", an_evt); + if (upstream) + gf_fs_post_task(filter->session, gf_filter_pid_send_event_upstream, filter, evt->base.on_pid, "upstream_event", an_evt); + else + gf_fs_post_task(filter->session, gf_filter_pid_send_event_downstream, filter, evt->base.on_pid, "downstream_event", an_evt); } @@ -5954,7 +5981,7 @@ { if (!pid || !filter) return GF_FALSE; pid = pid->pid; - return filter_in_parent_chain(pid->pid->filter, filter); + return gf_filter_in_parent_chain(pid->filter, filter); } static void filter_pid_collect_stats(GF_List *pidi_list, GF_FilterPidStatistics *stats) @@ -6455,6 +6482,8 @@ do_skip = GF_TRUE; } else if (!strncmp(name, "Init", 4)) { do_skip = GF_TRUE; + } else if (!strncmp(name, "XInit", 4)) { + do_skip = GF_TRUE; } else if (!strncmp(name, "Path", 4)) { do_skip = GF_TRUE; } else {
View file
gpac-1.0.0.tar.gz/src/filter_core/filter_props.c -> gpac-1.0.1.tar.gz/src/filter_core/filter_props.c
Changed
@@ -941,7 +941,8 @@ u32 idx; #endif GF_List *list; - dst_props->timescale = src_props->timescale; + if (src_props->timescale) + dst_props->timescale = src_props->timescale; #if GF_PROPS_HASHTABLE_SIZE for (idx=0; idx<GF_PROPS_HASHTABLE_SIZE; idx++) { @@ -1105,6 +1106,8 @@ { GF_PROP_PID_ID, "ID", "Stream ID", GF_PROP_UINT}, { GF_PROP_PID_ESID, "ESID", "MPEG-4 ESID of pid", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_ITEM_ID, "ItemID", "ID of image item in HEIF, same value as ID", GF_PROP_UINT}, + { GF_PROP_PID_ITEM_NUM, "ItemNumber", "Number (1-based) of image item in HEIF, in order of declaration in file", GF_PROP_UINT}, + { GF_PROP_PID_TRACK_NUM, "TrackNumber", "Number (1-based) of track in order of declaration in file", GF_PROP_UINT}, { GF_PROP_PID_SERVICE_ID, "ServiceID", "ID of parent service", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_CLOCK_ID, "ClockID", "ID of clock reference pid", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_DEPENDENCY_ID, "DependencyID", "ID of layer dependended on", GF_PROP_UINT}, @@ -1232,7 +1235,7 @@ "- 1: a clear clone of the sample description is created, inserted before the CENC sample description\n" "- 2: a clear clone of the sample description is created, inserted after the CENC sample description", GF_PROP_UINT}, { GF_PROP_PID_AMR_MODE_SET, "AMRModeSet", "ModeSet for AMR and AMR-WideBand", GF_PROP_UINT}, - { GF_PROP_PCK_SUBS, "SubSampleInfo", "Binary blob describing N subsamples of the sample, formatted as N [(u32)flags(u32)size(u32)reserved(u8)priority(u8) discardable]", GF_PROP_DATA}, + { GF_PROP_PCK_SUBS, "SubSampleInfo", "Binary blob describing N subsamples of the sample, formatted as N [(u32)flags(u32)size(u32)codec_param(u8)priority(u8) discardable]. Subsamples for a given flag MUST appear in order, however flags can be interleaved", GF_PROP_DATA}, { GF_PROP_PID_MAX_NALU_SIZE, "NALUMaxSize", "Max size of NAL units in stream - changes are signaled through pid_set_info (no reconfigure)", GF_PROP_UINT}, { GF_PROP_PCK_FILENUM, "FileNumber", "Index of file when dumping to files", GF_PROP_UINT, GF_PROP_FLAG_PCK}, { GF_PROP_PCK_FILENAME, "FileName", "Name of output file when dumping / dashing. Must be set on first packet belonging to new file", GF_PROP_STRING, GF_PROP_FLAG_PCK}, @@ -1276,8 +1279,11 @@ { GF_PROP_PID_XLINK, "xlink", "Remote period URL for DASH - cf dasher help", GF_PROP_STRING, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_CLAMP_DUR, "CDur", "Max media duration to process from pid in DASH mode", GF_PROP_DOUBLE, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_HLS_PLAYLIST, "HLSPL", "Name of the HLS variant playlist for this media", GF_PROP_STRING, GF_PROP_FLAG_GSF_REM}, + { GF_PROP_PID_HLS_GROUPID, "HLSGroup", "Name of HLS Group of a stream", GF_PROP_STRING, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_DASH_CUE, "DCue", "Name of a cue list file for this pid - see dasher help", GF_PROP_STRING, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_DASH_SEGMENTS, "DSegs", "Number of DASH segments defined by the DASH cue info", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, + { GF_PROP_PID_CODEC, "Codec", "codec parameter string to force. If starting with '.', appended to ISOBMF code point; otherwise replace the codec string", GF_PROP_STRING, GF_PROP_FLAG_GSF_REM}, + { GF_PROP_PID_SINGLE_SCALE, "SingleScale", "Indicates the movie header should use the media timescale of the first track added", GF_PROP_BOOL, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_UDP, "RequireReorder", "Indicates the PID packets come from source with losses and reordering happening (UDP)", GF_PROP_BOOL, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_PRIMARY_ITEM, "Primary", "Indicates this is a primary item in isobmf", GF_PROP_BOOL, GF_PROP_FLAG_GSF_REM}, @@ -1288,7 +1294,7 @@ { GF_PROP_PID_COLR_RANGE, "FullRange", "Indicate color full range flag for a visual pid (see ISO/IEC 23001-8 / 23091-2)", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_COLR_CHROMALOC, "ChromaLoc", "Indicate chrom location for a visual pid (see ISO/IEC 23001-8 / 23091-2)", GF_PROP_UINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_PID_SRC_MAGIC, "SrcMagic", "Indicate a magic number to store in the track, only used by importers", GF_PROP_LUINT, GF_PROP_FLAG_GSF_REM}, - { GF_PROP_PID_TRACK_INDEX, "TrackIndex", "Indicate target track index in destination file, stored by lowest value first (not set by demuxers)", GF_PROP_LUINT, GF_PROP_FLAG_GSF_REM}, + { GF_PROP_PID_MUX_INDEX, "MuxIndex", "Indicate target track index in destination file, stored by lowest value first (not set by demuxers)", GF_PROP_LUINT, GF_PROP_FLAG_GSF_REM}, { GF_PROP_NO_TS_LOOP, "NoTSLoop", "Indicate the timestamps on this PID are adjusted in case of loops (used by TS muxer output)", GF_PROP_BOOL, 0},
View file
gpac-1.0.0.tar.gz/src/filter_core/filter_session.c -> gpac-1.0.1.tar.gz/src/filter_core/filter_session.c
Changed
@@ -31,8 +31,10 @@ #endif //#define CHECK_TASK_LIST_INTEGRITY +#ifndef GPAC_DISABLE_PLAYER struct _gf_ft_mgr *gf_font_manager_new(); void gf_font_manager_del(struct _gf_ft_mgr *fm); +#endif static GFINLINE void gf_fs_sema_io(GF_FilterSession *fsess, Bool notify, Bool main) @@ -116,9 +118,14 @@ static Bool fs_default_event_proc(void *ptr, GF_Event *evt) { + GF_FilterSession *fs = (GF_FilterSession *)ptr; +#ifdef GPAC_HAS_QJS + if (fs->on_evt_task) + return jsfs_on_event(fs, evt); +#endif + if (evt->type==GF_EVENT_QUIT) { - GF_FilterSession *fsess = (GF_FilterSession *)ptr; - gf_fs_abort(fsess, GF_FALSE); + gf_fs_abort(fs, GF_FALSE); } return 0; } @@ -617,8 +624,12 @@ fsess->filters = NULL; } + gf_fs_unload_script(fsess, NULL); + if (fsess->download_manager) gf_dm_del(fsess->download_manager); +#ifndef GPAC_DISABLE_PLAYER if (fsess->font_manager) gf_font_manager_del(fsess->font_manager); +#endif if (fsess->registry) { while (gf_list_count(fsess->registry)) { @@ -980,16 +991,15 @@ GF_Filter *gf_fs_load_filter(GF_FilterSession *fsess, const char *name, GF_Err *err_code) { const char *args=NULL; + const char *sep; u32 i, len, count = gf_list_count(fsess->registry); Bool quiet = (err_code && (*err_code == GF_EOS)) ? GF_TRUE : GF_FALSE; - char *sep; - assert(fsess); assert(name); if (err_code) *err_code = GF_OK; - sep = strchr(name, fsess->sep_args); + sep = gf_fs_path_escape_colon(fsess, name); if (sep) { args = sep+1; len = (u32) (sep - name); @@ -2747,6 +2757,9 @@ GF_EXPORT struct _gf_ft_mgr *gf_filter_get_font_manager(GF_Filter *filter) { +#ifdef GPAC_DISABLE_PLAYER + return NULL; +#else GF_FilterSession *fsess; if (!filter) return NULL; fsess = filter->session; @@ -2755,6 +2768,7 @@ fsess->font_manager = gf_font_manager_new(); } return fsess->font_manager; +#endif } void gf_fs_cleanup_filters(GF_FilterSession *fsess) @@ -2902,15 +2916,12 @@ } GF_EXPORT -GF_Err gf_fs_get_filter_stats(GF_FilterSession *session, u32 idx, GF_FilterStats *stats) +GF_Err gf_filter_get_stats(GF_Filter *f, GF_FilterStats *stats) { - GF_Filter *f; u32 i; Bool set_name=GF_FALSE; - if (!stats || !session) return GF_BAD_PARAM; + if (!stats || !f) return GF_BAD_PARAM; memset(stats, 0, sizeof(GF_FilterStats)); - f = gf_list_get(session->filters, idx); - if (!f) return GF_BAD_PARAM; stats->filter = f; stats->filter_alias = f->multi_sink_target; if (f->multi_sink_target) return GF_OK; @@ -2945,6 +2956,9 @@ stats->nb_out_pck += pid->nb_pck_sent; if (pid->has_seen_eos) stats->in_eos = GF_TRUE; + if (pid->last_ts_sent.num * stats->last_ts_sent.den >= stats->last_ts_sent.num * pid->last_ts_sent.den) + stats->last_ts_sent = pid->last_ts_sent; + if (f->num_output_pids!=1) continue; if (!stats->codecid) @@ -2970,6 +2984,9 @@ if (pidi->pid->stream_type==GF_STREAM_FILE) stats->type = GF_FS_STATS_FILTER_DEMUX; + if (pidi->last_ts_drop.num * stats->last_ts_drop.den >= stats->last_ts_drop.num * pidi->last_ts_drop.den) + stats->last_ts_drop = pidi->last_ts_drop; + if ((f->num_input_pids!=1) && f->num_output_pids) continue; @@ -2983,9 +3000,23 @@ set_name = GF_FALSE; } } + if (!stats->type && stats->codecid) { + if (!stats->nb_pid_out) { + stats->type = GF_FS_STATS_FILTER_MEDIA_SINK; + } else if (!stats->nb_pid_in) { + stats->type = GF_FS_STATS_FILTER_MEDIA_SOURCE; + } + } return GF_OK; } +GF_EXPORT +GF_Err gf_fs_get_filter_stats(GF_FilterSession *session, u32 idx, GF_FilterStats *stats) +{ + if (!stats || !session) return GF_BAD_PARAM; + return gf_filter_get_stats(gf_list_get(session->filters, idx), stats); +} + Bool gf_fs_ui_event(GF_FilterSession *session, GF_Event *uievt) { Bool ret; @@ -3007,6 +3038,11 @@ } #ifndef GPAC_DISABLE_3D + + +#define GF_VIDEO_HW_INTERNAL (1<<29) +#define GF_VIDEO_HW_ATTACHED (1<<30) + static Bool fsess_on_event(void *cbk, GF_Event *evt) { return GF_TRUE; @@ -3034,6 +3070,7 @@ if (!gf_opts_get_key("core", "video-output")) { gf_opts_set_key("core", "video-output", session->gl_driver->module_name); } + session->gl_driver->hw_caps |= GF_VIDEO_HW_INTERNAL; session->gl_driver->on_event = fsess_on_event; session->gl_driver->evt_cbk_hdl = session; @@ -3074,6 +3111,48 @@ evt.type = GF_EVENT_SET_GL; return session->gl_driver->ProcessEvent(session->gl_driver, &evt); } + +GF_VideoOutput *gf_filter_claim_opengl_provider(GF_Filter *filter) +{ + if (!filter || !filter->session || !filter->session->gl_driver) return NULL; + + if (! (filter->session->gl_driver->hw_caps & GF_VIDEO_HW_INTERNAL)) + return NULL; + if (filter->session->gl_driver->hw_caps & GF_VIDEO_HW_ATTACHED) + return NULL; + + filter->session->gl_driver->hw_caps |= GF_VIDEO_HW_ATTACHED; + return filter->session->gl_driver; +} + +Bool gf_filter_unclaim_opengl_provider(GF_Filter *filter, GF_VideoOutput * video_out) +{ + if (!filter || !video_out) return GF_FALSE; + + if (! (video_out->hw_caps & GF_VIDEO_HW_INTERNAL)) + return GF_FALSE; + if (video_out != filter->session->gl_driver) + return GF_FALSE; + + if (filter->session->gl_driver->hw_caps & GF_VIDEO_HW_ATTACHED) { + filter->session->gl_driver->hw_caps &= ~GF_VIDEO_HW_ATTACHED; + filter->session->gl_driver->on_event = fsess_on_event; + filter->session->gl_driver->evt_cbk_hdl = filter->session; + return GF_TRUE; + } + return GF_FALSE; +} + +#else +void *gf_filter_claim_opengl_provider(GF_Filter *filter) +{ + return NULL; +} +Bool gf_filter_unclaim_opengl_provider(GF_Filter *filter, void *vout) +{ + return GF_FALSE; +} + #endif
View file
gpac-1.0.0.tar.gz/src/filter_core/filter_session.h -> gpac-1.0.1.tar.gz/src/filter_core/filter_session.h
Changed
@@ -31,6 +31,9 @@ #include <gpac/filters.h> #include <gpac/user.h> +#ifdef GPAC_HAS_QJS +#include "../scenegraph/qjs_common.h" +#endif #define GF_FILTER_SPEED_SCALER 1000 @@ -419,8 +422,20 @@ #endif //internal video output to hidden window for GL context struct _video_out *gl_driver; + +#ifdef GPAC_HAS_QJS + struct JSContext *js_ctx; + GF_List *jstasks; + struct __jsfs_task *new_f_task, *del_f_task, *on_evt_task; +#endif }; +#ifdef GPAC_HAS_QJS +void jsfs_on_filter_created(GF_Filter *new_filter); +void jsfs_on_filter_destroyed(GF_Filter *del_filter); +Bool jsfs_on_event(GF_FilterSession *session, GF_Event *evt); +#endif + void gf_fs_reg_all(GF_FilterSession *fsess, GF_FilterSession *a_sess); typedef struct @@ -684,6 +699,12 @@ GF_Filter *multi_sink_target; + Bool event_target; + +#ifdef GPAC_HAS_QJS + char *iname; + JSValue jsval; +#endif }; GF_Filter *gf_filter_new(GF_FilterSession *fsess, const GF_FilterRegister *freg, const char *args, const char *dst_args, GF_FilterArgType arg_type, GF_Err *err, GF_Filter *multi_sink_target, Bool dynamic_filter); @@ -781,6 +802,9 @@ GF_FilterClockType last_clock_type; GF_Filter *alias_orig; + + GF_Fraction64 last_ts_drop; + }; struct __gf_filter_pid @@ -839,6 +863,8 @@ //1000x speed value u32 playback_speed_scaler; + GF_Fraction64 last_ts_sent; + Bool initial_play_done; Bool is_playing; void *udta; @@ -875,8 +901,6 @@ void gf_filter_remove_task(GF_FSTask *task); void gf_filter_pid_detach_task(GF_FSTask *task); -Bool filter_in_parent_chain(GF_Filter *parent, GF_Filter *filter); - u32 gf_filter_caps_bundle_count(const GF_FilterCapability *caps, u32 nb_caps); void gf_filter_post_remove(GF_Filter *filter); @@ -983,6 +1007,8 @@ void gf_filter_renegociate_output_task(GF_FSTask *task); +void gf_fs_unload_script(GF_FilterSession *fs, void *js_ctx); + #endif //_GF_FILTER_SESSION_H_
View file
gpac-1.0.1.tar.gz/src/filter_core/filter_session_js.c
Added
@@ -0,0 +1,1241 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2017-2020 + * All rights reserved + * + * This file is part of GPAC / filters sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terfsess 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 "filter_session.h" + +#include <gpac/internal/scenegraph_dev.h> +#include "../scenegraph/qjs_common.h" + +#ifdef GPAC_HAS_QJS +void js_load_constants(JSContext *ctx, JSValue global_obj); + + + +static JSClassID fs_class_id; +typedef struct __jsfs_task +{ + JSValue fun; + JSValue _obj; + u32 type; + JSContext *ctx; +} JSFS_Task; + +static void jsfs_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) +{ + GF_FilterSession *fs = JS_GetOpaque(val, fs_class_id); + if (fs) { + u32 i, count=gf_list_count(fs->jstasks); + for (i=0; i<count; i++) { + JSFS_Task *task = gf_list_get(fs->jstasks, i); + JS_MarkValue(rt, task->fun, mark_func); + JS_MarkValue(rt, task->_obj, mark_func); + } + gf_fs_lock_filters(fs, GF_TRUE); + count = gf_list_count(fs->filters); + for (i=0; i<count; i++) { + GF_Filter *f = gf_list_get(fs->filters, i); + if (!JS_IsUndefined(f->jsval)) + JS_MarkValue(rt, f->jsval, mark_func); + } + gf_fs_lock_filters(fs, GF_FALSE); + } +} + +static JSClassDef fs_class = { + "FilterSession", + .gc_mark = jsfs_mark +}; + + +static JSClassID fs_f_class_id; +static JSClassDef fs_f_class = { + "Filter", +}; + +enum +{ + JSFS_NB_FILTERS = 0, + JSFS_LAST_TASK, + JSFS_HTTP_MAX_RATE, + JSFS_HTTP_RATE, + JSFS_RMT_SAMPLING +}; + +GF_Filter *jsff_get_filter(JSContext *c, JSValue this_val) +{ + return JS_GetOpaque(this_val, fs_f_class_id); +} +static JSValue jsfs_new_filter_obj(JSContext *ctx, GF_Filter *f); + + +static void jsfs_exec_task_custom(JSFS_Task *task, const char *text, GF_Filter *new_filter, GF_Filter *del_filter) +{ + JSValue ret, arg; + + gf_js_lock(task->ctx, GF_TRUE); + if (text) { + arg = JS_NewString(task->ctx, text); + } else if (new_filter) { + arg = jsfs_new_filter_obj(task->ctx, new_filter); + } else { + arg = JS_DupValue(task->ctx, del_filter->jsval); + } + + ret = JS_Call(task->ctx, task->fun, task->_obj, 1, &arg); + JS_FreeValue(task->ctx, arg); + + if (del_filter) { + JS_SetOpaque(del_filter->jsval, NULL); + JS_FreeValue(task->ctx, del_filter->jsval); + del_filter->jsval = JS_UNDEFINED; + } + + if (JS_IsException(ret)) { + js_dump_error(task->ctx); + } + JS_FreeValue(task->ctx, ret); + js_do_loop(task->ctx); + gf_js_lock(task->ctx, GF_FALSE); +} + +static void jsfs_rmt_user_callback(void *udta, const char* text) +{ + JSFS_Task *task = udta; + if (!task) return; + jsfs_exec_task_custom(task, text, NULL, NULL); +} + +static JSValue jsfs_prop_get(JSContext *ctx, JSValueConst this_val, int magic) +{ + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs) + return JS_EXCEPTION; + + switch (magic) { + case JSFS_NB_FILTERS: + return JS_NewInt32(ctx, gf_fs_get_filters_count(fs)); + case JSFS_LAST_TASK: + return gf_fs_is_last_task(fs) ? JS_TRUE : JS_FALSE; + + case JSFS_HTTP_MAX_RATE: + if (fs->download_manager) + return JS_NewInt32(ctx, gf_dm_get_data_rate(fs->download_manager) ); + return JS_NULL; + + case JSFS_HTTP_RATE: + if (fs->download_manager) + return JS_NewInt32(ctx, gf_dm_get_global_rate(fs->download_manager) / 1000); + return JS_NULL; + case JSFS_RMT_SAMPLING: + return JS_NewBool(ctx, gf_sys_profiler_sampling_enabled() ); + } + return JS_UNDEFINED; +} + +static JSValue jsfs_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +{ + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs) + return JS_EXCEPTION; + + switch (magic) { + case JSFS_HTTP_MAX_RATE: + if (fs->download_manager) { + s32 ival; + if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION; + gf_dm_set_data_rate(fs->download_manager, (u32) ival); + } + break; + case JSFS_RMT_SAMPLING: + gf_sys_profiler_enable_sampling(JS_ToBool(ctx, value) ? GF_TRUE : GF_FALSE); + break; + } + return JS_UNDEFINED; +} + +static Bool jsfs_task_exec(GF_FilterSession *fs, void *udta, u32 *timeout_ms) +{ + JSValue ret; + s32 ret_val; + Bool do_free=GF_TRUE; + JSFS_Task *task = udta; + gf_js_lock(task->ctx, GF_TRUE); + ret = JS_Call(task->ctx, task->fun, task->_obj, 0, NULL); + + *timeout_ms = 0; + if (JS_IsException(ret)) { + js_dump_error(task->ctx); + } + else if (JS_IsBool(ret)) { + if (JS_ToBool(task->ctx, ret)) + do_free = GF_FALSE; + } + else if (JS_IsInteger(ret)) { + JS_ToInt32(task->ctx, (int*)&ret_val, ret); + if (ret_val>=0) { + *timeout_ms = ret_val; + do_free = GF_FALSE; + } + } + + JS_FreeValue(task->ctx, ret); + js_do_loop(task->ctx); + gf_js_lock(task->ctx, GF_FALSE); + + if (do_free) { + JS_FreeValue(task->ctx, task->fun); + JS_FreeValue(task->ctx, task->_obj); + gf_list_del_item(fs->jstasks, task); + gf_free(task); + return GF_FALSE; + } + return GF_TRUE; +} + +static JSValue jsfs_post_task(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + JSFS_Task *task; + const char *tname = NULL; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) return JS_EXCEPTION; + if (!JS_IsFunction(ctx, argv[0]) ) return JS_EXCEPTION; + + GF_SAFEALLOC(task, JSFS_Task); + if (!task) return JS_EXCEPTION; + task->ctx = ctx; + + if (argc>1) { + tname = JS_ToCString(ctx, argv[1]); + } + task->fun = JS_DupValue(ctx, argv[0]); + task->_obj = JS_DupValue(ctx, this_val); + gf_list_add(fs->jstasks, task); + + gf_fs_post_user_task(fs, jsfs_task_exec, task, tname ? tname : "task"); + if (tname) + JS_FreeCString(ctx, tname); + + return JS_UNDEFINED; +} + +static JSValue jsfs_abort(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool do_flush = GF_FALSE; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs) return JS_EXCEPTION; + if (argc && JS_IsBool(argv[0]) && JS_ToBool(ctx, argv[0])) { + do_flush = GF_FALSE; + } + gf_fs_abort(fs, do_flush); + return JS_UNDEFINED; +} +static JSValue jsfs_lock_filters(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool do_lock; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) return JS_EXCEPTION; + if (JS_IsBool(argv[0])) do_lock = JS_ToBool(ctx, argv[0]); + else return JS_EXCEPTION; + + gf_fs_lock_filters(fs, do_lock); + return JS_UNDEFINED; +} + + +static JSValue jsfs_rmt_send(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *msg; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs ||!argc) return JS_EXCEPTION; + msg = JS_ToCString(ctx, argv[0]); + if (!msg) return JS_EXCEPTION; + gf_sys_profiler_send(msg); + JS_FreeCString(ctx, msg); + return JS_UNDEFINED; +} + + +void jsfs_on_filter_created(GF_Filter *new_filter) +{ + new_filter->jsval = JS_UNDEFINED; + if (!new_filter->session->new_f_task) return; + jsfs_exec_task_custom(new_filter->session->new_f_task, NULL, new_filter, NULL); +} + +void jsfs_on_filter_destroyed(GF_Filter *del_filter) +{ + if (! JS_IsUndefined(del_filter->jsval)) { + void *p = JS_GetOpaque(del_filter->jsval, fs_f_class_id); + if (!p) return; + if (del_filter->session->del_f_task) { + jsfs_exec_task_custom(del_filter->session->del_f_task, NULL, NULL, del_filter); + } else { + JSRuntime *gf_js_get_rt(); + JSRuntime *rt = gf_js_get_rt(); + if (rt) { + gf_js_lock(NULL, GF_TRUE); + JS_FreeValueRT(rt, del_filter->jsval); + gf_js_lock(NULL, GF_FALSE); + } + } + del_filter->jsval = JS_UNDEFINED; + } +} + +Bool jsfs_on_event(GF_FilterSession *fs, GF_Event *evt) +{ + GF_FilterEvent fevt; + JSValue js_init_evt_obj(JSContext *ctx, const GF_FilterEvent *evt); + + JSValue arg, ret; + Bool res; + assert(fs->on_evt_task); + gf_js_lock(fs->on_evt_task->ctx, GF_TRUE); + + memset(&fevt, 0, sizeof(GF_FilterEvent)); + fevt.user_event.event = *evt; + fevt.base.type = GF_FEVT_USER; + + arg = js_init_evt_obj(fs->on_evt_task->ctx, &fevt); + + ret = JS_Call(fs->on_evt_task->ctx, fs->on_evt_task->fun, fs->on_evt_task->_obj, 1, &arg); + JS_SetOpaque(arg, NULL); + JS_FreeValue(fs->on_evt_task->ctx, arg); + + if (JS_IsException(ret)) { + js_dump_error(fs->on_evt_task->ctx); + } + fevt.user_event.event.type = evt->type; + *evt = fevt.user_event.event; + res = JS_ToBool(fs->on_evt_task->ctx, ret) ? GF_TRUE : GF_FALSE; + if (!res && (evt->type==GF_EVENT_COPY_TEXT) && evt->clipboard.text) { + gf_free(evt->clipboard.text); + evt->clipboard.text = NULL; + } + JS_FreeValue(fs->on_evt_task->ctx, ret); + js_do_loop(fs->on_evt_task->ctx); + gf_js_lock(fs->on_evt_task->ctx, GF_FALSE); + return res; +} + + +static JSValue jsfs_set_fun_callback(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 cbk_type) +{ + JSFS_Task *task = NULL; + u32 i, count; + Bool is_rem = GF_FALSE; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) return JS_EXCEPTION; + + if (JS_IsNull(argv[0])) + is_rem = GF_TRUE; + else if (!JS_IsFunction(ctx, argv[0]) ) + return JS_EXCEPTION; + + if (cbk_type==2) { + task = fs->new_f_task; + } else if (cbk_type==3) { + task = fs->del_f_task; + } else if (cbk_type==4) { + task = fs->on_evt_task; + } else { + count = gf_list_count(fs->jstasks); + for (i=0; i<count; i++) { + task = gf_list_get(fs->jstasks, i); + if (task->type==1) break; + task = NULL; + } + } + if (is_rem) { + if (task) { + JS_FreeValue(ctx, task->fun); + JS_FreeValue(ctx, task->_obj); + gf_list_del_item(fs->jstasks, task); + gf_free(task); + } + if (cbk_type == 1) + gf_sys_profiler_set_callback(task, NULL); + else if (cbk_type == 2) + fs->new_f_task = NULL; + else if (cbk_type == 3) + fs->del_f_task = NULL; + else if (cbk_type == 4) + fs->on_evt_task = NULL; + + return JS_UNDEFINED; + } + + if (task) { + JS_FreeValue(ctx, task->fun); + JS_FreeValue(ctx, task->_obj); + } else { + GF_SAFEALLOC(task, JSFS_Task); + if (!task) return JS_EXCEPTION; + gf_list_add(fs->jstasks, task); + task->type = cbk_type; + task->ctx = ctx; + } + task->fun = JS_DupValue(ctx, argv[0]); + task->_obj = JS_DupValue(ctx, this_val); + + if (cbk_type == 1) + gf_sys_profiler_set_callback(task, jsfs_rmt_user_callback); + else if (cbk_type == 2) + fs->new_f_task = task; + else if (cbk_type == 3) + fs->del_f_task = task; + else if (cbk_type == 4) + fs->on_evt_task = task; + return JS_UNDEFINED; +} + +static JSValue jsfs_set_rmt_fun(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsfs_set_fun_callback(ctx, this_val, argc, argv, 1); +} +static JSValue jsfs_set_new_filter_fun(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsfs_set_fun_callback(ctx, this_val, argc, argv, 2); +} +static JSValue jsfs_set_del_filter_fun(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsfs_set_fun_callback(ctx, this_val, argc, argv, 3); +} +static JSValue jsfs_set_event_fun(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsfs_set_fun_callback(ctx, this_val, argc, argv, 4); +} + +enum +{ + JSFF_NAME = 0, + JSFF_TYPE, + JSFF_ID, + JSFF_NB_IPID, + JSFF_NB_OPID, + JSFF_STATUS, + JSFF_ALIAS, + JSFF_ARGS, + JSFF_DYNAMIC, + JSFF_REMOVED, + JSFF_PCK_DONE, + JSFF_BYTES_DONE, + JSFF_TIME, + JSFF_PCK_SENT_IFCE, + JSFF_PCK_SENT, + JSFF_BYTES_SENT, + JSFF_NB_TASKS, + JSFF_NB_ERRORS, + JSFF_REPORT_UPDATED, + JSFF_CLASS, + JSFF_CODEC, + JSFF_STREAMTYPE, + JSFF_INAME, + JSFF_EVENT_TARGET, + JSFF_LAST_TS_SENT, + JSFF_LAST_TS_DROP, +}; + + +static JSValue jsfs_f_prop_get(JSContext *ctx, JSValueConst this_val, int magic) +{ + const char *val_s; + Bool val_b; + GF_FilterStats stats; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f) + return JS_EXCEPTION; + + switch (magic) { + case JSFF_NAME: + return JS_NewString(ctx, gf_filter_get_name(f) ); + case JSFF_TYPE: + return JS_NewString(ctx, f->freg->name ); + case JSFF_ID: + val_s = gf_filter_get_id(f); + if (!val_s) return JS_NULL; + return JS_NewString(ctx, val_s); + case JSFF_NB_IPID: + return JS_NewInt32(ctx, gf_filter_get_ipid_count(f) ); + case JSFF_NB_OPID: + return JS_NewInt32(ctx, gf_filter_get_opid_count(f) ); + case JSFF_STATUS: + return JS_NewString(ctx, f->status_str ? f->status_str : ""); + case JSFF_ALIAS: + return JS_NewBool(ctx, f->multi_sink_target ? 1 : 0); + case JSFF_ARGS: + return JS_NewString(ctx, f->src_args ? f->src_args : ""); + case JSFF_DYNAMIC: + return JS_NewBool(ctx, f->dynamic_filter); + case JSFF_REMOVED: + return JS_NewBool(ctx, (f->removed || f->finalized)); + + case JSFF_PCK_DONE: + return JS_NewInt64(ctx, f->nb_pck_processed); + case JSFF_BYTES_DONE: + return JS_NewInt64(ctx, f->nb_bytes_processed); + case JSFF_TIME: + return JS_NewInt64(ctx, f->time_process); + case JSFF_PCK_SENT_IFCE: + return JS_NewInt64(ctx, f->nb_hw_pck_sent); + case JSFF_PCK_SENT: + return JS_NewInt64(ctx, f->nb_pck_sent); + case JSFF_BYTES_SENT: + return JS_NewInt64(ctx, f->nb_bytes_sent); + case JSFF_NB_TASKS: + return JS_NewInt64(ctx, f->nb_tasks_done); + case JSFF_NB_ERRORS: + return JS_NewInt64(ctx, f->nb_errors); + case JSFF_REPORT_UPDATED: + val_b = f->report_updated; + f->report_updated = GF_FALSE; + return JS_NewBool(ctx, val_b); + case JSFF_CLASS: + gf_filter_get_stats(f, &stats); + switch (stats.type) { + case GF_FS_STATS_FILTER_RAWIN: return JS_NewString(ctx, "rawin"); + case GF_FS_STATS_FILTER_DEMUX: return JS_NewString(ctx, "demuxer"); + case GF_FS_STATS_FILTER_DECODE: return JS_NewString(ctx, "decoder"); + case GF_FS_STATS_FILTER_ENCODE: return JS_NewString(ctx, "encoder"); + case GF_FS_STATS_FILTER_MUX: return JS_NewString(ctx, "muxer"); + case GF_FS_STATS_FILTER_RAWOUT: return JS_NewString(ctx, "rawout"); + case GF_FS_STATS_FILTER_MEDIA_SINK: return JS_NewString(ctx, "mediasink"); + case GF_FS_STATS_FILTER_MEDIA_SOURCE: return JS_NewString(ctx, "mediasource"); + default: return JS_NewString(ctx, "unknown"); + } + case JSFF_CODEC: + gf_filter_get_stats(f, &stats); + if (stats.codecid) { + return JS_NewString(ctx, gf_codecid_name(stats.codecid)); + } + return JS_NewString(ctx, "unknown"); + case JSFF_STREAMTYPE: + gf_filter_get_stats(f, &stats); + if (stats.stream_type) { + return JS_NewString(ctx, gf_stream_type_name(stats.stream_type)); + } + return JS_NewString(ctx, "unknown"); + + case JSFF_LAST_TS_SENT: + gf_filter_get_stats(f, &stats); + if (!stats.last_ts_sent.den) return JS_NULL; + return JS_NewInt64(ctx, stats.last_ts_sent.num); + case JSFF_LAST_TS_DROP: + gf_filter_get_stats(f, &stats); + if (!stats.last_ts_drop.den) return JS_NULL; + return JS_NewInt64(ctx, stats.last_ts_drop.num); + + case JSFF_INAME: + if (f->iname) return JS_NewString(ctx, f->iname); + return JS_NULL; + case JSFF_EVENT_TARGET: + return JS_NewBool(ctx, f->event_target); + } + return JS_UNDEFINED; +} + +static JSValue jsfs_f_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +{ + const char *s_val; +#ifdef GPAC_ENABLE_COVERAGE + GF_Filter *f = jsff_get_filter(ctx, this_val); +#else + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); +#endif + if (!f) + return JS_EXCEPTION; + + switch (magic) { + case JSFF_INAME: + s_val = JS_ToCString(ctx, value); + if (f->iname) gf_free(f->iname); + f->iname = s_val ? gf_strdup(s_val) : NULL; + JS_FreeCString(ctx, s_val); + break; + } + return JS_UNDEFINED; +} + + +static JSValue jsff_is_destroyed(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f) + return JS_TRUE; + return JS_FALSE; +} + +JSValue jsf_NewProp(JSContext *ctx, const GF_PropertyValue *new_val); + +static JSValue jsff_enum_pid_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_output) +{ + u32 idx; + GF_FilterPid *pid; + const char *pname=NULL; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f || (argc!=2) ) + return JS_EXCEPTION; + + if (JS_IsString(argv[1])) { + pname = JS_ToCString(ctx, argv[1]); + if (!pname) return JS_EXCEPTION; + } + else if (!JS_IsFunction(ctx, argv[1])) + return JS_EXCEPTION; + + if (JS_ToInt32(ctx, &idx, argv[0])) + return JS_EXCEPTION; + + if (is_output) { + pid = gf_filter_get_opid(f, idx); + if (!pid) return JS_EXCEPTION; + } else { + pid = gf_filter_get_ipid(f, idx); + if (!pid) return JS_EXCEPTION; + } + + if (pname) { + const GF_PropertyValue *p; + u32 p4cc = gf_props_get_id(pname); + if (p4cc) + p = gf_filter_pid_get_property(pid, p4cc); + else + p = gf_filter_pid_get_property_str(pid, pname); + + JS_FreeCString(ctx, pname); + return jsf_NewProp(ctx, p); + } + + idx = 0; + while (1) { + u32 prop_4cc; + const char *prop_name; + JSValue args[3], ret; + const GF_PropertyValue *prop = gf_filter_pid_enum_properties(pid, &idx, &prop_4cc, &prop_name); + if (!prop) break; + if (prop->type==GF_PROP_POINTER) continue; + + args[0] = JS_NewString(ctx, prop_name ? prop_name : gf_props_4cc_get_name(prop_4cc) ); + args[1] = JS_NewString(ctx, gf_props_get_type_name(prop->type) ); + args[2] = jsf_NewProp(ctx, prop); + ret = JS_Call(ctx, argv[1], this_val, 3, args); + if (JS_IsException(ret)) { + js_dump_error(ctx); + } + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); + JS_FreeValue(ctx, args[2]); + } + return JS_UNDEFINED; +} +static JSValue jsff_enum_ipid_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsff_enum_pid_props(ctx, this_val, argc, argv, GF_FALSE); +} +static JSValue jsff_enum_opid_props(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return jsff_enum_pid_props(ctx, this_val, argc, argv, GF_TRUE); +} + + +static JSValue jsff_get_pid_source(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 idx; + GF_FilterPid *pid; + GF_FilterPidInst *ipid; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f || (argc!=1) ) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &idx, argv[0])) + return JS_EXCEPTION; + + pid = gf_filter_get_ipid(f, idx); + if (!pid) return JS_NULL; + + ipid = (GF_FilterPidInst *)pid; + idx = gf_list_find(f->session->filters, ipid->pid->filter); + + return jsfs_new_filter_obj(ctx, ipid->pid->filter); +} + +static JSValue jsff_get_pid_sinks(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 idx; + JSValue ret; + GF_FilterPid *pid; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f || (argc!=1) ) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &idx, argv[0])) + return JS_EXCEPTION; + + pid = gf_filter_get_opid(f, idx); + if (!pid) return JS_NULL; + + ret = JS_NewArray(ctx); + JS_SetPropertyStr(ctx, ret, "length", JS_NewInt32(ctx, pid->num_destinations) ); + + for (idx=0; idx<pid->num_destinations; idx++) { + GF_FilterPidInst *pid_inst = gf_list_get(pid->destinations, idx); + JS_SetPropertyUint32(ctx, ret, idx, jsfs_new_filter_obj(ctx, pid_inst->filter) ); + } + return ret; +} + +static JSValue jsff_all_args(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 idx, a_idx; + JSValue res; + Bool val_only = GF_TRUE; + const GF_FilterArgs *args; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f) + return JS_EXCEPTION; + + if (argc && JS_IsBool(argv[0]) && JS_ToBool(ctx, argv[0])) + val_only = GF_FALSE; + + res = JS_NewArray(ctx); + idx=0; + a_idx=0; + args = f->instance_args ? f->instance_args : f->freg->args; + while (args && args[idx].arg_name) { + const GF_FilterArgs *arg = &args[idx]; + GF_PropertyValue p; + JSValue aval; + if (arg->flags & GF_FS_ARG_HINT_HIDE) { + idx++; + continue; + } + + aval = JS_NewObject(ctx); + JS_SetPropertyStr(ctx, aval, "name", JS_NewString(ctx, arg->arg_name) ); + if (f->instance_args) { + char szArgName[100]; + char *arg_start; + snprintf(szArgName, 100, "%c%s%c", f->session->sep_args, arg->arg_name, f->session->sep_name); + arg_start = f->orig_args ? strstr(f->orig_args, szArgName) : NULL; + if (arg_start) { + char *arg_end; + arg_start += strlen(szArgName); + arg_start = gf_strdup(arg_start); + arg_end = strchr(arg_start, f->session->sep_args); + if (arg_end) arg_end[0] = 0; + JS_SetPropertyStr(ctx, aval, "value", JS_NewString(ctx, arg_start) ); + gf_free(arg_start); + } else { + snprintf(szArgName, 100, "%c%s", f->session->sep_args, arg->arg_name); + arg_start = f->orig_args ? strstr(f->orig_args, szArgName) : NULL; + if (arg_start && (arg->arg_type==GF_PROP_BOOL)) { + p.type = GF_PROP_BOOL; + p.value.boolean = GF_TRUE; + JS_SetPropertyStr(ctx, aval, "value", jsf_NewProp(ctx, &p) ); + } else { + snprintf(szArgName, 100, "%c%c%s", f->session->sep_args, f->session->sep_neg, arg->arg_name); + arg_start = f->orig_args ? strstr(f->orig_args, szArgName) : NULL; + if (arg_start && (arg->arg_type==GF_PROP_BOOL)) { + p.type = GF_PROP_BOOL; + p.value.boolean = GF_FALSE; + JS_SetPropertyStr(ctx, aval, "value", jsf_NewProp(ctx, &p) ); + } else { + if (arg->arg_default_val) { + gf_props_parse_value(arg->arg_type, arg->arg_name, arg->arg_default_val, arg->min_max_enum, f->session->sep_list); + JS_SetPropertyStr(ctx, aval, "value", jsf_NewProp(ctx, &p) ); + } else { + JS_SetPropertyStr(ctx, aval, "value", JS_NULL); + } + } + } + } + } else { + gf_filter_get_arg(f, arg->arg_name, &p); + JS_SetPropertyStr(ctx, aval, "value", jsf_NewProp(ctx, &p) ); + } + if (!val_only) { + if (arg->arg_desc) + JS_SetPropertyStr(ctx, aval, "desc", JS_NewString(ctx, arg->arg_desc) ); + if (arg->min_max_enum) + JS_SetPropertyStr(ctx, aval, "min_max_enum", JS_NewString(ctx, arg->min_max_enum) ); + if (arg->arg_default_val) + JS_SetPropertyStr(ctx, aval, "default", JS_NewString(ctx, arg->arg_default_val) ); + JS_SetPropertyStr(ctx, aval, "update", JS_NewBool(ctx, (arg->flags & GF_FS_ARG_UPDATE) ) ); + if (arg->flags & GF_FS_ARG_HINT_ADVANCED) { + JS_SetPropertyStr(ctx, aval, "hint", JS_NewString(ctx, "advanced") ); + } + else if (arg->flags & GF_FS_ARG_HINT_EXPERT) { + JS_SetPropertyStr(ctx, aval, "hint", JS_NewString(ctx, "expert") ); + } + } + JS_SetPropertyUint32(ctx, res, idx, aval); + idx++; + a_idx++; + } + return res; +} + +static JSValue jsff_update(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *aname, *aval; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f || (argc!=2) ) + return JS_EXCEPTION; + + aname = JS_ToCString(ctx, argv[0]); + if (!aname) return JS_EXCEPTION; + aval = JS_ToCString(ctx, argv[1]); + if (!aval) { + JS_FreeCString(ctx, aname); + return JS_EXCEPTION; + } + gf_fs_send_update(f->session, NULL, f, aname, aval, 0); + JS_FreeCString(ctx, aname); + JS_FreeCString(ctx, aval); + return JS_UNDEFINED; +} + +static JSValue jsff_remove(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f) + return JS_EXCEPTION; + + gf_filter_remove(f); + return JS_UNDEFINED; +} + +static JSValue jsff_insert_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *fname, *link_args; + GF_Filter *new_f; + GF_Err e; + GF_Filter *f = JS_GetOpaque(this_val, fs_f_class_id); + if (!f || !argc) + return JS_EXCEPTION; + + fname = JS_ToCString(ctx, argv[0]); + if (!fname) return JS_EXCEPTION; + link_args = NULL; + if (argc>1) { + link_args = JS_ToCString(ctx, argv[1]); + if (!link_args) { + JS_FreeCString(ctx, fname); + return JS_EXCEPTION; + } + } + + if (!strncmp(fname, "src=", 4)) { + new_f = gf_fs_load_source(f->session, fname+4, NULL, NULL, &e); + } else if (!strncmp(fname, "dst=", 4)) { + new_f = gf_fs_load_destination(f->session, fname+4, NULL, NULL, &e); + } else { + new_f = gf_fs_load_filter(f->session, fname, &e); + } + + if (!new_f) { + JSValue ret = js_throw_err_msg(ctx, e, "Cannot load filter %s: %s\n", fname, gf_error_to_string(e)); + JS_FreeCString(ctx, fname); + if (link_args) JS_FreeCString(ctx, link_args); + return ret; + } + gf_filter_set_source(new_f, (GF_Filter *) f, link_args); + //reconnect outputs of source + gf_filter_reconnect_output((GF_Filter *) f); + + JS_FreeCString(ctx, fname); + if (link_args) JS_FreeCString(ctx, link_args); + + return jsfs_new_filter_obj(ctx, new_f); +} + +#define JS_CGETSET_MAGIC_DEF_ENUM(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE|JS_PROP_ENUMERABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } + +static const JSCFunctionListEntry fs_f_funcs[] = { + JS_CGETSET_MAGIC_DEF_ENUM("name", jsfs_f_prop_get, NULL, JSFF_NAME), + JS_CGETSET_MAGIC_DEF_ENUM("type", jsfs_f_prop_get, NULL, JSFF_TYPE), + JS_CGETSET_MAGIC_DEF_ENUM("ID", jsfs_f_prop_get, NULL, JSFF_ID), + JS_CGETSET_MAGIC_DEF_ENUM("nb_ipid", jsfs_f_prop_get, NULL, JSFF_NB_IPID), + JS_CGETSET_MAGIC_DEF_ENUM("nb_opid", jsfs_f_prop_get, NULL, JSFF_NB_OPID), + JS_CGETSET_MAGIC_DEF_ENUM("status", jsfs_f_prop_get, NULL, JSFF_STATUS), + JS_CGETSET_MAGIC_DEF_ENUM("alias", jsfs_f_prop_get, NULL, JSFF_ALIAS), + JS_CGETSET_MAGIC_DEF_ENUM("args", jsfs_f_prop_get, NULL, JSFF_ARGS), + JS_CGETSET_MAGIC_DEF_ENUM("dynamic", jsfs_f_prop_get, NULL, JSFF_DYNAMIC), + JS_CGETSET_MAGIC_DEF_ENUM("done", jsfs_f_prop_get, NULL, JSFF_REMOVED), + JS_CGETSET_MAGIC_DEF_ENUM("pck_done", jsfs_f_prop_get, NULL, JSFF_PCK_DONE), + JS_CGETSET_MAGIC_DEF_ENUM("bytes_done", jsfs_f_prop_get, NULL, JSFF_BYTES_DONE), + JS_CGETSET_MAGIC_DEF_ENUM("time", jsfs_f_prop_get, NULL, JSFF_TIME), + JS_CGETSET_MAGIC_DEF_ENUM("pck_sent", jsfs_f_prop_get, NULL, JSFF_PCK_SENT), + JS_CGETSET_MAGIC_DEF_ENUM("pck_ifce_sent", jsfs_f_prop_get, NULL, JSFF_PCK_SENT_IFCE), + JS_CGETSET_MAGIC_DEF_ENUM("bytes_sent", jsfs_f_prop_get, NULL, JSFF_BYTES_SENT), + JS_CGETSET_MAGIC_DEF_ENUM("tasks", jsfs_f_prop_get, NULL, JSFF_NB_TASKS), + JS_CGETSET_MAGIC_DEF_ENUM("errors", jsfs_f_prop_get, NULL, JSFF_NB_ERRORS), + JS_CGETSET_MAGIC_DEF_ENUM("report_updated", jsfs_f_prop_get, NULL, JSFF_REPORT_UPDATED), + JS_CGETSET_MAGIC_DEF_ENUM("class", jsfs_f_prop_get, NULL, JSFF_CLASS), + JS_CGETSET_MAGIC_DEF_ENUM("streamtype", jsfs_f_prop_get, NULL, JSFF_STREAMTYPE), + JS_CGETSET_MAGIC_DEF_ENUM("codec", jsfs_f_prop_get, NULL, JSFF_CODEC), + JS_CGETSET_MAGIC_DEF_ENUM("iname", jsfs_f_prop_get, jsfs_f_prop_set, JSFF_INAME), + JS_CGETSET_MAGIC_DEF_ENUM("event_target", jsfs_f_prop_get, NULL, JSFF_EVENT_TARGET), + JS_CGETSET_MAGIC_DEF_ENUM("last_ts_sent", jsfs_f_prop_get, NULL, JSFF_LAST_TS_SENT), + JS_CGETSET_MAGIC_DEF_ENUM("last_ts_drop", jsfs_f_prop_get, NULL, JSFF_LAST_TS_DROP), + + JS_CFUNC_DEF("is_destroyed", 0, jsff_is_destroyed), + JS_CFUNC_DEF("ipid_props", 0, jsff_enum_ipid_props), + JS_CFUNC_DEF("opid_props", 0, jsff_enum_opid_props), + JS_CFUNC_DEF("ipid_source", 0, jsff_get_pid_source), + JS_CFUNC_DEF("opid_sinks", 0, jsff_get_pid_sinks), + JS_CFUNC_DEF("all_args", 0, jsff_all_args), + JS_CFUNC_DEF("update", 0, jsff_update), + JS_CFUNC_DEF("remove", 0, jsff_remove), + JS_CFUNC_DEF("insert", 0, jsff_insert_filter), +}; + +static JSValue jsfs_new_filter_obj(JSContext *ctx, GF_Filter *f) +{ + if (JS_IsUndefined(f->jsval)) { + f->jsval = JS_NewObjectClass(ctx, fs_f_class_id); + JS_SetPropertyFunctionList(ctx, f->jsval, fs_f_funcs, countof(fs_f_funcs)); + JS_SetOpaque(f->jsval, f); + } + return JS_DupValue(ctx, f->jsval); +} + +static JSValue jsfs_get_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 idx; + GF_Filter *f = NULL; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) return JS_EXCEPTION; + + if (JS_IsString(argv[0])) { + const char *iname = JS_ToCString(ctx, argv[0]); + if (iname) { + u32 i, count; + gf_fs_lock_filters(fs, GF_TRUE); + count=gf_list_count(fs->filters); + for (i=0; i<count; i++) { + f = gf_list_get(fs->filters, i); + if (f->iname && !strcmp(f->iname, iname)) break; + f = NULL; + } + gf_fs_lock_filters(fs, GF_FALSE); + } + JS_FreeCString(ctx, iname); + } else { + if (JS_ToInt32(ctx, &idx, argv[0])) + return JS_EXCEPTION; + + f = gf_list_get(fs->filters, idx); + } + if (!f) return JS_EXCEPTION; + + return jsfs_new_filter_obj(ctx, f); +} + + +static JSValue jsfs_add_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *fname, *link_args; + GF_Filter *new_f; + GF_Err e; + GF_Filter *link_from = NULL; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) + return JS_EXCEPTION; + + fname = JS_ToCString(ctx, argv[0]); + if (!fname) return JS_EXCEPTION; + + link_args = NULL; + if (argc>1) { + link_from = JS_GetOpaque(argv[1], fs_f_class_id); + if (!link_from) { + JS_FreeCString(ctx, fname); + return JS_EXCEPTION; + } + if (argc>2) { + link_args = JS_ToCString(ctx, argv[2]); + } + } + + if (!strncmp(fname, "src=", 4)) { + new_f = gf_fs_load_source(fs, fname+4, NULL, NULL, &e); + } else if (!strncmp(fname, "dst=", 4)) { + new_f = gf_fs_load_destination(fs, fname+4, NULL, NULL, &e); + } else { + new_f = gf_fs_load_filter(fs, fname, &e); + } + + if (!new_f) { + JSValue ret = js_throw_err_msg(ctx, e, "Cannot load filter %s: %s\n", fname, gf_error_to_string(e)); + JS_FreeCString(ctx, fname); + if (link_args) JS_FreeCString(ctx, link_args); + return ret; + } + JS_FreeCString(ctx, fname); + if (link_from) { + gf_filter_set_source(new_f, link_from, link_args); + } + + if (link_args) JS_FreeCString(ctx, link_args); + + return jsfs_new_filter_obj(ctx, new_f); +} + +static JSValue jsfs_fire_event(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 i, count; + GF_Filter *f = NULL; + Bool ret=GF_FALSE; + GF_FilterPid *on_pid; + GF_FilterEvent *jsf_get_event(JSContext *ctx, JSValueConst this_val); + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + GF_FilterEvent *evt; + if (!fs || !argc) + return JS_EXCEPTION; + + evt = jsf_get_event(ctx, argv[0]); + if (!evt) return JS_EXCEPTION; + + if (argc>1) { + f = jsff_get_filter(ctx, argv[1]); + } + on_pid = evt->base.on_pid; + evt->base.on_pid = NULL; + if (f) { + Bool upstream = GF_FALSE; + if (evt->base.type==GF_FEVT_USER) { + if (f->freg->process_event && f->event_target) { + gf_mx_p(f->tasks_mx); + f->freg->process_event(f, evt); + gf_mx_v(f->tasks_mx); + ret = GF_TRUE; + } + } + if (!ret) { + if (argc>2) upstream = JS_ToBool(ctx, argv[2]); + gf_mx_p(f->tasks_mx); + if (f->num_output_pids && upstream) ret = GF_TRUE; + else if (f->num_input_pids && !upstream) ret = GF_TRUE; + gf_filter_send_event(f, evt, upstream); + gf_mx_v(f->tasks_mx); + } + } else { + gf_fs_lock_filters(fs, GF_TRUE); + count = gf_list_count(fs->filters); + for (i=0; i<count; i++) { + Bool canceled; + f = gf_list_get(fs->filters, i); + if (f->disabled || f->removed) continue; + if (f->multi_sink_target) continue; + if (!f->freg->process_event) continue; + if (!f->event_target) continue; + + gf_mx_p(f->tasks_mx); + canceled = f->freg->process_event(f, evt); + gf_mx_v(f->tasks_mx); + ret = GF_TRUE; + if (canceled) break; + } + gf_fs_lock_filters(fs, GF_FALSE); + } + evt->base.on_pid = on_pid; + return JS_NewBool(ctx, ret); +} + +static JSValue jsfs_reporting(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool report_on; + GF_FilterSession *fs = JS_GetOpaque(this_val, fs_class_id); + if (!fs || !argc) + return JS_EXCEPTION; + report_on = JS_ToBool(ctx, argv[0]); + gf_fs_enable_reporting(fs, report_on); + return JS_UNDEFINED; +} + + +static const JSCFunctionListEntry fs_funcs[] = { + JS_CGETSET_MAGIC_DEF_ENUM("nb_filters", jsfs_prop_get, NULL, JSFS_NB_FILTERS), + JS_CGETSET_MAGIC_DEF_ENUM("last_task", jsfs_prop_get, NULL, JSFS_LAST_TASK), + JS_CGETSET_MAGIC_DEF("http_max_bitrate", jsfs_prop_get, jsfs_prop_set, JSFS_HTTP_MAX_RATE), + JS_CGETSET_MAGIC_DEF("http_bitrate", jsfs_prop_get, NULL, JSFS_HTTP_RATE), + JS_CGETSET_MAGIC_DEF("rmt_sampling", jsfs_prop_get, jsfs_prop_set, JSFS_RMT_SAMPLING), + + JS_CFUNC_DEF("post_task", 0, jsfs_post_task), + JS_CFUNC_DEF("abort", 0, jsfs_abort), + JS_CFUNC_DEF("get_filter", 0, jsfs_get_filter), + JS_CFUNC_DEF("lock_filters", 0, jsfs_lock_filters), + JS_CFUNC_DEF("rmt_send", 0, jsfs_rmt_send), + JS_CFUNC_DEF("set_rmt_fun", 0, jsfs_set_rmt_fun), + JS_CFUNC_DEF("set_new_filter_fun", 0, jsfs_set_new_filter_fun), + JS_CFUNC_DEF("set_del_filter_fun", 0, jsfs_set_del_filter_fun), + JS_CFUNC_DEF("set_event_fun", 0, jsfs_set_event_fun), + JS_CFUNC_DEF("add_filter", 0, jsfs_add_filter), + JS_CFUNC_DEF("fire_event", 0, jsfs_fire_event), + JS_CFUNC_DEF("reporting", 0, jsfs_reporting), + +}; + +GF_Err gf_fs_load_js_api(JSContext *c, GF_FilterSession *fs) +{ + JSValue fs_obj; + JSRuntime *rt; + JSValue global_obj; + + if (fs->js_ctx) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSFS] FilterSession API already loaded by another script, cannot load twice\n")); + return GF_NOT_SUPPORTED; + } + + rt = JS_GetRuntime(c); + global_obj = JS_GetGlobalObject(c); + + js_load_constants(c, global_obj); + if (!fs->jstasks) { + fs->jstasks = gf_list_new(); + if (!fs->jstasks) return GF_OUT_OF_MEM; + } + + + //initialize filter class and create a single filter object in global scope + JS_NewClassID(&fs_class_id); + JS_NewClass(rt, fs_class_id, &fs_class); + + JS_NewClassID(&fs_f_class_id); + JS_NewClass(rt, fs_f_class_id, &fs_f_class); + + + fs_obj = JS_NewObjectClass(c, fs_class_id); + JS_SetPropertyFunctionList(c, fs_obj, fs_funcs, countof(fs_funcs)); + JS_SetOpaque(fs_obj, fs); + JS_SetPropertyStr(c, global_obj, "session", fs_obj); + + JS_FreeValue(c, global_obj); + return GF_OK; +} + +GF_EXPORT +GF_Err gf_fs_load_script(GF_FilterSession *fs, const char *jsfile) +{ + JSValue global_obj; + u8 *buf; + u32 buf_len; + u32 flags = JS_EVAL_TYPE_GLOBAL; + JSValue ret; + JSContext *ctx; + + + if (!fs) return GF_BAD_PARAM; + if (fs->js_ctx) return GF_NOT_SUPPORTED; + +#ifdef GPAC_HAS_QJS + ctx = gf_js_create_context(); + if (!ctx) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Failed to load QuickJS context\n")); + return GF_IO_ERR; + } + JS_SetContextOpaque(ctx, fs); + + global_obj = JS_GetGlobalObject(ctx); + gf_fs_load_js_api(ctx, fs); + fs->js_ctx = ctx; + + JS_SetPropertyStr(fs->js_ctx, global_obj, "_gpac_log_name", JS_NewString(fs->js_ctx, gf_file_basename(jsfile) ) ); + JS_FreeValue(fs->js_ctx, global_obj); + + + //load script + GF_Err e = gf_file_load_data(jsfile, &buf, &buf_len); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading script file %s: %s\n", jsfile, gf_error_to_string(e) )); + return e; + } + + if (!gf_opts_get_bool("core", "no-js-mods") && JS_DetectModule((char *)buf, buf_len)) { + //init modules + qjs_module_init_gpaccore(fs->js_ctx); + qjs_module_init_xhr(fs->js_ctx); + qjs_module_init_evg(fs->js_ctx); + qjs_module_init_storage(fs->js_ctx); + qjs_module_init_webgl(fs->js_ctx); + flags = JS_EVAL_TYPE_MODULE; + } + + ret = JS_Eval(fs->js_ctx, (char *)buf, buf_len, jsfile, flags); + gf_free(buf); + + if (JS_IsException(ret)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading script %s\n", jsfile)); + js_dump_error(fs->js_ctx); + JS_FreeValue(fs->js_ctx, ret); + return GF_BAD_PARAM; + } + JS_FreeValue(fs->js_ctx, ret); + return GF_OK; +#else + return GF_NOT_SUPPORTED; +#endif + +} + +void gf_fs_unload_script(GF_FilterSession *fs, void *js_ctx) +{ + u32 i, count=gf_list_count(fs->jstasks); + for (i=0; i<count; i++) { + JSFS_Task *task = gf_list_get(fs->jstasks, i); + if (js_ctx && (task->ctx != js_ctx)) + continue; + JS_FreeValue(task->ctx, task->fun); + JS_FreeValue(task->ctx, task->_obj); + gf_free(task); + gf_list_rem(fs->jstasks, i); + i--; + count--; + } + if (fs->js_ctx) { + gf_js_delete_context(fs->js_ctx); + fs->js_ctx = NULL; + } + if (!js_ctx || !gf_list_count(fs->jstasks)) { + gf_list_del(fs->jstasks); + fs->jstasks = NULL; + } +} + +#else +GF_EXPORT +GF_Err gf_fs_load_script(GF_FilterSession *fs, const char *jsfile) +{ + return GF_NOT_SUPPORTED; +} +void gf_fs_unload_script(GF_FilterSession *fs, void *js_ctx) +{ + +} + +#endif + + +
View file
gpac-1.0.0.tar.gz/src/filters/bsrw.c -> gpac-1.0.1.tar.gz/src/filters/bsrw.c
Changed
@@ -213,6 +213,8 @@ return GF_OK; } +#ifndef GPAC_DISABLE_HEVC + static GF_Err hevc_rewrite_packet(GF_BSRWCtx *ctx, BSRWPid *pctx, GF_FilterPacket *pck) { u32 size, pck_size, final_size; @@ -310,6 +312,7 @@ } return GF_OK; } +#endif // GPAC_DISABLE_HEVC static GF_Err none_rewrite_pid_config(GF_BSRWCtx *ctx, BSRWPid *pctx) { @@ -471,11 +474,13 @@ case GF_CODECID_MVC: pctx->rewrite_pid_config = avc_rewrite_pid_config; break; +#ifndef GPAC_DISABLE_HEVC case GF_CODECID_HEVC: case GF_CODECID_HEVC_TILES: case GF_CODECID_LHVC: pctx->rewrite_pid_config = hevc_rewrite_pid_config; break; +#endif case GF_CODECID_MPEG4_PART2: pctx->rewrite_pid_config = m4v_rewrite_pid_config; break;
View file
gpac-1.0.0.tar.gz/src/filters/compose.c -> gpac-1.0.1.tar.gz/src/filters/compose.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2017-2018 + * Copyright (c) Telecom ParisTech 2017-2020 * All rights reserved * * This file is part of GPAC / compositor filter @@ -29,6 +29,7 @@ //to set caps in filter session, to cleanup! #include "../filter_core/filter_session.h" +#ifndef GPAC_DISABLE_PLAYER GF_Err compose_bifs_dec_config_input(GF_Scene *scene, GF_FilterPid *pid, u32 oti, Bool is_remove); GF_Err compose_bifs_dec_process(GF_Scene *scene, GF_FilterPid *pid); @@ -348,21 +349,26 @@ was_dyn_scene = scene->is_dynamic_scene; - //we have an MPEG-4 ESID defined for the PID, this is MPEG-4 systems - prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID); - if (prop && scene->is_dynamic_scene) { - scene->is_dynamic_scene = GF_FALSE; - } - //pure OCR streams are handled by dispatching OCR on the PID(s) if (codecid != GF_CODECID_RAW) return GF_NOT_SUPPORTED; - prop = gf_filter_pid_get_property(pid, GF_PROP_PID_IN_IOD); - if (prop && prop->value.boolean) { - scene->is_dynamic_scene = GF_FALSE; - in_iod = GF_TRUE; + switch (mtype) { + case GF_STREAM_SCENE: + case GF_STREAM_OD: + //we have an MPEG-4 ESID defined for the PID, this is MPEG-4 systems + prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID); + if (prop && scene->is_dynamic_scene) { + scene->is_dynamic_scene = GF_FALSE; + } + prop = gf_filter_pid_get_property(pid, GF_PROP_PID_IN_IOD); + if (prop && prop->value.boolean) { + scene->is_dynamic_scene = GF_FALSE; + in_iod = GF_TRUE; + } + break; } + if ((mtype==GF_STREAM_OD) && !in_iod) return GF_NOT_SUPPORTED; //we inserted a root scene (bt/svg/...) after a pid (passthrough mode), we need to create a new namesapce for @@ -562,6 +568,9 @@ } return GF_TRUE; + case GF_FEVT_USER: + return gf_sc_user_event(gf_filter_get_udta(filter), (GF_Event *) &evt->user_event.event); + default: break; } @@ -696,6 +705,7 @@ //always request a process task since we don't depend on input packets arrival (animations, pure scene presentations) gf_filter_post_process_task(filter); + gf_filter_set_event_target(filter, GF_TRUE); if (ctx->player==2) { const char *gui_path = gf_opts_get_key("General", "StartupFile"); if (gui_path) @@ -707,14 +717,14 @@ #define OFFS(_n) #_n, offsetof(GF_Compositor, _n) static GF_FilterArgs CompositorArgs[] = { - { OFFS(aa), "set anti-aliasing mode for raster graphics - whether the setting is applied or not depends on the graphics module / graphic card.\n"\ + { OFFS(aa), "set anti-aliasing mode for raster graphics; whether the setting is applied or not depends on the graphics module or graphic card\n"\ "- none: no anti-aliasing\n"\ "- text: anti-aliasing for text only\n"\ "- all: complete anti-aliasing", GF_PROP_UINT, "all", "none|text|all", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(hlfill), "set highlight fill color (ARGB)", GF_PROP_UINT, "0x0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(hlline), "set highlight stroke color (ARGB)", GF_PROP_UINT, "0xFF000000", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(hllinew), "set highlight stroke width", GF_PROP_FLOAT, "1.0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, - { OFFS(sz), "enable scalable zoom. When scalable zoom is enabled, resizing the output window will also recompute all vectorial objects. Otherwise only the final buffer is stretched.", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, + { OFFS(sz), "enable scalable zoom. When scalable zoom is enabled, resizing the output window will also recompute all vectorial objects. Otherwise only the final buffer is stretched", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(bc), "default background color to use when displaying transparent images or video with no scene composition instructions", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, { OFFS(yuvhw), "enable YUV hardware for 2D blits", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(blitp), "partial hardware blits (if not set, will force more redraw)", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, @@ -722,7 +732,7 @@ { OFFS(stress), "enable stress mode of compositor (rebuild all vector graphics and texture states at each frame)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(fast), "enable speed optimization - whether the setting is applied or not depends on the graphics module / graphic card", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE}, - { OFFS(bvol), "draw bounding volume of objects.\n"\ + { OFFS(bvol), "draw bounding volume of objects\n"\ "- no: disable bounding box\n"\ "- box: draws a rectangle (2D) or box (3D mode)\n"\ "- aabb: draws axis-aligned bounding-box tree (3D only)", GF_PROP_UINT, "no", "no|box|aabb", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, @@ -731,53 +741,59 @@ "- never: never uses text textures\n"\ "- always: always render text to texture before drawing"\ "", GF_PROP_UINT, "default", "default|never|always", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, - { OFFS(out8b), "convert 10-bit video to 8 bit texture before GPU upload.", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, + { OFFS(out8b), "convert 10-bit video to 8 bit texture before GPU upload", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(drop), "drop late frame when drawing. By default frames are not droped until a heavy desync of 1 sec is observed", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE}, { OFFS(sclock), "force synchronizing all streams on a single clock", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(sgaze), "simulate gaze events through mouse", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, - { OFFS(ckey), "color key to use in windowless mode (0xFFRRGGBB). GPAC currently does not support true alpha blitting to desktop due to limitations in most windowing toolkit, it therefore uses color keying mechanism. The alpha part of the key is used for global transparency of the output, if supported.", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, + { OFFS(ckey), "color key to use in windowless mode (0xFFRRGGBB). GPAC currently does not support true alpha blitting to desktop due to limitations in most windowing toolkit, it therefore uses color keying mechanism. The alpha part of the key is used for global transparency of the output, if supported", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(timeout), "timeout in ms after which a source is considered dead", GF_PROP_UINT, "10000", NULL, GF_FS_ARG_UPDATE}, - { OFFS(fps), "simulation frame rate when animation-only sources are played (ignored when video is present).", GF_PROP_FRACTION, "30/1", NULL, GF_FS_ARG_UPDATE}, - { OFFS(timescale), "timescale used for output packets when no input video pid. A value of 0 means fps numerator.", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, + { OFFS(fps), "simulation frame rate when animation-only sources are played (ignored when video is present)", GF_PROP_FRACTION, "30/1", NULL, GF_FS_ARG_UPDATE}, + { OFFS(timescale), "timescale used for output packets when no input video pid. A value of 0 means fps numerator", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, { OFFS(autofps), "use video input fps for output. If no video or not set, uses [-fps](). Ignored in player mode", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(vfr), "only emit frames when changes are detected. Always true in player mode and when filter is dynamically loaded", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(dur), "duration of generation. Mostly used when no video input is present. Negative values mean number of frames, positive values duration in second, 0 stops as soon as all streams are done.", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_UPDATE}, + { OFFS(dur), "duration of generation. Mostly used when no video input is present. Negative values mean number of frames, positive values duration in second, 0 stops as soon as all streams are done", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_UPDATE}, { OFFS(fsize), "force the scene to resize to the biggest bitmap available if no size info is given in the BIFS configuration", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(mode2d), "specify whether immediate drawing should be used or not\n"\ - "- immediate: the screen is completely redrawn at each frame (always on if passthrough mode is detected).\n"\ - "- defer: object positioning is tracked from frame to frame and dirty rectangles info is collected in order to redraw the minimal amount of the screen buffer.\n"\ + "- immediate: the screen is completely redrawn at each frame (always on if passthrough mode is detected)\n"\ + "- defer: object positioning is tracked from frame to frame and dirty rectangles info is collected in order to redraw the minimal amount of the screen buffer\n"\ "- debug: only renders changed areas, reseting other areas\n"\ - "Whether the setting is applied or not depends on the graphics module and player mode.", GF_PROP_UINT, "defer", "defer|immediate|debug", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, + "Whether the setting is applied or not depends on the graphics module and player mode", GF_PROP_UINT, "defer", "defer|immediate|debug", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, { OFFS(amc), "audio multichannel support; if disabled always downmix to stereo. Useful if the multichannel output does not work properly", GF_PROP_BOOL, "true", NULL, 0}, { OFFS(asr), "force output sample rate - 0 for auto", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(ach), "force output channels - 0 for auto", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(alayout), "force output channel layout - 0 for auto", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(afmt), "force output channel format - 0 for auto", GF_PROP_PCMFMT, "s16", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(asize), "audio output packet size in samples", GF_PROP_UINT, "1024", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(abuf), "audio output buffer duration in ms - the audio renderer fills the output pid up to this value. A too low value will lower latency but can have real-time playback issues", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(abuf), "audio output buffer duration in ms - the audio renderer fills the output pid up to this value. A too low value will lower latency but can have real-time playback issues", GF_PROP_UINT, +#ifdef GPAC_CONFIG_ANDROID + "200" +#else + "100" +#endif + , NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(avol), "audio volume in percent", GF_PROP_UINT, "100", NULL, GF_FS_ARG_UPDATE}, { OFFS(apan), "audio pan in percent, 50 is no pan", GF_PROP_UINT, "50", NULL, GF_FS_ARG_UPDATE}, { OFFS(async), "audio resynchronization; if disabled, audio data is never dropped but may get out of sync", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(max_aspeed), "silence audio if playback speed is greater than sepcified value", GF_PROP_DOUBLE, "2.0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(max_vspeed), "move to i-frame only decoding if playback speed is greater than sepcified value", GF_PROP_DOUBLE, "4.0", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, - { OFFS(buf), "playout buffer in ms. Overriden by BufferLenth property of input pid", GF_PROP_UINT, "3000", NULL, GF_FS_ARG_UPDATE}, - { OFFS(rbuf), "rebuffer trigger in ms. Overriden by RebufferLenth property of input pid", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_UPDATE}, - { OFFS(mbuf), "max buffer in ms (must be greater than playout buffer). Overriden by BufferMaxOccupancy property of input pid", GF_PROP_UINT, "3000", NULL, GF_FS_ARG_UPDATE}, - { OFFS(ntpsync), "ntp resync threshold (drops frame if their NTP is more than the given threshold above local ntp), 0 disables ntp drop", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, + { OFFS(buf), "playout buffer in ms. overridden by BufferLenth property of input pid", GF_PROP_UINT, "3000", NULL, GF_FS_ARG_UPDATE}, + { OFFS(rbuf), "rebuffer trigger in ms. overridden by RebufferLenth property of input pid", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_UPDATE}, + { OFFS(mbuf), "max buffer in ms (must be greater than playout buffer). overridden by BufferMaxOccupancy property of input pid", GF_PROP_UINT, "3000", NULL, GF_FS_ARG_UPDATE}, + { OFFS(ntpsync), "ntp resync threshold in ms (drops frame if their NTP is more than the given threshold above local ntp), 0 disables ntp drop", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, { OFFS(nojs), "disable javascript", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(noback), "ignore background nodes and viewport fill (usefull when dumping to PNG)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, #ifndef GPAC_DISABLE_3D { OFFS(ogl), "specify 2D rendering mode\n"\ - "- auto: automatically decides betwwen on, off and hybrid based on content.\n"\ - "- off: disables OpenGL - 3D will not be rendered.\n"\ - "- on: uses OpenGL for all graphics - this will involve polygon tesselation and 2D graphics will not look as nice as 2D mode.\n"\ - "- hybrid: the compositor performs software drawing of 2D graphics with no textures (better quality) and uses OpenGL for all 2D objects with textures and 3D objects."\ + "- auto: automatically decides betwwen on, off and hybrid based on content\n"\ + "- off: disables OpenGL; 3D will not be rendered\n"\ + "- on: uses OpenGL for all graphics; this will involve polygon tesselation and 2D graphics will not look as nice as 2D mode\n"\ + "- hybrid: the compositor performs software drawing of 2D graphics with no textures (better quality) and uses OpenGL for all 2D objects with textures and 3D objects"\ , GF_PROP_UINT, "auto", "auto|off|hybrid|on", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, - { OFFS(pbo), "enable PixelBufferObjects to push YUV textures to GPU in OpenGL Mode. This may slightly increase the performances of the playback.", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, + { OFFS(pbo), "enable PixelBufferObjects to push YUV textures to GPU in OpenGL Mode. This may slightly increase the performances of the playback", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(nav), "override the default navigation mode of MPEG-4/VRML (Walk) and X3D (Examine)\n"\ "- none: disables navigation\n"\ "- walk: 3D world walk\n"\ @@ -793,13 +809,13 @@ { OFFS(epow2), "emulate power-of-2 textures for openGL (old hardware). Ignored if OpenGL rectangular texture extension is enabled\n"\ "- yes: video texture is not resized but emulated with padding. This usually speeds up video mapping on shapes but disables texture transformations\n"\ "- no: video is resized to a power of 2 texture when mapping to a shape", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, - { OFFS(paa), "indicate whether polygon antialiasing should be used in full antialiasing mode. If not set, only lines and points antialiasing are used.", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, + { OFFS(paa), "indicate whether polygon antialiasing should be used in full antialiasing mode. If not set, only lines and points antialiasing are used", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(bcull), "indicate whether backface culling shall be disable or not\n"\ "- on: enables backface culling\n"\ "- off: disables backface culling\n"\ "- alpha: only enables backface culling for transparent meshes"\ "", GF_PROP_UINT, "on", "off|on|alpha", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, - { OFFS(wire), "wireframe mode.\n"\ + { OFFS(wire), "wireframe mode\n"\ "- none: objects are drawn as solid\n"\ "- only: objects are drawn as wireframe only\n"\ "- solid: objects are drawn as solid and wireframe is then drawn", GF_PROP_UINT, "none", "none|only|solid", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED}, @@ -817,15 +833,15 @@ "- strip: same as point but thins point set" "", GF_PROP_UINT, "none", "none|point|strip", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(nbviews), "number of views to use in stereo mode", GF_PROP_UINT, "0", NULL, GF_FS_ARG_UPDATE}, - { OFFS(stereo), "stereo output type. If your graphic card does not support OpenGL shaders, only `top` and `side` modes will be available.\n"\ - "- side: images are displayed side by side from left to right.\n"\ - "- top: images are displayed from top (laft view) to bottom (right view).\n"\ - "- hmd: same as side except that view aspect ratio is not changed.\n"\ - "- ana: standard color anaglyph (red for left view, green and blue for right view) is used (forces views=2).\n"\ - "- cols: images are interleaved by columns, left view on even columns and left view on odd columns (forces views=2).\n"\ - "- rows: images are interleaved by columns, left view on even rows and left view on odd rows (forces views=2).\n"\ - "- spv5: images are interleaved by for SpatialView 5 views display, fullscreen mode (forces views=5).\n"\ - "- alio8: images are interleaved by for Alioscopy 8 views displays, fullscreen mode (forces views=8).\n"\ + { OFFS(stereo), "stereo output type. If your graphic card does not support OpenGL shaders, only `top` and `side` modes will be available\n"\ + "- side: images are displayed side by side from left to right\n"\ + "- top: images are displayed from top (laft view) to bottom (right view)\n"\ + "- hmd: same as side except that view aspect ratio is not changed\n"\ + "- ana: standard color anaglyph (red for left view, green and blue for right view) is used (forces views=2)\n"\ + "- cols: images are interleaved by columns, left view on even columns and left view on odd columns (forces views=2)\n"\ + "- rows: images are interleaved by columns, left view on even rows and left view on odd rows (forces views=2)\n"\ + "- spv5: images are interleaved by for SpatialView 5 views display, fullscreen mode (forces views=5)\n"\ + "- alio8: images are interleaved by for Alioscopy 8 views displays, fullscreen mode (forces views=8)\n"\ "- custom: images are interleaved according to the shader file indicated in [-mvshader](). The shader is exposed each view as uniform sampler2D gfViewX, where X is the view number starting from the left", GF_PROP_UINT, "none", "none|top|side|hmd|custom|cols|rows|ana|spv5|alio8", GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(mvshader), "file path to the custom multiview interleaving shader", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_EXPERT}, { OFFS(fpack), "default frame packing of input video\n" @@ -971,4 +987,10 @@ } return &CompositorFilterRegister; } +#else +const GF_FilterRegister *compose_filter_register(GF_FilterSession *session) +{ + return NULL; +} +#endif // GPAC_DISABLE_PLAYER
View file
gpac-1.0.0.tar.gz/src/filters/dasher.c -> gpac-1.0.1.tar.gz/src/filters/dasher.c
Changed
@@ -29,6 +29,7 @@ #include <gpac/mpd.h> #include <gpac/internal/media_dev.h> #include <gpac/base_coding.h> +#include <gpac/network.h> #define DEFAULT_PERIOD_ID "_gf_dash_def_period" @@ -50,6 +51,16 @@ DASHER_BS_SWITCH_MULTI, }; +typedef enum +{ + DASHER_UTCREF_NONE=0, + DASHER_UTCREF_NTP, + DASHER_UTCREF_HTTP_HEAD, + DASHER_UTCREF_ISO, + DASHER_UTCREF_XSDATE, + DASHER_UTCREF_INBAND, +} DasherUTCTimingType; + enum { DASHER_NTP_REM=0, @@ -87,16 +98,11 @@ u32 bs_switch, profile, cp, ntp; s32 subs_sidx; s32 buf, timescale; - Bool forcep, sfile, sseg, no_sar, mix_codecs, stl, tpl, align, sap, no_frag_def, sidx, split, hlsc, strict_cues; + Bool sfile, sseg, no_sar, mix_codecs, stl, tpl, align, sap, no_frag_def, sidx, split, hlsc, strict_cues, force_flush; u32 strict_sap; u32 pssh; Double segdur; u32 dmode; - char *avcp; - char *hvcp; - char *aacp; - char *av1p; - char *vpxp; char *template; char *segext; char *initext; @@ -116,6 +122,7 @@ char *styp; Bool sigfrag; u32 sbound; + char *utcs; //internal @@ -169,6 +176,12 @@ Bool purge_segments; Bool is_playing; + + Bool no_seg_dur; + + Bool utc_initialized; + DasherUTCTimingType utc_timing_type; + s32 utc_diff; } GF_DasherCtx; typedef enum @@ -296,6 +309,7 @@ u64 cumulated_dur; Double cumulated_subdur; Bool subdur_done; + u64 subdur_forced_use_period_dur; u64 nb_pck; u64 est_next_dts; u64 seek_to_pck; @@ -326,6 +340,12 @@ GF_Fraction64 duration; GF_List *packet_queue; u32 nb_sap_in_queue; + + //gm_ for gen manifest + Double gm_duration_total, gm_duration_min, gm_duration_max; + u32 gm_nb_segments; + + Bool no_seg_dur; } GF_DashStream; static void dasher_flush_segment(GF_DasherCtx *ctx, GF_DashStream *ds); @@ -698,8 +718,12 @@ ds->startNumber = 1; CHECK_PROP(GF_PROP_PID_START_NUMBER, ds->startNumber, GF_EOS) ds->dash_dur = ctx->segdur; + ds->no_seg_dur = ctx->no_seg_dur; p = gf_filter_pid_get_property(pid, GF_PROP_PID_DASH_DUR); - if (p) ds->dash_dur = p->value.number; + if (p) { + ds->dash_dur = p->value.number; + ds->no_seg_dur = GF_FALSE; + } //this avoids very weird cases where (u64) (dash_dur*timescale) is 0. we limit the max segment duration to 1M sec, a bit more than 11.5 days if (ds->dash_dur>1000000) ds->dash_dur=1000000; @@ -747,8 +771,9 @@ gf_odf_hevc_cfg_del(hevccfg); } } + else #endif - else if (ds->codec_id == GF_CODECID_AVC || ds->codec_id == GF_CODECID_SVC || ds->codec_id == GF_CODECID_MVC) { + if (ds->codec_id == GF_CODECID_AVC || ds->codec_id == GF_CODECID_SVC || ds->codec_id == GF_CODECID_MVC) { AVCState avc; GF_AVCConfig* avccfg = gf_odf_avc_cfg_read(dsi->value.data.ptr, dsi->value.data.size); GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(avccfg->sequenceParameterSets, 0); @@ -868,7 +893,9 @@ s32 res = gf_list_del_item(ctx->current_period->streams, ds); //force end of segment if stream is not yet done and in current period if ((res>=0) && !ds->done && !ds->seg_done) { - GF_DashStream *base_ds = ds->muxed_base ? ds->muxed_base : ds; + GF_DashStream *base_ds; + + base_ds = ds->muxed_base ? ds->muxed_base : ds; GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] PID %s config changed during active period, forcing period switch\n", gf_filter_pid_get_name(ds->ipid) )); ds->seg_done = GF_TRUE; assert(base_ds->nb_comp_done < base_ds->nb_comp); @@ -1032,8 +1059,11 @@ static GF_Err dasher_get_rfc_6381_codec_name(GF_DasherCtx *ctx, GF_DashStream *ds, char *szCodec, Bool force_inband, Bool force_sbr) { - u32 subtype=0; - const GF_PropertyValue *dcd, *dcd_enh, *dovi; + u32 subtype=0, subtype_src=0, mha_pl=0; + const GF_PropertyValue *dcd, *dcd_enh, *dovi, *codec; + + dcd = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_ISOM_SUBTYPE); + if (dcd) subtype_src = dcd->value.uint; dcd = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_DECODER_CONFIG); dcd_enh = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT); @@ -1057,6 +1087,18 @@ } } + codec = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_CODEC); + if (codec && (codec->type==GF_PROP_STRING) && codec->value.string) { + const char *codec_str = codec->value.string; + if (codec_str[0] != '.') { + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", codec_str); + return GF_OK; + } + if (!subtype_src) + subtype_src = gf_codecid_4cc_type(ds->codec_id); + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s%s", gf_4cc_to_str(subtype_src), codec_str); + return GF_OK; + } dovi = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_DOLBY_VISION); if (dovi) { @@ -1080,7 +1122,7 @@ case GF_CODECID_AAC_MPEG2_MP: case GF_CODECID_AAC_MPEG2_LCP: case GF_CODECID_AAC_MPEG2_SSRP: - if (dcd && (!ctx->forcep || !ctx->aacp) ) { + if (dcd) { u8 audio_object_type; if (dcd->value.data.size < 2) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[RFC6381-AAC] invalid DSI size %u < 2\n", dcd->value.data.size)); @@ -1108,14 +1150,8 @@ return GF_OK; } - if (ctx->aacp) - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "mp4a.%s", ctx->aacp); - else - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "mp4a.%02X", ds->codec_id); - - if (!ctx->forcep) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AAC config, using default %s\n", szCodec)); - } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "mp4a.%02X", ds->codec_id); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AAC config, using default %s\n", szCodec)); return GF_OK; break; @@ -1144,7 +1180,7 @@ } } - if (dcd && (!ctx->forcep || !ctx->avcp) ) { + if (dcd) { GF_AVCConfig *avcc = gf_odf_avc_cfg_read(dcd->value.data.ptr, dcd->value.data.size); if (avcc) { snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.%02X%02X%02X", gf_4cc_to_str(subtype), avcc->AVCProfileIndication, avcc->profile_compatibility, avcc->AVCLevelIndication); @@ -1152,13 +1188,8 @@ return GF_OK; } } - if (ctx->avcp) - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.%s", gf_4cc_to_str(subtype), ctx->avcp); - else - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); - if (!ctx->forcep) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AVC config, using default %s\n", szCodec)); - } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AVC config, using default %s\n", szCodec)); return GF_OK; #ifndef GPAC_DISABLE_HEVC case GF_CODECID_LHVC: @@ -1190,7 +1221,7 @@ subtype = force_inband ? GF_ISOM_SUBTYPE_HEV1 : GF_ISOM_SUBTYPE_HVC1; } } - if ((dcd || dcd_enh) && (!ctx->forcep || !ctx->hvcp)) { + if (dcd || dcd_enh) { u8 c; GF_HEVCConfig *hvcc = dcd ? gf_odf_hevc_cfg_read(dcd->value.data.ptr, dcd->value.data.size, GF_FALSE) : NULL; @@ -1259,13 +1290,8 @@ return GF_OK; } - if (ctx->hvcp) - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.%s", gf_4cc_to_str(subtype), ctx->hvcp); - else - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); - if (!ctx->forcep) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find HEVC config, using default %s\n", szCodec)); - } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find HEVC config, using default %s\n", szCodec)); return GF_OK; #endif @@ -1273,7 +1299,7 @@ case GF_CODECID_AV1: if (!subtype) subtype = GF_ISOM_SUBTYPE_AV01; - if (dcd && (!ctx->forcep || !ctx->av1p)) { + if (dcd) { GF_AV1Config *av1c = gf_odf_av1_cfg_read(dcd->value.data.ptr, dcd->value.data.size); if (!av1c) { @@ -1327,14 +1353,8 @@ #endif } } - - if (ctx->av1p) - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.%s", gf_4cc_to_str(subtype), ctx->av1p); - else - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); - if (!ctx->forcep) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AV1 config, using default %s\n", szCodec)); - } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find AV1 config, using default %s\n", szCodec)); return GF_OK; #endif /*GPAC_DISABLE_AV1*/ @@ -1343,7 +1363,7 @@ case GF_CODECID_VP9: if (!subtype) subtype = GF_ISOM_SUBTYPE_VP09; - if (dcd && (!ctx->forcep || !ctx->vpxp)) { + if (dcd) { GF_VPConfig *vpcc = gf_odf_vp_cfg_read(dcd->value.data.ptr, dcd->value.data.size); if (!vpcc) { @@ -1363,13 +1383,35 @@ return GF_OK; } } - if (ctx->vpxp) - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.%s", gf_4cc_to_str(subtype), ctx->vpxp); - else - snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); - if (!ctx->forcep) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find VPX config, using default %s\n", szCodec)); + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s", gf_4cc_to_str(subtype)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find VPX config, using default %s\n", szCodec)); + return GF_OK; + + case GF_CODECID_MPHA: + subtype = subtype_src ? subtype_src : GF_ISOM_SUBTYPE_MH3D_MHA1; + + if (!dcd || (dcd->value.data.size<2) ) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find MPEG-H Audio Config, defaulting to profile 0x01\n")); + mha_pl = 1; + } else { + mha_pl = dcd->value.data.ptr[1]; } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.0x%02X", gf_4cc_to_str(subtype), mha_pl); + return GF_OK; + case GF_CODECID_MHAS: + subtype = subtype_src ? subtype_src : GF_ISOM_SUBTYPE_MH3D_MHM1; + if (dcd && (dcd->value.data.size>2)) { + mha_pl = dcd->value.data.ptr[1]; + } else { + const GF_PropertyValue *pl = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_PROFILE_LEVEL); + if (pl) { + mha_pl = pl->value.uint; + } else { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[Dasher] Cannot find MPEG-H Audio Config or audio PL, defaulting to profile 0x01\n")); + mha_pl = 1; + } + } + snprintf(szCodec, RFC6381_CODEC_NAME_SIZE_MAX, "%s.0x%02X", gf_4cc_to_str(subtype), mha_pl); return GF_OK; default: @@ -1704,11 +1746,15 @@ } } else if (ds->stream_type==GF_STREAM_AUDIO) { + Bool use_cicp = GF_FALSE; GF_MPD_Descriptor *desc; char value[256]; ds->rep->samplerate = ds->sr; - if (!ds->nb_surround && !ds->nb_lfe) { + if (ds->nb_surround || ds->nb_lfe) use_cicp = GF_TRUE; + if ((ds->codec_id==GF_CODECID_MHAS) || (ds->codec_id==GF_CODECID_MPHA)) use_cicp = GF_TRUE; + + if (!use_cicp) { sprintf(value, "%d", ds->nb_ch); desc = gf_mpd_descriptor_new(NULL, "urn:mpeg:dash:23003:3:audio_channel_configuration:2011", value); } else { @@ -2070,7 +2116,7 @@ Bool has_vodcache=GF_FALSE; char sep_args = gf_filter_get_sep(filter, GF_FS_SEP_ARGS); char sep_name = gf_filter_get_sep(filter, GF_FS_SEP_NAME); - const char *dst_args; + const char *dst_args, *trailer_args=NULL; char *szDST = NULL; char szSRC[100]; @@ -2103,11 +2149,17 @@ dst_args = gf_filter_get_dst_args(filter); if (dst_args) { - char szKey[20]; + char szKey[20], *sep; sprintf(szSRC, "%c", sep_args); gf_dynstrcat(&szDST, szSRC, NULL); gf_dynstrcat(&szDST, dst_args, NULL); + sprintf(szKey, "%c%c", sep_args, sep_args); + sep = strstr(szDST, szKey); + if (sep) { + sep[0] = 0; + trailer_args = strstr(dst_args, szKey); + } //look for frag arg sprintf(szKey, "%cfrag", sep_args); if (strstr(dst_args, szKey)) has_frag = GF_TRUE; @@ -2190,6 +2242,9 @@ sprintf(szSRC, "%cmoovts%c-1", sep_args, sep_name); gf_dynstrcat(&szDST, szSRC, NULL); } + if (trailer_args) + gf_dynstrcat(&szDST, trailer_args, NULL); + ds->dst_filter = gf_filter_connect_destination(filter, szDST, &e); gf_free(szDST); szDST = NULL; @@ -2404,7 +2459,7 @@ char szInitSegmentFilename[GF_MAX_PATH]; char szIndexSegmentName[GF_MAX_PATH]; char szSetFileSuffix[200], szDASHSuffix[220]; - const char *template; + const char *template = NULL; u32 as_id = 0; Bool single_template = GF_TRUE; u32 i, j, count, nb_base, nb_streams; @@ -2425,8 +2480,10 @@ count = gf_list_count(set->representations); - assert(ctx->template); - template = ((GF_DashStream *)set->udta)->template; + if (!ctx->sigfrag) { + assert(ctx->template); + template = ((GF_DashStream *)set->udta)->template; + } for (i=0; i<count; i++) { rep = gf_list_get(set->representations, i); @@ -2531,6 +2588,9 @@ } for (i=0; i<count; i++) { + if (ctx->sigfrag) + break; + rep = gf_list_get(set->representations, i); ds = rep->playback.udta; @@ -2662,7 +2722,7 @@ continue; } if (ds->template) strcpy(szTemplate, ds->template); - else strcpy(szTemplate, ctx->template); + else strcpy(szTemplate, ctx->template ? ctx->template : ""); if (use_inband) ds->inband_params = GF_TRUE; @@ -2782,9 +2842,11 @@ gf_media_mpd_format_segment_name(init_template_mode, is_bs_switch, szInitSegmentTemplate, ds->rep_id, NULL, szDASHTemplate, init_ext, 0, 0, 0, ctx->stl); if (ctx->sigfrag) { - strcpy(szInitSegmentFilename, gf_file_basename(ds->src_url)); - strcpy(szSegmentName, gf_file_basename(ds->src_url)); - strcpy(szInitSegmentTemplate, gf_file_basename(ds->src_url)); + if (ctx->template || ds->template) { + } else { + strcpy(szInitSegmentFilename, gf_file_basename(ds->src_url)); + strcpy(szSegmentName, gf_file_basename(ds->src_url)); + } } if (ctx->store_seg_states) { @@ -2812,8 +2874,8 @@ //we use segment template if (ctx->tpl) { GF_MPD_SegmentTemplate *seg_template; - //bs switching but multiple templates - if ((!i && (set->bitstream_switching || single_template) )) { + //first rep in set and bs switching or single template, create segment template at set level + if (!i && (set->bitstream_switching || single_template) ) { init_template_done = GF_TRUE; seg_template = NULL; if (!skip_init || single_template) { @@ -2840,14 +2902,19 @@ } set->segment_template = seg_template; } - if (i || !single_template) { + //non-first rep in set and single template, only open destination + if (i && single_template) { + dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, (set->bitstream_switching || skip_init) ? GF_TRUE : GF_FALSE); + } + //first rep in set and no bs switching or mutliple templates, create segment template at rep level + else if (i || !single_template) { GF_SAFEALLOC(seg_template, GF_MPD_SegmentTemplate); if (seg_template) { if (!init_template_done) { seg_template->initialization = skip_init ? NULL : gf_strdup(szInitSegmentTemplate); dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, skip_init); } else if (i) { - dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, GF_TRUE); + dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, (set->bitstream_switching || skip_init) ? GF_TRUE : GF_FALSE); } seg_template->media = gf_strdup(szSegmentName); if (ds->idx_template) @@ -2988,6 +3055,8 @@ while (1) { Double time, dur; + Bool seg_url_found = GF_FALSE; + Bool has_seg_list = GF_FALSE; GF_DASH_SegmentContext *sctx = gf_list_get(ds->rep->state_seg_list, 0); if (!sctx) break; /*not yet flushed*/ @@ -3004,20 +3073,34 @@ GF_FEVT_INIT(evt, GF_FEVT_FILE_DELETE, ds->opid); evt.file_del.url = sctx->filepath; gf_filter_pid_send_event(ds->opid, &evt); - - if (sctx->filename) gf_free(sctx->filename); gf_free(sctx->filepath); } if (ds->rep->segment_list) { GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->rep->segment_list->segment_URLs); - gf_mpd_segment_url_free(surl); + has_seg_list = GF_TRUE; + //can be NULL if we mutualize everything at AdaptatioSet level + if (surl) { + gf_mpd_segment_url_free(surl); + seg_url_found = GF_TRUE; + } } //not an else due to inheritance if (ds->owns_set && ds->set->segment_list) { GF_MPD_SegmentURL *surl = gf_list_pop_front(ds->set->segment_list->segment_URLs); - gf_mpd_segment_url_free(surl); + has_seg_list = GF_TRUE; + //can be NULL if we don't mutualize at AdaptatioSet level + if (surl) { + gf_mpd_segment_url_free(surl); + seg_url_found = GF_TRUE; + } + } + //but we must have at least one segment URL entry + if (has_seg_list && !seg_url_found) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] purging segment %s for AS %d rep %s but segment list is empty!\n", + sctx->filename ? sctx->filename : "", ds->set->id, ds->rep->id)); } + if (ds->rep->segment_template) { if (ds->rep->segment_template->segment_timeline) { dahser_purge_segment_timeline(ds, ds->rep->segment_template->segment_timeline, sctx); @@ -3033,6 +3116,7 @@ ds->nb_segments_purged ++; ds->dur_purged += dur; assert(gf_list_find(ds->pending_segment_states, sctx)<0); + if (sctx->filename) gf_free(sctx->filename); gf_free(sctx); gf_list_rem(ds->rep->state_seg_list, 0); } @@ -3070,6 +3154,11 @@ pdur = (u32) (1000*ds->period_dur); } else { u64 ds_dur = ds->max_period_dur; + //we had to generate one extra segment to unlock looping, but we don't want to advertise it in the manifest duration + //because other sets may not be ready for this time interval + if (ds->subdur_forced_use_period_dur) + ds_dur = ds->subdur_forced_use_period_dur; + if (ds->clamped_dur && !ctx->loop) { u64 clamp_dur = (u64) (ds->clamped_dur * 1000); if (clamp_dur<ds_dur) ds_dur = clamp_dur; @@ -3184,6 +3273,11 @@ gf_filter_pck_send(pck); } +static u64 dasher_get_utc(GF_DasherCtx *ctx) +{ + return gf_net_get_utc() - ctx->utc_diff; +} + GF_Err dasher_send_manifest(GF_Filter *filter, GF_DasherCtx *ctx, Bool for_mpd_only) { GF_Err e; @@ -3200,7 +3294,30 @@ GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] patch for old regression tests hit, changing max seg dur from 1022 to 1080\nPlease notify GPAC devs to remove this, and do not use fot_test modes in dash filter\n")); } - ctx->mpd->publishTime = gf_net_get_utc(); + ctx->mpd->publishTime = dasher_get_utc(ctx); + if (ctx->utc_timing_type==DASHER_UTCREF_INBAND) { + GF_MPD_Descriptor *d = gf_list_get(ctx->mpd->utc_timings, 0); + if (d) { + time_t gtime; + struct tm *t; + u32 sec; + u32 ms; + char szTime[100]; + if (d->value) gf_free(d->value); + + gtime = ctx->mpd->publishTime / 1000; + sec = (u32)(ctx->mpd->publishTime / 1000); + ms = (u32)(ctx->mpd->publishTime - ((u64)sec) * 1000); + + t = gf_gmtime(>ime); + sec = t->tm_sec; + //see issue #859, no clue how this happened... + if (sec > 60) + sec = 60; + snprintf(szTime, 100, "%d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, sec, ms); + d->value = gf_strdup(szTime); + } + } dasher_update_mpd(ctx); ctx->mpd->write_context = GF_FALSE; ctx->mpd->was_dynamic = GF_FALSE; @@ -3259,6 +3376,11 @@ return e; } + if (ctx->profile == GF_DASH_PROFILE_HBBTV_1_5_ISOBMF_LIVE) { + if (gf_ftell(tmp) > 100 * 1024) + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] manifest MPD is too big for HbbTV 1.5. Limit is 100kB, current size is "LLU"kB\n", gf_ftell(tmp) / 1024)); + } + dasher_transfer_file(tmp, opid, NULL); gf_fclose(tmp); } @@ -3404,6 +3526,7 @@ ds->rep->dasher_ctx->dur_purged = ds->dur_purged; ds->rep->dasher_ctx->moof_sn = ds->moof_sn; ds->rep->dasher_ctx->moof_sn_inc = ds->moof_sn_inc; + ds->rep->dasher_ctx->subdur_forced = ds->subdur_forced_use_period_dur ? GF_TRUE : GF_FALSE; } if (ctx->subdur) { ds->rep->dasher_ctx->cumulated_subdur = ds->cumulated_subdur + ctx->subdur; @@ -3729,7 +3852,8 @@ ds->cumulated_dur = (u64) (rep->dasher_ctx->cumulated_dur * ds->timescale); ds->cumulated_subdur = rep->dasher_ctx->cumulated_subdur; ds->rep_init = GF_TRUE; - ds->subdur_done = GF_FALSE; + ds->subdur_done = rep->dasher_ctx->subdur_forced ? GF_TRUE : GF_FALSE; + ds->subdur_forced_use_period_dur = 0; ds->nb_pck = 0; if (!ctx->subdur) { ds->nb_pck = ds->seek_to_pck; @@ -3840,6 +3964,167 @@ dasher_send_manifest(filter, ctx, GF_FALSE); } +typedef struct +{ + Double period_start; + const char *period_id; +} PeriodInfo; + +static u32 dasher_period_count(GF_List *streams_in /*GF_DashStream*/) +{ + u32 nb_periods, i, j; + PeriodInfo *info; + GF_List *pinfos = gf_list_new(); + + for (i=0; i < gf_list_count(streams_in); i++) { + Bool same_period = GF_FALSE; + GF_DashStream *ds = gf_list_get(streams_in, i); + //check if we already have a period info with same ID or same start time + nb_periods = gf_list_count(pinfos); + for (j=0; j < nb_periods; j++) { + info = gf_list_get(pinfos, j); + if (info->period_start == ds->period_start) { + same_period = GF_TRUE; + break; + } + if (info->period_id && ds->period_id && !strcmp(info->period_id, ds->period_id)) { + same_period = GF_TRUE; + break; + } + } + //nope, register it + if (!same_period) { + GF_SAFEALLOC(info, PeriodInfo); + if (info) { + info->period_start = ds->period_start; + info->period_id = ds->period_id; + gf_list_add(pinfos, info); + } + } + } + nb_periods = gf_list_count(pinfos); + while (1) { + info = gf_list_pop_back(pinfos); + if (!info) break; + gf_free(info); + } + gf_list_del(pinfos); + + return nb_periods; +} + +static void dasher_init_utc(GF_Filter *filter, GF_DasherCtx *ctx) +{ + const char *cache_name; + u32 size; + u8 *data; + u64 remote_utc; + GF_Err e; + GF_DownloadSession *sess; + GF_DownloadManager *dm; + char *url; + DasherUTCTimingType def_type = DASHER_UTCREF_NONE; + + ctx->utc_initialized = GF_TRUE; + ctx->utc_timing_type = DASHER_UTCREF_NONE; + if (!ctx->utcs) { + return; + } + url = ctx->utcs; + if (!strncmp(url, "xsd@", 4)) { + def_type = DASHER_UTCREF_XSDATE; + url += 4; + } + + dm = gf_filter_get_download_manager(filter); + if (!dm) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to get download manager, cannot sync to remote UTC clock\n")); + return; + } + if (!strcmp(ctx->utcs, "inband")) { + ctx->utc_timing_type = DASHER_UTCREF_INBAND; + return; + } + + sess = gf_dm_sess_new(dm, url, GF_NETIO_SESSION_MEMORY_CACHE|GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to create session for remote UTC source %s: %s\n", url, gf_error_to_string(e) )); + return; + } + while (1) { + GF_NetIOStatus status; + e = gf_dm_sess_process(sess); + if (e) break; + gf_dm_sess_get_stats(sess, NULL, NULL, NULL, NULL, NULL, &status); + if (status>=GF_NETIO_DATA_TRANSFERED) break; + } + if (e<0) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to fetch remote UTC source %s: %s\n", url, gf_error_to_string(e) )); + gf_dm_sess_del(sess); + return; + } + cache_name = gf_dm_sess_get_cache_name(sess); + gf_blob_get_data(cache_name, &data, &size); + if (data) { + //xsDate or isoDate - we always signal using iso + if (strchr(data, 'T')) { + remote_utc = gf_net_parse_date(data); + if (remote_utc) + ctx->utc_timing_type = def_type ? def_type : DASHER_UTCREF_ISO; + } + //ntp + else if (sscanf(data, LLU, &remote_utc) == 1) { + remote_utc = gf_net_ntp_to_utc(remote_utc); + if (remote_utc) + ctx->utc_timing_type = DASHER_UTCREF_NTP; + } + } + //not match, try http date + if (!ctx->utc_timing_type) { + const char *hdr = gf_dm_sess_get_header(sess, "Date"); + if (hdr) { + //http-head + remote_utc = gf_net_parse_date(hdr); + if (remote_utc) + ctx->utc_timing_type = DASHER_UTCREF_HTTP_HEAD; + } + } + + if (!ctx->utc_timing_type) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to parse response %s from remote UTC source %s\n", data, url )); + } else { + ctx->utc_diff = (s32) ( (s64) gf_net_get_utc() - (s64) remote_utc ); + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] Synchronized clock to remote %s - UTC diff (local - remote) %d ms\n", url, ctx->utc_diff)); + + if (!gf_list_count(ctx->mpd->utc_timings) ) { + GF_MPD_Descriptor *utc_t; + GF_SAFEALLOC(utc_t, GF_MPD_Descriptor); + utc_t->value = gf_strdup(url); + switch (ctx->utc_timing_type) { + case DASHER_UTCREF_HTTP_HEAD: + utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-head:2014"); + break; + case DASHER_UTCREF_XSDATE: + utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http- xsdate:2014"); + break; + case DASHER_UTCREF_ISO: + utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-iso:2014"); + break; + case DASHER_UTCREF_NTP: + utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-ntp:2014"); + break; + case DASHER_UTCREF_INBAND: + utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:direct:2014"); + break; + default: + break; + } + gf_list_add(ctx->mpd->utc_timings, utc_t); + } + } + gf_dm_sess_del(sess); +} + static GF_Err dasher_switch_period(GF_Filter *filter, GF_DasherCtx *ctx) { u32 i, count, j, nb_sets, nb_done, srd_rep_idx; @@ -3913,23 +4198,7 @@ period_idx = 0; if (ctx->profile == GF_DASH_PROFILE_HBBTV_1_5_ISOBMF_LIVE) { - //count periods - GF_List *streams = gf_list_clone(ctx->current_period->streams); - for (i=0; i< gf_list_count(streams); i++) { - GF_DashStream *ds = gf_list_get(streams, i); - for (j=i+1; j<gf_list_count(streams); j++) { - GF_DashStream *a_ds = gf_list_get(streams, i); - Bool same_period = GF_FALSE; - if (a_ds->period_start == ds->period_start) same_period = GF_TRUE; - if (a_ds->period_id && ds->period_id && !strcmp(a_ds->period_id, ds->period_id) ) same_period = GF_TRUE; - if (same_period) { - nb_periods++; - gf_list_rem(streams, j); - j--; - } - } - } - gf_list_del(streams); + nb_periods = dasher_period_count(ctx->current_period->streams); } if (ctx->first_context_load) { @@ -4193,8 +4462,8 @@ } for (i=0; i<count; i++) { GF_DashStream *ds = gf_list_get(ctx->current_period->streams, i); - if (ds->clamped_dur > max_adur) { - GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Input %s: max audio duration (%lf) in the period is less than duration (%lf), clamping will happen\n", ds->src_url , max_adur, ds->clamped_dur)); + if (ds->duration.num > max_adur * ds->duration.den) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Input %s: max audio duration (%lf) in the period is less than duration (%lf), clamping will happen\n", ds->src_url , max_adur, ((Double)ds->duration.num)/ds->duration.den )); } ds->clamped_dur = max_adur; } @@ -4295,7 +4564,12 @@ for (i=0; i<nb_sets; i++) { GF_DashStream *ds; GF_MPD_Representation *rep; - GF_MPD_AdaptationSet *set = gf_list_get(ctx->current_period->period->adaptation_sets, i); + GF_MPD_AdaptationSet *set; + + if (ctx->sigfrag) + break; + + set = gf_list_get(ctx->current_period->period->adaptation_sets, i); assert(set); rep = gf_list_get(set->representations, 0); assert(rep); @@ -4358,8 +4632,12 @@ if (!ctx->mpd->availabilityStartTime && (ctx->dmode!=GF_MPD_TYPE_STATIC) ) { u64 dash_start_date = ctx->ast ? gf_net_parse_date(ctx->ast) : 0; + if (!ctx->utc_initialized) { + dasher_init_utc(filter, ctx); + } + ctx->mpd->gpac_init_ntp_ms = gf_net_get_ntp_ms(); - ctx->mpd->availabilityStartTime = gf_net_get_utc(); + ctx->mpd->availabilityStartTime = dasher_get_utc(ctx); if (dash_start_date && (dash_start_date < ctx->mpd->availabilityStartTime)) { u64 start_date_sec_ntp, secs; @@ -4451,7 +4729,8 @@ if (ds->rep && ds->rep->state_seg_list) { GF_DASH_SegmentContext *sctx = gf_list_last(ds->rep->state_seg_list); - sctx->dur = ds->first_cts_in_next_seg - ds->first_cts_in_seg; + if (sctx) + sctx->dur = ds->first_cts_in_next_seg - ds->first_cts_in_seg; } //we only use segment timeline with templates @@ -4646,6 +4925,32 @@ seg_duration = (Double) base_ds->first_cts_in_next_seg - ds->first_cts_in_seg; seg_duration /= base_ds->timescale; + if (ctx->sigfrag) { + if (ds->no_seg_dur) { + ds->gm_duration_total += seg_duration; + ds->gm_nb_segments++; + if (!ds->gm_duration_min || (ds->gm_duration_min>seg_duration) ) + ds->gm_duration_min = seg_duration; + if (ds->gm_duration_max<seg_duration) + ds->gm_duration_max = seg_duration; + ds->dash_dur = ds->gm_duration_total; + ds->dash_dur /= ds->gm_nb_segments; + ds->rep->dash_dur = ds->dash_dur; + } + + if (ds->rep->segment_list && (ds->rep->segment_list->duration != ds->dash_dur) ) { + ds->rep->segment_list->duration = (u64) (ds->dash_dur * ds->rep->segment_list->timescale); + } + if (ds->set && ds->set->segment_list && ( ds->set->segment_list->duration != ds->dash_dur) ) { + ds->set->segment_list->duration = (u64) (ds->dash_dur * ds->set->segment_list->timescale); + } + if (ds->rep->segment_template && (ds->rep->segment_template->duration != ds->dash_dur) ) { + ds->rep->segment_template->duration = (u64) (ds->dash_dur * ds->rep->segment_template->timescale); + } + if (ds->set && ds->set->segment_template && (ds->set->segment_template->duration != ds->dash_dur) ) { + ds->set->segment_template->duration = (u64) (ds->dash_dur * ds->set->segment_template->timescale); + } + } if (!base_ds->done && !ctx->stl && ctx->tpl && !ctx->cues) { if (seg_duration< ds->dash_dur/2) { @@ -4676,8 +4981,11 @@ } } set_ds->nb_rep_done++; - if (set_ds->nb_rep_done < set_ds->nb_rep) return; - + if (set_ds->nb_rep_done < set_ds->nb_rep) { + if (ctx->subdur && (ds->cumulated_dur >= 0.8 * (ds->cumulated_subdur + ctx->subdur) * ds->timescale)) + ds->subdur_done = GF_TRUE; + return; + } set_ds->set_seg_duration = 0; set_ds->nb_rep_done = 0; } @@ -4756,6 +5064,31 @@ base_ds->seg_done = GF_FALSE; base_ds->nb_comp_done = 0; +#ifndef GPAC_DISABLE_LOG + if (ctx->dmode>=GF_DASH_DYNAMIC) { + u32 asid; + s64 ast_diff; + u64 seg_ast = ctx->mpd->availabilityStartTime; + seg_ast += ctx->current_period->period->start; + seg_ast += (base_ds->adjusted_next_seg_start*1000) / base_ds->timescale; + + //if theoretical AST of the segment is less than the current UTC, we are producing the segment too late. + ast_diff = (s64) dasher_get_utc(ctx); + ast_diff -= seg_ast; + + asid = base_ds->set->id; + if (!asid) + asid = gf_list_find(ctx->current_period->period->adaptation_sets, base_ds->set) + 1; + + if (ast_diff>10) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] AS%d Rep %s segment %d done TOO LATE by %d ms\n", asid, base_ds->rep->id, base_ds->seg_number, (s32) ast_diff)); + } else { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] AS%d Rep %s segment %d done %d ms %s UTC due time\n", asid, base_ds->rep->id, base_ds->seg_number, ABS(ast_diff), (ast_diff<0) ? "before" : "after")); + } + } +#endif + + assert(base_ds->segment_started); base_ds->segment_started = GF_FALSE; @@ -4802,6 +5135,23 @@ } } +static char *dasher_strip_base(GF_DasherCtx *ctx, char *url) +{ + char *manifest_path = ctx->out_path; + char *file_path = url; + char *res = url; + + if (!strncmp(manifest_path, "./", 2)) manifest_path+=2; + if (!strncmp(file_path, "./", 2)) file_path+=2; + + const char *base_manifest = gf_file_basename(manifest_path); + u32 diff = (u32) (base_manifest - manifest_path); + if (!strncmp(file_path, manifest_path, diff)) { + res = file_path + diff; + } + return res; +} + static void dasher_mark_segment_start(GF_DasherCtx *ctx, GF_DashStream *ds, GF_FilterPacket *pck, GF_FilterPacket *in_pck) { GF_DASH_SegmentContext *seg_state=NULL; @@ -4833,11 +5183,32 @@ ds->rep->state_seg_list = gf_list_new(); } if (!ds->rep->dash_dur) { + const GF_PropertyValue *p; ds->rep->timescale = ds->timescale; ds->rep->streamtype = ds->stream_type; ds->rep->timescale_mpd = ds->mpd_timescale; + p = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_HLS_GROUPID); + if (p) + ds->rep->groupID = p->value.string; + ds->rep->dash_dur = ds->dash_dur; - ds->rep->hls_single_file_name = ds->init_seg; + if (ctx->sigfrag) { + const GF_PropertyValue *pid_url = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_URL); + if (pid_url && pid_url->value.string) { + ds->rep->hls_single_file_name = dasher_strip_base(ctx, pid_url->value.string); + } + } + + if (!ds->rep->hls_single_file_name && !ctx->m2ts) { + switch (ctx->muxtype) { + case DASHER_MUX_TS: + case DASHER_MUX_OGG: + case DASHER_MUX_RAW: + break; + default: + ds->rep->hls_single_file_name = ds->init_seg; + } + } ds->rep->nb_chan = ds->nb_ch; ds->rep->m3u8_name = ds->hls_vp_name; if (ds->fps.den) { @@ -4851,10 +5222,15 @@ seg_state->seg_num = ds->seg_number; gf_list_add(ds->rep->state_seg_list, seg_state); if (ctx->sigfrag) { - const GF_PropertyValue *p = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_FRAG_RANGE); - if (p) { - seg_state->file_offset = p->value.lfrac.num; - seg_state->file_size = (u32) (p->value.lfrac.den - seg_state->file_offset); + const GF_PropertyValue *frag_range = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_FRAG_RANGE); + const GF_PropertyValue *frag_url = gf_filter_pck_get_property(in_pck, GF_PROP_PID_URL); + if (frag_url && frag_url->value.string) { + char *f_url = dasher_strip_base(ctx, frag_url->value.string); + seg_state->filename = gf_strdup(f_url); + } + else if (frag_range) { + seg_state->file_offset = frag_range->value.lfrac.num; + seg_state->file_size = (u32) (frag_range->value.lfrac.den - seg_state->file_offset); if (ds->rep->segment_base && !ds->rep->segment_base->initialization_segment) { GF_MPD_URL *url; @@ -4868,6 +5244,11 @@ } ds->rep->segment_base->initialization_segment = url; } + } else { + gf_list_del_item(ds->rep->state_seg_list, seg_state); + gf_free(seg_state); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Manifest generation only but not fragment information in packet, source demux not properly configured\n")); + ctx->in_error = GF_TRUE; } } else { gf_list_add(ds->pending_segment_states, seg_state); @@ -4901,6 +5282,18 @@ if (ds->rep->segment_base->index_range) { ds->rep->segment_base->index_range->start_range = p->value.lfrac.num; ds->rep->segment_base->index_range->end_range = p->value.lfrac.den; + ds->rep->segment_base->index_range_exact = GF_TRUE; + } + + if (!ds->rep->segment_base->initialization_segment) { + GF_SAFEALLOC(ds->rep->segment_base->initialization_segment, GF_MPD_URL); + } + if (ds->rep->segment_base->initialization_segment && !ds->rep->segment_base->initialization_segment->byte_range) { + GF_SAFEALLOC(ds->rep->segment_base->initialization_segment->byte_range, GF_MPD_ByteRange); + if (ds->rep->segment_base->initialization_segment->byte_range) { + ds->rep->segment_base->initialization_segment->byte_range->start_range = 0; + ds->rep->segment_base->initialization_segment->byte_range->end_range = p->value.lfrac.num-1; + } } } else { ctx->in_error = GF_TRUE; @@ -4922,18 +5315,40 @@ seg_url->index = gf_strdup(szIndexName); if (ctx->sigfrag) { - const GF_PropertyValue *p = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_FRAG_RANGE); - if (p) { + const GF_PropertyValue *frag_range = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_FRAG_RANGE); + const GF_PropertyValue *frag_url = gf_filter_pck_get_property(in_pck, GF_PROP_PID_URL); + if (frag_url && frag_url->value.string) { + seg_url->media = gf_strdup(dasher_strip_base(ctx, frag_url->value.string)); + if (ds->rep->segment_list && ds->rep->segment_list->initialization_segment && !ds->rep->segment_list->initialization_segment->sourceURL) { + + frag_url = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_URL); + if (frag_url && frag_url->value.string) { + u32 j, nb_base; + ds->rep->segment_list->initialization_segment->sourceURL = gf_strdup(dasher_strip_base(ctx, frag_url->value.string) ); + + nb_base = gf_list_count(ds->rep->base_URLs); + for (j=0; j<nb_base; j++) { + GF_MPD_BaseURL *burl = gf_list_get(ds->rep->base_URLs, j); + if (! strcmp(burl->URL, frag_url->value.string)) { + gf_list_rem(ds->rep->base_URLs, j); + gf_mpd_base_url_free(burl); + break; + } + } + } + } + } + else if (frag_range) { GF_SAFEALLOC(seg_url->media_range, GF_MPD_ByteRange); if (seg_url->media_range) { - seg_url->media_range->start_range = p->value.lfrac.num; - seg_url->media_range->end_range = p->value.lfrac.den; + seg_url->media_range->start_range = frag_range->value.lfrac.num; + seg_url->media_range->end_range = frag_range->value.lfrac.den - 1; } if (ds->rep->segment_list && ds->rep->segment_list->initialization_segment && !ds->rep->segment_list->initialization_segment->byte_range) { GF_SAFEALLOC(ds->rep->segment_list->initialization_segment->byte_range, GF_MPD_ByteRange); if (ds->rep->segment_list->initialization_segment->byte_range) { ds->rep->segment_list->initialization_segment->byte_range->start_range = 0; - ds->rep->segment_list->initialization_segment->byte_range->end_range = p->value.lfrac.num-1; + ds->rep->segment_list->initialization_segment->byte_range->end_range = frag_range->value.lfrac.num-1; } } } @@ -5036,8 +5451,13 @@ for (i=0; i<count; i++) { GF_DashStream *a_ds = gf_list_get(ctx->current_period->streams, i); - if (a_ds->subdur_done) - continue; + //one pid is waiting for loop while another has done its subdur and won't process any new segment until the next subdur call, which + //will never happen since the first PID waits for loop. We must force early generation in this case + if (a_ds->subdur_done) { + a_ds->subdur_done = GF_FALSE; + //remember the max period dur before this forced segment generation + a_ds->subdur_forced_use_period_dur = a_ds->max_period_dur; + } //wait for each input to query loop if (!a_ds->loop_state) { @@ -5058,6 +5478,9 @@ for (i=0; i<count; i++) { GF_DashStream *a_ds = gf_list_get(ctx->current_period->streams, i); + if (a_ds->subdur_done) + continue; + ts_offset = max_ts_offset; ts_offset *= a_ds->timescale; ts_offset /= max_ts_scale; @@ -5227,7 +5650,7 @@ static GF_Err dasher_process(GF_Filter *filter) { - u32 i, count, nb_init, has_init; + u32 i, count, nb_init, has_init, nb_reg_done; GF_DasherCtx *ctx = gf_filter_get_udta(filter); GF_Err e; Bool seg_done = GF_FALSE; @@ -5235,6 +5658,18 @@ if (ctx->in_error) return GF_SERVICE_ERROR; + //session regulation is on and we have a an MPD (setup done) and a next time (first seg processed) + //check if we have reached the next time + if (ctx->sreg && !ctx->state && ctx->mpd && ctx->mpd->gpac_next_ntp_ms) { + s64 diff = (s64) ctx->mpd->gpac_next_ntp_ms; + diff -= (s64) gf_net_get_ntp_ms(); + if (diff>100) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[Dasher] Next generation scheduled in %d ms, nothing to do\n", diff)); + gf_filter_ask_rt_reschedule(filter, (u32) (diff*1000)); + return GF_OK; + } + } + if (ctx->streams_not_ready) { if (! dasher_check_streams_ready(ctx)) return GF_OK; } @@ -5245,7 +5680,7 @@ return GF_EOS; if (ctx->setup_failure) return ctx->setup_failure; - nb_init = has_init = 0; + nb_init = has_init = nb_reg_done = 0; count = gf_list_count(ctx->current_period->streams); for (i=0; i<count; i++) { @@ -5461,7 +5896,13 @@ cts -= ds->first_cts; dts -= ds->first_dts; + if (ctx->sreg && ctx->mpd->gpac_mpd_time && (dts * 1000 > ctx->mpd->gpac_mpd_time * ds->timescale)) { + nb_reg_done++; + break; + } + dur = o_dur = gf_filter_pck_get_duration(pck); + split_dur = 0; split_dur_next = 0; @@ -5500,6 +5941,9 @@ if (ds->seek_to_pck) { ds->seek_to_pck = 0; } + //force flush mode, segment is done upon eos + else if (ctx->force_flush) { + } //source-driven fragmentation check for segment start else if (ctx->sigfrag) { const GF_PropertyValue *p = gf_filter_pck_get_property(pck, GF_PROP_PCK_FRAG_START); @@ -5651,10 +6095,16 @@ if (ctx->sbound==DASHER_BOUNDS_CLOSEST) { s64 diff = cts * base_ds->timescale / ds->timescale; diff -= base_ds->adjusted_next_seg_start; - //this one may be negative + //this one may be negative, but we always want diff_next positive (next SAP in next segment) if (diff<0) diff = -diff; - if (diff<diff_next) { + //old arch was only using closest for tracks with sync points + if (gf_sys_old_arch_compat() && !base_ds->has_sync_points) { + if (diff_next > 0) { + force_seg_flush = GF_TRUE; + } + } + else if (diff<diff_next) { force_seg_flush = GF_TRUE; } } @@ -5676,7 +6126,7 @@ } //we exceed segment duration - if segment was started, check if we need to stop segment //if segment was not started we insert the packet anyway - else if (ds->segment_started && ((cts + check_dur) * base_ds->timescale >= base_ds->adjusted_next_seg_start * ds->timescale ) ) { + else if (!ctx->sbound && ds->segment_started && ((cts + check_dur) * base_ds->timescale >= base_ds->adjusted_next_seg_start * ds->timescale ) ) { //no sap, segment is over if (! ctx->sap) { seg_over = GF_TRUE; @@ -5796,6 +6246,19 @@ gf_filter_pck_set_dts(dst, dts + ds->first_dts); } + if (gf_sys_old_arch_compat() && ds->clamped_dur && ctx->loop && (cts + 2*o_dur >= ds->ts_offset + base_ds->clamped_dur * ds->timescale) + ) { + u32 _dur = dur; + /* simple round with (int)+.5 to avoid trucating .99999 to 0 */ + dur = (u32)( ds->clamped_dur * ds->timescale - (dts - ds->ts_offset) + 0.5); + //it may happen that the sample duration is 0 if the clamp duration is right after the sample DTS and timescale is not big enough to express it - force to 1 + if (dur==0) + dur=1; + + gf_filter_pck_set_duration(dst, dur); + ds->est_next_dts += (s32) dur - (s32) _dur;; + } + if (!ds->segment_started) { ds->first_cts_in_seg = cts; dasher_mark_segment_start(ctx, ds, dst, pck); @@ -5889,6 +6352,10 @@ } } + if (nb_reg_done && (nb_reg_done == count)) { + ctx->mpd->gpac_mpd_time = 0; + } + dasher_format_report(filter, ctx); if (seg_done) { @@ -5906,7 +6373,7 @@ } //we have a minimum ipdate period else if (ctx->mpd->minimum_update_period) { - u64 diff = gf_net_get_utc() - ctx->mpd->publishTime; + u64 diff = dasher_get_utc(ctx) - ctx->mpd->publishTime; if (diff >= ctx->mpd->minimum_update_period) update_manifest = GF_TRUE; } @@ -6075,7 +6542,8 @@ GF_DashStream *ds = gf_list_get(ctx->pids, i); if (ds->opid != evt->base.on_pid) continue; - if (ds->muxed_base) continue; + if (ds->muxed_base) + ds = ds->muxed_base; if (ctx->store_seg_states && !evt->seg_size.is_init) { GF_DASH_SegmentContext *sctx = gf_list_pop_front(ds->pending_segment_states); @@ -6226,7 +6694,6 @@ case GF_DASH_PROFILE_HBBTV_1_5_ISOBMF_LIVE: ctx->check_main_role = GF_TRUE; ctx->bs_switch = DASHER_BS_SWITCH_MULTI; - GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] HBBTV1.5 profile not yet ported to filter architecture.\n")); //FALLTHROUGH case GF_DASH_PROFILE_AVC264_LIVE: ctx->sseg = ctx->sfile = GF_FALSE; @@ -6291,8 +6758,11 @@ //check we have a segment template if (!ctx->template) { - ctx->template = gf_strdup( ctx->sfile ? "$File$$FS$_dash" : (ctx->stl ? "$File$_dash$FS$$Time$" : "$File$_dash$FS$$Number$") ); - GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] No template assigned, using %s\n", ctx->template)); + if (!ctx->sigfrag) { + ctx->template = gf_strdup( ctx->sfile ? "$File$$FS$_dash" : (ctx->stl ? "$File$_dash$FS$$Time$" : "$File$_dash$FS$$Number$") ); + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] No template assigned, using %s\n", ctx->template)); + } + if (ctx->profile == GF_DASH_PROFILE_FULL) { ctx->sfile = GF_TRUE; } @@ -6326,6 +6796,11 @@ if (!ctx->initext && (ctx->muxtype==DASHER_MUX_AUTO)) ctx->muxtype = DASHER_MUX_ISOM; + if (ctx->segdur<=0) { + ctx->segdur = 1.0; + ctx->no_seg_dur = GF_TRUE; + } + e = dasher_setup_profile(ctx); if (e) return e; @@ -6344,9 +6819,22 @@ } //we build manifest from input frag/seg, always use single frag if (ctx->sigfrag) { - if (!ctx->sseg) - ctx->sfile = GF_TRUE; - ctx->tpl = GF_FALSE; + if (ctx->tpl) { + if (!ctx->template) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Warning, manifest generation only mode requested for live-based profile but no template provided, switching to main profile.\n")); + ctx->profile = GF_DASH_PROFILE_MAIN; + ctx->tpl = GF_FALSE; + dasher_setup_profile(ctx); + //we force single file in this mode, but we will replace byte ranges by source URL + ctx->sfile = GF_TRUE; + } else { + ctx->sseg = GF_FALSE; + ctx->sfile = GF_FALSE; + } + } else { + if (!ctx->sseg) + ctx->sfile = GF_TRUE; + } } if (!ctx->sap || ctx->sigfrag || ctx->cues) @@ -6443,7 +6931,7 @@ #define OFFS(_n) #_n, offsetof(GF_DasherCtx, _n) static const GF_FilterArgs DasherArgs[] = { - { OFFS(segdur), "target segment duration in seconds", GF_PROP_DOUBLE, "1.0", NULL, 0}, + { OFFS(segdur), "target segment duration in seconds. A value less than or equal to 0 means to 1.0 second", GF_PROP_DOUBLE, "0.0", NULL, 0}, { OFFS(tpl), "use template mode (multiple segment, template URLs)", GF_PROP_BOOL, "true", NULL, 0}, { OFFS(stl), "use segment timeline (ignored in on_demand mode)", GF_PROP_BOOL, "false", NULL, 0}, { OFFS(dmode), "dash content mode\n" @@ -6459,10 +6947,9 @@ { OFFS(ntp), "insert/override NTP clock at the begining of each segment\n" "- rem: removes NTP from all input packets\n" "- yes: inserts NTP at each segment start\n" - "- keep: leaves input packet NTP untouched.", GF_PROP_UINT, "rem", "rem|yes|keep", GF_FS_ARG_HINT_ADVANCED}, + "- keep: leaves input packet NTP untouched", GF_PROP_UINT, "rem", "rem|yes|keep", GF_FS_ARG_HINT_ADVANCED}, { OFFS(no_sar), "do not check for identical sample aspect ratio for adaptation sets", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(m2ts), "generate MPEG-2 TS output", GF_PROP_BOOL, "false", NULL, 0}, - { OFFS(forcep), "force profile string for avc/hevc/aac", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(bs_switch), "bitstream switching mode (single init segment)\n" "- def: resolves to off for onDemand and inband for live\n" "- off: disables BS switching\n" @@ -6470,11 +6957,6 @@ "- inband: moves decoder config inband if possible\n" "- force: enables it even if only one representation\n" "- multi: uses multiple stsd entries in ISOBMFF", GF_PROP_UINT, "def", "def|off|on|inband|force|multi", GF_FS_ARG_HINT_ADVANCED}, - { OFFS(avcp), "profile to use for AVC|H264 if no profile could be found. If forcep is set, enforces this profile", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(hvcp), "profile to use for HEVC if no profile could be found. If forcep is set, enforces this profile", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(aacp), "profile to use for AAC if no profile could be found. If forcep is set, enforces this profile", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(av1p), "profile to use for AV1 if no profile could be found. If forcep is set, enforces this profile", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(vpxp), "profile to use for VP8/9 if no profile could be found. If forcep is set, enforces this profile", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(template), "template string to use to generate segment name - see filter help", GF_PROP_STRING, NULL, NULL, 0}, { OFFS(segext), "file extension to use for segments", GF_PROP_STRING, NULL, NULL, 0}, { OFFS(initext), "file extension to use for the init segment", GF_PROP_STRING, NULL, NULL, 0}, @@ -6486,7 +6968,7 @@ "- raw: uses raw media format (disables muxed representations)\n" "- auto: guess format based on extension, default to mp4 if no extension", GF_PROP_UINT, "auto", "mp4|ts|mkv|webm|ogg|raw|auto", 0}, { OFFS(asto), "availabilityStartTimeOffset to use in seconds. A negative value simply increases the AST, a positive value sets the ASToffset to representations", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(profile), "target DASH profile. This will set default option values to ensure conformance to the desired profile. For MPEG-2 TS, only main and live are used, others default to main.\n" + { OFFS(profile), "target DASH profile. This will set default option values to ensure conformance to the desired profile. For MPEG-2 TS, only main and live are used, others default to main\n" "- auto: turns profile to live for dynamic and full for non-dynamic\n" "- live: DASH live profile, using segment template\n" "- onDemand: MPEG-DASH live profile\n" @@ -6522,7 +7004,7 @@ { OFFS(base), "set base URLs of MPD", GF_PROP_STRING_LIST, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(refresh), "refresh rate for dynamic manifests, in seconds. A negative value sets the MPD duration. If 0, uses dash duration", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tsb), "time-shift buffer depth in seconds. A negative value means infinity", GF_PROP_DOUBLE, "30", NULL, 0}, - { OFFS(subdur), "maximum duration of the input file to be segmented. This does not change the segment duration, segmentation stops once segments produced exceeded the duration.", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(subdur), "maximum duration of the input file to be segmented. This does not change the segment duration, segmentation stops once segments produced exceeded the duration", GF_PROP_DOUBLE, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(ast), "set start date (as xs:date, eg YYYY-MM-DDTHH:MM:SSZ) for live mode. Default is now. !! Do not use with multiple periods, nor when DASH duration is not a multiple of GOP size !!", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(state), "path to file used to store/reload state info when simulating live. This is stored as a valid MPD with GPAC XML extensions", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(loop), "loop sources when dashing with subdur and state. If not set, a new period is created once the sources are over", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -6547,8 +7029,12 @@ "- closest: segment split at closest SAP to theoretical bound\n" "- in: `TSS` is always in segment (`TSS` >= segment_start)", GF_PROP_UINT, "out", "out|closest|in", GF_FS_ARG_HINT_EXPERT}, { OFFS(reschedule), "reschedule sources with no period ID assigned once done (dynamic mode only)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(sreg), "regulate the session when using subdur to only generate segments from the past up to live edge", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(sreg), "regulate the session\n" + "- when using subdur and context, only generate segments from the past up to live edge\n" + "- otherwise in dynamic mode without context, do not generate segments ahead of time", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(scope_deps), "scope PID dependencies to be within source. If disabled, PID dependencies will be checked across all input PIDs regardless of their sources", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(utcs), "URL to use as time server / UTCTiming source. Special value `inband` enables inband UTC (same as publishTime), special prefix `xsd@` uses xsDateTime schemeURI rather than ISO", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(force_flush), "force generating a single segment for each input. This can be usefull in batch mode when average source duration is known and used as segment duration but actual duration may sometimes be greater", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, {0} }; @@ -6561,13 +7047,13 @@ "The segmenter currently supports:\n" "- MPD and m3u8 generation (potentially in parallel)\n" "- ISOBMFF, MPEG-2 TS, MKV and raw bitstream segment formats\n" - "- override of profiles and levels in manifest for common codecs (aac, hevc, vp9, av1, aac)\n" + "- override of profiles and levels in manifest for codecs\n" "- most MPEG-DASH profiles\n" "- static and dynamic (live) manifest offering\n" "- context store and reload for batch processing of live/dynamic sessions\n" "\n" - "Warning: the filter does not perform any real-time regulation, even in dynamic offering mode.\n" - "If your inputs are not real-time, insert a [reframer](reframer) before to perform real-time regulation.\n" + "The filter does perform per-segment real-time regulation using [-sreg]().\n" + "If you need per-frame real-time regulation on non-real-time inputs, insert a [reframer](reframer) before to perform real-time regulation.\n" "EX src=file.mp4 reframer:rt=on @ -o live.mpd:dmode=dynamic\n" "## Template strings\n" "The segmenter uses templates to derive output file names, regardless of the DASH mode (even when templates are not used). " @@ -6586,13 +7072,14 @@ "\n" "Additional replacement strings (not DASH, not generic GPAC replacements but may occur multiple times in template):\n" "- $Init=NAME$: replaced by NAME for init segment, ignored otherwise\n" + "- $XInit=NAME$: complete replace by NAME for init segment, ignored otherwise\n" "- $Index=NAME$: replaced by NAME for index segments, ignored otherwise\n" "- $Path=PATH$: replaced by PATH when creating segments, ignored otherwise\n" "- $Segment=NAME$: replaced by NAME for media segments, ignored for init segments\n" "- $FS$ (FileSuffix): replaced by `_trackN` in case the input is an AV multiplex, or kept empty otherwise\n" "Note: these strings are replaced in the manifest templates elements.\n" "\n" - "## PID assignment\n" + "## PID assignment and configuration\n" "To assign PIDs into periods and adaptation sets and configure the session, the segmenter looks for the following properties on each input pid:\n" "- Representation: assigns representation ID to input pid. If not set, the default behaviour is to have each media component in different adaptation sets. Setting the RepresentationID allows explicit multiplexing of the source(s)\n" "- Period: assigns period ID to input pid. If not set, the default behaviour is to have all media in the same period with the same start time\n" @@ -6606,7 +7093,7 @@ "- Template: overrides segmenter [-template]() for this PID\n" "- DashDur: overrides segmenter segment duration for this PID\n" "- StartNumber: sets the start number for the first segment in the PID, default is 1\n" - "- Non-dash properties: Bitrate, SAR, Language, Width, Height, SampleRate, NumChannels, Language, ID, DependencyID, FPS, Interlaced. These properties are used to setup each representation and can be overriden on input PIDs using the general PID property settings (cf global help).\n" + "- Non-dash properties: Bitrate, SAR, Language, Width, Height, SampleRate, NumChannels, Language, ID, DependencyID, FPS, Interlaced, Codec. These properties are used to setup each representation and can be overridden on input PIDs using the general PID property settings (cf global help).\n" " \n" "EX src=test.mp4:#Bitrate=1M dst=test.mpd\n" "This will force declaring a bitrate of 1M for the representation, regardless of actual input bitrate.\n" @@ -6660,12 +7147,29 @@ "Warning: Cues shall be listed in decoding order.\n" "\n" "## Manifest Generation only mode\n" - "The segmenter can try to generate manifests from already fragmented ISOBMFF inputs using [-sigfrag]().\n" + "The segmenter can be used to generate manifests from already fragmented ISOBMFF inputs using [-sigfrag]().\n" "In this case, segment boundaries are attached to each packet starting a segment and used to drive the segmentation.\n" - "This should only be used with single-track ISOBMFF sources. If onDemand [-profile]() is requested, sources have to be formatted as a DASH self-initializing media segment with the proper sidx.\n" - "This mode automatically disables templates and forces [-sseg]() for all profiles except onDemand ones.\n" + "This can be used with single-track ISOBMFF sources, either single file or multi file.\n" + "For single file source:\n" + "- if onDemand [-profile]() is requested, sources have to be formatted as a DASH self-initializing media segment with the proper sidx.\n" + "- templates are disabled.\n" + "- [-sseg]() is forced for all profiles except onDemand ones.\n" + "For multi files source:\n" + "- input shall be a playlist containing the initial file followed by the ordered list of segments.\n" + "- if no [-template]() is provided, the full or main [-profile]() will be used\n" + "- if [-template]() is provided, it shall be correct: the filter will not try to guess one from the input file names and will not validate it either.\n" + "\n" "The manifest generation-only mode supports both MPD and HLS generation.\n" "\n" + "EX -i ondemand_src.mp4 -o dash.mpd:sigfrag:profile=onDemand\n" + "This will generate a DASH manifest for onDemand Profile based on the input file.\n" + "EX -i ondemand_src.mp4 -o dash.m3u8:sigfrag\n" + "This will generate a HLS manifest based on the input file.\n" + "EX -i seglist.txt -o dash.mpd:sigfrag\n" + "This will generate a DASH manifest in Main Profile based on the input files.\n" + "EX -i seglist.txt:Template=$XInit=init$$q1/$Number$ -o dash.mpd:sigfrag:profile=live\n" + "This will generate a DASH manifest in live Profile based on the input files. The input file will contain `init.mp4`, `q1/1.m4s`, `q1/2.m4s`...\n" + "\n" "## Muxer development considerations\n" "Output muxers allowing segmented output must obey the following:\n" "- inspect packet properties\n" @@ -6677,7 +7181,7 @@ "- for muxers with init data, send a downstream event signaling the size of the init and the size of the global index if any\n" "- the following filter options are passed to muxers, which should declare them as arguments:\n" " - noinit: disables output of init segment for the muxer (used to handle bitstream switching with single init in DASH)\n" - " - frag: indicates muxer shall used fragmented format (used for ISOBMFF mostly)\n" + " - frag: indicates muxer shall use fragmented format (used for ISOBMFF mostly)\n" " - subs_sidx=0: indicates an SIDX shall be generated - only added if not already specified by user\n" " - xps_inband=all|no: indicates AVC/HEVC/... parameter sets shall be sent inband or out of band\n" " - nofragdef: indicates fragment defaults should be set in each segment rather than in init segment\n"
View file
gpac-1.0.0.tar.gz/src/filters/dec_bifs.c -> gpac-1.0.1.tar.gz/src/filters/dec_bifs.c
Changed
@@ -29,6 +29,8 @@ #include <gpac/compositor.h> #include <gpac/internal/compositor_dev.h> +#ifndef GPAC_DISABLE_BIFS + typedef struct { @@ -40,8 +42,6 @@ GF_FilterPid *out_pid; } GF_BIFSDecCtx; -#ifndef GPAC_DISABLE_BIFS - static GF_Err bifs_dec_configure_bifs_dec(GF_BIFSDecCtx *ctx, GF_FilterPid *pid) { GF_Err e;
View file
gpac-1.0.0.tar.gz/src/filters/dec_mediacodec.c -> gpac-1.0.1.tar.gz/src/filters/dec_mediacodec.c
Changed
@@ -27,7 +27,7 @@ #include <gpac/internal/media_dev.h> #include <gpac/constants.h> -#ifdef GPAC_CONFIG_ANDROID +#if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC) #include "dec_mediacodec.h" @@ -329,7 +329,7 @@ ctx->format = AMediaFormat_new(); if(!ctx->format) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_new failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_new failed\n")); return GF_FILTER_NOT_FOUND; } @@ -367,7 +367,7 @@ } if (!ctx->codec) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_createDecoderByType failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_createDecoderByType failed\n")); return GF_FILTER_NOT_FOUND; } @@ -380,18 +380,18 @@ //TODO add support for crypto if( AMediaCodec_configure(ctx->codec, ctx->format, (ctx->surface_rendering) ? ctx->window : NULL, NULL, 0) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_configure failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_configure failed\n")); return GF_BAD_PARAM; } if( AMediaCodec_start(ctx->codec) != AMEDIA_OK){ - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC , ("[MCDec] AMediaCodec_start failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC , ("[MCDec] AMediaCodec_start failed\n")); return GF_BAD_PARAM; } ctx->inputEOS = GF_FALSE; ctx->outputEOS = GF_FALSE; - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] Video size: %d x %d", ctx->width, ctx->height)); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] Video size: %d x %d\n", ctx->width, ctx->height)); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) ); @@ -629,10 +629,10 @@ if (codecid!=ctx->codecid) do_reset = GF_TRUE; else if (!ctx->is_adaptive) do_reset = GF_TRUE; + else ctx->inject_xps = GF_TRUE; ctx->codecid = codecid; - if (do_reset && ctx->codec) { AMediaCodec_delete(ctx->codec); ctx->codec = NULL; @@ -729,17 +729,17 @@ return mcdec_init_decoder(ctx); } -static void mcdec_write_ps(GF_BitStream *bs, GF_List *ps, s32 active_ps) +static void mcdec_write_ps(GF_BitStream *bs, GF_List *ps, s32 active_ps, Bool all) { u32 i, count; - if (active_ps<0) return; + if (!all && (active_ps<0)) return; count = gf_list_count(ps); for (i=0; i<count; i++) { GF_AVCConfigSlot *sl = gf_list_get(ps, i); - if (sl->id==active_ps) { + if (all || (sl->id==active_ps)) { gf_bs_write_u32(bs, 1); gf_bs_write_data(bs, sl->data, sl->size); - return; + if (!all) return; } } } @@ -761,9 +761,9 @@ if (ctx->inject_xps) { ctx->inject_xps = GF_FALSE; - mcdec_write_ps(bs, ctx->VPSs, ctx->active_vps); - mcdec_write_ps(bs, ctx->SPSs, ctx->active_sps); - mcdec_write_ps(bs, ctx->PPSs, ctx->active_pps); + mcdec_write_ps(bs, ctx->VPSs, ctx->active_vps, ctx->is_adaptive); + mcdec_write_ps(bs, ctx->SPSs, ctx->active_sps, ctx->is_adaptive); + mcdec_write_ps(bs, ctx->PPSs, ctx->active_pps, ctx->is_adaptive); } while (inBufferLength) { @@ -817,7 +817,7 @@ default: if ((nal_type <= GF_AVC_NALU_IDR_SLICE) && ctx->avc.s_info.sps) { if (ctx->avc.sps_active_idx != ctx->active_sps) { - ctx->reconfig_needed = 1; + ctx->reconfig_needed = GF_TRUE; ctx->active_sps = ctx->avc.sps_active_idx; ctx->active_pps = ctx->avc.s_info.pps->id; gf_bs_del(bs); @@ -840,7 +840,7 @@ default: if ((nal_type <= GF_HEVC_NALU_SLICE_CRA) && ctx->hevc.s_info.sps) { if ((ctx->hevc.sps_active_idx != ctx->active_sps) || (ctx->hevc.sps[ctx->active_sps].vps_id != ctx->active_vps)) { - ctx->reconfig_needed = 1; + ctx->reconfig_needed = GF_TRUE; ctx->active_sps = ctx->hevc.sps_active_idx; ctx->active_pps = ctx->hevc.s_info.pps->id; ctx->active_vps = ctx->hevc.sps[ctx->active_sps].vps_id; @@ -959,7 +959,7 @@ } if (in_data_size > inSize) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] The returned buffer is too small")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] The returned buffer is too small\n")); if (do_free) gf_free(in_data); return GF_OK; } @@ -969,16 +969,17 @@ gf_filter_pid_drop_packet(ref_pid); if (do_free) gf_free(in_data); } else { - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM input")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM input\n")); ctx->inputEOS = GF_TRUE; flags = AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM; } if (AMediaCodec_queueInputBuffer(ctx->codec, inIndex, 0, in_data_size, cts, flags) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_queueInputBuffer failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_queueInputBuffer failed\n")); return GF_BAD_PARAM; } mcdec_buffer_available = GF_TRUE; + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] AMediaCodec_queueInputBuffer OK, %d bytes queued (in EOS %d)\n", in_data_size, ctx->inputEOS)); } } @@ -990,7 +991,7 @@ switch(ctx->outIndex) { case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED: - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED\n")); ctx->format = AMediaCodec_getOutputFormat(ctx->codec); AMediaFormat_getInt32(ctx->format, AMEDIAFORMAT_KEY_WIDTH, &width); AMediaFormat_getInt32(ctx->format, AMEDIAFORMAT_KEY_HEIGHT, &height); @@ -1002,11 +1003,11 @@ break; case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED: - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED\n")); break; case AMEDIACODEC_INFO_TRY_AGAIN_LATER: - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_TRY_AGAIN_LATER")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_TRY_AGAIN_LATER\n")); break; default: @@ -1016,7 +1017,7 @@ dec_frame = NULL; if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { - GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM output")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM output\n")); ctx->outputEOS = GF_TRUE; } @@ -1026,10 +1027,12 @@ dec_frame = buffer + info.offset; if (!dec_frame) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_getOutputBuffer failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_getOutputBuffer failed\n")); break; } } + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] got output buffer CTS "LLU" (out EOS %d)\n", info.presentationTimeUs, ctx->outputEOS)); + e = mcdec_send_frame(ctx, dec_frame, info.presentationTimeUs); if (e) return e; break; @@ -1048,7 +1051,7 @@ if (f->ctx->codec && !f->flushed) { if ( AMediaCodec_releaseOutputBuffer(f->ctx->codec, f->outIndex, GF_FALSE) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d", f->outIndex)); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d\n", f->outIndex)); } } f->ctx->decoded_frames_pending--; @@ -1096,7 +1099,7 @@ if(!f->flushed && f->ctx->codec) { if (AMediaCodec_releaseOutputBuffer(f->ctx->codec, f->outIndex, GF_TRUE) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d to surface", f->outIndex)); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d to surface\n", f->outIndex)); return GF_OK; } if(mcdec_update_surface(f->ctx->surfaceTex) != GF_OK) return GF_BAD_PARAM; @@ -1134,6 +1137,7 @@ if (ctx->frame_size_changed) { mc_frame->frame_ifce.flags = GF_FRAME_IFCE_BLOCKING; + ctx->frame_size_changed = GF_FALSE; } ctx->decoded_frames_pending++; @@ -1156,10 +1160,12 @@ GF_MCDecCtx *ctx = gf_filter_get_udta(filter); ctx->filter = filter; + ctx->frames_res = gf_list_new(); + ctx->streams = gf_list_new(); + ctx->SPSs = gf_list_new(); ctx->PPSs = gf_list_new(); ctx->VPSs = gf_list_new(); - ctx->frames_res = gf_list_new(); ctx->active_vps = -1; ctx->active_sps = -1; @@ -1173,11 +1179,11 @@ GF_MCDecCtx *ctx = gf_filter_get_udta(filter); if (ctx->format && AMediaFormat_delete(ctx->format) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_delete failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_delete failed\n")); } if (ctx->codec && AMediaCodec_delete(ctx->codec) != AMEDIA_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_delete failed")); + GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_delete failed\n")); } if(ctx->window) { @@ -1203,6 +1209,7 @@ gf_free(f); } gf_list_del(ctx->frames_res); + gf_list_del(ctx->streams); } #else @@ -1217,7 +1224,8 @@ { CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL), CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE), - CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2), + //commented as some devices seem to have issues with this one +// CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2), CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC), CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC), CAP_BOOL(GF_CAPS_INPUT_EXCLUDED,GF_PROP_PID_TILE_BASE, GF_TRUE), @@ -1226,7 +1234,7 @@ CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW), }; -#ifdef GPAC_CONFIG_ANDROID +#if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC) #define OFFS(_n) #_n, offsetof(GF_MCDecCtx, _n) #else #define OFFS(_n) #_n, -1 @@ -1244,14 +1252,13 @@ GF_FS_SET_HELP("This filter decodes video streams using hardware decoder on android devices") .args = MCDecArgs, SETCAPS(MCDecCaps), -#ifdef GPAC_CONFIG_ANDROID +#if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC) .private_size = sizeof(GF_MCDecCtx), .initialize = mcdec_initialize, .finalize = mcdec_finalize, .configure_pid = mcdec_configure_pid, -#else - .process = mcdec_process, #endif + .process = mcdec_process, };
View file
gpac-1.0.0.tar.gz/src/filters/dec_nvdec_sdk.c -> gpac-1.0.1.tar.gz/src/filters/dec_nvdec_sdk.c
Changed
@@ -213,7 +213,7 @@ #define STRINGIFY(X) #X #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) -#include <Windows.h> +#include <windows.h> #ifdef UNICODE static LPCWSTR __CudaLibName = L"nvcuda.dll";
View file
gpac-1.0.0.tar.gz/src/filters/dec_nvdec_sdk.h -> gpac-1.0.1.tar.gz/src/filters/dec_nvdec_sdk.h
Changed
@@ -1712,8 +1712,8 @@ * driver API (___CURRENT_FILE___) ___ENDMANBRIEF___ * * This section describes the OpenGL interoperability functions of the - * low-level CUDA driver application programming interface. Note that mapping - * of OpenGL resources is performed with the graphics API agnostic, resource + * low-level CUDA driver application programming interface. Note that mapping + * of OpenGL resources is performed with the graphics API agnostic, resource * mapping interface described in \ref CUDA_GRAPHICS "Graphics Interoperability". * * @{ @@ -1760,7 +1760,7 @@ typedef enum CUGLmap_flags_enum { CU_GL_MAP_RESOURCE_FLAGS_NONE = 0x00, CU_GL_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01, - CU_GL_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02, + CU_GL_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02, } CUGLmap_flags; //#if __CUDA_API_VERSION >= 3020 @@ -1812,7 +1812,7 @@ #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) -#include <Windows.h> +#include <windows.h> typedef HMODULE CUDADRIVER; #else typedef void *CUDADRIVER; @@ -2605,7 +2605,7 @@ extern tcuvidCtxLockDestroy *cuvidCtxLockDestroy; extern tcuvidCtxLock *cuvidCtxLock; extern tcuvidCtxUnlock *cuvidCtxUnlock; - + //////////////////////////////////////////////////////////////////////////////////////////////// // // High-level helper APIs for video sources @@ -2896,4 +2896,3 @@ #endif // defined(WIN32) || defined(GPAC_CONFIG_LINUX) #endif //__cuda_tools_h__ -
View file
gpac-1.0.0.tar.gz/src/filters/dec_odf.c -> gpac-1.0.1.tar.gz/src/filters/dec_odf.c
Changed
@@ -27,6 +27,8 @@ #include <gpac/constants.h> #include <gpac/compositor.h> +#ifndef GPAC_DISABLE_PLAYER + typedef struct { GF_ObjectManager *odm; @@ -472,4 +474,9 @@ { return &ODFDecRegister; } - +#else +const GF_FilterRegister *odf_dec_register(GF_FilterSession *session) +{ + return NULL; +} +#endif // GPAC_DISABLE_PLAYER
View file
gpac-1.0.0.tar.gz/src/filters/dec_vtb.c -> gpac-1.0.1.tar.gz/src/filters/dec_vtb.c
Changed
@@ -822,6 +822,7 @@ else gf_bs_reassign_buffer(ctx->ps_bs, data, size); if (hevc_nal_type) { +#ifndef GPAC_DISABLE_HEVC if (hevc_nal_type==GF_HEVC_NALU_SEQ_PARAM) { dest = ctx->SPSs; ps_id = gf_media_hevc_read_sps_bs(ctx->ps_bs, &ctx->hevc); @@ -837,6 +838,7 @@ ps_id = gf_media_hevc_read_vps_bs(ctx->ps_bs, &ctx->hevc); if (ps_id<0) return; } +#endif //GPAC_DISABLE_HEVC } else { dest = is_sps ? ctx->SPSs : ctx->PPSs; @@ -1272,6 +1274,9 @@ } } } else if (ctx->is_hevc) { +#ifdef GPAC_DISABLE_HEVC + return GF_NOT_SUPPORTED; +#else u8 temporal_id, ayer_id; if (!ctx->nal_bs) ctx->nal_bs = gf_bs_new(ptr, nal_size, GF_BITSTREAM_READ); @@ -1306,6 +1311,8 @@ } } } +#endif + } //if sps and pps are ready, init decoder
View file
gpac-1.0.0.tar.gz/src/filters/dmx_dash.c -> gpac-1.0.1.tar.gz/src/filters/dmx_dash.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2017 + * Copyright (c) Telecom ParisTech 2017-2020 * All rights reserved * * This file is part of GPAC / DASH/HLS demux filter @@ -34,14 +34,14 @@ { //opts s32 shift_utc, debug_as, atsc_shift; - u32 max_buffer, auto_switch, timeshift, tiles_rate, store, delay40X, exp_threshold, switch_count; + u32 max_buffer, auto_switch, init_timeshift, tiles_rate, segstore, delay40X, exp_threshold, switch_count; Bool server_utc, screen_res, aggressive, speedadapt; GF_DASHInitialSelectionMode start_with; GF_DASHTileAdaptationMode tile_mode; GF_DASHAdaptationAlgorithm algo; Bool max_res, immediate, abort, use_bmin; char *query; - Bool noxlink, split_as; + Bool noxlink, split_as, noseek; u32 lowlat; GF_FilterPid *mpd_pid; @@ -261,11 +261,11 @@ } //not from file system, set cache option if (url_type) { - if (!ctx->store) { + if (!ctx->segstore) { if (!has_sep) { strcat(sURL, ":gpac"); has_sep = GF_TRUE; } strcat(sURL, ":cache=mem"); } - else if (ctx->store==2) { + else if (ctx->segstore==2) { if (!has_sep) { strcat(sURL, ":gpac"); has_sep = GF_TRUE; } strcat(sURL, ":cache=keep"); } @@ -278,7 +278,7 @@ strcat(sURL, szRange); } - group->seg_filter_src = gf_filter_connect_source(ctx->filter, sURL, NULL, &e); + group->seg_filter_src = gf_filter_connect_source(ctx->filter, sURL, NULL, GF_FALSE, &e); if (!group->seg_filter_src) { gf_free(sURL); gf_free(group); @@ -308,7 +308,6 @@ GF_DASHFileIOSession dashdmx_io_create(GF_DASHFileIO *dashio, Bool persistent, const char *url, s32 group_idx) { GF_DownloadSession *sess; - const GF_PropertyValue *p; GF_Err e; u32 flags = GF_NETIO_SESSION_NOT_THREADED; GF_DASHDmxCtx *ctx = (GF_DASHDmxCtx *)dashio->udta; @@ -319,18 +318,24 @@ //crude hack when using gpac downloader to initialize the MPD pid: get the pointer to the download session //this should be safe unless the mpd_pid is destroyed, which should only happen upon destruction of the DASH session - p = gf_filter_pid_get_property(ctx->mpd_pid, GF_PROP_PID_DOWNLOAD_SESSION); - if (p) { - sess = (GF_DownloadSession *) p->value.ptr; - if (!ctx->store) { - gf_dm_sess_force_memory_mode(sess); + if (group_idx==-1) { + const GF_PropertyValue *p = gf_filter_pid_get_property(ctx->mpd_pid, GF_PROP_PID_DOWNLOAD_SESSION); + if (p) { + sess = (GF_DownloadSession *) p->value.ptr; + if (!ctx->segstore) { + gf_dm_sess_force_memory_mode(sess); + } + ctx->reuse_download_session = GF_TRUE; + return (GF_DASHFileIOSession) sess; } - ctx->reuse_download_session = GF_TRUE; - return (GF_DASHFileIOSession) sess; } - if (!ctx->store) flags |= GF_NETIO_SESSION_MEMORY_CACHE; - if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT; + if (group_idx<-1) { + flags |= GF_NETIO_SESSION_MEMORY_CACHE; + } else { + if (!ctx->segstore) flags |= GF_NETIO_SESSION_MEMORY_CACHE; + if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT; + } sess = gf_dm_sess_new(ctx->dm, url, flags, NULL, NULL, &e); return (GF_DASHFileIOSession) sess; } @@ -751,6 +756,17 @@ return gf_filter_pid_new(filter); } +Bool dashdmx_merge_prop(void *cbk, u32 prop_4cc, const char *prop_name, const GF_PropertyValue *src_prop) +{ + const GF_PropertyValue *p; + GF_FilterPid *pid = (GF_FilterPid *) cbk; + + if (prop_4cc) p = gf_filter_pid_get_property(pid, prop_4cc); + else p = gf_filter_pid_get_property_str(pid, prop_name); + if (p) return GF_FALSE; + return GF_TRUE; +} + static void dashdmx_declare_properties(GF_DASHDmxCtx *ctx, GF_DASHGroup *group, u32 group_idx, GF_FilterPid *opid, GF_FilterPid *ipid) { GF_DASHQualityInfo qinfo; @@ -923,6 +939,13 @@ //setup initial quality - this is disabled in test mode for the time being (invalidates all dash playback hashes) if (!gf_sys_is_test_mode()) dashdmx_io_on_dash_event(&ctx->dash_io, GF_DASH_EVENT_QUALITY_SWITCH, group->idx, GF_OK); + + + //if MPD file pid is defined, merge its properties. This will allow forwarding user-defined properties, + // eg -i dash.mpd:#MyProp=toto to all PIDs coming from media sources + if (ctx->mpd_pid) { + gf_filter_pid_merge_properties(opid, ctx->mpd_pid, dashdmx_merge_prop, ipid); + } } static GF_Err dashdmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove) @@ -1072,7 +1095,7 @@ ctx->dash_io.on_dash_event = dashdmx_io_on_dash_event; - ctx->dash = gf_dash_new(&ctx->dash_io, GF_DASH_THREAD_NONE, 0, ctx->auto_switch, (ctx->store==2) ? GF_TRUE : GF_FALSE, (ctx->algo==GF_DASH_ALGO_NONE) ? GF_TRUE : GF_FALSE, ctx->start_with, ctx->timeshift); + ctx->dash = gf_dash_new(&ctx->dash_io, GF_DASH_THREAD_NONE, 0, ctx->auto_switch, (ctx->segstore==2) ? GF_TRUE : GF_FALSE, (ctx->algo==GF_DASH_ALGO_NONE) ? GF_TRUE : GF_FALSE, ctx->start_with, ctx->init_timeshift); if (!ctx->dash) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASHDmx] Error - cannot create DASH Client\n")); @@ -1130,8 +1153,6 @@ u32 i, count; GF_FilterEvent src_evt; GF_FilterPid *ipid; - u64 pto; - u32 timescale; Bool initial_play; Double offset; GF_DASHDmxCtx *ctx = (GF_DASHDmxCtx*) gf_filter_get_udta(filter); @@ -1207,6 +1228,8 @@ if (fevt->play.timestamp_based) { if (fevt->play.timestamp_based==1) { + u64 pto; + u32 timescale; gf_dash_group_get_presentation_time_offset(ctx->dash, group->idx, &pto, ×cale); offset = (Double) pto; offset /= timescale; @@ -1280,11 +1303,16 @@ gf_dash_set_group_done(ctx->dash, (u32) group->idx, 0); //adjust start range from MPD time to media time - src_evt.play.start_range = gf_dash_group_get_start_range(ctx->dash, group->idx); - gf_dash_group_get_presentation_time_offset(ctx->dash, group->idx, &pto, ×cale); - src_evt.play.start_range += ((Double)pto) / timescale; + if (gf_dash_is_dynamic_mpd(ctx->dash) && ctx->noseek) { + src_evt.play.start_range=0; + } else { + u64 pto; + u32 timescale; + src_evt.play.start_range = gf_dash_group_get_start_range(ctx->dash, group->idx); + gf_dash_group_get_presentation_time_offset(ctx->dash, group->idx, &pto, ×cale); + src_evt.play.start_range += ((Double)pto) / timescale; + } src_evt.play.no_byterange_forward = 1; - dashdmx_setup_buffer(ctx, group); gf_filter_prevent_blocking(filter, GF_TRUE); @@ -1710,7 +1738,7 @@ static const GF_FilterArgs DASHDmxArgs[] = { { OFFS(auto_switch), "switch quality every N segments, disabled if 0", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(store), "enable file caching\n" + { OFFS(segstore), "enable file caching\n" "- mem: all files are stored in memory, no disk IO\n" "- file: files are stored to disk but discarded once played\n" "- cache: all files are stored to disk and kept" @@ -1742,7 +1770,7 @@ { OFFS(atsc_shift), "shift ATSC requests time by given ms", GF_PROP_SINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(server_utc), "use ServerUTC: or Date: http headers instead of local UTC", GF_PROP_BOOL, "yes", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(screen_res), "use screen resolution in selection phase", GF_PROP_BOOL, "yes", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(timeshift), "set initial timshift in ms (if >0) or in %% of timeshift buffer (if <0)", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(init_timeshift), "set initial timshift in ms (if >0) or in per-cent of timeshift buffer (if <0)", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tile_mode), "tile adaptation mode\n"\ "- none: bitrate is shared equaly accross all tiles\n"\ "- rows: bitrate decreases for each row of tiles starting from the top, same rate for each tile on the row\n"\ @@ -1754,7 +1782,7 @@ "- center: bitrate decreased for all tiles on the edge of the picture\n"\ "- edges: bitrate decreased for all tiles on the center of the picture" , GF_PROP_UINT, "none", "none|rows|rrows|mrows|cols|rcols|mcols|center|edges", GF_FS_ARG_HINT_EXPERT}, - { OFFS(tiles_rate), "indicate the amount of bandwidth to use at each quality level. The rate is recursively applied at each level, e.g. if 50%, Level1 gets 50%, level2 gets 25%, ... If 100, automatic rate allocation will be done by maximizing the quality in order of priority. If 0, bitstream will not be smoothed across tiles/qualities, and concurrency may happen between different media.", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(tiles_rate), "indicate the amount of bandwidth to use at each quality level. The rate is recursively applied at each level, e.g. if 50%, Level1 gets 50%, level2 gets 25%, ... If 100, automatic rate allocation will be done by maximizing the quality in order of priority. If 0, bitstream will not be smoothed across tiles/qualities, and concurrency may happen between different media", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(delay40X), "delay in millisconds to wait between two 40X on the same segment", GF_PROP_UINT, "500", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(exp_threshold), "delay in millisconds to wait after the segment AvailabilityEndDate before considering the segment lost", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(switch_count), "indicate how many segments the client shall wait before switching up bandwidth. If 0, switch will happen as soon as the bandwidth is enough, but this is more prone to network variations", GF_PROP_UINT, "1", NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -1764,6 +1792,7 @@ { OFFS(noxlink), "disable xlink if period has both xlink and adaptation sets", GF_PROP_BOOL, "no", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(query), "set query string (without initial '?') to append to xlink of periods", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(split_as), "separate all qualities into different adaptation sets and stream all qualities", GF_PROP_BOOL, "no", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(noseek), "disable seeking of initial segment(s) in dynamic mode (useful when UTC clocks do not match)", GF_PROP_BOOL, "no", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(lowlat), "segment scheduling policy in low latency mode\n" "- no: disable low latency\n" "- strict: strict respect of AST offset in low latency\n" @@ -1786,8 +1815,7 @@ { .code=GF_PROP_PID_STREAM_TYPE, .val.type=GF_PROP_UINT, .val.value.uint=GF_STREAM_FILE, .flags=(GF_CAPFLAG_IN_BUNDLE|GF_CAPFLAG_INPUT|GF_CAPFLAG_EXCLUDED|GF_CAPFLAG_LOADED_FILTER) }, { .code=GF_PROP_PID_UNFRAMED, .val.type=GF_PROP_BOOL, .val.value.boolean=GF_TRUE, .flags=(GF_CAPFLAG_IN_BUNDLE|GF_CAPFLAG_INPUT|GF_CAPFLAG_EXCLUDED|GF_CAPFLAG_LOADED_FILTER) }, CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW), - CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO), - CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL), + CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE), CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW), };
View file
gpac-1.0.0.tar.gz/src/filters/dmx_gsf.c -> gpac-1.0.1.tar.gz/src/filters/dmx_gsf.c
Changed
@@ -217,6 +217,7 @@ static void gsfdmx_decrypt(GSF_DemuxCtx *ctx, char *data, u32 size) { +#ifndef GPAC_DISABLE_CRYPTO u32 pos=0; u32 clear_tail = size%16; u32 bytes_crypted = size - clear_tail; @@ -239,6 +240,7 @@ } else { gf_crypt_decrypt(ctx->crypt, data, bytes_crypted); } +#endif } static GFINLINE u32 gsfdmx_read_vlen(GF_BitStream *bs) @@ -474,6 +476,9 @@ return GF_NOT_SUPPORTED; } if (is_crypted) { +#ifdef GPAC_DISABLE_CRYPTO + return GF_NOT_SUPPORTED; +#else if (pck_size<25) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFDemux] Wrong serialized header size %d, should be at least 25 bytes for encrypted streams\n", pck_size )); ctx->tune_error = GF_TRUE; @@ -497,6 +502,7 @@ gf_crypt_init(ctx->crypt, ctx->key.ptr, ctx->crypt_IV); gsfdmx_decrypt(ctx, pck_data+25, pck_size - 25); +#endif } ctx->use_seq_num = gf_bs_read_int(bs, 1); gf_bs_read_int(bs, 7); @@ -719,7 +725,7 @@ dur = gf_bs_read_int(bs, durmodebits); } - if (sap==GF_FILTER_SAP_4) { + if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL)) { roll = gf_bs_read_u16(bs); } if (has_dep) @@ -819,7 +825,8 @@ if (seek) gf_filter_pck_set_seek_flag(gpck->pck, seek); if (crypt) gf_filter_pck_set_crypt_flags(gpck->pck, crypt); if (sap) gf_filter_pck_set_sap(gpck->pck, sap); - if (sap==GF_FILTER_SAP_4) gf_filter_pck_set_roll_info(gpck->pck, roll); + if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL)) + gf_filter_pck_set_roll_info(gpck->pck, roll); return GF_OK; } @@ -1215,7 +1222,9 @@ } gf_list_del(ctx->pck_res); +#ifndef GPAC_DISABLE_CRYPTO if (ctx->crypt) gf_crypt_close(ctx->crypt); +#endif if (ctx->buffer) gf_free(ctx->buffer); if (ctx->bs_r) gf_bs_del(ctx->bs_r); if (ctx->bs_pck) gf_bs_del(ctx->bs_pck); @@ -1237,7 +1246,9 @@ #define OFFS(_n) #_n, offsetof(GSF_DemuxCtx, _n) static const GF_FilterArgs GSFDemuxArgs[] = { +#ifndef GPAC_DISABLE_CRYPTO { OFFS(key), "key for decrypting packets", GF_PROP_DATA, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, +#endif { OFFS(magic), "magic string to check in setup packet", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(mq), "set max packet queue length for loss detection. 0 will flush incomplete packet when a new one starts", GF_PROP_UINT, "4", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(pad), "byte value used to pad lost packets", GF_PROP_UINT, "0", "0-255", GF_FS_ARG_HINT_ADVANCED}, @@ -1248,11 +1259,17 @@ GF_FilterRegister GSFDemuxRegister = { .name = "gsfdmx", GF_FS_SET_DESCRIPTION("GSF Demuxer") - GF_FS_SET_HELP("This filter provides GSF (__GPAC Super/Simple/Serialized/Stream/State Format__) demultiplexing.\n" +#ifndef GPAC_DISABLE_DOC + .help = "This filter provides GSF (__GPAC Super/Simple/Serialized/Stream/State Format__) demultiplexing.\n" "It deserializes the stream states (config/reconfig/info update/remove/eos) and packets of input PIDs.\n" "This allows either reading a session saved to file, or receiving the state/data of streams from another instance of GPAC using either pipes or sockets\n" "\n" - "The stream format can be encrypted in AES 128 CBC mode, in which case the demux filters must be given a 128 bit key.") +#ifndef GPAC_DISABLE_CRYPTO + "The stream format can be encrypted in AES 128 CBC mode, in which case the demux filters must be given a 128 bit key." +#endif + , +#endif + .private_size = sizeof(GSF_DemuxCtx), .max_extra_pids = (u32) -1, .args = GSFDemuxArgs,
View file
gpac-1.0.0.tar.gz/src/filters/dmx_m2ts.c -> gpac-1.0.1.tar.gz/src/filters/dmx_m2ts.c
Changed
@@ -39,6 +39,13 @@ u32 pid; } GF_M2TSDmxCtx_Prog; +typedef struct { + u32 timeline_id; + Bool is_loc; + u32 len; + u8 *data; +} GF_TEMIInfo; + enum { DMX_TUNE_DONE=0, @@ -387,6 +394,22 @@ } } +static void m2tdmx_merge_temi(GF_M2TS_ES *stream, GF_FilterPacket *pck) +{ + if (stream->props) { + char szID[100]; + while (gf_list_count(stream->props)) { + GF_TEMIInfo *t = gf_list_pop_front(stream->props); + snprintf(szID, 100, "%s:%d", t->is_loc ? "temi_l" : "temi_t", t->timeline_id); + + gf_filter_pck_set_property_dyn(pck, szID, &PROP_DATA_NO_COPY(t->data, t->len)); + gf_free(t); + } + gf_list_del(stream->props); + stream->props = NULL; + } +} + static void m2tsdmx_send_packet(GF_M2TSDmxCtx *ctx, GF_M2TS_PES_PCK *pck) { GF_FilterPid *opid; @@ -410,6 +433,7 @@ } gf_filter_pck_set_sap(dst_pck, (pck->flags & GF_M2TS_PES_PCK_RAP) ? GF_FILTER_SAP_1 : GF_FILTER_SAP_NONE); } + m2tdmx_merge_temi((GF_M2TS_ES *)pck->stream, dst_pck); gf_filter_pck_send(dst_pck); } @@ -467,6 +491,7 @@ gf_filter_pck_set_carousel_version(dst_pck, pck->version_number); + m2tdmx_merge_temi(pck->stream, dst_pck); gf_filter_pck_send(dst_pck); if (pck->version_number + 1 == pck->stream->slcfg->carousel_version) @@ -693,39 +718,86 @@ } break; -#ifdef FILTER_FIXME case GF_M2TS_EVT_TEMI_LOCATION: { - GF_NetworkCommand com; - memset(&com, 0, sizeof(com)); - com.addon_info.command_type = GF_NET_ASSOCIATED_CONTENT_LOCATION; - com.addon_info.external_URL = ((GF_M2TS_TemiLocationDescriptor*)param)->external_URL; - if (ctx->force_temi_url) - com.addon_info.external_URL = ctx->force_temi_url; - com.addon_info.is_announce = ((GF_M2TS_TemiLocationDescriptor*)param)->is_announce; - com.addon_info.is_splicing = ((GF_M2TS_TemiLocationDescriptor*)param)->is_splicing; - com.addon_info.activation_countdown = ((GF_M2TS_TemiLocationDescriptor*)param)->activation_countdown; -// com.addon_info.reload_external = ((GF_M2TS_TemiLocationDescriptor*)param)->reload_external; - com.addon_info.timeline_id = ((GF_M2TS_TemiLocationDescriptor*)param)->timeline_id; - gf_service_command(ctx->service, &com, GF_OK); + GF_M2TS_TemiLocationDescriptor *temi_l = (GF_M2TS_TemiLocationDescriptor *)param; + const char *url; + u32 len; + GF_BitStream *bs; + GF_M2TS_ES *es=NULL; + GF_TEMIInfo *t; + if ((temi_l->pid<8192) && (ctx->ts->ess[temi_l->pid])) { + es = ctx->ts->ess[temi_l->pid]; + } + if (!es || !es->user) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] TEMI location not assigned to a given PID, not supported\n")); + break; + } + GF_SAFEALLOC(t, GF_TEMIInfo); + if (!t) break; + t->timeline_id = temi_l->timeline_id; + t->is_loc = GF_TRUE; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + if (ctx->temi_url) + url = ctx->temi_url; + else + url = temi_l->external_URL; + len = url ? (u32) strlen(url) : 0; + gf_bs_write_data(bs, url, len); + gf_bs_write_u8(bs, 0); + gf_bs_write_int(bs, temi_l->is_announce, 1); + gf_bs_write_int(bs, temi_l->is_splicing, 1); + gf_bs_write_int(bs, temi_l->reload_external, 1); + gf_bs_write_int(bs, 0, 5); + gf_bs_write_double(bs, temi_l->activation_countdown); + gf_bs_get_content(bs, &t->data, &t->len); + gf_bs_del(bs); + + if (!es->props) { + es->props = gf_list_new(); + } + gf_list_add(es->props, t); } break; case GF_M2TS_EVT_TEMI_TIMECODE: { - GF_NetworkCommand com; - memset(&com, 0, sizeof(com)); - com.addon_time.command_type = GF_NET_ASSOCIATED_CONTENT_TIMING; - com.addon_time.timeline_id = ((GF_M2TS_TemiTimecodeDescriptor*)param)->timeline_id; - com.addon_time.media_pts = ((GF_M2TS_TemiTimecodeDescriptor*)param)->pes_pts; - com.addon_time.media_timescale = ((GF_M2TS_TemiTimecodeDescriptor*)param)->media_timescale; - com.addon_time.media_timestamp = ((GF_M2TS_TemiTimecodeDescriptor*)param)->media_timestamp; - com.addon_time.force_reload = ((GF_M2TS_TemiTimecodeDescriptor*)param)->force_reload; - com.addon_time.is_paused = ((GF_M2TS_TemiTimecodeDescriptor*)param)->is_paused; - com.addon_time.ntp = ((GF_M2TS_TemiTimecodeDescriptor*)param)->ntp; - gf_service_command(ctx->service, &com, GF_OK); + GF_M2TS_TemiTimecodeDescriptor *temi_t = (GF_M2TS_TemiTimecodeDescriptor*)param; + GF_BitStream *bs; + GF_TEMIInfo *t; + GF_M2TS_ES *es=NULL; + if ((temi_t->pid<8192) && (ctx->ts->ess[temi_t->pid])) { + es = ctx->ts->ess[temi_t->pid]; + } + if (!es || !es->user) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] TEMI timing not assigned to a given PID, not supported\n")); + break; + } + GF_SAFEALLOC(t, GF_TEMIInfo); + if (!t) break; + t->timeline_id = temi_t->timeline_id; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + gf_bs_write_u32(bs, temi_t->media_timescale); + gf_bs_write_u64(bs, temi_t->media_timestamp); + gf_bs_write_u64(bs, temi_t->pes_pts); + gf_bs_write_int(bs, temi_t->force_reload, 1); + gf_bs_write_int(bs, temi_t->is_paused, 1); + gf_bs_write_int(bs, temi_t->is_discontinuity, 1); + gf_bs_write_int(bs, temi_t->ntp ? 1 : 0, 1); + gf_bs_write_int(bs, 0, 4); + if (temi_t->ntp) + gf_bs_write_u64(bs, temi_t->ntp); + + gf_bs_get_content(bs, &t->data, &t->len); + gf_bs_del(bs); + + if (!es->props) { + es->props = gf_list_new(); + } + gf_list_add(es->props, t); } break; -#endif } } @@ -873,7 +945,7 @@ /*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, ("[GF_M2TSDmxCtx] Setting default reframing for PID %d\n", pes->pid)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[M2TSDmx] Setting default reframing for PID %d\n", pes->pid)); /*this is a multplex, only trigger the play command for the first stream activated*/ ctx->nb_playing++;
View file
gpac-1.0.0.tar.gz/src/filters/dmx_vobsub.c -> gpac-1.0.1.tar.gz/src/filters/dmx_vobsub.c
Changed
@@ -126,7 +126,7 @@ } } - ctx->sub_filter = gf_filter_connect_source(filter, sURL, NULL, &e); + ctx->sub_filter = gf_filter_connect_source(filter, sURL, NULL, GF_TRUE, &e); if (e) return e; if (ctx->mdia) gf_fclose(ctx->mdia); ctx->mdia = NULL;
View file
gpac-1.0.0.tar.gz/src/filters/encrypt_cenc_isma.c -> gpac-1.0.1.tar.gz/src/filters/encrypt_cenc_isma.c
Changed
@@ -159,7 +159,7 @@ if (!scheme_uri || !strlen(scheme_uri)) scheme_uri = "urn:gpac:isma:encryption_scheme"; if (cstr->tci && ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND) || (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND_RANGE)) ) { - gf_rand_init(1); + gf_rand_init(GF_TRUE); } cstr->isma_IV_size = 0;
View file
gpac-1.0.0.tar.gz/src/filters/ff_dec.c -> gpac-1.0.1.tar.gz/src/filters/ff_dec.c
Changed
@@ -683,6 +683,13 @@ } codec_id = ffmpeg_codecid_from_gpac(gpac_codecid, &ff_codectag); + //specific remaps + if (!codec_id) { + switch (gpac_codecid) { + case GF_CODECID_MVC: codec_id = AV_CODEC_ID_H264; break; + } + + } if (codec_id) codec = avcodec_find_decoder(codec_id); if (!codec) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] No decoder found for codec %s\n", gf_codecid_name(gpac_codecid) ));
View file
gpac-1.0.0.tar.gz/src/filters/filelist.c -> gpac-1.0.1.tar.gz/src/filters/filelist.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2018-2019 + * Copyright (c) Telecom ParisTech 2018-2020 * All rights reserved * * This file is part of GPAC / file concatenator filter @@ -28,6 +28,8 @@ #include <gpac/thread.h> #include <gpac/list.h> #include <gpac/bitstream.h> +#include <gpac/isomedia.h> +#include <gpac/network.h> #ifndef GPAC_DISABLE_AV_PARSERS #include <gpac/avparse.h> @@ -73,6 +75,7 @@ Bool revert; s32 floop; u32 fsort; + u32 ka; GF_List *srcs; GF_Fraction fdur; u32 timescale; @@ -92,13 +95,17 @@ u32 nb_repeat; Double start, stop; - + Bool do_cat; + u64 start_range, end_range; GF_List *file_list; s32 file_list_idx; u64 current_file_dur; - + Bool last_is_isom; char szCom[GF_MAX_PATH]; + + Bool wait_update; + u64 last_file_modif_time; } GF_FileListCtx; static const GF_FilterCapability FileListCapsSrc[] = @@ -109,12 +116,14 @@ static void filelist_start_ipid(GF_FileListCtx *ctx, FileListPid *iopid) { - GF_FilterEvent evt; iopid->is_eos = GF_FALSE; - //if we reattached the input, we must send a play request - gf_filter_pid_init_play_event(iopid->ipid, &evt, ctx->start, 1.0, "FileList"); - gf_filter_pid_send_event(iopid->ipid, &evt); + if (!ctx->do_cat) { + GF_FilterEvent evt; + //if we reattached the input, we must send a play request + gf_filter_pid_init_play_event(iopid->ipid, &evt, ctx->start, 1.0, "FileList"); + gf_filter_pid_send_event(iopid->ipid, &evt); + } //and convert back cts/dts offsets from 1Mhs to OLD timescale (since we dispatch in this timescale) iopid->dts_o = ctx->dts_offset; @@ -129,6 +138,17 @@ iopid->first_dts_plus_one = 0; } +Bool filelist_merge_prop(void *cbk, u32 prop_4cc, const char *prop_name, const GF_PropertyValue *src_prop) +{ + const GF_PropertyValue *p; + GF_FilterPid *pid = (GF_FilterPid *) cbk; + + if (prop_4cc) p = gf_filter_pid_get_property(pid, prop_4cc); + else p = gf_filter_pid_get_property_str(pid, prop_name); + if (p) return GF_FALSE; + return GF_TRUE; +} + GF_Err filelist_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove) { FileListPid *iopid; @@ -158,6 +178,7 @@ //from now on we only accept the above caps gf_filter_override_caps(filter, FileListCapsSrc, 2); + } if (ctx->file_pid == pid) return GF_OK; @@ -200,9 +221,18 @@ iopid->stream_type = p->value.uint; } + //copy properties at init or reconfig: + //reset (no more props) gf_filter_pid_reset_properties(iopid->opid); - //copy properties at init or reconfig + gf_filter_pid_copy_properties(iopid->opid, iopid->ipid); + + //if file pid is defined, merge its properties. This will allow forwarding user-defined properties, + // eg -i list.txt:#MyProp=toto to all PIDs coming from the sources + if (ctx->file_pid) { + gf_filter_pid_merge_properties(iopid->opid, ctx->file_pid, filelist_merge_prop, iopid->ipid); + } + //we could further optimize by querying the duration of all sources in the list gf_filter_pid_set_property(iopid->opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_NONE) ); gf_filter_pid_set_property(iopid->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(iopid->o_timescale) ); @@ -262,7 +292,7 @@ return GF_TRUE; } -void filelist_parse_arg(char *com, char *name, Bool is_float, u32 *int_val, Double *float_val) +void filelist_parse_arg(char *com, char *name, u32 type, u32 *int_val, Double *float_val, u64 *luint_val) { char *val = strstr(com, name); if (val) { @@ -276,19 +306,58 @@ sep[0] = 0; } val += strlen(name); - if (is_float) (*float_val) = atof(val); - else (*int_val) = atoi(val); + if (type==1) { + (*int_val) = atoi(val); + } else if (type==2) { + (*int_val) = atoi(val); + } else if (type==3) { + sscanf(val, LLU, luint_val); + } else if (type==0) { + (*int_val) = 1; + } if (sep) sep[0] = c; } } +void filelist_check_implicit_cat(GF_FileListCtx *ctx, char *szURL) +{ + char *res_url = NULL; + if (ctx->file_path) { + res_url = gf_url_concatenate(ctx->file_path, szURL); + szURL = res_url; + } + + switch (gf_isom_probe_file(szURL)) { + //this is a fragment + case 3: + if (ctx->last_is_isom) { + ctx->do_cat = GF_TRUE; + } + break; + //this is a movie, reload + case 2: + case 1: + ctx->do_cat = GF_FALSE; + ctx->last_is_isom = GF_TRUE; + break; + default: + ctx->do_cat = GF_FALSE; + ctx->last_is_isom = GF_FALSE; + } + if (res_url) + gf_free(res_url); +} + Bool filelist_next_url(GF_FileListCtx *ctx, char szURL[GF_MAX_PATH]) { u32 len; Bool last_found = GF_FALSE; FILE *f; u32 nb_repeat=0, lineno=0; + u64 start_range, end_range; Double start=0, stop=0; + Bool do_cat=0; + Bool is_end=0; if (ctx->file_list) { FileListEntry *fentry, *next; @@ -311,12 +380,20 @@ fentry = gf_list_get(ctx->file_list, ctx->file_list_idx); strncpy(szURL, fentry->file_name, sizeof(char)*(GF_MAX_PATH-1) ); szURL[GF_MAX_PATH-1] = 0; + filelist_check_implicit_cat(ctx, szURL); next = gf_list_get(ctx->file_list, ctx->file_list_idx + 1); if (next) ctx->current_file_dur = next->last_mod_time - fentry->last_mod_time; return GF_TRUE; } + if (ctx->wait_update) { + u64 last_modif_time = gf_file_modification_time(ctx->file_path); + if (ctx->last_file_modif_time >= last_modif_time) + return GF_FALSE; + ctx->wait_update = GF_FALSE; + ctx->last_file_modif_time = last_modif_time; + } f = gf_fopen(ctx->file_path, "rt"); while (f) { @@ -330,6 +407,12 @@ continue; } gf_fclose(f); + if (is_end) { + ctx->ka = 0; + } else if (ctx->ka) { + ctx->wait_update = GF_TRUE; + ctx->last_file_modif_time = gf_file_modification_time(ctx->file_path); + } return GF_FALSE; } lineno++; @@ -345,9 +428,20 @@ if (szURL[0] == '#') { nb_repeat=0; start=stop=0; - filelist_parse_arg(szURL, "repeat=", GF_FALSE, &nb_repeat, NULL); - filelist_parse_arg(szURL, "start=", GF_TRUE, NULL, &start); - filelist_parse_arg(szURL, "stop=", GF_TRUE, NULL, &stop); + do_cat = 0; + start_range=end_range=0; + + filelist_parse_arg(szURL, "repeat=", 1, &nb_repeat, NULL, NULL); + filelist_parse_arg(szURL, "start=", 2, NULL, &start, NULL); + filelist_parse_arg(szURL, "stop=", 2, NULL, &stop, NULL); + filelist_parse_arg(szURL, "cat", 0, (u32 *)&do_cat, NULL, NULL); + if (do_cat) { + filelist_parse_arg(szURL, "srange=", 3, NULL, NULL, &start_range); + filelist_parse_arg(szURL, "send=", 3, NULL, NULL, &end_range); + } + if (ctx->ka) { + filelist_parse_arg(szURL, "end", 0, (u32 *)&is_end, NULL, NULL); + } strcpy(ctx->szCom, szURL); continue; } @@ -361,6 +455,8 @@ last_found = GF_TRUE; nb_repeat=0; start=stop=0; + do_cat=0; + start_range=end_range=0; ctx->szCom[0] = 0; continue; } @@ -371,6 +467,8 @@ } nb_repeat=0; start=stop=0; + do_cat=0; + start_range=end_range=0; ctx->szCom[0] = 0; } gf_fclose(f); @@ -383,6 +481,10 @@ ctx->nb_repeat = nb_repeat; ctx->start = start; ctx->stop = stop; + ctx->do_cat = do_cat; + ctx->start_range = start_range; + ctx->end_range = end_range; + filelist_check_implicit_cat(ctx, szURL); return GF_TRUE; } @@ -435,16 +537,27 @@ if (ctx->load_next) { GF_Filter *fsrc; + u32 s_idx; char *url; char szURL[GF_MAX_PATH]; + Bool next_url_ok; + + next_url_ok = filelist_next_url(ctx, szURL); - while (gf_list_count(ctx->filter_srcs)) { - fsrc = gf_list_pop_back(ctx->filter_srcs); - gf_filter_remove_src(filter, fsrc); + if (!next_url_ok && ctx->ka) { + gf_filter_ask_rt_reschedule(filter, ctx->ka*1000); + return GF_OK; } + if (!next_url_ok || !ctx->do_cat) { + while (gf_list_count(ctx->filter_srcs)) { + fsrc = gf_list_pop_back(ctx->filter_srcs); + gf_filter_remove_src(filter, fsrc); + } + } + ctx->load_next = GF_FALSE; - if (! filelist_next_url(ctx, szURL)) { + if (! next_url_ok) { for (i=0; i<count; i++) { iopid = gf_list_get(ctx->io_pids, i); gf_filter_pid_set_eos(iopid->opid); @@ -453,37 +566,73 @@ ctx->is_eos = GF_TRUE; return GF_EOS; } + for (i=0; i<gf_list_count(ctx->io_pids); i++) { + FileListPid *an_iopid = gf_list_get(ctx->io_pids, i); + if (ctx->do_cat) { + gf_filter_pid_clear_eos(an_iopid->ipid, GF_TRUE); + filelist_start_ipid(ctx, an_iopid); + } else { + an_iopid->ipid = NULL; + } + } + s_idx = 0; url = szURL; while (url) { char *sep = strstr(url, " && "); if (sep) sep[0] = 0; - fsrc = gf_filter_connect_source(filter, url, ctx->file_path, &e); - if (e) { - if (sep) sep[0] = ' '; - GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[FileList] Failed to open file %s: %s\n", szURL, gf_error_to_string(e) )); - return GF_SERVICE_ERROR; + if (ctx->do_cat) { + char *f_url; + GF_FilterEvent evt; + fsrc = gf_list_get(ctx->filter_srcs, s_idx); + if (!fsrc) { + if (sep) sep[0] = ' '; + GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[FileList] More URL to cat than opened service!\n")); + return GF_BAD_PARAM; + } + f_url = gf_url_concatenate(ctx->file_path, url); + memset(&evt, 0, sizeof(GF_FilterEvent)); + evt.base.type = GF_FEVT_SOURCE_SWITCH; + evt.seek.source_switch = f_url ? f_url : url; + evt.seek.start_offset = ctx->start_range; + evt.seek.end_offset = ctx->end_range; + gf_filter_send_event(fsrc, &evt, GF_FALSE); + if (f_url) + gf_free(f_url); + } else { + fsrc = gf_filter_connect_source(filter, url, ctx->file_path, GF_TRUE, &e); + if (e) { + if (sep) sep[0] = ' '; + GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[FileList] Failed to open file %s: %s\n", szURL, gf_error_to_string(e) )); + return GF_SERVICE_ERROR; + } + gf_list_add(ctx->filter_srcs, fsrc); } - gf_list_add(ctx->filter_srcs, fsrc); - if (!sep) break; sep[0] = ' '; url = sep+4; } //wait for PIDs to connect GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[FileList] Switching to file %s\n", szURL)); + } //init first timestamp if (!ctx->dts_sub_plus_one) { + u32 nb_eos = 0; for (i=0; i<count; i++) { GF_FilterPacket *pck; u64 dts; iopid = gf_list_get(ctx->io_pids, i); if (!iopid->ipid) return GF_OK; pck = gf_filter_pid_get_packet(iopid->ipid); - if (!pck) return GF_OK; - + if (!pck) { + if (gf_filter_pid_is_eos(iopid->ipid)) { + nb_eos++; + continue; + } + return GF_OK; + } dts = gf_filter_pck_get_dts(pck); if (dts==GF_FILTER_NO_TS) dts=0; @@ -492,6 +641,14 @@ if (!ctx->dts_sub_plus_one) ctx->dts_sub_plus_one = dts + 1; else if (dts < ctx->dts_sub_plus_one - 1) ctx->dts_sub_plus_one = dts + 1; } + if (nb_eos) { + if (nb_eos==count) { + //force load + ctx->load_next = GF_TRUE; + return filelist_process(filter); + } + return GF_OK; + } for (i=0; i<count; i++) { iopid = gf_list_get(ctx->io_pids, i); iopid->dts_sub = ctx->dts_sub_plus_one - 1; @@ -642,11 +799,6 @@ filelist_start_ipid(ctx, iopid); } } else { - //detach all input pids and - for (i=0; i<count; i++) { - iopid = gf_list_get(ctx->io_pids, i); - iopid->ipid = NULL; - } //force load ctx->load_next = GF_TRUE; return filelist_process(filter); @@ -714,18 +866,16 @@ GF_FileListCtx *ctx = gf_filter_get_udta(filter); ctx->io_pids = gf_list_new(); + ctx->filter_srcs = gf_list_new(); + if (ctx->ka) + ctx->floop = 0; + if (!ctx->srcs || !gf_list_count(ctx->srcs)) { - GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[FileList] No inputs\n")); - //not completely correct, needs further testing -#if 0 - if (!gf_filter_connections_pending(filter)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[FileList] No source specified and no input PIDs pending, cannot instantiate\n")); - return GF_BAD_PARAM; + if (! gf_filter_is_dynamic(filter)) { + GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[FileList] No inputs\n")); } -#endif return GF_OK; } - ctx->filter_srcs = gf_list_new(); ctx->file_list = gf_list_new(); count = gf_list_count(ctx->srcs); for (i=0; i<count; i++) { @@ -814,6 +964,7 @@ { OFFS(fdur), "for source files with a single frame, sets frame duration. 0/NaN fraction means reuse source timing which is usually not set!", GF_PROP_FRACTION, "1/25", NULL, 0}, { OFFS(revert), "revert list of files (not playlist)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(timescale), "force output timescale on all pids. 0 uses the timescale of the first pid found", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(ka), "keep playlist alive (disable loop), waiting the for a new input to be added or `#end` to end playlist. The value specify the refresh rate in ms", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(fsort), "sort list of files\n" "- no: no sorting, use default directory enumeration of OS\n" @@ -862,11 +1013,14 @@ "The playlist mode is activated when opening a playlist file (extension txt or m3u).\n" "In this mode, directives can be given in a comment line, i.e. a line starting with '#' before the line with the file name.\n" "The following directives, separated with space or comma, are supported:\n" - "- repeat=N: repeats N times the content (hence played N+1)\n" - "- start=T: tries to play the file from start time T seconds (double format only)\n" - "Warning: This may not work with some files/formats not supporting seeking\n" - "- stop=T: stops source playback after T seconds (double format only)\n" - "This works on any source (implemented independently from seek support).\n" + "- repeat=N: repeats N times the content (hence played N+1).\n" + "- start=T: tries to play the file from start time T seconds (double format only). This may not work with some files/formats not supporting seeking.\n" + "- stop=T: stops source playback after T seconds (double format only). This works on any source (implemented independently from seek support).\n" + "- cat: specifies that the following entry should be concatenated to the previous source rather than opening a new source. This can optionnally specify a byte range if desired, otherwise the full file is concatenated.\n" + "- srange=T: when cat is set, indicates the start T (64 bit decimal, default 0) of the byte range from the next entry to concatenate.\n" + "- send=T: when cat is set, indicates the end T (64 bit decimal, default 0) of the byte range from the next entry to concatenate.\n" + "\n" + "Note: When sources are ISOBMFF files or segments on local storage or GF_FileIO objects, the concatenation will be automatically detected.\n" "\n" "The source lines follow the usual source syntax, see `gpac -h`.\n" "Additional pid properties can be added per source (see `gpac -h doc`), but are valid only for the current source, and reset at next source.\n"
View file
gpac-1.0.0.tar.gz/src/filters/hevcmerge.c -> gpac-1.0.1.tar.gz/src/filters/hevcmerge.c
Changed
@@ -32,7 +32,7 @@ #include <gpac/internal/media_dev.h> #include <math.h> -#ifndef GPAC_DISABLE_AV_PARSERS +#if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS) typedef struct {
View file
gpac-1.0.0.tar.gz/src/filters/hevcsplit.c -> gpac-1.0.1.tar.gz/src/filters/hevcsplit.c
Changed
@@ -31,7 +31,7 @@ #include <gpac/constants.h> #include <gpac/internal/media_dev.h> -#ifndef GPAC_DISABLE_AV_PARSERS +#if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS) typedef struct {
View file
gpac-1.0.0.tar.gz/src/filters/in_atsc.c -> gpac-1.0.1.tar.gz/src/filters/in_atsc.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2018 + * Copyright (c) Telecom ParisTech 2018-2020 * All rights reserved * * This file is part of GPAC / ATSC input filter @@ -46,7 +46,7 @@ { //options char *src, *ifce, *odir; - Bool cache, kc, sr, reorder; + Bool gcache, kc, sr, reorder; u32 buffer, timeout, stats, max_segs, tsidbg, rtimeout; s32 tunein, stsi; @@ -204,7 +204,7 @@ break; case GF_ATSC_EVT_MPD: - if (!ctx->cache) { + if (!ctx->gcache) { atscin_send_file(ctx, evt_param, finfo, evt); break; } @@ -236,7 +236,7 @@ break; case GF_ATSC_EVT_SEG: - if (!ctx->cache) { + if (!ctx->gcache) { atscin_send_file(ctx, evt_param, finfo, evt); break; } @@ -269,7 +269,7 @@ //fallthrough case GF_ATSC_EVT_INIT_SEG: - if (!ctx->cache) { + if (!ctx->gcache) { atscin_send_file(ctx, evt_param, finfo, evt); break; } @@ -382,9 +382,9 @@ if (strcmp(ctx->src, "atsc://")) return GF_BAD_PARAM; if (ctx->odir) - ctx->cache = GF_FALSE; + ctx->gcache = GF_FALSE; - if (ctx->cache) { + if (ctx->gcache) { ctx->dm = gf_filter_get_download_manager(filter); if (!ctx->dm) return GF_SERVICE_ERROR; gf_dm_set_localcache_provider(ctx->dm, atscin_local_cache_probe, ctx); @@ -423,16 +423,16 @@ { { OFFS(src), "location of source content - see filter help", GF_PROP_NAME, NULL, NULL, 0}, { OFFS(ifce), "default interface to use for multicast. If NULL, the default system interface will be used", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(cache), "indicate the files should populate GPAC HTTP cache - see filter help", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(gcache), "indicate the files should populate GPAC HTTP cache - see filter help", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tunein), "service ID to bootstrap on. 0 means tune to no service, -1 tune all services -2 means tune on first service found", GF_PROP_SINT, "-2", NULL, 0}, { OFFS(buffer), "receive buffer size to use in bytes", GF_PROP_UINT, "0x80000", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(timeout), "timeout in ms after which tunein fails", GF_PROP_UINT, "5000", NULL, 0}, { OFFS(kc), "keep corrupted file", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(sr), "skip repeated files - ignored in [-cache]() mode", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(stsi), "define one output pid per tsi/serviceID - ignored in [-cache]() mode, see filter help", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(sr), "skip repeated files - ignored in cache mode", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(stsi), "define one output pid per tsi/serviceID - ignored in cache mode, see filter help", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(stats), "log statistics at the given rate in ms (0 disables stats)", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tsidbg), "gather only objects with given TSI (debug)", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(max_segs), "maximum number of segments to keep - ignored in [-cache]() mode", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(max_segs), "maximum number of segments to keep - ignored in cache mode", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(odir), "output directory for stand-alone mode - see filter help", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(reorder), "ignore order flag in ROUTE/LCT packets, avoiding considering object done when TOI changes", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(rtimeout), "default timeout in ms to wait when gathering out-of-order packets", GF_PROP_UINT, "5000", NULL, GF_FS_ARG_HINT_EXPERT},
View file
gpac-1.0.0.tar.gz/src/filters/in_file.c -> gpac-1.0.1.tar.gz/src/filters/in_file.c
Changed
@@ -446,6 +446,23 @@ ctx->block[nb_read] = 0; if (!ctx->pid || ctx->do_reconfigure) { + //quick hack for ID3v2: if detected, increase block size to have the full id3v2 + some frames in the initial block + //to avoid relying on file extension for demux + if (!ctx->pid && (nb_read>10) + && (ctx->block[0] == 'I' && ctx->block[1] == 'D' && ctx->block[2] == '3') + ) { + u32 tag_size = ((ctx->block[9] & 0x7f) + ((ctx->block[8] & 0x7f) << 7) + ((ctx->block[7] & 0x7f) << 14) + ((ctx->block[6] & 0x7f) << 21)); + if (tag_size > nb_read) { + u32 probe_size = tag_size + ctx->block_size; + if (probe_size>ctx->file_size) + probe_size = (u32) ctx->file_size; + + ctx->block_size = probe_size; + ctx->block = gf_realloc(ctx->block, ctx->block_size+1); + nb_read += (u32) gf_fread(ctx->block + nb_read, probe_size-nb_read, ctx->file); + } + } + ctx->do_reconfigure = GF_FALSE; e = gf_filter_pid_raw_new(filter, ctx->src, ctx->src, ctx->mime, ctx->ext, ctx->block, nb_read, GF_TRUE, &ctx->pid); if (e) return e;
View file
gpac-1.0.0.tar.gz/src/filters/in_http.c -> gpac-1.0.1.tar.gz/src/filters/in_http.c
Changed
@@ -95,6 +95,7 @@ flags = GF_NETIO_SESSION_NOT_THREADED | GF_NETIO_SESSION_PERSISTENT; if (ctx->cache==GF_HTTPIN_STORE_MEM) flags |= GF_NETIO_SESSION_MEMORY_CACHE; else if (ctx->cache==GF_HTTPIN_STORE_NONE) flags |= GF_NETIO_SESSION_NOT_CACHED; + else if (ctx->cache==GF_HTTPIN_STORE_DISK_KEEP) flags |= GF_NETIO_SESSION_KEEP_CACHE; server = strstr(ctx->src, "://"); if (server) server += 3; @@ -437,7 +438,7 @@ { OFFS(block_size), "block size used to read file", GF_PROP_UINT, "100000", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(cache), "set cache mode\n" "- disk: cache to disk, discard once session is no longer used\n" - "- disk: cache to disk and keep\n" + "- keep: cache to disk and keep\n" "- mem: stores to memory, discard once session is no longer used\n" "- none: no cache", GF_PROP_UINT, "disk", "disk|keep|mem|none", GF_FS_ARG_HINT_ADVANCED}, { OFFS(range), "set byte range, as fraction", GF_PROP_FRACTION64, "0-0", NULL, 0},
View file
gpac-1.0.0.tar.gz/src/filters/in_sock.c -> gpac-1.0.1.tar.gz/src/filters/in_sock.c
Changed
@@ -220,6 +220,7 @@ return GF_FPROBE_NOT_SUPPORTED; } +#ifndef GPAC_DISABLE_STREAMING static void sockin_rtp_destructor(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck) { u32 size; @@ -229,6 +230,7 @@ data = (char *) gf_filter_pck_get_data(pck, &size); if (data) gf_free(data); } +#endif static Bool sockin_process_event(GF_Filter *filter, const GF_FilterEvent *evt) { @@ -296,7 +298,7 @@ #ifndef GPAC_DISABLE_STREAMING sock_c->rtp_reorder = gf_rtp_reorderer_new(ctx->reorder_pck, ctx->reorder_delay); #else - ctx- >is_rtp = GF_TRUE; + sock_c->is_rtp = GF_TRUE; #endif mime = "video/mp2t"; } else if (ctx->buffer[0] == 0x47) {
View file
gpac-1.0.0.tar.gz/src/filters/inspect.c -> gpac-1.0.1.tar.gz/src/filters/inspect.c
Changed
@@ -49,6 +49,8 @@ GF_M4VParser *mv124_state; GF_M4VDecSpecInfo dsi; #endif + //for analyzing + GF_BitStream *bs; Bool has_svcc; u32 nalu_size_length; @@ -73,6 +75,7 @@ INSPECT_TEST_NO=0, INSPECT_TEST_NOPROP, INSPECT_TEST_NETWORK, + INSPECT_TEST_NETX, INSPECT_TEST_ENCODE, INSPECT_TEST_ENCX, }; @@ -130,6 +133,12 @@ gf_fprintf(dump, " %s 0x%08X", _name, _val);\ } +#define DUMP_ATT_F(_name, _val) if (ctx->xml) { \ + gf_fprintf(dump, " %s=\"%f\"", _name, _val);\ + } else {\ + gf_fprintf(dump, " %s %f", _name, _val);\ + } + #ifndef GPAC_DISABLE_AV_PARSERS @@ -184,8 +193,7 @@ gf_fprintf(dump, "\""); } -GF_EXPORT -void gf_inspect_dump_nalu(FILE *dump, u8 *ptr, u32 ptr_size, Bool is_svc, HEVCState *hevc, AVCState *avc, u32 nalh_size, Bool dump_crc, Bool is_encrypted) +static void gf_inspect_dump_nalu_internal(FILE *dump, u8 *ptr, u32 ptr_size, Bool is_svc, HEVCState *hevc, AVCState *avc, u32 nalh_size, Bool dump_crc, Bool is_encrypted, PidCtx *pctx) { s32 res = 0; u8 type, nal_ref_idc; @@ -484,9 +492,17 @@ gf_fputs("\"", dump); if ((type == GF_HEVC_NALU_SEI_PREFIX) || (type == GF_HEVC_NALU_SEI_SUFFIX)) { - bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + if (pctx) { + if (!pctx->bs) + pctx->bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, ptr, ptr_size); + bs = pctx->bs; + } else { + bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + } dump_sei(dump, bs, GF_TRUE); - gf_bs_del(bs); + if (!pctx) gf_bs_del(bs); } if (type < GF_HEVC_NALU_VID_PARAM) { @@ -513,7 +529,16 @@ nal_ref_idc>>=5; gf_fprintf(dump, "code=\"%d\" type=\"", type); res = -2; - bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + + if (pctx) { + if (!pctx->bs) + pctx->bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, ptr, ptr_size); + bs = pctx->bs; + } else { + bs = gf_bs_new(ptr, ptr_size, GF_BITSTREAM_READ); + } switch (type) { case GF_AVC_NALU_NON_IDR_SLICE: gf_fputs("Non IDR slice", dump); @@ -673,7 +698,13 @@ if (res == -1) gf_fprintf(dump, " status=\"error decoding slice\""); - if (bs) gf_bs_del(bs); + if (bs && !pctx) gf_bs_del(bs); +} + +GF_EXPORT +void gf_inspect_dump_nalu(FILE *dump, u8 *ptr, u32 ptr_size, Bool is_svc, HEVCState *hevc, AVCState *avc, u32 nalh_size, Bool dump_crc, Bool is_encrypted) +{ + gf_inspect_dump_nalu_internal(dump, ptr, ptr_size, is_svc, hevc, avc, nalh_size, dump_crc, is_encrypted, NULL); } static void av1_dump_tile(FILE *dump, u32 idx, AV1Tile *tile) @@ -748,16 +779,20 @@ gf_fprintf(dump, "/>\n"); } -GF_EXPORT -void gf_inspect_dump_prores(FILE *dump, u8 *ptr, u64 frame_size, Bool dump_crc) +static void gf_inspect_dump_prores_internal(FILE *dump, u8 *ptr, u64 frame_size, Bool dump_crc, PidCtx *pctx) { - GF_BitStream *bs; GF_ProResFrameInfo prores_frame; GF_Err e; - - bs = gf_bs_new(ptr, frame_size, GF_BITSTREAM_READ); + GF_BitStream *bs; + if (pctx) { + gf_bs_reassign_buffer(pctx->bs, ptr, frame_size); + bs = pctx->bs; + } else { + bs = gf_bs_new(ptr, frame_size, GF_BITSTREAM_READ); + } e = gf_media_prores_parse_bs(bs, &prores_frame); - gf_bs_del(bs); + if (!pctx) gf_bs_del(bs); + if (e) { gf_fprintf(dump, " <!-- Error reading frame %s -->\n", gf_error_to_string(e) ); return; @@ -840,6 +875,9 @@ } gf_fprintf(dump, " numPictures=\"%d\"" , prores_frame.transfer_characteristics, prores_frame.nb_pic); + if (dump_crc) { + gf_fprintf(dump, " crc=\"%d\"" , gf_crc_32(ptr, (u32) frame_size) ); + } if (!prores_frame.load_luma_quant_matrix && !prores_frame.load_chroma_quant_matrix) { gf_fprintf(dump, "/>\n"); } else { @@ -866,6 +904,156 @@ gf_fprintf(dump, " </ProResFrame>\n"); } } + +GF_EXPORT +void gf_inspect_dump_prores(FILE *dump, u8 *ptr, u64 frame_size, Bool dump_crc) +{ + gf_inspect_dump_prores_internal(dump, ptr, frame_size, dump_crc, NULL); +} +enum { + MHAS_FILLER = 0, + MHAS_CONFIG, + MHAS_FRAME, + MHAS_SCENE_INFO, + MHAS_RES4, + MHAS_RES5, + MHAS_SYNC, + MHAS_SYNC_GAP, + MHAS_MARKER, + MHAS_CRC16, + MHAS_CRC32, + MHAS_DESCRIPTOR, + MHAS_INTERACTION, + MHAS_LOUDNESS_CRC, + MHAS_BUFFER_INFO, + MHAS_GLOBAL_CRC16, + MHAS_GLOBAL_CRC32, + MHAS_AUDIO_TRUNCATION, + MHAS_GEN_DATA, +}; +static struct { + u32 type; + const char *name; +} mhas_pack_types[] = +{ + {MHAS_FILLER, "filler"}, + {MHAS_CONFIG, "config"}, + {MHAS_FRAME, "frame"}, + {MHAS_SCENE_INFO, "scene_info"}, + {MHAS_SYNC, "sync"}, + {MHAS_SYNC_GAP, "sync_gap"}, + {MHAS_MARKER, "marker"}, + {MHAS_CRC16, "crc16"}, + {MHAS_CRC32, "crc32"}, + {MHAS_DESCRIPTOR, "descriptor"}, + {MHAS_INTERACTION, "interaction"}, + {MHAS_LOUDNESS_CRC, "loudness_drc"}, + {MHAS_BUFFER_INFO, "buffer_info"}, + {MHAS_GLOBAL_CRC16, "global_crc16"}, + {MHAS_GLOBAL_CRC32, "global_crc32"}, + {MHAS_AUDIO_TRUNCATION, "audio_truncation"}, + {MHAS_GEN_DATA, "gen_data"}, +}; + +static void dump_mha_config(FILE *dump, GF_BitStream *bs, const char *indent) +{ + u32 val; + gf_fprintf(dump, "%s<MPEGHConfig", indent); + val = gf_bs_read_int(bs, 8); + gf_fprintf(dump, " ProfileLevelIndication=\"%d\"", val); + val = gf_bs_read_int(bs, 5); + gf_fprintf(dump, " usacSamplerateIndex=\"%d\"", val); + if (val==0x1f) { + val = gf_bs_read_int(bs, 24); + gf_fprintf(dump, " usacSamplerate=\"%d\"", val); + } + val = gf_bs_read_int(bs, 3); + gf_fprintf(dump, " coreSbrFrameLengthIndex=\"%d\"", val); + gf_bs_read_int(bs, 1); + val = gf_bs_read_int(bs, 1); + gf_fprintf(dump, " receiverDelayCompensation=\"%d\"", val); + gf_fprintf(dump, "/>\n"); +} +static void gf_inspect_dump_mha_frame(FILE *dump, GF_BitStream *bs, const char *indent) +{ + u32 val; + gf_fprintf(dump, "%s<MPEGHFrame", indent); + val = gf_bs_read_int(bs, 1); + gf_fprintf(dump, " usacIndependencyFlag=\"%d\"", val); + gf_fprintf(dump, "/>\n"); +} +static void gf_inspect_dump_mhas(FILE *dump, u8 *ptr, u64 frame_size, Bool dump_crc, PidCtx *pctx) +{ + u64 gf_mpegh_escaped_value(GF_BitStream *bs, u32 nBits1, u32 nBits2, u32 nBits3); + gf_bs_reassign_buffer(pctx->bs, ptr, frame_size); + GF_BitStream *bs = pctx->bs; + + gf_fprintf(dump, " <MHASFrame>\n"); + + while (gf_bs_available(bs)) { + u32 i, count; + const char *type_name="uknown"; + u64 pos; + u32 type = (u32) gf_mpegh_escaped_value(bs, 3, 8, 8); + u64 label = gf_mpegh_escaped_value(bs, 2, 8, 32); + u64 size = gf_mpegh_escaped_value(bs, 11, 24, 24); + + count = GF_ARRAY_LENGTH(mhas_pack_types); + for (i=0; i<count; i++) { + if (mhas_pack_types[i].type==type) { + type_name = mhas_pack_types[i].name; + break; + } + } + gf_fprintf(dump, " <MHASPacket type=\"%s\" label=\""LLU"\" size=\""LLU"\"", type_name, label, size); + + pos = gf_bs_get_position(bs); + switch (type) { + case MHAS_CONFIG: + gf_fprintf(dump, ">\n"); + dump_mha_config(dump, bs, " "); + gf_fprintf(dump, " </MHASPacket>\n"); + break; + case MHAS_FRAME: + gf_fprintf(dump, ">\n"); + gf_inspect_dump_mha_frame(dump, bs, " "); + gf_fprintf(dump, " </MHASPacket>\n"); + break; + case MHAS_BUFFER_INFO: + if (gf_bs_read_int(bs, 1)) { + gf_fprintf(dump, " buffer_fullness_present=\"1\" buffer_fullness=\""LLU"\"", gf_mpegh_escaped_value(bs, 15,24,32) ); + } else { + gf_fprintf(dump, " buffer_fullness_present=\"0\""); + + } + gf_fprintf(dump, "/>\n"); + break; + case MHAS_SYNC: + gf_fprintf(dump, " sync=\"0x%02X\"/>\n", gf_bs_read_u8(bs) ); + break; + case MHAS_SYNC_GAP: + gf_fprintf(dump, " syncSpacingLength=\"0x%02" LLX_SUF "\"/>\n", gf_mpegh_escaped_value(bs, 16, 24, 24) ); + break; + case MHAS_MARKER: + case MHAS_DESCRIPTOR: + gf_fprintf(dump, " %s=\"0x", (type==MHAS_MARKER) ? "markers" : "descriptors"); + for (i=0; i<size; i++) + gf_fprintf(dump, "%02X", gf_bs_read_u8(bs) ); + gf_fprintf(dump, "\"/>\n"); + break; + default: + gf_fprintf(dump, "/>\n"); + break; + } + gf_bs_align(bs); + pos = gf_bs_get_position(bs) - pos; + if (pos < size) + gf_bs_skip_bytes(bs, size - pos); + + } + gf_fprintf(dump, " </MHASFrame>\n"); +} + #endif @@ -924,6 +1112,7 @@ gf_free(pctx->av1_state); } #endif + if (pctx->bs) gf_bs_del(pctx->bs); gf_free(pctx); } gf_list_del(ctx->src_pids); @@ -944,7 +1133,101 @@ } -static void inspect_dump_property(GF_InspectCtx *ctx, FILE *dump, u32 p4cc, const char *pname, const GF_PropertyValue *att) +static void dump_temi_loc(GF_InspectCtx *ctx, PidCtx *pctx, FILE *dump, const char *pname, const GF_PropertyValue *att) +{ + u32 val; + Double dval; + if (ctx->xml) { + gf_fprintf(dump, " <TEMILocation"); + } else { + gf_fprintf(dump, " TEMILocation"); + } + if (!pctx->bs) + pctx->bs = gf_bs_new(att->value.data.ptr, att->value.data.size, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, att->value.data.ptr, att->value.data.size); + + while (1) { + u8 achar = gf_bs_read_u8(pctx->bs); + if (!achar) break; + } + + val = atoi(pname+7); + + DUMP_ATT_D("timeline", val) + DUMP_ATT_STR("url", att->value.data.ptr) + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("announce", 1) + } + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("splicing", 1) + } + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("reload", 1) + } + gf_bs_read_int(pctx->bs, 5); + dval = gf_bs_read_double(pctx->bs); + if (dval) { + DUMP_ATT_F("splice_start", dval) + } + dval = gf_bs_read_double(pctx->bs); + if (dval) { + DUMP_ATT_F("splice_end", dval) + } + if (ctx->xml) { + gf_fprintf(dump, "/>\n"); + } else { + gf_fprintf(dump, "\n"); + } +} + +static void dump_temi_time(GF_InspectCtx *ctx, PidCtx *pctx, FILE *dump, const char *pname, const GF_PropertyValue *att) +{ + u32 val; + u64 lval; + if (ctx->xml) { + gf_fprintf(dump, " <TEMITiming"); + } else { + gf_fprintf(dump, " TEMITiming"); + } + val = atoi(pname+7); + if (!pctx->bs) + pctx->bs = gf_bs_new(att->value.data.ptr, att->value.data.size, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, att->value.data.ptr, att->value.data.size); + + DUMP_ATT_D("timeline", val) + val = gf_bs_read_u32(pctx->bs); + DUMP_ATT_D("media_timescale", val) + lval = gf_bs_read_u64(pctx->bs); + DUMP_ATT_LLU("media_timestamp", lval) + lval = gf_bs_read_u64(pctx->bs); + DUMP_ATT_LLU("media_pts", lval) + + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("reload", 1) + } + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("paused", 1) + } + if (gf_bs_read_int(pctx->bs, 1)) { + DUMP_ATT_D("discontinuity", 1) + } + val = gf_bs_read_int(pctx->bs, 1); + gf_bs_read_int(pctx->bs, 4); + + if (val) { + lval = gf_bs_read_u64(pctx->bs); + DUMP_ATT_LLU("ntp", lval) + } + if (ctx->xml) { + gf_fprintf(dump, "/>\n"); + } else { + gf_fprintf(dump, "\n"); + } +} + +static void inspect_dump_property(GF_InspectCtx *ctx, FILE *dump, u32 p4cc, const char *pname, const GF_PropertyValue *att, PidCtx *pctx) { char szDump[GF_PROP_DUMP_ARG_SIZE]; @@ -960,7 +1243,7 @@ return; case GF_PROP_PID_FILE_CACHED: case GF_PROP_PID_DURATION: - if (ctx->test==INSPECT_TEST_NETWORK) + if ((ctx->test==INSPECT_TEST_NETWORK) || (ctx->test==INSPECT_TEST_NETX)) return; break; case GF_PROP_PID_DECODER_CONFIG: @@ -979,6 +1262,12 @@ return; break; + case GF_PROP_PID_ISOM_TRACK_TEMPLATE: + case GF_PROP_PID_ISOM_MOVIE_TIME: + if (ctx->test==INSPECT_TEST_NETX) + return; + break; + case GF_PROP_PID_ISOM_TREX_TEMPLATE: case GF_PROP_PID_ISOM_STSD_TEMPLATE: //TODO once all OK: remove this test and regenerate all hashes @@ -1036,7 +1325,12 @@ if (ctx->dtype) { gf_fprintf(dump, "\t%s (%s): ", pname ? pname : gf_4cc_to_str(p4cc), gf_props_get_type_name(att->type)); } else { - gf_fprintf(dump, "\t%s: ", pname ? pname : gf_4cc_to_str(p4cc)); + if (!p4cc && !strncmp(pname, "temi_l", 6)) + dump_temi_loc(ctx, pctx, dump, pname, att); + else if (!p4cc && !strncmp(pname, "temi_t", 6)) + dump_temi_time(ctx, pctx, dump, pname, att); + else + gf_fprintf(dump, "\t%s: ", pname ? pname : gf_4cc_to_str(p4cc)); } if (att->type==GF_PROP_UINT_LIST) { @@ -1073,6 +1367,7 @@ u32 size=0; const char *data=NULL; char *str = ctx->fmt; + if (!dump) return; assert(str); if (pck) @@ -1164,7 +1459,14 @@ else if (end) gf_fprintf(dump, "frame_end"); else gf_fprintf(dump, "frame_cont"); } - else if (!strcmp(key, "sap") || !strcmp(key, "rap")) gf_fprintf(dump, "%u", gf_filter_pck_get_sap(pck) ); + else if (!strcmp(key, "sap") || !strcmp(key, "rap")) { + u32 sap = gf_filter_pck_get_sap(pck); + if (sap==GF_FILTER_SAP_4_PROL) { + gf_fprintf(dump, "4 (prol)"); + } else { + gf_fprintf(dump, "%u", sap ); + } + } else if (!strcmp(key, "ilace")) gf_fprintf(dump, "%d", gf_filter_pck_get_interlaced(pck) ); else if (!strcmp(key, "corr")) gf_fprintf(dump, "%d", gf_filter_pck_get_corrupted(pck) ); else if (!strcmp(key, "seek")) gf_fprintf(dump, "%d", gf_filter_pck_get_seek_flag(pck) ); @@ -1337,13 +1639,13 @@ { u32 h, m, s, f; Bool neg=GF_FALSE; - GF_BitStream *bs; + if (!pctx->tmcd_rate.den || !pctx->tmcd_rate.num) return; - bs = gf_bs_new(data, size, GF_BITSTREAM_READ); + gf_bs_reassign_buffer(pctx->bs, data, size); - u32 value = gf_bs_read_u32(bs); - gf_bs_seek(bs, 0); + u32 value = gf_bs_read_u32(pctx->bs); + gf_bs_seek(pctx->bs, 0); gf_fprintf(dump, "<TimeCode"); if (ctx->fftmcd || (pctx->tmcd_flags & 0x00000008)) { @@ -1394,27 +1696,25 @@ } } } else { - h = gf_bs_read_u8(bs); - neg = gf_bs_read_int(bs, 1); - m = gf_bs_read_int(bs, 7); - s = gf_bs_read_u8(bs); - f = gf_bs_read_u8(bs); + h = gf_bs_read_u8(pctx->bs); + neg = gf_bs_read_int(pctx->bs, 1); + m = gf_bs_read_int(pctx->bs, 7); + s = gf_bs_read_u8(pctx->bs); + f = gf_bs_read_u8(pctx->bs); } gf_fprintf(dump, " time=\"%s%02d:%02d:%02d:%02d\"/>\n", neg ? "-" : "", h, m, s, f); - gf_bs_del(bs); - - } static void inspect_dump_packet(GF_InspectCtx *ctx, FILE *dump, GF_FilterPacket *pck, u32 pid_idx, u64 pck_num, PidCtx *pctx) { - u32 idx=0, size; + u32 idx=0, size, sap; u64 ts; u8 dflags = 0; GF_FilterClockType ck_type; GF_FilterFrameInterface *fifce=NULL; Bool start, end; u8 *data; + if (!dump) return; if (!ctx->deep && !ctx->fmt) return; @@ -1469,7 +1769,12 @@ else DUMP_ATT_LLU("cts", ts ) DUMP_ATT_U("dur", gf_filter_pck_get_duration(pck) ) - DUMP_ATT_U("sap", gf_filter_pck_get_sap(pck) ) + sap = gf_filter_pck_get_sap(pck); + if (sap==GF_FILTER_SAP_4_PROL) { + DUMP_ATT_STR(sap, "4 (prol)"); + } else { + DUMP_ATT_U("sap", gf_filter_pck_get_sap(pck) ) + } DUMP_ATT_D("ilace", gf_filter_pck_get_interlaced(pck) ) DUMP_ATT_D("corr", gf_filter_pck_get_corrupted(pck) ) DUMP_ATT_D("seek", gf_filter_pck_get_seek_flag(pck) ) @@ -1548,7 +1853,7 @@ if (!p) break; if (idx==0) gf_fprintf(dump, "properties:\n"); - inspect_dump_property(ctx, dump, prop_4cc, prop_name, p); + inspect_dump_property(ctx, dump, prop_4cc, prop_name, p, pctx); } @@ -1586,7 +1891,7 @@ break; } else { gf_fprintf(dump, " <NALU size=\"%d\" ", nal_size); - gf_inspect_dump_nalu(dump, data, nal_size, pctx->has_svcc ? 1 : 0, pctx->hevc_state, pctx->avc_state, pctx->nalu_size_length, ctx->dump_crc, pctx->is_cenc_protected); + gf_inspect_dump_nalu_internal(dump, data, nal_size, pctx->has_svcc ? 1 : 0, pctx->hevc_state, pctx->avc_state, pctx->nalu_size_length, ctx->dump_crc, pctx->is_cenc_protected, pctx); gf_fprintf(dump, "/>\n"); } idx++; @@ -1594,12 +1899,12 @@ size -= nal_size + pctx->nalu_size_length; } } else if (pctx->av1_state) { - GF_BitStream *bs = gf_bs_new(data, size, GF_BITSTREAM_READ); + gf_bs_reassign_buffer(pctx->bs, data, size); while (size) { ObuType obu_type; u64 obu_size; u32 hdr_size; - gf_media_aom_av1_parse_obu(bs, &obu_type, &obu_size, &hdr_size, pctx->av1_state); + gf_media_aom_av1_parse_obu(pctx->bs, &obu_type, &obu_size, &hdr_size, pctx->av1_state); if (obu_size > size) { gf_fprintf(dump, " <!-- OBU is corrupted: size is %d but only %d remains -->\n", (u32) obu_size, size); @@ -1611,7 +1916,6 @@ size -= (u32)obu_size; idx++; } - gf_bs_del(bs); } else { u32 hdr, pos, fsize, i; switch (pctx->codec_id) { @@ -1658,7 +1962,16 @@ case GF_CODECID_APCS: case GF_CODECID_AP4X: case GF_CODECID_AP4H: - gf_inspect_dump_prores(dump, (char *) data, size, ctx->dump_crc); + gf_inspect_dump_prores_internal(dump, (char *) data, size, ctx->dump_crc, pctx); + break; + + case GF_CODECID_MPHA: + gf_bs_reassign_buffer(pctx->bs, data, size); + gf_inspect_dump_mha_frame(dump, pctx->bs, ""); + break; + + case GF_CODECID_MHAS: + gf_inspect_dump_mhas(dump, (char *) data, size, ctx->dump_crc, pctx); break; } @@ -1673,7 +1986,7 @@ for (i=0; i<gf_list_count(arr); i++) {\ slc = gf_list_get(arr, i);\ gf_fprintf(dump, " <NALU size=\"%d\" ", slc->size);\ - gf_inspect_dump_nalu(dump, slc->data, slc->size, _is_svc, pctx->hevc_state, pctx->avc_state, nalh_size, ctx->dump_crc, GF_FALSE);\ + gf_inspect_dump_nalu_internal(dump, slc->data, slc->size, _is_svc, pctx->hevc_state, pctx->avc_state, nalh_size, ctx->dump_crc, GF_FALSE, pctx);\ gf_fprintf(dump, "/>\n");\ }\ gf_fprintf(dump, " </%sArray>\n", name);\ @@ -1717,6 +2030,7 @@ char *elt_name = NULL; const GF_PropertyValue *p, *dsi, *dsi_enh; + if (!ctx->dump) return; if (ctx->test==INSPECT_TEST_NOPROP) return; //disconnect of src pid (not yet supported) @@ -1751,7 +2065,7 @@ const char *prop_name; p = gf_filter_pid_enum_properties(pid, &idx, &prop_4cc, &prop_name); if (!p) break; - inspect_dump_property(ctx, dump, prop_4cc, prop_name, p); + inspect_dump_property(ctx, dump, prop_4cc, prop_name, p, pctx); if (prop_name) { if (!strcmp(prop_name, "tmcd:flags")) @@ -1769,7 +2083,7 @@ const char *prop_name; p = gf_filter_pid_enum_info(pid, &idx, &prop_4cc, &prop_name); if (!p) break; - inspect_dump_property(ctx, dump, prop_4cc, prop_name, p); + inspect_dump_property(ctx, dump, prop_4cc, prop_name, p, pctx); } } @@ -1944,10 +2258,14 @@ u64 obu_size; u32 hdr_size; GF_AV1_OBUArrayEntry *obu = gf_list_get(pctx->av1_state->config->obu_array, i); - GF_BitStream *bs = gf_bs_new((const char *)obu->obu, (u32) obu->obu_length, GF_BITSTREAM_READ); - gf_media_aom_av1_parse_obu(bs, &obu_type, &obu_size, &hdr_size, pctx->av1_state); + + if (!pctx->bs) + pctx->bs = gf_bs_new((const u8 *)obu->obu, (u32) obu->obu_length, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, (const u8 *)obu->obu, (u32) obu->obu_length); + + gf_media_aom_av1_parse_obu(pctx->bs, &obu_type, &obu_size, &hdr_size, pctx->av1_state); gf_inspect_dump_obu(dump, pctx->av1_state, (char*)obu->obu, obu->obu_length, obu_type, obu_size, hdr_size, ctx->dump_crc); - gf_bs_del(bs); idx++; } #endif @@ -2019,6 +2337,31 @@ case GF_CODECID_AP4X: gf_fprintf(dump, "/>\n"); return; + case GF_CODECID_MPHA: + case GF_CODECID_MHAS: + if (dsi) { + u16 size; + if (!pctx->bs) + pctx->bs = gf_bs_new(dsi->value.data.ptr, dsi->value.data.size, GF_BITSTREAM_READ); + else + gf_bs_reassign_buffer(pctx->bs, dsi->value.data.ptr, dsi->value.data.size); + + gf_fprintf(dump, " <MPEGHAudioConfig"); + gf_fprintf(dump, " version=\"%d\"", gf_bs_read_u8(pctx->bs) ); + gf_fprintf(dump, " ProfileLevelIndication=\"%d\"", gf_bs_read_u8(pctx->bs) ); + gf_fprintf(dump, " ReferenceChannelLayout=\"%d\"", gf_bs_read_u8(pctx->bs) ); + size = gf_bs_read_u16(pctx->bs); + if (size) { + gf_fprintf(dump, ">\n"); + dump_mha_config(dump, pctx->bs, " "); + gf_fprintf(dump, " </MPEGHAudioConfig>\n"); + } else { + gf_fprintf(dump, "/>\n"); + } + gf_fprintf(dump, "/>\n"); + } + gf_fprintf(dump, "/>\n"); + return; default: GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[Inspect] bitstream analysis for codec %s not supported\n", gf_codecid_name(pctx->codec_id))); gf_fprintf(dump, "/>\n"); @@ -2144,7 +2487,9 @@ } GF_SAFEALLOC(pctx, PidCtx); if (!pctx) return GF_OUT_OF_MEM; - + if (ctx->analyze) + pctx->bs = gf_bs_new((u8 *)pctx, 0, GF_BITSTREAM_READ); + pctx->src_pid = pid; gf_filter_pid_set_udta(pid, pctx); @@ -2181,7 +2526,7 @@ pctx->idx = gf_list_find(ctx->src_pids, pctx) + 1; - if (! ctx->interleave && !pctx->tmp) { + if (! ctx->interleave && !pctx->tmp && ctx->dump) { pctx->tmp = gf_file_temp(NULL); if (ctx->xml) gf_fprintf(ctx->dump, "<PIDInspect ID=\"%d\" name=\"%s\">\n", pctx->idx, gf_filter_pid_get_name(pid) ); @@ -2251,6 +2596,7 @@ if (!ctx->log) return GF_BAD_PARAM; if (!strcmp(ctx->log, "stderr")) ctx->dump = stderr; else if (!strcmp(ctx->log, "stdout")) ctx->dump = stdout; + else if (!strcmp(ctx->log, "null")) ctx->dump = NULL; else { ctx->dump = gf_fopen(ctx->log, "wt"); if (!ctx->dump) { @@ -2262,7 +2608,7 @@ ctx->xml = GF_TRUE; } - if (ctx->xml) { + if (ctx->xml && ctx->dump) { ctx->fmt = NULL; gf_fprintf(ctx->dump, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); gf_fprintf(ctx->dump, "<GPACInspect>\n"); @@ -2290,10 +2636,11 @@ static Bool inspect_process_event(GF_Filter *filter, const GF_FilterEvent *evt) { - GF_InspectCtx *ctx = (GF_InspectCtx *) gf_filter_get_udta(filter); + PidCtx *pctx; + GF_InspectCtx *ctx = (GF_InspectCtx *) gf_filter_get_udta(filter); + if (evt->base.type != GF_FEVT_INFO_UPDATE) return GF_TRUE; if (!ctx->info) return GF_TRUE; - if (evt->base.type!=GF_FEVT_INFO_UPDATE) return GF_TRUE; - PidCtx *pctx = gf_filter_pid_get_udta(evt->base.on_pid); + pctx = gf_filter_pid_get_udta(evt->base.on_pid); pctx->dump_pid = 2; return GF_TRUE; } @@ -2301,7 +2648,7 @@ #define OFFS(_n) #_n, offsetof(GF_InspectCtx, _n) static const GF_FilterArgs InspectArgs[] = { - { OFFS(log), "set inspect log filename", GF_PROP_STRING, "stderr", "fileName, stderr or stdout", GF_FS_ARG_UPDATE}, + { OFFS(log), "set inspect log filename", GF_PROP_STRING, "stderr", "fileName, stderr, stdout or null", 0}, { OFFS(mode), "dump mode\n" "- pck: dump full packet\n" "- blk: dump packets before reconstruction\n" @@ -2327,8 +2674,9 @@ "- no: no properties skipped\n" "- noprop: all properties/info changes on pid are skipped, only packets are dumped\n" "- network: URL/path dump, cache state, file size properties skipped (used for hashing network results)\n" + "- netx: same as network but skip track duration and templates (used for hashing progressive load of fmp4)\n" "- encode: same as network plus skip decoder config (used for hashing encoding results)\n" - "- encx: same as encode and skip bitrates, media data size and co", GF_PROP_UINT, "no", "no|noprop|network|encode|encx", GF_FS_ARG_HINT_EXPERT|GF_FS_ARG_UPDATE}, + "- encx: same as encode and skip bitrates, media data size and co", GF_PROP_UINT, "no", "no|noprop|network|netx|encode|encx", GF_FS_ARG_HINT_EXPERT|GF_FS_ARG_UPDATE}, {0} };
View file
gpac-1.0.0.tar.gz/src/filters/isoffin.h -> gpac-1.0.1.tar.gz/src/filters/isoffin.h
Changed
@@ -84,6 +84,7 @@ Bool input_is_stop; u64 missing_bytes, last_size; + Bool seg_name_changed; u32 play_only_track_id; u32 play_only_first_media; Bool full_segment_flush; @@ -136,7 +137,8 @@ GF_ISOSample *sample; u64 sample_data_offset, last_valid_sample_data_offset; GF_Err last_state; - Bool sap_3, sap_4; + Bool sap_3; + GF_ISOSampleRollType sap_4_type; s32 roll; Bool has_edit_list; @@ -185,7 +187,7 @@ u8 *sai_buffer; u32 sai_alloc_size, sai_buffer_size; - Bool check_avc_ps, check_hevc_ps; + Bool check_avc_ps, check_hevc_ps, check_mhas_pl; GF_HEVCConfig *hvcc; GF_AVCConfig *avcc; GF_BitStream *nal_bs;
View file
gpac-1.0.0.tar.gz/src/filters/isoffin_load.c -> gpac-1.0.1.tar.gz/src/filters/isoffin_load.c
Changed
@@ -216,7 +216,7 @@ codec_id = GF_CODECID_RAW; audio_fmt = gf_audio_fmt_from_isobmf(m_subtype); break; - case GF_ISOM_MEDIA_TMCD: + case GF_ISOM_MEDIA_TIMECODE: codec_id = GF_CODECID_TMCD; streamtype = GF_STREAM_METADATA; break; @@ -261,7 +261,7 @@ case GF_ISOM_SUBTYPE_MP3: codec_id = GF_CODECID_MPEG_AUDIO; break; - + default: codec_id = gf_codec_id_from_isobmf(m_subtype); if (!codec_id) @@ -378,12 +378,20 @@ gf_filter_pid_set_property(pid, GF_PROP_PID_ESID, &PROP_UINT(esid)); if (gf_isom_is_track_in_root_od(read->mov, track)) { - gf_filter_pid_set_property(pid, GF_PROP_PID_IN_IOD, &PROP_BOOL(GF_TRUE)); + switch (streamtype) { + case GF_STREAM_SCENE: + case GF_STREAM_OD: + gf_filter_pid_set_property(pid, GF_PROP_PID_IN_IOD, &PROP_BOOL(GF_TRUE)); + break; + } } gf_filter_pid_set_property(pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(streamtype)); gf_filter_pid_set_property(pid, GF_PROP_PID_TIMESCALE, &PROP_UINT( gf_isom_get_media_timescale(read->mov, track) ) ); + if (!gf_sys_is_test_mode()) + gf_filter_pid_set_property(pid, GF_PROP_PID_TRACK_NUM, &PROP_UINT(track) ); + //Dolby Vision if (m_subtype == GF_ISOM_SUBTYPE_DVHE) { GF_DOVIDecoderConfigurationRecord *dovi = gf_isom_dovi_config_get(read->mov, track, 1); @@ -501,6 +509,11 @@ if (!read->mem_load_mode) { gf_filter_pid_set_property(ch->pid, GF_PROP_PID_MEDIA_DATA_SIZE, &PROP_LONGUINT(gf_isom_get_media_data_size(read->mov, track) ) ); } + //in no cache mode, depending on fetch speed we may have fetched a fragment or not, resulting in has_rap set + //always for HAS_SYNC to false + else if (gf_sys_is_test_mode() && !sample_count) { + gf_filter_pid_set_property(pid, GF_PROP_PID_HAS_SYNC, &PROP_BOOL(GF_FALSE) ); + } w = gf_isom_get_constant_sample_size(read->mov, track); @@ -521,20 +534,24 @@ gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_BRANDS, &brands); gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_MBRAND, &PROP_UINT(major_brand) ); - max_size = gf_isom_get_max_sample_size(read->mov, ch->track); - if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_FRAME_SIZE, &PROP_UINT(max_size) ); + //we cannot expose average size/dur in mem mode with fragmented files (sample_count=0) + if (sample_count) { + max_size = gf_isom_get_max_sample_size(read->mov, ch->track); + if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_FRAME_SIZE, &PROP_UINT(max_size) ); - max_size = gf_isom_get_avg_sample_size(read->mov, ch->track); - if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_AVG_FRAME_SIZE, &PROP_UINT(max_size) ); + max_size = gf_isom_get_avg_sample_size(read->mov, ch->track); + if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_AVG_FRAME_SIZE, &PROP_UINT(max_size) ); - max_size = gf_isom_get_max_sample_delta(read->mov, ch->track); - if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_TS_DELTA, &PROP_UINT(max_size) ); + max_size = gf_isom_get_max_sample_delta(read->mov, ch->track); + if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_TS_DELTA, &PROP_UINT(max_size) ); - max_size = gf_isom_get_max_sample_cts_offset(read->mov, ch->track); - if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_CTS_OFFSET, &PROP_UINT(max_size) ); + max_size = gf_isom_get_max_sample_cts_offset(read->mov, ch->track); + if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_CTS_OFFSET, &PROP_UINT(max_size) ); + + max_size = gf_isom_get_constant_sample_duration(read->mov, ch->track); + if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_CONSTANT_DURATION, &PROP_UINT(max_size) ); + } - max_size = gf_isom_get_constant_sample_duration(read->mov, ch->track); - if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_CONSTANT_DURATION, &PROP_UINT(max_size) ); u32 media_pl=0; if (streamtype==GF_STREAM_VISUAL) { @@ -605,57 +622,77 @@ char *tx3g_config_sdp = NULL; for (i=0; i<gf_isom_get_sample_description_count(read->mov, ch->track); i++) { u8 *tx3g; - char buffer[2000]; u32 l1; u32 tx3g_len, len; - gf_isom_text_get_encoded_tx3g(read->mov, ch->track, i+1, GF_RTP_TX3G_SIDX_OFFSET, &tx3g, &tx3g_len); - len = gf_base64_encode(tx3g, tx3g_len, buffer, 2000); - gf_free(tx3g); - buffer[len] = 0; - - l1 = tx3g_config_sdp ? (u32) strlen(tx3g_config_sdp) : 0; - tx3g_config_sdp = gf_realloc(tx3g_config_sdp, len+3+l1); - tx3g_config_sdp[l1] = 0; - if (i) strcat(tx3g_config_sdp, ", "); - strcat(tx3g_config_sdp, buffer); + e = gf_isom_text_get_encoded_tx3g(read->mov, ch->track, i+1, GF_RTP_TX3G_SIDX_OFFSET, &tx3g, &tx3g_len); + if (e==GF_OK) { + char buffer[2000]; + len = gf_base64_encode(tx3g, tx3g_len, buffer, 2000); + gf_free(tx3g); + buffer[len] = 0; + + l1 = tx3g_config_sdp ? (u32) strlen(tx3g_config_sdp) : 0; + tx3g_config_sdp = gf_realloc(tx3g_config_sdp, len+3+l1); + tx3g_config_sdp[l1] = 0; + if (i) strcat(tx3g_config_sdp, ", "); + strcat(tx3g_config_sdp, buffer); + } } if (tx3g_config_sdp) { gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, &PROP_STRING_NO_COPY(tx3g_config_sdp) ); } } + u32 idx=0; + while (1) { + u32 tag_len; + const u8 *tag; + u32 itag; + const char *name = gf_itags_enum_tags(&idx, &itag, NULL, NULL); + if (!name) break; + if (gf_isom_apple_get_tag(read->mov, itag, &tag, &tag_len)==GF_OK) { + switch (itag) { + case GF_ISOM_ITUNE_TRACK: + case GF_ISOM_ITUNE_TRACKNUMBER: + case GF_ISOM_ITUNE_DISK: + if (tag_len>=6) { + u16 tk_n = (tag[2]<<8)|tag[3]; + u16 tk_all = (tag[4]<<8)|tag[5]; + gf_filter_pid_set_property_str(ch->pid, name, &PROP_FRAC_INT(tk_n, tk_all) ); + } + break; + case GF_ISOM_ITUNE_GAPLESS: + case GF_ISOM_ITUNE_COMPILATION: + if (tag_len) + gf_filter_pid_set_property_str(ch->pid, name, &PROP_BOOL(tag[0]) ); + break; + case GF_ISOM_ITUNE_GENRE: + if (tag_len>=2) { + u32 genre_t = tag[0]<<8 | tag[1]; + const char *genre = gf_id3_get_genre(genre_t); + if (genre) { + gf_filter_pid_set_property_str(ch->pid, name, &PROP_STRING(genre) ); + break; + } + } + gf_filter_pid_set_property_str(ch->pid, name, &PROP_STRING(tag) ); + break; + case GF_ISOM_ITUNE_TEMPO: + if (tag_len==2) { + u32 tempo = tag[0]<<8 | tag[1]; + gf_filter_pid_set_property_str(ch->pid, name, &PROP_UINT(tempo) ); + } else { + gf_filter_pid_set_property_str(ch->pid, name, &PROP_STRING(tag) ); + } + break; - u32 tag_len; - const u8 *tag; - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_NAME, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:name", &PROP_STRING(tag) ); - - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_ARTIST, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:artist", &PROP_STRING(tag) ); - - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_ALBUM, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:album", &PROP_STRING(tag) ); - - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_COMMENT, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:comment", &PROP_STRING(tag) ); - - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_TRACK, &tag, &tag_len)==GF_OK) { - u16 tk_n = (tag[2]<<8)|tag[3]; - u16 tk_all = (tag[4]<<8)|tag[5]; - gf_filter_pid_set_info_str(ch->pid, "info:track", &PROP_FRAC_INT(tk_n, tk_all) ); - } - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_COMPOSER, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:composer", &PROP_STRING(tag) ); - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_WRITER, &tag, &tag_len)==GF_OK) - gf_filter_pid_set_info_str(ch->pid, "info:writer", &PROP_STRING(tag) ); - - if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_GENRE, &tag, &tag_len)==GF_OK) { - if (tag[0]) { - } else { - /*com->info.genre = (tag[0]<<8) | tag[1];*/ + default: + gf_filter_pid_set_property_str(ch->pid, name, &PROP_STRING(tag) ); + } } } + if (codec_id==GF_CODECID_TMCD) { u32 tmcd_flags=0, tmcd_fps_num=0, tmcd_fps_den=0, tmcd_fpt=0; gf_isom_get_tmcd_config(read->mov, track, stsd_idx, &tmcd_flags, &tmcd_fps_num, &tmcd_fps_den, &tmcd_fpt); @@ -806,7 +843,8 @@ } sr = nb_ch = nb_bps = 0; gf_isom_get_audio_info(read->mov,track, stsd_idx, &sr, &nb_ch, &nb_bps); - if (sr && nb_ch) { + //nb_ch may be set to 0 for "not applicable" (3D / object coding audio) + if (sr) { u32 d1, d2; gf_filter_pid_set_property(ch->pid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(sr)); gf_filter_pid_set_property(ch->pid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(nb_ch)); @@ -897,6 +935,20 @@ ch->check_avc_ps = GF_TRUE; else if (codec_id==GF_CODECID_HEVC) ch->check_hevc_ps = GF_TRUE; + else if (codec_id==GF_CODECID_MHAS) { + if (!dsi) { + ch->check_mhas_pl = GF_TRUE; + GF_ISOSample *samp = gf_isom_get_sample(ch->owner->mov, ch->track, 1, NULL); + if (samp) { + s32 PL = gf_mpegh_get_mhas_pl(samp->data, samp->dataLength); + if (PL>0) { + gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT((u32) PL)); + ch->check_mhas_pl = GF_FALSE; + } + gf_isom_sample_del(&samp); + } + } + } if (udesc) { gf_filter_pid_set_property_str(ch->pid, "codec_vendor", &PROP_UINT(udesc->vendor_code)); @@ -1107,8 +1159,6 @@ if (read->expart && !isom_contains_video) { GF_FilterPid *cover_pid=NULL; - gf_filter_pid_set_property(cover_pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) ); - e = gf_filter_pid_raw_new(read->filter, NULL, NULL, NULL, NULL, (char *) tag, tlen, GF_FALSE, &cover_pid); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[MP3Dmx] error setting up video pid for cover art: %s\n", gf_error_to_string(e) )); @@ -1116,6 +1166,7 @@ if (cover_pid) { u8 *out_buffer; GF_FilterPacket *dst_pck; + gf_filter_pid_set_property(cover_pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) ); gf_filter_pid_set_name(cover_pid, "CoverArt"); dst_pck = gf_filter_pck_new_alloc(cover_pid, tlen, &out_buffer); gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE); @@ -1190,6 +1241,9 @@ gf_filter_pid_set_property(pid, GF_PROP_PID_PRIMARY_ITEM, &PROP_BOOL(GF_FALSE)); } + if (!gf_sys_is_test_mode()) + gf_filter_pid_set_property(pid, GF_PROP_PID_ITEM_NUM, &PROP_UINT(item_idx) ); + gf_filter_pid_set_property_str(pid, "meta:mime", item_mime_type ? &PROP_STRING(item_mime_type) : NULL ); gf_filter_pid_set_property_str(pid, "meta:name", item_name ? &PROP_STRING(item_name) : NULL ); gf_filter_pid_set_property_str(pid, "meta:encoding", item_encoding ? &PROP_STRING(item_encoding) : NULL );
View file
gpac-1.0.0.tar.gz/src/filters/isoffin_read.c -> gpac-1.0.1.tar.gz/src/filters/isoffin_read.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2000-2018 + * Copyright (c) Telecom ParisTech 2000-2020 * All rights reserved * * This file is part of GPAC / ISOBMFF reader filter @@ -130,7 +130,13 @@ return e; } read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0; - + if (!read->frag_type && read->sigfrag) { + e = GF_BAD_PARAM; + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] sigfrag requested but file %s is not fragmented\n", szURL)); + gf_filter_setup_failure(filter, e); + return e; + } + read->time_scale = gf_isom_get_timescale(read->mov); if (!read->input_loaded && read->frag_type) read->refresh_fragmented = GF_TRUE; @@ -198,6 +204,7 @@ read->refresh_fragmented = GF_TRUE; e = GF_OK; } + read->seg_name_changed = GF_TRUE; for (i=0; i<gf_list_count(read->channels); i++) { ISOMChannel *ch = gf_list_get(read->channels, i); @@ -827,7 +834,9 @@ u64 dur=0; GF_Err e = gf_isom_get_file_offset_for_time(read->mov, evt->play.start_range, &max_offset); if (e==GF_OK) { - gf_isom_reset_tables(read->mov, GF_TRUE); + if (evt->play.start_range>0) + gf_isom_reset_tables(read->mov, GF_TRUE); + is_sidx_seek = GF_TRUE; //in case we loaded moov but not sidx, update duration if ((gf_isom_get_sidx_duration(read->mov, &dur, &ts)==GF_OK) && dur) { @@ -1163,6 +1172,8 @@ if (ch->sample) { u32 sample_dur; u8 dep_flags; + u8 *subs_buf; + u32 subs_buf_size; GF_FilterPacket *pck; if (ch->needs_pid_reconfig) { isor_update_channel_config(ch); @@ -1188,8 +1199,8 @@ if (ch->sap_3) gf_filter_pck_set_sap(pck, GF_FILTER_SAP_3); - else if (ch->sap_4) { - gf_filter_pck_set_sap(pck, GF_FILTER_SAP_4); + else if (ch->sap_4_type) { + gf_filter_pck_set_sap(pck, (ch->sap_4_type==GF_ISOM_SAMPLE_PREROLL) ? GF_FILTER_SAP_4_PROL : GF_FILTER_SAP_4); gf_filter_pck_set_roll_info(pck, ch->roll); } @@ -1213,6 +1224,12 @@ gf_filter_pck_set_crypt_flags(pck, ch->pck_encrypted ? GF_FILTER_PCK_CRYPT : 0); gf_filter_pck_set_seq_num(pck, ch->sample_num); + + subs_buf = gf_isom_sample_get_subsamples_buffer(read->mov, ch->track, ch->sample_num, &subs_buf_size); + if (subs_buf) { + gf_filter_pck_set_property(pck, GF_PROP_PCK_SUBS, &PROP_DATA_NO_COPY(subs_buf, subs_buf_size) ); + } + /**/ if (ch->cenc_state_changed && ch->pck_encrypted) { gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CENC_PATTERN, &PROP_FRAC_INT(ch->skip_byte_block, ch->crypt_byte_block) ); @@ -1250,6 +1267,14 @@ if (finfo.sidx_end) { gf_filter_pck_set_property(pck, GF_PROP_PCK_SIDX_RANGE, &PROP_FRAC64_INT(finfo.sidx_start , finfo.sidx_end)); } + + if (read->seg_name_changed) { + const GF_PropertyValue *p = gf_filter_pid_get_property(read->pid, GF_PROP_PID_URL); + read->seg_name_changed = GF_FALSE; + if (p && p->value.string) { + gf_filter_pck_set_property(pck, GF_PROP_PID_URL, &PROP_STRING(p->value.string)); + } + } } } if (ch->sender_ntp) { @@ -1316,7 +1341,7 @@ "- single: a single track is declared (highest level for scalable, tile base for tiling)", GF_PROP_UINT, "split", "split|splitx|single", GF_FS_ARG_HINT_ADVANCED}, { OFFS(alltk), "declare all tracks even disabled ones", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(frame_size), "frame size for raw audio samples (dispatches frame_size samples per packet)", GF_PROP_UINT, "1024", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(expart), "expose cover art as a dedicated video pid", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(expart), "expose cover art as a dedicated video pid", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(sigfrag), "signal fragment and segment boundaries of source on output packets", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tkid), "declare only track based on given param"
View file
gpac-1.0.0.tar.gz/src/filters/isoffin_read_ch.c -> gpac-1.0.1.tar.gz/src/filters/isoffin_read_ch.c
Changed
@@ -28,6 +28,7 @@ #ifndef GPAC_DISABLE_ISOM #include <gpac/network.h> +#include <gpac/avparse.h> void isor_reset_reader(ISOMChannel *ch) @@ -320,9 +321,9 @@ if (ch->sap_only) { Bool is_rap = gf_isom_get_sample_sync(ch->owner->mov, ch->track, ch->sample_num); if (!is_rap) { - Bool has_roll; - gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &is_rap, &has_roll, NULL); - if (has_roll) is_rap = GF_TRUE; + GF_ISOSampleRollType roll_type; + gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &is_rap, &roll_type, NULL); + if (roll_type) is_rap = GF_TRUE; } if (!is_rap) { @@ -392,7 +393,13 @@ if (sample_desc_index != ch->last_sample_desc_index) { if (!ch->owner->stsd) { - ch->needs_pid_reconfig = GF_TRUE; + //we used sample entry 1 by default to setup, if no active prev sample (edit list might trigger this) + //and new sample desc is 1, do not reconfigure + if (!ch->last_sample_desc_index && (sample_desc_index==1)) { + + } else { + ch->needs_pid_reconfig = GF_TRUE; + } } ch->last_sample_desc_index = sample_desc_index; } @@ -401,10 +408,10 @@ ch->au_duration = gf_isom_get_sample_duration(ch->owner->mov, ch->track, ch->sample_num); ch->sap_3 = GF_FALSE; - ch->sap_4 = GF_FALSE; + ch->sap_4_type = 0; ch->roll = 0; if (ch->sample) { - gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &ch->sap_3, &ch->sap_4, &ch->roll); + gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &ch->sap_3, &ch->sap_4_type, &ch->roll); } /*still seeking or not ? @@ -596,17 +603,27 @@ void isor_reader_check_config(ISOMChannel *ch) { - u32 nalu_len = 0; - u32 reset_state = 0; - if (ch->owner->analyze) return; - if (!ch->check_hevc_ps && !ch->check_avc_ps) return; + u32 nalu_len, reset_state; + if (!ch->check_hevc_ps && !ch->check_avc_ps && !ch->check_mhas_pl) return; if (!ch->sample) return; //we cannot touch the payload if encrypted !! //TODO, in CENC try to remove non-encrypted NALUs and update saiz accordingly if (ch->is_encrypted) return; + if (ch->check_mhas_pl) { + s32 PL = gf_mpegh_get_mhas_pl(ch->sample->data, ch->sample->dataLength); + if (PL>0) { + gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT((u32) PL)); + ch->check_mhas_pl = GF_FALSE; + } + return; + } + + if (ch->owner->analyze) return; + nalu_len = ch->hvcc ? ch->hvcc->nal_unit_size : (ch->avcc ? ch->avcc->nal_unit_size : 4); + reset_state = 0; if (!ch->nal_bs) ch->nal_bs = gf_bs_new(ch->sample->data, ch->sample->dataLength, GF_BITSTREAM_READ); else gf_bs_reassign_buffer(ch->nal_bs, ch->sample->data, ch->sample->dataLength);
View file
gpac-1.0.0.tar.gz/src/filters/jsfilter.c -> gpac-1.0.1.tar.gz/src/filters/jsfilter.c
Changed
@@ -40,6 +40,8 @@ #include "../scenegraph/qjs_common.h" +//to load session API +#include "../filter_core/filter_session.h" /* Currently unmapped functions @@ -103,6 +105,7 @@ JSF_FILTER_CLOCK_HINT_TIME, JSF_FILTER_CLOCK_HINT_MEDIATIME, JSF_FILTER_CONNECTIONS_PENDING, + JSF_FILTER_INAME }; enum @@ -128,7 +131,7 @@ GF_FilterArgs *args; u32 nb_args; - + Bool has_wilcard_arg; GF_FilterCapability *caps; u32 nb_caps; @@ -137,6 +140,9 @@ char *log_name; GF_List *pck_res; + + Bool unload_session_api; + Bool disable_filter; } GF_JSFilterCtx; enum @@ -262,6 +268,12 @@ { GF_FilterEvent *evt = JS_GetOpaque(val, jsf_event_class_id); if (!evt) return; + if (evt->base.type==GF_FEVT_USER) { + if (evt->user_event.event.type==GF_EVENT_SET_CAPTION) { + if (evt->user_event.event.caption.caption) + gf_free((char *) evt->user_event.event.caption.caption); + } + } gf_free(evt); } static JSClassDef jsf_event_class = { @@ -468,6 +480,7 @@ case GF_PROP_STRING: case GF_PROP_STRING_NO_COPY: case GF_PROP_NAME: + if (!new_val->value.string) return JS_NULL; return JS_NewString(ctx, new_val->value.string); case GF_PROP_VEC2: res = JS_NewObject(ctx); @@ -855,6 +868,18 @@ if (JS_ToInt32(ctx, &caps.max_audio_bit_depth, value)) return JS_EXCEPTION; gf_filter_set_session_caps(jsf->filter, &caps); break; + + case JSF_FILTER_INAME: + { + const char *val = JS_ToCString(ctx, value); + if (jsf->filter->iname) gf_free(jsf->filter->iname); + if (val) + jsf->filter->iname = gf_strdup(val); + else + jsf->filter->iname = NULL; + JS_FreeCString(ctx, val); + } + break; } return JS_UNDEFINED; } @@ -952,6 +977,9 @@ return JS_NewFloat64(ctx, dval); case JSF_FILTER_CONNECTIONS_PENDING: return JS_NewBool(ctx, gf_filter_connections_pending(jsf->filter) ); + case JSF_FILTER_INAME: + if (jsf->filter->iname) return JS_NewString(ctx, jsf->filter->iname); + return JS_NULL; } return JS_UNDEFINED; @@ -965,6 +993,7 @@ const char *def = NULL; const char *min_enum = NULL; u32 type = 0; + Bool is_wildcard=GF_FALSE; GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id); if (!jsf || !argc) return JS_EXCEPTION; @@ -973,6 +1002,12 @@ JS_FreeValue(ctx, v); if (!name) return JS_EXCEPTION; + if (!strcmp(name, "*")) { + if (jsf->has_wilcard_arg) return JS_UNDEFINED; + is_wildcard = GF_TRUE; + jsf->has_wilcard_arg = GF_TRUE; + } + v = JS_GetPropertyStr(ctx, argv[0], "desc"); if (!JS_IsUndefined(v)) desc = JS_ToCString(ctx, v); JS_FreeValue(ctx, v); @@ -986,9 +1021,13 @@ JS_ToInt32(ctx, &type, v); JS_FreeValue(ctx, v); if (!type) { - JS_FreeCString(ctx, name); - JS_FreeCString(ctx, desc); - return JS_EXCEPTION; + if (is_wildcard) { + type = GF_PROP_STRING; + } else { + JS_FreeCString(ctx, name); + JS_FreeCString(ctx, desc); + return JS_EXCEPTION; + } } v = JS_GetPropertyStr(ctx, argv[0], "def"); @@ -1032,6 +1071,7 @@ GF_PropertyValue p; GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id); if (!jsf) return JS_EXCEPTION; + jsf->disable_filter = GF_FALSE; memset(&p, 0, sizeof(GF_PropertyValue)); if (argc) { @@ -1182,6 +1222,7 @@ if (!jsf) return JS_EXCEPTION; GF_FilterPid *opid = gf_filter_pid_new(jsf->filter); if (!opid) return JS_EXCEPTION; + jsf->disable_filter = GF_FALSE; GF_SAFEALLOC(pctx, GF_JSPidCtx); if (!pctx) @@ -1366,6 +1407,7 @@ JS_ScriptTask *task; GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id); if (!jsf || !argc) return JS_EXCEPTION; + jsf->disable_filter = GF_FALSE; if (!JS_IsFunction(ctx, argv[0])) return JS_EXCEPTION; if ((argc>1) && !JS_IsObject(argv[1])) @@ -1465,6 +1507,7 @@ const char *url=NULL; const char *parent=NULL; GF_Err e=GF_OK; + Bool inherit_args = GF_FALSE; GF_JSFilterInstanceCtx *f_ctx; GF_JSFilterCtx *jsf = JS_GetOpaque(this_val, jsf_filter_class_id); if (!jsf || !argc) return JS_EXCEPTION; @@ -1477,6 +1520,9 @@ JS_FreeCString(ctx, url); return JS_EXCEPTION; } + if (argc>2) { + inherit_args = JS_ToBool(ctx, argv[2]); + } } GF_SAFEALLOC(f_ctx, GF_JSFilterInstanceCtx); if (!f_ctx) { @@ -1487,7 +1533,7 @@ f_ctx->fmode = mode; if (mode==JSF_FINST_SOURCE) { - f_ctx->filter = gf_filter_connect_source(jsf->filter, url, parent, &e); + f_ctx->filter = gf_filter_connect_source(jsf->filter, url, parent, inherit_args, &e); } else if (mode==JSF_FINST_DEST) { f_ctx->filter = gf_filter_connect_destination(jsf->filter, url, &e); } else { @@ -1542,7 +1588,6 @@ } - static const JSCFunctionListEntry jsf_filter_funcs[] = { JS_CGETSET_MAGIC_DEF("initialize", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_INITIALIZE), JS_CGETSET_MAGIC_DEF("finalize", jsf_filter_prop_get, jsf_filter_prop_set, JSF_EVT_FINALIZE), @@ -1577,6 +1622,7 @@ JS_CGETSET_MAGIC_DEF("clock_hint_us", jsf_filter_prop_get, NULL, JSF_FILTER_CLOCK_HINT_TIME), JS_CGETSET_MAGIC_DEF("clock_hint_mediatime", jsf_filter_prop_get, NULL, JSF_FILTER_CLOCK_HINT_MEDIATIME), JS_CGETSET_MAGIC_DEF("connections_pending", jsf_filter_prop_get, NULL, JSF_FILTER_CONNECTIONS_PENDING), + JS_CGETSET_MAGIC_DEF("iname", jsf_filter_prop_get, jsf_filter_prop_set, JSF_FILTER_INAME), JS_CFUNC_DEF("set_desc", 0, jsf_filter_set_desc), @@ -2525,6 +2571,7 @@ enum { JSF_EVENT_TYPE, + JSF_EVENT_NAME, /*PLAY event*/ JSF_EVENT_START_RANGE, JSF_EVENT_SPEED, @@ -2573,11 +2620,25 @@ JSF_EVENT_USER_BUTTON, JSF_EVENT_USER_HWKEY, JSF_EVENT_USER_DROPFILES, + JSF_EVENT_USER_TEXT, + JSF_EVENT_USER_MT_ROTATION, + JSF_EVENT_USER_MT_PINCH, + JSF_EVENT_USER_MT_FINGERS, + JSF_EVENT_USER_WIDTH, + JSF_EVENT_USER_HEIGHT, + JSF_EVENT_USER_SHOWTYPE, + JSF_EVENT_USER_MOVE_X, + JSF_EVENT_USER_MOVE_Y, + JSF_EVENT_USER_MOVE_RELATIVE, + JSF_EVENT_USER_MOVE_ALIGN_X, + JSF_EVENT_USER_MOVE_ALIGN_Y, + JSF_EVENT_USER_CAPTION, }; static Bool jsf_check_evt(u32 evt_type, u8 ui_type, int magic) { if (magic==JSF_EVENT_TYPE) return GF_TRUE; + if (magic==JSF_EVENT_NAME) return GF_TRUE; switch (evt_type) { case GF_FEVT_PLAY: switch (magic) { @@ -2657,6 +2718,9 @@ } break; case GF_FEVT_USER: + if (magic==JSF_EVENT_USER_TYPE) + return GF_TRUE; + switch (ui_type) { case GF_EVENT_CLICK: case GF_EVENT_MOUSEUP: @@ -2666,7 +2730,6 @@ case GF_EVENT_MOUSEMOVE: case GF_EVENT_MOUSEWHEEL: switch (magic) { - case JSF_EVENT_USER_TYPE: case JSF_EVENT_USER_MOUSE_X: case JSF_EVENT_USER_MOUSE_Y: case JSF_EVENT_USER_WHEEL: @@ -2676,12 +2739,24 @@ break; } return GF_FALSE; + case GF_EVENT_MULTITOUCH: + switch (magic) { + case JSF_EVENT_USER_MOUSE_X: + case JSF_EVENT_USER_MOUSE_Y: + case JSF_EVENT_USER_MT_ROTATION: + case JSF_EVENT_USER_MT_PINCH: + case JSF_EVENT_USER_MT_FINGERS: + return GF_TRUE; + default: + break; + } + return GF_FALSE; + case GF_EVENT_KEYUP: case GF_EVENT_KEYDOWN: case GF_EVENT_LONGKEYPRESS: case GF_EVENT_TEXTINPUT: switch (magic) { - case JSF_EVENT_USER_TYPE: case JSF_EVENT_USER_KEYCODE: case JSF_EVENT_USER_HWKEY: case JSF_EVENT_USER_DROPFILES: @@ -2690,6 +2765,47 @@ break; } return GF_FALSE; + case GF_EVENT_DROPFILE: + switch (magic) { + case JSF_EVENT_USER_DROPFILES: + return GF_TRUE; + default: + break; + } + return GF_FALSE; + case GF_EVENT_PASTE_TEXT: + case GF_EVENT_COPY_TEXT: + switch (magic) { + case JSF_EVENT_USER_TEXT: + return GF_TRUE; + default: + break; + } + return GF_FALSE; + case GF_EVENT_SIZE: + switch (magic) { + case JSF_EVENT_USER_WIDTH: + case JSF_EVENT_USER_HEIGHT: + return GF_TRUE; + default: + break; + } + return GF_FALSE; + case GF_EVENT_MOVE: + switch (magic) { + case JSF_EVENT_USER_MOVE_X: + case JSF_EVENT_USER_MOVE_Y: + case JSF_EVENT_USER_MOVE_RELATIVE: + case JSF_EVENT_USER_MOVE_ALIGN_X: + case JSF_EVENT_USER_MOVE_ALIGN_Y: + return GF_TRUE; + default: + break; + } + return GF_FALSE; + case GF_EVENT_SET_CAPTION: + if (magic==JSF_EVENT_USER_CAPTION) return GF_TRUE; + return GF_FALSE; } } return GF_FALSE; @@ -2700,10 +2816,11 @@ { GF_Err e = GF_OK; u32 ival; + Double dval; const char *str=NULL; GF_FilterEvent *evt = JS_GetOpaque(this_val, jsf_event_class_id); if (!evt) return JS_EXCEPTION; - if (!jsf_check_evt(evt->base.type, 0, magic)) + if (!jsf_check_evt(evt->base.type, evt->user_event.event.type, magic)) return JS_EXCEPTION; switch (magic) { @@ -2789,6 +2906,76 @@ case JSF_EVENT_BUFREQ_PID_ONLY: evt->buffer_req.pid_only = JS_ToBool(ctx, value); return JS_UNDEFINED; + + case JSF_EVENT_USER_TYPE: + if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION; + evt->user_event.event.type = (u8) ival; + return JS_UNDEFINED; + + + case JSF_EVENT_USER_MOUSE_X: + if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) { + if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION; + evt->user_event.event.mtouch.x = FLT2FIX(dval); + return JS_UNDEFINED; + } + return JS_ToInt32(ctx, &evt->user_event.event.mouse.x, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_MOUSE_Y: + if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) { + if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION; + evt->user_event.event.mtouch.y = FLT2FIX(dval); + return JS_UNDEFINED; + } + return JS_ToInt32(ctx, &evt->user_event.event.mouse.y, value) ? JS_EXCEPTION : JS_UNDEFINED; + + case JSF_EVENT_USER_WHEEL: + if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION; + evt->user_event.event.mouse.wheel_pos = FLT2FIX(dval); + return JS_UNDEFINED; + case JSF_EVENT_USER_BUTTON: return JS_ToInt32(ctx, &evt->user_event.event.mouse.button, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_HWKEY: return JS_ToInt32(ctx, &evt->user_event.event.key.hw_code, value) ? JS_EXCEPTION : JS_UNDEFINED; + + case JSF_EVENT_USER_MT_ROTATION: + if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION; + evt->user_event.event.mtouch.rotation = FLT2FIX(dval); + return JS_UNDEFINED; + case JSF_EVENT_USER_MT_PINCH: + if (JS_ToFloat64(ctx, &dval, value)) return JS_EXCEPTION; + evt->user_event.event.mtouch.pinch = FLT2FIX(dval); + return JS_UNDEFINED; + case JSF_EVENT_USER_MT_FINGERS: + return JS_ToInt32(ctx, &evt->user_event.event.mtouch.num_fingers, value) ? JS_EXCEPTION : JS_UNDEFINED; + + case JSF_EVENT_USER_TEXT: + { + str = JS_ToCString(ctx, value); + evt->user_event.event.clipboard.text = gf_strdup(str ? str : ""); + if (str) JS_FreeCString(ctx, str); + return JS_UNDEFINED; + } + + case JSF_EVENT_USER_WIDTH: return JS_ToInt32(ctx, &evt->user_event.event.size.width, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_HEIGHT: return JS_ToInt32(ctx, &evt->user_event.event.size.height, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_SHOWTYPE: return JS_ToInt32(ctx, &evt->user_event.event.show.show_type, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_MOVE_X: return JS_ToInt32(ctx, &evt->user_event.event.move.x, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_MOVE_Y: return JS_ToInt32(ctx, &evt->user_event.event.move.y, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_MOVE_RELATIVE: return JS_ToInt32(ctx, &evt->user_event.event.move.relative, value) ? JS_EXCEPTION : JS_UNDEFINED; + case JSF_EVENT_USER_MOVE_ALIGN_X: + case JSF_EVENT_USER_MOVE_ALIGN_Y: + if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION; + if (magic==JSF_EVENT_USER_MOVE_ALIGN_X) + evt->user_event.event.move.align_x = ival; + else + evt->user_event.event.move.align_x = ival; + return JS_UNDEFINED; + + case JSF_EVENT_USER_CAPTION: + { + str = JS_ToCString(ctx, value); + evt->user_event.event.caption.caption = gf_strdup(str ? str : ""); + if (str) JS_FreeCString(ctx, str); + return JS_UNDEFINED; + } } if (str) @@ -2804,8 +2991,42 @@ if (!jsf_check_evt(evt->base.type, evt->user_event.event.type, magic)) return JS_EXCEPTION; switch (magic) { - /*PLAY*/ case JSF_EVENT_TYPE: return JS_NewInt32(ctx, evt->base.type); + case JSF_EVENT_NAME: + if (evt->base.type==GF_FEVT_USER) { + const char *ename=NULL; + switch (evt->user_event.event.type) { + case GF_EVENT_CLICK: ename = "click"; break; + case GF_EVENT_MOUSEUP: ename = "mouseup"; break; + case GF_EVENT_MOUSEDOWN: ename = "mousedown"; break; + case GF_EVENT_MOUSEMOVE: ename = "mousemove"; break; + case GF_EVENT_MOUSEWHEEL: ename = "mousewheel"; break; + case GF_EVENT_DBLCLICK: ename = "dblclick"; break; + case GF_EVENT_MULTITOUCH: ename = "touch"; break; + case GF_EVENT_KEYUP: ename = "keyup"; break; + case GF_EVENT_KEYDOWN: ename = "keydown"; break; + case GF_EVENT_TEXTINPUT: ename = "text"; break; + case GF_EVENT_DROPFILE: ename = "dropfile"; break; + case GF_EVENT_TIMESHIFT_DEPTH: ename = "timeshift_depth"; break; + case GF_EVENT_TIMESHIFT_UPDATE: ename = "timeshift_update"; break; + case GF_EVENT_TIMESHIFT_OVERFLOW: ename = "timeshift_overflow"; break; + case GF_EVENT_TIMESHIFT_UNDERRUN: ename = "timeshift_underrun"; break; + case GF_EVENT_PASTE_TEXT: ename = "paste_text"; break; + case GF_EVENT_COPY_TEXT: ename = "copy_text"; break; + case GF_EVENT_SIZE: ename = "size"; break; + case GF_EVENT_SHOWHIDE: ename = "showhide"; break; + case GF_EVENT_MOVE: ename = "move"; break; + case GF_EVENT_SET_CAPTION: ename = "caption"; break; + case GF_EVENT_REFRESH: ename = "refresh"; break; + case GF_EVENT_QUIT: ename = "quit"; break; + case GF_EVENT_VIDEO_SETUP: ename = "video_setup"; break; + default: + ename = "unknown"; break; + } + return JS_NewString(ctx, ename); + } + return JS_NewString(ctx, gf_filter_event_name(evt->base.type)); + /*PLAY*/ case JSF_EVENT_START_RANGE: return JS_NewFloat64(ctx, evt->play.start_range); case JSF_EVENT_SPEED: return JS_NewFloat64(ctx, evt->play.speed); case JSF_EVENT_HW_BUFFER_RESET: return JS_NewBool(ctx, evt->play.hw_buffer_reset); @@ -2853,8 +3074,14 @@ return JS_NULL; #endif - case JSF_EVENT_USER_MOUSE_X: return JS_NewInt32(ctx, evt->user_event.event.mouse.x); - case JSF_EVENT_USER_MOUSE_Y: return JS_NewInt32(ctx, evt->user_event.event.mouse.y); + case JSF_EVENT_USER_MOUSE_X: + if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) + return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.x) ); + return JS_NewInt32(ctx, evt->user_event.event.mouse.x); + case JSF_EVENT_USER_MOUSE_Y: + if (evt->user_event.event.type==GF_EVENT_MULTITOUCH) + return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.y) ); + return JS_NewInt32(ctx, evt->user_event.event.mouse.y); case JSF_EVENT_USER_WHEEL: return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mouse.wheel_pos)); case JSF_EVENT_USER_BUTTON: return JS_NewInt32(ctx, evt->user_event.event.mouse.button); case JSF_EVENT_USER_HWKEY: return JS_NewInt32(ctx, evt->user_event.event.key.hw_code); @@ -2871,14 +3098,41 @@ } return files_array; } + case JSF_EVENT_USER_TEXT: + return JS_NewString(ctx, evt->user_event.event.clipboard.text ? evt->user_event.event.clipboard.text : ""); + case JSF_EVENT_USER_MT_ROTATION: + return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.rotation) ); + case JSF_EVENT_USER_MT_PINCH: + return JS_NewFloat64(ctx, FIX2FLT(evt->user_event.event.mtouch.pinch) ); + case JSF_EVENT_USER_MT_FINGERS: + return JS_NewInt32(ctx, evt->user_event.event.mtouch.num_fingers); + case JSF_EVENT_USER_WIDTH: return JS_NewInt32(ctx, evt->user_event.event.size.width); + case JSF_EVENT_USER_HEIGHT: return JS_NewInt32(ctx, evt->user_event.event.size.height); + case JSF_EVENT_USER_SHOWTYPE: return JS_NewInt32(ctx, evt->user_event.event.show.show_type); + + case JSF_EVENT_USER_MOVE_X: return JS_NewInt32(ctx, evt->user_event.event.move.x); + case JSF_EVENT_USER_MOVE_Y: return JS_NewInt32(ctx, evt->user_event.event.move.y); + case JSF_EVENT_USER_MOVE_RELATIVE: return JS_NewInt32(ctx, evt->user_event.event.move.relative); + case JSF_EVENT_USER_MOVE_ALIGN_X: return JS_NewInt32(ctx, evt->user_event.event.move.align_x); + case JSF_EVENT_USER_MOVE_ALIGN_Y: return JS_NewInt32(ctx, evt->user_event.event.move.align_y); + + case JSF_EVENT_USER_CAPTION: + return JS_NewString(ctx, evt->user_event.event.caption.caption ? evt->user_event.event.caption.caption : ""); } return JS_UNDEFINED; } +GF_FilterEvent *jsf_get_event(JSContext *ctx, JSValueConst this_val) +{ + GF_FilterEvent *evt = JS_GetOpaque(this_val, jsf_event_class_id); + return evt; +} + static const JSCFunctionListEntry jsf_event_funcs[] = { JS_CGETSET_MAGIC_DEF("type", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_TYPE), + JS_CGETSET_MAGIC_DEF("name", jsf_event_get_prop, NULL, JSF_EVENT_NAME), /*PLAY event*/ JS_CGETSET_MAGIC_DEF("start_range", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_START_RANGE), JS_CGETSET_MAGIC_DEF("speed", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_SPEED), @@ -2919,14 +3173,31 @@ JS_CGETSET_MAGIC_DEF("min_playout_us", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_MIN_PLAYOUT_US), JS_CGETSET_MAGIC_DEF("pid_only", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_BUFREQ_PID_ONLY), /*ui events*/ - JS_CGETSET_MAGIC_DEF("ui_type", jsf_event_get_prop, NULL, JSF_EVENT_USER_TYPE), - JS_CGETSET_MAGIC_DEF("keycode", jsf_event_get_prop, NULL, JSF_EVENT_USER_KEYCODE), - JS_CGETSET_MAGIC_DEF("mouse_x", jsf_event_get_prop, NULL, JSF_EVENT_USER_MOUSE_X), - JS_CGETSET_MAGIC_DEF("mouse_y", jsf_event_get_prop, NULL, JSF_EVENT_USER_MOUSE_Y), - JS_CGETSET_MAGIC_DEF("wheel", jsf_event_get_prop, NULL, JSF_EVENT_USER_WHEEL), - JS_CGETSET_MAGIC_DEF("button", jsf_event_get_prop, NULL, JSF_EVENT_USER_BUTTON), - JS_CGETSET_MAGIC_DEF("hwkey", jsf_event_get_prop, NULL, JSF_EVENT_USER_HWKEY), + JS_CGETSET_MAGIC_DEF("ui_type", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_TYPE), + JS_CGETSET_MAGIC_DEF("keycode", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_KEYCODE), + JS_CGETSET_MAGIC_DEF("mouse_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_X), + JS_CGETSET_MAGIC_DEF("mouse_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_Y), + JS_CGETSET_MAGIC_DEF("wheel", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_WHEEL), + JS_CGETSET_MAGIC_DEF("button", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_BUTTON), + JS_CGETSET_MAGIC_DEF("hwkey", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_HWKEY), JS_CGETSET_MAGIC_DEF("dropfiles", jsf_event_get_prop, NULL, JSF_EVENT_USER_DROPFILES), + JS_CGETSET_MAGIC_DEF("clipboard", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_TEXT), + + JS_CGETSET_MAGIC_DEF("mt_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_X), + JS_CGETSET_MAGIC_DEF("mt_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOUSE_Y), + JS_CGETSET_MAGIC_DEF("mt_rotate", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_ROTATION), + JS_CGETSET_MAGIC_DEF("mt_pinch", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_PINCH), + JS_CGETSET_MAGIC_DEF("mt_fingers", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MT_FINGERS), + + JS_CGETSET_MAGIC_DEF("width", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_WIDTH), + JS_CGETSET_MAGIC_DEF("height", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_HEIGHT), + JS_CGETSET_MAGIC_DEF("showtype", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_SHOWTYPE), + JS_CGETSET_MAGIC_DEF("move_x", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_X), + JS_CGETSET_MAGIC_DEF("move_y", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_Y), + JS_CGETSET_MAGIC_DEF("move_relative", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_RELATIVE), + JS_CGETSET_MAGIC_DEF("move_alignx", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_ALIGN_X), + JS_CGETSET_MAGIC_DEF("move_aligny", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_MOVE_ALIGN_Y), + JS_CGETSET_MAGIC_DEF("caption", jsf_event_get_prop, jsf_event_set_prop, JSF_EVENT_USER_CAPTION), }; static JSValue jsf_event_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) @@ -3579,49 +3850,16 @@ return e; } - -static GF_Err jsfilter_initialize(GF_Filter *filter) +void js_load_constants(JSContext *ctx, JSValue global_obj) { - u8 *buf; - u32 buf_len; - u32 flags = JS_EVAL_TYPE_GLOBAL; - JSValue ret; - JSValue global_obj, val, args; - u32 i, nb_args; - JSRuntime *rt; - GF_JSFilterCtx *jsf = gf_filter_get_udta(filter); - - jsf->filter = filter; - jsf->pids = gf_list_new(); - jsf->pck_res = gf_list_new(); - jsf->log_name = gf_strdup("JSF"); - - if (!jsf->js) { - GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Missing script file\n")); - return GF_BAD_PARAM; - } - if (!gf_file_exists(jsf->js)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Script file %s does not exist\n", jsf->js)); - return GF_BAD_PARAM; - } - jsf->filter_obj = JS_UNDEFINED; - - jsf->ctx = gf_js_create_context(); - if (!jsf->ctx) { - GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Failed to load QuickJS context\n")); - return GF_IO_ERR; - } - JS_SetContextOpaque(jsf->ctx, jsf); - rt = JS_GetRuntime(jsf->ctx); - - global_obj = JS_GetGlobalObject(jsf->ctx); + JSValue val; - val = JS_NewObject(jsf->ctx); - JS_SetPropertyStr(jsf->ctx, val, "log", JS_NewCFunction(jsf->ctx, js_print, "log", 1)); - JS_SetPropertyStr(jsf->ctx, global_obj, "console", val); + val = JS_NewObject(ctx); + JS_SetPropertyStr(ctx, val, "log", JS_NewCFunction(ctx, js_print, "log", 1)); + JS_SetPropertyStr(ctx, global_obj, "console", val); #define DEF_CONST( _val ) \ - JS_SetPropertyStr(jsf->ctx, global_obj, #_val, JS_NewInt32(jsf->ctx, _val)); + JS_SetPropertyStr(ctx, global_obj, #_val, JS_NewInt32(ctx, _val)); DEF_CONST(GF_LOG_ERROR) DEF_CONST(GF_LOG_WARNING) @@ -3656,7 +3894,7 @@ DEF_CONST(GF_PROP_STRING_LIST) DEF_CONST(GF_PROP_UINT_LIST) - + DEF_CONST(GF_FEVT_PLAY) DEF_CONST(GF_FEVT_SET_SPEED) DEF_CONST(GF_FEVT_STOP) @@ -3689,6 +3927,7 @@ DEF_CONST(GF_FILTER_SAP_2) DEF_CONST(GF_FILTER_SAP_3) DEF_CONST(GF_FILTER_SAP_4) + DEF_CONST(GF_FILTER_SAP_4_PROL) DEF_CONST(GF_EOS); DEF_CONST(GF_OK) @@ -3744,25 +3983,78 @@ DEF_CONST(GF_EVENT_MOUSEMOVE) DEF_CONST(GF_EVENT_MOUSEWHEEL) DEF_CONST(GF_EVENT_DBLCLICK) + DEF_CONST(GF_EVENT_MULTITOUCH) DEF_CONST(GF_EVENT_KEYUP) DEF_CONST(GF_EVENT_KEYDOWN) DEF_CONST(GF_EVENT_TEXTINPUT) DEF_CONST(GF_EVENT_DROPFILE) - DEF_CONST(GF_EVENT_QUALITY_SWITCHED) DEF_CONST(GF_EVENT_TIMESHIFT_DEPTH) DEF_CONST(GF_EVENT_TIMESHIFT_UPDATE) DEF_CONST(GF_EVENT_TIMESHIFT_OVERFLOW) DEF_CONST(GF_EVENT_TIMESHIFT_UNDERRUN) + DEF_CONST(GF_EVENT_PASTE_TEXT) + DEF_CONST(GF_EVENT_COPY_TEXT) + DEF_CONST(GF_EVENT_SIZE) + DEF_CONST(GF_EVENT_SHOWHIDE) + DEF_CONST(GF_EVENT_MOVE) + DEF_CONST(GF_EVENT_SET_CAPTION) + DEF_CONST(GF_EVENT_REFRESH) DEF_CONST(GF_EVENT_QUIT) - args = JS_NewArray(jsf->ctx); - nb_args = gf_sys_get_argc(); - for (i=0; i<nb_args; i++) { - JS_SetPropertyUint32(jsf->ctx, args, i, JS_NewString(jsf->ctx, gf_sys_get_arg(i))); - } - JS_SetPropertyStr(jsf->ctx, global_obj, "args", args); - JS_SetPropertyStr(jsf->ctx, global_obj, "print", JS_NewCFunction(jsf->ctx, js_print, "print", 1)); - JS_SetPropertyStr(jsf->ctx, global_obj, "alert", JS_NewCFunction(jsf->ctx, js_print, "alert", 1)); + JS_SetPropertyStr(ctx, global_obj, "print", JS_NewCFunction(ctx, js_print, "print", 1)); + JS_SetPropertyStr(ctx, global_obj, "alert", JS_NewCFunction(ctx, js_print, "alert", 1)); + + + //initialize filter event class + JS_NewClassID(&jsf_event_class_id); + JS_NewClass(JS_GetRuntime(ctx), jsf_event_class_id, &jsf_event_class); + JSValue evt_proto = JS_NewObjectClass(ctx, jsf_event_class_id); + JS_SetPropertyFunctionList(ctx, evt_proto, jsf_event_funcs, countof(jsf_event_funcs)); + JS_SetClassProto(ctx, jsf_event_class_id, evt_proto); + + JSValue evt_ctor = JS_NewCFunction2(ctx, jsf_event_constructor, "FilterEvent", 1, JS_CFUNC_constructor, 0); + JS_SetPropertyStr(ctx, global_obj, "FilterEvent", evt_ctor); + +} + +static GF_Err jsfilter_initialize(GF_Filter *filter) +{ + u8 *buf; + u32 buf_len; + u32 flags = JS_EVAL_TYPE_GLOBAL; + JSValue ret; + JSValue global_obj; + u32 i; + JSRuntime *rt; + GF_JSFilterCtx *jsf = gf_filter_get_udta(filter); + + jsf->filter = filter; + jsf->pids = gf_list_new(); + jsf->pck_res = gf_list_new(); + jsf->log_name = gf_strdup("JSF"); + + if (!jsf->js) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Missing script file\n")); + return GF_BAD_PARAM; + } + if (!gf_file_exists(jsf->js)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Script file %s does not exist\n", jsf->js)); + return GF_BAD_PARAM; + } + jsf->filter_obj = JS_UNDEFINED; + + jsf->ctx = gf_js_create_context(); + if (!jsf->ctx) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Failed to load QuickJS context\n")); + return GF_IO_ERR; + } + JS_SetContextOpaque(jsf->ctx, jsf); + rt = JS_GetRuntime(jsf->ctx); + + global_obj = JS_GetGlobalObject(jsf->ctx); + + js_load_constants(jsf->ctx, global_obj); + //initialize filter class and create a single filter object in global scope JS_NewClassID(&jsf_filter_class_id); @@ -3787,16 +4079,6 @@ JS_SetPropertyFunctionList(jsf->ctx, pid_proto, jsf_pid_funcs, countof(jsf_pid_funcs)); JS_SetClassProto(jsf->ctx, jsf_pid_class_id, pid_proto); - //initialize filter event class - JS_NewClassID(&jsf_event_class_id); - JS_NewClass(rt, jsf_event_class_id, &jsf_event_class); - JSValue evt_proto = JS_NewObjectClass(jsf->ctx, jsf_event_class_id); - JS_SetPropertyFunctionList(jsf->ctx, evt_proto, jsf_event_funcs, countof(jsf_event_funcs)); - JS_SetClassProto(jsf->ctx, jsf_event_class_id, evt_proto); - - JSValue evt_ctor = JS_NewCFunction2(jsf->ctx, jsf_event_constructor, "FilterEvent", 1, JS_CFUNC_constructor, 0); - JS_SetPropertyStr(jsf->ctx, global_obj, "FilterEvent", evt_ctor); - //initialize filter event class JS_NewClassID(&jsf_pck_class_id); @@ -3816,19 +4098,33 @@ return e; } + if (strstr(buf, "session.")) { + GF_Err gf_fs_load_js_api(JSContext *c, GF_FilterSession *fs); +// GF_FilterSession *fs = sjs->compositor->filter->session; + + e = gf_fs_load_js_api(jsf->ctx, filter->session); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JSF] Error loading session API: %s\n", gf_error_to_string(e) )); + return e; + } + jsf->unload_session_api = GF_TRUE; + } + for (i=0; i<JSF_EVT_LAST_DEFINED; i++) { jsf->funcs[i] = JS_UNDEFINED; } + if (!gf_opts_get_bool("core", "no-js-mods") && JS_DetectModule((char *)buf, buf_len)) { //init modules + qjs_module_init_gpaccore(jsf->ctx); qjs_module_init_xhr(jsf->ctx); qjs_module_init_evg(jsf->ctx); qjs_module_init_storage(jsf->ctx); qjs_module_init_webgl(jsf->ctx); flags = JS_EVAL_TYPE_MODULE; } - + jsf->disable_filter = GF_TRUE; ret = JS_Eval(jsf->ctx, (char *)buf, buf_len, jsf->js, flags); gf_free(buf); @@ -3839,7 +4135,6 @@ return GF_BAD_PARAM; } JS_FreeValue(jsf->ctx, ret); - return GF_OK; } @@ -3871,6 +4166,10 @@ } JS_SetOpaque(jsf->filter_obj, NULL); + + if (jsf->unload_session_api) + gf_fs_unload_script(filter->session, jsf->ctx); + gf_js_delete_context(jsf->ctx); while (gf_list_count(jsf->pids)) { @@ -3902,6 +4201,7 @@ } gf_free(jsf->args); } + if (jsf->caps) gf_free(jsf->caps); } @@ -3932,10 +4232,21 @@ JS_FreeValue(jsf->ctx, ret); } jsf->initialized = GF_TRUE; + //filter object not used (no new_pid, post_task or set_cap), disable it + if (jsf->disable_filter) { + JSAtom prop; + JSValue global_obj = JS_GetGlobalObject(jsf->ctx); + prop = JS_NewAtom(jsf->ctx, "filter"); + JS_DeleteProperty(jsf->ctx, global_obj, prop, 0); + JS_FreeValue(jsf->ctx, global_obj); + JS_FreeAtom(jsf->ctx, prop); + filter->disabled = GF_TRUE; + jsf->filter_obj = JS_UNDEFINED; + } gf_js_lock(jsf->ctx, GF_FALSE); return e; } - if (!arg_name) + if (!arg_name || (jsf->initialized && jsf->disable_filter)) return GF_OK; for (i=0; i<jsf->nb_args; i++) { @@ -3944,7 +4255,7 @@ break; } } - if (!the_arg) return GF_OK; + if (!the_arg && !jsf->has_wilcard_arg) return GF_OK; gf_js_lock(jsf->ctx, GF_TRUE); @@ -3973,6 +4284,13 @@ return e; } +JSValue js_init_evt_obj(JSContext *ctx, const GF_FilterEvent *evt) +{ + JSValue v = JS_NewObjectClass(ctx, jsf_event_class_id); + JS_SetOpaque(v, (void *) evt); + return v; +} + static Bool jsfilter_process_event(GF_Filter *filter, const GF_FilterEvent *evt) { JSValue argv[2]; @@ -3991,8 +4309,8 @@ } else { argv[0] = JS_NULL; } - argv[1] = JS_NewObjectClass(jsf->ctx, jsf_event_class_id); - JS_SetOpaque(argv[1], (void *) evt); + argv[1] = js_init_evt_obj(jsf->ctx, evt); + ret = JS_Call(jsf->ctx, jsf->funcs[JSF_EVT_PROCESS_EVENT], jsf->filter_obj, 2, argv); if (JS_IsException(ret)) { GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[%s] Error processing event\n", jsf->log_name));
View file
gpac-1.0.0.tar.gz/src/filters/load_bt_xmt.c -> gpac-1.0.1.tar.gz/src/filters/load_bt_xmt.c
Changed
@@ -862,8 +862,6 @@ return NULL; } -#endif //defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH) - static const GF_FilterCapability CTXLoadCaps[] = { CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE), @@ -898,6 +896,8 @@ .probe_data = ctxload_probe_data, }; +#endif //defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH) + const GF_FilterRegister *ctxload_register(GF_FilterSession *session) {
View file
gpac-1.0.0.tar.gz/src/filters/load_svg.c -> gpac-1.0.1.tar.gz/src/filters/load_svg.c
Changed
@@ -412,7 +412,7 @@ svgin->loader.scene_graph = svgin->scene->graph; svgin->loader.localPath = gf_get_default_cache_directory(); - /*Warning: svgin->loader.type may be overriden in attach stream */ + /*Warning: svgin->loader.type may be overridden in attach stream */ svgin->loader.type = GF_SM_LOAD_SVG; svgin->loader.flags = GF_SM_LOAD_FOR_PLAYBACK;
View file
gpac-1.0.0.tar.gz/src/filters/load_text.c -> gpac-1.0.1.tar.gz/src/filters/load_text.c
Changed
@@ -92,14 +92,12 @@ u64 last_sample_duration; //TTML state is the same as ttxt plus the timescale and start (webvtt) for cts compute u32 txml_timescale; + u32 current_tt_interval; //TTML state GF_XMLNode *root_working_copy, *div_node, *sample_list_node; GF_DOMParser *parser_working_copy; Bool non_compliant_ttml; - u32 nb_p_found; - - #ifndef GPAC_DISABLE_SWF_IMPORT //SWF text @@ -108,8 +106,14 @@ #endif + GF_List *intervals; }; +typedef struct +{ + s64 begin, end; +} TTMLInterval; + enum { @@ -461,7 +465,7 @@ u8 *dsi; GF_TextSampleDescriptor *sd; - ctx->src = gf_fopen(ctx->file_name, "rt"); + ctx->src = gf_fopen(ctx->file_name, "rb"); if (!ctx->src) return GF_URL_ERROR; file_size = (u32) gf_fsize(ctx->src); @@ -618,6 +622,7 @@ } } ctx->style.style_flags = 0; + ctx->style.text_color = 0xFFFFFFFF; ctx->style.startCharOffset = ctx->style.endCharOffset = 0; if (txt_line) { if (ctx->prev_end && (ctx->start != ctx->prev_end) && (ctx->state<=2)) { @@ -975,7 +980,7 @@ Bool is_srt; char *ext; - ctx->src = gf_fopen(ctx->file_name, "rt"); + ctx->src = gf_fopen(ctx->file_name, "rb"); if (!ctx->src) return GF_URL_ERROR; file_size = (u32) gf_fsize(ctx->src); @@ -1096,7 +1101,7 @@ return str; } -static void GF_TXTIN_MODE_ebu_ttd_remove_samples(GF_XMLNode *root, GF_XMLNode **sample_list_node) +static void ebu_ttd_remove_samples(GF_XMLNode *root, GF_XMLNode **sample_list_node) { u32 idx = 0; GF_XMLNode *node = NULL; @@ -1125,6 +1130,142 @@ #define TTML_NAMESPACE "http://www.w3.org/ns/ttml" +static s64 ttml_get_timestamp(const char *value) +{ + u32 h, m, s, ms; + s64 ts = -1; + if (sscanf(value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(value, "%u:%u:%u", &h, &m, &s) == 3) { + ts = (h*3600 + m*60+s)*1000; + } + return ts; +} + +static GF_Err ttml_push_interval(GF_TXTIn *ctx, s64 begin, s64 end) +{ + u32 i; + TTMLInterval *interval; + if (begin==-1) return GF_OK; + if (end==-1) return GF_OK; + + if (end < begin) { + GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] invalid timings: \"begin\"="LLD" , \"end\"="LLD". Abort.\n", begin, end)); + return GF_NON_COMPLIANT_BITSTREAM; + } + + interval = NULL; + for (i=0; i<gf_list_count(ctx->intervals); i++) { + interval = gf_list_get(ctx->intervals, i); + //contained, do nothing + if ((begin>=interval->begin) && (end<=interval->end)) + return GF_OK; + //not overlapping + if ((end < interval->begin) || (begin > interval->end)) + continue; + + //new interval starts before current and end after, remove current and push extended interval + if ((begin < interval->end) && (end > interval->end)) { + if (begin>interval->begin) + begin = interval->begin; + gf_list_rem(ctx->intervals, i); + gf_free(interval); + return ttml_push_interval(ctx, begin, end); + } + //new interval starts before current and end before, remove current and push rewinded + if ((begin < interval->end) && (end <= interval->end)) { + end = interval->end; + if (begin>interval->begin) + begin = interval->begin; + gf_list_rem(ctx->intervals, i); + gf_free(interval); + return ttml_push_interval(ctx, begin, end); + } + } + //need a new interval + GF_SAFEALLOC(interval, TTMLInterval); + interval->begin = begin; + interval->end = end; + + for (i=0; i<gf_list_count(ctx->intervals); i++) { + TTMLInterval *an_interval = gf_list_get(ctx->intervals, i); + if (an_interval->begin > interval->begin) { + return gf_list_insert(ctx->intervals, interval, i); + } + } + return gf_list_add(ctx->intervals, interval); +} + +static void ttml_reset_intervals(GF_TXTIn *ctx) +{ + while (gf_list_count(ctx->intervals)) { + TTMLInterval *ival = gf_list_pop_back(ctx->intervals); + gf_free(ival); + } +} + +static GF_Err ttml_setup_intervals(GF_TXTIn *ctx) +{ + u32 k; + GF_Err e; + GF_XMLNode *root; + + if (!ctx->intervals) + ctx->intervals = gf_list_new(); + else + ttml_reset_intervals(ctx); + + root = gf_xml_dom_get_root(ctx->parser); + + for (k=0; k<ctx->nb_children; k++) { + u32 p_idx; + GF_XMLAttribute *p_att; + GF_XMLNode *p_node; + s64 begin=-1, end=-1; + GF_XMLNode *adiv_child = (GF_XMLNode*)gf_list_get(ctx->div_node->content, k); + if (adiv_child->type) continue; + e = gf_xml_get_element_check_namespace(adiv_child, "p", root->ns); + if (e) continue; + + p_idx = 0; + while ( (p_att = (GF_XMLAttribute*)gf_list_enum(adiv_child->attributes, &p_idx))) { + if (!strcmp(p_att->name, "begin")) { + begin = ttml_get_timestamp(p_att->value); + } + if (!strcmp(p_att->name, "end")) { + end = ttml_get_timestamp(p_att->value); + } + } + e = ttml_push_interval(ctx, begin, end); + if (e) return e; + + p_idx = 0; + while ( (p_node = (GF_XMLNode*)gf_list_enum(adiv_child->content, &p_idx))) { + s64 s_begin=-1, s_end=-1; + e = gf_xml_get_element_check_namespace(p_node, "span", root->ns); + if (e) continue; + + u32 span_idx = 0; + GF_XMLAttribute *span_att; + while ( (span_att = (GF_XMLAttribute*)gf_list_enum(p_node->attributes, &span_idx))) { + if (!strcmp(span_att->name, "begin")) { + s_begin = ttml_get_timestamp(span_att->value); + } else if (!strcmp(span_att->name, "end")) { + s_end = ttml_get_timestamp(span_att->value); + } + } + e = ttml_push_interval(ctx, s_begin, s_end); + if (e) return e; + } + } + + for (k=0; k<gf_list_count(ctx->intervals); k++) { + TTMLInterval *ival = gf_list_get(ctx->intervals, k); + GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[TTML EBU-TTD] Interval %d: "LLU"-"LLU"\n", k+1, ival->begin, ival->end)); + } + + return GF_OK; +} static GF_Err gf_text_ttml_setup(GF_Filter *filter, GF_TXTIn *ctx) { GF_Err e; @@ -1178,7 +1319,7 @@ ctx->non_compliant_ttml = GF_TRUE; return GF_NON_COMPLIANT_BITSTREAM; } - } else if (!strcmp(att->name, "xml:lang")) { + } else if (!strcmp(att->name, "xml:lang") && att->value && strlen(att->value)) { lang = att->value; } } @@ -1252,10 +1393,13 @@ assert(ctx->root_working_copy); /*remove all the sample entries (instances in body) entries from the working copy, we will add each sample in this clone DOM to create full XML of each sample*/ - GF_TXTIN_MODE_ebu_ttd_remove_samples(ctx->root_working_copy, &ctx->sample_list_node); + ebu_ttd_remove_samples(ctx->root_working_copy, &ctx->sample_list_node); + if (!ctx->sample_list_node) { + return GF_NON_COMPLIANT_BITSTREAM; + } ctx->nb_children = gf_list_count(ctx->div_node->content); - ctx->cur_child_idx = 0; + ctx->current_tt_interval = 0; ctx->last_sample_duration = 0; ctx->end = 0; @@ -1263,14 +1407,34 @@ txtin_probe_duration(ctx); - return GF_OK; + return ttml_setup_intervals(ctx); +} + +static Bool ttml_check_range(TTMLInterval *interval, s64 ts_begin, s64 ts_end) +{ + //if in current interval, push node + if ((ts_begin != -1) && (ts_end != -1) && ((ts_begin>=interval->begin) && (ts_end<=interval->end)) + ) { + return GF_TRUE; + } + //begin not set, end set: in range if end less than interval end range + else if ((ts_begin==-1) && (ts_end != -1) && (ts_end<=interval->end)) { + return GF_TRUE; + } + //begin set, end not set: in range if begin greater than interval begin range + else if ((ts_begin!=-1) && (ts_end==-1) && (ts_begin>=interval->begin)) { + return GF_TRUE; + } + return GF_FALSE; } static GF_Err gf_text_process_ttml(GF_Filter *filter, GF_TXTIn *ctx) { GF_Err e; GF_XMLNode *root; + u32 i; char *samp_text=NULL; + TTMLInterval *interval; if (!ctx->is_setup) return gf_text_ttml_setup(filter, ctx); if (ctx->non_compliant_ttml || !ctx->opid) return GF_NOT_SUPPORTED; @@ -1279,18 +1443,28 @@ if (ctx->seek_state==1) { ctx->seek_state = 2; - ctx->cur_child_idx = 0; + ctx->current_tt_interval = 0; } + interval = gf_list_get(ctx->intervals, ctx->current_tt_interval); + if (!interval) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[TTML EBU-TTD] last_sample_duration="LLU", last_sample_end="LLU"\n", ctx->last_sample_duration, ctx->end)); + + gf_filter_pid_set_info_str( ctx->opid, "ttxt:last_dur", &PROP_UINT((u32) ctx->last_sample_duration) ); + gf_filter_pid_set_eos(ctx->opid); + return GF_EOS; + } + ctx->current_tt_interval++; + root = gf_xml_dom_get_root(ctx->parser); - for (; ctx->cur_child_idx < ctx->nb_children; ctx->cur_child_idx++) { + for (i=0; i < ctx->nb_children; i++) { GF_XMLNode *p_node; GF_XMLAttribute *p_att; - u32 p_idx = 0, h, m, s, ms; + u32 p_idx = 0; s64 ts_begin = -1, ts_end = -1; - - GF_XMLNode *div_child = (GF_XMLNode*)gf_list_get(ctx->div_node->content, ctx->cur_child_idx); + Bool in_range; + GF_XMLNode *div_child = (GF_XMLNode*)gf_list_get(ctx->div_node->content, i); if (div_child->type) { continue; } @@ -1300,162 +1474,136 @@ continue; } + //sample is either in the <p> ... + p_idx = 0; while ( (p_att = (GF_XMLAttribute*)gf_list_enum(div_child->attributes, &p_idx))) { - if (!strcmp(p_att->name, "begin")) { if (ts_begin != -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"begin\" attribute. Abort.\n")); e = GF_NON_COMPLIANT_BITSTREAM; goto exit; } - if (sscanf(p_att->value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts_begin = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(p_att->value, "%u:%u:%u", &h, &m, &s) == 3) { - ts_begin = (h*3600 + m*60+s)*1000; - } + ts_begin = ttml_get_timestamp(p_att->value); } else if (!strcmp(p_att->name, "end")) { if (ts_end != -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"end\" attribute. Abort.\n")); e = GF_NON_COMPLIANT_BITSTREAM; goto exit; } - if (sscanf(p_att->value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts_end = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(p_att->value, "%u:%u:%u", &h, &m, &s) == 3) { - ts_end = (h*3600 + m*60+s)*1000; - } - } - if ((ts_begin != -1) && (ts_end != -1) && !samp_text && ctx->sample_list_node) { - e = gf_xml_dom_append_child(ctx->sample_list_node, div_child); - assert(e == GF_OK); - samp_text = gf_xml_dom_serialize((GF_XMLNode*)ctx->root_working_copy, GF_FALSE); - e = gf_xml_dom_rem_child(ctx->sample_list_node, div_child); - assert(e == GF_OK); + ts_end = ttml_get_timestamp(p_att->value); } } + in_range = ttml_check_range(interval, ts_begin, ts_end); + if (in_range) { + e = gf_xml_dom_append_child(ctx->sample_list_node, div_child); + assert(e == GF_OK); + } + //or under a <span> p_idx = 0; while ( (p_node = (GF_XMLNode*)gf_list_enum(div_child->content, &p_idx))) { + u32 span_idx = 0; + GF_XMLAttribute *span_att; e = gf_xml_get_element_check_namespace(p_node, "span", root->ns); if (e == GF_BAD_PARAM) { GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[TTML EBU-TTD] ignored \"%s\" node, check your namespaces\n", p_node->name)); - } else if (e == GF_OK) { - u32 span_idx = 0; - GF_XMLAttribute *span_att; - while ( (span_att = (GF_XMLAttribute*)gf_list_enum(p_node->attributes, &span_idx))) { - - if (!strcmp(span_att->name, "begin")) { - if (ts_begin != -1) { - GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"begin\" attribute under <span>. Abort.\n")); - e = GF_NON_COMPLIANT_BITSTREAM; - goto exit; - } - if (sscanf(span_att->value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts_begin = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(span_att->value, "%u:%u:%u", &h, &m, &s) == 3) { - ts_begin = (h*3600 + m*60+s)*1000; - } - } else if (!strcmp(span_att->name, "end")) { - if (ts_end != -1) { - GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"end\" attribute under <span>. Abort.\n")); - e = GF_NON_COMPLIANT_BITSTREAM; - goto exit; - } - if (sscanf(span_att->value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts_end = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(span_att->value, "%u:%u:%u", &h, &m, &s) == 3) { - ts_end = (h*3600 + m*60+s)*1000; - } + } + else if (e) + continue; + + ts_begin = ts_end = -1; + while ( (span_att = (GF_XMLAttribute*)gf_list_enum(p_node->attributes, &span_idx))) { + if (!strcmp(span_att->name, "begin")) { + if (ts_begin != -1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"begin\" attribute under <span>. Abort.\n")); + e = GF_NON_COMPLIANT_BITSTREAM; + goto exit; } - if ((ts_begin != -1) && (ts_end != -1) && !samp_text && ctx->sample_list_node) { - /*append the sample*/ - e = gf_xml_dom_append_child(ctx->sample_list_node, div_child); - assert(e == GF_OK); - samp_text = gf_xml_dom_serialize((GF_XMLNode*)ctx->root_working_copy, GF_FALSE); - e = gf_xml_dom_rem_child(ctx->sample_list_node, div_child); - assert(e == GF_OK); + ts_begin = ttml_get_timestamp(span_att->value); + } else if (!strcmp(span_att->name, "end")) { + if (ts_end != -1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] duplicated \"end\" attribute under <span>. Abort.\n")); + e = GF_NON_COMPLIANT_BITSTREAM; + goto exit; } + ts_end = ttml_get_timestamp(span_att->value); } } + + /*append the entire <p> and break (we cannot split the text content)*/ + in_range = ttml_check_range(interval, ts_begin, ts_end); + if (in_range) { + e = gf_xml_dom_append_child(ctx->sample_list_node, div_child); + assert(e == GF_OK); + break; + } } + } - if ((ts_begin != -1) && (ts_end != -1) && samp_text) { - GF_FilterPacket *pck; - u8 *pck_data; - Bool skip_pck = GF_FALSE; - u32 txt_len; - char *txt_str; + if (gf_list_count(ctx->sample_list_node->content)) { + samp_text = gf_xml_dom_serialize((GF_XMLNode*)ctx->root_working_copy, GF_FALSE); + gf_list_reset(ctx->sample_list_node->content); + } - if (ts_end < ts_begin) { - GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] invalid timings: \"begin\"="LLD" , \"end\"="LLD". Abort.\n", ts_begin, ts_end)); - e = GF_NON_COMPLIANT_BITSTREAM; - goto exit; - } + if (samp_text) { + GF_FilterPacket *pck; + u8 *pck_data; + Bool skip_pck = GF_FALSE; + u32 txt_len; + char *txt_str; - if (ts_begin < (s64) ctx->end) { - GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] timing overlapping not supported: \"begin\" is "LLD" , last \"end\" was "LLD". Abort.\n", ts_begin, ctx->end)); - e = GF_NOT_SUPPORTED; - goto exit; - } - txt_str = ttxt_parse_string(samp_text, GF_TRUE); - if (!txt_str) txt_str = ""; - txt_len = (u32) strlen(txt_str); + if (interval->begin < (s64) ctx->end) { + GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[TTML EBU-TTD] Error computing overlapped intervals! \"begin\" is "LLD" , last \"end\" was "LLD". Abort.\n", interval->begin, ctx->end)); + e = GF_NOT_SUPPORTED; + goto exit; + } - if (ctx->first_samp) { - ts_begin = 0; /*in MP4 we must start at T=0*/ - ctx->last_sample_duration = ts_end; - ctx->first_samp = GF_FALSE; - } else { - ctx->last_sample_duration = ts_end - ts_begin; - } + txt_str = ttxt_parse_string(samp_text, GF_TRUE); + if (!txt_str) txt_str = ""; + txt_len = (u32) strlen(txt_str); - ctx->end = ts_end; - GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("ts_begin="LLD", ts_end="LLD", last_sample_duration="LLU" (real duration: "LLU"), last_sample_end="LLU"\n", ts_begin, ts_end, ts_end - ctx->end, ctx->last_sample_duration, ctx->end)); + if (ctx->first_samp) { + interval->begin = 0; /*in MP4 we must start at T=0*/ + ctx->first_samp = GF_FALSE; + } - if (ctx->seek_state==2) { - Double end = (Double) ts_end; - end /= ctx->timescale; - if (end<ctx->start_range) skip_pck = GF_TRUE; - else ctx->seek_state = 0; - } + ctx->last_sample_duration = interval->end - interval->begin; - if (!skip_pck) { - pck = gf_filter_pck_new_alloc(ctx->opid, txt_len, &pck_data); - memcpy(pck_data, txt_str, txt_len); - gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1); - gf_filter_pck_set_cts(pck, (ctx->timescale*ts_begin)/1000); - gf_filter_pck_send(pck); - } + ctx->end = interval->end; + GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("ts_begin="LLD", ts_end="LLD", last_sample_duration="LLU" (real duration: "LLU"), last_sample_end="LLU"\n", interval->begin, interval->end, interval->end - ctx->end, ctx->last_sample_duration, ctx->end)); - gf_free(samp_text); - samp_text = NULL; - ctx->nb_p_found++; - } else { - GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[TTML EBU-TTD] incomplete sample (begin="LLD", end="LLD", text=\"%s\"). Skip.\n", ts_begin, ts_end, samp_text ? samp_text : "NULL")); + if (ctx->seek_state==2) { + Double end = (Double) interval->end; + end /= ctx->timescale; + if (end<ctx->start_range) skip_pck = GF_TRUE; + else ctx->seek_state = 0; } - if (gf_filter_pid_would_block(ctx->opid)) { - ctx->cur_child_idx++; - return GF_OK; + if (!skip_pck) { + pck = gf_filter_pck_new_alloc(ctx->opid, txt_len, &pck_data); + memcpy(pck_data, txt_str, txt_len); + gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1); + gf_filter_pck_set_cts(pck, (ctx->timescale * interval->begin)/1000); + gf_filter_pck_send(pck); } - } - if (!ctx->nb_p_found) { - GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[TTML EBU-TTD] \"%s\" div node has no <p> elements.\n", ctx->div_node->name)); + gf_free(samp_text); + samp_text = NULL; + } else { + GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[TTML EBU-TTD] empty sample (begin="LLD", end="LLD"). Skip.\n", interval->begin, interval->end)); } - GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[TTML EBU-TTD] last_sample_duration="LLU", last_sample_end="LLU"\n", ctx->last_sample_duration, ctx->end)); - - gf_filter_pid_set_info_str( ctx->opid, "ttxt:last_dur", &PROP_UINT((u32) ctx->last_sample_duration) ); - - return GF_EOS; + return GF_OK; exit: - ctx->non_compliant_ttml = GF_TRUE; + if (!ctx->non_compliant_ttml) { + ctx->non_compliant_ttml = GF_TRUE; + gf_filter_pid_set_discard(ctx->ipid, GF_TRUE); + } return e; } @@ -2813,6 +2961,11 @@ #ifndef GPAC_DISABLE_SWF_IMPORT gf_swf_reader_del(ctx->swf_parse); #endif + + if (ctx->intervals) { + ttml_reset_intervals(ctx); + gf_list_del(ctx->intervals); + } } static const char *txtin_probe_data(const u8 *data, u32 data_size, GF_FilterProbeScore *score)
View file
gpac-1.0.0.tar.gz/src/filters/mux_avi.c -> gpac-1.0.1.tar.gz/src/filters/mux_avi.c
Changed
@@ -52,6 +52,7 @@ char *dst; GF_Fraction fps; Bool noraw; + u64 opendml_size; avi_t *avi_out; @@ -84,7 +85,7 @@ return GF_NOT_SUPPORTED; } - ctx->avi_out = AVI_open_output_file((char *) filename); + ctx->avi_out = AVI_open_output_file((char *) filename, ctx->opendml_size); if (had_file && ctx->nb_write) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[AVIOut] re-opening in write mode output file %s, content overwrite\n", filename)); @@ -520,6 +521,7 @@ { OFFS(dst), "location of destination file", GF_PROP_NAME, NULL, NULL, 0}, { OFFS(fps), "default framerate if none indicated in stream", GF_PROP_FRACTION, "25/1", NULL, 0}, { OFFS(noraw), "disable raw output in AVI, only compressed ones allowed", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(opendml_size), "force opendml format when chunks are larger than this amount (0 means 1.9Gb max size in each riff chunk)", GF_PROP_LUINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, {0} };
View file
gpac-1.0.0.tar.gz/src/filters/mux_gsf.c -> gpac-1.0.1.tar.gz/src/filters/mux_gsf.c
Changed
@@ -154,6 +154,7 @@ static void gsfmx_encrypt(GSFMxCtx *ctx, char *data, u32 nb_crypt_bytes) { +#ifndef GPAC_DISABLE_CRYPTO u32 clear_trail; clear_trail = nb_crypt_bytes % 16; @@ -177,6 +178,7 @@ } else { gf_crypt_encrypt(ctx->crypt, data, nb_crypt_bytes); } +#endif // GPAC_DISABLE_CRYPTO } static void gsfmx_send_packets(GSFMxCtx *ctx, GSFStream *gst, GF_GSFPacketType pck_type, Bool is_end, Bool is_redundant, u32 frame_size, u32 frame_hdr_size) @@ -784,7 +786,7 @@ gf_bs_write_int(ctx->bs_w, duration, tsdiffmodebits); } - if (sap==GF_FILTER_SAP_4) { + if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL)) { s16 roll = gf_filter_pck_get_roll_info(pck); gf_bs_write_u16(ctx->bs_w, roll); } @@ -1002,6 +1004,9 @@ gf_rand_init(GF_FALSE); if (ctx->key.size==16) { +#ifdef GPAC_DISABLE_CRYPTO + return GF_NOT_SUPPORTED; +#else GF_Err e; if (ctx->IV.size==16) { memcpy(ctx->crypt_IV, ctx->IV.ptr, 16); @@ -1033,6 +1038,7 @@ GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFMux] Failed to setup encryption: %s\n", gf_error_to_string(e) )); return GF_IO_ERR; } +#endif } else if (ctx->key.size) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[GSFMux] Wrong key value, size %d expecting 16\n", ctx->key.size)); return GF_BAD_PARAM; @@ -1057,7 +1063,9 @@ if (ctx->bs_w) gf_bs_del(ctx->bs_w); if (ctx->buffer) gf_free(ctx->buffer); +#ifndef GPAC_DISABLE_CRYPTO if (ctx->crypt) gf_crypt_close(ctx->crypt); +#endif } static const GF_FilterCapability GSFMxCaps[] = @@ -1083,9 +1091,11 @@ "- no: disable debug\n" "- nodata: force packet size to 0\n" "- nopck: skip packet", GF_PROP_UINT, "no", "no|nodata|nopck", GF_FS_ARG_HINT_EXPERT}, +#ifndef GPAC_DISABLE_CRYPTO { OFFS(key), "encrypt packets using given key - see filter helps", GF_PROP_DATA, NULL, NULL, 0}, { OFFS(IV), "set IV for encryption - a constant IV is used to keep packet overhead small (cbcs-like)", GF_PROP_DATA, NULL, NULL, 0}, { OFFS(pattern), "set nb crypt / nb_skip block pattern. default is all encrypted", GF_PROP_FRACTION, "1/0", NULL, GF_FS_ARG_HINT_ADVANCED}, +#endif // GPAC_DISABLE_CRYPTO { OFFS(mpck), "set max packet size. 0 means no fragmentation (each AU is sent in one packet)", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(magic), "magic string to append in setup packet", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(skp), "comma separated list of pid property names to skip - see filter help", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -1098,7 +1108,8 @@ GF_FilterRegister GSFMxRegister = { .name = "gsfmx", GF_FS_SET_DESCRIPTION("GSF Muxer") - GF_FS_SET_HELP("This filter provides GSF (__GPAC Super/Simple/Serialized/Stream/State Format__) multiplexing.\n" +#ifndef GPAC_DISABLE_DOC + .help = "This filter provides GSF (__GPAC Super/Simple/Serialized/Stream/State Format__) multiplexing.\n" "It serializes the stream states (config/reconfig/info update/remove/eos) and packets of input PIDs. " "This allows either saving to file a session, or forwarding the state/data of streams to another instance of GPAC " "using either pipes or sockets. Upstream events are not serialized.\n" @@ -1106,6 +1117,7 @@ "The default behaviour does not insert sequence numbers. When running over general protocols not ensuring packet order, this should be inserted.\n" "The serializer sends tune-in packets (global and per pid) at the requested carousel rate - if 0, no carousel. These packets are marked as redundant so that they can be discarded by output filters if needed.\n" "\n" +#ifndef GPAC_DISABLE_CRYPTO "The stream format can be encrypted in AES 128 CBC mode. For all packets, the packet header (header, size, frame size/block offset and optional seq num) are in the clear " "and the followings byte until the last byte of the last multiple of block size (16) fitting in the payload are encrypted.\n" "For data packets, each fragment is encrypted individually to avoid error propagation in case of losses.\n" @@ -1113,13 +1125,16 @@ "For header/tunein packets, the first 25 bytes after the header are in the clear (signature,version,IV and pattern).\n" "The [-IV]() is constant to avoid packet overhead, randomly generated if not set and sent in the initial stream header. " "Pattern mode can be used (cf CENC cbcs) to encrypt K block and leave N blocks in the clear.\n" - "\n"\ + "\n" +#endif "The header/tunein packet may get quite big when all pid properties are kept. In order to help reduce its size, the [-minp]() option can be used: " "this will remove all built-in properties marked as dropable (cf property help) as well as all non built-in properties.\n" "The [-skp]() option may also be used to specify which property to drop:\n" "EX skp=\"4CC1,Name2\n"\ "This will remove properties of type 4CC1 and properties (built-in or not) of name Name2.\n" - "\n") + "\n" + , +#endif .private_size = sizeof(GSFMxCtx), .max_extra_pids = (u32) -1, .args = GSFMxArgs,
View file
gpac-1.0.0.tar.gz/src/filters/mux_isom.c -> gpac-1.0.1.tar.gz/src/filters/mux_isom.c
Changed
@@ -55,6 +55,13 @@ CENC_SETUP_ERROR }; +enum{ + TAG_NONE, + TAG_STRICT, + TAG_ALL +}; + + typedef struct { GF_FilterPid *ipid; @@ -84,7 +91,7 @@ Bool skip_bitrate_update; Bool has_open_gop; - Bool has_gdr; + GF_FilterSAPType gdr_type; Bool next_is_first_sample; @@ -228,6 +235,9 @@ Bool ctrn; Bool ctrni; #endif + Bool mfra; + Bool forcesync; + u32 tags; //internal Bool owns_mov; @@ -518,9 +528,151 @@ ctx->tracks = new_tracks; } +static void mp4_mux_set_tags(GF_MP4MuxCtx *ctx, TrackWriter *tkw) +{ + u32 idx=0; + if (ctx->tags==TAG_NONE) return; + + while (1) { + GF_Err e; + u32 tag_val; + u32 prop_4cc=0; + s32 itag; + const char *tag_name=NULL; + const GF_PropertyValue *tag = gf_filter_pid_enum_properties(tkw->ipid, &idx, &prop_4cc, &tag_name); + if (!tag) break; + + if (prop_4cc==GF_PROP_PID_COVER_ART) { + e = gf_isom_apple_set_tag(ctx->file, GF_ISOM_ITUNE_COVER_ART, tag->value.data.ptr, tag->value.data.size); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MP4Mux] Failed to set cover art: %s\n", gf_error_to_string(e))); + } + } + if (!tag_name) + continue; + + itag = gf_itags_find_by_name(tag_name); + if (itag>=0) { + Bool tag_set=GF_FALSE; + u32 val; + char _t[8]; + u32 itype = gf_itags_get_type((u32) itag); + itag = gf_itags_get_itag(itag); + + e = GF_OK; + if ((itag==GF_ISOM_ITUNE_DISK) ||(itag==GF_ISOM_ITUNE_TRACKNUMBER)) { + u32 n=0, t=0, tlen=0; + if (tag->value.string) { + memset(_t, 0, sizeof(char) * 8); + tlen = (itag == GF_ISOM_ITUNE_DISK) ? 6 : 8; + if (sscanf(tag->value.string, "%u/%u", &n, &t) == 2) { + _t[3] = n; + _t[2] = n >> 8; + _t[5] = t; + _t[4] = t >> 8; + } + else if (sscanf(tag->value.string, "%u", &n) == 1) { + _t[3] = n; + _t[2] = n >> 8; + } + else tlen = 0; + } + if (!tag->value.string || tlen) { + e = gf_isom_apple_set_tag(ctx->file, itag, tlen ? (u8 *)_t : NULL, tlen); + tag_set = GF_TRUE; + } + } + else if (itag==GF_ISOM_ITUNE_GENRE) { + val = 0; + if ((tag->type==GF_PROP_STRING) && tag->value.string) { + val = gf_id3_get_genre_tag(tag->value.string); + if (val) { + e = gf_isom_apple_set_tag(ctx->file, itag, NULL, val); + tag_set = GF_TRUE; + } + } + } + + if (!tag_set) { + switch (itype) { + case GF_ITAG_STR: + case GF_ITAG_SUBSTR: + if ((tag->type==GF_PROP_STRING) && tag->value.string) { + e = gf_isom_apple_set_tag(ctx->file, itag, tag->value.string, (u32) strlen(tag->value.string)); + } else { + e = GF_BAD_PARAM; + } + break; + case GF_ITAG_INT: + val=0; + if ((tag->type==GF_PROP_STRING) && tag->value.string) { + val = atoi(tag->value.string); + } else if (tag->type==GF_PROP_UINT) { + val = tag->value.uint; + } + if (val) { + e = gf_isom_apple_set_tag(ctx->file, itag, NULL, val); + } + break; + + case GF_ITAG_BOOL: + _t[0] = 0; + if ((tag->type==GF_PROP_STRING) && tag->value.string && + (!stricmp(tag->value.string, "yes") || !stricmp(tag->value.string, "true") || !stricmp(tag->value.string, "1")) + ) { + _t[0] = 1; + } else if (tag->value.boolean) { + _t[0] = 1; + } + e = gf_isom_apple_set_tag(ctx->file, itag, _t, 1); + } + } + + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MP4Mux] Failed to set tag %s: %s\n", tag_name, gf_error_to_string(e))); + } + continue; + } + if (ctx->tags==TAG_STRICT) + continue; + + if (strnicmp(tag_name, "tag_", 4)) + continue; + + tag_name += 4; + + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MP4Mux] Unrecognized tag %s: %s\n", tag_name, tag->value.string)); + if ((tag->type!=GF_PROP_STRING) && (tag->type!=GF_PROP_DATA) && (tag->type!=GF_PROP_CONST_DATA)) continue; + + if (strlen(tag_name)==4) { + tag_val = GF_4CC(tag_name[0], tag_name[1], tag_name[2], tag_name[3]); + } else { + tag_val = gf_crc_32(tag_name, (u32) strlen(tag_name)); + GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MP4Mux] Tag name %s is not a 4CC, using CRC32 %d as value\n", tag_name, tag_val)); + } + if (tag->type==GF_PROP_STRING) { + if (tag->value.string) { + if (tag_val==GF_ID3V2_FRAME_TCOP) { + e = gf_isom_set_copyright(ctx->file, "unk", tag->value.string); + } else { + e = gf_isom_apple_set_tag(ctx->file, tag_val, tag->value.string, (u32) strlen(tag->value.string) ); + } + } else { + e = gf_isom_apple_set_tag(ctx->file, tag_val, NULL, 0); + } + } else { + e = gf_isom_apple_set_tag(ctx->file, tag_val, tag->value.data.ptr , tag->value.data.size); + } + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MP4Mux] Failed to set tag %s: %s\n", tag_name, gf_error_to_string(e))); + } + } +} + static GF_Err mp4_mux_setup_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_true_pid) { + void mux_assign_mime_file_ext(GF_FilterPid *ipid, GF_FilterPid *opid, const char *file_exts, const char *mime_types, const char *def_ext); Bool use_m4sys = GF_FALSE; Bool use_tx3g = GF_FALSE; Bool use_webvtt = GF_FALSE; @@ -542,6 +694,7 @@ Bool is_text_subs = GF_FALSE; Bool force_colr = GF_FALSE; u32 m_subtype=0; + u32 m_subtype_src=0; u32 m_subtype_alt_raw=0; u32 raw_bitdepth=0; u32 override_stype=0; @@ -600,7 +753,6 @@ } //copy properties at init or reconfig if (ctx->opid && is_true_pid) { - Bool found=GF_FALSE; gf_filter_pid_copy_properties(ctx->opid, pid); if (gf_list_count(ctx->tracks)>1) gf_filter_pid_set_name(ctx->opid, "isobmf_mux"); @@ -610,30 +762,9 @@ gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, NULL); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) ); - p = gf_filter_pid_get_property(pid, GF_PROP_PID_FILE_EXT); - if (p) { - char *match = strstr(ISOM_FILE_EXT, p->value.string); - if (match) { - u32 slen = (u32) strlen(match); - if (!match[slen-1] || (match[slen-1]=='|')) - found = GF_TRUE; - } - } - if (!found) - gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("*") ); - p = gf_filter_pid_get_property(pid, GF_PROP_PID_MIME); - found = GF_FALSE; - if (p) { - char *match = strstr(ISOM_FILE_MIME, p->value.string); - if (match) { - u32 slen = (u32) strlen(match); - if (!match[slen-1] || (match[slen-1]=='|')) - found = GF_TRUE; - } - } - if (!found) - gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_MIME, &PROP_STRING("*") ); + mux_assign_mime_file_ext(pid, ctx->opid, ISOM_FILE_EXT, ISOM_FILE_MIME, NULL); + gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DASH_MODE, NULL); switch (ctx->store) { @@ -785,7 +916,7 @@ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MP4Mux] ProRes track detected, muxing to QTFF even though ISOBMFF was asked\n")); ctx->make_qt = 2; } - if (ctx->prores_track == tkw) { + if (ctx->prores_track && (ctx->prores_track != tkw)) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MP4Mux] More than one ProRes track detected, result might be non compliant\n")); } is_prores = GF_TRUE; @@ -936,7 +1067,7 @@ gf_isom_set_timescale(ctx->file, (u32) ctx->moovts); } - p = gf_filter_pid_get_property(tkw->ipid, GF_PROP_PID_TRACK_INDEX); + p = gf_filter_pid_get_property(tkw->ipid, GF_PROP_PID_MUX_INDEX); if (p) { tk_idx = p->value.uint; } @@ -1159,6 +1290,9 @@ if (p) tkw->nb_frames = p->value.uint; else tkw->nb_frames = 0; } + p = gf_filter_pid_get_property(pid, GF_PROP_PID_ISOM_SUBTYPE); + if (p) m_subtype_src = p->value.uint; + //get our subtype switch (codec_id) { @@ -1265,6 +1399,20 @@ comp_name = "EAC-3"; use_ac3_entry = GF_TRUE; break; + case GF_CODECID_MPHA: + if ((m_subtype_src!=GF_ISOM_SUBTYPE_MH3D_MHA1) && (m_subtype_src!=GF_ISOM_SUBTYPE_MH3D_MHA2)) + m_subtype = GF_ISOM_SUBTYPE_MH3D_MHA1; + else + m_subtype = m_subtype_src; + comp_name = "MPEG-H Audio"; + break; + case GF_CODECID_MHAS: + if ((m_subtype_src!=GF_ISOM_SUBTYPE_MH3D_MHM1) && (m_subtype_src!=GF_ISOM_SUBTYPE_MH3D_MHM2)) + m_subtype = GF_ISOM_SUBTYPE_MH3D_MHM1; + else + m_subtype = m_subtype_src; + comp_name = "MPEG-H AudioMux"; + break; case GF_CODECID_FLAC: m_subtype = GF_ISOM_SUBTYPE_FLAC; comp_name = "FLAC"; @@ -1287,7 +1435,10 @@ use_avc = GF_TRUE; comp_name = (codec_id == GF_CODECID_SVC) ? "MPEG-4 SVC" : "MPEG-4 AVC"; use_gen_sample_entry = GF_FALSE; - if (ctx->xps_inband==1) skip_dsi = GF_TRUE; + if (ctx->xps_inband) { + use_m4sys = GF_FALSE; + if (ctx->xps_inband==1) skip_dsi = GF_TRUE; + } break; case GF_CODECID_HEVC: case GF_CODECID_LHVC: @@ -1295,7 +1446,10 @@ use_hevc = GF_TRUE; comp_name = (codec_id == GF_CODECID_LHVC) ? "L-HEVC" : "HEVC"; use_gen_sample_entry = GF_FALSE; - if (ctx->xps_inband==1) skip_dsi = GF_TRUE; + if (ctx->xps_inband) { + use_m4sys = GF_FALSE; + if (ctx->xps_inband==1) skip_dsi = GF_TRUE; + } if (codec_id==GF_CODECID_HEVC_TILES) { m_subtype = GF_ISOM_SUBTYPE_HVT1; skip_dsi = GF_TRUE; @@ -1305,6 +1459,7 @@ m_subtype = GF_ISOM_SUBTYPE_HVT1; skip_dsi = GF_TRUE; use_hvt1 = GF_TRUE; + use_m4sys = GF_FALSE; comp_name = "HEVC Tiles"; use_gen_sample_entry = GF_FALSE; break; @@ -1663,6 +1818,8 @@ if (tkw->codecid == GF_CODECID_SVC) { e = gf_isom_svc_config_new(ctx->file, tkw->track_num, tkw->avcc, NULL, NULL, &tkw->stsd_idx); + } else if (tkw->codecid == GF_CODECID_MVC) { + e = gf_isom_mvc_config_new(ctx->file, tkw->track_num, tkw->avcc, NULL, NULL, &tkw->stsd_idx); } else { e = gf_isom_avc_config_new(ctx->file, tkw->track_num, tkw->avcc, NULL, NULL, &tkw->stsd_idx); } @@ -1671,7 +1828,11 @@ if (tkw->svcc) gf_odf_avc_cfg_del(tkw->svcc); tkw->svcc = gf_odf_avc_cfg_read(enh_dsi->value.data.ptr, enh_dsi->value.data.size); if (tkw->svcc) { - e = gf_isom_svc_config_update(ctx->file, tkw->track_num, tkw->stsd_idx, tkw->svcc, GF_TRUE); + if ((tkw->svcc->AVCProfileIndication==118) || (tkw->svcc->AVCProfileIndication==128)) { + e = gf_isom_mvc_config_update(ctx->file, tkw->track_num, tkw->stsd_idx, tkw->svcc, GF_TRUE); + } else { + e = gf_isom_svc_config_update(ctx->file, tkw->track_num, tkw->stsd_idx, tkw->svcc, GF_TRUE); + } if (e) { gf_odf_avc_cfg_del(tkw->svcc); tkw->svcc = NULL; @@ -2168,13 +2329,13 @@ } if (!reuse_stsd) { tkw->samples_in_stsd = 0; - } else if (use_3gpp_config && tkw->amr_mode_set) { + } else if (use_3gpp_config) { GF_3GPConfig *gpp_cfg = gf_isom_3gp_config_get(ctx->file, tkw->track_num, tkw->stsd_idx); - if (gpp_cfg->AMR_mode_set != tkw->amr_mode_set) { + if (gpp_cfg) { gpp_cfg->AMR_mode_set = tkw->amr_mode_set; gf_isom_3gp_config_update(ctx->file, tkw->track_num, gpp_cfg, tkw->stsd_idx); + gf_free(gpp_cfg); } - gf_free(gpp_cfg); } } @@ -2474,25 +2635,36 @@ tkw->probe_min_ctts = GF_FALSE; if (is_true_pid && !tkw->nb_samples && !tkw->is_item) { Bool use_negccts = GF_FALSE; + Bool remove_edits = GF_FALSE; s64 moffset=0; ctx->config_timing = GF_TRUE; ctx->update_report = GF_TRUE; //if we have an edit list (due to track template) only providing media offset, trash it if (!gf_isom_get_edit_list_type(ctx->file, tkw->track_num, &moffset)) { - gf_isom_remove_edits(ctx->file, tkw->track_num); + if (!gf_sys_old_arch_compat()) { + gf_isom_remove_edits(ctx->file, tkw->track_num); + } else { + remove_edits = GF_TRUE; + } } p = gf_filter_pid_get_property(tkw->ipid, GF_PROP_PID_DELAY); if (p) { if (p->value.sint < 0) { if (ctx->ctmode==MP4MX_CT_NEGCTTS) use_negccts = GF_TRUE; else { + if (remove_edits) { + gf_isom_remove_edits(ctx->file, tkw->track_num); + } gf_isom_set_edit(ctx->file, tkw->track_num, 0, 0, -p->value.sint, GF_ISOM_EDIT_NORMAL); } } else if (p->value.sint > 0) { s64 dur = p->value.sint; dur *= (u32) ctx->moovts; dur /= tkw->src_timescale; + if (remove_edits) { + gf_isom_remove_edits(ctx->file, tkw->track_num); + } gf_isom_set_edit(ctx->file, tkw->track_num, 0, dur, 0, GF_ISOM_EDIT_DWELL); gf_isom_set_edit(ctx->file, tkw->track_num, 0, 0, 0, GF_ISOM_EDIT_NORMAL); } @@ -2516,6 +2688,8 @@ //this will remove any cslg in the track due to template gf_isom_set_composition_offset_mode(ctx->file, tkw->track_num, GF_FALSE); } + + mp4_mux_set_tags(ctx, tkw); } return GF_OK; } @@ -2811,6 +2985,13 @@ return GF_OK; } +GF_FilterSAPType mp4_mux_get_sap(GF_MP4MuxCtx *ctx, GF_FilterPacket *pck) +{ + GF_FilterSAPType sap = gf_filter_pck_get_sap(pck); + if (!sap) return sap; + if (ctx->forcesync) return GF_FILTER_SAP_1; + return sap; +} static GF_Err mp4_mux_process_sample(GF_MP4MuxCtx *ctx, TrackWriter *tkw, GF_FilterPacket *pck, Bool for_fragment) { @@ -2821,7 +3002,6 @@ u32 timescale = 0; const GF_PropertyValue *subs; GF_FilterSAPType sap_type; - u8 dep_flags; Bool insert_subsample_dsi = GF_FALSE; u32 first_nal_is_audelim = GF_FALSE; u32 sample_desc_index = tkw->stsd_idx; @@ -2876,7 +3056,7 @@ tkw->sample.DTS -= tkw->ts_shift; cts -= tkw->ts_shift; } else { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MP4Mux] broken timing in track, initial ts "LLU" gretaer than TS "LLU"\n", tkw->ts_shift, tkw->sample.DTS)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MP4Mux] broken timing in track, initial ts "LLU" greater than TS "LLU"\n", tkw->ts_shift, tkw->sample.DTS)); } } } @@ -2896,7 +3076,7 @@ tkw->sample.IsRAP = 0; - sap_type = gf_filter_pck_get_sap(pck); + sap_type = mp4_mux_get_sap(ctx, pck); if (sap_type==GF_FILTER_SAP_1) tkw->sample.IsRAP = SAP_TYPE_1; else if ( (sap_type == GF_FILTER_SAP_4) && (tkw->stream_type != GF_STREAM_VISUAL) ) @@ -3045,17 +3225,25 @@ tkw->has_open_gop = GF_TRUE; } if (!ctx->noroll) { - if ((sap_type==4) || tkw->has_gdr) { + if ((sap_type==GF_FILTER_SAP_4) || (sap_type==GF_FILTER_SAP_4_PROL) || tkw->gdr_type) { + GF_ISOSampleRollType roll_type = 0; s16 roll = gf_filter_pck_get_roll_info(pck); + if (sap_type==GF_FILTER_SAP_4) roll_type = GF_ISOM_SAMPLE_ROLL; + else if (sap_type==GF_FILTER_SAP_4_PROL) roll_type = GF_ISOM_SAMPLE_PREROLL; + else if (tkw->gdr_type==GF_FILTER_SAP_4_PROL) { + roll_type = GF_ISOM_SAMPLE_PREROLL_NONE; + } + if (for_fragment) { - e = gf_isom_fragment_set_sample_roll_group(ctx->file, tkw->track_id, tkw->samples_in_frag, (sap_type==4) ? GF_TRUE : GF_FALSE, roll); + e = gf_isom_fragment_set_sample_roll_group(ctx->file, tkw->track_id, tkw->samples_in_frag, roll_type, roll); } else { - e = gf_isom_set_sample_roll_group(ctx->file, tkw->track_num, tkw->nb_samples, (sap_type==4) ? GF_TRUE : GF_FALSE, roll); + e = gf_isom_set_sample_roll_group(ctx->file, tkw->track_num, tkw->nb_samples, roll_type, roll); } if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MP4Mux] Failed to set sample DTS "LLU" SAP 4 roll %s in roll group: %s\n", tkw->sample.DTS, roll, gf_error_to_string(e) )); } - tkw->has_gdr = GF_TRUE; + if (sap_type && !tkw->gdr_type) + tkw->gdr_type = sap_type; } } @@ -3101,16 +3289,18 @@ } } - dep_flags = gf_filter_pck_get_dependency_flags(pck); - if (dep_flags) { - u32 is_leading = (dep_flags>>6) & 0x3; - u32 depends_on = (dep_flags>>4) & 0x3; - u32 depended_on = (dep_flags>>2) & 0x3; - u32 redundant = (dep_flags) & 0x3; - if (for_fragment) { - gf_isom_fragment_set_sample_flags(ctx->file, tkw->track_id, is_leading, depends_on, depended_on, redundant); - } else { - gf_isom_set_sample_flags(ctx->file, tkw->track_num, tkw->nb_samples, is_leading, depends_on, depended_on, redundant); + if (ctx->deps) { + u8 dep_flags = gf_filter_pck_get_dependency_flags(pck); + if (dep_flags) { + u32 is_leading = (dep_flags>>6) & 0x3; + u32 depends_on = (dep_flags>>4) & 0x3; + u32 depended_on = (dep_flags>>2) & 0x3; + u32 redundant = (dep_flags) & 0x3; + if (for_fragment) { + gf_isom_fragment_set_sample_flags(ctx->file, tkw->track_id, is_leading, depends_on, depended_on, redundant); + } else { + gf_isom_set_sample_flags(ctx->file, tkw->track_num, tkw->nb_samples, is_leading, depends_on, depended_on, redundant); + } } } @@ -3538,7 +3728,9 @@ for (i=0; i<count; i++) { u32 def_pck_dur; u32 def_is_rap; +#ifdef GF_ENABLE_CTRN u32 inherit_traf_from_track = 0; +#endif u64 dts; const GF_PropertyValue *p; @@ -3637,8 +3829,10 @@ continue; } +#ifdef GF_ENABLE_CTRN if (inherit_traf_from_track) gf_isom_enable_traf_inherit(ctx->file, tkw->track_id, inherit_traf_from_track); +#endif if (!tkw->box_patched) { p = gf_filter_pid_get_property_str(tkw->ipid, "boxpatch"); @@ -4214,7 +4408,7 @@ } else if (!ctx->flush_seg && !ctx->dash_mode && (cts >= (u64) (ctx->adjusted_next_frag_start * tkw->src_timescale) + tkw->ts_delay) ) { - u32 sap = gf_filter_pck_get_sap(pck); + GF_FilterSAPType sap = mp4_mux_get_sap(ctx, pck); if ((ctx->store==MP4MX_MODE_FRAG) || (sap && sap<GF_FILTER_SAP_3)) { tkw->fragment_done = GF_TRUE; tkw->samples_in_frag = 0; @@ -4239,7 +4433,7 @@ } if (ctx->trun_inter) { - s32 sap = gf_filter_pck_get_sap(pck); + GF_FilterSAPType sap = mp4_mux_get_sap(ctx, pck); s32 tid_group = 0; if (sap) { tkw->prev_tid_group = 0; @@ -4894,6 +5088,11 @@ } if (!ctx->moovts) ctx->moovts=600; + if (ctx->mfra && (ctx->store>=MP4MX_MODE_FRAG)) { + GF_Err e = gf_isom_enable_mfra(ctx->file); + if (e) return e; + } + if (!ctx->tracks) ctx->tracks = gf_list_new(); @@ -5277,15 +5476,15 @@ { { OFFS(m4sys), "force MPEG-4 Systems signaling of tracks", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(dref), "only references data from source file - not compatible with all media sources", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(ctmode), "set composition offset mode for video tracks.\n" + { OFFS(ctmode), "set composition offset mode for video tracks\n" "- edit: uses edit lists to shift first frame to presentation time 0\n" "- noedit: ignore edit lists and does not shift timeline\n" "- negctts: uses ctts v1 with possibly negative offsets and no edit lists", GF_PROP_UINT, "edit", "edit|noedit|negctts", GF_FS_ARG_HINT_ADVANCED}, { OFFS(idur), "only import the specified duration. If negative, specify the number of coded frames to import", GF_PROP_FRACTION, "0", NULL, 0}, { OFFS(pack3gp), "pack a given number of 3GPP audio frames in one sample", GF_PROP_UINT, "1", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(importer), "compatibility with old importer, displays import progress", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(pack_nal), "repack NALU size length to minimum possible size for AVC/HEVC/...", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(xps_inband), "use inband (in sample data) param set for AVC/HEVC/...\n" + { OFFS(pack_nal), "repack NALU size length to minimum possible size for NALU-based video (AVC/HEVC/...)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(xps_inband), "use inband (in sample data) param set for NALU-based video (AVC/HEVC/...)\n" "- no: paramater sets are not inband, several sample descriptions might be created\n" "- all: paramater sets are inband, no param sets in sample description\n" "- both: paramater sets are inband, signaled as inband, and also first set is kept in sample descripton\n" @@ -5299,7 +5498,7 @@ "- sfrag: framents the file using cdur duration but adjusting to start with SAP1/3", GF_PROP_UINT, "inter", "inter|flat|fstart|tight|frag|sfrag", 0}, { OFFS(cdur), "chunk duration for interleaving and fragmentation modes\n" "- 0: no specific interleaving but moov first\n" - "- negative: defaults to 1.0 unless overriden by storage profile", GF_PROP_DOUBLE, "-1.0", NULL, 0}, + "- negative: defaults to 1.0 unless overridden by storage profile", GF_PROP_DOUBLE, "-1.0", NULL, 0}, { OFFS(moovts), "timescale to use for movie. A negative value picks the media timescale of the first track added", GF_PROP_SINT, "600", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(moof_first), "generate fragments starting with moof then mdat", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(abs_offset), "use absolute file offset in fragments rather than offsets from moof", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -5374,6 +5573,13 @@ { OFFS(block_size), "target output block size, 0 for default internal value (10k)", GF_PROP_UINT, "10000", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(boxpatch), "apply box patch before writing", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(deps), "add samples dependencies information", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(mfra), "enable movie fragment random access when fragmenting (ignored when dashing)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(forcesync), "force all SAP types to be considered sync samples (might produce non-conformant files)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(tags), "tag injection mode\n" + "- none: do not inject tags\n" + "- strict: only inject recognized itunes tags\n" + "- all: inject all possible tags" + , GF_PROP_UINT, "strict", "none|strict|all", GF_FS_ARG_HINT_EXPERT}, {0} }; @@ -5411,8 +5617,15 @@ "The box patch is applied before writing the initial moov box in fragmented mode, or when writing the complete file otherwise.\n" "The box patch can either be a filename or the full XML string.\n" " \n" + "# Tagging\n" + "When tagging is enabled, the filter will watch the property `CoverArt` and all custom properties on incoming pid.\n" + "The built-in tag names are `album`, `artist`, `comment`, `complilation`, `composer`, `year`, `disk`, `tool`, `genre`, `contentgroup`, `title`, `tempo`, `track`, `tracknum`, `writer`, `encoder`, `album_artist`, `gapless`, `conductor`.\n" + "Other tag class may be specified using `tag_NAME` property names, and will be added if [-tags]() is set to `all` using:\n" + "- `NAME` as a box 4CC if `NAME` is four characters long\n" + "- the CRC32 of the `NAME` as a box 4CC if `NAME` is not four characters long\n" + " \n" "# Notes\n" - "The filter watches the property `FileNumber` on incoming packets to create new files or new segments in DASH mode.\n" + "The filter watches the property `FileNumber` on incoming packets to create new files or new segments in DASH mode.\n" ) .private_size = sizeof(GF_MP4MuxCtx), .args = MP4MuxArgs,
View file
gpac-1.0.0.tar.gz/src/filters/mux_ts.c -> gpac-1.0.1.tar.gz/src/filters/mux_ts.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2018 + * Copyright (c) Telecom ParisTech 2018-2020 * All rights reserved * * This file is part of GPAC / MPEG-2 TS mux filter @@ -29,6 +29,52 @@ #include <gpac/iso639.h> #include <gpac/webvtt.h> + +#define M2TS_FILE_EXTS "ts|m2t|mts|dmb|trp" +#define M2TS_MIMES "video/mpeg-2|video/mp2t|video/mpeg|audio/mp2t" + + +void mux_assign_mime_file_ext(GF_FilterPid *ipid, GF_FilterPid *opid, const char *file_exts, const char *mime_types, const char *def_ext) +{ + Bool found=GF_FALSE; + const GF_PropertyValue *p; + + p = gf_filter_pid_get_property(ipid, GF_PROP_PID_FILE_EXT); + if (p) { + char *match = strstr(file_exts, p->value.string); + if (match) { + u32 slen = (u32) strlen(match); + if (!match[slen-1] || (match[slen-1]=='|')) + found = GF_TRUE; + } + } + if (!found) + gf_filter_pid_set_property(opid, GF_PROP_PID_FILE_EXT, &PROP_STRING(def_ext ? (char *)def_ext : "*") ); + + p = gf_filter_pid_get_property(ipid, GF_PROP_PID_MIME); + found = GF_FALSE; + if (p) { + char *match = strstr(mime_types, p->value.string); + if (match) { + u32 slen = (u32) strlen(match); + if (!match[slen-1] || (match[slen-1]=='|')) + found = GF_TRUE; + } + } + if (!found) + gf_filter_pid_set_property(opid, GF_PROP_PID_MIME, &PROP_STRING("*") ); +} + + + +enum +{ + TEMI_TC64_AUTO=0, + TEMI_TC64_OFF, + TEMI_TC64_ALWAYS, +}; + + typedef struct { u64 sap_time; @@ -42,10 +88,11 @@ typedef struct { //filter args - u32 pmt_id, pmt_rate, pcr_offset, pmt_version, sdt_rate, breq, mpeg4; - u32 rate, pat_rate, repeat_rate, repeat_img, max_pcr, nb_pack, sid, bifs_pes, temi_delay, temi_offset; + u32 pmt_id, pmt_rate, pmt_version, sdt_rate, breq, mpeg4; + u64 pcr_offset, first_pts; + u32 rate, pat_rate, repeat_rate, repeat_img, max_pcr, nb_pack, sid, bifs_pes; GF_M2TS_PackMode pes_pack; - Bool flush_rap, realtime, pcr_only, disc, temi_ntp, latm; + Bool flush_rap, realtime, pcr_only, disc, latm; s64 pcr_init; char *name, *provider, *temi; u32 log_freq; @@ -93,6 +140,16 @@ typedef struct { + u32 id, delay, timescale; + u64 offset, init_val; + char *url; + Bool ntp, use_init_val; + u32 mode_64bits; + u64 cts_at_init_val_plus_one; +} TEMIDesc; + +typedef struct +{ GF_ESInterface esi; GF_FilterPid *ipid; GF_M2TS_Mux_Stream *mstream; @@ -108,14 +165,15 @@ GF_TSMuxCtx *ctx; u32 last_cv; //ts media skip - s32 media_delay; + s32 media_delay, max_media_skip; Bool done; - u32 temi_id; - char *temi_url; + GF_List *temi_descs; u32 last_temi_url; - char af_data[188]; + u8 *af_data; + u32 af_data_alloc; + GF_BitStream *temi_af_bs; Bool rewrite_odf; Bool has_seen_eods; @@ -125,18 +183,15 @@ u64 last_dts; u32 last_dur; - char *pck_data_buf; + u8 *pck_data_buf; u32 suspended; } M2Pid; -static u32 tsmux_format_af_descriptor(char *af_data, u32 timeline_id, u64 timecode, u32 timescale, u64 ntp, const char *temi_url, u32 temi_delay, u32 *last_url_time) +static GF_Err tsmux_format_af_descriptor(GF_BitStream *bs, u32 timeline_id, u64 timecode, u32 timescale, u32 mode_64bits, u64 ntp, const char *temi_url, u32 temi_delay, u32 *last_url_time) { - u32 res; u32 len; u32 last_time; - GF_BitStream *bs = gf_bs_new(af_data, 188, GF_BITSTREAM_WRITE); - if (ntp) { last_time = 1000*(ntp>>32); last_time += 1000*(ntp&0xFFFFFFFF)/0xFFFFFFFF; @@ -144,6 +199,8 @@ last_time = (u32) (1000*timecode/timescale); } if (temi_url && (!*last_url_time || (last_time - *last_url_time + 1 >= temi_delay)) ) { + u64 start = gf_bs_get_position(bs); + u64 end; *last_url_time = last_time + 1; len = 0; gf_bs_write_int(bs, GF_M2TS_AFDESC_LOCATION_DESCRIPTOR, 8); @@ -172,12 +229,27 @@ gf_bs_write_u8(bs, 0); //nb_addons } //rewrite len - len = (u32) gf_bs_get_position(bs) - 2; - af_data[1] = len; + end = gf_bs_get_position(bs); + len = (u32) (end - start - 2); + gf_bs_seek(bs, start+1); + gf_bs_write_int(bs, len, 8); + gf_bs_seek(bs, end); } if (timescale || ntp) { - Bool use64 = (timecode > 0xFFFFFFFFUL) ? GF_TRUE : GF_FALSE; + Bool use64; + if (mode_64bits==TEMI_TC64_AUTO) { + use64 = (timecode > 0xFFFFFFFFUL) ? GF_TRUE : GF_FALSE; + } else if (mode_64bits==TEMI_TC64_ALWAYS) { + use64 = GF_TRUE; + } else { + use64 = GF_FALSE; + while (timecode > 0xFFFFFFFFUL) { + timecode -= 0xFFFFFFFFUL; + } + + } + len = 3; //3 bytes flags if (timescale) len += 4 + (use64 ? 8 : 4); @@ -207,9 +279,7 @@ gf_bs_write_u64(bs, ntp); //ntp } } - res = (u32) gf_bs_get_position(bs); - gf_bs_del(bs); - return res; + return GF_OK; } @@ -314,11 +384,21 @@ } p = gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM); if (tspid->ctx->dash_mode) { - if (p && tspid->ctx->dash_seg_num && (tspid->ctx->dash_seg_num != p->value.uint)) { - tspid->has_seen_eods = GF_TRUE; + + if (tspid->has_seen_eods) + return GF_OK; + + //detect segment change + if (p && tspid->ctx->dash_seg_num && (tspid->ctx->dash_seg_num < p->value.uint)) { tspid->ctx->wait_dash_flush = GF_TRUE; tspid->ctx->dash_seg_num = p->value.uint; tspid->ctx->dash_file_name[0] = 0; + } + + //segment change is pending, check for filename as well - we don't do that in the previous test + //since the filename property is sent on a single pid, not each of them + if (tspid->ctx->wait_dash_flush && p && (tspid->ctx->dash_seg_num == p->value.uint)) { + tspid->has_seen_eods = GF_TRUE; p = gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENAME); if (p) { @@ -328,9 +408,7 @@ return GF_OK; } - if (tspid->has_seen_eods) - return GF_OK; - + //at this point the new segment is started if (p) tspid->ctx->dash_seg_num = p->value.uint; @@ -403,25 +481,59 @@ } es_pck.cts = cts; - if (tspid->temi_id) { - u64 ntp=0; - //TOCHECK: do we want media timeline or composition timeline ? - u64 tc = cts; - if (tspid->ctx->temi_offset) { - tc += ((u64) tspid->ctx->temi_offset) * ifce->timescale / 1000; - } + if (tspid->temi_descs) { + u32 i, count=gf_list_count(tspid->temi_descs); + + if (!tspid->temi_af_bs) tspid->temi_af_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + else gf_bs_reassign_buffer(tspid->temi_af_bs, tspid->af_data, tspid->af_data_alloc); + + for (i=0; i<count; i++) { + TEMIDesc *temi = gf_list_get(tspid->temi_descs, i); + u64 ntp=0; + u32 timescale = ifce->timescale; + u64 tc; - if (tspid->ctx->temi_ntp) { - u32 sec, frac; - gf_net_get_ntp(&sec, &frac); - ntp = sec; - ntp <<= 32; - ntp |= frac; + if (temi->timescale && (temi->timescale!=timescale)) { + timescale = temi->timescale; + } + if (temi->use_init_val) { + if (!temi->cts_at_init_val_plus_one) temi->cts_at_init_val_plus_one = cts+1; + + tc = (cts - (temi->cts_at_init_val_plus_one-1)); + if (timescale != ifce->timescale) { + tc *= temi->timescale; + tc /= ifce->timescale; + } + tc += temi->init_val; + } else { + //TOCHECK: do we want media timeline or composition timeline ? + tc = cts; + if (timescale != ifce->timescale) { + tc *= temi->timescale; + tc /= ifce->timescale; + } + } + + if (temi->offset) { + if (timescale != ifce->timescale) + tc += ((u64) temi->offset) * ifce->timescale / 1000; + else + tc += temi->offset; + } + + if (temi->ntp) { + u32 sec, frac; + gf_net_get_ntp(&sec, &frac); + ntp = sec; + ntp <<= 32; + ntp |= frac; + } + tsmux_format_af_descriptor(tspid->temi_af_bs, temi->id, tc, timescale, temi->mode_64bits, ntp, temi->url, temi->delay, &tspid->last_temi_url); } - es_pck.mpeg2_af_descriptors_size = tsmux_format_af_descriptor(tspid->af_data, tspid->temi_id, tc, tspid->esi.timescale, ntp, tspid->temi_url, tspid->ctx->temi_delay, &tspid->last_temi_url); + gf_bs_get_content_no_truncate(tspid->temi_af_bs, &tspid->af_data, &es_pck.mpeg2_af_descriptors_size, &tspid->af_data_alloc); es_pck.mpeg2_af_descriptors = tspid->af_data; } - es_pck.cts += tspid->prog->max_media_skip + tspid->media_delay; + es_pck.cts += tspid->max_media_skip + tspid->media_delay; if (tspid->nb_repeat_last) { es_pck.cts += tspid->nb_repeat_last * ifce->timescale * tspid->ctx->repeat_img / 1000; @@ -440,7 +552,7 @@ if (dts != GF_FILTER_NO_TS) { tspid->last_dts = dts; es_pck.dts = dts; - es_pck.dts += tspid->prog->max_media_skip + tspid->media_delay; + es_pck.dts += tspid->max_media_skip + tspid->media_delay; if (es_pck.dts > es_pck.cts) { u64 diff; @@ -629,11 +741,15 @@ static void tsmux_setup_temi(GF_TSMuxCtx *ctx, M2Pid *tspid) { GF_M2TS_Mux_Stream *a_stream; - u32 service_id=0; u32 st_idx=0; - char *turl = ctx->temi; - if (!turl) return; - u32 idx = 0; + const GF_PropertyValue *p; + char *temi_cfg; + + p = gf_filter_pid_get_property_str(tspid->ipid, "tsmux:temi"); + if (p && (p->type==GF_PROP_STRING)) temi_cfg = p->value.string; + else temi_cfg = ctx->temi; + + if (!temi_cfg) return; u32 temi_id=0; //find our stream index @@ -644,39 +760,126 @@ a_stream = a_stream->next; } - while (turl) { + while (temi_cfg) { + u32 service_id=0; + u32 temi_delay=1000; + u64 temi_offset=0; + u32 temi_timescale=0; + Bool temi_ntp=GF_FALSE; + u32 temi_64bits=TEMI_TC64_AUTO; + Bool temi_use_init_val=GF_FALSE; + u64 temi_init_val = 0; + u32 temi_streamtype=0; + u32 temi_index=0; + Bool done=GF_FALSE; char *sep; - if (turl[0]=='#') { - sscanf(turl, "#%d#", &service_id); - turl = strchr(turl+1, '#'); - if (!turl) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSMux] Invalid temi syntax, expecting #SID# but got nothing\n")); - return; + + if (!strlen(temi_cfg)) + break; + + while (temi_cfg[0]=='#') { + sep = strchr(temi_cfg+1, '#'); + if (!sep) { + temi_cfg += 1; + break; } - turl += 1; - idx = 0; + sep[0] = 0; + switch (temi_cfg[1]) { + case 'S': + service_id = atoi(temi_cfg+2); + break; + case 'N': + temi_ntp = GF_TRUE; + break; + case 'D': + temi_delay = atoi(temi_cfg+2); + break; + case 'O': + sscanf(temi_cfg+2, LLU, &temi_offset); + break; + case 'I': + sscanf(temi_cfg+2, LLU, &temi_init_val); + temi_use_init_val=GF_TRUE; + break; + case 'T': + temi_timescale = atoi(temi_cfg+2); + break; + case 'L': + if (temi_cfg[2]=='Y') temi_64bits = TEMI_TC64_ALWAYS; + else if (temi_cfg[2]=='N') temi_64bits = TEMI_TC64_OFF; + break; + case 'P': + //all pids target + if (!temi_cfg[2] || (temi_cfg[2]=='*')) { } + else if ((temi_cfg[2]=='v') || (temi_cfg[2]=='V')) { temi_streamtype = GF_STREAM_VISUAL; } + else if ((temi_cfg[2]=='a') || (temi_cfg[2]=='A')) { temi_streamtype = GF_STREAM_AUDIO; } + else if ((temi_cfg[2]=='t') || (temi_cfg[2]=='T')) { temi_streamtype = GF_STREAM_TEXT; } + else { + temi_index = atoi(temi_cfg+2); + } + break; + default: + done=GF_TRUE; + break; + } + sep[0] = '#'; + if (done) { + temi_cfg++; + break; + } + temi_cfg = sep; + } + if (!temi_cfg || !strlen(temi_cfg)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSMux] Invalid temi syntax, no ID or URL specified\n")); + return; } - sep = strchr(turl, ','); - if (sep) sep[0] = 0; - - if (strlen(turl) && (idx==st_idx) && (!service_id || (service_id == tspid->mstream->program->number) )) { - tspid->temi_id = atoi(turl); - if (!tspid->temi_id) { - tspid->temi_url = gf_strdup(turl); - tspid->temi_id = temi_id+1; + sep = strchr(temi_cfg, ','); + if (sep) sep[0] = 0; + + done = GF_TRUE; + if (temi_index && (temi_index!=st_idx)) done = GF_FALSE; + else if (temi_streamtype && (temi_streamtype!=tspid->esi.stream_type)) done = GF_FALSE; + else if (service_id && (service_id != tspid->mstream->program->number)) done = GF_FALSE; + + //that's for this stream + if (done) { + TEMIDesc *temi; + if (!tspid->temi_descs) tspid->temi_descs = gf_list_new(); + GF_SAFEALLOC(temi, TEMIDesc); + temi->id = atoi(temi_cfg); + if (!temi->id) { + temi->url = gf_strdup(temi_cfg); + temi->id = temi_id+1; } + temi->ntp = temi_ntp; + temi->offset = temi_offset; + temi->delay = temi_delay; + temi->timescale = temi_timescale; + temi->mode_64bits = temi_64bits; + temi->init_val = temi_init_val; + temi->use_init_val = temi_use_init_val; + gf_list_add(tspid->temi_descs, temi); } - idx++; if (!sep) break; sep[0] = ','; - turl = sep+1; + temi_cfg = sep+1; } } static void tsmux_del_stream(M2Pid *tspid) { - if (tspid->temi_url) gf_free(tspid->temi_url); + if (tspid->temi_descs) { + while (gf_list_count(tspid->temi_descs)) { + TEMIDesc *temi = gf_list_pop_back(tspid->temi_descs); + if (temi->url) gf_free(temi->url); + gf_free(temi); + } + gf_list_del(tspid->temi_descs); + } + if (tspid->af_data) gf_free(tspid->af_data); + if (tspid->temi_af_bs) gf_bs_del(tspid->temi_af_bs); + if (tspid->esi.sl_config) gf_free(tspid->esi.sl_config); if (tspid->pck_data_buf) gf_free(tspid->pck_data_buf); gf_free(tspid); @@ -733,10 +936,12 @@ gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, NULL); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) ); - gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("ts") ); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_FAKE_MP2T)); gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(90000)); gf_filter_pid_set_property(ctx->opid, GF_PROP_NO_TS_LOOP, &PROP_BOOL(GF_TRUE)); + gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DASH_MODE, NULL); + + mux_assign_mime_file_ext(pid, ctx->opid, M2TS_FILE_EXTS, M2TS_MIMES, "ts"); p = gf_filter_pid_get_info(pid, GF_PROP_PID_DASH_MODE, &pe); if (p) { @@ -773,7 +978,8 @@ prog = gf_m2ts_mux_program_find(ctx->mux, service_id); if (!prog) { u32 nb_progs; - u32 pcr_offset=0; + u64 first_pts_val; + u64 pcr_offset=0; u32 pmt_id = ctx->pmt_id; if (!pmt_id) pmt_id = 100; @@ -786,7 +992,10 @@ pmt_id += (nb_progs - 1) * 100; } - if (ctx->pcr_offset==(u32)-1) { + p = gf_filter_pid_get_property_str(tspid->ipid, "tsmux:pcr_offset"); + if (p && (p->type==GF_PROP_LUINT)) { + pcr_offset = p->value.longuint; + } else if (ctx->pcr_offset==(u64)-1) { p = gf_filter_pid_get_property(pid, GF_PROP_PID_MAX_FRAME_SIZE); if (p && p->value.uint && ctx->rate) { Double r = p->value.uint * 8; @@ -794,13 +1003,16 @@ r/= ctx->rate; //add 10% of safety to cover TS signaling and other potential table update while sending the largest PES r *= 1.1; - pcr_offset = (u32) r; + pcr_offset = (u64) r; } } else { pcr_offset = ctx->pcr_offset; } + p = gf_filter_pid_get_property_str(tspid->ipid, "tsmux:force_pts"); + if (p && (p->type==GF_PROP_LUINT)) first_pts_val = p->value.longuint; + else first_pts_val = ctx->first_pts; - prog = gf_m2ts_mux_program_add(ctx->mux, service_id, pmt_id, ctx->pmt_rate, pcr_offset, ctx->mpeg4, ctx->pmt_version, ctx->disc); + prog = gf_m2ts_mux_program_add(ctx->mux, service_id, pmt_id, ctx->pmt_rate, pcr_offset, ctx->mpeg4, ctx->pmt_version, ctx->disc, first_pts_val); if (sname) gf_m2ts_mux_program_set_name(prog, sname, pname); @@ -847,13 +1059,27 @@ tspid->media_delay = p->value.sint; //compute max ts skip for this program - prog->max_media_skip = 0; + s64 max_media_skip = 0; + u32 max_skip_ts = 0; ts_stream = prog->streams; while (ts_stream) { M2Pid *atspid = ts_stream->ifce->input_udta; - s32 media_skip = -atspid->media_delay; - if (media_skip > prog->max_media_skip) - prog->max_media_skip = media_skip ; + s64 media_skip = (s64) -atspid->media_delay; + if (media_skip > max_media_skip) { + max_media_skip = media_skip ; + max_skip_ts = atspid->esi.timescale; + } + ts_stream = ts_stream->next; + } + + ts_stream = prog->streams; + while (ts_stream) { + M2Pid *atspid = ts_stream->ifce->input_udta; + if (max_skip_ts) { + atspid->max_media_skip = (s32) (max_media_skip * atspid->esi.timescale / max_skip_ts); + } else { + atspid->max_media_skip = 0; + } ts_stream = ts_stream->next; } } @@ -942,12 +1168,16 @@ segidx_size += 24 +( large_sidx ? 16 : 8) + ctx->nb_sidx_entries*12; if (!ctx->idx_opid) { + const char *ext = gf_file_ext_start(ctx->idx_file_name); + if (!ext) ext = "idx"; + else ext++; ctx->idx_filter = gf_filter_connect_destination(filter, ctx->idx_file_name, NULL); ctx->idx_opid = gf_filter_pid_new(filter); gf_filter_pid_set_property(ctx->idx_opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) ); - gf_filter_pid_set_property(ctx->idx_opid, GF_PROP_PID_FILE_EXT, &PROP_STRING("*") ); + gf_filter_pid_set_property(ctx->idx_opid, GF_PROP_PID_FILE_EXT, &PROP_STRING(ext) ); gf_filter_pid_set_property(ctx->idx_opid, GF_PROP_PID_MIME, &PROP_STRING("*") ); gf_filter_pid_set_name(ctx->idx_opid, "ts_idx"); + if (ctx->idx_filter) gf_filter_set_source(ctx->idx_filter, filter, NULL); } idx_pck = gf_filter_pck_new_alloc(ctx->idx_opid, segidx_size, &output); @@ -1099,7 +1329,6 @@ M2Pid *tspid = gf_list_get(ctx->pids, i); tspid->has_seen_eods = 0; } - ctx->dash_seg_num = 0; ctx->wait_dash_flush = GF_FALSE; ctx->next_is_start = ctx->dash_file_switch; ctx->mux->force_pat = GF_TRUE; @@ -1108,6 +1337,7 @@ tsmux_insert_sidx(ctx, GF_TRUE); tsmux_send_seg_event(filter, ctx); } + ctx->dash_seg_num = 0; ctx->nb_pck_in_seg = 0; ctx->pck_start_idx = ctx->nb_pck; @@ -1153,6 +1383,7 @@ gf_filter_pck_set_framing(pck, ctx->nb_pck ? ctx->next_is_start : GF_TRUE, (status==GF_M2TS_STATE_EOS) ? GF_TRUE : GF_FALSE); if (ctx->next_is_start && ctx->dash_mode) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[M2TSMux] starting TS segment %d\r", ctx->dash_seg_num)); gf_filter_pck_set_property(pck, GF_PROP_PCK_FILENUM, &PROP_UINT(ctx->dash_seg_num) ); if (ctx->dash_file_name[0]) gf_filter_pck_set_property(pck, GF_PROP_PCK_FILENAME, &PROP_STRING(ctx->dash_file_name) ) ; @@ -1176,8 +1407,8 @@ } gf_filter_pck_send(pck); ctx->nb_pck += nb_pck_in_pack; - ctx->nb_pck_in_seg++; - ctx->nb_pck_in_file++; + ctx->nb_pck_in_seg += nb_pck_in_pack; + ctx->nb_pck_in_file += nb_pck_in_pack; nb_pck_in_call += nb_pck_in_pack; nb_pck_in_pack = 0; @@ -1359,10 +1590,10 @@ //static output cap file extension CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE), - CAP_STRING(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_FILE_EXT, "ts|m2t|mts|dmb|trp"), - CAP_STRING(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_MIME, "video/mpeg-2|video/mp2t|video/mpeg"), + CAP_STRING(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_FILE_EXT, M2TS_FILE_EXTS), + CAP_STRING(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_MIME, M2TS_MIMES), {0}, - + //for now don't accept files as input, although we could store them as items, to refine CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE), //these caps are framed @@ -1387,19 +1618,20 @@ { OFFS(rate), "target rate in bps of the multiplex. If not set, variable rate is used", GF_PROP_UINT, "0", NULL, 0}, { OFFS(pmt_rate), "interval between PMT in ms", GF_PROP_UINT, "200", NULL, 0}, { OFFS(pat_rate), "interval between PAT in ms", GF_PROP_UINT, "200", NULL, 0}, - { OFFS(pcr_offset), "offset all timestamps from PCR by V, in 90kHz. Default value is computed based on input media", GF_PROP_UINT, "-1", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(mpeg4), "force usage of MPEG-4 signaling (IOD and SL Config).\n"\ + { OFFS(first_pts), "force PTS value of first packet, in 90kHz", GF_PROP_LUINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(pcr_offset), "offset all timestamps from PCR by V, in 90kHz. Default value is computed based on input media", GF_PROP_LUINT, "-1", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(mpeg4), "force usage of MPEG-4 signaling (IOD and SL Config)\n"\ "- none: disables 4on2\n"\ "- full: sends AUs as SL packets over section for OD, section/pes for scene (cf bifs_pes)\n"\ "- scene: sends only scene streams as 4on2 but uses regular PES without SL for audio and video"\ , GF_PROP_UINT, "none", "none|full|scene", GF_FS_ARG_HINT_EXPERT}, { OFFS(pmt_version), "set version number of the PMT", GF_PROP_UINT, "200", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(disc), "set the discontinuity marker for the first packet of each stream", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(repeat_rate), "interval in ms between two carousel send for MPEG-4 systems. Is overriden by carousel duration PID property if defined", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(repeat_img), "interval in ms between resending (as PES) of single-image streams. If 0, image data is sent once only", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(repeat_rate), "interval in ms between two carousel send for MPEG-4 systems. Is overridden by carousel duration PID property if defined", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(repeat_img), "interval in ms between re-sending (as PES) of single-image streams. If 0, image data is sent once only", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(max_pcr), "set max interval in ms between 2 PCR", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(nb_pack), "pack N TS packets in output packets", GF_PROP_UINT, "4", NULL, 0}, - { OFFS(pes_pack), "set AU to PES packing mode.\n"\ + { OFFS(pes_pack), "set AU to PES packing mode\n"\ "- audio: will pack only multiple audio AUs in a PES\n"\ "- none: make exactly one AU per PES\n"\ "- all: will pack multiple AUs per PES for all streams", GF_PROP_UINT, "audio", "audio|none|all", GF_FS_ARG_HINT_ADVANCED}, @@ -1417,9 +1649,6 @@ { OFFS(sdt_rate), "interval in ms between two DVB SDT tables. If 0, SDT is disabled", GF_PROP_UINT, "0", NULL, 0}, { OFFS(temi), "insert TEMI time codes in adaptation field - see filter help", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(temi_delay), "set delay in ms between two TEMI url descriptors", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(temi_offset), "set offset in ms to add to TEMI timecodes", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(temi_ntp), "insert NTP timestamp in TEMI timeline descriptor", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(log_freq), "delay between logs for realtime mux", GF_PROP_UINT, "500", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(latm), "use LATM AAC encapsulation instead of regular ADTS", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(subs_sidx), "number of subsegments per sidx. negative value disables sidx", GF_PROP_SINT, "-1", NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -1433,28 +1662,50 @@ GF_FS_SET_HELP("GPAC TS multiplexer selects M2TS PID for media streams using the PID of the PMT plus the stream index.\n" "For example, default config creates the first program with a PMT PID 100, the first stream will have a PID of 101.\n" "Streams are grouped in programs based on input PID property ServiceID if present. If absent, stream will go in the program with service ID as indicated by [-sid]() option.\n" - "[-name]() option is overriden by input PID property `ServiceName`.\n" - "[-provider]() option is overriden by input PID property `ServiceProvider`.\n" + "- [-name]() option is overridden by input PID property `ServiceName`.\n" + "- [-provider]() option is overridden by input PID property `ServiceProvider`.\n" + "- [-pcr_offset]() option is overridden by input PID property `\"tsmux:pcr_offset\"`\n" + "- [-first_pts]() option is overridden by input PID property `\"tsmux:force_pts\"`\n" + "- [-temi]() option is overridden by input PID property `\"tsmux:temi\"`\n" + "\n" "# Time and External Media Information (TEMI)\n" - "The [-temi]() option allows specifying a list of URLs or timeline IDs to insert in the program.\n" - "Only a single TEMI timeline can be specified per PID.\n" - "The syntax is a comma-separated list of one or more TEMI description, each of them separated by '#'\n" - "Each TEMI description is formated as #ServiceID#ID_OR_URL, with:\n" - "- ServiceID: optional, number indicating the target serviceID\n" - "- ID_OR_URL: If numbern indicates the TEMI ID to use for external timeline. Otherwise, gives the URL to insert\n" - "Each comma-separated description designs a stream index in the target service.\n" - "EX temi=\"url\"\nIinserts a TEMI URL+timecode in the first stream of all programs.\n" - "EX temi=\"url,4\"\n" + "The [-temi]() option allows specifying a list of URLs or timeline IDs to insert in streams of a program.\n" + "One or more TEMI timeline can be specified per PID.\n" + "The syntax is a comma-separated list of one or more TEMI description.\n" + "Each TEMI description is formatted as ID_OR_URL or #OPT1[#OPT2]#ID_OR_URL. Options are:\n" + "- S`N`: gives number N indicating the target serviceID\n" + "- T`N`: set timescale to use (default: PID timescale)\n" + "- D`N`: set delay in ms between two TEMI url descriptors (default 1000)\n" + "- O`N`: set offset (max 64 bits) to add to TEMI timecodes (default 0). If timescale is not specified, offset value is in ms, otherwise in timescale units.\n" + "- I`N`: set initial value (max 64 bits) of TEMI timecodes. If not set, initial value will match first packet CTS. If timescale is not specified, value is in PID timescale units, otherwise in specified timescale units.\n" + "- P`N`: indicate target PID in program. Possible values are\n" + " - `V`: only insert for video streams.\n" + " - `A`: only insert for audio streams.\n" + " - `T`: only insert for text streams.\n" + " - N: only insert for stream with index N (0-based) in the program.\n" + "- L`N`: set 64bit timecode signaling. Possible values are:\n" + " - `A`: automatic switch between 32 and 64 bit depending on timecode value (default if not specified).\n" + " - `Y`: use 64 bit signaling only.\n" + " - `N`: use 32 bit signaling only and wrap around timecode value.\n" + "- N: insert NTP timestamp in TEMI timeline descriptor\n" + "- ID_OR_URL: If number, indicates the TEMI ID to use for external timeline. Otherwise, gives the URL to insert\n" + " \n" + "EX temi=\"url\"\n" + "Inserts a TEMI URL+timecode in the each stream of each program.\n" + "EX temi=\"#P0#url,#P1#4\"\n" "Inserts a TEMI URL+timecode in the first stream of all programs and an external TEMI with ID 4 in the second stream of all programs.\n" - "EX temi=\"#20#4,#10#URL\"\n" - "Inserts an external TEMI with ID 4 in the first stream of program with ServiceID 20 and a TEMI URL to the second stream of program with ServiceID 10.\n" - "EX temi=\"#20#4,,#10#URL\"\n" - "Inserts an external TEMI with ID 4 in the first stream of program with ServiceID 20 and a TEMI URL to the third stream of program with ServiceID 10 (and nothing on second stream).\n" + "EX temi=\"#P0#2,#P0#url,#P1#4\"\n" + "Inserts a TEMI with ID 2 and a TEMI URL+timecode in the first stream of all programs, and an external TEMI with ID 4 in the second stream of all programs.\n" + "EX temi=\"#S20#4,#S10#URL\"\n" + "Inserts an external TEMI with ID 4 in the each stream of program with ServiceID 20 and a TEMI URL in each stream of program with ServiceID 10.\n" + "EX temi=\"#N#D500#PV#T30000#4\"\n" + "Inserts an external TEMI with ID 4 and timescale 30000, NTP injection and carousel of 500 ms in the video stream of all programs.\n" "\n" + "Warning: multipliers (k,m,g) are not supported in TEMI options.\n" "# Notes\n" "In DASH mode, the PCR is always initialized at 0, and [-flush_rap]() is automatically set.\n" - "The filter watches the property `FileNumber` on incoming packets to create new files or new segments in DASH mode.\n" + "The filter watches the property `FileNumber` on incoming packets to create new files or new segments in DASH mode.\n" ) .private_size = sizeof(GF_TSMuxCtx), .args = TSMuxArgs,
View file
gpac-1.0.0.tar.gz/src/filters/out_http.c -> gpac-1.0.1.tar.gz/src/filters/out_http.c
Changed
@@ -769,7 +769,7 @@ } gf_dynstrcat(&full_path, url+1, NULL); - if (gf_file_exists(full_path)) + if (gf_file_exists(full_path) || gf_dir_exists(full_path) ) break; gf_free(full_path); full_path = NULL; @@ -2693,7 +2693,7 @@ "- an HTTP server __source__\n" " \n" "The server currently handles GET, HEAD, PUT, POST, DELETE methods.\n" - "Single or multiple byte ranges are supported for both GET and PUT/POST methods.\n" + "Single or multiple byte ranges are supported for both GET and PUT/POST methods, in all server modes.\n" "- for GET, the resulting body is a single-part body formed by the concatenated byte ranges as requested (no overlap checking).\n" "- for PUT/POST, the received data is pushed to the target file according to the byte ranges specified in the client request.\n" " \n" @@ -2731,16 +2731,20 @@ " \n" "In this mode, ICECast meta-data can be inserted using [-ice](). The default inserted values are `ice-audio-info`, `icy-br`, `icy-pub` (set to 1) and `icy-name` if input `ServiceName` property is set.\n" "The server will also look for any property called `ice-*` on the input pid and inject them.\n" - "EX gpac -i source.mp3:#ice-Genre=CoolRock -o http://IP/live.mp3:ice\n" + "EX gpac -i source.mp3:#ice-Genre=CoolRock -o http://IP/live.mp3 --ice\n" "This will inject the header `ice-Genre: CoolRock` in the response." " \n" "# HTTP server file sink\n" "In this mode, the filter will write input PIDs to files in the first read directory specified, acting as a file output sink.\n" "The filter uses a read directory in this mode, which must be writable.\n" - "Upon client GET request, the server will check if the requested file matches the name of a file currently being written by the server.\n" - "If so, the server will keep refreshing the source size until the associated input file is closed.\n" - "This mode is typically used for origin server in HAS sessions where clients may request files while they are being produced (low latency DASH).\n" - "EX gpac -i SOURCE -o http://localhost/live.mpd --rdirs=temp\n" + "Upon client GET request, the server will check if the requested URL matches the name of a file currently being written by the server.\n" + "- If so, the server will:\n" + " - send the content using HTTP chunk transfer mode, starting with what is already written on disk\n" + " - push remaining data to the client as soon as recieved while writing it to disk, until source file is done\n" + "- If not so, the server will simply send the file from the disk as a regular HTTP session, without chunk transfer.\n" + " \nThis mode is typically used for origin server in HAS sessions where clients may request files while they are being produced (low latency DASH).\n" + "EX gpac -i SOURCE reframer:rt=on @ -o http://localhost:8080/live.mpd --rdirs=temp --dmode=dynamic --cdur=0.1\n" + "In this example, a real-time dynamic DASH session with chunks of 100ms is created, outputing files in `temp`. A client connecting to the live edge will receive segments as they are produced using HTTP chunk transfer.\n" " \n" "# HTTP client sink\n" "In this mode, the filter will upload input PIDs data to remote server using PUT (or POST if [-post]() is set).\n" @@ -2759,7 +2763,7 @@ "# HTTPS server\n" "The server can run over TLS (https) for all the server modes. TLS is enabled by specifying [-cert]() and [-pkey]() options.\n" "Both certificate and key must be in PEM format.\n" - "Note: the server currently only operates in either HTTPS or HTTP mode and cannot run both modes at the same time. You will need to use two httpout filters for this, one operating in HTTPS and one operating in HTTP.\n" + "The server currently only operates in either HTTPS or HTTP mode and cannot run both modes at the same time. You will need to use two httpout filters for this, one operating in HTTPS and one operating in HTTP.\n" ) .private_size = sizeof(GF_HTTPOutCtx), .max_extra_pids = -1,
View file
gpac-1.0.0.tar.gz/src/filters/out_rtp.c -> gpac-1.0.1.tar.gz/src/filters/out_rtp.c
Changed
@@ -767,7 +767,7 @@ ctx->microsec_ts_init = min_dts; GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTPOut] RTP clock initialized - time origin set to "LLU" us (sys clock) / "LLU" us (media clock)\n", ctx->sys_clock_at_init, ctx->microsec_ts_init)); if (ctx->tso<0) { - gf_rand_init(0); + gf_rand_init(GF_FALSE); for (i=0; i<count; i++) { GF_RTPOutStream *stream = gf_list_get(ctx->streams, i); stream->rtp_ts_offset = gf_rand(); @@ -1131,7 +1131,7 @@ { OFFS(mtu), "size of RTP MTU in bytes", GF_PROP_UINT, "1460", NULL, 0}, { OFFS(ttl), "time-to-live for muticast packets", GF_PROP_UINT, "2", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(ifce), "default network inteface to use", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(payt), "payload type to use for dynamic configs.", GF_PROP_UINT, "96", "96-127", GF_FS_ARG_HINT_EXPERT}, + { OFFS(payt), "payload type to use for dynamic configs", GF_PROP_UINT, "96", "96-127", GF_FS_ARG_HINT_EXPERT}, { OFFS(delay), "send delay for packet (negative means send earlier)", GF_PROP_SINT, "0", NULL, 0}, { OFFS(tt), "time tolerance in microseconds. Whenever schedule time minus realtime is below this value, the packet is sent right away", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_HINT_EXPERT}, { OFFS(runfor), "run for the given time in ms. Negative value means run for ever (if loop) or source duration, 0 only outputs the sdp", GF_PROP_SINT, "-1", NULL, 0},
View file
gpac-1.0.0.tar.gz/src/filters/out_rtsp.c -> gpac-1.0.1.tar.gz/src/filters/out_rtsp.c
Changed
@@ -486,7 +486,7 @@ sess->microsec_ts_init = min_dts; GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTSPOut] Session %s: RTP clock initialized - time origin set to "LLU" us (sys clock) / "LLU" us (media clock)\n", sess->service_name, sess->sys_clock_at_init, sess->microsec_ts_init)); if (ctx->tso<0) { - gf_rand_init(0); + gf_rand_init(GF_FALSE); for (i=0; i<count; i++) { GF_RTPOutStream *stream = gf_list_get(sess->streams, i); stream->rtp_ts_offset = gf_rand(); @@ -625,7 +625,7 @@ } } if (!found) { - GF_Filter *filter_src = gf_filter_connect_source(filter, src_url, NULL, &e); + GF_Filter *filter_src = gf_filter_connect_source(filter, src_url, NULL, GF_FALSE, &e); if (!filter_src) { gf_rtsp_response_reset(sess->response); sess->response->ResponseCode = NC_RTSP_Session_Not_Found; @@ -1267,7 +1267,7 @@ { OFFS(mtu), "size of RTP MTU in bytes", GF_PROP_UINT, "1460", NULL, 0}, { OFFS(ttl), "time-to-live for muticast packets. A value of 0 uses client requested TTL, or 1", GF_PROP_UINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(ifce), "default network inteface to use", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(payt), "payload type to use for dynamic configs.", GF_PROP_UINT, "96", "96-127", GF_FS_ARG_HINT_EXPERT}, + { OFFS(payt), "payload type to use for dynamic configs", GF_PROP_UINT, "96", "96-127", GF_FS_ARG_HINT_EXPERT}, { OFFS(mpeg4), "send all streams using MPEG-4 generic payload format if posible", GF_PROP_BOOL, "false", NULL, 0}, { OFFS(delay), "send delay for packet (negative means send earlier)", GF_PROP_SINT, "0", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(tt), "time tolerance in microseconds. Whenever schedule time minus realtime is below this value, the packet is sent right away", GF_PROP_UINT, "1000", NULL, GF_FS_ARG_HINT_ADVANCED}, @@ -1280,9 +1280,9 @@ { OFFS(maxc), "maximum number of connections", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(user_agent), "user agent string, by default solved from GPAC preferences", GF_PROP_STRING, "$GUA", NULL, 0}, { OFFS(close), "close RTSP connection after each request, except when RTP over RTSP is used", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(loop), "loop all streams in session (not always possible depending on source type) - see filter help.", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(dynurl), "allow dynamic service assembly - see filter help.", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(mcast), "control multicast setup of a session.\n" + { OFFS(loop), "loop all streams in session (not always possible depending on source type) - see filter help", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(dynurl), "allow dynamic service assembly - see filter help", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(mcast), "control multicast setup of a session\n" "- off: clients are never allowed to create a multicast\n" "- on: clients can create multicast sessions\n" "- mirror: clients can create a multicast session. Any later request to the same URL will use that multicast session"
View file
gpac-1.0.0.tar.gz/src/filters/out_sock.c -> gpac-1.0.1.tar.gz/src/filters/out_sock.c
Changed
@@ -122,6 +122,11 @@ else { ext = gf_file_ext_start(ctx->dst); if (ext) ext++; + if (ext) { + const char *szport = strchr(ext, ':'); + if (szport) + ext = gf_file_ext_start(szport); + } } if (!ext && !ctx->mime) {
View file
gpac-1.0.0.tar.gz/src/filters/out_video.c -> gpac-1.0.1.tar.gz/src/filters/out_video.c
Changed
@@ -29,6 +29,7 @@ #include <gpac/modules/video_out.h> #include <gpac/color.h> +#ifndef GPAC_DISABLE_PLAYER //#define GPAC_DISABLE_3D @@ -615,6 +616,9 @@ return GF_TRUE; } +GF_VideoOutput *gf_filter_claim_opengl_provider(GF_Filter *filter); +Bool gf_filter_unclaim_opengl_provider(GF_Filter *filter, GF_VideoOutput *vout); + static GF_Err vout_initialize(GF_Filter *filter) { const char *sOpt; @@ -625,7 +629,14 @@ ctx->filter = filter; - ctx->video_out = (GF_VideoOutput *) gf_module_load(GF_VIDEO_OUTPUT_INTERFACE, ctx->drv); +#ifdef VOUT_USE_OPENGL + if (ctx->disp <= MODE_GL_PBO) { + ctx->video_out = (GF_VideoOutput *) gf_filter_claim_opengl_provider(filter); + } +#endif + + if (!ctx->video_out) + ctx->video_out = (GF_VideoOutput *) gf_module_load(GF_VIDEO_OUTPUT_INTERFACE, ctx->drv); if (ctx->dumpframes.nb_items) { @@ -666,11 +677,10 @@ return e; } - if ( !(ctx->video_out->hw_caps & GF_VIDEO_HW_OPENGL) -#ifndef VOUT_USE_OPENGL - || (1) +#ifdef VOUT_USE_OPENGL + if ( !(ctx->video_out->hw_caps & GF_VIDEO_HW_OPENGL) ) #endif - ) { + { if (ctx->disp < MODE_2D) { GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("No openGL support - using 2D rasterizer!\n", ctx->video_out->module_name)); ctx->disp = MODE_2D; @@ -695,6 +705,7 @@ } #endif + gf_filter_set_event_target(filter, GF_TRUE); return GF_OK; } @@ -721,8 +732,10 @@ /*stop and shutdown*/ if (ctx->video_out) { - ctx->video_out->Shutdown(ctx->video_out); - gf_modules_close_interface((GF_BaseInterface *)ctx->video_out); + if (! gf_filter_unclaim_opengl_provider(filter, ctx->video_out)) { + ctx->video_out->Shutdown(ctx->video_out); + gf_modules_close_interface((GF_BaseInterface *)ctx->video_out); + } ctx->video_out = NULL; } if (ctx->dump_buffer) gf_free(ctx->dump_buffer); @@ -1458,6 +1471,14 @@ vout_set_caption(ctx); return GF_TRUE; } + if (!fevt->base.on_pid && (fevt->base.type==GF_FEVT_USER)) { + GF_VideoOutCtx *ctx = (GF_VideoOutCtx *) gf_filter_get_udta(filter); + GF_Err e; + if (!ctx->video_out) return GF_FALSE; + e = ctx->video_out->ProcessEvent(ctx->video_out, (GF_Event *) &fevt->user_event.event); + if (e) return GF_FALSE; + return GF_TRUE; + } //cancel return GF_TRUE; } @@ -1486,8 +1507,8 @@ { OFFS(hide), "hide output window", GF_PROP_BOOL, "false", NULL, 0}, { OFFS(fullscreen), "use fullcreen", GF_PROP_BOOL, "false", NULL, 0}, { OFFS(buffer), "set buffer in ms", GF_PROP_UINT, "100", NULL, 0}, - { OFFS(dumpframes), "ordered list of frames to dump, 1 being first frame - see filter help. Special value 0 means dump all frames.", GF_PROP_UINT_LIST, NULL, NULL, GF_FS_ARG_HINT_EXPERT}, - { OFFS(out), "radical of dump frame filenames. If no extension is provided, frames are exported as $OUT_%d.PFMT.", GF_PROP_STRING, "dump", NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(dumpframes), "ordered list of frames to dump, 1 being first frame - see filter help. Special value 0 means dump all frames", GF_PROP_UINT_LIST, NULL, NULL, GF_FS_ARG_HINT_EXPERT}, + { OFFS(out), "radical of dump frame filenames. If no extension is provided, frames are exported as $OUT_%d.PFMT", GF_PROP_STRING, "dump", NULL, GF_FS_ARG_HINT_EXPERT}, {0} }; @@ -1525,3 +1546,9 @@ { return &VideoOutRegister; } +#else +const GF_FilterRegister *vout_register(GF_FilterSession *session) +{ + return NULL; +} +#endif // GPAC_DISABLE_PLAYER
View file
gpac-1.0.0.tar.gz/src/filters/reframe_ac3.c -> gpac-1.0.1.tar.gz/src/filters/reframe_ac3.c
Changed
@@ -534,13 +534,17 @@ static const char *ac3dmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score) { u32 nb_frames=0; + Bool has_broken_frames = GF_FALSE; u32 pos=0; while (1) { GF_AC3Header ahdr; if (! gf_ac3_parser((u8 *) data, size, &pos, &ahdr, GF_FALSE) ) break; u32 fsize = ahdr.framesize; - if (pos) nb_frames=0; + if (pos) { + nb_frames=0; + has_broken_frames = GF_TRUE; + } nb_frames++; if (fsize > size+pos) break; if (nb_frames>4) break; @@ -549,7 +553,7 @@ data += fsize+pos; } if (nb_frames>2) { - *score = GF_FPROBE_SUPPORTED; + *score = has_broken_frames ? GF_FPROBE_MAYBE_SUPPORTED : GF_FPROBE_SUPPORTED; return "audio/ac3"; } return NULL;
View file
gpac-1.0.0.tar.gz/src/filters/reframe_adts.c -> gpac-1.0.1.tar.gz/src/filters/reframe_adts.c
Changed
@@ -783,6 +783,7 @@ ADTSHeader prev_hdr; GF_BitStream *bs; Bool has_id3=GF_FALSE; + Bool has_broken_data=GF_FALSE; /*check for id3*/ if (size>= 10) { @@ -823,6 +824,7 @@ break; } else { nb_frames=1; + has_broken_data=GF_TRUE; } prev_hdr = hdr; gf_bs_skip_bytes(bs, hdr.frame_size); @@ -830,7 +832,7 @@ } gf_bs_del(bs); if (max_consecutive_frames>=4) { - *score = GF_FPROBE_SUPPORTED; + *score = has_broken_data ? GF_FPROBE_MAYBE_SUPPORTED : GF_FPROBE_SUPPORTED; return "audio/aac"; } if (has_id3 && max_consecutive_frames) {
View file
gpac-1.0.0.tar.gz/src/filters/reframe_mp3.c -> gpac-1.0.1.tar.gz/src/filters/reframe_mp3.c
Changed
@@ -185,7 +185,7 @@ #include <gpac/utf.h> -static void id3dmx_set_string(GF_FilterPid *apid, char *name, u8 *buf) +static void id3dmx_set_string(GF_FilterPid *apid, char *name, u8 *buf, Bool is_dyn) { if ((buf[0]==0xFF) || (buf[0]==0xFE)) { const u16 *sptr = (u16 *) (buf+2); @@ -194,13 +194,21 @@ len = (s32) gf_utf8_wcstombs(tmp, len, &sptr); if (len>=0) { tmp[len] = 0; - gf_filter_pid_set_property_dyn(apid, name, &PROP_STRING(tmp) ); + if (is_dyn) { + gf_filter_pid_set_property_dyn(apid, name, &PROP_STRING(tmp) ); + } else { + gf_filter_pid_set_property_str(apid, name, &PROP_STRING(tmp) ); + } } else { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[MP3Dmx] Corrupted ID3 text frame %s\n", name)); } gf_free(tmp); } else { - gf_filter_pid_set_property_dyn(apid, name, &PROP_STRING(buf) ); + if (is_dyn) { + gf_filter_pid_set_property_dyn(apid, name, &PROP_STRING(buf) ); + } else { + gf_filter_pid_set_property_str(apid, name, &PROP_STRING(buf) ); + } } } @@ -226,6 +234,7 @@ while (size && (gf_bs_available(bs)>=10) ) { char szTag[1024]; char *sep; + s32 tag_idx; u32 pic_size; //u32 pic_type; u32 ftag = gf_bs_read_u32(bs); @@ -250,38 +259,22 @@ buf[fsize]=0; buf[fsize+1]=0; - switch (ftag) { - case ID3V2_FRAME_TIT2: - id3dmx_set_string(audio_pid, "tag:title", buf+1); - break; - case ID3V2_FRAME_TPE1: - id3dmx_set_string(audio_pid, "tag:artist", buf+1); - break; - case ID3V2_FRAME_TALB: - id3dmx_set_string(audio_pid, "tag:album", buf+1); - break; - case ID3V2_FRAME_TCON: - id3dmx_set_string(audio_pid, "tag:genre", buf+1); - break; - case ID3V2_FRAME_TDRC: - id3dmx_set_string(audio_pid, "tag:recdate", buf+1); - break; - case ID3V2_FRAME_TRCK: - id3dmx_set_string(audio_pid, "tag:tracknum", buf+1); - break; - case ID3V2_FRAME_TSSE: - id3dmx_set_string(audio_pid, "tag:encoder", buf+1); - break; - case ID3V2_FRAME_TXXX: + tag_idx = gf_itags_find_by_id3tag(ftag); + if (tag_idx>=0) { + const char *tag_name = gf_itags_get_name((u32) tag_idx); + id3dmx_set_string(audio_pid, (char *) tag_name, buf+1, GF_FALSE); + } else if (ftag==GF_ID3V2_FRAME_TXXX) { sep = memchr(buf, 0, fsize); if (sep) { - strcpy(szTag, "tag:"); - strncat(szTag, buf+1, 1019); - id3dmx_set_string(audio_pid, szTag, sep+1); + if (!stricmp(buf+1, "comment")) { + id3dmx_set_string(audio_pid, "comment", sep+1, GF_FALSE); + } else { + strcpy(szTag, "tag_"); + strncat(szTag, buf+1, 1019); + id3dmx_set_string(audio_pid, szTag, sep+1, GF_TRUE); + } } - break; - - case ID3V2_FRAME_APIC: + } else if (ftag == GF_ID3V2_FRAME_APIC) { //first char is text encoding //then mime sep = memchr(buf+1, 0, fsize-1); @@ -314,15 +307,12 @@ gf_filter_pid_set_property(audio_pid, GF_PROP_PID_COVER_ART, &PROP_DATA(sep_desc+1, pic_size) ); } } - break; - - default: - sprintf(szTag, "tag:%s", gf_4cc_to_str(ftag)); - + } else { + sprintf(szTag, "tag_%s", gf_4cc_to_str(ftag)); if ((ftag>>24) == 'T') { - id3dmx_set_string(audio_pid, szTag, buf+1); + id3dmx_set_string(audio_pid, szTag, buf+1, GF_TRUE); } else { - gf_filter_pid_set_property_str(audio_pid, szTag, &PROP_DATA(buf, fsize) ); + gf_filter_pid_set_property_dyn(audio_pid, szTag, &PROP_DATA(buf, fsize) ); } break; }
View file
gpac-1.0.0.tar.gz/src/filters/reframe_nalu.c -> gpac-1.0.1.tar.gz/src/filters/reframe_nalu.c
Changed
@@ -53,13 +53,20 @@ u32 min_temporal_id, max_temporal_id; } LHVCLayerInfo; +enum { + STRICT_POC_OFF = 0, + STRICT_POC_ON, + STRICT_POC_ERROR, +}; + typedef struct { //filter args GF_Fraction fps; Double index; - Bool explicit, force_sync, strict_poc, nosei, importer, subsamples, nosvc, novpsext, deps, seirw, audelim, analyze; + Bool explicit, force_sync, nosei, importer, subsamples, nosvc, novpsext, deps, seirw, audelim, analyze; u32 nal_length; + u32 strict_poc; GF_Fraction idur; //only one input pid declared @@ -71,8 +78,8 @@ GF_BitStream *bs_r; //write bitstream for nalus size length rewrite GF_BitStream *bs_w; - //current CTS/DTS of the stream, may be overriden by input packet if not file (eg TS PES) - u64 cts, dts, prev_dts; + //current CTS/DTS of the stream, may be overridden by input packet if not file (eg TS PES) + u64 cts, dts, prev_dts, prev_cts; u32 pck_duration; //basic config stored here: with, height CRC of base and enh layer decoder config, sample aspect ratio //when changing, a new pid config will be emitted @@ -126,7 +133,7 @@ //list of packet (in decode order !!) not yet dispatched. //Dispatch depends on the mode: //strict_poc=0: we wait after each IDR until we find a stable poc diff between pictures, controled by poc_probe_done - //strict_poc=1: we dispatch only after IDR or at the end (huge delay) + //strict_poc>=1: we dispatch only after IDR or at the end (huge delay) GF_List *pck_queue; //dts of the last IDR found u64 dts_last_IDR; @@ -208,6 +215,8 @@ char init_aud[3]; Bool interlaced, eos_in_bs; + + Bool is_mvc; } GF_NALUDmxCtx; @@ -270,10 +279,14 @@ } } if (ctx->is_hevc) { +#ifdef GPAC_DISABLE_HEVC + return GF_NOT_SUPPORTED; +#else ctx->log_name = "HEVC"; if (ctx->avc_state) gf_free(ctx->avc_state); if (!ctx->hevc_state) GF_SAFEALLOC(ctx->hevc_state, HEVCState); ctx->min_layer_id = 0xFF; +#endif } else { ctx->log_name = "AVC|H264"; if (ctx->hevc_state) gf_free(ctx->hevc_state); @@ -384,6 +397,7 @@ gf_bs_seek(bs, nal_start); if (hevc_state) { +#ifndef GPAC_DISABLE_HEVC u8 temporal_id, layer_id, nal_type; res = gf_media_hevc_parse_nalu_bs(bs, hevc_state, &nal_type, &temporal_id, &layer_id); @@ -411,6 +425,7 @@ is_slice = GF_TRUE; break; } +#endif // GPAC_DISABLE_HEVC } else { u32 nal_type; u64 pos = gf_bs_get_position(bs); @@ -496,7 +511,39 @@ //TODO: we are dispatching frames in "negctts mode", ie we may have DTS>CTS //need to signal this for consumers using DTS (eg MPEG-2 TS) if (flush_ref && ctx->pck_queue && ctx->poc_diff) { + u32 dts_inc=0; + s32 last_poc = 0; + Bool patch_missing_frame = GF_FALSE; //send all reference packet queued + if (ctx->strict_poc==STRICT_POC_ERROR) { + u32 i; + u32 nb_bframes = 0; + for (i=0; i<gf_list_count(ctx->pck_queue); i++) { + s32 poc; + u64 poc_ts, dts; + GF_FilterPacket *q_pck = gf_list_get(ctx->pck_queue, i); + + if (q_pck == ctx->first_pck_in_au) break; + + dts = gf_filter_pck_get_dts(q_pck); + if (dts == GF_FILTER_NO_TS) continue; + poc_ts = gf_filter_pck_get_cts(q_pck); + assert(poc_ts != GF_FILTER_NO_TS); + poc = (s32) ((s64) poc_ts - CTS_POC_OFFSET_SAFETY); + + if (i) { + if (last_poc>poc) nb_bframes ++; + else if (last_poc + ctx->poc_diff<poc) + patch_missing_frame = GF_TRUE; + } + last_poc = poc; + } + if (nb_bframes>1) + patch_missing_frame = GF_FALSE; + else if (nb_bframes) + patch_missing_frame = GF_TRUE; + } + last_poc = GF_INT_MIN; while (gf_list_count(ctx->pck_queue) ) { u64 dts; @@ -519,9 +566,30 @@ } gf_filter_pck_set_carousel_version(q_pck, 0); + poc_ts = gf_filter_pck_get_cts(q_pck); assert(poc_ts != GF_FILTER_NO_TS); poc = (s32) ((s64) poc_ts - CTS_POC_OFFSET_SAFETY); + + if (patch_missing_frame) { + if (last_poc!=GF_INT_MIN) { + //check if we missed an IDR (poc reset) + if (poc && (last_poc > poc) ) { + last_poc = 0; + dts_inc += ctx->cur_fps.den; + ctx->dts_last_IDR = dts; + ctx->dts += ctx->cur_fps.den; + } + //check if we miss a frame + while (last_poc + ctx->poc_diff < poc) { + last_poc += ctx->poc_diff; + dts_inc += ctx->cur_fps.den; + ctx->dts += ctx->cur_fps.den; + } + } + last_poc = poc; + dts += dts_inc; + } //poc is stored as diff since last IDR which has min_poc cts = ( (ctx->min_poc + (s32) poc) * ctx->cur_fps.den ) / ctx->poc_diff + ctx->dts_last_IDR; @@ -555,6 +623,8 @@ gf_list_add(ctx->pck_queue, n_pck); } +#ifndef GPAC_DISABLE_HEVC + static void naludmx_hevc_add_param(GF_HEVCConfig *cfg, GF_AVCConfigSlot *sl, u8 nal_type) { GF_HEVCParamArray *pa = NULL; @@ -610,6 +680,7 @@ else if (!use_tiles && (use_wpp==nb_pps) ) hevc_cfg->parallelismType = 3; else hevc_cfg->parallelismType = 0; } +#endif // GPAC_DISABLE_HEVC GF_Err naludmx_set_hevc_oinf(GF_NALUDmxCtx *ctx, u8 *max_temporal_id) { @@ -785,6 +856,7 @@ static void naludmx_create_hevc_decoder_config(GF_NALUDmxCtx *ctx, u8 **dsi, u32 *dsi_size, u8 **dsi_enh, u32 *dsi_enh_size, u32 *max_width, u32 *max_height, u32 *max_enh_width, u32 *max_enh_height, GF_Fraction *sar, Bool *has_hevc_base) { +#ifndef GPAC_DISABLE_HEVC u32 i, count; u8 layer_id; Bool first = GF_TRUE; @@ -947,6 +1019,7 @@ } gf_odf_hevc_cfg_del(hvcc); gf_odf_hevc_cfg_del(lvcc); +#endif // GPAC_DISABLE_HEVC } void naludmx_create_avc_decoder_config(GF_NALUDmxCtx *ctx, u8 **dsi, u32 *dsi_size, u8 **dsi_enh, u32 *dsi_enh_size, u32 *max_width, u32 *max_height, u32 *max_enh_width, u32 *max_enh_height, GF_Fraction *sar) @@ -968,6 +1041,7 @@ avcc->nal_unit_size = ctx->nal_length; svcc->nal_unit_size = ctx->nal_length; + ctx->is_mvc = GF_FALSE; count = gf_list_count(ctx->sps); for (i=0; i<count; i++) { Bool is_svc = GF_FALSE; @@ -975,6 +1049,10 @@ AVC_SPS *sps = &ctx->avc_state->sps[sl->id]; u32 nal_type = sl->data[0] & 0x1F; + if ((sps->profile_idc == 118) || (sps->profile_idc == 128)) { + ctx->is_mvc = GF_TRUE; + } + if (ctx->explicit) { cfg = svcc; } else if (nal_type == GF_AVC_NALU_SVC_SUBSEQ_PARAM) { @@ -1614,9 +1692,11 @@ ctx->subs_mapped_bytes += subs_size + ctx->nal_length; } - static s32 naludmx_parse_nal_hevc(GF_NALUDmxCtx *ctx, char *data, u32 size, Bool *skip_nal, Bool *is_slice, Bool *is_islice) { +#ifdef GPAC_DISABLE_HEVC + return -1; +#else s32 ps_idx = 0; s32 res; u8 nal_unit_type, temporal_id, layer_id; @@ -1781,6 +1861,7 @@ ctx->max_temporal_id[layer_id] = temporal_id; if (ctx->min_layer_id > layer_id) ctx->min_layer_id = layer_id; return res; +#endif // GPAC_DISABLE_HEVC } static s32 naludmx_parse_nal_avc(GF_NALUDmxCtx *ctx, char *data, u32 size, u32 nal_type, Bool *skip_nal, Bool *is_slice, Bool *is_islice) @@ -1929,6 +2010,11 @@ } } *is_slice = GF_TRUE; + //we disable temporal scalability when parsing mvc - never used and many encoders screw up POC in enhancemen + if (ctx->is_mvc && (res>=0)) { + res=0; + ctx->avc_state->s_info.poc = ctx->last_poc; + } if (ctx->avc_state->s_info.sps) { switch (ctx->avc_state->s_info.slice_type) { case GF_AVC_TYPE_P: @@ -1959,6 +2045,45 @@ ctx->eos_in_bs = GF_TRUE; } +static void naldmx_switch_timestamps(GF_NALUDmxCtx *ctx, GF_FilterPacket *pck) +{ + //input pid sets some timescale - we flushed pending data , update cts + if (ctx->timescale) { + u64 ts = gf_filter_pck_get_cts(pck); + if (ts != GF_FILTER_NO_TS) { + ctx->prev_cts = ctx->cts; + ctx->cts = ts; + } + ts = gf_filter_pck_get_dts(pck); + if (ts != GF_FILTER_NO_TS) { + GF_FilterClockType ck_type = gf_filter_pid_get_clock_info(ctx->ipid, NULL, NULL); + if (ck_type==GF_FILTER_CLOCK_PCR_DISC) + ctx->dts = ts; + else if (ctx->dts<ts) + ctx->dts=ts; + + if (!ctx->prev_dts) ctx->prev_dts = ts; + else if (ctx->prev_dts != ts) { + u64 diff = ts; + diff -= ctx->prev_dts; + if (!ctx->cur_fps.den) + ctx->cur_fps.den = (u32) diff; + else if (ctx->cur_fps.den > diff) + ctx->cur_fps.den = (u32) diff; + + ctx->prev_dts = ts; + } + } + ctx->pck_duration = gf_filter_pck_get_duration(pck); + if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck); + ctx->src_pck = pck; + gf_filter_pck_ref_props(&ctx->src_pck); + //store framing flags. If input_is_au_start, the first NAL of the first frame begining in this packet will + //use the DTS/CTS of the input packet, otherwise we will use our internal POC recompute + gf_filter_pck_get_framing(pck, &ctx->input_is_au_start, NULL); + } +} + GF_Err naludmx_process(GF_Filter *filter) { GF_NALUDmxCtx *ctx = gf_filter_get_udta(filter); @@ -1990,6 +2115,9 @@ if (ctx->first_pck_in_au) { naludmx_finalize_au_flags(ctx); } + //single-frame stream + if (!ctx->poc_diff) ctx->poc_diff = 1; + ctx->strict_poc = STRICT_POC_OFF; naludmx_enqueue_or_dispatch(ctx, NULL, GF_TRUE); if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck); ctx->src_pck = NULL; @@ -2012,39 +2140,9 @@ start = data; remain = pck_size; - //input pid sets some timescale - we flushed pending data , update cts - if (ctx->timescale) { - u64 ts = gf_filter_pck_get_cts(pck); - if (ts != GF_FILTER_NO_TS) - ctx->cts = ts; - ts = gf_filter_pck_get_dts(pck); - if (ts != GF_FILTER_NO_TS) { - GF_FilterClockType ck_type = gf_filter_pid_get_clock_info(ctx->ipid, NULL, NULL); - if (ck_type==GF_FILTER_CLOCK_PCR_DISC) - ctx->dts = ts; - else if (ctx->dts<ts) - ctx->dts=ts; - - if (!ctx->prev_dts) ctx->prev_dts = ts; - else if (ctx->prev_dts != ts) { - u64 diff = ts; - diff -= ctx->prev_dts; - if (!ctx->cur_fps.den) - ctx->cur_fps.den = (u32) diff; - else if (ctx->cur_fps.den > diff) - ctx->cur_fps.den = (u32) diff; - - ctx->prev_dts = ts; - } - } - ctx->pck_duration = gf_filter_pck_get_duration(pck); - if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck); - ctx->src_pck = pck; - gf_filter_pck_ref_props(&ctx->src_pck); - //store framing flags. If input_is_au_start, the first NAL of the first frame begining in this packet will - //use the DTS/CTS of the inout packet, otherwise we will use our internal POC recompute - gf_filter_pck_get_framing(pck, &ctx->input_is_au_start, NULL); - } + //if we have bytes from previous packet in the header, we cannot switch timing until we know what these bytes are + if (!ctx->bytes_in_header) + naldmx_switch_timestamps(ctx, pck); //we stored some data to find the complete vosh, aggregate this packet with current one if (!ctx->resume_from && ctx->hdr_store_size) { @@ -2169,6 +2267,9 @@ //hence current+sc_pos-ctx->bytes_in_header in the new packet hdr_offset = current + sc_size - ctx->bytes_in_header; nal_sc_in_store = GF_TRUE; + + //since the nal is completely in the pes, its timestamp is the one of the source packet, switch timing + naldmx_switch_timestamps(ctx, pck); } else { //this is trickier, nal start is in the store buffer u8 lastb2, lastb1, nextb1; @@ -2563,7 +2664,7 @@ //store all variables needed to compute POC/CTS and sample SAP and recovery info if (ctx->is_hevc) { - +#ifndef GPAC_DISABLE_HEVC slice_is_ref = gf_media_hevc_slice_is_IDR(ctx->hevc_state); recovery_point_valid = ctx->hevc_state->sei.recovery_point.valid; @@ -2598,30 +2699,31 @@ slice_is_b = GF_TRUE; break; } - +#endif // GPAC_DISABLE_HEVC } else { /*fixme - we need finer grain for priority*/ if ((nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE)) { - unsigned char *p = (unsigned char *) start; - // RefPicFlag - avc_svc_subs_reserved |= (p[0] & 0x60) ? 0x80000000 : 0; - // RedPicFlag TODO: not supported, would require to parse NAL unit payload - avc_svc_subs_reserved |= (0) ? 0x40000000 : 0; - // VclNALUnitFlag - avc_svc_subs_reserved |= (1<=nal_type && nal_type<=5) || (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE) ? 0x20000000 : 0; - // use values of IdrFlag and PriorityId directly from SVC extension header - avc_svc_subs_reserved |= p[1] << 16; - // use values of DependencyId and QualityId directly from SVC extension header - avc_svc_subs_reserved |= p[2] << 8; - // use values of TemporalId and UseRefBasePicFlag directly from SVC extension header - avc_svc_subs_reserved |= p[3] & 0xFC; - // StoreBaseRepFlag TODO: SVC FF mentions a store_base_rep_flag which cannot be found in SVC spec - avc_svc_subs_reserved |= (0) ? 0x00000002 : 0; - - // priority_id (6 bits) in SVC has inverse meaning -> lower value means higher priority - invert it and scale it to 8 bits - avc_svc_subs_priority = (63 - (p[1] & 0x3F)) << 2; + if (!ctx->is_mvc) { + unsigned char *p = (unsigned char *) start; + // RefPicFlag + avc_svc_subs_reserved |= (p[0] & 0x60) ? 0x80000000 : 0; + // RedPicFlag TODO: not supported, would require to parse NAL unit payload + avc_svc_subs_reserved |= (0) ? 0x40000000 : 0; + // VclNALUnitFlag + avc_svc_subs_reserved |= (1<=nal_type && nal_type<=5) || (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) || (nal_type==GF_AVC_NALU_SVC_SLICE) ? 0x20000000 : 0; + // use values of IdrFlag and PriorityId directly from SVC extension header + avc_svc_subs_reserved |= p[1] << 16; + // use values of DependencyId and QualityId directly from SVC extension header + avc_svc_subs_reserved |= p[2] << 8; + // use values of TemporalId and UseRefBasePicFlag directly from SVC extension header + avc_svc_subs_reserved |= p[3] & 0xFC; + // StoreBaseRepFlag TODO: SVC FF mentions a store_base_rep_flag which cannot be found in SVC spec + avc_svc_subs_reserved |= (0) ? 0x00000002 : 0; + // priority_id (6 bits) in SVC has inverse meaning -> lower value means higher priority - invert it and scale it to 8 bits + avc_svc_subs_priority = (63 - (p[1] & 0x3F)) << 2; + } if (nal_type==GF_AVC_NALU_SVC_PREFIX_NALU) { if (ctx->svc_prefix_buffer_size) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[%s] broken bitstream, two consecutive SVC prefix NALU without SVC slice inbetween\n", ctx->log_name)); @@ -2745,8 +2847,8 @@ //second frame with the same poc diff, we should be able to properly recompute CTSs ctx->poc_probe_done = GF_TRUE; } + ctx->last_poc = slice_poc; } - ctx->last_poc = slice_poc; GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[%s] POC is %d - min poc diff %d - slice is ref %d\n", ctx->log_name, slice_poc, ctx->poc_diff, slice_is_ref)); /*ref slice, reset poc*/ @@ -2883,6 +2985,8 @@ ctx->bytes_in_header -= next_size+store_sc_size; continue; } + //we're done consuming data from previous packet, switch timing + naldmx_switch_timestamps(ctx, pck); } else { //bytes only come from the data packet memcpy(pck_data, pck_start, (size_t) size); @@ -3163,7 +3267,10 @@ { OFFS(fps), "import frame rate (0 default to FPS from bitstream or 25 Hz)", GF_PROP_FRACTION, "0/1000", NULL, 0}, { OFFS(index), "indexing window length. If 0, bitstream is not probed for duration. A negative value skips the indexing if the source file is larger than 100M (slows down importers) unless a play with start range > 0 is issued, otherwise uses the positive value", GF_PROP_DOUBLE, "-1.0", NULL, 0}, { OFFS(explicit), "use explicit layered (SVC/LHVC) import", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(strict_poc), "delay frame output of an entire GOP to ensure CTS info is correct when POC suddenly changes", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(strict_poc), "delay frame output of an entire GOP to ensure CTS info is correct when POC suddenly changes\n" + "- off: disable GOP buffering\n" + "- on: enable GOP buffering, assuming no error in POC\n" + "- error: enable GOP buffering and try to detect lost frames", GF_PROP_UINT, "off", "off|on|error", GF_FS_ARG_HINT_ADVANCED}, { OFFS(nosei), "remove all sei messages", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(nosvc), "remove all SVC/MVC/LHVC data", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(novpsext), "remove all VPS extensions", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
View file
gpac-1.0.0.tar.gz/src/filters/reframer.c -> gpac-1.0.1.tar.gz/src/filters/reframer.c
Changed
@@ -971,8 +971,9 @@ nb_eos++; } } - //some streams are not done and we have an estimated size less than target split - if ((nb_eos < count ) && (cumulated_size < ctx->split_size) + //not done yet (estimated size less than target split) + if ( + (cumulated_size < ctx->split_size) && ctx->min_ts_scale //do this only if first time we estimate this chunk size, or if previous estimated min_ts is not the same as current min_ts && (!ctx->prev_min_ts_computed || (ctx->prev_min_ts_computed < ctx->min_ts_computed)) @@ -987,7 +988,8 @@ } return; } - //decide which one we use + + //decide which split size we use if (ctx->xround==REFRAME_ROUND_BEFORE) { use_prev = GF_TRUE; } else if (ctx->xround==REFRAME_ROUND_AFTER) { @@ -1583,6 +1585,7 @@ if (!ctx->filter_sap3) forward = GF_FALSE; break; case GF_FILTER_SAP_4: + case GF_FILTER_SAP_4_PROL: if (!ctx->filter_sap4) forward = GF_FALSE; break; default:
View file
gpac-1.0.0.tar.gz/src/filters/resample_audio.c -> gpac-1.0.1.tar.gz/src/filters/resample_audio.c
Changed
@@ -28,6 +28,8 @@ #include <gpac/filters.h> #include <gpac/internal/compositor_dev.h> +#ifndef GPAC_DISABLE_PLAYER + typedef struct { //opts @@ -392,3 +394,11 @@ { return &ResamplerRegister; } +#else + +const GF_FilterRegister *resample_register(GF_FilterSession *session) +{ + return NULL; +} + +#endif // GPAC_DISABLE_PLAYER
View file
gpac-1.0.0.tar.gz/src/filters/rewrite_adts.c -> gpac-1.0.1.tar.gz/src/filters/rewrite_adts.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2000-2017 + * Copyright (c) Telecom ParisTech 2000-2020 * All rights reserved * * This file is part of GPAC / AAC ADTS write filter @@ -87,12 +87,7 @@ p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE); if (!p) return GF_NOT_SUPPORTED; sr = p->value.uint; - for (i=0; i<16; i++) { - if (GF_M4ASampleRates[i] == (u32) sr) { - ctx->sr_idx = i; - break; - } - } + ctx->channels = 0; p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS); if (p) @@ -140,10 +135,14 @@ #ifndef GPAC_DISABLE_AV_PARSERS if (ctx->channels && acfg.nb_chan && (ctx->channels != acfg.nb_chan)) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("RFADTS] Mismatch betwwen container number of channels (%d) and AAC config (%d), using AAC config\n", ctx->channels, acfg.nb_chan)); + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] Mismatch betwwen container number of channels (%d) and AAC config (%d), using AAC config\n", ctx->channels, acfg.nb_chan)); ctx->channels = acfg.nb_chan; patch_channels = GF_TRUE; } + if ((acfg.base_object_type==2) && (acfg.base_sr!=sr)) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[RFADTS] Mismatch betwwen container samplerate (%d) and AAC config SBR base samplerate (%d), using AAC config\n", sr, acfg.base_sr)); + sr = acfg.base_sr; + } #else p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG); @@ -159,6 +158,14 @@ GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("RFADTS] no channel config found for ADTS, forcing stereo\n")); } + for (i=0; i<16; i++) { + if (GF_M4ASampleRates[i] == (u32) sr) { + ctx->sr_idx = i; + break; + } + } + + if (!ctx->opid) { ctx->opid = gf_filter_pid_new(filter); }
View file
gpac-1.0.0.tar.gz/src/filters/rewrite_obu.c -> gpac-1.0.1.tar.gz/src/filters/rewrite_obu.c
Changed
@@ -53,13 +53,6 @@ u32 codec_id; } GF_OBUMxCtx; -#ifdef GPAC_ENABLE_COVERAGE -static Bool obumx_test_filter_prop(void *cbk, u32 prop_4cc, const char *prop_name, const GF_PropertyValue *src_prop) -{ - return GF_TRUE; -} -#endif - GF_Err obumx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove) { u32 crc; @@ -85,14 +78,8 @@ ctx->opid = gf_filter_pid_new(filter); } //copy properties at init or reconfig -#ifdef GPAC_ENABLE_COVERAGE - if (gf_sys_is_cov_mode()) { - gf_filter_pid_merge_properties(ctx->opid, pid, obumx_test_filter_prop, NULL); - } else -#endif - { - gf_filter_pid_copy_properties(ctx->opid, pid); - } + gf_filter_pid_copy_properties(ctx->opid, pid); + gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) ); ctx->ipid = pid;
View file
gpac-1.0.0.tar.gz/src/filters/vcrop.c -> gpac-1.0.1.tar.gz/src/filters/vcrop.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2018 + * Copyright (c) Telecom ParisTech 2018-2020 * All rights reserved * * This file is part of GPAC / video cropping filter @@ -589,7 +589,7 @@ { { OFFS(wnd), "size of output to crop, indicated as TxLxWxH. If % is indicated after a number, the value is in percent of the source width (for L and W) or height (for T and H). An absolute offset (+x, -x) can be added after percent", GF_PROP_STRING, NULL, NULL, 0}, { OFFS(copy), "copy the source pixels. By default the filter will try to forward crop frames by adjusting offsets and strides of the source if possible (window contained in frame)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, - { OFFS(round), "adjust dimension to be a multiple of 2.\n" + { OFFS(round), "adjust dimension to be a multiple of 2\n" "- up: up rounding\n" "- down: down rounding\n" "- allup: up rounding on formats that do not require it (RGB, YUV444)\n"
View file
gpac-1.0.0.tar.gz/src/filters/write_generic.c -> gpac-1.0.1.tar.gz/src/filters/write_generic.c
Changed
@@ -998,7 +998,7 @@ "- first: inserted on first packet\n" "- sap: inserted at each SAP\n" "- auto: selects between no and first based on media type", GF_PROP_UINT, "auto", "no|first|sap|auto", GF_FS_ARG_HINT_ADVANCED}, - { OFFS(split), "force one file per decoded frame.", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, + { OFFS(split), "force one file per decoded frame", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED}, { OFFS(frame), "force single frame dump with no rewrite. In this mode, all codecids are supported", GF_PROP_BOOL, "false", NULL, 0}, { OFFS(sstart), "start number of frame to forward. If 0, all samples are forwarded", GF_PROP_UINT, "0", NULL, 0}, { OFFS(send), "end number of frame to forward. If less than start frame, all samples after start are forwarded", GF_PROP_UINT, "0", NULL, 0},
View file
gpac-1.0.0.tar.gz/src/filters/write_nhml.c -> gpac-1.0.1.tar.gz/src/filters/write_nhml.c
Changed
@@ -398,7 +398,8 @@ sprintf(nhml, "sampleRate=\"%d\" numChannels=\"%d\" ", ctx->sr, ctx->chan); gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml)); p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_AUDIO_FORMAT); - sprintf(nhml, "bitsPerSample=\"%d\" ", gf_audio_fmt_bit_depth(p->value.uint)); + if (p) + sprintf(nhml, "bitsPerSample=\"%d\" ", gf_audio_fmt_bit_depth(p->value.uint)); gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml)); } @@ -665,9 +666,9 @@ } else if (ctx->pckp) { sprintf(nhml, "isRAP=\"no\" "); gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml)); - if (sap==GF_FILTER_SAP_4) { + if ((sap==GF_FILTER_SAP_4) || (sap==GF_FILTER_SAP_4_PROL)) { s32 roll = gf_filter_pck_get_roll_info(pck); - sprintf(nhml, "SAPType=\"4\" roll=\"%d\" ", roll); + sprintf(nhml, "SAPType=\"4\" %s=\"%d\" ", (sap==GF_FILTER_SAP_4_PROL) ? "prol" : "roll", roll); gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml)); } }
View file
gpac-1.0.0.tar.gz/src/ietf/rtp_pck_3gpp.c -> gpac-1.0.1.tar.gz/src/ietf/rtp_pck_3gpp.c
Changed
@@ -249,7 +249,7 @@ builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*RRLLLNNN (all 0, no interleaving)*/ gf_bs_write_u8(builder->pck_hdr, 0); - /*MMM + count-1 : overriden when flushing*/ + /*MMM + count-1 : overridden when flushing*/ gf_bs_write_u8(builder->pck_hdr, 0); builder->bytesInPacket = 2; }
View file
gpac-1.0.0.tar.gz/src/isomedia/avc_ext.c -> gpac-1.0.1.tar.gz/src/isomedia/avc_ext.c
Changed
@@ -721,7 +721,10 @@ } if (is_hevc) { +#ifndef GPAC_DISABLE_HEVC GF_BitStream *write_to_bs = mdia->nalu_out_bs; +#endif + if (!ps_transfered) { gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE); ps_transfered = GF_TRUE; @@ -1263,6 +1266,70 @@ } #endif + +static GF_Err gf_isom_check_mvc(GF_ISOFile *the_file, GF_TrackBox *trak, GF_MPEGVisualSampleEntryBox *entry) +{ + u32 i; + GF_Box *mvci; + GF_MultiviewGroupBox *mvcg; + GF_ViewIdentifierBox *vwid; + + if (entry->mvc_config) {} + else if (entry->avc_config && entry->avc_config->config && entry->avc_config->config->sequenceParameterSetExtensions) {} + else + return GF_OK; + + mvci = gf_isom_box_find_child(trak->Media->information->child_boxes, GF_ISOM_BOX_TYPE_MVCI); + if (!mvci) { + mvci = gf_isom_box_new_parent(&trak->Media->information->child_boxes, GF_ISOM_BOX_TYPE_MVCI); + if (!mvci) return GF_OUT_OF_MEM; + } + mvcg = (GF_MultiviewGroupBox *) gf_isom_box_find_child(mvci->child_boxes, GF_ISOM_BOX_TYPE_MVCG); + if (!mvcg) { + mvcg = (GF_MultiviewGroupBox *)gf_isom_box_new_parent(&mvci->child_boxes, GF_ISOM_BOX_TYPE_MVCG); + if (!mvcg) return GF_OUT_OF_MEM; + } + //this is very crude, we should try to parse the bitstream to fill these + mvcg->num_entries = 0; + if (mvcg->entries) { + gf_free(mvcg->entries); + mvcg->entries = NULL; + } + if (entry->avc_config) { + if (gf_list_count(entry->avc_config->config->sequenceParameterSets)) + mvcg->num_entries += 1; + mvcg->num_entries += gf_list_count(entry->avc_config->config->sequenceParameterSetExtensions); + } + if (entry->mvc_config) { + mvcg->num_entries += gf_list_count(entry->mvc_config->config->sequenceParameterSets); + } + mvcg->entries = gf_malloc(sizeof(MVCIEntry)*mvcg->num_entries); + if (!mvcg->entries) return GF_OUT_OF_MEM; + memset(mvcg->entries, 0, sizeof(MVCIEntry)*mvcg->num_entries); + for (i=0; i<mvcg->num_entries; i++) { + mvcg->entries[i].entry_type = 2; + mvcg->entries[i].output_view_id = i; + } + vwid = (GF_ViewIdentifierBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_VWID); + if (!vwid) { + vwid = (GF_ViewIdentifierBox *)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VWID); + if (!mvcg) return GF_OUT_OF_MEM; + } + if (vwid->views) gf_free(vwid->views); + vwid->num_views = mvcg->num_entries; + vwid->views = gf_malloc(sizeof(ViewIDEntry)*vwid->num_views); + if (!vwid->views) return GF_OUT_OF_MEM; + memset(vwid->views, 0, sizeof(ViewIDEntry)*vwid->num_views); + + for (i=0; i<vwid->num_views; i++) { + vwid->views[i].base_view_type = i ? 0 : 1; + vwid->views[i].view_id = i; + vwid->views[i].view_order_index = i; + } + + return GF_OK; +} + static GF_AV1Config* AV1_DuplicateConfig(GF_AV1Config const * const cfg) { u32 i = 0; GF_AV1Config *out = gf_malloc(sizeof(GF_AV1Config)); @@ -1552,6 +1619,8 @@ entry->mvc_config->config = AVC_DuplicateConfig(cfg); if (!entry->mvc_config->config) return GF_OUT_OF_MEM; entry->type = GF_ISOM_BOX_TYPE_AVC1; + e = gf_isom_check_mvc(the_file, trak, entry); + if (e) return e; break; /*MVCC replacement and AVC removal*/ case 5: @@ -1568,6 +1637,8 @@ entry->mvc_config->config = AVC_DuplicateConfig(cfg); if (!entry->mvc_config->config) return GF_OUT_OF_MEM; entry->type = GF_ISOM_BOX_TYPE_MVC1; + e = gf_isom_check_mvc(the_file, trak, entry); + if (e) return e; break; } AVC_RewriteESDescriptor(entry); @@ -2297,6 +2368,10 @@ if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format; } + if (type == GF_ISOM_BOX_TYPE_DVHE) { + type = GF_ISOM_BOX_TYPE_HEV1; + } + switch (type) { case GF_ISOM_BOX_TYPE_HVC1: case GF_ISOM_BOX_TYPE_HEV1:
View file
gpac-1.0.0.tar.gz/src/isomedia/box_code_adobe.c -> gpac-1.0.1.tar.gz/src/isomedia/box_code_adobe.c
Changed
@@ -93,12 +93,13 @@ i=0; if (ptr->size<8) return GF_ISOM_INVALID_FILE; - tmp_strsize =(u32)ptr->size-8; + tmp_strsize =(u32)ptr->size; tmp_str = gf_malloc(sizeof(char)*tmp_strsize); if (!tmp_str) return GF_OUT_OF_MEM; memset(tmp_str, 0, sizeof(char)*tmp_strsize); while (tmp_strsize) { + ISOM_DECREASE_SIZE(ptr, 1) tmp_str[i] = gf_bs_read_u8(bs); tmp_strsize--; if (!tmp_str[i]) @@ -109,11 +110,13 @@ ptr->movie_identifier = gf_strdup(tmp_str); } + ISOM_DECREASE_SIZE(ptr, 1) ptr->server_entry_count = gf_bs_read_u8(bs); for (i=0; i<ptr->server_entry_count; i++) { int j=0; - tmp_strsize=(u32)ptr->size-8; + tmp_strsize=(u32)ptr->size; while (tmp_strsize) { + ISOM_DECREASE_SIZE(ptr, 1) tmp_str[j] = gf_bs_read_u8(bs); tmp_strsize--; if (!tmp_str[j]) @@ -125,11 +128,13 @@ } } + ISOM_DECREASE_SIZE(ptr, 1) ptr->quality_entry_count = gf_bs_read_u8(bs); for (i=0; i<ptr->quality_entry_count; i++) { int j=0; - tmp_strsize=(u32)ptr->size-8; + tmp_strsize=(u32)ptr->size; while (tmp_strsize) { + ISOM_DECREASE_SIZE(ptr, 1) tmp_str[j] = gf_bs_read_u8(bs); tmp_strsize--; if (!tmp_str[j]) @@ -143,8 +148,9 @@ } i=0; - tmp_strsize=(u32)ptr->size-8; + tmp_strsize=(u32)ptr->size; while (tmp_strsize) { + ISOM_DECREASE_SIZE(ptr, 1) tmp_str[i] = gf_bs_read_u8(bs); tmp_strsize--; if (!tmp_str[i]) @@ -156,8 +162,9 @@ } i=0; - tmp_strsize=(u32)ptr->size-8; + tmp_strsize=(u32)ptr->size; while (tmp_strsize) { + ISOM_DECREASE_SIZE(ptr, 1) tmp_str[i] = gf_bs_read_u8(bs); tmp_strsize--; if (!tmp_str[i]) @@ -168,6 +175,7 @@ ptr->meta_data = gf_strdup(tmp_str); } + ISOM_DECREASE_SIZE(ptr, 1) ptr->segment_run_table_count = gf_bs_read_u8(bs); for (i=0; i<ptr->segment_run_table_count; i++) { GF_AdobeSegmentRunTableBox *asrt = NULL; @@ -180,6 +188,7 @@ gf_list_add(ptr->segment_run_table_entries, asrt); } + ISOM_DECREASE_SIZE(ptr, 1) ptr->fragment_run_table_count = gf_bs_read_u8(bs); for (i=0; i<ptr->fragment_run_table_count; i++) { GF_AdobeFragmentRunTableBox *afrt = NULL;
View file
gpac-1.0.0.tar.gz/src/isomedia/box_code_apple.c -> gpac-1.0.1.tar.gz/src/isomedia/box_code_apple.c
Changed
@@ -612,7 +612,8 @@ u32 len; GF_TimeCodeMediaInformationBox *ptr = (GF_TimeCodeMediaInformationBox *)s; - ISOM_DECREASE_SIZE(s, 21); + //don't remove font name len field, some writers just skip it if no font ... + ISOM_DECREASE_SIZE(s, 20); ptr->text_font = gf_bs_read_u16(bs); ptr->text_face = gf_bs_read_u16(bs); @@ -624,6 +625,12 @@ ptr->back_color_red = gf_bs_read_u16(bs); ptr->back_color_green = gf_bs_read_u16(bs); ptr->back_color_blue = gf_bs_read_u16(bs); + if (!ptr->size) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] broken tmci box, missing font name length field\n" )); + return GF_OK; + } + ISOM_DECREASE_SIZE(s, 1); + len = gf_bs_read_u8(bs); if (len > ptr->size) len = (u32) ptr->size;
View file
gpac-1.0.0.tar.gz/src/isomedia/box_code_base.c -> gpac-1.0.1.tar.gz/src/isomedia/box_code_base.c
Changed
@@ -580,6 +580,10 @@ ptr->location = (char*)gf_malloc((u32) ptr->size); if (! ptr->location) return GF_OUT_OF_MEM; gf_bs_read_data(bs, ptr->location, (u32)ptr->size); + if (ptr->location[ptr->size-1]) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] url box location is not 0-terminated\n" )); + return GF_ISOM_INVALID_FILE; + } } return GF_OK; } @@ -773,6 +777,7 @@ if (e == GF_OK) { gf_bs_seek(sub_bs, 0); + gf_bs_set_cookie(sub_bs, GF_ISOM_BS_COOKIE_NO_LOGS); e = gf_isom_box_array_read(s, sub_bs, NULL); } gf_bs_del(sub_bs); @@ -3221,7 +3226,7 @@ GF_Err tfra_box_write(GF_Box *s, GF_BitStream *bs) { GF_Err e; - u32 i; + u32 i, sap_nb_entries; GF_TrackFragmentRandomAccessBox *ptr = (GF_TrackFragmentRandomAccessBox *)s; e = gf_isom_full_box_write(s, bs); @@ -3234,10 +3239,19 @@ gf_bs_write_int(bs, ptr->trun_bits/8 - 1, 2); gf_bs_write_int(bs, ptr->sample_bits/8 - 1, 2); - gf_bs_write_u32(bs, ptr->nb_entries); + sap_nb_entries = 0; + for (i=0; i<ptr->nb_entries; i++) { + GF_RandomAccessEntry *p = &ptr->entries[i]; + //no sap found, do not store + if (p->trun_number) sap_nb_entries++; + } + + gf_bs_write_u32(bs, sap_nb_entries); for (i=0; i<ptr->nb_entries; i++) { GF_RandomAccessEntry *p = &ptr->entries[i]; + //no sap found, do not store + if (!p->trun_number) continue; if (ptr->version==1) { gf_bs_write_u64(bs, p->time); gf_bs_write_u64(bs, p->moof_offset); @@ -3254,11 +3268,16 @@ GF_Err tfra_box_size(GF_Box *s) { + u32 i; GF_TrackFragmentRandomAccessBox *ptr = (GF_TrackFragmentRandomAccessBox *)s; - ptr->size += 12; - ptr->size += ptr->nb_entries * ( ((ptr->version==1) ? 16 : 8 ) + ptr->traf_bits/8 + ptr->trun_bits/8 + ptr->sample_bits/8); + for (i=0; i<ptr->nb_entries; i++) { + GF_RandomAccessEntry *p = &ptr->entries[i]; + //no sap found, do not store + if (!p->trun_number) continue; + ptr->size += ((ptr->version==1) ? 16 : 8 ) + ptr->traf_bits/8 + ptr->trun_bits/8 + ptr->sample_bits/8; + } return GF_OK; } @@ -3514,6 +3533,7 @@ gf_isom_check_position(s, (GF_Box *)ptr->InfoHeader, &pos); //then dataInfo gf_isom_check_position(s, (GF_Box *)ptr->dataInformation, &pos); + gf_isom_check_position(s, gf_isom_box_find_child(s->child_boxes, GF_ISOM_BOX_TYPE_MVCI), &pos); //then sampleTable gf_isom_check_position(s, (GF_Box *)ptr->sampleTable, &pos); return GF_OK; @@ -3742,10 +3762,7 @@ if (ptr->cfg_ac3) ERROR_ON_DUPLICATED_BOX(a, ptr) ptr->cfg_ac3 = (GF_AC3ConfigBox *) a; break; - case GF_ISOM_BOX_TYPE_MHA1: - case GF_ISOM_BOX_TYPE_MHA2: - case GF_ISOM_BOX_TYPE_MHM1: - case GF_ISOM_BOX_TYPE_MHM2: + case GF_ISOM_BOX_TYPE_MHAC: if (ptr->cfg_mha) ERROR_ON_DUPLICATED_BOX(a, ptr) ptr->cfg_mha = (GF_MHAConfigBox *) a; ptr->qtff_mode = GF_ISOM_AUDIO_QTFF_NONE; @@ -3816,7 +3833,11 @@ cfg_ptr = (GF_Box **) &ptr->cfg_opus; subtype = GF_ISOM_BOX_TYPE_DOPS; } - else if ((s->type == GF_ISOM_BOX_TYPE_MHA1) || (s->type == GF_ISOM_BOX_TYPE_MHA2)) { + else if ((s->type == GF_ISOM_BOX_TYPE_MHA1) + || (s->type == GF_ISOM_BOX_TYPE_MHA2) + || (s->type == GF_ISOM_BOX_TYPE_MHM1) + || (s->type == GF_ISOM_BOX_TYPE_MHM2) + ) { cfg_ptr = (GF_Box **) &ptr->cfg_mha; subtype = GF_ISOM_BOX_TYPE_MHAC; } @@ -4284,7 +4305,10 @@ /*avc / SVC + MVC*/ gf_isom_check_position(s, (GF_Box *)ptr->avc_config, &pos); gf_isom_check_position(s, (GF_Box *)ptr->svc_config, &pos); - gf_isom_check_position(s, (GF_Box *)ptr->mvc_config, &pos); + if (ptr->mvc_config) { + gf_isom_check_position(s, gf_isom_box_find_child(s->child_boxes, GF_ISOM_BOX_TYPE_VWID), &pos); + gf_isom_check_position(s, (GF_Box *)ptr->mvc_config, &pos); + } /*HEVC*/ gf_isom_check_position(s, (GF_Box *)ptr->hevc_config, &pos); @@ -5046,7 +5070,7 @@ if (ptr->sub_samples) { gf_isom_check_position_list(s, ptr->sub_samples, &pos); } - if (ptr->sampleGroupsDescription && !ptr->skip_sample_groups) { + if (ptr->sampleGroupsDescription) { gf_isom_check_position_list(s, ptr->sampleGroupsDescription, &pos); } if (ptr->sampleGroups) { @@ -7068,12 +7092,7 @@ GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s; if (ptr == NULL) return; - while (gf_list_count(ptr->entries)) { - GF_TrunEntry *p = (GF_TrunEntry*)gf_list_get(ptr->entries, 0); - gf_list_rem(ptr->entries, 0); - gf_free(p); - } - gf_list_del(ptr->entries); + if (ptr->samples) gf_free(ptr->samples); if (ptr->cache) gf_bs_del(ptr->cache); if (ptr->sample_order) gf_free(ptr->sample_order); gf_free(ptr); @@ -7221,7 +7240,6 @@ GF_Err trun_box_read(GF_Box *s, GF_BitStream *bs) { u32 i; - GF_TrunEntry *p; GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s; #ifdef GF_ENABLE_CTRN @@ -7249,17 +7267,23 @@ ptr->first_sample_flags = gf_bs_read_u32(bs); } if (! (ptr->flags & (GF_ISOM_TRUN_DURATION | GF_ISOM_TRUN_SIZE | GF_ISOM_TRUN_FLAGS | GF_ISOM_TRUN_CTS_OFFSET) ) ) { - GF_SAFEALLOC(p, GF_TrunEntry); - if (!p) return GF_OUT_OF_MEM; - p->nb_pack = ptr->sample_count; - gf_list_add(ptr->entries, p); + ptr->samples = gf_malloc(sizeof(GF_TrunEntry)); + if (!ptr->samples) return GF_OUT_OF_MEM; + ptr->sample_alloc = ptr->nb_samples = 1; + ptr->samples[0].nb_pack = ptr->sample_count; } else { + //if we get here, at least one flag (so at least 4 bytes) is set, check size + if (ptr->sample_count * 4 > ptr->size) { + ISOM_DECREASE_SIZE(ptr, ptr->sample_count*4); + } + ptr->samples = gf_malloc(sizeof(GF_TrunEntry) * ptr->sample_count); + if (!ptr->samples) return GF_OUT_OF_MEM; + ptr->sample_alloc = ptr->nb_samples = ptr->sample_count; //read each entry (even though nothing may be written) for (i=0; i<ptr->sample_count; i++) { u32 trun_size = 0; - p = (GF_TrunEntry *) gf_malloc(sizeof(GF_TrunEntry)); - if (!p) return GF_OUT_OF_MEM; + GF_TrunEntry *p = &ptr->samples[i]; memset(p, 0, sizeof(GF_TrunEntry)); if (ptr->flags & GF_ISOM_TRUN_DURATION) { @@ -7283,7 +7307,6 @@ } trun_size += 4; } - gf_list_add(ptr->entries, p); ISOM_DECREASE_SIZE(ptr, trun_size); } } @@ -7298,7 +7321,6 @@ GF_Box *trun_box_new() { ISOM_DECL_BOX_ALLOC(GF_TrackFragmentRunBox, GF_ISOM_BOX_TYPE_TRUN); - tmp->entries = gf_list_new(); //NO FLAGS SET BY DEFAULT return (GF_Box *)tmp; } @@ -7398,7 +7420,7 @@ GF_Err trun_box_write(GF_Box *s, GF_BitStream *bs) { GF_Err e; - u32 i, count; + u32 i; GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *) s; if (!s) return GF_BAD_PARAM; @@ -7421,10 +7443,8 @@ } if (ptr->flags & (GF_ISOM_TRUN_DURATION | GF_ISOM_TRUN_SIZE | GF_ISOM_TRUN_FLAGS | GF_ISOM_TRUN_CTS_OFFSET) ) { - - count = gf_list_count(ptr->entries); - for (i=0; i<count; i++) { - GF_TrunEntry *p = (GF_TrunEntry*)gf_list_get(ptr->entries, i); + for (i=0; i<ptr->nb_samples; i++) { + GF_TrunEntry *p = &ptr->samples[i]; if (ptr->flags & GF_ISOM_TRUN_DURATION) { gf_bs_write_u32(bs, p->Duration); @@ -7626,7 +7646,6 @@ GF_Err trun_box_size(GF_Box *s) { - u32 i, count; GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s; #ifdef GF_ENABLE_CTRN @@ -7652,14 +7671,12 @@ } //if nothing to do, this will be skipped automatically - count = gf_list_count(ptr->entries); - for (i=0; i<count; 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 - if (ptr->flags & GF_ISOM_TRUN_FLAGS) ptr->size += 4; - if (ptr->flags & GF_ISOM_TRUN_CTS_OFFSET) ptr->size += 4; - } + if (ptr->flags & GF_ISOM_TRUN_DURATION) ptr->size += 4*ptr->nb_samples; + if (ptr->flags & GF_ISOM_TRUN_SIZE) ptr->size += 4*ptr->nb_samples; + //SHOULDN'T BE USED IF GF_ISOM_TRUN_FIRST_FLAG IS DEFINED + if (ptr->flags & GF_ISOM_TRUN_FLAGS) ptr->size += 4*ptr->nb_samples; + if (ptr->flags & GF_ISOM_TRUN_CTS_OFFSET) ptr->size += 4*ptr->nb_samples; + return GF_OK; } @@ -8023,6 +8040,7 @@ ptr->sample_info = (u8 *) gf_malloc(sizeof(u8)*ptr->sampleCount); if (!ptr->sample_info) return GF_OUT_OF_MEM; + ptr->sample_alloc = ptr->sampleCount; gf_bs_read_data(bs, (char*)ptr->sample_info, ptr->sampleCount); ISOM_DECREASE_SIZE(ptr, ptr->sampleCount); return GF_OK; @@ -11559,7 +11577,7 @@ { u32 i; GF_ViewIdentifierBox *ptr = (GF_ViewIdentifierBox *) s; - if (ptr->num_views) { + if (ptr->views) { for (i=0; i<ptr->num_views; i++) { if (ptr->views[i].view_refs) gf_free(ptr->views[i].view_refs);
View file
gpac-1.0.0.tar.gz/src/isomedia/box_dump.c -> gpac-1.0.1.tar.gz/src/isomedia/box_dump.c
Changed
@@ -421,7 +421,24 @@ s = (u32) (dur/1000); dur -= s*1000; ms = (u32) (dur); - sprintf(szDur, "%02d:%02d:%02d.%03d", h, m, s, ms); + + if (h<=24) { + sprintf(szDur, "%02d:%02d:%02d.%03d", h, m, s, ms); + } else { + u32 d = (u32) (dur / 3600000 / 24); + h = (u32) (dur/3600000)-24*d; + if (d<=365) { + sprintf(szDur, "%d Days, %02d:%02d:%02d.%03d", d, h, m, s, ms); + } else { + u32 y=0; + while (d>365) { + y++; + d-=365; + if (y%4) d--; + } + sprintf(szDur, "%d Years %d Days, %02d:%02d:%02d.%03d", y, d, h, m, s, ms); + } + } return szDur; } @@ -542,7 +559,7 @@ gf_isom_box_dump_start(a, "MPEGSystemsSampleDescriptionBox", trace); gf_fprintf(trace, "DataReferenceIndex=\"%d\">\n", p->dataReferenceIndex); if (!p->esd && p->size) { - gf_fprintf(trace, "<!--INVALID MP4 FILE: ESDBox not present in MPEG Sample Description or corrupted-->\n"); + gf_fprintf(trace, "<!--INVALID MP4 FILE: ESDBox not present in MPEG Sample Description -->\n"); } gf_isom_box_dump_done("MPEGSystemsSampleDescriptionBox", a, trace); return GF_OK; @@ -715,22 +732,22 @@ case GF_ISOM_BOX_TYPE_MP4A: szName = "MPEGAudioSampleDescriptionBox"; if (!p->esd) - error = "<!--INVALID MP4 Entry: ESDBox not present in Audio Sample Description or corrupted-->"; + error = "<!--INVALID MP4 Entry: ESDBox not present in Audio Sample Description -->"; break; case GF_ISOM_BOX_TYPE_AC3: szName = "AC3SampleEntryBox"; if (!p->cfg_ac3) - error = "<!--INVALID AC3 Entry: AC3Config not present in Audio Sample Description or corrupted-->"; + error = "<!--INVALID AC3 Entry: AC3Config not present in Audio Sample Description -->"; break; case GF_ISOM_BOX_TYPE_EC3: szName = "EC3SampleEntryBox"; if (!p->cfg_ac3) - error = "<!--INVALID AC3 Entry: AC3Config not present in Audio Sample Description or corrupted-->"; + error = "<!--INVALID EC3 Entry: AC3Config not present in Audio Sample Description -->"; break; case GF_ISOM_BOX_TYPE_MHA1: case GF_ISOM_BOX_TYPE_MHA2: if (!p->cfg_mha) - error = "<!--INVALID MPEG-H 3D Audio Entry: MHA config not present in Audio Sample Description or corrupted-->"; + error = "<!--INVALID MPEG-H 3D Audio Entry: MHA config not present in Audio Sample Description -->"; case GF_ISOM_BOX_TYPE_MHM1: case GF_ISOM_BOX_TYPE_MHM2: szName = "MHASampleEntry"; @@ -1125,6 +1142,9 @@ GF_SampleDependencyTypeBox *p; u32 i; + if (dump_skip_samples) + return GF_OK; + p = (GF_SampleDependencyTypeBox*)a; gf_isom_box_dump_start(a, "SampleDependencyTypeBox", trace); gf_fprintf(trace, "SampleCount=\"%d\">\n", p->sampleCount); @@ -2234,7 +2254,7 @@ { gf_isom_box_dump_start(a, "HintTrackInfoBox", trace); gf_fprintf(trace, ">\n"); - gf_isom_box_dump_done("HintTrackInfoBox", NULL, trace); + gf_isom_box_dump_done("HintTrackInfoBox", a, trace); return GF_OK; } @@ -2478,10 +2498,9 @@ } if (full_dump) { - GF_TrunEntry *ent; - i=0; - while ((ent = (GF_TrunEntry *)gf_list_enum(p->entries, &i))) { - + for (i=0; i<p->nb_samples; i++) { + GF_TrunEntry *ent = &p->samples[i]; + gf_fprintf(trace, "<TrackRunEntry"); #ifdef GF_ENABLE_CTRN @@ -2764,7 +2783,7 @@ return szDur; } -static GF_Err gf_isom_dump_ttxt_track(GF_ISOFile *the_file, u32 track, FILE *dump, Bool box_dump) +static GF_Err gf_isom_dump_ttxt_track(GF_ISOFile *the_file, u32 track, FILE *dump, GF_TextDumpType dump_type) { u32 i, j, count, di, nb_descs, shift_offset[20], so_count; u64 last_DTS; @@ -2773,6 +2792,8 @@ Bool has_scroll; char szDur[100]; GF_Tx3gSampleEntryBox *txt_e; + Bool box_dump = (dump_type==GF_TEXTDUMPTYPE_TTXT_BOXES) ? GF_TRUE : GF_FALSE; + Bool skip_empty = (dump_type==GF_TEXTDUMPTYPE_TTXT_CHAP) ? GF_TRUE : GF_FALSE; GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, track); if (!trak) return GF_BAD_PARAM; @@ -2938,11 +2959,19 @@ GF_ISOSample *s = gf_isom_get_sample(the_file, track, i+1, &di); if (!s) continue; - gf_fprintf(dump, "<TextSample sampleTime=\"%s\" sampleDescriptionIndex=\"%d\"", tx3g_format_time(s->DTS, trak->Media->mediaHeader->timeScale, szDur, GF_FALSE), di); bs = gf_bs_new(s->data, s->dataLength, GF_BITSTREAM_READ); s_txt = gf_isom_parse_text_sample(bs); gf_bs_del(bs); + if (skip_empty && (s_txt->len<1)) { + gf_isom_sample_del(&s); + gf_isom_delete_text_sample(s_txt); + gf_set_progress("TTXT Extract", i, count); + continue; + } + + gf_fprintf(dump, "<TextSample sampleTime=\"%s\" sampleDescriptionIndex=\"%d\"", tx3g_format_time(s->DTS, trak->Media->mediaHeader->timeScale, szDur, GF_FALSE), di); + if (!box_dump) { if (s_txt->highlight_color) { gf_fprintf(dump, " "); @@ -3088,7 +3117,7 @@ gf_isom_delete_text_sample(s_txt); gf_set_progress("TTXT Extract", i, count); } - if (last_DTS < trak->Media->mediaHeader->duration) { + if (!skip_empty && (last_DTS < trak->Media->mediaHeader->duration)) { gf_fprintf(dump, "<TextSample sampleTime=\"%s\" text=\"\" />\n", tx3g_format_time(trak->Media->mediaHeader->duration, trak->Media->mediaHeader->timeScale, szDur, GF_FALSE)); } @@ -3395,6 +3424,63 @@ return GF_OK; } +static GF_Err gf_isom_dump_ogg_chap(GF_ISOFile *the_file, u32 track, FILE *dump, GF_TextDumpType dump_type) +{ + u32 i, count, di, ts, cur_frame; + u64 start; + GF_BitStream *bs; + + GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, track); + if (!trak) return GF_BAD_PARAM; + switch (trak->Media->handler->handlerType) { + case GF_ISOM_MEDIA_TEXT: + case GF_ISOM_MEDIA_SUBT: + break; + default: + return GF_BAD_PARAM; + } + + ts = trak->Media->mediaHeader->timeScale; + cur_frame = 0; + + count = gf_isom_get_sample_count(the_file, track); + for (i=0; i<count; i++) { + GF_TextSample *txt; + GF_ISOSample *s = gf_isom_get_sample(the_file, track, i+1, &di); + if (!s) continue; + + start = s->DTS; + if (s->dataLength==2) { + gf_isom_sample_del(&s); + continue; + } + if (i+1<count) { + GF_ISOSample *next = gf_isom_get_sample_info(the_file, track, i+2, NULL, NULL); + if (next) { + gf_isom_sample_del(&next); + } + } + + cur_frame++; + bs = gf_bs_new(s->data, s->dataLength, GF_BITSTREAM_READ); + txt = gf_isom_parse_text_sample(bs); + gf_bs_del(bs); + + if (!txt->len) continue; + + if (dump_type==GF_TEXTDUMPTYPE_OGG_CHAP) { + char szDur[20]; + fprintf(dump, "CHAPTER%02d=%s\n", i+1, format_duration(start, ts, szDur)); + fprintf(dump, "CHAPTER%02dNAME=%s\n", i+1, txt->text); + } else { + fprintf(dump, "AddChapterBySecond("LLD",%s)\n", start / ts, txt->text); + } + + gf_isom_sample_del(&s); + gf_isom_delete_text_sample(txt); + } + return GF_OK; +} GF_EXPORT GF_Err gf_isom_text_dump(GF_ISOFile *the_file, u32 track, FILE *dump, GF_TextDumpType dump_type) { @@ -3405,7 +3491,11 @@ return gf_isom_dump_srt_track(the_file, track, dump); case GF_TEXTDUMPTYPE_TTXT: case GF_TEXTDUMPTYPE_TTXT_BOXES: - return gf_isom_dump_ttxt_track(the_file, track, dump, (dump_type==GF_TEXTDUMPTYPE_TTXT_BOXES) ? GF_TRUE : GF_FALSE); + case GF_TEXTDUMPTYPE_TTXT_CHAP: + return gf_isom_dump_ttxt_track(the_file, track, dump, dump_type); + case GF_TEXTDUMPTYPE_OGG_CHAP: + case GF_TEXTDUMPTYPE_ZOOM_CHAP: + return gf_isom_dump_ogg_chap(the_file, track, dump, dump_type); default: return GF_BAD_PARAM; } @@ -3631,7 +3721,7 @@ } gf_isom_box_dump_start(a, name, trace); - if (!no_dump) { + if (!no_dump && itune->data) { GF_BitStream *bs; switch (itune->type) { case GF_ISOM_BOX_TYPE_DISK:
View file
gpac-1.0.0.tar.gz/src/isomedia/box_funcs.c -> gpac-1.0.1.tar.gz/src/isomedia/box_funcs.c
Changed
@@ -191,7 +191,8 @@ size = gf_bs_read_u64(bs); hdr_size += 8; } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Read Box type %s size "LLD" start "LLD"\n", gf_4cc_to_str(type), size, start)); + if (!skip_logs) + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Read Box type %s size "LLD" start "LLD"\n", gf_4cc_to_str(type), size, start)); if ( size < hdr_size ) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Box size "LLD" less than box header size %d\n", size, hdr_size)); @@ -1461,23 +1462,42 @@ } } -static u32 get_box_reg_idx(u32 boxCode, u32 parent_type) +static u32 get_box_reg_idx(u32 boxCode, u32 parent_type, u32 start_from) { u32 i=0, count = gf_isom_get_num_supported_boxes(); const char *parent_name = parent_type ? gf_4cc_to_str(parent_type) : NULL; - for (i=1; i<count; i++) { - if (box_registry[i].box_4cc==boxCode) { - if (!parent_type) return i; - if (strstr(box_registry[i].parents_4cc, parent_name) != NULL) return i; - - if (strstr(box_registry[i].parents_4cc, "sample_entry") != NULL) { - u32 j = get_box_reg_idx(parent_type, 0); - if (parent_type==GF_QT_SUBTYPE_RAW) - return i; - if (box_registry[j].parents_4cc && (strstr(box_registry[j].parents_4cc, "stsd") != NULL)) - return i; - } + if (!start_from) start_from = 1; + + for (i=start_from; i<count; i++) { + u32 start_par_from; + if (box_registry[i].box_4cc != boxCode) + continue; + + if (!parent_type) + return i; + if (strstr(box_registry[i].parents_4cc, parent_name) != NULL) + return i; + if (strstr(box_registry[i].parents_4cc, "*") != NULL) + return i; + + if (strstr(box_registry[i].parents_4cc, "sample_entry") == NULL) + continue; + + /*parent is a sample entry, check if the parent_type matches a sample entry box (eg its parent must be stsd)*/ + + if (parent_type==GF_QT_SUBTYPE_RAW) + return i; + + start_par_from = 0; + while (parent_type) { + //locate parent registry + u32 j = get_box_reg_idx(parent_type, 0, start_par_from); + if (!j) break; + //if parent registry has "stsd" as parent, this is a sample entry + if (box_registry[j].parents_4cc && (strstr(box_registry[j].parents_4cc, "stsd") != NULL)) + return i; + start_par_from = j+1; } } return 0; @@ -1486,7 +1506,7 @@ GF_Box *gf_isom_box_new_ex(u32 boxType, u32 parentType, Bool skip_logs, Bool is_root_box) { GF_Box *a; - s32 idx = get_box_reg_idx(boxType, parentType); + s32 idx = get_box_reg_idx(boxType, parentType, 0); if (idx==0) { #ifndef GPAC_DISABLE_LOG if (!skip_logs && (boxType != GF_ISOM_BOX_TYPE_UNKNOWN) && (boxType != GF_ISOM_BOX_TYPE_UUID)) { @@ -1496,6 +1516,7 @@ case GF_ISOM_BOX_TYPE_UDTA: case GF_ISOM_BOX_TYPE_UNKNOWN: case GF_ISOM_BOX_TYPE_iTunesSpecificInfo: + case GF_QT_BOX_TYPE_WAVE: break; default: if (is_root_box) { @@ -1644,7 +1665,6 @@ if (!a_box_registry) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Delete invalid box type %s without registry\n", gf_4cc_to_str(a->type) )); } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Delete box type %s\n", gf_4cc_to_str(a->type) )); a_box_registry->del_fn(a); } //delet the other boxes after deleting the box for dumper case where all child boxes are stored in otherbox
View file
gpac-1.0.0.tar.gz/src/isomedia/data_map.c -> gpac-1.0.1.tar.gz/src/isomedia/data_map.c
Changed
@@ -26,6 +26,10 @@ #include <gpac/internal/isomedia_dev.h> #include <gpac/network.h> + +/*File Mapping object, read-only mode on complete files (no download)*/ +//#define GF_ISOM_DATA_FILE_MAPPING 0x02 + #ifndef GPAC_DISABLE_ISOM @@ -42,9 +46,11 @@ case GF_ISOM_DATA_MEM: gf_isom_fdm_del((GF_FileDataMap *)ptr); break; +#if 0 case GF_ISOM_DATA_FILE_MAPPING: gf_isom_fmo_del((GF_FileMappingDataMap *)ptr); break; +#endif default: if (ptr->bs) gf_bs_del(ptr->bs); gf_free(ptr); @@ -161,9 +167,8 @@ if (mode == GF_ISOM_DATA_MAP_READ_ONLY) { mode = GF_ISOM_DATA_MAP_READ; - /*It seems win32 file mapping is reported in prog mem usage -> large increases of occupancy. Should not be a pb - but unless you want mapping, only regular IO will be used...*/ -#if 0 + +#if 0 //file mapping is disabled if (IsLargeFile(sPath)) { *outDataMap = gf_isom_fdm_new(sPath, mode); } else { @@ -272,8 +277,10 @@ case GF_ISOM_DATA_MEM: return gf_isom_fdm_get_data((GF_FileDataMap *)map, buffer, bufferLength, Offset); +#if 0 case GF_ISOM_DATA_FILE_MAPPING: return gf_isom_fmo_get_data((GF_FileMappingDataMap *)map, buffer, bufferLength, Offset); +#endif default: return 0; @@ -555,6 +562,8 @@ #endif /*GPAC_DISABLE_ISOM_WRITE*/ +#if 0 //file mapping disabled + #ifdef WIN32 #include <windows.h> @@ -673,6 +682,7 @@ return gf_isom_fdm_get_data((GF_FileDataMap *)ptr, buffer, bufferLength, fileOffset); } -#endif +#endif //win32 +#endif //file mapping disabled #endif /*GPAC_DISABLE_ISOM*/
View file
gpac-1.0.0.tar.gz/src/isomedia/drm_sample.c -> gpac-1.0.1.tar.gz/src/isomedia/drm_sample.c
Changed
@@ -98,6 +98,12 @@ return NULL; } +#if 0 //unused +/*! rewrites ISMA sample as an ISO sample +\param s the ISMA sample to rewrite +\param dest the destination ISO sample +\return error if any +*/ GF_Err gf_isom_ismacryp_sample_to_sample(const GF_ISMASample *s, GF_ISOSample *dest) { GF_BitStream *bs; @@ -121,6 +127,8 @@ gf_bs_del(bs); return GF_OK; } +#endif + static GF_ProtectionSchemeInfoBox *isom_get_sinf_entry(GF_TrackBox *trak, u32 sampleDescriptionIndex, u32 scheme_type, GF_SampleEntryBox **out_sea) { @@ -328,7 +336,13 @@ #ifndef GPAC_DISABLE_ISOM_WRITE -GF_EXPORT +#if 0 //unused +/*! removes protection info (does not perform decryption), for ISMA, OMA and CENC of a sample description +\param isom_file the target ISO file +\param trackNumber the target track +\param sampleDescriptionIndex the sample description index +\return error if any +*/ GF_Err gf_isom_remove_track_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) { GF_TrackBox *trak; @@ -363,6 +377,7 @@ if (sea->type == GF_ISOM_BOX_TYPE_265B) sea->type = GF_ISOM_BOX_TYPE_HVC1; return GF_OK; } +#endif GF_EXPORT GF_Err gf_isom_change_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, char *scheme_uri, char *kms_uri) @@ -743,6 +758,12 @@ } +#if 0 +/*! removes CENC SAI size info +\param isom_file the target ISO file +\param trackNumber the target track +\return error if any +*/ GF_Err gf_isom_remove_cenc_saiz(GF_ISOFile *the_file, u32 trackNumber) { u32 i; @@ -779,6 +800,11 @@ return GF_OK; } +/*! removes CENC SAI offset info +\param isom_file the target ISO file +\param trackNumber the target track +\return error if any +*/ GF_Err gf_isom_remove_cenc_saio(GF_ISOFile *the_file, u32 trackNumber) { u32 i; @@ -814,6 +840,7 @@ return GF_OK; } +#endif GF_Err gf_cenc_set_pssh(GF_ISOFile *file, bin128 systemID, u32 version, u32 KID_count, bin128 *KIDs, u8 *data, u32 len, Bool use_piff) { @@ -991,6 +1018,11 @@ return GF_OK; } +#if 0 //unused +/*! removes CENC PSSH box +\param isom_file the target ISO file +\return error if any +*/ GF_Err gf_isom_remove_pssh_box(GF_ISOFile *the_file) { u32 i; @@ -1012,6 +1044,8 @@ return GF_OK; } +#endif + #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -1143,7 +1177,7 @@ stbl_on_child_box((GF_Box*)stbl, (GF_Box *)senc->cenc_saio); } - if (!senc->cenc_saiz->sample_count || (senc->cenc_saiz->default_sample_info_size==len)) { + if (!senc->cenc_saiz->sample_count || (!senc->cenc_saiz->sample_alloc && (senc->cenc_saiz->default_sample_info_size==len))) { senc->cenc_saiz->sample_count ++; senc->cenc_saiz->default_sample_info_size = len; } else { @@ -1839,6 +1873,10 @@ } +#if 0 //unused +/*! removes the IPMPX tools from files +\param isom_file the target ISO file +*/ void gf_isom_ipmpx_remove_tool_list(GF_ISOFile *the_file) { /*remove IPMPToolList if any*/ @@ -1848,5 +1886,7 @@ iod->IPMPToolList = NULL; } } +#endif + #endif /*GPAC_DISABLE_ISOM*/
View file
gpac-1.0.0.tar.gz/src/isomedia/hinting.c -> gpac-1.0.1.tar.gz/src/isomedia/hinting.c
Changed
@@ -278,7 +278,7 @@ #endif /*GPAC_DISABLE_ISOM_WRITE*/ - +GF_EXPORT GF_HintPacket *gf_isom_hint_pck_new(u32 HintType) { GF_HintPacket *pck; @@ -298,6 +298,7 @@ } } +GF_EXPORT void gf_isom_hint_pck_del(GF_HintPacket *ptr) { if (!ptr) return; @@ -315,6 +316,7 @@ } } +GF_EXPORT GF_Err gf_isom_hint_pck_read(GF_HintPacket *ptr, GF_BitStream *bs) { if (!ptr) return GF_BAD_PARAM; @@ -332,6 +334,7 @@ #ifndef GPAC_DISABLE_ISOM_WRITE +GF_EXPORT GF_Err gf_isom_hint_pck_write(GF_HintPacket *ptr, GF_BitStream *bs) { if (!ptr) return GF_BAD_PARAM; @@ -347,6 +350,7 @@ } } +GF_EXPORT u32 gf_isom_hint_pck_size(GF_HintPacket *ptr) { if (!ptr) return GF_BAD_PARAM; @@ -396,6 +400,7 @@ } } +GF_EXPORT u32 gf_isom_hint_pck_length(GF_HintPacket *ptr) { if (!ptr) return 0; @@ -420,65 +425,45 @@ Creation of DataTable entries in the RTP sample ********************************************************************/ -GF_GenericDTE *New_EmptyDTE() -{ - GF_EmptyDTE *dte = (GF_EmptyDTE *)gf_malloc(sizeof(GF_EmptyDTE)); - if (dte) dte->source = 0; - return (GF_GenericDTE *)dte; -} - -GF_GenericDTE *New_ImmediateDTE() -{ - GF_ImmediateDTE *dte; - GF_SAFEALLOC(dte, GF_ImmediateDTE); - if (dte) { - dte->source = 1; - dte->dataLength = 0; - } - return (GF_GenericDTE *)dte; -} - -GF_GenericDTE *New_SampleDTE() -{ - GF_SampleDTE *dte = (GF_SampleDTE *)gf_malloc(sizeof(GF_SampleDTE)); - if (!dte) return NULL; - dte->source = 2; - //can be -1 in QT , so init at -2 - dte->trackRefIndex = (s8) -2; - dte->dataLength = 0; - dte->sampleNumber = 0; - dte->samplesPerComp = 1; - dte->byteOffset = 0; - dte->bytesPerComp = 1; - return (GF_GenericDTE *)dte; -} - -GF_GenericDTE *New_StreamDescDTE() -{ - GF_StreamDescDTE *dte = (GF_StreamDescDTE *)gf_malloc(sizeof(GF_StreamDescDTE)); - if (!dte) return NULL; - dte->source = 3; - dte->byteOffset = 0; - dte->dataLength = 0; - dte->reserved = 0; - dte->streamDescIndex = 0; - //can be -1 in QT , so init at -2 - dte->trackRefIndex = (s8) -2; - return (GF_GenericDTE *)dte; -} - //creation of DTEs GF_GenericDTE *NewDTE(u8 type) { switch (type) { case 0: - return New_EmptyDTE(); + { + GF_EmptyDTE *dte; + GF_SAFEALLOC(dte, GF_EmptyDTE); + return (GF_GenericDTE *)dte; + } case 1: - return New_ImmediateDTE(); + { + GF_ImmediateDTE *dte; + GF_SAFEALLOC(dte, GF_ImmediateDTE); + if (dte) dte->source = 1; + return (GF_GenericDTE *)dte; + } case 2: - return New_SampleDTE(); + { + GF_SampleDTE *dte; + GF_SAFEALLOC(dte, GF_SampleDTE); + if (!dte) return NULL; + dte->source = 2; + //can be -1 in QT , so init at -2 + dte->trackRefIndex = (s8) -2; + dte->samplesPerComp = 1; + dte->bytesPerComp = 1; + return (GF_GenericDTE *)dte; + } case 3: - return New_StreamDescDTE(); + { + GF_StreamDescDTE *dte; + GF_SAFEALLOC(dte, GF_StreamDescDTE); + if (!dte) return NULL; + dte->source = 3; + //can be -1 in QT , so init at -2 + dte->trackRefIndex = (s8) -2; + return (GF_GenericDTE *)dte; + } default: return NULL; } @@ -487,41 +472,16 @@ /******************************************************************** Deletion of DataTable entries in the RTP sample ********************************************************************/ -void Del_EmptyDTE(GF_EmptyDTE *dte) -{ - gf_free(dte); -} - -void Del_ImmediateDTE(GF_ImmediateDTE *dte) -{ - gf_free(dte); -} - -void Del_SampleDTE(GF_SampleDTE *dte) -{ - gf_free(dte); -} - -void Del_StreamDescDTE(GF_StreamDescDTE *dte) -{ - gf_free(dte); -} //deletion of DTEs void DelDTE(GF_GenericDTE *dte) { switch (dte->source) { case 0: - Del_EmptyDTE((GF_EmptyDTE *)dte); - break; case 1: - Del_ImmediateDTE((GF_ImmediateDTE *)dte); - break; case 2: - Del_SampleDTE((GF_SampleDTE *)dte); - break; case 3: - Del_StreamDescDTE((GF_StreamDescDTE *)dte); + gf_free(dte); break; default: return; @@ -533,62 +493,50 @@ /******************************************************************** Reading of DataTable entries in the RTP sample ********************************************************************/ -GF_Err Read_EmptyDTE(GF_EmptyDTE *dte, GF_BitStream *bs) -{ - char empty[15]; - //empty but always 15 bytes !!! - gf_bs_read_data(bs, empty, 15); - return GF_OK; -} - -GF_Err Read_ImmediateDTE(GF_ImmediateDTE *dte, GF_BitStream *bs) -{ - dte->dataLength = gf_bs_read_u8(bs); - if (dte->dataLength > 14) return GF_ISOM_INVALID_FILE; - gf_bs_read_data(bs, dte->data, dte->dataLength); - if (dte->dataLength < 14) gf_bs_skip_bytes(bs, 14 - dte->dataLength); - return GF_OK; -} -GF_Err Read_SampleDTE(GF_SampleDTE *dte, GF_BitStream *bs) +GF_Err ReadDTE(GF_GenericDTE *_dte, GF_BitStream *bs) { - dte->trackRefIndex = (s8) gf_bs_read_u8(bs); - dte->dataLength = gf_bs_read_u16(bs); - dte->sampleNumber = gf_bs_read_u32(bs); - dte->byteOffset = gf_bs_read_u32(bs); - dte->bytesPerComp = gf_bs_read_u16(bs); - dte->samplesPerComp = gf_bs_read_u16(bs); - if (dte->bytesPerComp != 1) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with bytesperblock %d, not 1\n", dte->bytesPerComp)); - } - if (dte->samplesPerComp != 1) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with samplesperblock %d, not 1\n", dte->bytesPerComp)); - } - return GF_OK; -} - -GF_Err Read_StreamDescDTE(GF_StreamDescDTE *dte, GF_BitStream *bs) -{ - dte->trackRefIndex = gf_bs_read_u8(bs); - dte->dataLength = gf_bs_read_u16(bs); - dte->streamDescIndex = gf_bs_read_u32(bs); - dte->byteOffset = gf_bs_read_u32(bs); - dte->reserved = gf_bs_read_u32(bs); - return GF_OK; -} - -GF_Err ReadDTE(GF_GenericDTE *dte, GF_BitStream *bs) -{ - switch (dte->source) { + switch (_dte->source) { case 0: - //nothing to o, it is an empty entry - return Read_EmptyDTE((GF_EmptyDTE *)dte, bs); + //empty but always 15 bytes !!! + gf_bs_skip_bytes(bs, 15); + return GF_OK; case 1: - return Read_ImmediateDTE((GF_ImmediateDTE *)dte, bs); + { + GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte; + dte->dataLength = gf_bs_read_u8(bs); + if (dte->dataLength > 14) return GF_ISOM_INVALID_FILE; + gf_bs_read_data(bs, dte->data, dte->dataLength); + if (dte->dataLength < 14) gf_bs_skip_bytes(bs, 14 - dte->dataLength); + return GF_OK; + } case 2: - return Read_SampleDTE((GF_SampleDTE *)dte, bs); + { + GF_SampleDTE *dte = (GF_SampleDTE *)_dte; + dte->trackRefIndex = (s8) gf_bs_read_u8(bs); + dte->dataLength = gf_bs_read_u16(bs); + dte->sampleNumber = gf_bs_read_u32(bs); + dte->byteOffset = gf_bs_read_u32(bs); + dte->bytesPerComp = gf_bs_read_u16(bs); + dte->samplesPerComp = gf_bs_read_u16(bs); + if (dte->bytesPerComp != 1) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with bytesperblock %d, not 1\n", dte->bytesPerComp)); + } + if (dte->samplesPerComp != 1) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with samplesperblock %d, not 1\n", dte->bytesPerComp)); + } + return GF_OK; + } case 3: - return Read_StreamDescDTE((GF_StreamDescDTE *)dte, bs); + { + GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte; + dte->trackRefIndex = gf_bs_read_u8(bs); + dte->dataLength = gf_bs_read_u16(bs); + dte->streamDescIndex = gf_bs_read_u32(bs); + dte->byteOffset = gf_bs_read_u32(bs); + dte->reserved = gf_bs_read_u32(bs); + return GF_OK; + } default: return GF_ISOM_INVALID_FILE; } @@ -597,63 +545,56 @@ /******************************************************************** Writing of DataTable entries in the RTP sample ********************************************************************/ -GF_Err Write_EmptyDTE(GF_EmptyDTE *dte, GF_BitStream *bs) -{ - gf_bs_write_u8(bs, dte->source); - //empty but always 15 bytes !!! - gf_bs_write_data(bs, "empty hint DTE", 15); - return GF_OK; -} - -GF_Err Write_ImmediateDTE(GF_ImmediateDTE *dte, GF_BitStream *bs) -{ - gf_bs_write_u8(bs, dte->source); - gf_bs_write_u8(bs, dte->dataLength); - gf_bs_write_data(bs, dte->data, dte->dataLength); - if (dte->dataLength < 14) { - char data[14]; - memset(data, 0, 14); - gf_bs_write_data(bs, data, 14 - dte->dataLength); - } - return GF_OK; -} -GF_Err Write_SampleDTE(GF_SampleDTE *dte, GF_BitStream *bs) -{ - gf_bs_write_u8(bs, dte->source); - gf_bs_write_u8(bs, dte->trackRefIndex); - gf_bs_write_u16(bs, dte->dataLength); - gf_bs_write_u32(bs, dte->sampleNumber); - gf_bs_write_u32(bs, dte->byteOffset); - gf_bs_write_u16(bs, dte->bytesPerComp); - gf_bs_write_u16(bs, dte->samplesPerComp); - return GF_OK; -} - -GF_Err Write_StreamDescDTE(GF_StreamDescDTE *dte, GF_BitStream *bs) -{ - gf_bs_write_u8(bs, dte->source); - - gf_bs_write_u8(bs, dte->trackRefIndex); - gf_bs_write_u16(bs, dte->dataLength); - gf_bs_write_u32(bs, dte->streamDescIndex); - gf_bs_write_u32(bs, dte->byteOffset); - gf_bs_write_u32(bs, dte->reserved); - return GF_OK; -} -GF_Err WriteDTE(GF_GenericDTE *dte, GF_BitStream *bs) +GF_Err WriteDTE(GF_GenericDTE *_dte, GF_BitStream *bs) { - switch (dte->source) { + switch (_dte->source) { case 0: - //nothing to do, it is an empty entry - return Write_EmptyDTE((GF_EmptyDTE *)dte, bs); + { + GF_EmptyDTE *dte = (GF_EmptyDTE *)_dte; + gf_bs_write_u8(bs, dte->source); + //empty but always 15 bytes !!! + gf_bs_write_data(bs, "empty hint DTE", 15); + return GF_OK; + } case 1: - return Write_ImmediateDTE((GF_ImmediateDTE *)dte, bs); + { + GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte; + gf_bs_write_u8(bs, dte->source); + gf_bs_write_u8(bs, dte->dataLength); + gf_bs_write_data(bs, dte->data, dte->dataLength); + if (dte->dataLength < 14) { + char data[14]; + memset(data, 0, 14); + gf_bs_write_data(bs, data, 14 - dte->dataLength); + } + return GF_OK; + } case 2: - return Write_SampleDTE((GF_SampleDTE *)dte, bs); + { + GF_SampleDTE *dte = (GF_SampleDTE *)_dte; + gf_bs_write_u8(bs, dte->source); + gf_bs_write_u8(bs, dte->trackRefIndex); + gf_bs_write_u16(bs, dte->dataLength); + gf_bs_write_u32(bs, dte->sampleNumber); + gf_bs_write_u32(bs, dte->byteOffset); + gf_bs_write_u16(bs, dte->bytesPerComp); + gf_bs_write_u16(bs, dte->samplesPerComp); + return GF_OK; + } case 3: - return Write_StreamDescDTE((GF_StreamDescDTE *)dte, bs); + { + GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte; + gf_bs_write_u8(bs, dte->source); + + gf_bs_write_u8(bs, dte->trackRefIndex); + gf_bs_write_u16(bs, dte->dataLength); + gf_bs_write_u32(bs, dte->streamDescIndex); + gf_bs_write_u32(bs, dte->byteOffset); + gf_bs_write_u32(bs, dte->reserved); + return GF_OK; + } default: return GF_ISOM_INVALID_FILE; }
View file
gpac-1.0.0.tar.gz/src/isomedia/iff.c -> gpac-1.0.1.tar.gz/src/isomedia/iff.c
Changed
@@ -981,7 +981,7 @@ char sz_item_name[256]; GF_TileItemMode orig_tile_mode; -#ifndef GPAC_DISABLE_AV_PARSERS +#if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS) e = gf_media_split_hevc_tiles(movie, 0); #else e = GF_NOT_SUPPORTED;
View file
gpac-1.0.0.tar.gz/src/isomedia/isom_intern.c -> gpac-1.0.1.tar.gz/src/isomedia/isom_intern.c
Changed
@@ -164,10 +164,10 @@ } while ((trun = (GF_TrackFragmentRunBox*)gf_list_enum(traf->TrackRuns, &j))) { - u32 i = 0; - GF_TrunEntry *entry; + u32 i; trun->flags |= GF_ISOM_TRUN_FLAGS; - while ((entry = (GF_TrunEntry*)gf_list_enum(trun->entries, &i))) { + for (i=0; i<trun->nb_samples; i++) { + GF_TrunEntry *entry = &trun->samples[i]; const u8 info = traf->sdtp->sample_info[sample_index]; entry->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(info >> 6, info >> 4, info >> 2, info); sample_index++; @@ -229,7 +229,7 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u32 *boxType, u64 *bytesMissing, Bool progressive_mode) { GF_Box *a; - u64 totSize; + u64 totSize, mdat_end=0; GF_Err e = GF_OK; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS @@ -315,6 +315,10 @@ } } + if (mdat_end && mov->signal_frag_bounds && !(mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) ) { + gf_isom_push_mdat_end(mov, mdat_end); + mdat_end=0; + } break; /*META box*/ @@ -350,7 +354,11 @@ if (mov->signal_frag_bounds && !(mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) ) { - gf_isom_push_mdat_end(mov, gf_bs_get_position(mov->movieFileMap->bs) ); + mdat_end = gf_bs_get_position(mov->movieFileMap->bs); + if (mov->moov) { + gf_isom_push_mdat_end(mov, mdat_end); + mdat_end=0; + } } } /*if we don't have any MDAT yet, create one (edit-write mode) @@ -1120,14 +1128,20 @@ //but we have the edit one if (OpenMode == GF_ISOM_OPEN_WRITE) { + const char *ext; //THIS IS NOT A TEMP FILE, WRITE mode is used for "live capture" //this file will be the final file... mov->fileName = fileName ? gf_strdup(fileName) : NULL; e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_WRITE, &mov->editFileMap); if (e) goto err_exit; - /*brand is set to ISOM by default - it may be touched until sample data is added to track*/ - gf_isom_set_brand_info( (GF_ISOFile *) mov, GF_ISOM_BRAND_ISOM, 1); + /*brand is set to ISOM or QT by default - it may be touched until sample data is added to track*/ + ext = gf_file_ext_start(fileName); + if (ext && (!strnicmp(ext, ".mov", 4) || !strnicmp(ext, ".qt", 3))) { + gf_isom_set_brand_info((GF_ISOFile *) mov, GF_ISOM_BRAND_QT, 512); + } else { + gf_isom_set_brand_info((GF_ISOFile *) mov, GF_ISOM_BRAND_ISOM, 1); + } } else { //we are in EDIT mode but we are creating the file -> temp file mov->finalName = fileName ? gf_strdup(fileName) : NULL; @@ -1243,6 +1257,7 @@ #endif /*GPAC_DISABLE_ISOM_WRITE*/ +#if 0 //unused u32 gf_isom_sample_get_subsamples_count(GF_ISOFile *movie, u32 track) { GF_TrackBox *trak = gf_isom_get_track_from_file(movie, track); @@ -1250,6 +1265,7 @@ if (!trak->Media || !trak->Media->information->sampleTable || !trak->Media->information->sampleTable->sub_samples) return 0; return gf_list_count(trak->Media->information->sampleTable->sub_samples); } +#endif Bool gf_isom_get_subsample_types(GF_ISOFile *movie, u32 track, u32 subs_index, u32 *flags) {
View file
gpac-1.0.0.tar.gz/src/isomedia/isom_read.c -> gpac-1.0.1.tar.gz/src/isomedia/isom_read.c
Changed
@@ -56,7 +56,11 @@ return the_file->openMode; } -GF_EXPORT +#if 0 //unused +/*! gets file size of an ISO file +\param isom_file the target ISO file +\return the file size in bytes +*/ u64 gf_isom_get_file_size(GF_ISOFile *the_file) { if (!the_file) return 0; @@ -66,6 +70,7 @@ #endif return 0; } +#endif GF_EXPORT GF_Err gf_isom_freeze_order(GF_ISOFile *file) @@ -562,8 +567,16 @@ e = gf_isom_box_size((GF_Box *)movie->mfra); if (e) return e; movie->mfra->mfro->container_size = (u32) movie->mfra->size; + //write mfra - e = gf_isom_box_write((GF_Box *)movie->mfra, movie->editFileMap->bs); + if (!strcmp(movie->fileName, "_gpac_isobmff_redirect") && movie->on_block_out) { + GF_BitStream *bs = gf_bs_new_cbk(movie->on_block_out, movie->on_block_out_usr_data, movie->on_block_out_block_size); + + e = gf_isom_box_write((GF_Box *)movie->mfra, bs); + gf_bs_del(bs); + } else { + e = gf_isom_box_write((GF_Box *)movie->mfra, movie->editFileMap->bs); + } } } else #endif @@ -598,12 +611,16 @@ } -GF_EXPORT +#if 0 //unused +/*! checks if files has root OD/IOD or not +\param isom_file the target ISO file +\return GF_TRUE if the file has a root OD or IOD */ Bool gf_isom_has_root_od(GF_ISOFile *movie) { if (!movie || !movie->moov || !movie->moov->iods || !movie->moov->iods->descriptor) return GF_FALSE; return GF_TRUE; } +#endif GF_EXPORT void gf_isom_disable_odf_conversion(GF_ISOFile *movie, Bool disable) @@ -1924,6 +1941,7 @@ } /*retrieves given sample DTS*/ +GF_EXPORT u32 gf_isom_get_sample_from_dts(GF_ISOFile *the_file, u32 trackNumber, u64 dts) { GF_Err e; @@ -2082,8 +2100,9 @@ return e; } if (sample && ! (*sample)->IsRAP) { - Bool has_roll, is_rap; - e = gf_isom_get_sample_rap_roll_info(the_file, trackNumber, sampleNumber, &is_rap, &has_roll, NULL); + Bool is_rap; + GF_ISOSampleRollType roll_type; + e = gf_isom_get_sample_rap_roll_info(the_file, trackNumber, sampleNumber, &is_rap, &roll_type, NULL); if (e) return e; if (is_rap) (*sample)->IsRAP = SAP_TYPE_3; } @@ -2400,6 +2419,7 @@ return movie->brand->altBrand; } +GF_EXPORT GF_Err gf_isom_get_sample_padding_bits(GF_ISOFile *the_file, u32 trackNumber, u32 sampleNumber, u8 *NbBits) { GF_TrackBox *trak; @@ -2913,16 +2933,22 @@ stbl = trak->Media->information->sampleTable; if (!stbl->TimeToSample || !stbl->SampleSize || !stbl->SampleToChunk) return GF_ISOM_INVALID_FILE; - //then remove first sample + + //remove at once nb_samples in stts, ctts, stsz, stco, stsc and stdp (n-times removal is way too slow) + //do NOT change the order DTS, CTS, size chunk + stbl_RemoveDTS(stbl, 1, nb_samples, 0); + stbl_RemoveCTS(stbl, 1, nb_samples); + stbl_RemoveSize(stbl, 1, nb_samples); + stbl_RemoveChunk(stbl, 1, nb_samples); + stbl_RemoveRedundant(stbl, 1, nb_samples); + + //then remove sample per sample for the rest, which is either + //- sparse data + //- allocated structure rather than memmove-able array + //- not very frequent info (paddind bits) while (nb_samples) { - //do NOT change the order DTS, CTS, size chunk - stbl_RemoveDTS(stbl, 1, 0); - stbl_RemoveCTS(stbl, 1); - stbl_RemoveSize(stbl, 1); - stbl_RemoveChunk(stbl, 1); stbl_RemoveRAP(stbl, 1); stbl_RemoveShadow(stbl, 1); - stbl_RemoveRedundant(stbl, 1); stbl_RemoveSubSample(stbl, 1); stbl_RemovePaddingBits(stbl, 1); stbl_RemoveSampleGroup(stbl, 1); @@ -3980,7 +4006,50 @@ return id+1; } +GF_EXPORT +u8 *gf_isom_sample_get_subsamples_buffer(GF_ISOFile *movie, u32 track, u32 sampleNumber, u32 *osize) +{ + u8 *data; + u32 size; + u32 i, count; + GF_BitStream *bs = NULL; + GF_TrackBox *trak = gf_isom_get_track_from_file(movie, track); + if (!trak || !osize) return NULL; + if (!trak->Media || !trak->Media->information->sampleTable || !trak->Media->information->sampleTable->sub_samples) return NULL; + + count = gf_list_count(trak->Media->information->sampleTable->sub_samples); + for (i=0; i<count; i++) { + u32 j, sub_count, last_sample = 0; + GF_SubSampleInformationBox *sub_samples = gf_list_get(trak->Media->information->sampleTable->sub_samples, i); + + sub_count = gf_list_count(sub_samples->Samples); + for (j=0; j<sub_count; j++) { + GF_SubSampleInfoEntry *pSamp = (GF_SubSampleInfoEntry *) gf_list_get(sub_samples->Samples, j); + if (last_sample + pSamp->sample_delta == sampleNumber) { + u32 scount = gf_list_count(pSamp->SubSamples); + for (j=0; j<scount; j++) { + GF_SubSampleEntry *sent = gf_list_get(pSamp->SubSamples, j); + if (!bs) bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + gf_bs_write_u32(bs, sub_samples->flags); + gf_bs_write_u32(bs, sent->subsample_size); + gf_bs_write_u32(bs, sent->reserved); + gf_bs_write_u8(bs, sent->subsample_priority); + gf_bs_write_u8(bs, sent->discardable); + } + break; + } + last_sample += pSamp->sample_delta; + } + } + if (!bs) return NULL; + gf_bs_get_content(bs, &data, &size); + gf_bs_del(bs); + *osize = size; + return data; +} +GF_EXPORT u32 gf_isom_sample_has_subsamples(GF_ISOFile *movie, u32 track, u32 sampleNumber, u32 flags) { GF_TrackBox *trak = gf_isom_get_track_from_file(movie, track); @@ -3989,6 +4058,7 @@ return gf_isom_sample_get_subsample_entry(movie, track, sampleNumber, flags, NULL); } +GF_EXPORT GF_Err gf_isom_sample_get_subsample(GF_ISOFile *movie, u32 track, u32 sampleNumber, u32 flags, u32 subSampleNumber, u32 *size, u8 *priority, u32 *reserved, Bool *discardable) { GF_SubSampleEntry *entry; @@ -4108,13 +4178,13 @@ } GF_EXPORT -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_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, Bool *is_rap, GF_ISOSampleRollType *roll_type, s32 *roll_distance) { GF_TrackBox *trak; u32 i, count; if (is_rap) *is_rap = GF_FALSE; - if (has_roll) *has_roll = GF_FALSE; + if (roll_type) *roll_type = 0; if (roll_distance) *roll_distance = 0; trak = gf_isom_get_track_from_file(the_file, trackNumber); @@ -4131,7 +4201,9 @@ if (is_rap) *is_rap = GF_TRUE; break; case GF_ISOM_SAMPLE_GROUP_ROLL: - if (has_roll) *has_roll = GF_TRUE; + case GF_ISOM_SAMPLE_GROUP_PROL: + if (roll_type) + *roll_type = (sgdesc->grouping_type==GF_ISOM_SAMPLE_GROUP_PROL) ? GF_ISOM_SAMPLE_PREROLL : GF_ISOM_SAMPLE_ROLL; if (roll_distance) { s32 max_roll = 0; u32 j; @@ -4185,7 +4257,10 @@ if (is_rap) *is_rap = GF_TRUE; break; case GF_ISOM_SAMPLE_GROUP_ROLL: - if (has_roll) *has_roll = GF_TRUE; + case GF_ISOM_SAMPLE_GROUP_PROL: + if (roll_type) + *roll_type = (sgdesc->grouping_type==GF_ISOM_SAMPLE_GROUP_PROL) ? GF_ISOM_SAMPLE_PREROLL : GF_ISOM_SAMPLE_ROLL; + if (roll_distance) { GF_RollRecoveryEntry *roll_entry = (GF_RollRecoveryEntry *) gf_list_get(sgdesc->group_descriptions, group_desc_index - 1); if (roll_entry) @@ -4304,18 +4379,17 @@ for (k=0; k<gf_list_count(traf->TrackRuns); k++) { GF_TrackFragmentRunBox *trun = (GF_TrackFragmentRunBox*)gf_list_get(traf->TrackRuns, k); - u32 nb_ent = gf_list_count(trun->entries); *nb_samples += trun->sample_count; - for (l=0; l<gf_list_count(trun->entries); l++) { - GF_TrunEntry *ent = (GF_TrunEntry*)gf_list_get(trun->entries, l); + for (l=0; l<trun->nb_samples; l++) { + GF_TrunEntry *ent = &trun->samples[l]; samp_dur = def_duration; if (trun->flags & GF_ISOM_TRUN_DURATION) samp_dur = ent->Duration; - if (nb_ent == trun->sample_count) + if (trun->nb_samples == trun->sample_count) *duration += samp_dur; } - if (nb_ent != trun->sample_count) + if (trun->nb_samples != trun->sample_count) *duration += samp_dur * trun->sample_count; } } @@ -4407,7 +4481,14 @@ return count; } -GF_EXPORT +#if 0 //unused +/*! gets serialized PSS +\param isom_file the target ISO file +\param pssh_index 1-based index of PSSH to query, see \ref gf_isom_get_pssh_count +\param pssh_data set to a newly allocated buffer containing serialized PSSH - shall be freeed by caller +\param pssh_size set to the size of the allocated buffer +\return error if any +*/ GF_Err gf_isom_get_pssh(GF_ISOFile *file, u32 pssh_index, u8 **pssh_data, u32 *pssh_size) { GF_Err e; @@ -4429,6 +4510,7 @@ gf_bs_del(bs); return e; } +#endif GF_EXPORT GF_Err gf_isom_get_pssh_info(GF_ISOFile *file, u32 pssh_index, bin128 SystemID, u32 *version, u32 *KID_count, const bin128 **KIDs, const u8 **private_data, u32 *private_data_size) @@ -4840,6 +4922,12 @@ if (!trak || !trak->Media) return GF_FALSE; if (!trak->Media->information->sampleTable->traf_map) return GF_FALSE; +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + if (sampleNum<=trak->sample_count_at_seg_start) + return GF_FALSE; + sampleNum -= trak->sample_count_at_seg_start; +#endif + tmap = trak->Media->information->sampleTable->traf_map; if (!tmap) return GF_FALSE; for (i=0; i<tmap->nb_entries; i++) {
View file
gpac-1.0.0.tar.gz/src/isomedia/isom_store.c -> gpac-1.0.1.tar.gz/src/isomedia/isom_store.c
Changed
@@ -190,7 +190,7 @@ /*for progress, assume only one descIndex*/ if (Media_IsSelfContained(writer->mdia, 1)) mw->total_samples += writer->stbl->SampleSize->sampleCount; - /*optimization for interleaving: put audio last (this can be overriden by priorities)*/ + /*optimization for interleaving: put audio last (this can be overridden by priorities)*/ if (movie->storageMode != GF_ISOM_STORE_INTERLEAVED) { gf_list_add(writers, writer); } else { @@ -200,8 +200,10 @@ gf_list_insert(writers, writer, 0); } } - if (movie->sample_groups_in_traf && trak->Media->information->sampleTable) - trak->Media->information->sampleTable->skip_sample_groups = GF_TRUE; + if (movie->sample_groups_in_traf && trak->Media->information->sampleTable) { + gf_isom_box_array_del_parent(&trak->Media->information->sampleTable->child_boxes, trak->Media->information->sampleTable->sampleGroupsDescription); + trak->Media->information->sampleTable->sampleGroupsDescription = NULL; + } } return GF_OK; @@ -320,7 +322,7 @@ *box_csize = (u32) root_box->size; gf_bs_get_content(comp_bs, &box_data, &box_size); - gf_gz_compress_payload_ex(&box_data, box_size, &comp_size, 8, GF_TRUE); + gf_gz_compress_payload_ex(&box_data, box_size, &comp_size, 8, GF_TRUE, NULL); if (mov->force_compress || (comp_size + COMP_BOX_COST_BYTES < box_size)) { if (bs) { gf_bs_write_u32(bs, comp_size+8); @@ -790,6 +792,12 @@ GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; s32 moov_meta_pos=-1; + + //in case we did a read on the file while producing it, seek to end of edit + totSize = gf_bs_get_size(bs); + if (gf_bs_get_position(bs) != totSize) { + gf_bs_seek(bs, totSize); + } begin = totSize = 0; //first setup the writers
View file
gpac-1.0.0.tar.gz/src/isomedia/isom_write.c -> gpac-1.0.1.tar.gz/src/isomedia/isom_write.c
Changed
@@ -1404,18 +1404,18 @@ //do NOT change the order DTS, CTS, size chunk //remove DTS - e = stbl_RemoveDTS(trak->Media->information->sampleTable, sampleNumber, trak->Media->mediaHeader->timeScale); + e = stbl_RemoveDTS(trak->Media->information->sampleTable, sampleNumber, 1, trak->Media->mediaHeader->timeScale); if (e) return e; //remove CTS if any if (trak->Media->information->sampleTable->CompositionOffset) { - e = stbl_RemoveCTS(trak->Media->information->sampleTable, sampleNumber); + e = stbl_RemoveCTS(trak->Media->information->sampleTable, sampleNumber, 1); if (e) return e; } //remove size - e = stbl_RemoveSize(trak->Media->information->sampleTable, sampleNumber); + e = stbl_RemoveSize(trak->Media->information->sampleTable, sampleNumber, 1); if (e) return e; //remove sampleToChunk and chunk - e = stbl_RemoveChunk(trak->Media->information->sampleTable, sampleNumber); + e = stbl_RemoveChunk(trak->Media->information->sampleTable, sampleNumber, 1); if (e) return e; //remove sync if (trak->Media->information->sampleTable->SyncSample) { @@ -1424,7 +1424,7 @@ } //remove sample dep if (trak->Media->information->sampleTable->SampleDep) { - e = stbl_RemoveRedundant(trak->Media->information->sampleTable, sampleNumber); + e = stbl_RemoveRedundant(trak->Media->information->sampleTable, sampleNumber, 1); if (e) return e; } //remove shadow @@ -5613,6 +5613,11 @@ info->data->flags = 0x15; break; default: + if (info->type==GF_ISOM_BOX_TYPE_UNKNOWN) { + info = (GF_ListItemBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TRKN); + if (info == NULL) return GF_OUT_OF_MEM; + info->type = btype; + } info->data->flags = 0x1; break; } @@ -5661,7 +5666,8 @@ } return GF_OK; } - + if (!ilst->child_boxes) ilst->child_boxes = gf_list_new(); + return gf_list_add(ilst->child_boxes, info); } @@ -6354,15 +6360,23 @@ } GF_EXPORT -GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_number, Bool is_roll, s16 roll_distance) +GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_number, GF_ISOSampleRollType roll_type, s16 roll_distance) { - return gf_isom_set_sample_group_info(movie, track, 0, sample_number, GF_ISOM_SAMPLE_GROUP_ROLL, 0, &roll_distance, is_roll ? sg_roll_create_entry : NULL, is_roll ? sg_roll_compare_entry : NULL); + u32 grp_type = (roll_type>=GF_ISOM_SAMPLE_PREROLL) ? GF_ISOM_SAMPLE_GROUP_PROL : GF_ISOM_SAMPLE_GROUP_ROLL; + if (roll_type==GF_ISOM_SAMPLE_PREROLL_NONE) + roll_type = 0; + + return gf_isom_set_sample_group_info(movie, track, 0, sample_number, grp_type, 0, &roll_distance, roll_type ? sg_roll_create_entry : NULL, roll_type ? sg_roll_compare_entry : NULL); } GF_EXPORT -GF_Err gf_isom_fragment_set_sample_roll_group(GF_ISOFile *movie, GF_ISOTrackID trackID, u32 sample_number_in_frag, Bool is_roll, s16 roll_distance) +GF_Err gf_isom_fragment_set_sample_roll_group(GF_ISOFile *movie, GF_ISOTrackID trackID, u32 sample_number_in_frag, GF_ISOSampleRollType roll_type, s16 roll_distance) { - return gf_isom_set_sample_group_info(movie, 0, trackID, sample_number_in_frag, GF_ISOM_SAMPLE_GROUP_ROLL, 0, &roll_distance, is_roll ? sg_roll_create_entry : NULL, is_roll ? sg_roll_compare_entry : NULL); + u32 grp_type = (roll_type>=GF_ISOM_SAMPLE_PREROLL) ? GF_ISOM_SAMPLE_GROUP_PROL : GF_ISOM_SAMPLE_GROUP_ROLL; + if (roll_type==GF_ISOM_SAMPLE_PREROLL_NONE) + roll_type = 0; + + return gf_isom_set_sample_group_info(movie, 0, trackID, sample_number_in_frag, grp_type, 0, &roll_distance, roll_type ? sg_roll_create_entry : NULL, roll_type ? sg_roll_compare_entry : NULL); } @@ -6442,7 +6456,23 @@ } if (!ctts->version) { ctts->version = 1; - gf_isom_remove_edits(file, track); + //if we had edit lists, shift all media times by the given amount + if (trak->editBox && trak->editBox->editList) { + for (i=0; i<gf_list_count(trak->editBox->editList->entryList); i++) { + GF_EdtsEntry *ent = (GF_EdtsEntry*)gf_list_get(trak->editBox->editList->entryList, i); + //empty edit + if (ent->mediaTime<0) continue; + if (ent->mediaTime>=shift) ent->mediaTime -= shift; + else ent->mediaTime = 0; + //no offset and last entry, trash edit + if (!ent->mediaTime && (gf_list_count(trak->editBox->editList->entryList)==1)) { + gf_isom_box_del_parent(&trak->child_boxes, (GF_Box *)trak->editBox); + trak->editBox = NULL; + break; + } + } + SetTrackDuration(trak); + } } if (!trak->Media->information->sampleTable->CompositionToDecode) { @@ -6499,11 +6529,23 @@ gf_isom_box_del_parent(&trak->Media->information->sampleTable->child_boxes, (GF_Box *)cslg); trak->Media->information->sampleTable->CompositionToDecode = NULL; } - if (! trak->editBox && shift>0) { - u64 dur = trak->Media->mediaHeader->duration; - dur *= file->moov->mvhd->timeScale; - dur /= trak->Media->mediaHeader->timeScale; - gf_isom_set_edit(file, gf_list_find(file->moov->trackList, trak)+1, 0, dur, shift, GF_ISOM_EDIT_NORMAL); + if (shift>0) { + //no edits, insert one + if (! trak->editBox) { + u64 dur = trak->Media->mediaHeader->duration; + dur *= file->moov->mvhd->timeScale; + dur /= trak->Media->mediaHeader->timeScale; + gf_isom_set_edit(file, gf_list_find(file->moov->trackList, trak)+1, 0, dur, shift, GF_ISOM_EDIT_NORMAL); + } else { + //otherwise shift media times in all entries + for (i=0; i<gf_list_count(trak->editBox->editList->entryList); i++) { + GF_EdtsEntry *ent = (GF_EdtsEntry*)gf_list_get(trak->editBox->editList->entryList, i); + //empty edit + if (ent->mediaTime<0) continue; + ent->mediaTime += shift; + } + SetTrackDuration(trak); + } } ctts->version = 0; gf_isom_modify_alternate_brand(file, GF_ISOM_BRAND_ISO4, GF_FALSE);
View file
gpac-1.0.0.tar.gz/src/isomedia/media.c -> gpac-1.0.1.tar.gz/src/isomedia/media.c
Changed
@@ -369,6 +369,31 @@ case GF_ISOM_SUBTYPE_MH3D_MHA2: case GF_ISOM_SUBTYPE_MH3D_MHM1: case GF_ISOM_SUBTYPE_MH3D_MHM2: + if (true_desc_only) { + return GF_ISOM_INVALID_MEDIA; + } else { + GF_MPEGAudioSampleEntryBox*ptr = (GF_MPEGAudioSampleEntryBox*)entry; + esd = gf_odf_desc_esd_new(2); + *out_esd = esd; + esd->decoderConfig->streamType = GF_STREAM_AUDIO; + if ((type==GF_ISOM_SUBTYPE_MH3D_MHA1) || (type==GF_ISOM_SUBTYPE_MH3D_MHA2)) + esd->decoderConfig->objectTypeIndication = GF_CODECID_MPHA; + else + esd->decoderConfig->objectTypeIndication = GF_CODECID_MHAS; + if (ptr->cfg_mha) { + GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + gf_bs_write_u8(bs, ptr->cfg_mha->configuration_version); + gf_bs_write_u8(bs, ptr->cfg_mha->mha_pl_indication); + gf_bs_write_u8(bs, ptr->cfg_mha->reference_channel_layout); + gf_bs_write_u16(bs, ptr->cfg_mha->mha_config ? ptr->cfg_mha->mha_config_size : 0); + if (ptr->cfg_mha->mha_config && ptr->cfg_mha->mha_config_size) + gf_bs_write_data(bs, ptr->cfg_mha->mha_config, ptr->cfg_mha->mha_config_size); + + gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); + gf_bs_del(bs); + } + } break; default: @@ -475,9 +500,9 @@ if (!sIDX && !out_offset) return GF_OK; if (!sIDX) return GF_OK; - (*sIDX) = 0; - e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, sIDX, &stsc_entry); - if (e) return e; + (*sIDX) = sdesc_idx; +// e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, sIDX, &stsc_entry); +// if (e) return e; //then get the DataRef e = Media_GetSampleDesc(mdia, sdesc_idx, &entry, &dataRefIndex); @@ -800,9 +825,6 @@ ent = NULL; } trak->Media->mediaHeader->duration = DTS; -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - trak->Media->mediaHeader->duration += trak->dts_at_seg_start; -#endif #if 1
View file
gpac-1.0.0.tar.gz/src/isomedia/meta.c -> gpac-1.0.1.tar.gz/src/isomedia/meta.c
Changed
@@ -93,6 +93,7 @@ return GF_OK; } +#if 0 //unused GF_XMLBox *gf_isom_get_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool *is_binary) { u32 i, count; @@ -113,7 +114,7 @@ } return NULL; } - +#endif GF_EXPORT @@ -512,12 +513,14 @@ } GF_EXPORT -GF_Err gf_isom_set_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, char *XMLFileName, Bool IsBinaryXML) +GF_Err gf_isom_set_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, char *XMLFileName, unsigned char *data, u32 data_size, Bool IsBinaryXML) { GF_Err e; GF_XMLBox *xml; GF_MetaBox *meta; u32 length; + if (!XMLFileName && !data) + return GF_BAD_PARAM; e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); if (e) return e; @@ -532,31 +535,10 @@ if (!xml) return GF_OUT_OF_MEM; if (IsBinaryXML) xml->type = GF_ISOM_BOX_TYPE_BXML; - - /*assume 32bit max size = 4Go should be sufficient for a DID!!*/ - return gf_file_load_data(XMLFileName, (u8 **) &xml->xml, &length); -} - -GF_EXPORT -GF_Err gf_isom_set_meta_xml_memory(GF_ISOFile *file, Bool root_meta, u32 track_num, unsigned char *data, u32 data_size, Bool IsBinaryXML) -{ - GF_Err e; - GF_XMLBox *xml; - GF_MetaBox *meta; - - e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); - if (e) return e; - - meta = gf_isom_get_meta(file, root_meta, track_num); - if (!meta) return GF_BAD_PARAM; - - e = gf_isom_remove_meta_xml(file, root_meta, track_num); - if (e) return e; - - xml = (GF_XMLBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_XML); - if (!xml) return GF_OUT_OF_MEM; - if (IsBinaryXML) xml->type = GF_ISOM_BOX_TYPE_BXML; - + if (XMLFileName) { + /*assume 32bit max size = 4Go should be sufficient for a DID!!*/ + return gf_file_load_data(XMLFileName, (u8 **) &xml->xml, &length); + } /*assume 32bit max size = 4Go should be sufficient for a DID!!*/ xml->xml = (char*)gf_malloc(sizeof(unsigned char)*data_size); @@ -565,6 +547,7 @@ return GF_OK; } + GF_EXPORT GF_Err gf_isom_get_meta_image_props(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, GF_ImageItemProperties *prop) { u32 count, i;
View file
gpac-1.0.0.tar.gz/src/isomedia/movie_fragments.c -> gpac-1.0.1.tar.gz/src/isomedia/movie_fragments.c
Changed
@@ -40,16 +40,6 @@ return NULL; } -GF_TrackExtensionPropertiesBox *GetTrep(GF_MovieBox *moov, GF_ISOTrackID TrackID) -{ - u32 i; - GF_TrackExtensionPropertiesBox *trep; - i=0; - while ((trep = (GF_TrackExtensionPropertiesBox*) gf_list_enum(moov->mvex->TrackExPropList, &i))) { - if (trep->trackID == TrackID) return trep; - } - return NULL; -} GF_TrackFragmentBox *gf_isom_get_traf(GF_ISOFile *mov, GF_ISOTrackID TrackID) { @@ -121,8 +111,11 @@ while ((trex = (GF_TrackExtendsBox *)gf_list_enum(movie->moov->mvex->TrackExList, &i))) { if (trex->type != GF_ISOM_BOX_TYPE_TREX) continue; if (trex->track->Media->information->sampleTable->CompositionToDecode) { + u32 k=0; GF_TrackExtensionPropertiesBox *trep; - trep = GetTrep(movie->moov, trex->trackID); + while ((trep = (GF_TrackExtensionPropertiesBox*) gf_list_enum(movie->moov->mvex->TrackExPropList, &k))) { + if (trep->trackID == trex->trackID) break; + } if (!trep) { trep = (GF_TrackExtensionPropertiesBox*) gf_isom_box_new_parent(&movie->moov->mvex->child_boxes, GF_ISOM_BOX_TYPE_TREP); @@ -300,6 +293,7 @@ return gf_isom_change_track_fragment_defaults(movie, TrackID, DefaultSampleDescriptionIndex, DefaultSampleDuration, DefaultSampleSize, DefaultSampleIsSync, DefaultSamplePadding, DefaultDegradationPriority, force_traf_flags); } +#ifdef GF_ENABLE_CTRN GF_EXPORT GF_Err gf_isom_enable_traf_inherit(GF_ISOFile *movie, GF_ISOTrackID TrackID, GF_ISOTrackID BaseTrackID) { @@ -321,6 +315,7 @@ trex->inherit_from_traf_id = BaseTrackID; return GF_OK; } +#endif GF_EXPORT GF_Err gf_isom_setup_track_fragment_template(GF_ISOFile *movie, GF_ISOTrackID TrackID, u8 *boxes, u32 boxes_size, u8 force_traf_flags) @@ -380,9 +375,8 @@ i=0; while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) { - GF_TrunEntry *ent; - j=0; - while ((ent = (GF_TrunEntry *)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + GF_TrunEntry *ent = &trun->samples[j]; switch (index) { case 1: if (value == ent->Duration) NumValue ++; @@ -410,8 +404,8 @@ MaxNum = DefValue = 0; i=0; while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) { - j=0; - while ((ent = (GF_TrunEntry *)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; ret = GetNumUsedValues(traf, ent->Duration, 1); if (ret>MaxNum) { //at least 2 duration, specify for all @@ -434,8 +428,8 @@ MaxNum = DefValue = 0; i=0; while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) { - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; ret = GetNumUsedValues(traf, ent->size, 2); if (ret>MaxNum || (ret==1)) { //at least 2 sizes so we must specify all sizes @@ -459,8 +453,8 @@ MaxNum = DefValue = 0; i=0; while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) { - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; ret = GetNumUsedValues(traf, ent->flags, 3); if (ret>MaxNum) { MaxNum = ret; @@ -553,7 +547,7 @@ static u32 UpdateRuns(GF_ISOFile *movie, GF_TrackFragmentBox *traf) { - u32 sampleCount, i, j, RunSize, RunDur, RunFlags, NeedFlags, UseCTS, count; + u32 sampleCount, i, j, RunSize, RunDur, RunFlags, NeedFlags, UseCTS; /* enum: 0 - use values per sample in the trun box 1 - use default values from track fragment header @@ -607,9 +601,8 @@ NeedFlags = 0; //process all samples in run - count = gf_list_count(trun->entries); - for (j=0; j<count; j++) { - ent = (GF_TrunEntry*)gf_list_get(trun->entries, j); + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; if (!j) { first_ent = ent; RunSize = ent->size; @@ -617,12 +610,12 @@ RunDur = ent->Duration; } //we may have one entry only ... - if (j || (count==1)) { + if (j || (trun->nb_samples==1)) { u32 ssize = ent->size; if (ent->nb_pack) ssize /= ent->nb_pack; //flags are only after first entry - if (j==1 || (count==1) ) RunFlags = ent->flags; + if (j==1 || (trun->nb_samples==1) ) RunFlags = ent->flags; if (ssize != RunSize) RunSize = 0; if (ent->Duration != RunDur) RunDur = 0; @@ -636,7 +629,6 @@ gf_list_rem(traf->TrackRuns, i); continue; } -// trun->sample_count = gf_list_count(trun->entries); trun->flags = 0; //size checking @@ -796,7 +788,7 @@ while ((trun = (GF_TrackFragmentRunBox*)gf_list_enum(traf->TrackRuns, &i))) { if (trun->flags & GF_ISOM_TRUN_FIRST_FLAG) { if (GF_ISOM_GET_FRAG_SYNC(trun->flags)) { - ent = (GF_TrunEntry*)gf_list_get(trun->entries, 0); + ent = &trun->samples[0]; // if (!delta) earliest_cts = ent->CTS_Offset; *sap_delta = delta + ent->CTS_Offset - ent->CTS_Offset; *starts_with_sap = first; @@ -804,8 +796,8 @@ return sap_type; } } - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; if (!delta) earliest_cts = ent->CTS_Offset; if (GF_ISOM_GET_FRAG_SYNC(ent->flags)) { @@ -843,9 +835,8 @@ duration = 0; i=0; while ((trun = (GF_TrackFragmentRunBox*)gf_list_enum(traf->TrackRuns, &i))) { - GF_TrunEntry *ent; - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + GF_TrunEntry *ent = &trun->samples[j]; if (ent->flags & GF_ISOM_TRAF_SAMPLE_DUR) duration += ent->Duration; else @@ -872,9 +863,8 @@ cts = (u64) -1; i=0; while ((trun = (GF_TrackFragmentRunBox*)gf_list_enum(traf->TrackRuns, &i))) { - GF_TrunEntry *ent; - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + GF_TrunEntry *ent = &trun->samples[j]; if (duration + ent->CTS_Offset < cts) cts = duration + ent->CTS_Offset; duration += ent->Duration; @@ -996,7 +986,13 @@ while (s_count>1) { GF_TrackFragmentRunBox *atrun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, 1); trun->sample_count += atrun->sample_count; - gf_list_transfer(trun->entries, atrun->entries); + + trun->sample_alloc = trun->nb_samples + atrun->nb_samples; + trun->samples = gf_realloc(trun->samples, sizeof(GF_TrunEntry) * trun->sample_alloc); + if (!trun->samples) return GF_OUT_OF_MEM; + + memcpy(&trun->samples[trun->nb_samples], atrun->samples, sizeof(GF_TrunEntry)*atrun->nb_samples); + trun->nb_samples += atrun->nb_samples; for (k=0; k<atrun->sample_count; k++) { trun->sample_order[cur_idx] = atrun->first_sample_idx + k; @@ -1438,6 +1434,12 @@ return media_time ; } + +#if 0 //unused +/*! gets name of current segment (or last segment if called between close_segment and start_segment) +\param isom_file the target ISO file +\return associated file name of the segment +*/ GF_EXPORT const char *gf_isom_get_segment_name(GF_ISOFile *movie) { @@ -1445,6 +1447,7 @@ if (movie->append_segment) return movie->movieFileMap->szName; return movie->editFileMap->szName; } +#endif static void compute_seg_size(GF_ISOFile *movie, u64 *out_seg_size) { @@ -1470,12 +1473,11 @@ nb_trun = gf_list_count(traf->TrackRuns); for (j=0; j<nb_trun; j++) { - u32 k, nb_ent; + u32 k; GF_TrackFragmentRunBox *trun = gf_list_get(traf->TrackRuns, j); u32 offset = base_offset + trun->data_offset; - nb_ent = gf_list_count(trun->entries); - for (k=0; k<nb_ent; k++) { - GF_TrunEntry *ent = gf_list_get(trun->entries, k); + for (k=0; k<trun->nb_samples; k++) { + GF_TrunEntry *ent = &trun->samples[k]; if (ent->SAP_type) return offset + ent->size; offset += ent->size; @@ -1522,8 +1524,8 @@ i=0; while ((trun = (GF_TrackFragmentRunBox*)gf_list_enum(traf->TrackRuns, &i))) { - j=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) { + for (j=0; j<trun->nb_samples; j++) { + ent = &trun->samples[j]; if (nb_aus + 1 + movie->sidx_pts_store_count > movie->sidx_pts_store_alloc) { movie->sidx_pts_store_alloc = movie->sidx_pts_store_count+nb_aus+1; movie->sidx_pts_store = gf_realloc(movie->sidx_pts_store, sizeof(u64) * movie->sidx_pts_store_alloc); @@ -2338,7 +2340,7 @@ GF_EXPORT GF_Err gf_isom_set_fragment_reference_time(GF_ISOFile *movie, GF_ISOTrackID reference_track_ID, u64 ntp, u64 timestamp) { - if (!movie->moof) return GF_BAD_PARAM; + if (!movie || !movie->moof) return GF_BAD_PARAM; movie->moof->reference_track_ID = reference_track_ID; movie->moof->ntp = ntp; movie->moof->timestamp = timestamp; @@ -2454,7 +2456,11 @@ raf->traf_number = i+1; //trun number is set once we fond a sync raf->trun_number = 0; - raf->moof_offset = movie->moof->fragment_offset; + if (!strcmp(movie->fileName, "_gpac_isobmff_redirect")) { + raf->moof_offset = movie->fragmented_file_pos; + } else { + raf->moof_offset = movie->moof->fragment_offset; + } } } return GF_OK; @@ -2542,12 +2548,9 @@ static u32 GetRunSize(GF_TrackFragmentRunBox *trun) { - u32 i, size; - GF_TrunEntry *ent; - size = 0; - i=0; - while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &i))) { - size += ent->size; + u32 i, size=0; + for (i=0; i<trun->nb_samples; i++) { + size += trun->samples[i].size; } return size; } @@ -2560,7 +2563,7 @@ u8 *buffer; u64 pos; GF_ISOSample *od_sample = NULL; - GF_TrunEntry *ent, *prev_ent; + GF_TrunEntry ent, *prev_ent; GF_TrackFragmentBox *traf, *traf_2; GF_TrackFragmentRunBox *trun; @@ -2663,25 +2666,36 @@ trun->cache = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); } - GF_SAFEALLOC(ent, GF_TrunEntry); - if (!ent) return GF_OUT_OF_MEM; - ent->CTS_Offset = sample->CTS_Offset; - ent->Duration = Duration; - ent->dts = sample->DTS; - ent->size = sample->dataLength; - ent->nb_pack = sample->nb_pack; - ent->flags = GF_ISOM_FORMAT_FRAG_FLAGS(PaddingBits, sample->IsRAP, DegradationPriority); + memset(&ent, 0, sizeof(GF_TrunEntry)); + ent.CTS_Offset = sample->CTS_Offset; + ent.Duration = Duration; + ent.dts = sample->DTS; + ent.size = sample->dataLength; + ent.nb_pack = sample->nb_pack; + ent.flags = GF_ISOM_FORMAT_FRAG_FLAGS(PaddingBits, sample->IsRAP, DegradationPriority); if (sample->IsRAP) { - ent->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(0, 2, 0, (redundant_coding ? 1 : 0) ); - ent->SAP_type = sample->IsRAP; + ent.flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(0, 2, 0, (redundant_coding ? 1 : 0) ); + ent.SAP_type = sample->IsRAP; } - prev_ent = gf_list_last(trun->entries); + if (trun->nb_samples) { + prev_ent = &trun->samples[trun->nb_samples-1]; + } else { + prev_ent = NULL; + } + if (prev_ent && prev_ent->dts && sample->DTS) { if (prev_ent->Duration != sample->DTS - prev_ent->dts) prev_ent->Duration = (u32) (sample->DTS - prev_ent->dts); } - gf_list_add(trun->entries, ent); - + if (trun->nb_samples >= trun->sample_alloc) { + trun->sample_alloc += 50; + if (trun->nb_samples >= trun->sample_alloc) trun->sample_alloc = trun->nb_samples+1; + trun->samples = gf_realloc(trun->samples, sizeof(GF_TrunEntry)*trun->sample_alloc); + if (!trun->samples) return GF_OUT_OF_MEM; + } + trun->samples[trun->nb_samples] = ent; + trun->nb_samples ++; + if (sample->CTS_Offset<0) { trun->version = 1; } @@ -2848,9 +2862,8 @@ if (!count) return GF_BAD_PARAM; trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, count-1); - count = gf_list_count(trun->entries); - if (!count) return GF_BAD_PARAM; - ent = (GF_TrunEntry *)gf_list_get(trun->entries, count-1); + if (!trun->nb_samples) return GF_BAD_PARAM; + ent = &trun->samples[trun->nb_samples-1]; ent->size += data_size; rap = GF_ISOM_GET_FRAG_SYNC(ent->flags); @@ -2900,6 +2913,7 @@ if (!subs) return GF_OUT_OF_MEM; subs->version = (subSampleSize>0xFFFF) ? 1 : 0; subs->flags = flags; + gf_list_add(traf->sub_samples, subs); } return gf_isom_add_subsample_info(subs, last_sample, subSampleSize, priority, reserved, discardable); } @@ -3014,6 +3028,8 @@ traf->sdtp->sample_info = gf_realloc(traf->sdtp->sample_info, sizeof(u8)*(traf->sdtp->sampleCount+1)); traf->sdtp->sample_info[traf->sdtp->sampleCount] = (u8) sflags; traf->sdtp->sampleCount++; + traf->sdtp->sample_alloc = traf->sdtp->sampleCount+1; + if (traf->use_sdtp==2) { ent->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(isLeading, dependsOn, dependedOn, redundant); @@ -3123,10 +3139,8 @@ count = gf_list_count(traf->TrackRuns); if (!count) return GF_BAD_PARAM; trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, count-1); - count = gf_list_count(trun->entries); - if (!count) return GF_BAD_PARAM; - - ent = (GF_TrunEntry *)gf_list_get(trun->entries, count-1); + if (!trun->nb_samples) return GF_BAD_PARAM; + ent = &trun->samples[trun->nb_samples-1]; GF_ISOM_RESET_FRAG_DEPEND_FLAGS(ent->flags); @@ -3144,6 +3158,7 @@ traf->sdtp->sample_info = gf_realloc(traf->sdtp->sample_info, sizeof(u8)*(traf->sdtp->sampleCount+1)); traf->sdtp->sample_info[traf->sdtp->sampleCount] = (u8) sflags; traf->sdtp->sampleCount++; + traf->sdtp->sample_alloc = traf->sdtp->sampleCount; if (traf->use_sdtp==2) { ent->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(is_leading, dependsOn, dependedOn, redundant); } @@ -3197,89 +3212,6 @@ return GF_OK; } -#else - -GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file, u32 media_segment_type, Bool mvex_after_tracks) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_setup_track_fragment(GF_ISOFile *the_file, GF_ISOTrackID TrackID, - u32 DefaultSampleDescriptionIndex, - u32 DefaultSampleDuration, - u32 DefaultSampleSize, - u8 DefaultSampleIsSync, - u8 DefaultSamplePadding, - u16 DefaultDegradationPriority, - Bool u8 force_traf_flags) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_set_fragment_option(GF_ISOFile *the_file, GF_ISOTrackID TrackID, GF_ISOTrackFragmentOption Code, u32 Param) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_start_fragment(GF_ISOFile *the_file, GF_ISOStartFragmentFlags flags) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_fragment_add_sample(GF_ISOFile *the_file, GF_ISOTrackID TrackID, const GF_ISOSample *sample, u32 DescIndex, - u32 Duration, u8 PaddingBits, u16 DegradationPriority, Bool redCoded) -{ - return GF_NOT_SUPPORTED; -} - - -GF_EXPORT -Bool gf_isom_is_track_fragmented(GF_ISOFile *the_file, GF_ISOTrackID TrackID) -{ - return GF_FALSE; -} - -GF_EXPORT -Bool gf_isom_is_fragmented(GF_ISOFile *the_file) -{ - return GF_FALSE; -} - -GF_Err gf_isom_fragment_add_subsample(GF_ISOFile *movie, GF_ISOTrackID TrackID, u32 flags, u32 subSampleSize, u8 priority, u32 reserved, Bool discardable) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_fragment_copy_subsample(GF_ISOFile *dest, GF_ISOTrackID TrackID, GF_ISOFile *orig, u32 track, u32 sampleNumber, Bool sgpd_in_traf) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_set_traf_base_media_decode_time(GF_ISOFile *movie, GF_ISOTrackID TrackID, u64 decode_time) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_set_traf_mss_timeext(GF_ISOFile *movie, u32 reference_track_ID, u64 ntp_in_10mhz, u64 traf_duration_in_10mhz) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_enable_mfra(GF_ISOFile *file) -{ - return GF_NOT_SUPPORTED; -} -GF_Err gf_isom_fragment_set_sample_flags(GF_ISOFile *movie, GF_ISOTrackID trackID, u32 is_leading, u32 dependsOn, u32 dependedOn, u32 redundant) -{ - return GF_NOT_SUPPORTED; -} - -GF_Err gf_isom_set_fragment_template(GF_ISOFile *movie, u8 *tpl_data, u32 tpl_size, Bool *has_tfdt) -{ - return GF_NOT_SUPPORTED; -} - - #endif /*GPAC_DISABLE_ISOM_FRAGMENTS)*/
View file
gpac-1.0.0.tar.gz/src/isomedia/sample_descs.c -> gpac-1.0.1.tar.gz/src/isomedia/sample_descs.c
Changed
@@ -999,14 +999,6 @@ return e; } -GF_Err gf_isom_update_xml_metadata_description(GF_ISOFile *movie, u32 trackNumber, - const char *schema_loc, const char *encoding, - u32 DescriptionIndex) -{ - /* TODO */ - return GF_NOT_SUPPORTED; -} - #endif /*GPAC_DISABLE_ISOM_WRITE*/ /* XMLSubtitleSampleEntry */ @@ -1202,7 +1194,16 @@ return e; } +#if 0 //unused +/*! updates simple streaming text config +\param isom_file the target ISO file +\param trackNumber the target track +\param encoding the text encoding, if any +\param config the configuration string, if any +\param sampleDescriptionIndex the target sample description index +\return error if any +*/ GF_Err gf_isom_update_stxt_description(GF_ISOFile *movie, u32 trackNumber, const char *encoding, const char *config, u32 DescriptionIndex) @@ -1245,6 +1246,9 @@ } return GF_OK; } +#endif + + #endif /*GPAC_DISABLE_ISOM_WRITE*/ #ifndef GPAC_DISABLE_VTT @@ -1291,6 +1295,14 @@ #ifndef GPAC_DISABLE_VTT +#if 0 //unused +/*! updates a WebVTT sample description +\param isom_file the target ISO file +\param trackNumber the target track +\param sampleDescriptionIndex the target sample description index to update +\param config the WebVTT configuration string +\return error if any +*/ GF_Err gf_isom_update_webvtt_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, const char *config) { GF_Err e; @@ -1327,6 +1339,8 @@ wvtt->config = (GF_StringBox *)boxstring_new_with_data(GF_ISOM_BOX_TYPE_VTTC_CONFIG, config, &wvtt->child_boxes); return GF_OK; } +#endif + GF_Err gf_isom_new_webvtt_description(GF_ISOFile *movie, u32 trackNumber, const char *URLname, const char *URNname, u32 *outDescriptionIndex, const char *config) {
View file
gpac-1.0.0.tar.gz/src/isomedia/stbl_read.c -> gpac-1.0.1.tar.gz/src/isomedia/stbl_read.c
Changed
@@ -399,7 +399,7 @@ GF_Err stbl_GetSampleInfos(GF_SampleTableBox *stbl, u32 sampleNumber, u64 *offset, u32 *chunkNumber, u32 *descIndex, GF_StscEntry **out_ent) { GF_Err e; - u32 i, k, offsetInChunk, size; + u32 i, k, offsetInChunk, size, chunk_num; GF_ChunkOffsetBox *stco; GF_ChunkLargeOffsetBox *co64; GF_StscEntry *ent; @@ -444,6 +444,7 @@ i = 0; stbl->SampleToChunk->currentIndex = 0; stbl->SampleToChunk->currentChunk = 1; + stbl->SampleToChunk->ghostNumber = 1; stbl->SampleToChunk->firstSampleInCurrentChunk = 1; ent = &stbl->SampleToChunk->entries[0]; GetGhostNum(ent, 0, stbl->SampleToChunk->nb_entries, stbl); @@ -492,7 +493,7 @@ sample_found: (*descIndex) = ent->sampleDescriptionIndex; - (*chunkNumber) = ent->firstChunk + stbl->SampleToChunk->currentChunk - 1; + (*chunkNumber) = chunk_num = ent->firstChunk + stbl->SampleToChunk->currentChunk - 1; if (out_ent) *out_ent = ent; if (! *chunkNumber) return GF_ISOM_INVALID_FILE; @@ -503,6 +504,14 @@ if (stbl->SampleSize && stbl->SampleSize->sampleSize) { u32 diff = sampleNumber - stbl->SampleToChunk->firstSampleInCurrentChunk; offsetInChunk += diff * stbl->SampleSize->sampleSize; + } else if ((stbl->r_last_chunk_num == chunk_num) && (stbl->r_last_sample_num == sampleNumber)) { + offsetInChunk = stbl->r_last_offset_in_chunk; + } else if ((stbl->r_last_chunk_num == chunk_num) && (stbl->r_last_sample_num + 1 == sampleNumber)) { + e = stbl_GetSampleSize(stbl->SampleSize, stbl->r_last_sample_num, &size); + if (e) return e; + stbl->r_last_offset_in_chunk += size; + stbl->r_last_sample_num = sampleNumber; + offsetInChunk = stbl->r_last_offset_in_chunk; } else { //warning, firstSampleInChunk is at least 1 - not 0 for (i = stbl->SampleToChunk->firstSampleInCurrentChunk; i < sampleNumber; i++) { @@ -510,6 +519,9 @@ if (e) return e; offsetInChunk += size; } + stbl->r_last_chunk_num = chunk_num; + stbl->r_last_sample_num = sampleNumber; + stbl->r_last_offset_in_chunk = offsetInChunk; } //OK, that's the size of our offset in the chunk //now get the chunk
View file
gpac-1.0.0.tar.gz/src/isomedia/stbl_write.c -> gpac-1.0.1.tar.gz/src/isomedia/stbl_write.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2000-2019 + * Copyright (c) Telecom ParisTech 2000-2020 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -507,6 +507,7 @@ u32 missed = sampleNumber-1 - sdtp->sampleCount; sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount+missed) ); if (!sdtp->sample_info) return GF_OUT_OF_MEM; + sdtp->sample_alloc = sdtp->sampleCount+missed; memset(&sdtp->sample_info[sdtp->sampleCount], 0, sizeof(u8) * missed ); while (missed) { GF_ISOSAPType isRAP; @@ -520,6 +521,7 @@ sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1)); if (!sdtp->sample_info) return GF_OUT_OF_MEM; + sdtp->sample_alloc = sdtp->sampleCount+1; if (sdtp->sampleCount < sampleNumber) { sdtp->sample_info[sdtp->sampleCount] = 0x29; } else { @@ -552,6 +554,7 @@ u32 i; sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * sampleNumber); if (!sdtp->sample_info) return GF_OUT_OF_MEM; + sdtp->sample_alloc = sampleNumber; for (i=sdtp->sampleCount; i<sampleNumber; i++) { sdtp->sample_info[i] = 0; @@ -562,6 +565,7 @@ return GF_OK; } +#if 0 //unused GF_Err stbl_AddDependencyType(GF_SampleTableBox *stbl, u32 sampleNumber, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant) { u32 flags; @@ -576,6 +580,7 @@ u32 missed = sampleNumber-1 - sdtp->sampleCount; sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount+missed) ); if (!sdtp->sample_info) return GF_OUT_OF_MEM; + sdtp->sample_alloc = sdtp->sampleCount+missed; memset(&sdtp->sample_info[sdtp->sampleCount], 0, sizeof(u8) * missed ); while (missed) { GF_ISOSAPType isRAP; @@ -599,6 +604,7 @@ sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1)); if (!sdtp->sample_info) return GF_OUT_OF_MEM; + sdtp->sample_alloc = sdtp->sampleCount + 1; if (sdtp->sampleCount < sampleNumber) { sdtp->sample_info[sdtp->sampleCount] = flags; } else { @@ -610,6 +616,7 @@ sdtp->sampleCount ++; return GF_OK; } +#endif GF_Err stbl_AppendDependencyType(GF_SampleTableBox *stbl, u32 isLeading, u32 dependsOn, u32 dependedOn, u32 redundant) { @@ -627,9 +634,12 @@ flags |= dependedOn << 2; flags |= redundant; - - sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1)); - if (!sdtp->sample_info) return GF_OUT_OF_MEM; + if (sdtp->sampleCount >= sdtp->sample_alloc) { + ALLOC_INC(sdtp->sample_alloc); + if (sdtp->sampleCount >= sdtp->sample_alloc) sdtp->sample_alloc = sdtp->sampleCount+1; + sdtp->sample_info = (u8*) gf_realloc(sdtp->sample_info, sizeof(u8) * sdtp->sample_alloc); + if (!sdtp->sample_info) return GF_OUT_OF_MEM; + } sdtp->sample_info[sdtp->sampleCount] = flags; sdtp->sampleCount ++; return GF_OK; @@ -667,7 +677,6 @@ GF_SampleToChunkBox *stsc; GF_ChunkLargeOffsetBox *co64; GF_StscEntry *ent; - Bool needs_split = GF_TRUE; u32 i, k, *newOff, new_chunk_idx=0; u64 *newLarge; s32 insert_idx = -1; @@ -679,9 +688,7 @@ if (!nb_pack_samples) nb_pack_samples = 1; - if (stsc->w_lastSampleNumber + 1 == sampleNumber ) needs_split = GF_TRUE; - - if (!stsc->nb_entries || (stsc->nb_entries + (needs_split ? 2 : 0) >= stsc->alloc_size)) { + if (!stsc->nb_entries || (stsc->nb_entries + 2 >= stsc->alloc_size)) { if (!stsc->alloc_size) stsc->alloc_size = 1; ALLOC_INC(stsc->alloc_size); stsc->entries = gf_realloc(stsc->entries, sizeof(GF_StscEntry)*stsc->alloc_size); @@ -1023,13 +1030,15 @@ //always called before removing the sample from SampleSize -GF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 LastAUDefDuration) +GF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples, u32 LastAUDefDuration) { u64 *DTSs, curDTS; u32 i, j, k, sampNum; GF_SttsEntry *ent; GF_TimeToSampleBox *stts; + if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM; + stts = stbl->TimeToSample; //we're removing the only sample: empty the sample table @@ -1040,11 +1049,12 @@ return GF_OK; } //we're removing the last sample - if (sampleNumber == stbl->SampleSize->sampleCount) { + if ((nb_samples==1) && (sampleNumber == stbl->SampleSize->sampleCount)) { ent = &stts->entries[stts->nb_entries-1]; ent->sampleCount--; if (!ent->sampleCount) stts->nb_entries--; } else { + u32 tot_samples, nb_written=0; //unpack the DTSs... DTSs = (u64*)gf_malloc(sizeof(u64) * (stbl->SampleSize->sampleCount - 1)); if (!DTSs) return GF_OUT_OF_MEM; @@ -1058,26 +1068,43 @@ for (i=0; i<stts->nb_entries; i++) { ent = & stts->entries[i]; for (j=0; j<ent->sampleCount; j++) { - if (sampNum == sampleNumber - 1) { - k=1; - } else { - DTSs[sampNum-k] = curDTS; + if (nb_samples==1) { + if (sampNum == sampleNumber - 1) { + k=1; + } else { + DTSs[sampNum-k] = curDTS; + } + } else if (sampNum >= nb_samples) { + DTSs[sampNum - nb_samples] = curDTS; + nb_written++; } curDTS += ent->sampleDelta; sampNum ++; } } + + if (nb_samples>1) { + assert(sampNum == stbl->SampleSize->sampleCount); + assert(nb_written + nb_samples == stbl->SampleSize->sampleCount); + } j=0; stts->nb_entries = 1; stts->entries[0].sampleCount = 1; if (stbl->SampleSize->sampleCount == 2) { stts->entries[0].sampleDelta = LastAUDefDuration; } else { - stts->entries[0].sampleDelta = (u32) DTSs[1] /*- DTS[0]==0 */; + stts->entries[0].sampleDelta = (u32) DTSs[1] /*- DTSs[0]*/; } sampNum = 1; - for (i=1; i<stbl->SampleSize->sampleCount-1; i++) { - if (i+1 == stbl->SampleSize->sampleCount-1) { + + if (nb_samples==1) { + tot_samples = stbl->SampleSize->sampleCount - 1; + } else { + tot_samples = stbl->SampleSize->sampleCount - nb_samples; + } + + for (i=1; i<tot_samples; i++) { + if (i+1 == tot_samples) { //and by default, our last sample has the same delta as the prev stts->entries[j].sampleCount++; sampNum ++; @@ -1097,14 +1124,14 @@ sampNum ++; } } - stts->w_LastDTS = DTSs[stbl->SampleSize->sampleCount - 2]; + stts->w_LastDTS = DTSs[tot_samples - 1]; gf_free(DTSs); - assert(sampNum == stbl->SampleSize->sampleCount - 1); - + assert(sampNum == tot_samples); + assert(sampNum + nb_samples == stbl->SampleSize->sampleCount); } //reset write the cache to the end - stts->w_currentSampleNum = stbl->SampleSize->sampleCount - 1; + stts->w_currentSampleNum = stbl->SampleSize->sampleCount - nb_samples; //reset read the cache to the beginning stts->r_FirstSampleInEntry = stts->r_currentEntryIndex = 0; stts->r_CurrentDTS = 0; @@ -1113,12 +1140,13 @@ //always called before removing the sample from SampleSize -GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber) +GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples) { GF_CompositionOffsetBox *ctts = stbl->CompositionOffset; if (!ctts) return GF_OK; assert(ctts->unpack_mode); + if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM; //last one... if (stbl->SampleSize->sampleCount == 1) { @@ -1132,16 +1160,25 @@ //first case, we're removing a sample that was not added yet if (sampleNumber > ctts->w_LastSampleNumber) return GF_OK; - memmove(&ctts->entries[sampleNumber-1], &ctts->entries[sampleNumber], sizeof(GF_DttsEntry)* (ctts->nb_entries-sampleNumber) ); - ctts->nb_entries--; + if (nb_samples==1) { + assert(ctts->nb_entries); + memmove(&ctts->entries[sampleNumber-1], &ctts->entries[sampleNumber], sizeof(GF_DttsEntry)* (ctts->nb_entries-sampleNumber) ); + ctts->nb_entries--; + } else { + memmove(&ctts->entries[0], &ctts->entries[nb_samples], sizeof(GF_DttsEntry)* (ctts->nb_entries-nb_samples) ); + ctts->nb_entries -= nb_samples; + } + ctts->w_LastSampleNumber -= nb_samples; + assert(ctts->w_LastSampleNumber >= ctts->nb_entries); - ctts->w_LastSampleNumber -= 1; return GF_OK; } -GF_Err stbl_RemoveSize(GF_SampleTableBox *stbl, u32 sampleNumber) +GF_Err stbl_RemoveSize(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples) { GF_SampleSizeBox *stsz = stbl->SampleSize; + + if ((nb_samples>1) && (sampleNumber>1)) return GF_BAD_PARAM; //last sample if (stsz->sampleCount == 1) { if (stsz->sizes) gf_free(stsz->sizes); @@ -1151,24 +1188,29 @@ } //one single size if (stsz->sampleSize) { - stsz->sampleCount -= 1; + stsz->sampleCount -= nb_samples; return GF_OK; } - if (sampleNumber < stsz->sampleCount) { - memmove(stsz->sizes + sampleNumber - 1, stsz->sizes + sampleNumber, sizeof(u32) * (stsz->sampleCount - sampleNumber)); + if (nb_samples==1) { + if (sampleNumber < stsz->sampleCount) + memmove(stsz->sizes + sampleNumber - 1, stsz->sizes + sampleNumber, sizeof(u32) * (stsz->sampleCount - sampleNumber)); + } else { + if (nb_samples < stsz->sampleCount) + memmove(stsz->sizes, stsz->sizes + nb_samples, sizeof(u32) * (stsz->sampleCount - nb_samples)); } - stsz->sampleCount--; + stsz->sampleCount -= nb_samples; return GF_OK; } //always called after removing the sample from SampleSize -GF_Err stbl_RemoveChunk(GF_SampleTableBox *stbl, u32 sampleNumber) +GF_Err stbl_RemoveChunk(GF_SampleTableBox *stbl, u32 sampleNumber, u32 nb_samples) { - u32 i, k; - u32 *offsets; - u64 *Loffsets; + u32 i; GF_SampleToChunkBox *stsc = stbl->SampleToChunk; + if ((nb_samples>1) && (sampleNumber>1)) + return GF_BAD_PARAM; + //raw audio or constant sample size and dur if (stsc->nb_entries < stbl->SampleSize->sampleCount) { if (sampleNumber==stbl->SampleSize->sampleCount+1) { @@ -1193,67 +1235,73 @@ GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] removing sample in middle of track not supported for constant size and duration samples\n")); return GF_NOT_SUPPORTED; } + //remove the entry in SampleToChunk (1 <-> 1 in edit mode) - memmove(&stsc->entries[sampleNumber-1], &stsc->entries[sampleNumber], sizeof(GF_StscEntry)*(stsc->nb_entries-sampleNumber)); - stsc->nb_entries--; + if (nb_samples==1) { + memmove(&stsc->entries[sampleNumber-1], &stsc->entries[sampleNumber], sizeof(GF_StscEntry)*(stsc->nb_entries-sampleNumber)); + stsc->nb_entries--; + + //update the firstchunk info + for (i=sampleNumber-1; i < stsc->nb_entries; i++) { + assert(stsc->entries[i].firstChunk >= 1); + stsc->entries[i].firstChunk -= 1; + if (stsc->entries[i].nextChunk) { + assert(stsc->entries[i].nextChunk >= 1); + stsc->entries[i].nextChunk -= 1; + } + } + } else { + memmove(&stsc->entries[0], &stsc->entries[nb_samples], sizeof(GF_StscEntry)*(stsc->nb_entries-nb_samples)); + stsc->nb_entries -= nb_samples; - //update the firstchunk info - for (i=sampleNumber-1; i < stsc->nb_entries; i++) { - stsc->entries[i].firstChunk -= 1; - stsc->entries[i].nextChunk -= 1; + //update the firstchunk info + for (i=0; i < stsc->nb_entries; i++) { + stsc->entries[i].firstChunk = i+1; + stsc->entries[i].nextChunk = (stsc->nb_entries==i+1) ? 0 : i+2; + } } + memset(&stsc->entries[stsc->nb_entries], 0, sizeof(GF_StscEntry)*(stsc->alloc_size - stsc->nb_entries) ); + //update the cache - stbl->SampleToChunk->firstSampleInCurrentChunk = 1; - stbl->SampleToChunk->currentIndex = 0; - stbl->SampleToChunk->currentChunk = 1; - stbl->SampleToChunk->ghostNumber = 1; + stsc->firstSampleInCurrentChunk = 1; + stsc->currentIndex = 0; + stsc->currentChunk = 1; + stsc->ghostNumber = 1; //realloc the chunk offset if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) { + GF_ChunkOffsetBox *stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset; if (!stbl->SampleSize->sampleCount) { - gf_free(((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets); - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets = NULL; - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->nb_entries = 0; - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->alloc_size = 0; + gf_free(stco->offsets); + stco->offsets = NULL; + stco->nb_entries = 0; + stco->alloc_size = 0; return GF_OK; } - offsets = (u32*)gf_malloc(sizeof(u32) * (stbl->SampleSize->sampleCount)); - if (!offsets) return GF_OUT_OF_MEM; - k=0; - for (i=0; i<stbl->SampleSize->sampleCount+1; i++) { - if (i+1 == sampleNumber) { - k=1; - } else { - offsets[i-k] = ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets[i]; - } + assert(stco->nb_entries - nb_samples == stbl->SampleSize->sampleCount); + if (nb_samples==1) { + memmove(&stco->offsets[sampleNumber-1], &stco->offsets[sampleNumber], sizeof(u32) * (stco->nb_entries - sampleNumber) ); + } else { + memmove(&stco->offsets[0], &stco->offsets[nb_samples], sizeof(u32) * (stco->nb_entries - nb_samples) ); } - gf_free(((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets); - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets = offsets; - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->alloc_size = stbl->SampleSize->sampleCount; - ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->nb_entries -= 1; + stco->nb_entries -= nb_samples; } else { + GF_ChunkLargeOffsetBox *co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset; if (!stbl->SampleSize->sampleCount) { - gf_free(((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets); - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets = NULL; - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->nb_entries = 0; - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->alloc_size = 0; + gf_free(co64->offsets); + co64->offsets = NULL; + co64->nb_entries = 0; + co64->alloc_size = 0; return GF_OK; } - Loffsets = (u64*)gf_malloc(sizeof(u64) * (stbl->SampleSize->sampleCount)); - if (!Loffsets) return GF_OUT_OF_MEM; - k=0; - for (i=0; i<stbl->SampleSize->sampleCount+1; i++) { - if (i+1 == sampleNumber) { - k=1; - } else { - Loffsets[i-k] = ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets[i]; - } + assert(co64->nb_entries - nb_samples == stbl->SampleSize->sampleCount); + if (nb_samples==1) { + memmove(&co64->offsets[sampleNumber-1], &co64->offsets[sampleNumber], sizeof(u64) * (co64->nb_entries - sampleNumber) ); + } else { + memmove(&co64->offsets[0], &co64->offsets[nb_samples], sizeof(u64) * (co64->nb_entries - nb_samples) ); } - gf_free(((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets); - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets = Loffsets; - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->alloc_size = stbl->SampleSize->sampleCount; - ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->nb_entries -= 1; + co64->nb_entries -= nb_samples; } return GF_OK; } @@ -1292,18 +1340,25 @@ return GF_OK; } -GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber) +GF_Err stbl_RemoveRedundant(GF_SampleTableBox *stbl, u32 SampleNumber, u32 nb_samples) { u32 i; if (!stbl->SampleDep) return GF_OK; if (stbl->SampleDep->sampleCount < SampleNumber) return GF_BAD_PARAM; - - i = stbl->SampleDep->sampleCount - SampleNumber; - if (i) memmove(&stbl->SampleDep->sample_info[SampleNumber-1], & stbl->SampleDep->sample_info[SampleNumber], sizeof(u8)*i); - stbl->SampleDep->sample_info = (u8*)gf_realloc(stbl->SampleDep->sample_info, sizeof(u8) * (stbl->SampleDep->sampleCount-1)); - if (!stbl->SampleDep->sample_info) return GF_OUT_OF_MEM; - stbl->SampleDep->sampleCount-=1; + if ((nb_samples>1) && (SampleNumber>1)) return GF_BAD_PARAM; + + if (nb_samples==1) { + i = stbl->SampleDep->sampleCount - SampleNumber; + if (i) memmove(&stbl->SampleDep->sample_info[SampleNumber-1], & stbl->SampleDep->sample_info[SampleNumber], sizeof(u8)*i); + stbl->SampleDep->sample_info = (u8*)gf_realloc(stbl->SampleDep->sample_info, sizeof(u8) * (stbl->SampleDep->sampleCount-1)); + if (!stbl->SampleDep->sample_info) return GF_OUT_OF_MEM; + stbl->SampleDep->sample_alloc = stbl->SampleDep->sampleCount-1; + stbl->SampleDep->sampleCount-=1; + } else { + memmove(&stbl->SampleDep->sample_info[0], &stbl->SampleDep->sample_info[nb_samples], sizeof(u8) * (stbl->SampleDep->sampleCount - nb_samples) ); + stbl->SampleDep->sampleCount -= nb_samples; + } return GF_OK; } @@ -1749,8 +1804,9 @@ if (!stbl->CompositionOffset) return GF_OUT_OF_MEM; } ctts = stbl->CompositionOffset; + ctts->w_LastSampleNumber ++; - if (ctts->nb_entries && (ctts->entries[ctts->nb_entries-1].decodingOffset == offset) ) { + if (!ctts->unpack_mode && ctts->nb_entries && (ctts->entries[ctts->nb_entries-1].decodingOffset == offset) ) { ctts->entries[ctts->nb_entries-1].sampleCount++; return GF_OK; } @@ -1793,6 +1849,7 @@ } stbl->SampleDep->sample_info = (u8*)gf_realloc(stbl->SampleDep->sample_info, sizeof(u8)*stbl->SampleSize->sampleCount ); if (!stbl->SampleDep->sample_info) return GF_OUT_OF_MEM; + stbl->SampleDep->sample_alloc = stbl->SampleSize->sampleCount; stbl->SampleDep->sample_info[stbl->SampleDep->sampleCount] = DepType; stbl->SampleDep->sampleCount = stbl->SampleSize->sampleCount; return GF_OK;
View file
gpac-1.0.0.tar.gz/src/isomedia/track.c -> gpac-1.0.1.tar.gz/src/isomedia/track.c
Changed
@@ -413,6 +413,7 @@ #ifndef GPAC_DISABLE_ISOM_FRAGMENTS +#ifdef GF_ENABLE_CTRN GF_TrunEntry *traf_get_sample_entry(GF_TrackFragmentBox *traf, u32 sample_index) { u32 i, idx; @@ -435,6 +436,8 @@ } return NULL; } +#endif + GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, GF_MovieFragmentBox *moof_box, u64 moof_offset, s32 compressed_diff, u64 *cumulated_offset, Bool is_first_merge) { @@ -607,10 +610,10 @@ for (j=0; j<trun->sample_count; j++) { GF_Err e; s32 cts_offset=0; - ent = (GF_TrunEntry*)gf_list_get(trun->entries, j); - - if (!ent) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Track %d doesn't have enough trun entries (%d) compared to sample count (%d) in run\n", traf->trex->trackID, gf_list_count(trun->entries), trun->sample_count )); + if (j<trun->nb_samples) { + ent = &trun->samples[j]; + } else { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Track %d doesn't have enough trun entries (%d) compared to sample count (%d) in run\n", traf->trex->trackID, trun->nb_samples, trun->sample_count )); break; } size = def_size; @@ -1255,7 +1258,7 @@ MediaType = GF_ISOM_MEDIA_SCENE; str = "GPAC DIMS Handler"; break; - case GF_ISOM_MEDIA_TMCD: + case GF_ISOM_MEDIA_TIMECODE: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_GMHD); str = "GPAC TMCD Handler"; break;
View file
gpac-1.0.0.tar.gz/src/isomedia/tx3g.c -> gpac-1.0.1.tar.gz/src/isomedia/tx3g.c
Changed
@@ -424,12 +424,7 @@ return e; } -#if 0 //unused -/*! formats sample as a regular GF_ISOSample. -The resulting sample will always be marked as random access -\param tx_samp the target text sample -\return the corresponding serialized ISO sample -*/ +GF_EXPORT GF_ISOSample *gf_isom_text_to_sample(const GF_TextSample *samp) { GF_Err e; @@ -455,7 +450,6 @@ res->IsRAP = RAP; return res; } -#endif //unused u32 gf_isom_text_sample_size(GF_TextSample *samp) {
View file
gpac-1.0.1.tar.gz/src/jsmods/core.c
Added
@@ -0,0 +1,1919 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2020 + * All rights reserved + * + * This file is part of GPAC / JavaScript libgpac Core bindings + * + * 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. + * + */ + +/* + ANY CHANGE TO THE API MUST BE REFLECTED IN THE DOCUMENTATION IN gpac/share/doc/idl/storage.js + (no way to define inline JS doc with doxygen) +*/ + +#include <gpac/setup.h> + +#ifdef GPAC_HAS_QJS +#include <gpac/bitstream.h> +#include <gpac/network.h> +#include <gpac/base_coding.h> + +#include "../scenegraph/qjs_common.h" + +#define JS_CGETSET_MAGIC_DEF_ENUM(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE|JS_PROP_ENUMERABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } + + +static JSClassID bitstream_class_id = 0; +static JSClassID sha1_class_id = 0; +static JSClassID file_class_id = 0; + +typedef struct +{ + GF_BitStream *bs; + JSValue buf_ref; +} JSBitstream; + +#define GET_JSBS \ + JSBitstream *jbs = JS_GetOpaque(this_val, bitstream_class_id); \ + GF_BitStream *bs = jbs ? jbs->bs : NULL; + + +static void js_gpac_free(JSRuntime *rt, void *opaque, void *ptr) +{ + gf_free(ptr); +} + +static void js_bs_finalize(JSRuntime *rt, JSValue this_val) +{ + GET_JSBS + if (!bs) return; + gf_bs_del(bs); + JS_FreeValueRT(rt, jbs->buf_ref); + gf_free(jbs); +} +static void js_bs_gc_mark(JSRuntime *rt, JSValueConst this_val, JS_MarkFunc *mark_func) +{ + GET_JSBS + if (!bs) return; + JS_MarkValue(rt, jbs->buf_ref, mark_func); +} + +JSClassDef bitstreamClass = { + "Bitstream", + .finalizer = js_bs_finalize, + .gc_mark = js_bs_gc_mark +}; + + +static JSValue js_bs_get_u8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u8(bs) ); +} +static JSValue js_bs_get_s8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s8 v; + GET_JSBS + if (!bs) return JS_EXCEPTION; + v = (s8) gf_bs_read_u8(bs); + return JS_NewInt32(ctx, v ); +} +static JSValue js_bs_get_u16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u16(bs) ); +} +static JSValue js_bs_get_u16_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u16_le(bs) ); +} +static JSValue js_bs_get_s16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s16 v; + GET_JSBS + if (!bs) return JS_EXCEPTION; + v = (s16) gf_bs_read_u16(bs); + return JS_NewInt32(ctx, v ); +} +static JSValue js_bs_get_u24(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u24(bs) ); +} +static JSValue js_bs_get_s32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s32 v; + GET_JSBS + if (!bs) return JS_EXCEPTION; + v = (s32) gf_bs_read_u32(bs); + return JS_NewInt32(ctx, v); +} +static JSValue js_bs_get_u32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u32(bs) ); +} +static JSValue js_bs_get_u32_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_bs_read_u32_le(bs) ); +} +static JSValue js_bs_get_u64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt64(ctx, gf_bs_read_u64(bs) ); +} +static JSValue js_bs_get_u64_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewInt64(ctx, gf_bs_read_u64_le(bs) ); +} +static JSValue js_bs_get_s64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 v; + GET_JSBS + if (!bs) return JS_EXCEPTION; + v = (s64) gf_bs_read_u64(bs); + return JS_NewInt64(ctx, v ); +} +static JSValue js_bs_get_float(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewFloat64(ctx, gf_bs_read_float(bs) ); +} +static JSValue js_bs_get_double(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + return JS_NewFloat64(ctx, gf_bs_read_double(bs) ); +} +static JSValue js_bs_get_bits(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s32 nb_bits; + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &nb_bits, argv[0])) return JS_EXCEPTION; + if (nb_bits<=32) + return JS_NewInt32(ctx, gf_bs_read_int(bs, nb_bits) ); + return JS_NewInt64(ctx, gf_bs_read_long_int(bs, nb_bits) ); +} + +static JSValue js_bs_data_io(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 mode) +{ + s32 nb_bytes=0; + s64 offset=0; + size_t data_size; + u8 *data=NULL; + GET_JSBS + if (!bs) return JS_EXCEPTION; + if (argc<1) return JS_EXCEPTION; + + if (JS_IsObject(argv[0])) { + data = JS_GetArrayBuffer(ctx, &data_size, argv[0]); + if (argc>1) { + if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION; + if ((mode==2) && (argc>2)) { + if (JS_ToInt64(ctx, &offset, argv[2])) return JS_EXCEPTION; + + } + } + } + if (!data) return JS_EXCEPTION; + + if (nb_bytes> (s32) data_size) nb_bytes = (s32) data_size; + else if (!nb_bytes) nb_bytes = (s32) data_size; + + if (mode==1) { + data_size = gf_bs_write_data(bs, data, nb_bytes); + } else if (mode==2) { + GF_Err e = gf_bs_insert_data(bs, data, nb_bytes, offset); + if (e) js_throw_err(ctx, e); + return JS_UNDEFINED; + } else { + data_size = gf_bs_read_data(bs, data, nb_bytes); + } + return JS_NewInt32(ctx, (s32) data_size); +} + +static JSValue js_bs_get_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_data_io(ctx, this_val, argc, argv, 0); +} +static JSValue js_bs_skip_bytes(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s32 nb_bytes; + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &nb_bytes, argv[0])) return JS_EXCEPTION; + gf_bs_skip_bytes(bs, nb_bytes); + return JS_UNDEFINED; +} +static JSValue js_bs_is_align(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + if (gf_bs_is_align(bs)) return JS_TRUE; + return JS_FALSE; +} +static JSValue js_bs_align(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + gf_bs_align(bs); + return JS_UNDEFINED; +} +static JSValue js_bs_truncate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + gf_bs_truncate(bs); + return JS_UNDEFINED; +} +static JSValue js_bs_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + gf_bs_flush(bs); + return JS_UNDEFINED; +} +static JSValue js_bs_epb_mode(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + gf_bs_enable_emulation_byte_removal(bs, (JS_ToBool(ctx, argv[0])) ? GF_TRUE : GF_FALSE); + return JS_UNDEFINED; +} + +static JSValue js_bs_peek(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u64 byte_offset=0; + s32 nb_bits; + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &nb_bits, argv[0])) return JS_EXCEPTION; + if (argc>1) { + if (JS_ToInt64(ctx, &byte_offset, argv[1])) return JS_EXCEPTION; + } + return JS_NewInt32(ctx, gf_bs_peek_bits(bs, nb_bits, byte_offset)); +} + +static JSValue js_bs_put_val(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 mode) +{ + s64 val; + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + switch (mode) { + case 0: gf_bs_write_u8(bs, (u32) val); break; + case 1: gf_bs_write_u8(bs, (u32) val); break; + case 2: gf_bs_write_u16(bs, (u32) val); break; + case 3: gf_bs_write_u16_le(bs, (u32) val); break; + case 4: gf_bs_write_u16(bs, (u32) val); break; + case 5: gf_bs_write_u24(bs, (u32) val); break; + case 6: gf_bs_write_u32(bs, (u32) val); break; + case 7: gf_bs_write_u32_le(bs, (u32) val); break; + case 8: gf_bs_write_u32(bs, (u32) val); break; + case 9: gf_bs_write_u64(bs, (u64) val); break; + case 10: gf_bs_write_u64_le(bs, (u64) val); break; + case 11: gf_bs_write_u64(bs, (u64) val); break; + } + return JS_UNDEFINED; +} +static JSValue js_bs_put_u8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 0); +} +static JSValue js_bs_put_s8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 1); +} +static JSValue js_bs_put_u16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 2); +} +static JSValue js_bs_put_u16_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 3); +} +static JSValue js_bs_put_s16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 4); +} +static JSValue js_bs_put_u24(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 5); +} +static JSValue js_bs_put_u32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 6); +} +static JSValue js_bs_put_u32_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 7); +} +static JSValue js_bs_put_s32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 8); +} +static JSValue js_bs_put_u64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 9); +} +static JSValue js_bs_put_u64_le(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 10); +} +static JSValue js_bs_put_s64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_put_val(ctx, this_val, argc, argv, 11); +} +static JSValue js_bs_put_bits(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 val; + s32 nb_bits; + GET_JSBS + if (!bs || (argc!=2)) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &nb_bits, argv[1])) return JS_EXCEPTION; + if (nb_bits<=32) + gf_bs_write_int(bs, (u32) val, nb_bits); + else + gf_bs_write_long_int(bs, val, nb_bits); + return JS_UNDEFINED; +} +static JSValue js_bs_put_float(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Double val; + GET_JSBS + if (!bs || (argc!=1)) return JS_EXCEPTION; + if (JS_ToFloat64(ctx, &val, argv[0])) return JS_EXCEPTION; + gf_bs_write_float(bs, (Float) val); + return JS_UNDEFINED; +} +static JSValue js_bs_put_double(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Double val; + GET_JSBS + if (!bs || (argc!=1)) return JS_EXCEPTION; + if (JS_ToFloat64(ctx, &val, argv[0])) return JS_EXCEPTION; + gf_bs_write_double(bs, val); + return JS_UNDEFINED; +} +static JSValue js_bs_put_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_data_io(ctx, this_val, argc, argv, 1); +} +static JSValue js_bs_insert_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_bs_data_io(ctx, this_val, argc, argv, 2); +} + +static JSValue js_bs_get_content(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u8 *data; + u32 size; + JSValue res; + GET_JSBS + if (!bs) return JS_EXCEPTION; + gf_bs_get_content(bs, &data, &size); + + if (data) { + res = JS_NewArrayBuffer(ctx, data, size, js_gpac_free, NULL, 0); + } else { + res = JS_NULL; + } + return res; +} + +static JSValue js_bs_transfer(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool keep_src=GF_FALSE; + GF_Err e; + JSBitstream *jssrcbs; + GET_JSBS + if (!bs || !argc) return JS_EXCEPTION; + + jssrcbs = JS_GetOpaque(argv[0], bitstream_class_id); + if (!jssrcbs || !jssrcbs->bs) return JS_EXCEPTION; + if (argc>1) { + keep_src = JS_ToBool(ctx, argv[1]); + } + e = gf_bs_transfer(bs, jssrcbs->bs, keep_src); + if (e) return js_throw_err(ctx, e); + return JS_UNDEFINED; +} + +enum +{ + JS_BS_POS=0, + JS_BS_SIZE, + JS_BS_BIT_OFFSET, + JS_BS_BIT_POS, + JS_BS_AVAILABLE, + JS_BS_BITS_AVAILABLE, + JS_BS_REFRESH_SIZE, +}; + +static JSValue js_bs_prop_get(JSContext *ctx, JSValueConst this_val, int magic) +{ + GET_JSBS + if (!bs) return JS_EXCEPTION; + switch (magic) { + case JS_BS_POS: + return JS_NewInt64(ctx, gf_bs_get_position(bs)); + case JS_BS_SIZE: + return JS_NewInt64(ctx, gf_bs_get_size(bs)); + case JS_BS_REFRESH_SIZE: + return JS_NewInt64(ctx, gf_bs_get_refreshed_size(bs)); + case JS_BS_BIT_OFFSET: + return JS_NewInt64(ctx, gf_bs_get_bit_offset(bs)); + case JS_BS_BIT_POS: + return JS_NewInt64(ctx, gf_bs_get_bit_position(bs)); + case JS_BS_AVAILABLE: + return JS_NewInt64(ctx, gf_bs_available(bs)); + case JS_BS_BITS_AVAILABLE: + return JS_NewInt32(ctx, gf_bs_bits_available(bs)); + } + return JS_UNDEFINED; + +} +static JSValue js_bs_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +{ + s64 ival; + GET_JSBS + if (!bs) return JS_EXCEPTION; + + switch (magic) { + case JS_BS_POS: + if (JS_ToInt64(ctx, &ival, value)) return JS_EXCEPTION; + gf_bs_seek(bs, ival); + break; + } + return JS_UNDEFINED; +} + +static const JSCFunctionListEntry bitstream_funcs[] = { + JS_CGETSET_MAGIC_DEF_ENUM("pos", js_bs_prop_get, js_bs_prop_set, JS_BS_POS), + JS_CGETSET_MAGIC_DEF_ENUM("size", js_bs_prop_get, NULL, JS_BS_SIZE), + JS_CGETSET_MAGIC_DEF_ENUM("bit_offset", js_bs_prop_get, NULL, JS_BS_BIT_OFFSET), + JS_CGETSET_MAGIC_DEF_ENUM("bit_pos", js_bs_prop_get, NULL, JS_BS_BIT_POS), + JS_CGETSET_MAGIC_DEF_ENUM("available", js_bs_prop_get, NULL, JS_BS_AVAILABLE), + JS_CGETSET_MAGIC_DEF_ENUM("bits_available", js_bs_prop_get, NULL, JS_BS_BITS_AVAILABLE), + JS_CGETSET_MAGIC_DEF_ENUM("refreshed_size", js_bs_prop_get, NULL, JS_BS_REFRESH_SIZE), + + JS_CFUNC_DEF("skip", 0, js_bs_skip_bytes), + JS_CFUNC_DEF("is_align", 0, js_bs_is_align), + JS_CFUNC_DEF("align", 0, js_bs_align), + JS_CFUNC_DEF("truncate", 0, js_bs_truncate), + JS_CFUNC_DEF("peek", 0, js_bs_peek), + JS_CFUNC_DEF("flush", 0, js_bs_flush), + JS_CFUNC_DEF("epb_mode", 0, js_bs_epb_mode), + + JS_CFUNC_DEF("get_u8", 0, js_bs_get_u8), + JS_CFUNC_DEF("get_s8", 0, js_bs_get_s8), + JS_CFUNC_DEF("get_u16", 0, js_bs_get_u16), + JS_CFUNC_DEF("get_u16_le", 0, js_bs_get_u16_le), + JS_CFUNC_DEF("get_s16", 0, js_bs_get_s16), + JS_CFUNC_DEF("get_u24", 0, js_bs_get_u24), + JS_CFUNC_DEF("get_u32", 0, js_bs_get_u32), + JS_CFUNC_DEF("get_u32_le", 0, js_bs_get_u32_le), + JS_CFUNC_DEF("get_s32", 0, js_bs_get_s32), + JS_CFUNC_DEF("get_u64", 0, js_bs_get_u64), + JS_CFUNC_DEF("get_u64_le", 0, js_bs_get_u64_le), + JS_CFUNC_DEF("get_s64", 0, js_bs_get_s64), + JS_CFUNC_DEF("get_bits", 0, js_bs_get_bits), + JS_CFUNC_DEF("get_float", 0, js_bs_get_float), + JS_CFUNC_DEF("get_double", 0, js_bs_get_double), + JS_CFUNC_DEF("get_data", 0, js_bs_get_data), + JS_CFUNC_DEF("put_u8", 0, js_bs_put_u8), + JS_CFUNC_DEF("put_s8", 0, js_bs_put_s8), + JS_CFUNC_DEF("put_u16", 0, js_bs_put_u16), + JS_CFUNC_DEF("put_u16_le", 0, js_bs_put_u16_le), + JS_CFUNC_DEF("put_s16", 0, js_bs_put_s16), + JS_CFUNC_DEF("put_u24", 0, js_bs_put_u24), + JS_CFUNC_DEF("put_u32", 0, js_bs_put_u32), + JS_CFUNC_DEF("put_u32_le", 0, js_bs_put_u32_le), + JS_CFUNC_DEF("put_s32", 0, js_bs_put_s32), + JS_CFUNC_DEF("put_u64", 0, js_bs_put_u64), + JS_CFUNC_DEF("put_u64_le", 0, js_bs_put_u64_le), + JS_CFUNC_DEF("put_s64", 0, js_bs_put_s64), + JS_CFUNC_DEF("put_bits", 0, js_bs_put_bits), + JS_CFUNC_DEF("put_float", 0, js_bs_put_float), + JS_CFUNC_DEF("put_double", 0, js_bs_put_double), + JS_CFUNC_DEF("put_data", 0, js_bs_put_data), + JS_CFUNC_DEF("insert_data", 0, js_bs_insert_data), + JS_CFUNC_DEF("get_content", 0, js_bs_get_content), + JS_CFUNC_DEF("transfer", 0, js_bs_transfer), +}; + +static JSValue bitstream_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) +{ + JSValue anobj; + JSBitstream *jbs; + GF_BitStream *bs = NULL; + + if (!argc) { + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + } else if (JS_IsObject(argv[0])){ + FILE *f = JS_GetOpaque(argv[0], file_class_id); + if (f) { + if ((argc>1) && JS_ToBool(ctx, argv[1])) { + bs = gf_bs_from_file(f, GF_BITSTREAM_WRITE); + } else { + bs = gf_bs_from_file(f, GF_BITSTREAM_READ); + } + } else { + u8 *data; + size_t data_size; + + data = JS_GetArrayBuffer(ctx, &data_size, argv[0]); + if (!data) return JS_EXCEPTION; + if ((argc>1) && JS_ToBool(ctx, argv[1])) { + bs = gf_bs_new(data, data_size, GF_BITSTREAM_WRITE); + } else { + bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ); + } + } + } else { + return JS_EXCEPTION; + } + GF_SAFEALLOC(jbs, JSBitstream); + if (!jbs) { + gf_bs_del(bs); + return js_throw_err(ctx, GF_OUT_OF_MEM); + } + anobj = JS_NewObjectClass(ctx, bitstream_class_id); + if (JS_IsException(anobj)) { + gf_bs_del(bs); + gf_free(jbs); + return anobj; + } + jbs->bs = bs; + jbs->buf_ref = JS_UNDEFINED; + if (argc) + jbs->buf_ref = JS_DupValue(ctx, argv[0]); + + JS_SetOpaque(anobj, jbs); + return anobj; +} + +enum +{ + JS_SYS_NB_CORES = 1, + JS_SYS_SAMPLE_DUR, + JS_SYS_TOTAL_CPU, + JS_SYS_PROCESS_CPU, + JS_SYS_TOTAL_CPU_DIFF, + JS_SYS_PROCESS_CPU_DIFF, + JS_SYS_CPU_IDLE, + JS_SYS_TOTAL_CPU_USAGE, + JS_SYS_PROCESS_CPU_USAGE, + JS_SYS_PID, + JS_SYS_THREADS, + JS_SYS_PROCESS_MEM, + JS_SYS_TOTAL_MEM, + JS_SYS_TOTAL_MEM_AVAIL, + JS_SYS_GPAC_MEM, + + JS_SYS_BATTERY_ON, + JS_SYS_BATTERY_CHARGE, + JS_SYS_BATTERY_PERCENT, + JS_SYS_BATTERY_LIFETIME, + JS_SYS_BATTERY_LIFETIME_FULL, + JS_SYS_HOSTNAME, + JS_SYS_LAST_WORK_DIR, + JS_SYS_TEST_MODE, + JS_SYS_OLD_ARCH, + JS_SYS_LOG_COLOR, + JS_SYS_QUIET, + JS_SYS_USERNAME, + JS_SYS_TIMEZONE, + JS_SYS_FILES_OPEN, + JS_SYS_CACHE_DIR, + JS_SYS_SHARED_DIR, + JS_SYS_VERSION, + JS_SYS_VERSION_FULL, + JS_SYS_COPYRIGHT, + JS_SYS_V_MAJOR, + JS_SYS_V_MINOR, + JS_SYS_V_MICRO, +}; + +#define RTI_REFRESH_MS 200 +static JSValue js_sys_prop_get(JSContext *ctx, JSValueConst this_val, int magic) +{ + u32 uval; + Bool bval; + const char *res; + GF_SystemRTInfo rti; + + if (magic<=JS_SYS_GPAC_MEM) { + gf_sys_get_rti(RTI_REFRESH_MS, &rti, 0); + switch (magic) { + case JS_SYS_NB_CORES: + return JS_NewInt32(ctx, rti.nb_cores); + case JS_SYS_SAMPLE_DUR: + return JS_NewInt32(ctx, rti.sampling_period_duration); + case JS_SYS_TOTAL_CPU: + return JS_NewInt32(ctx, rti.total_cpu_time); + case JS_SYS_PROCESS_CPU: + return JS_NewInt32(ctx, rti.process_cpu_time); + case JS_SYS_TOTAL_CPU_DIFF: + return JS_NewInt32(ctx, rti.total_cpu_time_diff); + case JS_SYS_PROCESS_CPU_DIFF: + return JS_NewInt32(ctx, rti.process_cpu_time_diff); + case JS_SYS_CPU_IDLE: + return JS_NewInt32(ctx, rti.cpu_idle_time); + case JS_SYS_TOTAL_CPU_USAGE: + return JS_NewInt32(ctx, rti.total_cpu_time); + case JS_SYS_PROCESS_CPU_USAGE: + return JS_NewInt32(ctx, rti.process_cpu_usage); + case JS_SYS_PID: + return JS_NewInt32(ctx, rti.pid); + case JS_SYS_THREADS: + return JS_NewInt32(ctx, rti.thread_count); + case JS_SYS_PROCESS_MEM: + return JS_NewInt64(ctx, rti.process_memory); + case JS_SYS_TOTAL_MEM: + return JS_NewInt64(ctx, rti.physical_memory); + case JS_SYS_TOTAL_MEM_AVAIL: + return JS_NewInt64(ctx, rti.physical_memory_avail); + case JS_SYS_GPAC_MEM: + return JS_NewInt64(ctx, rti.gpac_memory); + } + return JS_UNDEFINED; + } + + switch (magic) { + case JS_SYS_BATTERY_ON: + bval = GF_FALSE; + gf_sys_get_battery_state(&bval, NULL, NULL, NULL, NULL); + return JS_NewBool(ctx, bval); + + case JS_SYS_BATTERY_CHARGE: + uval = 0; + gf_sys_get_battery_state(NULL, &uval, NULL, NULL, NULL); + return JS_NewBool(ctx, uval ? 1 : 0); + + case JS_SYS_BATTERY_PERCENT: + uval=0; + gf_sys_get_battery_state(NULL, NULL, &uval, NULL, NULL); + return JS_NewInt32(ctx, uval); + + case JS_SYS_BATTERY_LIFETIME: + uval=0; + gf_sys_get_battery_state(NULL, NULL, NULL, &uval, NULL); + return JS_NewInt32(ctx, uval); + + case JS_SYS_BATTERY_LIFETIME_FULL: + uval=0; + gf_sys_get_battery_state(NULL, NULL, NULL, NULL, &uval); + return JS_NewInt32(ctx, uval); + + case JS_SYS_HOSTNAME: + { + char hostname[100]; + gf_sk_get_host_name((char*)hostname); + return JS_NewString(ctx, hostname); + } + break; + case JS_SYS_LAST_WORK_DIR: + res = gf_opts_get_key("General", "LastWorkingDir"); +#ifdef WIN32 + if (!res) res = getenv("HOMEPATH"); + if (!res) res = "C:\\"; +#elif defined(GPAC_CONFIG_DARWIN) + if (!res) res = getenv("HOME"); + if (!res) res = "/Users"; +#elif defined(GPAC_CONFIG_ANDROID) + if (!res) res = getenv("EXTERNAL_STORAGE"); + if (!res) res = "/sdcard"; +#elif defined(GPAC_CONFIG_IOS) + if (!res) res = (char *) gf_opts_get_key("General", "iOSDocumentsDir"); +#else + if (!res) res = getenv("HOME"); + if (!res) res = "/home/"; +#endif + return JS_NewString(ctx, res); + + case JS_SYS_TEST_MODE: + return JS_NewBool(ctx, gf_sys_is_test_mode() ); + case JS_SYS_OLD_ARCH: + return JS_NewBool(ctx, gf_sys_old_arch_compat() ); + case JS_SYS_LOG_COLOR: + return JS_NewBool(ctx, gf_log_use_color() ); + case JS_SYS_QUIET: + return JS_NewBool(ctx, gf_sys_is_quiet() ); + case JS_SYS_USERNAME: + { + char username[1024]; + gf_get_user_name((char*)username); + return JS_NewString(ctx, username); + } + case JS_SYS_TIMEZONE: + return JS_NewInt32(ctx, gf_net_get_timezone()); + + case JS_SYS_FILES_OPEN: + return JS_NewInt32(ctx, gf_file_handles_count()); + + case JS_SYS_CACHE_DIR: + res = gf_get_default_cache_directory(); + if (res) return JS_NewString(ctx, res); + return JS_NULL; + + case JS_SYS_SHARED_DIR: + { + char szDir[GF_MAX_PATH]; + if (! gf_opts_default_shared_directory(szDir)) return JS_NULL; + return JS_NewString(ctx, szDir); + } + + case JS_SYS_VERSION: + return JS_NewString(ctx, GPAC_VERSION ); + case JS_SYS_VERSION_FULL: + return JS_NewString(ctx, gf_gpac_version() ); + case JS_SYS_COPYRIGHT: + return JS_NewString(ctx, gf_gpac_copyright() ); + + case JS_SYS_V_MAJOR: + return JS_NewInt32(ctx, GPAC_VERSION_MAJOR ); + case JS_SYS_V_MINOR: + return JS_NewInt32(ctx, GPAC_VERSION_MINOR ); + case JS_SYS_V_MICRO: + return JS_NewInt32(ctx, GPAC_VERSION_MICRO ); + } + + return JS_UNDEFINED; +} + +static JSValue js_sys_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +{ + const char *prop_val; + switch (magic) { + case JS_SYS_LAST_WORK_DIR: + if (!JS_IsString(value)) return JS_EXCEPTION; + prop_val = JS_ToCString(ctx, value); + gf_opts_set_key("General", "LastWorkingDir", prop_val); + JS_FreeCString(ctx, prop_val); + break; + } + return JS_UNDEFINED; +} + +static JSValue js_sys_set_arg_used(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 idx; + Bool used; + if (argc < 2) return JS_EXCEPTION; + + if (JS_ToInt32(ctx, &idx, argv[0])) + return JS_EXCEPTION; + used = JS_ToBool(ctx, argv[1]); + + gf_sys_mark_arg_used(idx, used); + return JS_UNDEFINED; +} + + +typedef struct +{ + JSContext *c; + JSValue array; + Bool is_dir; + u32 idx; +} enum_dir_cbk; + +static Bool js_enum_dir_fct(void *cbck, char *file_name, char *file_path, GF_FileEnumInfo *file_info) +{ + u32 i, len; + char *sep; + JSValue s; + JSValue obj; + enum_dir_cbk *cbk = (enum_dir_cbk*)cbck; + + if (file_name && (file_name[0]=='.')) return 0; + + obj = JS_NewObject(cbk->c); + JS_SetPropertyStr(cbk->c, obj, "name", JS_NewString(cbk->c, file_name) ); + + sep=NULL; + len = (u32) strlen(file_path); + for (i=0; i<len; i++) { + sep = strchr("/\\", file_path[len-i-1]); + if (sep) { + sep = file_path+len-i-1; + break; + } + } + if (sep) { + sep[0] = '/'; + sep[1] = 0; + s = JS_NewString(cbk->c, file_path); + } else { + s = JS_NewString(cbk->c, file_path); + } + JS_SetPropertyStr(cbk->c, obj, "path", s); + + JS_SetPropertyStr(cbk->c, obj, "directory", JS_NewBool(cbk->c, cbk->is_dir) ); + JS_SetPropertyStr(cbk->c, obj, "drive", JS_NewBool(cbk->c, file_info->drive) ); + JS_SetPropertyStr(cbk->c, obj, "hidden", JS_NewBool(cbk->c, file_info->hidden) ); + JS_SetPropertyStr(cbk->c, obj, "system", JS_NewBool(cbk->c, file_info->system) ); + JS_SetPropertyStr(cbk->c, obj, "size", JS_NewInt64(cbk->c, file_info->size) ); + JS_SetPropertyStr(cbk->c, obj, "last_modified", JS_NewInt64(cbk->c, file_info->last_modified) ); + + JS_SetPropertyUint32(cbk->c, cbk->array, cbk->idx, obj); + cbk->idx++; + return 0; +} + +static JSValue js_sys_enum_directory(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GF_Err err; + enum_dir_cbk cbk; + char *url = NULL; + const char *dir = NULL; + const char *filter = NULL; + Bool dir_only = 0; + Bool browse_root = 0; + + if ((argc >= 1) && JS_IsString(argv[0])) { + dir = JS_ToCString(ctx, argv[0]); + if (!strcmp(dir, "/")) browse_root = 1; + } + if ((argc >= 2) && JS_IsString(argv[1])) { + filter = JS_ToCString(ctx, argv[1]); + if (!strcmp(filter, "dir")) { + dir_only = 1; + filter = NULL; + } else if (!strlen(filter)) { + JS_FreeCString(ctx, filter); + filter=NULL; + } + } + if ((argc >= 3) && JS_IsBool(argv[2])) { + if (JS_ToBool(ctx, argv[2])) { + url = gf_url_concatenate(dir, ".."); + if (dir && ( !strcmp(url, "..") || (url[0]==0) )) { + if ((dir[1]==':') && ((dir[2]=='/') || (dir[2]=='\\')) ) browse_root = 1; + else if (!strcmp(dir, "/")) browse_root = 1; + } + if (!strcmp(url, "/")) browse_root = 1; + } + } + + if ( (!dir || !strlen(dir) ) && (!url || !strlen(url))) browse_root = 1; + + if (browse_root) { + cbk.c = ctx; + cbk.idx = 0; + cbk.array = JS_NewArray(ctx); + if (JS_IsException(cbk.array)) return cbk.array; + cbk.is_dir = 1; + gf_enum_directory("/", 1, js_enum_dir_fct, &cbk, NULL); + if (url) gf_free(url); + JS_FreeCString(ctx, dir); + JS_FreeCString(ctx, filter); + return cbk.array; + } + + cbk.c = ctx; + cbk.array = JS_NewArray(ctx); + if (JS_IsException(cbk.array)) return cbk.array; + cbk.is_dir = 1; + cbk.idx = 0; + +#if 0 + compositor = scenejs_get_compositor(ctx, this_val); + + /*concatenate with service url*/ + char *an_url = gf_url_concatenate(compositor->root_scene->root_od->scene_ns->url, url ? url : dir); + if (an_url) { + gf_free(url); + url = an_url; + } +#endif + + err = gf_enum_directory(url ? url : dir, 1, js_enum_dir_fct, &cbk, NULL); + if (err) return JS_EXCEPTION; + + if (!dir_only) { + cbk.is_dir = 0; + err = gf_enum_directory(url ? url : dir, 0, js_enum_dir_fct, &cbk, filter); + if (err) return JS_EXCEPTION; + } + + if (url) gf_free(url); + JS_FreeCString(ctx, dir); + JS_FreeCString(ctx, filter); + return cbk.array; +} + + +static JSValue js_sys_error_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + GF_Err e; + if (argc < 1) return JS_EXCEPTION; + if (JS_ToInt32(ctx, (int32_t *) &e, argv[0])) + return JS_EXCEPTION; + return JS_NewString(ctx, gf_error_to_string(e) ); +} + +static JSValue js_sys_prompt_input(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + char in_char[2]; + + if (!gf_prompt_has_input()) + return JS_NULL; + in_char[0] = gf_prompt_get_char(); + in_char[1] = 0; + return JS_NewString(ctx, in_char); +} + +static JSValue js_sys_prompt_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + char input[4096], *read; + u32 len; +//#ifdef GPAC_ENABLE_COVERAGE + if (argc) { + return JS_NewString(ctx, "Coverage OK"); + } +//#endif // GPAC_ENABLE_COVERAGE + + read = fgets(input, 4095, stdin); + if (!read) return JS_NULL; + input[4095]=0; + len = (u32) strlen(input); + if (len && (input[len-1] == '\n')) { + input[len-1] = 0; + len--; + } + if (!len) return JS_NULL; + return JS_NewString(ctx, input); +} + +static JSValue js_sys_prompt_echo_off(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool echo_off; + if (!argc) return JS_EXCEPTION; + echo_off = JS_ToBool(ctx, argv[0]); + if (argc<2) + gf_prompt_set_echo_off(echo_off); + return JS_UNDEFINED; +} +static JSValue js_sys_prompt_code(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s32 code; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &code, argv[0])) return JS_EXCEPTION; + + gf_sys_set_console_code(stderr, code); + return JS_UNDEFINED; +} +static JSValue js_sys_prompt_size(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 w, h; + JSValue res; + GF_Err e = gf_prompt_get_size(&w, &h); + if (e) return JS_NULL; + res = JS_NewObject(ctx); + JS_SetPropertyStr(ctx, res, "w", JS_NewInt32(ctx, w)); + JS_SetPropertyStr(ctx, res, "h", JS_NewInt32(ctx, h)); + return res; +} + + +static JSValue js_sys_gc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + JS_RunGC(JS_GetRuntime(ctx)); + return JS_UNDEFINED; +} + +static JSValue js_sys_clock(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return JS_NewInt32(ctx, gf_sys_clock() ); +} +static JSValue js_sys_clock_high_res(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return JS_NewInt64(ctx, gf_sys_clock_high_res() ); +} +static JSValue js_sys_4cc_to_str(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u64 val; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + return JS_NewString(ctx, gf_4cc_to_str((u32) val) ); +} + +static JSValue js_sys_rand_init(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool reset=GF_FALSE; + if (argc) reset = JS_ToBool(ctx, argv[0]); + gf_rand_init(reset); + return JS_UNDEFINED; +} +static JSValue js_sys_rand(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return JS_NewInt32(ctx, gf_rand()); +} +static JSValue js_sys_rand64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u64 lrand = (u64) gf_rand(); + lrand<<=32; + lrand |= gf_rand(); + return JS_NewInt64(ctx, lrand); +} + +static JSValue js_sys_getenv(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *str, *val; + if (!argc) return JS_EXCEPTION; + str = JS_ToCString(ctx, argv[0]); + if (!str) return JS_EXCEPTION; + val = getenv(str); + JS_FreeCString(ctx, str); + return val ? JS_NewString(ctx, val) : JS_NULL; +} + +static JSValue js_sys_get_utc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u32 y, mo, d, h, m, s; + if (!argc) return JS_NewInt64(ctx, gf_net_get_utc() ); + if (argc==1) { + u64 time; + const char *date = JS_ToCString(ctx, argv[0]); + if (!date) return JS_EXCEPTION; + time = gf_net_parse_date(date); + JS_FreeCString(ctx, date); + return JS_NewInt64(ctx, time); + } + + if (argc != 6) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &y, argv[0])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &mo, argv[1])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &d, argv[2])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &h, argv[3])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &m, argv[4])) return JS_EXCEPTION; + if (JS_ToInt32(ctx, &s, argv[5])) return JS_EXCEPTION; + + return JS_NewInt64(ctx, gf_net_get_utc_ts(y, mo, d, h, m, s) ); +} + + +static JSValue js_sys_crc32(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const u8 *data; + size_t data_size; + + if (!argc || !JS_IsObject(argv[0])) return JS_EXCEPTION; + data = JS_GetArrayBuffer(ctx, &data_size, argv[0] ); + if (!data) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_crc_32(data, (u32) data_size) ); +} + +static JSValue js_sys_sha1(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u8 csum[GF_SHA1_DIGEST_SIZE]; + const u8 *data; + size_t data_size; + + if (!argc) return JS_EXCEPTION; + if (JS_IsString(argv[0])) { + const char *filename = JS_ToCString(ctx, argv[0]); + if (!filename) return JS_EXCEPTION; + gf_sha1_file(filename, csum); + JS_FreeCString(ctx, filename); + return JS_NewArrayBufferCopy(ctx, csum, GF_SHA1_DIGEST_SIZE); + } else if (JS_IsObject(argv[0])) { + data = JS_GetArrayBuffer(ctx, &data_size, argv[0] ); + if (!data) return JS_EXCEPTION; + + gf_sha1_csum((u8 *) data, (u32) data_size, csum); + return JS_NewArrayBufferCopy(ctx, csum, GF_SHA1_DIGEST_SIZE); + } + return JS_EXCEPTION; +} + + +static JSValue js_sys_file_data(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *filename; + u8 *data; + u32 data_size; + GF_Err e; + JSValue res; + if (!argc || !JS_IsString(argv[0])) return JS_EXCEPTION; + filename = JS_ToCString(ctx, argv[0]); + if (!filename) return JS_EXCEPTION; + + e = gf_file_load_data(filename, &data, &data_size); + if (!data) res = js_throw_err_msg(ctx, e, "Failed to load file %s", filename); + else res = JS_NewArrayBuffer(ctx, data, data_size, js_gpac_free, NULL, 0); + JS_FreeCString(ctx, filename); + return res; +} + +static JSValue js_sys_compress_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_decomp) +{ + const u8 *data; + size_t data_size; + u32 out_size=0; + u8 *out_ptr = NULL; + JSValue res; + GF_Err e; + if (!argc || !JS_IsObject(argv[0])) return JS_EXCEPTION; + data = JS_GetArrayBuffer(ctx, &data_size, argv[0] ); + if (!data) return JS_EXCEPTION; + if (is_decomp) { + e = gf_gz_decompress_payload((u8*) data, (u32) data_size, &out_ptr, &out_size); + } else { + e = gf_gz_compress_payload_ex((u8 **)&data, (u32) data_size, &out_size, 0, GF_FALSE, &out_ptr); + } + + if (e) return js_throw_err(ctx, e); + res = JS_NewArrayBuffer(ctx, out_ptr, out_size, js_gpac_free, NULL, 0); + return res; +} +static JSValue js_sys_compress(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_compress_ex(ctx, this_val, argc, argv, GF_FALSE); +} +static JSValue js_sys_decompress(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_compress_ex(ctx, this_val, argc, argv, GF_TRUE); +} + +enum +{ + OPT_RMDIR, + OPT_MKDIR, + OPT_DIREXISTS, + OPT_DIRCLEAN, + OPT_FILEBASENAME, + OPT_FILEEXT, + OPT_FILEDEL, + OPT_FILEMODTIME, + OPT_FILEEXISTS, + OPT_FILEMOVE, +}; + +static JSValue js_sys_file_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 file_opt) +{ + const char *dirname, *newfile; + char *ext; + GF_Err e; + JSValue res; + if (!argc || !JS_IsString(argv[0])) return JS_EXCEPTION; + dirname = JS_ToCString(ctx, argv[0]); + if (!dirname) return JS_EXCEPTION; + + res = JS_UNDEFINED; + switch (file_opt) { + case OPT_RMDIR: + e = gf_rmdir(dirname); + if (e) res = js_throw_err_msg(ctx, e, "Failed to remove dir %s", dirname); + break; + case OPT_MKDIR: + e = gf_mkdir(dirname); + if (e) res = js_throw_err_msg(ctx, e, "Failed to create dir %s", dirname); + break; + case OPT_DIREXISTS: + res = JS_NewBool(ctx, gf_dir_exists(dirname) ); + break; + case OPT_DIRCLEAN: + e = gf_cleanup_dir(dirname); + if (e) res = js_throw_err_msg(ctx, e, "Failed to clean dir %s", dirname); + break; + case OPT_FILEBASENAME: + res = JS_NewString(ctx, gf_file_basename(dirname) ); + break; + case OPT_FILEEXT: + ext = gf_file_ext_start(dirname); + res = ext ? JS_NewString(ctx, ext) : JS_NULL; + break; + case OPT_FILEDEL: + e = gf_file_delete(dirname); + if (e) res = js_throw_err_msg(ctx, e, "Failed to delete file %s", dirname); + break; + case OPT_FILEMODTIME: + res = JS_NewInt64(ctx, gf_file_modification_time(dirname) ); + break; + case OPT_FILEEXISTS: + res = JS_NewBool(ctx, gf_file_exists(dirname) ); + break; + case OPT_FILEMOVE: + newfile = (argc<2) ? NULL : JS_ToCString(ctx, argv[1]); + if (!newfile) res = js_throw_err_msg(ctx, GF_BAD_PARAM, "Missing new file name"); + else { + e = gf_file_move(dirname, newfile); + if (e) res = js_throw_err_msg(ctx, e, "Failed to move file %s to %s", dirname, newfile); + JS_FreeCString(ctx, newfile); + } + break; + } + + JS_FreeCString(ctx, dirname); + return res; +} + +static JSValue js_sys_rmdir(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_RMDIR); +} +static JSValue js_sys_mkdir(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_MKDIR); +} +static JSValue js_sys_dir_exists(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_DIREXISTS); +} +static JSValue js_sys_dir_clean(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_DIRCLEAN); +} +static JSValue js_sys_basename(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEBASENAME); +} +static JSValue js_sys_file_ext(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEEXT); +} +static JSValue js_sys_file_exists(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEEXISTS); +} +static JSValue js_sys_file_del(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEDEL); +} +static JSValue js_sys_file_modtime(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEMODTIME); +} +static JSValue js_sys_file_move(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEMOVE); +} + + +static JSValue js_sys_get_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *sec, *key, *val; + JSValue res; + if (argc!=2) return JS_EXCEPTION; + sec = JS_ToCString(ctx, argv[0]); + if (!sec) return JS_EXCEPTION; + key = JS_ToCString(ctx, argv[1]); + if (!key) { + JS_FreeCString(ctx, sec); + return JS_EXCEPTION; + } + val = gf_opts_get_key_restricted(sec, key); + res = val ? JS_NewString(ctx, val) : JS_NULL; + JS_FreeCString(ctx, sec); + JS_FreeCString(ctx, key); + return res; +} + +static JSValue js_sys_set_opt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *sec, *key, *val; + if (argc<2) return JS_EXCEPTION; + sec = JS_ToCString(ctx, argv[0]); + if (!sec) return JS_EXCEPTION; + key = JS_ToCString(ctx, argv[1]); + if (!key) { + JS_FreeCString(ctx, sec); + return JS_EXCEPTION; + } + val = NULL; + if (argc>2) + val = JS_ToCString(ctx, argv[2]); + + gf_opts_set_key(sec, key, val); + + JS_FreeCString(ctx, sec); + JS_FreeCString(ctx, key); + if (val) + JS_FreeCString(ctx, val); + return JS_UNDEFINED; +} +static JSValue js_sys_discard_opts(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + gf_opts_discard_changes(); + return JS_UNDEFINED; +} + +static JSValue js_sys_basecode_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_dec, Bool is_16) +{ + u32 out_size=0; + u8 *out_ptr = NULL; + JSValue res; + GF_Err e; + if (!argc) return JS_EXCEPTION; + + if (is_dec) { + u32 len; + const char *str = JS_ToCString(ctx, argv[0]); + if (!str) return JS_EXCEPTION; + len = (u32) strlen(str); + out_ptr = gf_malloc(sizeof(u8) * len); + if (!out_ptr) { + e = GF_OUT_OF_MEM; + } else if (is_16) { + out_size = gf_base16_decode((u8*) str, (u32) len, out_ptr, len); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } else { + out_size = gf_base64_decode((u8*) str, (u32) len, out_ptr, len); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } + JS_FreeCString(ctx, str); + } else { + const u8 *data; + size_t data_size; + data = JS_GetArrayBuffer(ctx, &data_size, argv[0] ); + if (!data) return JS_EXCEPTION; + out_ptr = gf_malloc(sizeof(u8) * (1 + data_size * 2) ); + if (!out_ptr) { + e = GF_OUT_OF_MEM; + } else if (is_16) { + out_size = gf_base16_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } else { + out_size = gf_base64_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } + } + + if (e) return js_throw_err(ctx, e); + if (is_dec) { + res = JS_NewArrayBuffer(ctx, out_ptr, out_size, js_gpac_free, NULL, 0); + } else { + out_ptr[out_size] = 0; + res = JS_NewString(ctx, out_ptr); + gf_free(out_ptr); + } + return res; +} +static JSValue js_sys_base64enc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_FALSE, GF_FALSE); +} +static JSValue js_sys_base64dec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_TRUE, GF_FALSE); +} +static JSValue js_sys_base16enc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_FALSE, GF_TRUE); +} +static JSValue js_sys_base16dec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + return js_sys_basecode_ex(ctx, this_val, argc, argv, GF_TRUE, GF_TRUE); +} +static JSValue js_sys_ntohl(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 val; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_ntohl((u32) val)); +} +static JSValue js_sys_ntohs(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 val; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_ntohs((u16) val)); +} +static JSValue js_sys_htonl(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 val; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_htonl((u32) val)); +} +static JSValue js_sys_htons(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + s64 val; + if (!argc) return JS_EXCEPTION; + if (JS_ToInt64(ctx, &val, argv[0])) return JS_EXCEPTION; + return JS_NewInt32(ctx, gf_htons((u16) val)); +} + +static const JSCFunctionListEntry sys_funcs[] = { + JS_CGETSET_MAGIC_DEF_ENUM("nb_cores", js_sys_prop_get, NULL, JS_SYS_NB_CORES), + JS_CGETSET_MAGIC_DEF_ENUM("sampling_period_duration", js_sys_prop_get, NULL, JS_SYS_SAMPLE_DUR), + JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_time", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU), + JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_time", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU), + JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_time_diff", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU_DIFF), + JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_time_diff", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU_DIFF), + JS_CGETSET_MAGIC_DEF_ENUM("cpu_idle_time", js_sys_prop_get, NULL, JS_SYS_CPU_IDLE), + JS_CGETSET_MAGIC_DEF_ENUM("total_cpu_usage", js_sys_prop_get, NULL, JS_SYS_TOTAL_CPU_USAGE), + JS_CGETSET_MAGIC_DEF_ENUM("process_cpu_usage", js_sys_prop_get, NULL, JS_SYS_PROCESS_CPU_USAGE), + JS_CGETSET_MAGIC_DEF_ENUM("pid", js_sys_prop_get, NULL, JS_SYS_PID), + JS_CGETSET_MAGIC_DEF_ENUM("thread_count", js_sys_prop_get, NULL, JS_SYS_THREADS), + JS_CGETSET_MAGIC_DEF_ENUM("process_memory", js_sys_prop_get, NULL, JS_SYS_PROCESS_MEM), + JS_CGETSET_MAGIC_DEF_ENUM("physical_memory", js_sys_prop_get, NULL, JS_SYS_TOTAL_MEM), + JS_CGETSET_MAGIC_DEF_ENUM("physical_memory_avail", js_sys_prop_get, NULL, JS_SYS_TOTAL_MEM_AVAIL), + JS_CGETSET_MAGIC_DEF_ENUM("gpac_memory", js_sys_prop_get, NULL, JS_SYS_GPAC_MEM), + + JS_CGETSET_MAGIC_DEF_ENUM("last_wdir", js_sys_prop_get, js_sys_prop_set, JS_SYS_LAST_WORK_DIR), + JS_CGETSET_MAGIC_DEF_ENUM("batteryOn", js_sys_prop_get, NULL, JS_SYS_BATTERY_ON), + JS_CGETSET_MAGIC_DEF_ENUM("batteryCharging", js_sys_prop_get, NULL, JS_SYS_BATTERY_CHARGE), + JS_CGETSET_MAGIC_DEF_ENUM("batteryPercent", js_sys_prop_get, NULL, JS_SYS_BATTERY_PERCENT), + JS_CGETSET_MAGIC_DEF_ENUM("batteryLifeTime", js_sys_prop_get, NULL, JS_SYS_BATTERY_LIFETIME), + JS_CGETSET_MAGIC_DEF_ENUM("batteryFullLifeTime", js_sys_prop_get, NULL, JS_SYS_BATTERY_LIFETIME_FULL), + JS_CGETSET_MAGIC_DEF_ENUM("hostname", js_sys_prop_get, NULL, JS_SYS_HOSTNAME), + JS_CGETSET_MAGIC_DEF_ENUM("username", js_sys_prop_get, NULL, JS_SYS_USERNAME), + + JS_CGETSET_MAGIC_DEF_ENUM("test_mode", js_sys_prop_get, NULL, JS_SYS_TEST_MODE), + JS_CGETSET_MAGIC_DEF_ENUM("old_arch", js_sys_prop_get, NULL, JS_SYS_OLD_ARCH), + JS_CGETSET_MAGIC_DEF_ENUM("log_color", js_sys_prop_get, NULL, JS_SYS_LOG_COLOR), + + JS_CGETSET_MAGIC_DEF_ENUM("quiet", js_sys_prop_get, NULL, JS_SYS_QUIET), + JS_CGETSET_MAGIC_DEF_ENUM("timezone", js_sys_prop_get, NULL, JS_SYS_TIMEZONE), + JS_CGETSET_MAGIC_DEF_ENUM("nb_files_open", js_sys_prop_get, NULL, JS_SYS_FILES_OPEN), + JS_CGETSET_MAGIC_DEF_ENUM("cache_dir", js_sys_prop_get, NULL, JS_SYS_CACHE_DIR), + JS_CGETSET_MAGIC_DEF_ENUM("shared_dir", js_sys_prop_get, NULL, JS_SYS_SHARED_DIR), + JS_CGETSET_MAGIC_DEF_ENUM("version", js_sys_prop_get, NULL, JS_SYS_VERSION), + JS_CGETSET_MAGIC_DEF_ENUM("version_full", js_sys_prop_get, NULL, JS_SYS_VERSION_FULL), + JS_CGETSET_MAGIC_DEF_ENUM("copyright", js_sys_prop_get, NULL, JS_SYS_COPYRIGHT), + JS_CGETSET_MAGIC_DEF_ENUM("version_major", js_sys_prop_get, NULL, JS_SYS_V_MAJOR), + JS_CGETSET_MAGIC_DEF_ENUM("version_minor", js_sys_prop_get, NULL, JS_SYS_V_MINOR), + JS_CGETSET_MAGIC_DEF_ENUM("version_micro", js_sys_prop_get, NULL, JS_SYS_V_MICRO), + + JS_CFUNC_DEF("set_arg_used", 0, js_sys_set_arg_used), + JS_CFUNC_DEF("error_string", 0, js_sys_error_string), + JS_CFUNC_DEF("prompt_input", 0, js_sys_prompt_input), + JS_CFUNC_DEF("prompt_string", 0, js_sys_prompt_string), + JS_CFUNC_DEF("prompt_echo_off", 0, js_sys_prompt_echo_off), + JS_CFUNC_DEF("prompt_code", 0, js_sys_prompt_code), + JS_CFUNC_DEF("prompt_size", 0, js_sys_prompt_size), + + JS_CFUNC_DEF("gc", 0, js_sys_gc), + + JS_CFUNC_DEF("enum_directory", 0, js_sys_enum_directory), + JS_CFUNC_DEF("clock_ms", 0, js_sys_clock), + JS_CFUNC_DEF("clock_us", 0, js_sys_clock_high_res), + JS_CFUNC_DEF("fcc_to_str", 0, js_sys_4cc_to_str), + JS_CFUNC_DEF("rand_init", 0, js_sys_rand_init), + JS_CFUNC_DEF("rand", 0, js_sys_rand), + JS_CFUNC_DEF("rand64", 0, js_sys_rand64), + JS_CFUNC_DEF("getenv", 0, js_sys_getenv), + JS_CFUNC_DEF("get_utc", 0, js_sys_get_utc), + JS_CFUNC_DEF("crc32", 0, js_sys_crc32), + JS_CFUNC_DEF("sha1", 0, js_sys_sha1), + JS_CFUNC_DEF("load_file", 0, js_sys_file_data), + JS_CFUNC_DEF("compress", 0, js_sys_compress), + JS_CFUNC_DEF("decompress", 0, js_sys_decompress), + JS_CFUNC_DEF("rmdir", 0, js_sys_rmdir), + JS_CFUNC_DEF("mkdir", 0, js_sys_mkdir), + JS_CFUNC_DEF("dir_exists", 0, js_sys_dir_exists), + JS_CFUNC_DEF("dir_clean", 0, js_sys_dir_clean), + JS_CFUNC_DEF("basename", 0, js_sys_basename), + JS_CFUNC_DEF("file_ext", 0, js_sys_file_ext), + JS_CFUNC_DEF("file_exists", 0, js_sys_file_exists), + JS_CFUNC_DEF("del", 0, js_sys_file_del), + JS_CFUNC_DEF("mod_time", 0, js_sys_file_modtime), + JS_CFUNC_DEF("move", 0, js_sys_file_move), + JS_CFUNC_DEF("get_opt", 0, js_sys_get_opt), + JS_CFUNC_DEF("set_opt", 0, js_sys_set_opt), + JS_CFUNC_DEF("discard_opts", 0, js_sys_discard_opts), + + JS_CFUNC_DEF("base64enc", 0, js_sys_base64enc), + JS_CFUNC_DEF("base64dec", 0, js_sys_base64dec), + JS_CFUNC_DEF("base16enc", 0, js_sys_base16enc), + JS_CFUNC_DEF("base16dec", 0, js_sys_base16dec), + + JS_CFUNC_DEF("ntohl", 0, js_sys_ntohl), + JS_CFUNC_DEF("ntohs", 0, js_sys_ntohs), + JS_CFUNC_DEF("htonl", 0, js_sys_htonl), + JS_CFUNC_DEF("htons", 0, js_sys_htons), + +}; + + +static void js_sha1_finalize(JSRuntime *rt, JSValue obj) +{ + GF_SHA1Context *sha1 = JS_GetOpaque(obj, sha1_class_id); + if (!sha1) return; + gf_free(sha1); +} + +JSClassDef sha1Class = { + "SHA1", + .finalizer = js_sha1_finalize, +}; + +static JSValue js_sha1_push(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const u8 *data; + size_t data_size; + GF_SHA1Context *sha1 = JS_GetOpaque(this_val, sha1_class_id); + if (!sha1) { + sha1 = gf_sha1_starts(); + if (!sha1) { + return js_throw_err(ctx, GF_OUT_OF_MEM); + } + JS_SetOpaque(this_val, sha1); + } + if (!argc) return JS_EXCEPTION; + data = JS_GetArrayBuffer(ctx, &data_size, argv[0]); + gf_sha1_update(sha1, (u8 *) data, (u32) data_size); + + return JS_UNDEFINED; +} +static JSValue js_sha1_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + u8 output[GF_SHA1_DIGEST_SIZE]; + GF_SHA1Context *sha1 = JS_GetOpaque(this_val, sha1_class_id); + if (!sha1) return JS_EXCEPTION; + gf_sha1_finish(sha1, output); + JS_SetOpaque(this_val, NULL); + return JS_NewArrayBufferCopy(ctx, output, GF_SHA1_DIGEST_SIZE); +} + +static const JSCFunctionListEntry sha1_funcs[] = { + JS_CFUNC_DEF("push", 0, js_sha1_push), + JS_CFUNC_DEF("get", 0, js_sha1_get), +}; + +static JSValue sha1_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) +{ + JSValue anobj; + GF_SHA1Context *sha1; + + sha1 = gf_sha1_starts(); + if (!sha1) { + return js_throw_err(ctx, GF_OUT_OF_MEM); + } + anobj = JS_NewObjectClass(ctx, sha1_class_id); + if (JS_IsException(anobj)) { + gf_free(sha1); + return anobj; + } + JS_SetOpaque(anobj, sha1); + return anobj; +} + + +static void js_file_finalize(JSRuntime *rt, JSValue obj) +{ + FILE *f = JS_GetOpaque(obj, file_class_id); + if (!f) return; + gf_fclose(f); +} + +JSClassDef fileClass = { + "FILE", + .finalizer = js_file_finalize, +}; + +enum +{ + JS_FILE_POS = 0, + JS_FILE_EOF, + JS_FILE_ERROR, + JS_FILE_SIZE, + JS_FILE_IS_GFIO, +}; + +static JSValue js_file_prop_get(JSContext *ctx, JSValueConst this_val, int magic) +{ + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + + switch (magic) { + case JS_FILE_POS: + return JS_NewInt64(ctx, gf_ftell(f)); + case JS_FILE_EOF: + return JS_NewBool(ctx, gf_feof(f)); + case JS_FILE_ERROR: + return JS_NewInt32(ctx, gf_ferror(f) ); + case JS_FILE_SIZE: + return JS_NewInt64(ctx, gf_fsize(f) ); + case JS_FILE_IS_GFIO: + return JS_NewBool(ctx, gf_fileio_check(f)); + } + return JS_UNDEFINED; +} + +static JSValue js_file_prop_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +{ + s64 lival; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + + switch (magic) { + case JS_FILE_POS: + if (JS_ToInt64(ctx, &lival, value)) return JS_EXCEPTION; + gf_fseek(f, lival, SEEK_SET); + break; + } + return JS_UNDEFINED; +} +static JSValue js_file_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + gf_fflush(f); + return JS_UNDEFINED; +} +static JSValue js_file_close(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + gf_fclose(f); + JS_SetOpaque(this_val, NULL); + return JS_UNDEFINED; +} +static JSValue js_file_read(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const u8 *data; + size_t size; + u32 read; + s32 nb_bytes=0; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + if (!argc) return JS_EXCEPTION; + + data = JS_GetArrayBuffer(ctx, &size, argv[0]); + if (!data) return JS_EXCEPTION; + if (argc>1) { + if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION; + } + if (!nb_bytes) nb_bytes = (s32) size; + else if (nb_bytes > (s32) size) nb_bytes = (s32) size; + + read = (u32) gf_fread((void *) data, nb_bytes, f); + return JS_NewInt64(ctx, read); +} +static JSValue js_file_gets(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + char *data=NULL; + char temp[1025]; + JSValue res; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + + temp[1024] = 0; + while (1) { + u32 rlen; + temp[0] = 0; + const char *read = gf_fgets(temp, 1024, f); + if (!read) break; + gf_dynstrcat(&data, temp, NULL); + if (!data) return js_throw_err(ctx, GF_OUT_OF_MEM); + rlen = (u32) strlen(temp); + if (rlen <= 1024) + break; + if (temp[rlen-1] == '\n') + break; + } + res = JS_NewString(ctx, data); + gf_free(data); + return res; +} + +static JSValue js_file_getc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + char res[2]; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + + res[0] = gf_fgetc(f); + res[1] = 0; + return JS_NewString(ctx, res); +} + +static JSValue js_file_write(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const u8 *data; + size_t size; + u32 read; + s32 nb_bytes=0; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f) return JS_EXCEPTION; + if (!argc) return JS_EXCEPTION; + + data = JS_GetArrayBuffer(ctx, &size, argv[0]); + if (!data) return JS_EXCEPTION; + if (argc>1) { + if (JS_ToInt32(ctx, &nb_bytes, argv[1])) return JS_EXCEPTION; + } + if (!nb_bytes) nb_bytes = (u32) size; + else if (nb_bytes > (s32) size) nb_bytes = (u32) size; + + read = (u32) gf_fwrite((void *) data, nb_bytes, f); + return JS_NewInt64(ctx, read); +} +static JSValue js_file_puts(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + const char *string; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f || !argc) return JS_EXCEPTION; + + string = JS_ToCString(ctx, argv[0]); + if (!string) return JS_EXCEPTION; + gf_fputs(string, f); + JS_FreeCString(ctx, string); + return JS_UNDEFINED; +} + +static JSValue js_file_putc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + int val=0; + FILE *f = JS_GetOpaque(this_val, file_class_id); + if (!f || !argc) return JS_EXCEPTION; + + if (JS_IsString(argv[0])) { + const char *string = JS_ToCString(ctx, argv[0]); + if (!string) return JS_EXCEPTION; + val = string[0]; + JS_FreeCString(ctx, string); + } else { + if (JS_ToInt32(ctx, &val, argv[0])) return JS_EXCEPTION; + } + gf_fputc(val, f); + return JS_UNDEFINED; +} + +static const JSCFunctionListEntry file_funcs[] = { + JS_CGETSET_MAGIC_DEF_ENUM("pos", js_file_prop_get, js_file_prop_set, JS_FILE_POS), + JS_CGETSET_MAGIC_DEF_ENUM("eof", js_file_prop_get, NULL, JS_FILE_EOF), + JS_CGETSET_MAGIC_DEF_ENUM("error", js_file_prop_get, NULL, JS_FILE_ERROR), + JS_CGETSET_MAGIC_DEF_ENUM("size", js_file_prop_get, NULL, JS_FILE_SIZE), + JS_CGETSET_MAGIC_DEF_ENUM("gfio", js_file_prop_get, NULL, JS_FILE_IS_GFIO), + + JS_CFUNC_DEF("flush", 0, js_file_flush), + JS_CFUNC_DEF("close", 0, js_file_close), + JS_CFUNC_DEF("read", 0, js_file_read), + JS_CFUNC_DEF("gets", 0, js_file_gets), + JS_CFUNC_DEF("getc", 0, js_file_getc), + JS_CFUNC_DEF("write", 0, js_file_write), + JS_CFUNC_DEF("puts", 0, js_file_puts), + JS_CFUNC_DEF("putc", 0, js_file_putc), +}; + +static JSValue file_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) +{ + JSValue anobj; + FILE *f=NULL; + + if (!argc) { + f = gf_file_temp(NULL); + if (!f) { + return js_throw_err(ctx, GF_OUT_OF_MEM); + } + } else { + GF_Err e = GF_OK; + const char *name=NULL, *mode=NULL, *parent_io=NULL; + name = JS_ToCString(ctx, argv[0] ); + if (argc>1) { + mode = JS_ToCString(ctx, argv[1] ); + if (argc>2) { + parent_io = JS_ToCString(ctx, argv[2] ); + } + } + + if (!name || !mode) { + e = GF_BAD_PARAM; + } else { + f = gf_fopen_ex(name, parent_io, mode); + if (!f) e = GF_URL_ERROR; + } + if (name) JS_FreeCString(ctx, name); + if (mode) JS_FreeCString(ctx, mode); + if (parent_io) JS_FreeCString(ctx, parent_io); + + if (e) { + return js_throw_err(ctx, e); + } + } + + anobj = JS_NewObjectClass(ctx, file_class_id); + if (JS_IsException(anobj)) { + gf_fclose(f); + return anobj; + } + JS_SetOpaque(anobj, f); + return anobj; +} + + +static int js_gpaccore_init(JSContext *ctx, JSModuleDef *m) +{ + JSValue proto, ctor; + if (!bitstream_class_id) { + JS_NewClassID(&bitstream_class_id); + JS_NewClass(JS_GetRuntime(ctx), bitstream_class_id, &bitstreamClass); + + JS_NewClassID(&sha1_class_id); + JS_NewClass(JS_GetRuntime(ctx), sha1_class_id, &sha1Class); + + JS_NewClassID(&file_class_id); + JS_NewClass(JS_GetRuntime(ctx), file_class_id, &fileClass); + } + + JSValue core_o = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, core_o, sys_funcs, countof(sys_funcs)); + JS_SetModuleExport(ctx, m, "Sys", core_o); + + JSValue args = JS_NewArray(ctx); + u32 i, nb_args = gf_sys_get_argc(); + for (i=0; i<nb_args; i++) { + JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, gf_sys_get_arg(i))); + } + JS_SetPropertyStr(ctx, core_o, "args", args); + +#define DEF_CONST( _val ) \ + JS_SetPropertyStr(ctx, core_o, #_val, JS_NewInt32(ctx, _val)); + + DEF_CONST(GF_CONSOLE_RESET) + DEF_CONST(GF_CONSOLE_RED) + DEF_CONST(GF_CONSOLE_GREEN) + DEF_CONST(GF_CONSOLE_BLUE) + DEF_CONST(GF_CONSOLE_YELLOW) + DEF_CONST(GF_CONSOLE_CYAN) + DEF_CONST(GF_CONSOLE_WHITE) + DEF_CONST(GF_CONSOLE_MAGENTA) + DEF_CONST(GF_CONSOLE_CLEAR) + DEF_CONST(GF_CONSOLE_SAVE) + DEF_CONST(GF_CONSOLE_RESTORE) + DEF_CONST(GF_CONSOLE_BOLD) + DEF_CONST(GF_CONSOLE_ITALIC) + DEF_CONST(GF_CONSOLE_UNDERLINED) + DEF_CONST(GF_CONSOLE_STRIKE) + +#undef DEF_CONST + + + //bitstream constructor + proto = JS_NewObjectClass(ctx, bitstream_class_id); + JS_SetPropertyFunctionList(ctx, proto, bitstream_funcs, countof(bitstream_funcs)); + JS_SetClassProto(ctx, bitstream_class_id, proto); + ctor = JS_NewCFunction2(ctx, bitstream_constructor, "Bitstream", 1, JS_CFUNC_constructor, 0); + JS_SetModuleExport(ctx, m, "Bitstream", ctor); + + //sha1 constructor + proto = JS_NewObjectClass(ctx, sha1_class_id); + JS_SetPropertyFunctionList(ctx, proto, sha1_funcs, countof(sha1_funcs)); + JS_SetClassProto(ctx, sha1_class_id, proto); + ctor = JS_NewCFunction2(ctx, sha1_constructor, "SHA1", 1, JS_CFUNC_constructor, 0); + JS_SetModuleExport(ctx, m, "SHA1", ctor); + + //FILE constructor + proto = JS_NewObjectClass(ctx, file_class_id); + JS_SetPropertyFunctionList(ctx, proto, file_funcs, countof(file_funcs)); + JS_SetClassProto(ctx, file_class_id, proto); + ctor = JS_NewCFunction2(ctx, file_constructor, "File", 1, JS_CFUNC_constructor, 0); + JS_SetModuleExport(ctx, m, "File", ctor); + + return 0; +} + + +void qjs_module_init_gpaccore(JSContext *ctx) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, "gpaccore", js_gpaccore_init); + if (!m) return; + + JS_AddModuleExport(ctx, m, "Sys"); + JS_AddModuleExport(ctx, m, "Bitstream"); + JS_AddModuleExport(ctx, m, "SHA1"); + JS_AddModuleExport(ctx, m, "File"); + return; +} + + +#endif +
View file
gpac-1.0.0.tar.gz/src/jsmods/evg.c -> gpac-1.0.1.tar.gz/src/jsmods/evg.c
Changed
@@ -32,7 +32,7 @@ #include <gpac/setup.h> -#ifdef GPAC_HAS_QJS +#if defined(GPAC_HAS_QJS) /*base SVG type*/ #include <gpac/nodes_svg.h> @@ -6626,6 +6626,10 @@ return; } +#else +void qjs_module_init_evg(void *ctx) +{ +} #endif
View file
gpac-1.0.0.tar.gz/src/jsmods/scene_js.c -> gpac-1.0.1.tar.gz/src/jsmods/scene_js.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * Copyright (c) Telecom ParisTech 2007-2019 + * Copyright (c) Telecom ParisTech 2007-2020 * All rights reserved * * This file is part of GPAC / JavaScript Compositor extensions @@ -26,7 +26,7 @@ #include <gpac/setup.h> -#ifdef GPAC_HAS_QJS +#if defined(GPAC_HAS_QJS) && !defined(GPAC_DISABLE_PLAYER) /*base SVG type*/ #include <gpac/nodes_svg.h> @@ -48,9 +48,6 @@ #include <gpac/internal/compositor_dev.h> #include <gpac/term_info.h> -#define GPAC_JS_RTI_REFRESH_RATE 200 - - typedef struct { GF_Compositor *compositor; @@ -59,9 +56,8 @@ GF_Event *evt; JSContext *c; - JSValue evt_filter_obj, evt_obj, gpac_obj; + JSValue evt_filter_obj, evt_obj, scene_obj; - u32 rti_refresh_rate; GF_SystemRTInfo rti; //list of config files for storage @@ -70,7 +66,7 @@ GF_List *event_queue; GF_Mutex *event_mx; -} GF_GPACJSExt; +} GF_SCENEJSExt; enum { GJS_OM_PROP_ID=1, @@ -130,41 +126,27 @@ }; enum { - GJS_GPAC_PROP_LAST_WORK_DIR=1, - GJS_GPAC_PROP_BATTERY_ON, - GJS_GPAC_PROP_BATTERY_CHARGE, - GJS_GPAC_PROP_BATTERY_PERCENT, - GJS_GPAC_PROP_BATTERY_LIFETIME, - GJS_GPAC_PROP_BATTERY_LIFETIME_FULL, - GJS_GPAC_PROP_HOSTNAME, - GJS_GPAC_PROP_FULLSCREEN, - GJS_GPAC_PROP_CURRENT_PATH, - GJS_GPAC_PROP_VOLUME, - GJS_GPAC_PROP_NAVIGATION, - GJS_GPAC_PROP_NAVIGATION_TYPE, - GJS_GPAC_PROP_HARDWARE_YUV, - GJS_GPAC_PROP_HARDWARE_RGB, - GJS_GPAC_PROP_HARDWARE_RGBA, - GJS_GPAC_PROP_HARDWARE_STRETCH, - GJS_GPAC_PROP_SCREEN_WIDTH, - GJS_GPAC_PROP_SCREEN_HEIGHT, - GJS_GPAC_PROP_HTTP_MAX_RATE, - GJS_GPAC_PROP_HTTP_RATE, - GJS_GPAC_PROP_FPS, - GJS_GPAC_PROP_CPU, - GJS_GPAC_PROP_NB_CORES, - GJS_GPAC_PROP_MEMORY_SYSTEM, - GJS_GPAC_PROP_MEMORY, - GJS_GPAC_PROP_ARGC, - GJS_GPAC_PROP_CAPTION, - GJS_GPAC_PROP_FOCUS_HIGHLIGHT, - GJS_GPAC_PROP_DPI_X, - GJS_GPAC_PROP_DPI_Y, - GJS_GPAC_PROP_SENSORS_ACTIVE, - GJS_GPAC_PROP_SIM_FPS, - GJS_GPAC_PROP_HAS_OPENGL, - GJS_GPAC_PROP_ZOOM, - GJS_GPAC_PROP_TEXT_SEL, + GJS_SCENE_PROP_FULLSCREEN=1, + GJS_SCENE_PROP_CURRENT_PATH, + GJS_SCENE_PROP_VOLUME, + GJS_SCENE_PROP_NAVIGATION, + GJS_SCENE_PROP_NAVIGATION_TYPE, + GJS_SCENE_PROP_HARDWARE_YUV, + GJS_SCENE_PROP_HARDWARE_RGB, + GJS_SCENE_PROP_HARDWARE_RGBA, + GJS_SCENE_PROP_HARDWARE_STRETCH, + GJS_SCENE_PROP_SCREEN_WIDTH, + GJS_SCENE_PROP_SCREEN_HEIGHT, + GJS_SCENE_PROP_FPS, + GJS_SCENE_PROP_CAPTION, + GJS_SCENE_PROP_FOCUS_HIGHLIGHT, + GJS_SCENE_PROP_DPI_X, + GJS_SCENE_PROP_DPI_Y, + GJS_SCENE_PROP_SENSORS_ACTIVE, + GJS_SCENE_PROP_SIM_FPS, + GJS_SCENE_PROP_HAS_OPENGL, + GJS_SCENE_PROP_ZOOM, + GJS_SCENE_PROP_TEXT_SEL, }; @@ -182,25 +164,25 @@ GJS_EVT_PROP_FILES, }; -static JSClassID gpac_class_id = 0; +static JSClassID scene_class_id = 0; static JSClassID odm_class_id = 0; static JSClassID gpacevt_class_id = 0; static JSClassID any_class_id = 0; -static void gpac_js_finalize(JSRuntime *rt, JSValue obj); +static void scenejs_finalize(JSRuntime *rt, JSValue obj); -static void gpac_gc_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) +static void scenejs_gc_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { - GF_GPACJSExt *ext = JS_GetOpaque(val, gpac_class_id); + GF_SCENEJSExt *ext = JS_GetOpaque(val, scene_class_id); if (ext) { JS_MarkValue(rt, ext->evt_fun, mark_func); } } -JSClassDef gpacClass = { - "JSGPAC", - .finalizer = gpac_js_finalize, - .gc_mark = gpac_gc_mark +JSClassDef sceneClass = { + "JSSCENE", + .finalizer = scenejs_finalize, + .gc_mark = scenejs_gc_mark }; JSClassDef gpacEvtClass = { "GPACEVT" @@ -213,164 +195,88 @@ }; -static GF_Compositor *gpac_get_compositor(JSContext *c, JSValue obj) +static GF_Compositor *scenejs_get_compositor(JSContext *c, JSValue obj) { - GF_GPACJSExt *ext = JS_GetOpaque(obj, gpac_class_id); + GF_SCENEJSExt *ext = JS_GetOpaque(obj, scene_class_id); return ext ? ext->compositor : NULL; } -static JSValue gpac_getProperty(JSContext *ctx, JSValueConst this_val, int prop_id) +static JSValue scenejs_getProperty(JSContext *ctx, JSValueConst this_val, int prop_id) { Bool bval; - u32 uval; JSValue ret; char *str; - const char *res; - GF_GPACJSExt *ext = JS_GetOpaque(this_val, gpac_class_id); + GF_SCENEJSExt *ext = JS_GetOpaque(this_val, scene_class_id); GF_Compositor *compositor = ext ? ext->compositor : NULL; if (!ext || !compositor) return JS_EXCEPTION; switch (prop_id) { - case GJS_GPAC_PROP_LAST_WORK_DIR: - res = gf_opts_get_key("General", "LastWorkingDir"); - if (!res) res = gf_opts_get_key("core", "mod-dirs"); -#ifdef WIN32 - if (!res) res = "C:\\"; -#elif defined(GPAC_CONFIG_DARWIN) - if (!res) res = "/Users"; -#else - if (!res) res = "/home/"; -#endif - return JS_NewString(ctx, res); - - case GJS_GPAC_PROP_BATTERY_ON: - bval = GF_FALSE; - gf_sys_get_battery_state(&bval, NULL, NULL, NULL, NULL); - return JS_NewBool(ctx, bval); - - case GJS_GPAC_PROP_BATTERY_CHARGE: - uval = 0; - gf_sys_get_battery_state(NULL, &uval, NULL, NULL, NULL); - return JS_NewBool(ctx, uval ? 1 : 0); - - case GJS_GPAC_PROP_BATTERY_PERCENT: - uval=0; - gf_sys_get_battery_state(NULL, NULL, &uval, NULL, NULL); - return JS_NewInt32(ctx, uval); - case GJS_GPAC_PROP_BATTERY_LIFETIME: - uval=0; - gf_sys_get_battery_state(NULL, NULL, NULL, &uval, NULL); - return JS_NewInt32(ctx, uval); - - case GJS_GPAC_PROP_BATTERY_LIFETIME_FULL: - uval=0; - gf_sys_get_battery_state(NULL, NULL, NULL, NULL, &uval); - return JS_NewInt32(ctx, uval); - - case GJS_GPAC_PROP_HOSTNAME: - { - char hostname[100]; - gf_sk_get_host_name((char*)hostname); - return JS_NewString(ctx, hostname); - } - break; - - case GJS_GPAC_PROP_FULLSCREEN: + case GJS_SCENE_PROP_FULLSCREEN: return JS_NewBool(ctx, compositor->fullscreen); - case GJS_GPAC_PROP_CURRENT_PATH: + case GJS_SCENE_PROP_CURRENT_PATH: str = gf_url_concatenate(compositor->root_scene->root_od->scene_ns->url, ""); if (!str) str = gf_strdup(""); ret = JS_NewString(ctx, str); gf_free(str); return ret; - case GJS_GPAC_PROP_VOLUME: + case GJS_SCENE_PROP_VOLUME: return JS_NewInt32(ctx, gf_sc_get_option(compositor, GF_OPT_AUDIO_VOLUME)); - case GJS_GPAC_PROP_NAVIGATION: + case GJS_SCENE_PROP_NAVIGATION: return JS_NewInt32(ctx, gf_sc_get_option(compositor, GF_OPT_NAVIGATION)); - case GJS_GPAC_PROP_NAVIGATION_TYPE: + case GJS_SCENE_PROP_NAVIGATION_TYPE: return JS_NewInt32(ctx, gf_sc_get_option(compositor, GF_OPT_NAVIGATION_TYPE) ); - case GJS_GPAC_PROP_HARDWARE_YUV: + case GJS_SCENE_PROP_HARDWARE_YUV: return JS_NewBool(ctx, (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_YUV) ? 1 : 0 ); - case GJS_GPAC_PROP_HARDWARE_RGB: + case GJS_SCENE_PROP_HARDWARE_RGB: return JS_NewBool(ctx, (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_RGB) ? 1 : 0 ); - case GJS_GPAC_PROP_HARDWARE_RGBA: + case GJS_SCENE_PROP_HARDWARE_RGBA: bval = (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_RGBA) ? 1 : 0; #ifndef GPAC_DISABLE_3D if (compositor->hybrid_opengl || compositor->is_opengl) bval = 1; #endif return JS_NewBool(ctx, bval); - case GJS_GPAC_PROP_HARDWARE_STRETCH: + case GJS_SCENE_PROP_HARDWARE_STRETCH: return JS_NewBool(ctx, (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_STRETCH) ? 1 : 0 ); - case GJS_GPAC_PROP_SCREEN_WIDTH: + case GJS_SCENE_PROP_SCREEN_WIDTH: + if (compositor->osize.x) + return JS_NewInt32(ctx, compositor->osize.x); return JS_NewInt32(ctx, compositor->video_out->max_screen_width); - case GJS_GPAC_PROP_SCREEN_HEIGHT: + case GJS_SCENE_PROP_SCREEN_HEIGHT: + if (compositor->osize.y) + return JS_NewInt32(ctx, compositor->osize.y); return JS_NewInt32(ctx, compositor->video_out->max_screen_height); - case GJS_GPAC_PROP_HTTP_MAX_RATE: - { - GF_DownloadManager *dm = gf_sc_get_downloader(compositor); - if (dm) - return JS_NewInt32(ctx, gf_dm_get_data_rate(dm)); - } - break; - case GJS_GPAC_PROP_HTTP_RATE: - { - GF_DownloadManager *dm = gf_sc_get_downloader(compositor); - if (dm) - return JS_NewInt32(ctx, gf_dm_get_global_rate(dm) / 1000); - } - break; - - case GJS_GPAC_PROP_FPS: + case GJS_SCENE_PROP_FPS: return JS_NewFloat64(ctx, gf_sc_get_fps(compositor, 0) ); - case GJS_GPAC_PROP_SIM_FPS: + case GJS_SCENE_PROP_SIM_FPS: return JS_NewFloat64(ctx, ((Double)compositor->fps.den)/compositor->fps.num); - case GJS_GPAC_PROP_HAS_OPENGL: + case GJS_SCENE_PROP_HAS_OPENGL: return JS_NewBool(ctx, (compositor->ogl != GF_SC_GLMODE_OFF) ? 1 : 0); - case GJS_GPAC_PROP_CPU: - gf_sys_get_rti(ext->rti_refresh_rate, &ext->rti, 0); - return JS_NewInt32(ctx, ext->rti.process_cpu_usage); - - case GJS_GPAC_PROP_NB_CORES: - gf_sys_get_rti(ext->rti_refresh_rate, &ext->rti, 0); - return JS_NewInt32(ctx, ext->rti.nb_cores); - - case GJS_GPAC_PROP_MEMORY_SYSTEM: - gf_sys_get_rti(ext->rti_refresh_rate, &ext->rti, 0); - return JS_NewFloat64(ctx, (Double) ext->rti.physical_memory); - - case GJS_GPAC_PROP_MEMORY: - gf_sys_get_rti(ext->rti_refresh_rate, &ext->rti, 0); - return JS_NewInt64(ctx, ext->rti.process_memory); - - case GJS_GPAC_PROP_ARGC: - return JS_NewInt32(ctx, gf_sys_get_argc() ); - - case GJS_GPAC_PROP_DPI_X: + case GJS_SCENE_PROP_DPI_X: return JS_NewInt32(ctx, compositor->video_out->dpi_x); - case GJS_GPAC_PROP_DPI_Y: + case GJS_SCENE_PROP_DPI_Y: return JS_NewInt32(ctx, compositor->video_out->dpi_y); - case GJS_GPAC_PROP_SENSORS_ACTIVE: + case GJS_SCENE_PROP_SENSORS_ACTIVE: return JS_NewBool(ctx, compositor->orientation_sensors_active); - case GJS_GPAC_PROP_ZOOM: + case GJS_SCENE_PROP_ZOOM: if (compositor->root_scene && compositor->root_scene->graph->script_action) { GF_JSAPIParam jspar; memset(&jspar, 0, sizeof(GF_JSAPIParam)); @@ -385,7 +291,7 @@ return JS_NewFloat64(ctx, 1.0 ); } break; - case GJS_GPAC_PROP_TEXT_SEL: + case GJS_SCENE_PROP_TEXT_SEL: str = (char *) gf_sc_get_selected_text(compositor); if (!str) str = ""; return JS_NewString(ctx, str); @@ -394,7 +300,7 @@ } -static JSValue gpac_setProperty(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) +static JSValue scenejs_setProperty(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) { #ifndef GPAC_CONFIG_IOS Bool bval; @@ -402,18 +308,12 @@ s32 ival; Double dval; const char *prop_val; - GF_GPACJSExt *ext = JS_GetOpaque(this_val, gpac_class_id); + GF_SCENEJSExt *ext = JS_GetOpaque(this_val, scene_class_id); GF_Compositor *compositor = ext ? ext->compositor : NULL; if (!ext || !compositor) return JS_EXCEPTION; switch (magic) { - case GJS_GPAC_PROP_LAST_WORK_DIR: - if (!JS_IsString(value)) return JS_EXCEPTION; - prop_val = JS_ToCString(ctx, value); - gf_opts_set_key("General", "LastWorkingDir", prop_val); - JS_FreeCString(ctx, prop_val); - break; - case GJS_GPAC_PROP_CAPTION: + case GJS_SCENE_PROP_CAPTION: { GF_Event evt; if (!JS_IsString(value)) return JS_EXCEPTION; @@ -428,7 +328,7 @@ JS_FreeCString(ctx, prop_val); } break; - case GJS_GPAC_PROP_FULLSCREEN: + case GJS_SCENE_PROP_FULLSCREEN: /*no fullscreen for iOS (always on)*/ #ifndef GPAC_CONFIG_IOS bval = JS_ToBool(ctx, value); @@ -437,7 +337,7 @@ } #endif break; - case GJS_GPAC_PROP_VOLUME: + case GJS_SCENE_PROP_VOLUME: if (!JS_ToFloat64(ctx, &dval, value)) { gf_sc_set_option(compositor, GF_OPT_AUDIO_VOLUME, (u32) dval); } else if (!JS_ToInt32(ctx, &ival, value)) { @@ -445,26 +345,17 @@ } break; - case GJS_GPAC_PROP_NAVIGATION: + case GJS_SCENE_PROP_NAVIGATION: if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION; gf_sc_set_option(compositor, GF_OPT_NAVIGATION, (u32) ival); break; - case GJS_GPAC_PROP_NAVIGATION_TYPE: + case GJS_SCENE_PROP_NAVIGATION_TYPE: gf_sc_set_option(compositor, GF_OPT_NAVIGATION_TYPE, 0); break; - case GJS_GPAC_PROP_HTTP_MAX_RATE: - { - GF_DownloadManager *dm = gf_sc_get_downloader(compositor); - if (dm) { - if (JS_ToInt32(ctx, &ival, value)) return JS_EXCEPTION; - gf_dm_set_data_rate(dm, (u32) ival); - } - } - break; - case GJS_GPAC_PROP_FOCUS_HIGHLIGHT: + case GJS_SCENE_PROP_FOCUS_HIGHLIGHT: compositor->disable_focus_highlight = JS_ToBool(ctx, value); break; - case GJS_GPAC_PROP_SENSORS_ACTIVE: + case GJS_SCENE_PROP_SENSORS_ACTIVE: { GF_Event evt; compositor->orientation_sensors_active = JS_ToBool(ctx, value); @@ -482,13 +373,13 @@ return JS_UNDEFINED; } -static JSValue gpac_get_option(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_get_option(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *opt = NULL; const char *sec_name, *key_name; char arg_val[GF_PROP_DUMP_ARG_SIZE]; s32 idx = -1; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc < 2) return JS_EXCEPTION; if (!JS_IsString(argv[0])) return JS_EXCEPTION; @@ -525,10 +416,10 @@ return JS_NULL; } -static JSValue gpac_set_option(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_option(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *sec_name, *key_name, *key_val; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc < 3) return JS_EXCEPTION; if (!JS_IsString(argv[0])) return JS_EXCEPTION; @@ -554,39 +445,10 @@ } -static JSValue gpac_get_arg(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - u32 idx; - if (argc < 1) return JS_EXCEPTION; - - if (JS_ToInt32(ctx, &idx, argv[0])) - return JS_EXCEPTION; - - const char *arg = gf_sys_get_arg(idx); - if (arg) { - return JS_NewString(ctx, arg); - } - return JS_NULL; -} - -static JSValue gpac_set_arg_used(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - u32 idx; - Bool used; - if (argc < 2) return JS_EXCEPTION; - - if (JS_ToInt32(ctx, &idx, argv[0])) - return JS_EXCEPTION; - used = JS_ToBool(ctx, argv[1]); - - gf_sys_mark_arg_used(idx, used); - return JS_UNDEFINED; -} - -static JSValue gpac_set_back_color(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_back_color(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { u32 r, g, b, a, i; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc < 3) return JS_EXCEPTION; r = g = b = 0; @@ -615,9 +477,9 @@ } -static JSValue gpac_switch_quality(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_switch_quality(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc < 1) return JS_EXCEPTION; @@ -630,10 +492,10 @@ #if 0 //unused -static JSValue gpac_reload(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_reload(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_Event evt; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; memset(&evt, 0, sizeof(GF_Event)); @@ -643,10 +505,10 @@ } #endif -static JSValue gpac_navigation_supported(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_navigation_supported(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { u32 type; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc < 1) return JS_EXCEPTION; @@ -658,143 +520,11 @@ return JS_NewBool(ctx, gf_sc_navigation_supported(compositor, type) ? 1 : 0 ); } -typedef struct -{ - JSContext *c; - JSValue array; - Bool is_dir; - u32 idx; -} enum_dir_cbk; - -static Bool enum_dir_fct(void *cbck, char *file_name, char *file_path, GF_FileEnumInfo *file_info) -{ - u32 i, len; - char *sep; - JSValue s; - JSValue obj; - enum_dir_cbk *cbk = (enum_dir_cbk*)cbck; - - if (file_name && (file_name[0]=='.')) return 0; - - obj = JS_NewObject(cbk->c); - JS_SetPropertyStr(cbk->c, obj, "name", JS_NewString(cbk->c, file_name) ); - - sep=NULL; - len = (u32) strlen(file_path); - for (i=0; i<len; i++) { - sep = strchr("/\\", file_path[len-i-1]); - if (sep) { - sep = file_path+len-i-1; - break; - } - } - if (sep) { - sep[0] = '/'; - sep[1] = 0; - s = JS_NewString(cbk->c, file_path); - } else { - s = JS_NewString(cbk->c, file_path); - } - JS_SetPropertyStr(cbk->c, obj, "path", s); - - JS_SetPropertyStr(cbk->c, obj, "directory", JS_NewBool(cbk->c, cbk->is_dir) ); - JS_SetPropertyStr(cbk->c, obj, "drive", JS_NewBool(cbk->c, file_info->drive) ); - JS_SetPropertyStr(cbk->c, obj, "hidden", JS_NewBool(cbk->c, file_info->hidden) ); - JS_SetPropertyStr(cbk->c, obj, "system", JS_NewBool(cbk->c, file_info->system) ); - JS_SetPropertyStr(cbk->c, obj, "size", JS_NewInt64(cbk->c, file_info->size) ); - JS_SetPropertyStr(cbk->c, obj, "last_modified", JS_NewInt64(cbk->c, file_info->last_modified) ); - - JS_SetPropertyUint32(cbk->c, cbk->array, cbk->idx, obj); - cbk->idx++; - return 0; -} - -static JSValue gpac_enum_directory(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - GF_Err err; - enum_dir_cbk cbk; - char *url = NULL; - const char *dir = NULL; - const char *filter = NULL; - char *an_url; - Bool dir_only = 0; - Bool browse_root = 0; - GF_Compositor *compositor; - - if ((argc >= 1) && JS_IsString(argv[0])) { - dir = JS_ToCString(ctx, argv[0]); - if (!strcmp(dir, "/")) browse_root = 1; - } - if ((argc >= 2) && JS_IsString(argv[1])) { - filter = JS_ToCString(ctx, argv[1]); - if (!strcmp(filter, "dir")) { - dir_only = 1; - filter = NULL; - } else if (!strlen(filter)) { - JS_FreeCString(ctx, filter); - filter=NULL; - } - } - if ((argc >= 3) && JS_IsBool(argv[2])) { - if (JS_ToBool(ctx, argv[2])) { - url = gf_url_concatenate(dir, ".."); - if (dir && ( !strcmp(url, "..") || (url[0]==0) )) { - if ((dir[1]==':') && ((dir[2]=='/') || (dir[2]=='\\')) ) browse_root = 1; - else if (!strcmp(dir, "/")) browse_root = 1; - } - if (!strcmp(url, "/")) browse_root = 1; - } - } - - if ( (!dir || !strlen(dir) ) && (!url || !strlen(url))) browse_root = 1; - - if (browse_root) { - cbk.c = ctx; - cbk.idx = 0; - cbk.array = JS_NewArray(ctx); - if (JS_IsException(cbk.array)) return cbk.array; - cbk.is_dir = 1; - gf_enum_directory("/", 1, enum_dir_fct, &cbk, NULL); - if (url) gf_free(url); - JS_FreeCString(ctx, dir); - JS_FreeCString(ctx, filter); - return cbk.array; - } - - cbk.c = ctx; - cbk.array = JS_NewArray(ctx); - if (JS_IsException(cbk.array)) return cbk.array; - cbk.is_dir = 1; - cbk.idx = 0; - - compositor = gpac_get_compositor(ctx, this_val); - - /*concatenate with service url*/ - an_url = gf_url_concatenate(compositor->root_scene->root_od->scene_ns->url, url ? url : dir); - if (an_url) { - gf_free(url); - url = an_url; - } - err = gf_enum_directory(url ? url : dir, 1, enum_dir_fct, &cbk, NULL); - if (err) return JS_EXCEPTION; - - if (!dir_only) { - cbk.is_dir = 0; - err = gf_enum_directory(url ? url : dir, 0, enum_dir_fct, &cbk, filter); - if (err) return JS_EXCEPTION; - } - - if (url) gf_free(url); - JS_FreeCString(ctx, dir); - JS_FreeCString(ctx, filter); - return cbk.array; -} - -static JSValue gpac_set_size(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_size(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { Bool override_size_info = 0; u32 w, h; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (argc<2) return JS_EXCEPTION; @@ -833,10 +563,10 @@ } -static JSValue gpac_exit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_exit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_Event evt; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); memset(&evt, 0, sizeof(GF_Event)); evt.type = GF_EVENT_QUIT; if (argc) @@ -846,10 +576,10 @@ return JS_UNDEFINED; } -static JSValue gpac_set_3d(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_3d(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { Bool type_3d; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!argc) return JS_EXCEPTION; type_3d = JS_ToBool(ctx, argv[0]); @@ -861,10 +591,10 @@ return JS_UNDEFINED; } -static JSValue gpac_move_window(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_move_window(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_Event evt; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (argc < 2) return JS_EXCEPTION; evt.type = GF_EVENT_MOVE; @@ -882,20 +612,11 @@ } -static JSValue gpac_error_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - GF_Err e; - if (argc < 1) return JS_EXCEPTION; - if (JS_ToInt32(ctx, (int32_t *) &e, argv[0])) - return JS_EXCEPTION; - return JS_NewString(ctx, gf_error_to_string(e) ); -} - #if 0 //unused -static JSValue gpac_get_scene_time(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_get_scene_time(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_SceneGraph *sg = NULL; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor) return JS_EXCEPTION; if (!argc || !JS_IsObject(argv[0]) ) { @@ -908,10 +629,10 @@ } #endif -static JSValue gpac_trigger_gc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_trigger_gc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_SceneGraph *sg; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); sg = compositor->root_scene->graph; sg->trigger_gc = GF_TRUE; return JS_UNDEFINED; @@ -1415,6 +1136,32 @@ return JS_NULL; } +GF_Filter *jsff_get_filter(JSContext *c, JSValue this_val); + +static JSValue gjs_odm_in_parent_chain(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + Bool res; + GF_Filter *f; + GF_Scene *scene; + GF_ObjectManager *odm = JS_GetOpaque(this_val, odm_class_id); + if (!odm || !argc) return JS_EXCEPTION; + + f = jsff_get_filter(ctx, argv[0]); + if (!f) return JS_EXCEPTION; + + scene = odm->subscene ? odm->subscene : odm->parentscene; + if (!scene) return JS_EXCEPTION; + if (gf_filter_in_parent_chain(f, scene->compositor->filter)) + return JS_FALSE; + + if (odm->pid) { + res = gf_filter_pid_is_filter_in_parents(odm->pid, f); + } else { + res = gf_filter_in_parent_chain(f, odm->scene_ns->source_filter); + } + return res ? JS_TRUE : JS_FALSE; +} + static JSValue gjs_odm_select_quality(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { s32 idx = -1; @@ -1582,16 +1329,16 @@ return JS_UNDEFINED; } -static JSValue gpac_get_object_manager(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_get_object_manager(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue anobj; u32 i, count; GF_ObjectManager *odm = NULL; const char *service_url = NULL; - GF_GPACJSExt *gjs = JS_GetOpaque(this_val, gpac_class_id); - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_SCENEJSExt *sjs = JS_GetOpaque(this_val, scene_class_id); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); GF_Scene *scene = compositor->root_scene; - if (!gjs) return JS_EXCEPTION; + if (!sjs) return JS_EXCEPTION; if (JS_IsString(argv[0]) ) { const char *url; @@ -1635,9 +1382,9 @@ static JSValue gpacevt_getProperty(JSContext *ctx, JSValueConst this_val, int magic) { - GF_GPACJSExt *gjs = JS_GetOpaque(this_val, gpacevt_class_id); - if (!gjs || !gjs->evt) return JS_EXCEPTION; - GF_Event *evt = gjs->evt; + GF_SCENEJSExt *sjs = JS_GetOpaque(this_val, gpacevt_class_id); + if (!sjs || !sjs->evt) return JS_EXCEPTION; + GF_Event *evt = sjs->evt; switch (magic) { case GJS_EVT_PROP_KEYCODE: @@ -1652,9 +1399,9 @@ case GJS_EVT_PROP_MOUSE_Y: return JS_NewInt32(ctx, evt->mouse.y); case GJS_EVT_PROP_PICKED: - if (gjs->compositor->hit_appear) return JS_NewBool(ctx, 1); - else if (gf_list_count(gjs->compositor->previous_sensors) ) return JS_NewBool(ctx, 1); - else if (gjs->compositor->text_selection) return JS_NewBool(ctx, 1); + if (sjs->compositor->hit_appear) return JS_NewBool(ctx, 1); + else if (gf_list_count(sjs->compositor->previous_sensors) ) return JS_NewBool(ctx, 1); + else if (sjs->compositor->text_selection) return JS_NewBool(ctx, 1); else return JS_NewBool(ctx, 0); case GJS_EVT_PROP_WHEEL: @@ -1691,24 +1438,24 @@ return JS_UNDEFINED; } -static Bool gjs_event_filter_process(GF_GPACJSExt *gjs, GF_Event *evt) +static Bool gjs_event_filter_process(GF_SCENEJSExt *sjs, GF_Event *evt) { s32 res; JSValue rval; - gjs->evt = evt; - JS_SetOpaque(gjs->evt_obj, gjs); - rval = JS_Call(gjs->c, gjs->evt_fun, gjs->evt_filter_obj, 1, &gjs->evt_obj); - JS_SetOpaque(gjs->evt_obj, NULL); - gjs->evt = NULL; + sjs->evt = evt; + JS_SetOpaque(sjs->evt_obj, sjs); + rval = JS_Call(sjs->c, sjs->evt_fun, sjs->evt_filter_obj, 1, &sjs->evt_obj); + JS_SetOpaque(sjs->evt_obj, NULL); + sjs->evt = NULL; res = 0; if (JS_IsBool(rval)) - res = JS_ToBool(gjs->c, rval); + res = JS_ToBool(sjs->c, rval); else if (JS_IsNumber(rval)) - JS_ToInt32(gjs->c, &res, rval); + JS_ToInt32(sjs->c, &res, rval); - JS_FreeValue(gjs->c, rval); + JS_FreeValue(sjs->c, rval); return res ? GF_TRUE : GF_FALSE; } @@ -1716,75 +1463,75 @@ { u32 lock_fail; Bool res; - GF_GPACJSExt *gjs = (GF_GPACJSExt *)udta; + GF_SCENEJSExt *sjs = (GF_SCENEJSExt *)udta; if (consumed_by_compositor) return 0; - if (gjs->evt != NULL) return 0; + if (sjs->evt != NULL) return 0; lock_fail=0; - res = gf_mx_try_lock(gjs->compositor->mx); + res = gf_mx_try_lock(sjs->compositor->mx); if (!res) { lock_fail=1; } else { - res = gf_js_try_lock(gjs->c); + res = gf_js_try_lock(sjs->c); if (!res) lock_fail=2; } if (lock_fail) { GF_Event *evt_clone; - gf_mx_p(gjs->event_mx); + gf_mx_p(sjs->event_mx); evt_clone = gf_malloc(sizeof(GF_Event)); memcpy(evt_clone, evt, sizeof(GF_Event)); - gf_list_add(gjs->event_queue, evt_clone); - GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[GPACJS] Couldn't lock % mutex, queing event\n", (lock_fail==2) ? "JavaScript" : "Compositor")); - gf_mx_v(gjs->event_mx); + gf_list_add(sjs->event_queue, evt_clone); + GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[SCENEJS] Couldn't lock % mutex, queing event\n", (lock_fail==2) ? "JavaScript" : "Compositor")); + gf_mx_v(sjs->event_mx); if (lock_fail==2){ - gf_mx_v(gjs->compositor->mx); + gf_mx_v(sjs->compositor->mx); } return 0; } - gf_mx_p(gjs->event_mx); - while (gf_list_count(gjs->event_queue)) { - GF_Event *an_evt = (GF_Event *) gf_list_pop_front(gjs->event_queue); - gjs_event_filter_process(gjs, an_evt); + gf_mx_p(sjs->event_mx); + while (gf_list_count(sjs->event_queue)) { + GF_Event *an_evt = (GF_Event *) gf_list_pop_front(sjs->event_queue); + gjs_event_filter_process(sjs, an_evt); gf_free(an_evt); } - gf_mx_v(gjs->event_mx); + gf_mx_v(sjs->event_mx); - res = gjs_event_filter_process(gjs, evt); + res = gjs_event_filter_process(sjs, evt); - gf_mx_v(gjs->compositor->mx); - gf_js_lock(gjs->c, 0); + gf_mx_v(sjs->compositor->mx); + gf_js_lock(sjs->c, 0); return res; } -static JSValue gpac_set_event_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_event_filter(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - GF_GPACJSExt *gjs = JS_GetOpaque(this_val, gpac_class_id); - if (!gjs || !argc) + GF_SCENEJSExt *sjs = JS_GetOpaque(this_val, scene_class_id); + if (!sjs || !argc) return JS_EXCEPTION; if (!JS_IsNull(argv[0]) && !JS_IsUndefined(argv[0]) && !JS_IsFunction(ctx, argv[0])) return JS_EXCEPTION; - JS_FreeValue(gjs->c, gjs->evt_fun); - gjs->evt_fun = JS_DupValue(ctx, argv[0]); - gjs->evt_filter_obj = this_val; - gjs->c = ctx; - gjs->evt_filter.udta = gjs; - gjs->evt_filter.on_event = gjs_event_filter; + JS_FreeValue(sjs->c, sjs->evt_fun); + sjs->evt_fun = JS_DupValue(ctx, argv[0]); + sjs->evt_filter_obj = this_val; + sjs->c = ctx; + sjs->evt_filter.udta = sjs; + sjs->evt_filter.on_event = gjs_event_filter; - gf_filter_add_event_listener(gjs->compositor->filter, &gjs->evt_filter); + gf_filter_add_event_listener(sjs->compositor->filter, &sjs->evt_filter); return JS_UNDEFINED; } GF_Node *gf_sg_js_get_node(struct JSContext *c, JSValue obj); -static JSValue gpac_set_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_set_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_Node *elt; - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor || !argc) return JS_EXCEPTION; if (JS_IsNull(argv[0])) { @@ -1810,7 +1557,7 @@ } #if 0 //unused -static JSValue gpac_get_scene(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_get_scene(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { GF_Node *elt; u32 w, h; @@ -1819,8 +1566,8 @@ GF_SceneGraph *sg; #endif GF_Scene *scene=NULL; - GF_GPACJSExt *gjs = (GF_GPACJSExt *)JS_GetOpaque(this_val, gpac_class_id); - if (!gjs || !argc || !JS_IsObject(argv[0])) return JS_EXCEPTION; + GF_SCENEJSExt *sjs = (GF_SCENEJSExt *)JS_GetOpaque(this_val, scene_class_id); + if (!sjs || !argc || !JS_IsObject(argv[0])) return JS_EXCEPTION; elt = gf_sg_js_get_node(ctx, argv[0]); if (!elt) return JS_EXCEPTION; @@ -1860,9 +1607,9 @@ } #endif -static JSValue gpac_show_keyboard(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +static JSValue scenejs_show_keyboard(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - GF_Compositor *compositor = gpac_get_compositor(ctx, this_val); + GF_Compositor *compositor = scenejs_get_compositor(ctx, this_val); if (!compositor || !argc) return JS_EXCEPTION; GF_Event evt; @@ -1872,7 +1619,7 @@ return JS_UNDEFINED; } -static const JSCFunctionListEntry gpac_evt_funcs[] = { +static const JSCFunctionListEntry scenejs_evt_funcs[] = { JS_CGETSET_MAGIC_DEF("keycode", gpacevt_getProperty, NULL, GJS_EVT_PROP_KEYCODE), JS_CGETSET_MAGIC_DEF("mouse_x", gpacevt_getProperty, NULL, GJS_EVT_PROP_MOUSE_X), JS_CGETSET_MAGIC_DEF("mouse_y", gpacevt_getProperty, NULL, GJS_EVT_PROP_MOUSE_Y), @@ -1886,60 +1633,42 @@ JS_CGETSET_MAGIC_DEF("dropfiles", gpacevt_getProperty, NULL, GJS_EVT_PROP_FILES), }; -static const JSCFunctionListEntry gpac_funcs[] = { - JS_CGETSET_MAGIC_DEF("last_working_directory", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_LAST_WORK_DIR), - JS_CGETSET_MAGIC_DEF("batteryOn", gpac_getProperty, NULL, GJS_GPAC_PROP_BATTERY_ON), - JS_CGETSET_MAGIC_DEF("batteryCharging", gpac_getProperty, NULL, GJS_GPAC_PROP_BATTERY_CHARGE), - JS_CGETSET_MAGIC_DEF("batteryPercent", gpac_getProperty, NULL, GJS_GPAC_PROP_BATTERY_PERCENT), - JS_CGETSET_MAGIC_DEF("batteryLifeTime", gpac_getProperty, NULL, GJS_GPAC_PROP_BATTERY_LIFETIME), - JS_CGETSET_MAGIC_DEF("batteryFullLifeTime", gpac_getProperty, NULL, GJS_GPAC_PROP_BATTERY_LIFETIME_FULL), - JS_CGETSET_MAGIC_DEF("hostname", gpac_getProperty, NULL, GJS_GPAC_PROP_HOSTNAME), - JS_CGETSET_MAGIC_DEF("fullscreen", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_FULLSCREEN), - JS_CGETSET_MAGIC_DEF("current_path", gpac_getProperty, NULL, GJS_GPAC_PROP_CURRENT_PATH), - JS_CGETSET_MAGIC_DEF("volume", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_VOLUME), - JS_CGETSET_MAGIC_DEF("navigation", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_NAVIGATION), - JS_CGETSET_MAGIC_DEF("navigation_type", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_NAVIGATION_TYPE), - JS_CGETSET_MAGIC_DEF("hardware_yuv", gpac_getProperty, NULL, GJS_GPAC_PROP_HARDWARE_YUV), - JS_CGETSET_MAGIC_DEF("hardware_rgb", gpac_getProperty, NULL, GJS_GPAC_PROP_HARDWARE_RGB), - JS_CGETSET_MAGIC_DEF("hardware_rgba", gpac_getProperty, NULL, GJS_GPAC_PROP_HARDWARE_RGBA), - JS_CGETSET_MAGIC_DEF("hardware_stretch", gpac_getProperty, NULL, GJS_GPAC_PROP_HARDWARE_STRETCH), - JS_CGETSET_MAGIC_DEF("screen_width", gpac_getProperty, NULL, GJS_GPAC_PROP_SCREEN_WIDTH), - JS_CGETSET_MAGIC_DEF("screen_height", gpac_getProperty, NULL, GJS_GPAC_PROP_SCREEN_HEIGHT), - JS_CGETSET_MAGIC_DEF("http_max_bitrate", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_HTTP_MAX_RATE), - JS_CGETSET_MAGIC_DEF("http_bitrate", gpac_getProperty, NULL, GJS_GPAC_PROP_HTTP_RATE), - JS_CGETSET_MAGIC_DEF("fps", gpac_getProperty, NULL, GJS_GPAC_PROP_FPS), - JS_CGETSET_MAGIC_DEF("sim_fps", gpac_getProperty, NULL, GJS_GPAC_PROP_SIM_FPS), - JS_CGETSET_MAGIC_DEF("has_opengl", gpac_getProperty, NULL, GJS_GPAC_PROP_HAS_OPENGL), - JS_CGETSET_MAGIC_DEF("cpu", gpac_getProperty, NULL, GJS_GPAC_PROP_CPU), - JS_CGETSET_MAGIC_DEF("nb_cores", gpac_getProperty, NULL, GJS_GPAC_PROP_NB_CORES), - JS_CGETSET_MAGIC_DEF("system_memory", gpac_getProperty, NULL, GJS_GPAC_PROP_MEMORY_SYSTEM), - JS_CGETSET_MAGIC_DEF("memory", gpac_getProperty, NULL, GJS_GPAC_PROP_MEMORY), - JS_CGETSET_MAGIC_DEF("argc", gpac_getProperty, NULL, GJS_GPAC_PROP_ARGC), - JS_CGETSET_MAGIC_DEF("caption", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_CAPTION), - JS_CGETSET_MAGIC_DEF("focus_highlight", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_FOCUS_HIGHLIGHT), - JS_CGETSET_MAGIC_DEF("dpi_x", gpac_getProperty, NULL, GJS_GPAC_PROP_DPI_X), - JS_CGETSET_MAGIC_DEF("dpi_y", gpac_getProperty, NULL, GJS_GPAC_PROP_DPI_Y), - JS_CGETSET_MAGIC_DEF("sensors_active", gpac_getProperty, gpac_setProperty, GJS_GPAC_PROP_SENSORS_ACTIVE), - JS_CGETSET_MAGIC_DEF("zoom", gpac_getProperty, NULL, GJS_GPAC_PROP_ZOOM), - JS_CGETSET_MAGIC_DEF("text_selection", gpac_getProperty, NULL, GJS_GPAC_PROP_TEXT_SEL), - JS_CFUNC_DEF("get_option", 0, gpac_get_option), - JS_CFUNC_DEF("set_option", 0, gpac_set_option), - JS_CFUNC_DEF("get_arg", 0, gpac_get_arg), - JS_CFUNC_DEF("set_arg_used", 0, gpac_set_arg_used), - JS_CFUNC_DEF("enum_directory", 0, gpac_enum_directory), - JS_CFUNC_DEF("set_size", 0, gpac_set_size), - JS_CFUNC_DEF("exit", 0, gpac_exit), - JS_CFUNC_DEF("set_3d", 0, gpac_set_3d), - JS_CFUNC_DEF("move_window", 0, gpac_move_window), - JS_CFUNC_DEF("set_event_filter", 0, gpac_set_event_filter), - JS_CFUNC_DEF("set_focus", 0, gpac_set_focus), - JS_CFUNC_DEF("error_string", 0, gpac_error_string), - JS_CFUNC_DEF("show_keyboard", 0, gpac_show_keyboard), - JS_CFUNC_DEF("trigger_gc", 0, gpac_trigger_gc), - JS_CFUNC_DEF("get_object_manager", 0, gpac_get_object_manager), - JS_CFUNC_DEF("switch_quality", 0, gpac_switch_quality), - JS_CFUNC_DEF("navigation_supported", 0, gpac_navigation_supported), - JS_CFUNC_DEF("set_back_color", 0, gpac_set_back_color) +static const JSCFunctionListEntry scenejs_funcs[] = { + JS_CGETSET_MAGIC_DEF("fullscreen", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_FULLSCREEN), + JS_CGETSET_MAGIC_DEF("current_path", scenejs_getProperty, NULL, GJS_SCENE_PROP_CURRENT_PATH), + JS_CGETSET_MAGIC_DEF("volume", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_VOLUME), + JS_CGETSET_MAGIC_DEF("navigation", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_NAVIGATION), + JS_CGETSET_MAGIC_DEF("navigation_type", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_NAVIGATION_TYPE), + JS_CGETSET_MAGIC_DEF("hardware_yuv", scenejs_getProperty, NULL, GJS_SCENE_PROP_HARDWARE_YUV), + JS_CGETSET_MAGIC_DEF("hardware_rgb", scenejs_getProperty, NULL, GJS_SCENE_PROP_HARDWARE_RGB), + JS_CGETSET_MAGIC_DEF("hardware_rgba", scenejs_getProperty, NULL, GJS_SCENE_PROP_HARDWARE_RGBA), + JS_CGETSET_MAGIC_DEF("hardware_stretch", scenejs_getProperty, NULL, GJS_SCENE_PROP_HARDWARE_STRETCH), + JS_CGETSET_MAGIC_DEF("screen_width", scenejs_getProperty, NULL, GJS_SCENE_PROP_SCREEN_WIDTH), + JS_CGETSET_MAGIC_DEF("screen_height", scenejs_getProperty, NULL, GJS_SCENE_PROP_SCREEN_HEIGHT), + JS_CGETSET_MAGIC_DEF("fps", scenejs_getProperty, NULL, GJS_SCENE_PROP_FPS), + JS_CGETSET_MAGIC_DEF("sim_fps", scenejs_getProperty, NULL, GJS_SCENE_PROP_SIM_FPS), + JS_CGETSET_MAGIC_DEF("has_opengl", scenejs_getProperty, NULL, GJS_SCENE_PROP_HAS_OPENGL), + JS_CGETSET_MAGIC_DEF("caption", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_CAPTION), + JS_CGETSET_MAGIC_DEF("focus_highlight", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_FOCUS_HIGHLIGHT), + JS_CGETSET_MAGIC_DEF("dpi_x", scenejs_getProperty, NULL, GJS_SCENE_PROP_DPI_X), + JS_CGETSET_MAGIC_DEF("dpi_y", scenejs_getProperty, NULL, GJS_SCENE_PROP_DPI_Y), + JS_CGETSET_MAGIC_DEF("sensors_active", scenejs_getProperty, scenejs_setProperty, GJS_SCENE_PROP_SENSORS_ACTIVE), + JS_CGETSET_MAGIC_DEF("zoom", scenejs_getProperty, NULL, GJS_SCENE_PROP_ZOOM), + JS_CGETSET_MAGIC_DEF("text_selection", scenejs_getProperty, NULL, GJS_SCENE_PROP_TEXT_SEL), + JS_CFUNC_DEF("get_option", 0, scenejs_get_option), + JS_CFUNC_DEF("set_option", 0, scenejs_set_option), + JS_CFUNC_DEF("set_size", 0, scenejs_set_size), + JS_CFUNC_DEF("exit", 0, scenejs_exit), + JS_CFUNC_DEF("set_3d", 0, scenejs_set_3d), + JS_CFUNC_DEF("move_window", 0, scenejs_move_window), + JS_CFUNC_DEF("set_event_filter", 0, scenejs_set_event_filter), + JS_CFUNC_DEF("set_focus", 0, scenejs_set_focus), + JS_CFUNC_DEF("show_keyboard", 0, scenejs_show_keyboard), + JS_CFUNC_DEF("trigger_gc", 0, scenejs_trigger_gc), + JS_CFUNC_DEF("get_object_manager", 0, scenejs_get_object_manager), + JS_CFUNC_DEF("switch_quality", 0, scenejs_switch_quality), + JS_CFUNC_DEF("navigation_supported", 0, scenejs_navigation_supported), + JS_CFUNC_DEF("set_back_color", 0, scenejs_set_back_color) }; static const JSCFunctionListEntry odm_funcs[] = { @@ -2008,55 +1737,60 @@ JS_CFUNC_DEF("disable_main_addon", 0, gjs_odm_disable_main_addon), JS_CFUNC_DEF("select", 0, gjs_odm_select), JS_CFUNC_DEF("get_srd", 0, gjs_odm_get_srd), + JS_CFUNC_DEF("in_parent_chain", 0, gjs_odm_in_parent_chain), }; -static void gpac_js_finalize(JSRuntime *rt, JSValue obj) +#include "../filter_core/filter_session.h" + +static void scenejs_finalize(JSRuntime *rt, JSValue obj) { - GF_GPACJSExt *gjs = JS_GetOpaque(obj, gpac_class_id); - if (!gjs) return; + GF_SCENEJSExt *sjs = JS_GetOpaque(obj, scene_class_id); + if (!sjs) return; JS_SetOpaque(obj, NULL); - while (gf_list_count(gjs->storages)) { - GF_Config *cfg = (GF_Config *) gf_list_pop_back(gjs->storages); + while (gf_list_count(sjs->storages)) { + GF_Config *cfg = (GF_Config *) gf_list_pop_back(sjs->storages); gf_cfg_discard_changes(cfg); gf_cfg_del(cfg); } - gf_list_del(gjs->storages); + gf_list_del(sjs->storages); - while (gf_list_count(gjs->event_queue)) { - GF_Event *evt = (GF_Event *) gf_list_pop_back(gjs->event_queue); + while (gf_list_count(sjs->event_queue)) { + GF_Event *evt = (GF_Event *) gf_list_pop_back(sjs->event_queue); gf_free(evt); } - gf_list_del(gjs->event_queue); - gf_mx_del(gjs->event_mx); + gf_list_del(sjs->event_queue); + gf_mx_del(sjs->event_mx); + if (sjs->compositor && sjs->compositor->filter) { + gf_fs_unload_script(sjs->compositor->filter->session, NULL); + } /*if we destroy the script context holding the gpac event filter (only one for the time being), remove the filter*/ - JS_FreeValueRT(rt, gjs->evt_fun); - if (gjs->evt_filter.udta) { - gf_filter_remove_event_listener(gjs->compositor->filter, &gjs->evt_filter); - gjs->evt_filter.udta = NULL; + JS_FreeValueRT(rt, sjs->evt_fun); + if (sjs->evt_filter.udta) { + gf_filter_remove_event_listener(sjs->compositor->filter, &sjs->evt_filter); + sjs->evt_filter.udta = NULL; } - gf_free(gjs); + gf_free(sjs); } static int js_scene_init(JSContext *c, JSModuleDef *m) { GF_JSAPIParam par; - GF_GPACJSExt *gjs; - GF_SAFEALLOC(gjs, GF_GPACJSExt); + GF_SCENEJSExt *sjs; + GF_SAFEALLOC(sjs, GF_SCENEJSExt); GF_SceneGraph *scene; - if (!gjs) { + if (!sjs) { return -1; } - gjs->rti_refresh_rate = GPAC_JS_RTI_REFRESH_RATE; - gjs->storages = gf_list_new(); - gjs->event_queue = gf_list_new(); - gjs->event_mx = gf_mx_new("GPACJSEvt"); - gjs->evt_fun = JS_UNDEFINED; - gjs->gpac_obj = JS_UNDEFINED; - gjs->evt_obj = JS_UNDEFINED; + sjs->storages = gf_list_new(); + sjs->event_queue = gf_list_new(); + sjs->event_mx = gf_mx_new("GPACJSEvt"); + sjs->evt_fun = JS_UNDEFINED; + sjs->scene_obj = JS_UNDEFINED; + sjs->evt_obj = JS_UNDEFINED; scene = JS_GetContextOpaque(c); if (!scene) return -1; @@ -2065,9 +1799,9 @@ scene = n->sgprivate->scenegraph; } - if (!gpac_class_id) { - JS_NewClassID(&gpac_class_id); - JS_NewClass(JS_GetRuntime(c), gpac_class_id, &gpacClass); + if (!scene_class_id) { + JS_NewClassID(&scene_class_id); + JS_NewClass(JS_GetRuntime(c), scene_class_id, &sceneClass); JS_NewClassID(&odm_class_id); JS_NewClass(JS_GetRuntime(c), odm_class_id, &odmClass); @@ -2084,21 +1818,28 @@ JSValue global = JS_GetGlobalObject(c); - gjs->gpac_obj = JS_NewObjectClass(c, gpac_class_id); - JS_SetPropertyFunctionList(c, gjs->gpac_obj, gpac_funcs, countof(gpac_funcs)); - JS_SetOpaque(gjs->gpac_obj, gjs); -// JS_SetPropertyStr(c, global, "gpac", gjs->gpac_obj); + sjs->scene_obj = JS_NewObjectClass(c, scene_class_id); + JS_SetPropertyFunctionList(c, sjs->scene_obj, scenejs_funcs, countof(scenejs_funcs)); + JS_SetOpaque(sjs->scene_obj, sjs); +// JS_SetPropertyStr(c, global, "gpac", sjs->scene_obj); if (scene->script_action) { if (scene->script_action(scene->script_action_cbck, GF_JSAPI_OP_GET_COMPOSITOR, scene->RootNode, &par)) { - gjs->compositor = par.compositor; + sjs->compositor = par.compositor; } } + if (sjs->compositor && sjs->compositor->filter) { + GF_Err gf_fs_load_js_api(JSContext *c, GF_FilterSession *fs); + GF_FilterSession *fs = sjs->compositor->filter->session; + + //don't check error code, this may fail if global JS has been set but the script may still run + gf_fs_load_js_api(c, fs); + } - gjs->evt_obj = JS_NewObjectClass(c, gpacevt_class_id); - JS_SetPropertyFunctionList(c, gjs->evt_obj, gpac_evt_funcs, countof(gpac_evt_funcs)); - JS_SetOpaque(gjs->evt_obj, NULL); - JS_SetPropertyStr(c, global, "gpacevt", gjs->evt_obj); + sjs->evt_obj = JS_NewObjectClass(c, gpacevt_class_id); + JS_SetPropertyFunctionList(c, sjs->evt_obj, scenejs_evt_funcs, countof(scenejs_evt_funcs)); + JS_SetOpaque(sjs->evt_obj, NULL); + JS_SetPropertyStr(c, global, "gpacevt", sjs->evt_obj); #define DECLARE_CONST(_val) \ JS_SetPropertyStr(c, global, #_val, JS_NewInt32(c, _val)); @@ -2142,7 +1883,7 @@ JS_FreeValue(c, global); - JS_SetModuleExport(c, m, "gpac", gjs->gpac_obj); + JS_SetModuleExport(c, m, "scene", sjs->scene_obj); return 0; } @@ -2153,7 +1894,7 @@ m = JS_NewCModule(ctx, "scenejs", js_scene_init); if (!m) return; - JS_AddModuleExport(ctx, m, "gpac"); + JS_AddModuleExport(ctx, m, "scene"); return; }
View file
gpac-1.0.0.tar.gz/src/jsmods/webgl.c -> gpac-1.0.1.tar.gz/src/jsmods/webgl.c
Changed
@@ -1015,7 +1015,7 @@ namelen = (u32) strlen(named_tx->tx_name); while (a_source) { - char *loc = strstr(source, "texture2D"); + char *loc = strstr(a_source, "texture2D"); if (!loc) break; loc += 9; while (loc[0] && strchr(" (\n\t", loc[0])) loc++; @@ -1029,28 +1029,24 @@ } if (has_gptx) { - char *o_src; - char *main_fn = NULL; - char *start = strstr(source, "void main("); - if (!start) { - JS_FreeCString(ctx, source); - return js_throw_err_msg(ctx, WGL_INVALID_VALUE, "Missing main in shader"); - } - start[0] = 0; - //strip all sample2D declarations for GPACTextures + char *o_src, *start; + char *gf_source_pass1 = NULL; + + //first pass, strip all sample2D declarations for GPACTextures, replace with our own o_src = source; while (o_src) { char c; + GF_WebGLNamedTexture *named_tx=NULL; Bool found = GF_FALSE; char *sep, *start = strstr(o_src, "uniform sampler2D "); if (!start) { - gf_dynstrcat(&gf_source, o_src, NULL); + gf_dynstrcat(&gf_source_pass1, o_src, NULL); break; } sep = start + strlen("uniform sampler2D "); for (i=0; i<count; i++) { u32 namelen; - GF_WebGLNamedTexture *named_tx = gf_list_get(glc->named_textures, i); + named_tx = gf_list_get(glc->named_textures, i); namelen = (u32) strlen(named_tx->tx_name); if (strncmp(sep, named_tx->tx_name, namelen)) continue; @@ -1058,24 +1054,34 @@ sep += namelen; while (sep[0] && strchr(" ;", sep[0])) sep++; start[0] = 0; - gf_dynstrcat(&gf_source, o_src, NULL); + gf_dynstrcat(&gf_source_pass1, o_src, NULL); start[0] = 'u'; o_src = sep; found = GF_TRUE; break; } - if (found) break; } - if (found) continue; + if (found) { + //named texture but unknown pixel format, cannot create shader + if (!named_tx->tx.pix_fmt) { + JSValue ret = js_throw_err_msg(ctx, WGL_INVALID_VALUE, "NamedTexture %s pixel format undefined, cannot create shader", named_tx->tx_name); + JS_FreeCString(ctx, source); + gf_free(gf_source); + return ret; + } + //insert our uniform declaration and code + if (gf_gl_txw_insert_fragment_shader(named_tx->tx.pix_fmt, named_tx->tx_name, &gf_source_pass1)) + named_tx->shader_attached = GF_TRUE; + continue; + } c = sep[0]; sep[0] = 0; - gf_dynstrcat(&gf_source, o_src, NULL); + gf_dynstrcat(&gf_source_pass1, o_src, NULL); sep[0] = c; o_src = sep; } - - start[0] = 'v'; - + //second pass, replace all texture2D(NamedTX, ..) with our calls + start = gf_source_pass1; while (start && start[0]) { char c; char *next; @@ -1083,7 +1089,7 @@ char *end_gfTx; char *has_gfTx = strstr(start, "texture2D"); if (!has_gfTx) { - gf_dynstrcat(&main_fn, start, NULL); + gf_dynstrcat(&gf_source, start, NULL); break; } @@ -1102,42 +1108,33 @@ if (!named_tx) { next[0] = c; has_gfTx[0] = 0; - gf_dynstrcat(&main_fn, start, NULL); + gf_dynstrcat(&gf_source, start, NULL); has_gfTx[0] = 't'; - gf_dynstrcat(&main_fn, "texture2D", NULL); + gf_dynstrcat(&gf_source, "texture2D", NULL); start = has_gfTx + 9; continue; } - //named texture but unknown pixel format, cannot create shader - if (!named_tx->tx.pix_fmt) { - JSValue ret = js_throw_err_msg(ctx, WGL_INVALID_VALUE, "NamedTexture %s pixel format undefined, cannot create shader", has_gfTx); - JS_FreeCString(ctx, source); - gf_free(gf_source); - return ret; - } next[0] = c; has_gfTx[0] = 0; - gf_dynstrcat(&main_fn, start, NULL); + gf_dynstrcat(&gf_source, start, NULL); has_gfTx[0] = 't'; - gf_dynstrcat(&main_fn, named_tx->tx_name, NULL); - gf_dynstrcat(&main_fn, "_sample(", NULL); + gf_dynstrcat(&gf_source, named_tx->tx_name, NULL); + gf_dynstrcat(&gf_source, "_sample(", NULL); while (next[0] && strchr(" ,", next[0])) next++; - if (gf_gl_txw_insert_fragment_shader(named_tx->tx.pix_fmt, named_tx->tx_name, &gf_source)) - named_tx->shader_attached = GF_TRUE; - start = next; } - gf_dynstrcat(&gf_source, main_fn, NULL); - gf_free(main_fn); + gf_free(gf_source_pass1); final_source = gf_source; } else { final_source = source; } len = (u32) strlen(final_source); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONSOLE, ("[WebGL] Shader rewritten as\n%s", final_source)); + glShaderSource(shader, 1, &final_source, &len); JS_FreeCString(ctx, source);
View file
gpac-1.0.0.tar.gz/src/jsmods/xhr.c -> gpac-1.0.1.tar.gz/src/jsmods/xhr.c
Changed
@@ -156,9 +156,10 @@ /* dom graph in which the XHR is created */ GF_SceneGraph *owning_graph; +#ifndef GPAC_DISABLE_SVG /* dom graph used to parse XML into */ GF_SceneGraph *document; - +#endif Bool js_dom_loaded; }; @@ -326,13 +327,14 @@ gf_list_del(ctx->node_stack); ctx->node_stack = NULL; } +#ifndef GPAC_DISABLE_SVG if (ctx->document) { if (ctx->js_dom_loaded) { dom_js_unload(); ctx->js_dom_loaded = GF_FALSE; } - gf_node_unregister(ctx->document->RootNode, NULL); + /*we're sure the graph is a "nomade" one since we initially put the refcount to 1 ourselves*/ ctx->document->reference_count--; if (!ctx->document->reference_count) { @@ -341,6 +343,7 @@ } } ctx->document = NULL; +#endif ctx->size = 0; ctx->async = GF_FALSE; ctx->readyState = XHR_READYSTATE_UNSENT; @@ -360,8 +363,10 @@ JS_FreeValueRT(rt, ctx->onreadystatechange); JS_FreeValueRT(rt, ctx->ontimeout); xml_http_reset(ctx); +#ifndef GPAC_DISABLE_SVG if (ctx->event_target) gf_dom_event_target_del(ctx->event_target); +#endif gf_free(ctx); } @@ -375,6 +380,7 @@ return scene; } +#ifndef GPAC_DISABLE_SVG void xhr_get_event_target(JSContext *c, JSValue obj, GF_SceneGraph **sg, GF_DOMEventTarget **target) { if (c) { @@ -385,8 +391,8 @@ *sg = xml_get_scenegraph(c); *target = ctx->event_target; } - } +#endif static JSValue xml_http_constructor(JSContext *c, JSValueConst new_target, int argc, JSValueConst *argv) { @@ -402,8 +408,10 @@ p->c = c; p->_this = obj; p->owning_graph = xml_get_scenegraph(c); +#ifndef GPAC_DISABLE_SVG if (p->owning_graph) p->event_target = gf_dom_event_target_new(GF_DOM_EVENT_TARGET_XHR, p); +#endif p->onabort = JS_NULL; p->onerror = JS_NULL; @@ -420,6 +428,7 @@ static void xml_http_fire_event(XMLHTTPContext *ctx, GF_EventType evtType) { +#ifndef GPAC_DISABLE_SVG GF_DOM_Event xhr_evt; if (!ctx->event_target) return; @@ -429,8 +438,10 @@ xhr_evt.target = ctx->event_target->ptr; xhr_evt.target_type = ctx->event_target->ptr_type; gf_sg_fire_dom_event(ctx->event_target, &xhr_evt, ctx->owning_graph, NULL); +#endif } + static void xml_http_state_change(XMLHTTPContext *ctx) { #ifndef GPAC_DISABLE_VRML @@ -556,6 +567,9 @@ JS_FreeCString(c, val); return JS_TRUE; } + +#ifndef GPAC_DISABLE_SVG + static void xml_http_sax_start(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes) { u32 i; @@ -627,6 +641,7 @@ txt->type = is_cdata ? GF_DOM_TEXT_CDATA : GF_DOM_TEXT_REGULAR; } } +#endif // GPAC_DISABLE_SVG static void xml_http_terminate(XMLHTTPContext *ctx, GF_Err error) { @@ -736,6 +751,8 @@ /*prepare SAX parser*/ if (ctx->responseType != XHR_RESPONSETYPE_SAX) goto exit; if (strcmp(parameter->name, "Content-Type")) goto exit; + +#ifndef GPAC_DISABLE_SVG if (!strncmp(parameter->value, "application/xml", 15) || !strncmp(parameter->value, "text/xml", 8) || strstr(parameter->value, "+xml") @@ -749,6 +766,8 @@ /*mark this doc as "nomade", and let it leave until all references to it are destroyed*/ ctx->document->reference_count = 1; } +#endif + goto exit; case GF_NETIO_DATA_EXCHANGE: if (parameter->data && parameter->size) { @@ -1067,6 +1086,7 @@ return res; } +#ifndef GPAC_DISABLE_SVG static GF_Err xml_http_load_dom(XMLHTTPContext *ctx) { GF_Err e; @@ -1078,6 +1098,7 @@ gf_xml_dom_del(parser); return e; } +#endif //GPAC_DISABLE_SVG static JSValue xml_http_overrideMimeType(JSContext *c, JSValueConst obj, int argc, JSValueConst *argv) @@ -1119,6 +1140,7 @@ case XHR_RESPONSEXML: if (ctx->readyState<XHR_READYSTATE_LOADING) return JS_NULL; +#ifndef GPAC_DISABLE_SVG if (ctx->data) { if (!ctx->document) { ctx->document = gf_sg_new(); @@ -1134,6 +1156,9 @@ } else { return JS_NULL; } +#else + return js_throw_err_msg(c, GF_NOT_SUPPORTED, "DOM support not included in buil"); +#endif case XHR_RESPONSE: if (ctx->readyState<XHR_READYSTATE_LOADING) return JS_NULL; @@ -1152,6 +1177,7 @@ return JS_DupValue(c, ctx->arraybuffer); break; case XHR_RESPONSETYPE_DOCUMENT: +#ifndef GPAC_DISABLE_SVG if (ctx->data) { if (!ctx->document) { ctx->document = gf_sg_new(); @@ -1166,6 +1192,9 @@ return dom_document_construct_external(c, ctx->document); } return JS_NULL; +#else + return js_throw_err_msg(c, GF_NOT_SUPPORTED, "DOM support not included in buil"); +#endif case XHR_RESPONSETYPE_JSON: return JS_ParseJSON(c, ctx->data, ctx->size, "responseJSON"); case XHR_RESPONSETYPE_PUSH: @@ -1346,6 +1375,7 @@ JS_CFUNC_DEF("send", 0, xml_http_send), JS_CFUNC_DEF("setRequestHeader", 2, xml_http_set_header), JS_CFUNC_DEF("wait", 0, xml_http_wait), + /*eventTarget interface*/ JS_DOM3_EVENT_TARGET_INTERFACE };
View file
gpac-1.0.0.tar.gz/src/media_tools/av_parsers.c -> gpac-1.0.1.tar.gz/src/media_tools/av_parsers.c
Changed
@@ -73,137 +73,84 @@ } } +struct __m4v_profile +{ + u32 value; + const char *name; +} M4VProfiles[] = { + {0x00, "Reserved (0x00) Profile"}, + {0x01, "Simple Profile @ Level 1"}, + {0x02, "Simple Profile @ Level 2"}, + {0x03, "Simple Profile @ Level 3"}, + {0x08, "Simple Profile @ Level 0"}, + {0x10, "Simple Scalable Profile @ Level 0"}, + {0x11, "Simple Scalable Profile @ Level 1"}, + {0x12, "Simple Scalable Profile @ Level 2"}, + {0x21, "Core Profile @ Level 1"}, + {0x22, "Core Profile @ Level 2"}, + {0x32, "Main Profile @ Level 2"}, + {0x33, "Main Profile @ Level 3"}, + {0x34, "Main Profile @ Level 4"}, + {0x42, "N-bit Profile @ Level 2"}, + {0x51, "Scalable Texture Profile @ Level 1"}, + {0x61, "Simple Face Animation Profile @ Level 1"}, + {0x62, "Simple Face Animation Profile @ Level 2"}, + {0x63, "Simple FBA Profile @ Level 1"}, + {0x64, "Simple FBA Profile @ Level 2"}, + {0x71, "Basic Animated Texture Profile @ Level 1"}, + {0x72, "Basic Animated Texture Profile @ Level 2"}, + {0x7F, "AVC/H264 Profile"}, + {0x81, "Hybrid Profile @ Level 1"}, + {0x82, "Hybrid Profile @ Level 2"}, + {0x91, "Advanced Real Time Simple Profile @ Level 1"}, + {0x92, "Advanced Real Time Simple Profile @ Level 2"}, + {0x93, "Advanced Real Time Simple Profile @ Level 3"}, + {0x94, "Advanced Real Time Simple Profile @ Level 4"}, + {0xA1, "Core Scalable Profile @ Level1"}, + {0xA2, "Core Scalable Profile @ Level2"}, + {0xA3, "Core Scalable Profile @ Level3"}, + {0xB1, "Advanced Coding Efficiency Profile @ Level 1"}, + {0xB2, "Advanced Coding Efficiency Profile @ Level 2"}, + {0xB3, "Advanced Coding Efficiency Profile @ Level 3"}, + {0xB4, "Advanced Coding Efficiency Profile @ Level 4"}, + {0xC1, "Advanced Core Profile @ Level 1"}, + {0xC2, "Advanced Core Profile @ Level 2"}, + {0xD1, "Advanced Scalable Texture @ Level1"}, + {0xD2, "Advanced Scalable Texture @ Level2"}, + {0xE1, "Simple Studio Profile @ Level 1"}, + {0xE2, "Simple Studio Profile @ Level 2"}, + {0xE3, "Simple Studio Profile @ Level 3"}, + {0xE4, "Simple Studio Profile @ Level 4"}, + {0xE5, "Core Studio Profile @ Level 1"}, + {0xE6, "Core Studio Profile @ Level 2"}, + {0xE7, "Core Studio Profile @ Level 3"}, + {0xE8, "Core Studio Profile @ Level 4"}, + {0xF0, "Advanced Simple Profile @ Level 0"}, + {0xF1, "Advanced Simple Profile @ Level 1"}, + {0xF2, "Advanced Simple Profile @ Level 2"}, + {0xF3, "Advanced Simple Profile @ Level 3"}, + {0xF4, "Advanced Simple Profile @ Level 4"}, + {0xF5, "Advanced Simple Profile @ Level 5"}, + {0xF7, "Advanced Simple Profile @ Level 3b"}, + {0xF8, "Fine Granularity Scalable Profile @ Level 0"}, + {0xF9, "Fine Granularity Scalable Profile @ Level 1"}, + {0xFA, "Fine Granularity Scalable Profile @ Level 2"}, + {0xFB, "Fine Granularity Scalable Profile @ Level 3"}, + {0xFC, "Fine Granularity Scalable Profile @ Level 4"}, + {0xFD, "Fine Granularity Scalable Profile @ Level 5"}, + {0xFE, "Not part of MPEG-4 Visual profiles"}, + {0xFF, "No visual capability required"} +}; + GF_EXPORT const char *gf_m4v_get_profile_name(u8 video_pl) { - switch (video_pl) { - case 0x00: - return "Reserved (0x00) Profile"; - case 0x01: - return "Simple Profile @ Level 1"; - case 0x02: - return "Simple Profile @ Level 2"; - case 0x03: - return "Simple Profile @ Level 3"; - case 0x08: - return "Simple Profile @ Level 0"; - case 0x10: - return "Simple Scalable Profile @ Level 0"; - case 0x11: - return "Simple Scalable Profile @ Level 1"; - case 0x12: - return "Simple Scalable Profile @ Level 2"; - case 0x21: - return "Core Profile @ Level 1"; - case 0x22: - return "Core Profile @ Level 2"; - case 0x32: - return "Main Profile @ Level 2"; - case 0x33: - return "Main Profile @ Level 3"; - case 0x34: - return "Main Profile @ Level 4"; - case 0x42: - return "N-bit Profile @ Level 2"; - case 0x51: - return "Scalable Texture Profile @ Level 1"; - case 0x61: - return "Simple Face Animation Profile @ Level 1"; - case 0x62: - return "Simple Face Animation Profile @ Level 2"; - case 0x63: - return "Simple FBA Profile @ Level 1"; - case 0x64: - return "Simple FBA Profile @ Level 2"; - case 0x71: - return "Basic Animated Texture Profile @ Level 1"; - case 0x72: - return "Basic Animated Texture Profile @ Level 2"; - case 0x7F: - return "AVC/H264 Profile"; - case 0x81: - return "Hybrid Profile @ Level 1"; - case 0x82: - return "Hybrid Profile @ Level 2"; - case 0x91: - return "Advanced Real Time Simple Profile @ Level 1"; - case 0x92: - return "Advanced Real Time Simple Profile @ Level 2"; - case 0x93: - return "Advanced Real Time Simple Profile @ Level 3"; - case 0x94: - return "Advanced Real Time Simple Profile @ Level 4"; - case 0xA1: - return "Core Scalable Profile @ Level1"; - case 0xA2: - return "Core Scalable Profile @ Level2"; - case 0xA3: - return "Core Scalable Profile @ Level3"; - case 0xB1: - return "Advanced Coding Efficiency Profile @ Level 1"; - case 0xB2: - return "Advanced Coding Efficiency Profile @ Level 2"; - case 0xB3: - return "Advanced Coding Efficiency Profile @ Level 3"; - case 0xB4: - return "Advanced Coding Efficiency Profile @ Level 4"; - case 0xC1: - return "Advanced Core Profile @ Level 1"; - case 0xC2: - return "Advanced Core Profile @ Level 2"; - case 0xD1: - return "Advanced Scalable Texture @ Level1"; - case 0xD2: - return "Advanced Scalable Texture @ Level2"; - case 0xE1: - return "Simple Studio Profile @ Level 1"; - case 0xE2: - return "Simple Studio Profile @ Level 2"; - case 0xE3: - return "Simple Studio Profile @ Level 3"; - case 0xE4: - return "Simple Studio Profile @ Level 4"; - case 0xE5: - return "Core Studio Profile @ Level 1"; - case 0xE6: - return "Core Studio Profile @ Level 2"; - case 0xE7: - return "Core Studio Profile @ Level 3"; - case 0xE8: - return "Core Studio Profile @ Level 4"; - case 0xF0: - return "Advanced Simple Profile @ Level 0"; - case 0xF1: - return "Advanced Simple Profile @ Level 1"; - case 0xF2: - return "Advanced Simple Profile @ Level 2"; - case 0xF3: - return "Advanced Simple Profile @ Level 3"; - case 0xF4: - return "Advanced Simple Profile @ Level 4"; - case 0xF5: - return "Advanced Simple Profile @ Level 5"; - case 0xF7: - return "Advanced Simple Profile @ Level 3b"; - case 0xF8: - return "Fine Granularity Scalable Profile @ Level 0"; - case 0xF9: - return "Fine Granularity Scalable Profile @ Level 1"; - case 0xFA: - return "Fine Granularity Scalable Profile @ Level 2"; - case 0xFB: - return "Fine Granularity Scalable Profile @ Level 3"; - case 0xFC: - return "Fine Granularity Scalable Profile @ Level 4"; - case 0xFD: - return "Fine Granularity Scalable Profile @ Level 5"; - case 0xFE: - return "Not part of MPEG-4 Visual profiles"; - case 0xFF: - return "No visual capability required"; - default: - return "ISO Reserved Profile"; + u32 i, count = GF_ARRAY_LENGTH(M4VProfiles); + for (i=0; i<count; i++) { + if ((u32)video_pl == M4VProfiles[i].value) + return M4VProfiles[i].name; } + return "ISO Reserved Profile"; } @@ -944,236 +891,146 @@ AAC parser */ +struct __m4a_oti +{ + u32 type; + const char *name; +} M4AObjectTypes[] = { + {0, "MPEG-4 Audio Reserved"}, + {1, "MPEG-4 Audio AAC Main"}, + {2, "MPEG-4 Audio AAC LC"}, + {3, "MPEG-4 Audio AAC SSR"}, + {4, "MPEG-4 Audio AAC LTP"}, + {5, "MPEG-4 Audio SBR"}, + {6, "MPEG-4 Audio AAC Scalable"}, + {7, "MPEG-4 Audio TwinVQ"}, + {8, "MPEG-4 Audio CELP"}, + {9, "MPEG-4 Audio HVXC"}, + {10, "MPEG-4 Audio Reserved"}, + {11, "MPEG-4 Audio Reserved"}, + {12, "MPEG-4 Audio TTSI"}, + {13, "MPEG-4 Audio Main synthetic"}, + {14, "MPEG-4 Audio Wavetable synthesis"}, + {15, "MPEG-4 Audio General MIDI"}, + {16, "MPEG-4 Audio Algorithmic Synthesis and Audio FX"}, + {17, "MPEG-4 Audio ER AAC LC"}, + {18, "MPEG-4 Audio Reserved"}, + {19, "MPEG-4 Audio ER AAC LTP"}, + {20, "MPEG-4 Audio ER AAC scalable"}, + {21, "MPEG-4 Audio ER TwinVQ"}, + {22, "MPEG-4 Audio ER BSAC"}, + {23, "MPEG-4 Audio ER AAC LD"}, + {24, "MPEG-4 Audio ER CELP"}, + {25, "MPEG-4 Audio ER HVXC"}, + {26, "MPEG-4 Audio ER HILN"}, + {27, "MPEG-4 Audio ER Parametric"}, + {28, "MPEG-4 Audio SSC"}, + {29, "MPEG-4 Audio ParametricStereo"}, + {30, "MPEG-4 Audio Reserved"}, + {31, "MPEG-4 Audio Reserved"}, + {32, "MPEG-1 Audio Layer-1"}, + {33, "MPEG-1 Audio Layer-2"}, + {34, "MPEG-1 Audio Layer-3"}, + {35, "MPEG-4 Audio DST"}, + {36, "MPEG-4 Audio ALS"} +}; + GF_EXPORT const char *gf_m4a_object_type_name(u32 objectType) { - switch (objectType) { - case 0: - return "MPEG-4 Audio Reserved"; - case 1: - return "MPEG-4 Audio AAC Main"; - case 2: - return "MPEG-4 Audio AAC LC"; - case 3: - return "MPEG-4 Audio AAC SSR"; - case 4: - return "MPEG-4 Audio AAC LTP"; - case 5: - return "MPEG-4 Audio SBR"; - case 6: - return "MPEG-4 Audio AAC Scalable"; - case 7: - return "MPEG-4 Audio TwinVQ"; - case 8: - return "MPEG-4 Audio CELP"; - case 9: - return "MPEG-4 Audio HVXC"; - case 10: - return "MPEG-4 Audio Reserved"; - case 11: - return "MPEG-4 Audio Reserved"; - case 12: - return "MPEG-4 Audio TTSI"; - case 13: - return "MPEG-4 Audio Main synthetic"; - case 14: - return "MPEG-4 Audio Wavetable synthesis"; - case 15: - return "MPEG-4 Audio General MIDI"; - case 16: - return "MPEG-4 Audio Algorithmic Synthesis and Audio FX"; - case 17: - return "MPEG-4 Audio ER AAC LC"; - case 18: - return "MPEG-4 Audio Reserved"; - case 19: - return "MPEG-4 Audio ER AAC LTP"; - case 20: - return "MPEG-4 Audio ER AAC scalable"; - case 21: - return "MPEG-4 Audio ER TwinVQ"; - case 22: - return "MPEG-4 Audio ER BSAC"; - case 23: - return "MPEG-4 Audio ER AAC LD"; - case 24: - return "MPEG-4 Audio ER CELP"; - case 25: - return "MPEG-4 Audio ER HVXC"; - case 26: - return "MPEG-4 Audio ER HILN"; - case 27: - return "MPEG-4 Audio ER Parametric"; - case 28: - return "MPEG-4 Audio SSC"; - case 29: - return "MPEG-4 Audio ParametricStereo"; - case 30: - return "MPEG-4 Audio Reserved"; - case 31: - return "MPEG-4 Audio Reserved"; - case 32: - return "MPEG-1 Audio Layer-1"; - case 33: - return "MPEG-1 Audio Layer-2"; - case 34: - return "MPEG-1 Audio Layer-3"; - case 35: - return "MPEG-4 Audio DST"; - case 36: - return "MPEG-4 Audio ALS"; - default: - return "MPEG-4 Audio Unknown"; + u32 i, count = GF_ARRAY_LENGTH(M4AObjectTypes); + for (i=0; i<count; i++) { + if (objectType==M4AObjectTypes[i].type) + return M4AObjectTypes[i].name; } + return "MPEG-4 Audio Unknown"; } +struct __m4a_profile +{ + u32 value; + const char *name; +} M4AProfiles[] = { + {0x00, "ISO Reserved (0x00)"}, + {0x01, "Main Audio Profile @ Level 1"}, + {0x02, "Main Audio Profile @ Level 2"}, + {0x03, "Main Audio Profile @ Level 3"}, + {0x04, "Main Audio Profile @ Level 4"}, + {0x05, "Scalable Audio Profile @ Level 1"}, + {0x06, "Scalable Audio Profile @ Level 2"}, + {0x07, "Scalable Audio Profile @ Level 3"}, + {0x08, "Scalable Audio Profile @ Level 4"}, + {0x09, "Speech Audio Profile @ Level 1"}, + {0x0A, "Speech Audio Profile @ Level 2"}, + {0x0B, "Synthetic Audio Profile @ Level 1"}, + {0x0C, "Synthetic Audio Profile @ Level 2"}, + {0x0D, "Synthetic Audio Profile @ Level 3"}, + {0x0E, "High Quality Audio Profile @ Level 1"}, + {0x0F, "High Quality Audio Profile @ Level 2"}, + {0x10, "High Quality Audio Profile @ Level 3"}, + {0x11, "High Quality Audio Profile @ Level 4"}, + {0x12, "High Quality Audio Profile @ Level 5"}, + {0x13, "High Quality Audio Profile @ Level 6"}, + {0x14, "High Quality Audio Profile @ Level 7"}, + {0x15, "High Quality Audio Profile @ Level 8"}, + {0x16, "Low Delay Audio Profile @ Level 1"}, + {0x17, "Low Delay Audio Profile @ Level 2"}, + {0x18, "Low Delay Audio Profile @ Level 3"}, + {0x19, "Low Delay Audio Profile @ Level 4"}, + {0x1A, "Low Delay Audio Profile @ Level 5"}, + {0x1B, "Low Delay Audio Profile @ Level 6"}, + {0x1C, "Low Delay Audio Profile @ Level 7"}, + {0x1D, "Low Delay Audio Profile @ Level 8"}, + {0x1E, "Natural Audio Profile @ Level 1"}, + {0x1F, "Natural Audio Profile @ Level 2"}, + {0x20, "Natural Audio Profile @ Level 3"}, + {0x21, "Natural Audio Profile @ Level 4"}, + {0x22, "Mobile Audio Internetworking Profile @ Level 1"}, + {0x23, "Mobile Audio Internetworking Profile @ Level 2"}, + {0x24, "Mobile Audio Internetworking Profile @ Level 3"}, + {0x25, "Mobile Audio Internetworking Profile @ Level 4"}, + {0x26, "Mobile Audio Internetworking Profile @ Level 5"}, + {0x27, "Mobile Audio Internetworking Profile @ Level 6"}, + {0x28, "AAC Profile @ Level 1"}, + {0x29, "AAC Profile @ Level 2"}, + {0x2A, "AAC Profile @ Level 4"}, + {0x2B, "AAC Profile @ Level 5"}, + {0x2C, "High Efficiency AAC Profile @ Level 2"}, + {0x2D, "High Efficiency AAC Profile @ Level 3"}, + {0x2E, "High Efficiency AAC Profile @ Level 4"}, + {0x2F, "High Efficiency AAC Profile @ Level 5"}, + {0x30, "High Efficiency AAC v2 Profile @ Level 2"}, + {0x31, "High Efficiency AAC v2 Profile @ Level 3"}, + {0x32, "High Efficiency AAC v2 Profile @ Level 4"}, + {0x33, "High Efficiency AAC v2 Profile @ Level 5"}, + {0x34, "Low Delay AAC Profile"}, + {0x35, "Baseline MPEG Surround Profile @ Level 1"}, + {0x36, "Baseline MPEG Surround Profile @ Level 2"}, + {0x37, "Baseline MPEG Surround Profile @ Level 3"}, + {0x38, "Baseline MPEG Surround Profile @ Level 4"}, + {0x39, "Baseline MPEG Surround Profile @ Level 5"}, + {0x3A, "Baseline MPEG Surround Profile @ Level 6"}, + {0x50, "AAC Profile @ Level 6"}, + {0x51, "AAC Profile @ Level 7"}, + {0x52, "High Efficiency AAC Profile @ Level 6"}, + {0x53, "High Efficiency AAC Profile @ Level 7"}, + {0x54, "High Efficiency AAC v2 Profile @ Level 6"}, + {0x55, "High Efficiency AAC v2 Profile @ Level 7"}, + {0x56, "Extended High Efficiency AAC Profile @ Level 6"}, + {0x57, "Extended High Efficiency AAC Profile @ Level 7"}, + {0xFE, "Not part of MPEG-4 audio profiles"}, + {0xFF, "No audio capability required"} +}; + GF_EXPORT const char *gf_m4a_get_profile_name(u8 audio_pl) { - switch (audio_pl) { - case 0x00: - return "ISO Reserved (0x00)"; - case 0x01: - return "Main Audio Profile @ Level 1"; - case 0x02: - return "Main Audio Profile @ Level 2"; - case 0x03: - return "Main Audio Profile @ Level 3"; - case 0x04: - return "Main Audio Profile @ Level 4"; - case 0x05: - return "Scalable Audio Profile @ Level 1"; - case 0x06: - return "Scalable Audio Profile @ Level 2"; - case 0x07: - return "Scalable Audio Profile @ Level 3"; - case 0x08: - return "Scalable Audio Profile @ Level 4"; - case 0x09: - return "Speech Audio Profile @ Level 1"; - case 0x0A: - return "Speech Audio Profile @ Level 2"; - case 0x0B: - return "Synthetic Audio Profile @ Level 1"; - case 0x0C: - return "Synthetic Audio Profile @ Level 2"; - case 0x0D: - return "Synthetic Audio Profile @ Level 3"; - case 0x0E: - return "High Quality Audio Profile @ Level 1"; - case 0x0F: - return "High Quality Audio Profile @ Level 2"; - case 0x10: - return "High Quality Audio Profile @ Level 3"; - case 0x11: - return "High Quality Audio Profile @ Level 4"; - case 0x12: - return "High Quality Audio Profile @ Level 5"; - case 0x13: - return "High Quality Audio Profile @ Level 6"; - case 0x14: - return "High Quality Audio Profile @ Level 7"; - case 0x15: - return "High Quality Audio Profile @ Level 8"; - case 0x16: - return "Low Delay Audio Profile @ Level 1"; - case 0x17: - return "Low Delay Audio Profile @ Level 2"; - case 0x18: - return "Low Delay Audio Profile @ Level 3"; - case 0x19: - return "Low Delay Audio Profile @ Level 4"; - case 0x1A: - return "Low Delay Audio Profile @ Level 5"; - case 0x1B: - return "Low Delay Audio Profile @ Level 6"; - case 0x1C: - return "Low Delay Audio Profile @ Level 7"; - case 0x1D: - return "Low Delay Audio Profile @ Level 8"; - case 0x1E: - return "Natural Audio Profile @ Level 1"; - case 0x1F: - return "Natural Audio Profile @ Level 2"; - case 0x20: - return "Natural Audio Profile @ Level 3"; - case 0x21: - return "Natural Audio Profile @ Level 4"; - case 0x22: - return "Mobile Audio Internetworking Profile @ Level 1"; - case 0x23: - return "Mobile Audio Internetworking Profile @ Level 2"; - case 0x24: - return "Mobile Audio Internetworking Profile @ Level 3"; - case 0x25: - return "Mobile Audio Internetworking Profile @ Level 4"; - case 0x26: - return "Mobile Audio Internetworking Profile @ Level 5"; - case 0x27: - return "Mobile Audio Internetworking Profile @ Level 6"; - case 0x28: - return "AAC Profile @ Level 1"; - case 0x29: - return "AAC Profile @ Level 2"; - case 0x2A: - return "AAC Profile @ Level 4"; - case 0x2B: - return "AAC Profile @ Level 5"; - case 0x2C: - return "High Efficiency AAC Profile @ Level 2"; - case 0x2D: - return "High Efficiency AAC Profile @ Level 3"; - case 0x2E: - return "High Efficiency AAC Profile @ Level 4"; - case 0x2F: - return "High Efficiency AAC Profile @ Level 5"; - case 0x30: - return "High Efficiency AAC v2 Profile @ Level 2"; - case 0x31: - return "High Efficiency AAC v2 Profile @ Level 3"; - case 0x32: - return "High Efficiency AAC v2 Profile @ Level 4"; - case 0x33: - return "High Efficiency AAC v2 Profile @ Level 5"; - case 0x34: - return "Low Delay AAC Profile"; - case 0x35: - return "Baseline MPEG Surround Profile @ Level 1"; - case 0x36: - return "Baseline MPEG Surround Profile @ Level 2"; - case 0x37: - return "Baseline MPEG Surround Profile @ Level 3"; - case 0x38: - return "Baseline MPEG Surround Profile @ Level 4"; - case 0x39: - return "Baseline MPEG Surround Profile @ Level 5"; - case 0x3A: - return "Baseline MPEG Surround Profile @ Level 6"; - - case 0x50: - return "AAC Profile @ Level 6"; - case 0x51: - return "AAC Profile @ Level 7"; - case 0x52: - return "High Efficiency AAC Profile @ Level 6"; - case 0x53: - return "High Efficiency AAC Profile @ Level 7"; - case 0x54: - return "High Efficiency AAC v2 Profile @ Level 6"; - case 0x55: - return "High Efficiency AAC v2 Profile @ Level 7"; - case 0x56: - return "Extended High Efficiency AAC Profile @ Level 6"; - case 0x57: - return "Extended High Efficiency AAC Profile @ Level 7"; - - case 0xFE: - return "Not part of MPEG-4 audio profiles"; - case 0xFF: - return "No audio capability required"; - default: - return "ISO Reserved / User Private"; + u32 i, count = GF_ARRAY_LENGTH(M4AProfiles); + for (i=0; i<count; i++) { + if ((u32) audio_pl==M4AProfiles[i].value) + return M4AProfiles[i].name; } + return "ISO Reserved / User Private"; } #ifndef GPAC_DISABLE_AV_PARSERS @@ -5051,6 +4908,7 @@ { u32 i = 0, emulation_bytes_count = 0; u8 num_zero = 0; + if (!buffer || !nal_size) return 0; while (i < nal_size) { @@ -5422,7 +5280,7 @@ } } else if ((profile_idc == 118) || (profile_idc == 128)) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[avc-h264] MVC not supported - skipping parsing end of Subset SPS\n")); + GF_LOG(GF_LOG_INFO, GF_LOG_CODING, ("[avc-h264] MVC parsing not implemented - skipping parsing end of Subset SPS\n")); return sps_id; } @@ -5572,23 +5430,7 @@ return pps_id; } -static s32 gf_media_avc_read_sps_ext_bs_internal(GF_BitStream *bs, u32 nal_hdr) -{ - s32 sps_id; - - gf_bs_enable_emulation_byte_removal(bs, GF_TRUE); - if (!nal_hdr) { - /*nal_hdr = */gf_bs_read_u8(bs); - } - sps_id = gf_bs_get_ue(bs); - return sps_id; -} - #if 0 //unused -s32 gf_media_avc_read_sps_ext_bs(GF_BitStream *bs) -{ - return gf_media_avc_read_sps_ext_bs_internal(bs, 0); -} s32 gf_media_avc_read_sps_ext(const char *spse_data, u32 spse_size) { @@ -5946,6 +5788,7 @@ } +#if !defined(GPAC_DISABLE_HEVC) static void avc_parse_itu_t_t35_sei(GF_BitStream* bs, AVCSeiItuTT35DolbyVision *dovi) { u8 itu_t_t35_country_code = gf_bs_read_u8(bs); @@ -5956,7 +5799,7 @@ dovi->rpu_flag = GF_TRUE; } } - +#endif static void avc_compute_poc(AVCSliceInfo *si) { @@ -6204,7 +6047,7 @@ if (avc->last_ps_idx < 0) return -1; return 0; case GF_AVC_NALU_SEQ_PARAM_EXT: - avc->last_ps_idx = gf_media_avc_read_sps_ext_bs_internal(bs, nal_hdr); + avc->last_ps_idx = (s32) gf_bs_get_ue(bs); if (avc->last_ps_idx < 0) return -1; return 0; @@ -7695,12 +7538,12 @@ u32 new_vps_size, emulation_bytes; u32 bit_pos = gf_bs_get_bit_offset(bs); GF_BitStream *w_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); - gf_bs_write_u8(w_bs, data[0]); - gf_bs_write_u8(w_bs, data[1]); - gf_bs_write_u8(w_bs, data[2]); - gf_bs_write_u8(w_bs, data[3]); - gf_bs_write_u16(w_bs, 0xFFFF); - gf_bs_seek(bs, 6); + gf_bs_seek(bs, 0); + gf_bs_write_u8(w_bs, gf_bs_read_u8(bs) ); + gf_bs_write_u8(w_bs, gf_bs_read_u8(bs) ); + gf_bs_write_u8(w_bs, gf_bs_read_u8(bs) ); + gf_bs_write_u8(w_bs, gf_bs_read_u8(bs) ); + gf_bs_write_u16(w_bs, gf_bs_read_u16(bs) ); bit_pos -= 48; while (bit_pos) { u32 v = gf_bs_read_int(bs, 1); @@ -7720,10 +7563,13 @@ else { *size = gf_media_nalu_add_emulation_bytes(new_vps, data, new_vps_size); } + if (new_vps) + gf_free(new_vps); } exit: - if (bs) gf_bs_del(bs); + if (bs) + gf_bs_del(bs); if (data_without_emulation_bytes) gf_free(data_without_emulation_bytes); return vps_id; } @@ -7737,6 +7583,7 @@ GF_EXPORT s32 gf_media_hevc_read_vps_bs(GF_BitStream *bs, HEVCState *hevc) { + if (!bs || !hevc) return -1; gf_bs_enable_emulation_byte_removal(bs, GF_TRUE); if (!hevc_parse_nal_header(bs, NULL, NULL, NULL)) return -1; return gf_media_hevc_read_vps_bs_internal(bs, hevc, GF_FALSE); @@ -8078,6 +7925,7 @@ s32 gf_media_hevc_read_sps_bs(GF_BitStream *bs, HEVCState *hevc) { u8 layer_id; + if (!bs || !hevc) return -1; gf_bs_enable_emulation_byte_removal(bs, GF_TRUE); if (!hevc_parse_nal_header(bs, NULL, NULL, &layer_id)) return -1; return gf_media_hevc_read_sps_bs_internal(bs, hevc, layer_id, NULL); @@ -8193,6 +8041,7 @@ GF_EXPORT s32 gf_media_hevc_read_pps_bs(GF_BitStream *bs, HEVCState *hevc) { + if (!bs || !hevc) return -1; gf_bs_enable_emulation_byte_removal(bs, GF_TRUE); if (!hevc_parse_nal_header(bs, NULL, NULL, NULL)) return -1; return gf_media_hevc_read_pps_bs_internal(bs, hevc); @@ -9123,3 +8972,38 @@ } #endif /*!defined(GPAC_DISABLE_AV_PARSERS) && !defined (GPAC_DISABLE_OGG)*/ + +u64 gf_mpegh_escaped_value(GF_BitStream *bs, u32 nBits1, u32 nBits2, u32 nBits3) +{ + u64 value = gf_bs_read_int(bs, nBits1); + if (value == (1<<nBits1)-1) { + u32 vadd = gf_bs_read_int(bs, nBits2); + value += vadd; + if (vadd == (1<<nBits2)-1) { + vadd = gf_bs_read_int(bs, nBits3); + value += vadd; + } + } + return value; +} + +GF_EXPORT +s32 gf_mpegh_get_mhas_pl(u8 *ptr, u32 size) +{ + GF_BitStream *bs = gf_bs_new(ptr, size, GF_BITSTREAM_READ); + + while (gf_bs_available(bs)) { + u32 type = (u32) gf_mpegh_escaped_value(bs, 3, 8, 8); + /*u64 label = */gf_mpegh_escaped_value(bs, 2, 8, 32); + u64 mh_size = gf_mpegh_escaped_value(bs, 11, 24, 24); + //MHAS config + if (type==1) { + u32 PL = gf_bs_read_int(bs, 8); + gf_bs_del(bs); + return PL; + } + gf_bs_skip_bytes(bs, mh_size); + } + gf_bs_del(bs); + return -1; +}
View file
gpac-1.0.0.tar.gz/src/media_tools/avilib.c -> gpac-1.0.1.tar.gz/src/media_tools/avilib.c
Changed
@@ -35,9 +35,7 @@ #define INFO_LIST // add a new riff chunk after XX MB -//#define NEW_RIFF_THRES (1900*1024*1024) #define NEW_RIFF_THRES (1900*1024*1024) -//#define NEW_RIFF_THRES (10*1024*1024) // Maximum number of indices per stream #define NR_IXNN_CHUNKS 96 @@ -297,7 +295,7 @@ for (k = 0; k < NR_IXNN_CHUNKS; k++) { sil->stdindex[k] = (avistdindex_chunk *) gf_malloc (sizeof (avistdindex_chunk)); // gets rewritten later - sil->stdindex[k]->qwBaseOffset = (u64)k * NEW_RIFF_THRES; + sil->stdindex[k]->qwBaseOffset = (u64)k * AVI->new_riff_threshold; sil->stdindex[k]->aIndex = NULL; } @@ -435,7 +433,7 @@ //GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML: towrite = 0x%llX = %"LLD"\n", towrite, towrite)); if (AVI->video_superindex && - (s64)(AVI->pos+towrite) > (s64)((s64)NEW_RIFF_THRES*AVI->video_superindex->nEntriesInUse)) { + (s64)(AVI->pos+towrite) > (s64)((s64) AVI->new_riff_threshold*AVI->video_superindex->nEntriesInUse)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] Adding a new RIFF chunk: %d\n", AVI->video_superindex->nEntriesInUse)); @@ -607,7 +605,7 @@ */ GF_EXPORT -avi_t* AVI_open_output_file(char * filename) +avi_t* AVI_open_output_file(char * filename, u64 opendml_threshold) { avi_t *AVI; int i; @@ -647,6 +645,10 @@ AVI->pos = HEADERBYTES; AVI->mode = AVI_MODE_WRITE; /* open for writing */ + if (opendml_threshold) + AVI->new_riff_threshold = opendml_threshold; + else + AVI->new_riff_threshold = (1900*1024*1024); //init AVI->anum = 0;
View file
gpac-1.0.0.tar.gz/src/media_tools/dash_client.c -> gpac-1.0.1.tar.gz/src/media_tools/dash_client.c
Changed
@@ -254,6 +254,7 @@ u32 nb_retry_on_last_segment; s32 start_number_at_last_ast; u64 ast_at_init; + u32 ast_offset; /*next file (cached) to delete at next GF_NET_SERVICE_QUERY_NEXT for this group*/ char * urlToDeleteNext; @@ -430,11 +431,68 @@ return GF_FALSE; } +static Bool gf_dash_get_date(GF_DashClient *dash, char *scheme_id, char *url, u64 *utc) +{ + GF_DASHFileIOSession session; + GF_Err e; + u8 *data; + u32 len; + Bool res = GF_TRUE; + const char *cache_name; + *utc = 0; + + //unsupported schemes + if (!strcmp(scheme_id, "urn:mpeg:dash:utc:ntp:2014")) return GF_FALSE; + if (!strcmp(scheme_id, "urn:mpeg:dash:utc:sntp:2014")) return GF_FALSE; + + if (!dash->dash_io) return GF_FALSE; + + session = dash->dash_io->create(dash->dash_io, GF_FALSE, url, -2); + if (!session) return GF_FALSE; + e = dash->dash_io->run(dash->dash_io, session); + if (e) { + dash->dash_io->del(dash->dash_io, session); + return GF_FALSE; + } + cache_name = dash->dash_io->get_cache_name(dash->dash_io, session); + gf_blob_get_data(cache_name, &data, &len); + + if (!strcmp(scheme_id, "urn:mpeg:dash:utc:http-head:2014")) { + const char *hdr = dash->dash_io->get_header_value(dash->dash_io, session, "Date"); + if (hdr) + *utc = gf_net_parse_date(hdr); + else + res = GF_FALSE; + } + else if (!data) { + res = GF_FALSE; + } else { + if (!strcmp(scheme_id, "urn:mpeg:dash:utc:http-xsdate:2014")) { + *utc = gf_mpd_parse_date(data); + } + else if (!strcmp(scheme_id, "urn:mpeg:dash:utc:http-iso:2014")) { + *utc = gf_net_parse_date(data); + } + else if (!strcmp(scheme_id, "urn:mpeg:dash:utc:http-ntp:2014")) { + u64 ntp_ts; + if (sscanf((char *) data, LLU, &ntp_ts) == 1) { + *utc = gf_net_ntp_to_utc(ntp_ts); + } else { + res = GF_FALSE; + } + } + } + + dash->dash_io->del(dash->dash_io, session); + return res; +} + static void gf_dash_group_timeline_setup(GF_MPD *mpd, GF_DASH_Group *group, u64 fetch_time) { GF_MPD_SegmentTimeline *timeline = NULL; GF_MPD_Representation *rep = NULL; + GF_MPD_Descriptor *utc_timing = NULL; const char *val; u32 shift, timescale; u64 current_time, current_time_no_timeshift, availabilityStartTime; @@ -583,7 +641,57 @@ GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] No ATSC entity on HTPP request\n")); } - if ((!group->dash->atsc_clock_state || (group->dash->atsc_clock_state>2)) && !group->dash->ntp_forced && group->dash->estimate_utc_drift && !group->dash->utc_drift_estimate && group->dash->mpd_dnload && group->dash->dash_io->get_header_value) { + if (!group->dash->atsc_clock_state || (group->dash->atsc_clock_state>2)) { + GF_MPD_ProducerReferenceTime *pref = gf_list_get(group->adaptation_set->producer_reference_time, 0); + if (pref) + utc_timing = pref->utc_timing; + if (!utc_timing) + utc_timing = gf_list_get(group->dash->mpd->utc_timings, 0); + } + + if (utc_timing && utc_timing->scheme_id_uri) { + Bool res = GF_FALSE; + u64 utc=0; + s64 drift_estimate; + + if (!strcmp(utc_timing->scheme_id_uri, "urn:mpeg:dash:utc:direct:2014")) { + utc = gf_net_parse_date(utc_timing->value); + res = GF_TRUE; + } else { + char *time_refs = utc_timing->value; + utc = 0; + while (time_refs) { + char *sep = strchr(time_refs, ' '); + if (sep) sep[0] = 0; + + res = gf_dash_get_date(group->dash, utc_timing->scheme_id_uri, time_refs, &utc); + + time_refs = NULL; + if (sep) { + sep[0] = ' '; + time_refs = sep+1; + } + if (res) break; + } + } + if (res) { + drift_estimate = ((s64) fetch_time - (s64) utc); + group->dash->utc_drift_estimate = drift_estimate; + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Estimated UTC diff between client and server (%s): "LLD" ms (UTC fetch "LLU" - server UTC "LLU" - MPD AST "LLU" - MPD PublishTime "LLU"\n", utc_timing->value, group->dash->utc_drift_estimate, fetch_time, utc, + group->dash->mpd->availabilityStartTime, group->dash->mpd->publishTime)); + } else { + utc_timing = NULL; + } + } + + if ((!group->dash->atsc_clock_state || (group->dash->atsc_clock_state>2)) + && !group->dash->ntp_forced + && group->dash->estimate_utc_drift + && !group->dash->utc_drift_estimate + && group->dash->mpd_dnload + && group->dash->dash_io->get_header_value + && !utc_timing + ) { val = group->dash->dash_io->get_header_value(group->dash->dash_io, group->dash->mpd_dnload, "Server-UTC"); if (val) { u64 utc; @@ -820,7 +928,8 @@ group->download_segment_index = seg_idx; group->nb_segments_in_rep = count; group->start_playback_range = (segtime)*1.0/timescale; - group->ast_at_init = availabilityStartTime - (u32) (ast_offset*1000); + group->ast_at_init = availabilityStartTime; + group->ast_offset = (u32) (ast_offset*1000); group->broken_timing = GF_TRUE; return; } @@ -834,7 +943,8 @@ group->download_segment_index = seg_idx; group->nb_segments_in_rep = seg_idx + count - i; group->start_playback_range = (current_time)/1000.0; - group->ast_at_init = availabilityStartTime - (u32) (ast_offset*1000); + group->ast_at_init = availabilityStartTime; + group->ast_offset = (u32) (ast_offset*1000); //to remove - this is a hack to speedup starting for some strange MPDs which announce the live point as the first segment but have already produced the complete timeline if (group->dash->utc_drift_estimate<0) { @@ -853,8 +963,11 @@ GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] current time "LLU" is greater than last SegmentTimeline end "LLU" - defaulting to last entry in SegmentTimeline\n", current_time_rescale, segtime)); group->download_segment_index = seg_idx-1; group->nb_segments_in_rep = seg_idx; - group->start_playback_range = current_time/1000.0; - group->ast_at_init = availabilityStartTime - (u32) (ast_offset*1000); + //we can't trust our UTC check, play from last segment with start_range=0 (eg from start of first segment) + group->start_playback_range = 0; + + group->ast_at_init = availabilityStartTime; + group->ast_offset = (u32) (ast_offset*1000); //force an update in half the target period group->dash->last_update_time = gf_sys_clock() + group->dash->mpd->minimum_update_period/2; } else { @@ -943,7 +1056,8 @@ group->download_segment_index = shift; group->start_number_at_last_ast = start_number; - group->ast_at_init = availabilityStartTime - (u32) (ast_offset*1000); + group->ast_at_init = availabilityStartTime; + group->ast_offset = (u32) (ast_offset*1000); GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] AST at init "LLD"\n", group->ast_at_init)); GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] At current time "LLD" ms: Initializing Timeline: startNumber=%d segmentNumber=%d segmentDuration=%f - %.03f seconds in segment (start range %g)\n", current_time, start_number, shift, group->segment_duration, group->start_playback_range ? group->start_playback_range - shift*group->segment_duration : 0, group->start_playback_range)); @@ -954,7 +1068,8 @@ GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] At current time %d ms: Updating Timeline: startNumber=%d segmentNumber=%d downloadSegmentIndex=%d segmentDuration=%g AST_diff=%d\n", current_time, start_number, shift, group->download_segment_index, group->segment_duration, ast_diff)); } else { group->download_segment_index = shift; - group->ast_at_init = availabilityStartTime - (u32) (ast_offset*1000); + group->ast_at_init = availabilityStartTime; + group->ast_offset = (u32) (ast_offset*1000); GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] At current time "LLU" ms: Re-Initializing Timeline: startNumber=%d segmentNumber=%d segmentDuration=%g AST_diff=%d\n", current_time, start_number, shift, group->segment_duration, ast_diff)); } group->start_number_at_last_ast = start_number; @@ -1397,6 +1512,7 @@ seg_ast += seg_dur; seg_ast *= 1000; seg_ast += group->period->start + group->ast_at_init; + seg_ast -= group->ast_offset; return (u64) seg_ast; } @@ -5857,7 +5973,7 @@ /*if segment AST is greater than now, it is not yet available - we would need an estimate on how long the request takes to be sent to the server in order to be more reactive ...*/ if (to_wait > 1) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Set #%d At %d Next segment %d (AST "LLD" - sec in period %g) is not yet available on server - requesting later in %d ms\n", 1+gf_list_find(dash->groups, group), gf_sys_clock(), group->download_segment_index + start_number, segment_ast, (segment_ast - group->period->start - group->ast_at_init)/1000.0, to_wait)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Set #%d At %d Next segment %d (AST "LLD" - sec in period %g) is not yet available on server - requesting later in %d ms\n", 1+gf_list_find(dash->groups, group), gf_sys_clock(), group->download_segment_index + start_number, segment_ast, (segment_ast - group->period->start - group->ast_at_init + group->ast_offset)/1000.0, to_wait)); if (group->last_segment_time) { GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] %d ms elapsed since previous segment download\n", clock_time - group->last_segment_time)); } @@ -5866,7 +5982,7 @@ return GF_DASH_DownloadCancel; } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Set #%d At %d Next segment %d (AST "LLD" - sec in period %g) should now be available on server since %d ms - requesting it\n", 1+gf_list_find(dash->groups, group), gf_sys_clock(), group->download_segment_index + start_number, segment_ast, (segment_ast - group->period->start - group->ast_at_init)/1000.0, -to_wait)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Set #%d At %d Next segment %d (AST "LLD" - sec in period %g) should now be available on server since %d ms - requesting it\n", 1+gf_list_find(dash->groups, group), gf_sys_clock(), group->download_segment_index + start_number, segment_ast, (segment_ast - group->period->start - group->ast_at_init + group->ast_offset)/1000.0, -to_wait)); if (group->last_segment_time) { GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] %d ms elapsed since previous segment download\n", clock_time - group->last_segment_time));
View file
gpac-1.0.0.tar.gz/src/media_tools/dash_segmenter.c -> gpac-1.0.1.tar.gz/src/media_tools/dash_segmenter.c
Changed
@@ -643,7 +643,7 @@ if (dasher->dash_mode >= GF_DASH_DYNAMIC) { if (dasher->time_shift_depth<0) e |= gf_dynstrcat(&args, "tsb=-1", ":"); else { - sprintf(szArg, "tsb=%g", ((Double)dasher->time_shift_depth)/1000); + sprintf(szArg, "tsb=%u", (u32) dasher->time_shift_depth); e |= gf_dynstrcat(&args, szArg, ":"); }
View file
gpac-1.0.0.tar.gz/src/media_tools/isom_hinter.c -> gpac-1.0.1.tar.gz/src/media_tools/isom_hinter.c
Changed
@@ -658,16 +658,22 @@ gf_isom_set_track_priority_in_group(file, tmp->HintTrack, InterleaveGroupPriority); #if 0 - /*QT FF: not setting these flags = server uses a random offset*/ - gf_isom_rtp_set_time_offset(file, tmp->HintTrack, 1, 0); - /*we don't use seq offset for maintainance pruposes*/ - gf_isom_rtp_set_time_sequence_offset(file, tmp->HintTrack, 1, 0); #endif *e = GF_OK; return tmp; } GF_EXPORT +GF_Err gf_hinter_track_force_no_offsets(GF_RTPHinter *tkHinter) +{ + GF_Err e; + if (!tkHinter) return GF_BAD_PARAM; + e = gf_isom_rtp_set_time_offset(tkHinter->file, tkHinter->HintTrack, 1, 0); + if (e) return e; + return gf_isom_rtp_set_time_sequence_offset(tkHinter->file, tkHinter->HintTrack, 1, 0); +} + +GF_EXPORT u32 gf_hinter_track_get_bandwidth(GF_RTPHinter *tkHinter) { return tkHinter->bandwidth;
View file
gpac-1.0.0.tar.gz/src/media_tools/isom_tools.c -> gpac-1.0.1.tar.gz/src/media_tools/isom_tools.c
Changed
@@ -924,9 +924,16 @@ } //make QT gf_isom_remove_root_od(mp4); - gf_isom_set_brand_info(mp4, GF_ISOM_BRAND_QT, 512); - gf_isom_reset_alt_brands(mp4); - + if (gf_isom_get_mode(mp4) != GF_ISOM_OPEN_WRITE) { + gf_isom_set_brand_info(mp4, GF_ISOM_BRAND_QT, 512); + gf_isom_reset_alt_brands(mp4); + } else { + u32 brand, version; + gf_isom_get_brand_info(mp4, &brand, &version, NULL); + if (brand != GF_ISOM_BRAND_QT) { + GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ProRes] Cannot change brand from \"%s\" to \"qt \", flat storage used. Try using different storage mode\n", gf_4cc_to_str(brand))); + } + } if (!video_tk) { GF_LOG(GF_LOG_DEBUG, GF_LOG_AUTHOR, ("[QTFF] No visual track\n")); @@ -980,7 +987,6 @@ gf_isom_update_aperture_info(mp4, video_tk, GF_FALSE); } - //todo: patch colr e = gf_isom_get_color_info(mp4, video_tk, 1, &colour_type, &colour_primaries, &transfer_characteristics, &matrix_coefficients, &full_range_flag); if (e==GF_NOT_FOUND) { colour_primaries = transfer_characteristics = matrix_coefficients = 0; @@ -1085,6 +1091,10 @@ case GF_ISOM_SUBTYPE_AV01: case GF_ISOM_SUBTYPE_VP09: case GF_ISOM_SUBTYPE_VP08: + case GF_ISOM_SUBTYPE_MH3D_MHA1: + case GF_ISOM_SUBTYPE_MH3D_MHA2: + case GF_ISOM_SUBTYPE_MH3D_MHM1: + case GF_ISOM_SUBTYPE_MH3D_MHM2: return gf_isom_get_esd(mp4, track, stsd_idx); } @@ -2228,6 +2238,8 @@ } #ifndef GPAC_DISABLE_AV_PARSERS + +#if !defined(GPAC_DISABLE_HEVC) /* Split LHVC layers */ static GF_HEVCParamArray *alloc_hevc_param_array(GF_HEVCConfig *hevc_cfg, u8 type) { @@ -2247,6 +2259,7 @@ gf_list_add(hevc_cfg->param_array, ar); return ar; } +#endif typedef struct{ u8 layer_id_plus_one; @@ -2405,7 +2418,7 @@ GF_EXPORT GF_Err gf_media_split_lhvc(GF_ISOFile *file, u32 track, Bool for_temporal_sublayers, Bool splitAll, GF_LHVCExtractoreMode extractor_mode) { -#ifndef GPAC_DISABLE_AV_PARSERS +#if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS) LHVCTrackInfo sti[64]; GF_HEVCConfig *hevccfg, *lhvccfg; u32 sample_num, count, cur_extract_mode, j, k, max_layer_id; @@ -2584,12 +2597,13 @@ GF_BitStream *bs; u32 di; GF_ISOSample *sample; - Bool is_irap, has_roll; + Bool is_irap; + GF_ISOSampleRollType roll_type; s32 roll_distance; u8 cur_max_layer_id = 0; sample = gf_isom_get_sample(file, track, sample_num+1, &di); - gf_isom_get_sample_rap_roll_info(file, track, sample_num+1, &is_irap, &has_roll, &roll_distance); + gf_isom_get_sample_rap_roll_info(file, track, sample_num+1, &is_irap, &roll_type, &roll_distance); bs = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ); while (gf_bs_available(bs)) { @@ -2862,8 +2876,8 @@ if (is_irap) { gf_isom_set_sample_rap_group(file, sti[j].track_num, sample_idx, GF_TRUE, 0); } - else if (has_roll) { - gf_isom_set_sample_roll_group(file, sti[j].track_num, sample_idx, GF_TRUE, (s16) roll_distance); + else if (roll_type) { + gf_isom_set_sample_roll_group(file, sti[j].track_num, sample_idx, GF_ISOM_SAMPLE_ROLL, (s16) roll_distance); } }
View file
gpac-1.0.0.tar.gz/src/media_tools/m2ts_mux.c -> gpac-1.0.1.tar.gz/src/media_tools/m2ts_mux.c
Changed
@@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre , Cyril Concolato, Romain Bouqueau - * Copyright (c) Telecom ParisTech 2000-2018 + * Copyright (c) Telecom ParisTech 2000-2020 * All rights reserved * * This file is part of GPAC / MPEG2-TS multiplexer sub-project @@ -951,9 +951,9 @@ else stream->program->initial_ts = 0; - stream->program->initial_ts_set = GF_TRUE; + stream->program->initial_ts_set = 1; } - else if (*dts < stream->program->initial_ts) { + else if ( (*dts < stream->program->initial_ts) && (stream->program->initial_ts_set==1)) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is less than initial DTS "LLD" - adjusting\n", stream->pid, *dts, stream->program->initial_ts)); stream->program->initial_ts = *dts; } @@ -1007,7 +1007,7 @@ id3_write_size(bs, *len + 10); - gf_bs_write_u32(bs, ID3V2_FRAME_TXXX); + gf_bs_write_u32(bs, GF_ID3V2_FRAME_TXXX); id3_write_size(bs, *len); /* size of the text */ gf_bs_write_u8(bs, 0); gf_bs_write_u8(bs, 0); @@ -1148,6 +1148,43 @@ while (!stream->program->pcr_init_time) stream->program->pcr_init_time = gf_rand(); } + + if (stream->program->force_first_pts) { + u64 first_pts = stream->curr_pck.cts; + u64 first_dts = stream->curr_pck.dts; + + if (stream->ts_scale.den) { + first_pts = first_pts * stream->ts_scale.num / stream->ts_scale.den; + first_dts = first_dts * stream->ts_scale.num / stream->ts_scale.den; + } + + /*the final PTS is computed by: + force_first_pts = first_pts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300; + force_first_dts = first_dts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300; + + time_inc is computed as + time_inc = force_first_dts - stream->program->pcr_init_time/300; + + => time_inc = first_dts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300 - stream->program->pcr_init_time/300; + + => time_inc = first_dts + stream->program->pcr_offset - stream->program->initial_ts; + + we want at the initial time_inc=0, hence + stream->program->initial_ts = first_dts + stream->program->pcr_offset; + + */ +/* + stream->program->pcr_init_time = first_dts*300 - stream->program->pcr_offset; + stream->program->initial_ts = first_pts + stream->program->pcr_offset + stream->program->pcr_init_time/300 - stream->program->force_first_pts; +*/ + + stream->program->initial_ts = first_dts + stream->program->pcr_offset; + stream->program->pcr_init_time = 300 * (stream->program->force_first_pts - first_pts - stream->program->pcr_offset + stream->program->initial_ts); + + stream->program->initial_ts_set = 2; + } + + stream->program->pcr_init_time_set = GF_TRUE; stream->program->ts_time_at_pcr_init = muxer->time; stream->program->num_pck_at_pcr_init = muxer->tot_pck_sent; @@ -2107,28 +2144,20 @@ } } -static GF_M2TS_Mux_Stream *gf_m2ts_find_stream(GF_M2TS_Mux_Program *program, u32 pid, u32 stream_id) -{ - GF_M2TS_Mux_Stream *st = program->streams; - while (st) { - if (pid && (st->pid == pid)) - return st; - if (stream_id && (st->ifce->stream_id == stream_id)) - return st; - st = st->next; - } - return NULL; -} - -static s32 gf_m2ts_stream_index(GF_M2TS_Mux_Program *program, u32 pid, u32 stream_id) +static s32 gf_m2ts_find_stream(GF_M2TS_Mux_Program *program, u32 pid, u32 stream_id, GF_M2TS_Mux_Stream **out_stream) { s32 i=0; GF_M2TS_Mux_Stream *st = program->streams; + if (out_stream) *out_stream = NULL; while (st) { - if (pid && (st->pid == pid)) + if (pid && (st->pid == pid)) { + if (out_stream) *out_stream = st; return i; - if (stream_id && (st->ifce->stream_id == stream_id)) + } + if (stream_id && (st->ifce->stream_id == stream_id)) { + if (out_stream) *out_stream = st; return i; + } st = st->next; i++; } @@ -2157,13 +2186,13 @@ /*reserved*/ gf_bs_write_int(bs, 3, 2); /*hierarchy_layer_index*/ - gf_bs_write_int(bs, gf_m2ts_stream_index(stream->program, stream->pid, 0), 6); + gf_bs_write_int(bs, gf_m2ts_find_stream(stream->program, stream->pid, 0, NULL), 6); /*tref_present_flag = 1 : NOT PRESENT*/ gf_bs_write_int(bs, 1, 1); /*reserved*/ gf_bs_write_int(bs, 1, 1); /*hierarchy_embedded_layer_index*/ - gf_bs_write_int(bs, gf_m2ts_stream_index(stream->program, 0, stream->ifce->depends_on_stream), 6); + gf_bs_write_int(bs, gf_m2ts_find_stream(stream->program, 0, stream->ifce->depends_on_stream, NULL), 6); /*reserved*/ gf_bs_write_int(bs, 3, 2); /*hierarchy_channel*/ @@ -2317,7 +2346,7 @@ stream->mpeg2_stream_type = GF_M2TS_VIDEO_HEVC_TEMPORAL; gf_m2ts_stream_add_hierarchy_descriptor(stream); stream->force_single_au = GF_TRUE; - base_st = gf_m2ts_find_stream(program, 0, ifce->depends_on_stream); + gf_m2ts_find_stream(program, 0, ifce->depends_on_stream, &base_st); if (base_st) base_st->force_single_au = GF_TRUE; } @@ -2500,7 +2529,7 @@ } GF_EXPORT -GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_number, u32 pmt_pid, u32 pmt_refresh_rate, u32 pcr_offset, u32 mpeg4_signaling, u32 pmt_version, Bool initial_disc) +GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_number, u32 pmt_pid, u32 pmt_refresh_rate, u64 pcr_offset, u32 mpeg4_signaling, u32 pmt_version, Bool initial_disc, u64 force_first_pts) { GF_M2TS_Mux_Program *program; @@ -2528,6 +2557,7 @@ program->pmt->set_initial_disc = initial_disc; muxer->pat->table_needs_update = GF_TRUE; program->pmt->process = gf_m2ts_stream_process_pmt; + program->force_first_pts = force_first_pts; program->pmt->refresh_rate_ms = pmt_refresh_rate ? pmt_refresh_rate : (u32) -1; return program; } @@ -3016,7 +3046,6 @@ muxer->tot_pad_sent++; } } else { - if (stream_to_process->tables) { gf_m2ts_mux_table_get_next_packet(muxer, stream_to_process, muxer->dst_pck); } else {
View file
gpac-1.0.0.tar.gz/src/media_tools/media_export.c -> gpac-1.0.1.tar.gz/src/media_tools/media_export.c
Changed
@@ -90,7 +90,7 @@ if (gf_sys_is_test_mode()) { ogg_stream_init(&os, 1); } else { - gf_rand_init(1); + gf_rand_init(GF_TRUE); ogg_stream_init(&os, gf_rand()); }
View file
gpac-1.0.0.tar.gz/src/media_tools/media_import.c -> gpac-1.0.1.tar.gz/src/media_tools/media_import.c
Changed
@@ -30,6 +30,7 @@ #include <gpac/internal/media_dev.h> #include <gpac/xml.h> +#include <gpac/network.h> #ifndef GPAC_DISABLE_MEDIA_IMPORT @@ -1255,6 +1256,8 @@ sprintf(szSubArg, "trackid=%d", importer->esd->ESID); e |= gf_dynstrcat(&args, szSubArg, ":"); } + if (importer->flags & GF_IMPORT_FORCE_SYNC) + e |= gf_dynstrcat(&args, ":forcesync", NULL); if (importer->duration.den) { sprintf(szSubArg, "idur=%d/%d", importer->duration.num, importer->duration.den); @@ -1373,7 +1376,7 @@ e |= gf_dynstrcat(&args, szSubArg, ":"); } if (importer->track_index) { - sprintf(szSubArg, "#TrackIndex=%d", importer->track_index); + sprintf(szSubArg, "#MuxIndex=%d", importer->track_index); e |= gf_dynstrcat(&args, szSubArg, ":"); }
View file
gpac-1.0.0.tar.gz/src/media_tools/mpd.c -> gpac-1.0.1.tar.gz/src/media_tools/mpd.c
Changed
@@ -55,11 +55,13 @@ static Bool gf_mpd_is_known_descriptor(GF_XMLNode *child) { - if (!strcmp(child->name, "FramePacking") || - !strcmp(child->name, "AudioChannelConfiguration") || - !strcmp(child->name, "ContentProtection") || - !strcmp(child->name, "EssentialProperty") || - !strcmp(child->name, "SupplementalProperty")){ + if (!strcmp(child->name, "FramePacking") + || !strcmp(child->name, "AudioChannelConfiguration") + || !strcmp(child->name, "ContentProtection") + || !strcmp(child->name, "EssentialProperty") + || !strcmp(child->name, "SupplementalProperty") + || !strcmp(child->name, "UTCTiming") + ) { return GF_TRUE; } else{ @@ -130,7 +132,7 @@ return res; } -static u64 gf_mpd_parse_date(const char * const attr) +u64 gf_mpd_parse_date(const char * const attr) { return gf_net_parse_date(attr); } @@ -548,7 +550,7 @@ gf_list_rem(root->content, i); \ gf_list_add(_elem->children, child); \ -static GF_Err gf_mpd_parse_descriptor(GF_List *container, GF_XMLNode *root) +static GF_Err gf_mpd_parse_descriptor_ex(GF_List *container, GF_MPD_Descriptor **out_ptr, GF_XMLNode *root) { GF_XMLAttribute *att; GF_XMLNode *child; @@ -566,7 +568,12 @@ MPD_STORE_EXTENSION_ATTR(mpd_desc) } } - gf_list_add(container, mpd_desc); + if (container) + gf_list_add(container, mpd_desc); + else { + if (*out_ptr) gf_mpd_descriptor_free(*out_ptr); + *out_ptr = mpd_desc; + } i = 0; while ( (child = gf_list_enum(root->content, &i))) { @@ -575,10 +582,45 @@ MPD_STORE_EXTENSION_NODE(mpd_desc) } - return GF_OK; } +static GF_Err gf_mpd_parse_descriptor(GF_List *container, GF_XMLNode *root) +{ + return gf_mpd_parse_descriptor_ex(container, NULL, root); +} + +GF_MPD_ProducerReferenceTime *gf_mpd_parse_produce_ref_time(GF_XMLNode *root) +{ + GF_XMLAttribute *att; + GF_XMLNode *child; + GF_MPD_ProducerReferenceTime *pref; + u32 i = 0; + + GF_SAFEALLOC(pref, GF_MPD_ProducerReferenceTime); + if (!pref) return NULL; + + while ( (att = gf_list_enum(root->attributes, &i)) ) { + if (!strcmp(att->name, "id")) pref->ID = gf_mpd_parse_int(att->value); + else if (!strcmp(att->name, "inband")) pref->inband = gf_mpd_parse_bool(att->value); + else if (!strcmp(att->name, "type")) { + if (!strcmp(att->value, "application")) pref->type = GF_MPD_PRODUCER_REF_APPLICATION; + else if (!strcmp(att->value, "captured")) pref->type = GF_MPD_PRODUCER_REF_CAPTURED; + } + else if (!strcmp(att->name, "applicationScheme") && !pref->scheme) pref->scheme = gf_mpd_parse_string(att->value); + else if (!strcmp(att->name, "wallClockTime") && !pref->wallclock) pref->wallclock = gf_mpd_parse_string(att->value); + else if (!strcmp(att->name, "presentationTime")) pref->presentation_time = gf_mpd_parse_long_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, "UTCTiming")) + gf_mpd_parse_descriptor_ex(NULL, &pref->utc_timing, child); + } + return pref; +} + static void gf_mpd_parse_common_representation(GF_MPD *mpd, GF_MPD_CommonAttributes *com, GF_XMLNode *root) { GF_XMLAttribute *att; @@ -614,6 +656,8 @@ 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; } + else if (!strcmp(att->name, "selectionRriority")) com->selection_priority = gf_mpd_parse_int(att->value); + else if (!strcmp(att->name, "tag")) com->tag = gf_mpd_parse_string(att->value); } i = 0; @@ -634,6 +678,13 @@ else if (!strcmp(child->name, "SupplementalProperty")) { gf_mpd_parse_descriptor(com->supplemental_properties, child); } + else if (!strcmp(child->name, "ProducerReferenceTime")) { + GF_MPD_ProducerReferenceTime *pref = gf_mpd_parse_produce_ref_time(child); + if (pref) { + if (!com->producer_reference_time) com->producer_reference_time = gf_list_new(); + gf_list_add(com->producer_reference_time, pref); + } + } } } @@ -700,7 +751,7 @@ else if (!strcmp(att->name, "moofSN")) dasher->moof_sn = gf_mpd_parse_int(att->value); else if (!strcmp(att->name, "moofInc")) dasher->moof_sn_inc = gf_mpd_parse_int(att->value); else if (!strcmp(att->name, "lastDynPeriodID")) dasher->last_dyn_period_id = gf_mpd_parse_int(att->value); - + else if (!strcmp(att->name, "subdurForced")) dasher->subdur_forced = gf_mpd_parse_bool(att->value); } return dasher; } @@ -1153,6 +1204,15 @@ gf_free(item); } +void gf_mpd_producer_reftime_free(void *item) +{ + GF_MPD_ProducerReferenceTime *pref=(GF_MPD_ProducerReferenceTime*) item; + if (pref->scheme) gf_free(pref->scheme); + if (pref->wallclock) gf_free(pref->wallclock); + if (pref->utc_timing) gf_mpd_descriptor_free(pref->utc_timing); + gf_free(item); +} + void gf_mpd_common_attributes_free(GF_MPD_CommonAttributes *ptr) { if (ptr->profiles) gf_free(ptr->profiles); @@ -1166,6 +1226,7 @@ gf_mpd_del_list(ptr->content_protection, gf_mpd_descriptor_free, 0); gf_mpd_del_list(ptr->essential_properties, gf_mpd_descriptor_free, 0); gf_mpd_del_list(ptr->supplemental_properties, gf_mpd_descriptor_free, 0); + gf_mpd_del_list(ptr->producer_reference_time, gf_mpd_producer_reftime_free, 0); } void gf_mpd_representation_free(void *_item) @@ -1278,6 +1339,7 @@ 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_mpd_del_list(mpd->utc_timings, gf_mpd_descriptor_free, 0); gf_mpd_extensible_free((GF_MPD_ExtensibleVirtual*) mpd); gf_free(mpd); } @@ -1381,6 +1443,8 @@ } else if (!strcmp(child->name, "BaseURL")) { e = gf_mpd_parse_base_url(mpd->base_URLs, child); if (e) return e; + } else if (!strcmp(child->name, "UTCTiming")) { + gf_mpd_parse_descriptor(mpd->utc_timings, child); } else { MPD_STORE_EXTENSION_NODE(mpd) } @@ -1389,18 +1453,23 @@ return GF_OK; } - -GF_EXPORT -GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_base_url) +static void gf_mpd_init_struct(GF_MPD *mpd) { - if (!root || !mpd) return GF_BAD_PARAM; - 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(); + mpd->utc_timings = gf_list_new(); +} + +GF_EXPORT +GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_base_url) +{ + if (!root || !mpd) return GF_BAD_PARAM; + + gf_mpd_init_struct(mpd); /*setup some defaults*/ mpd->type = GF_MPD_TYPE_STATIC; @@ -1424,12 +1493,8 @@ char str[1024]; if (!mpd) return GF_BAD_PARAM; - 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(); + gf_mpd_init_struct(mpd); + mpd->time_shift_buffer_depth = (u32) -1; /*infinite by default*/ mpd->xml_namespace = "urn:mpeg:dash:schema:mpd:2011"; mpd->type = is_end ? GF_MPD_TYPE_STATIC : GF_MPD_TYPE_DYNAMIC; @@ -2601,28 +2666,32 @@ } } +static void gf_mpd_print_desc(FILE *out, GF_MPD_Descriptor *desc, char *desc_name, s32 indent) +{ + gf_mpd_nl(out, indent); + gf_fprintf(out, "<%s", desc_name); + if (desc->id) gf_fprintf(out, " id=\"%s\"", desc->id); + if (desc->scheme_id_uri) gf_fprintf(out, " schemeIdUri=\"%s\"", desc->scheme_id_uri); + if (desc->value) gf_fprintf(out, " value=\"%s\"", desc->value); + + if (desc->attributes) gf_mpd_extensible_print_attr(out, (GF_MPD_ExtensibleVirtual*)desc); + + if (desc->children) { + gf_mpd_extensible_print_nodes(out, (GF_MPD_ExtensibleVirtual*)desc, indent); + gf_mpd_nl(out, indent); + gf_fprintf(out, "</%s>", desc_name); + gf_mpd_lf(out, indent); + } else { + gf_fprintf(out, "/>"); + gf_mpd_lf(out, indent); + } +} static void gf_mpd_print_descriptors(FILE *out, GF_List *desc_list, char *desc_name, s32 indent) { u32 i=0; GF_MPD_Descriptor *desc; while ((desc = (GF_MPD_Descriptor *)gf_list_enum(desc_list, &i))) { - gf_mpd_nl(out, indent); - gf_fprintf(out, "<%s", desc_name); - if (desc->id) gf_fprintf(out, " id=\"%s\"", desc->id); - if (desc->scheme_id_uri) gf_fprintf(out, " schemeIdUri=\"%s\"", desc->scheme_id_uri); - if (desc->value) gf_fprintf(out, " value=\"%s\"", desc->value); - - if (desc->attributes) gf_mpd_extensible_print_attr(out, (GF_MPD_ExtensibleVirtual*)desc); - - if (desc->children) { - gf_mpd_extensible_print_nodes(out, (GF_MPD_ExtensibleVirtual*)desc, indent); - gf_mpd_nl(out, indent); - gf_fprintf(out, "</%s>", desc_name); - gf_mpd_lf(out, indent); - } else { - gf_fprintf(out, "/>"); - gf_mpd_lf(out, indent); - } + gf_mpd_print_desc(out, desc, desc_name, indent); } } @@ -2664,6 +2733,10 @@ if ((ca->max_playout_rate!=1.0)) gf_fprintf(out, " maxPlayoutRate=\"%g\"", ca->max_playout_rate); if (ca->coding_dependency) gf_fprintf(out, " codingDependency=\"true\""); if (ca->scan_type != GF_MPD_SCANTYPE_UNKNOWN) gf_fprintf(out, " scanType=\"%s\"", ca->scan_type == GF_MPD_SCANTYPE_PROGRESSIVE ? "progressive" : "interlaced"); + + if (ca->selection_priority) gf_fprintf(out, " selectionPriority=\"%d\"", ca->selection_priority); + if (ca->tag) gf_fprintf(out, " selectionPriority=\"%s\"", ca->tag); + } static u32 gf_mpd_print_common_children(FILE *out, GF_MPD_CommonAttributes *ca, s32 indent) @@ -2674,6 +2747,38 @@ gf_mpd_print_descriptors(out, ca->essential_properties, "EssentialProperty", indent); gf_mpd_print_descriptors(out, ca->supplemental_properties, "SupplementalProperty", indent); + if (ca->producer_reference_time) { + u32 i, count = gf_list_count(ca->producer_reference_time); + for (i=0; i<count; i++) { + GF_MPD_ProducerReferenceTime *pref = gf_list_get(ca->producer_reference_time, i); + gf_mpd_nl(out, indent); + gf_fprintf(out, "<ProducerReferenceTime id=\"%d\" presentationTime=\"%d\"", pref->ID, pref->presentation_time); + if (pref->inband) gf_fprintf(out, " inband=\"true\""); + if (pref->wallclock) gf_fprintf(out, " wallClockTime=\"%s\"", pref->wallclock); + switch (pref->type) { + case GF_MPD_PRODUCER_REF_ENCODER: + gf_fprintf(out, " type=\"encoder\""); + break; + case GF_MPD_PRODUCER_REF_CAPTURED: + gf_fprintf(out, " type=\"captured\""); + break; + case GF_MPD_PRODUCER_REF_APPLICATION: + gf_fprintf(out, " type=\"application\""); + if (pref->scheme) gf_fprintf(out, " applicationScheme=\"%s\"", pref->scheme); + break; + } + if (pref->utc_timing) { + gf_fprintf(out, ">"); + gf_mpd_lf(out, indent); + gf_mpd_print_desc(out, pref->utc_timing, "UTCTiming", indent+1); + gf_fprintf(out, "</ProducerReferenceTime>"); + gf_mpd_lf(out, indent); + } else { + gf_fprintf(out, "/>"); + gf_mpd_lf(out, indent); + } + } + } if (ca->isobmf_tracks) { u32 k=0; GF_MPD_ISOBMFInfo *info; @@ -2750,6 +2855,9 @@ if (dasher->last_dyn_period_id) { gf_fprintf(out, "lastDynPeriodID=\"%d\" ", dasher->last_dyn_period_id); } + if (dasher->subdur_forced) { + gf_fprintf(out, "subdurForced=\"true\" "); + } gf_fprintf(out, "ownsSet=\"%s\"/>", dasher->owns_set ? "true" : "false"); gf_mpd_lf(out, indent); @@ -3019,8 +3127,29 @@ return GF_OK; } -static void gf_mpd_write_m3u8_playlist_tags_entry(FILE *out, const GF_MPD_Representation *rep, char *m3u8_name, const char *codec_ext, const char *g_type, const char *g_id_pref, u32 g_as_idx, const char *g2_type, const char *g2_id_pref, u32 g2_as_idx) +static void gf_mpd_write_m3u8_playlist_tags_entry(FILE *out, const GF_MPD_Representation *rep, char *m3u8_name, const char *codec_ext, const char *g_type, const char *g_id_pref, u32 g_as_idx, const char *g2_type, const char *g2_id_pref, u32 g2_as_idx, GF_List *groups_done) { + if (groups_done) { + u32 i, count=gf_list_count(groups_done); + Bool g1_done = GF_FALSE; + Bool g2_done = GF_FALSE; + for (i=0; i<count; i++) { + const char *group_name = gf_list_get(groups_done, i); + if (g_id_pref && !strcmp(group_name, g_id_pref)) g1_done=GF_TRUE; + if (g2_id_pref && !strcmp(group_name, g2_id_pref)) g1_done=GF_TRUE; + } + if (g_id_pref) { + if (g1_done) return; + if (!g_as_idx) + gf_list_add(groups_done, (void *) g_id_pref); + } + if (g2_id_pref) { + if (g2_done) return; + if (!g2_as_idx) + gf_list_add(groups_done, (void *) g2_id_pref); + } + } + gf_fprintf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d,CODECS=\"%s", rep->bandwidth, rep->codecs); if (codec_ext) gf_fprintf(out, ",%s", codec_ext); @@ -3031,10 +3160,18 @@ if (rep->fps) gf_fprintf(out,",FRAME-RATE=\"%.03g\"", rep->fps); - if (g_type && g_id_pref) - gf_fprintf(out,",%s=\"%s%d\"", g_type, g_id_pref, g_as_idx); - if (g2_type && g2_id_pref) - gf_fprintf(out,",%s=\"%s%d\"", g2_type, g2_id_pref, g2_as_idx); + if (g_type && g_id_pref) { + gf_fprintf(out, ",%s=\"%s", g_type, g_id_pref); + if (g_as_idx) + gf_fprintf(out, "%d", g_as_idx); + gf_fprintf(out, "\""); + } + if (g2_type && g2_id_pref) { + gf_fprintf(out,",%s=\"%s", g2_type, g2_id_pref); + if (g2_as_idx) + gf_fprintf(out,"%d", g2_as_idx); + gf_fprintf(out,"\""); + } gf_fprintf(out,"\n"); gf_fprintf(out, "%s\n",m3u8_name); @@ -3046,6 +3183,7 @@ u32 i, j; GF_MPD_AdaptationSet *r_as; GF_MPD_Representation *r_rep; + GF_List *groups_done; if (!rep->mime_type) return; @@ -3059,13 +3197,16 @@ g_id = "audio"; } else if (rep->streamtype==GF_STREAM_TEXT) { - g_type = "SUBTITLE"; + g_type = "SUBTITLES"; g_id = "subs"; } if (!g_type || !g_id) return; - gf_fprintf(out, "#EXT-X-MEDIA:TYPE=%s,GROUP-ID=\"%s%d\",NAME=\"%s\",LANGUAGE=\"%s\",AUTOSELECT=YES,URI=\"%s\"", g_type, g_id, as_idx, rep->id, as->lang, m3u8_name); + if (rep->groupID) + gf_fprintf(out, "#EXT-X-MEDIA:TYPE=%s,GROUP-ID=\"%s\",NAME=\"%s\",LANGUAGE=\"%s\",AUTOSELECT=YES,URI=\"%s\"", g_type, rep->groupID, rep->id, as->lang, m3u8_name); + else + gf_fprintf(out, "#EXT-X-MEDIA:TYPE=%s,GROUP-ID=\"%s%d\",NAME=\"%s\",LANGUAGE=\"%s\",AUTOSELECT=YES,URI=\"%s\"", g_type, g_id, as_idx, rep->id, as->lang, m3u8_name); if (rep->nb_chan) gf_fprintf(out,",CHANNELS=\"%d\"", rep->nb_chan); return; @@ -3073,9 +3214,11 @@ //no other streams, directly write the entry if (!nb_audio && !nb_subs && !nb_cc) { - gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, NULL, NULL, NULL, 0, NULL, NULL, 0); + gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL); return; } + groups_done = gf_list_new(); + //otherwise browse all adaptation sets i=0; while ( (r_as = (GF_MPD_AdaptationSet *) gf_list_enum(period->adaptation_sets, &i))) { @@ -3097,11 +3240,15 @@ g_type = "AUDIO"; g_id = "audio"; g_codec = r_rep->codecs; + if (r_rep->groupID) { + g_id = r_rep->groupID; + g_as_idx = 0; + } } is_audio = GF_TRUE; } else { if (r_rep->streamtype==GF_STREAM_TEXT) { - g_type = "SUBTITLE"; + g_type = "SUBTITLES"; g_id = "subs"; } } @@ -3109,7 +3256,7 @@ if (!g_type) continue; //no audio, or no subs if (!is_audio || !nb_subs) { - gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, g_codec, g_type, g_id, g_as_idx, NULL, NULL, 0); + gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, g_codec, g_type, g_id, g_as_idx, NULL, NULL, 0, groups_done); continue; } //audio and subs, we need a second loop on audio to get all subs @@ -3123,20 +3270,25 @@ r2_rep = (GF_MPD_Representation *) gf_list_get(r2_as->representations, 0); if (r2_rep->streamtype==GF_STREAM_TEXT) { - g2_type = "SUBTITLE"; + g2_type = "SUBTITLES"; g2_id = "subs"; + if (r_rep->groupID) { + g2_id = r_rep->groupID; + g2_as_idx = 0; + } } if (!g2_type) continue; - gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, g_codec, g_type, g_id, g_as_idx, g2_type, g2_id, g2_as_idx); + gf_mpd_write_m3u8_playlist_tags_entry(out, rep, m3u8_name, g_codec, g_type, g_id, g_as_idx, g2_type, g2_id, g2_as_idx, groups_done); } } + gf_list_del(groups_done); } static const char *gf_mpd_m3u8_get_init_seg(const GF_MPD_Period *period, const GF_MPD_AdaptationSet *as, const GF_MPD_Representation *rep) { const char *url = NULL; - if (rep->segment_list) url = rep->segment_list->initialization_segment->sourceURL; + if (rep->segment_list && rep->segment_list->initialization_segment) url = rep->segment_list->initialization_segment->sourceURL; else if (rep->segment_template && rep->segment_template->initialization) url = rep->segment_template->initialization; else if (rep->segment_template && rep->segment_template->initialization_segment) url = rep->segment_template->initialization_segment->sourceURL; @@ -3217,7 +3369,11 @@ assert(base_url); if (init) { - gf_fprintf(out,"#EXT-X-MAP:URI=\"%s\",BYTERANGE=\"%d@"LLU"\"\n", base_url->URL, (u32) (1+init->byte_range->end_range - init->byte_range->start_range), init->byte_range->start_range); + if (init->byte_range) { + gf_fprintf(out,"#EXT-X-MAP:URI=\"%s\",BYTERANGE=\"%d@"LLU"\"\n", base_url->URL, (u32) (1+init->byte_range->end_range - init->byte_range->start_range), init->byte_range->start_range); + } else { + gf_fprintf(out,"#EXT-X-MAP:URI=\"%s\"\n", base_url->URL); + } } for (i=0; i<count; i++) { @@ -3415,10 +3571,6 @@ gf_fprintf(out, "\n"); } } - - if (mpd->type != GF_MPD_TYPE_DYNAMIC) - gf_fprintf(out,"#EXT-X-ENDLIST\n"); - gf_free(m3u8_name_rad); gf_free(szVariantName); return GF_OK; @@ -3558,6 +3710,8 @@ gf_mpd_lf(out, indent); } + if (gf_list_count(mpd->utc_timings)) + gf_mpd_print_descriptors(out, mpd->utc_timings, "UTCTiming", indent+1); /* i=0; while ((text = (char *)gf_list_enum(mpd->metrics, &i))) { @@ -4585,12 +4739,7 @@ if (!root || !mpd) return GF_BAD_PARAM; - 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(); + gf_mpd_init_struct(mpd); /*setup some defaults*/ mpd->type = GF_MPD_TYPE_STATIC; @@ -4683,7 +4832,7 @@ Bool is_init_template = (seg_type==GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE) ? GF_TRUE : GF_FALSE; Bool is_index_template = (seg_type==GF_DASH_TEMPLATE_REPINDEX_TEMPLATE) ? GF_TRUE : GF_FALSE; Bool needs_init=((is_init || is_init_template) && !is_bs_switching) ? GF_TRUE : GF_FALSE; - Bool has_init_keyword = GF_FALSE; + u32 has_init_keyword = 0; Bool needs_index = GF_FALSE; u32 char_template = 0; size_t seg_rad_name_len; @@ -4708,14 +4857,18 @@ seg_rad_name_len = strlen(seg_rad_name); - if ( (is_index || is_index_template) && !strstr(seg_rad_name, "$Index")) { - needs_index = GF_TRUE; + if (seg_type!=GF_DASH_TEMPLATE_REPINDEX) { + if ( (is_index || is_index_template) && !strstr(seg_rad_name, "$Index")) { + needs_index = GF_TRUE; + } } if (strstr(seg_rad_name, "$RepresentationID$") || strstr(seg_rad_name, "$Bandwidth$")) needs_init = GF_FALSE; if (strstr(seg_rad_name, "$Init=")) - has_init_keyword = GF_TRUE; + has_init_keyword = 1; + if (strstr(seg_rad_name, "$XInit=")) + has_init_keyword = 2; while (char_template <= seg_rad_name_len) { char szFmt[20]; @@ -4773,6 +4926,18 @@ char_template += (u32) strlen(seg_rad_name + char_template)+1; if (sep) sep[0] = '$'; } + else if (!strnicmp(& seg_rad_name[char_template], "$XInit=", 7)) { + char *sep = strchr(seg_rad_name + char_template+6, '$'); + if (sep) sep[0] = 0; + if (is_init || is_init_template) { + strcpy(segment_name, seg_rad_name + char_template+7); + needs_init = GF_FALSE; + if (sep) sep[0] = '$'; + break; + } + char_template += (u32) strlen(seg_rad_name + char_template)+1; + if (sep) sep[0] = '$'; + } else if (!strnicmp(& seg_rad_name[char_template], "$Index=", 7)) { char *sep = strchr(seg_rad_name + char_template+7, '$'); if (sep) sep[0] = 0; @@ -4839,7 +5004,11 @@ strcat(segment_name, seg_ext); } - if ((seg_type != GF_DASH_TEMPLATE_TEMPLATE) && (seg_type != GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE)) { + if ((seg_type != GF_DASH_TEMPLATE_TEMPLATE) + && (seg_type != GF_DASH_TEMPLATE_SEGMENT) + && (seg_type != GF_DASH_TEMPLATE_INITIALIZATION) + && (seg_type != GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE) + ) { char *sep = strrchr(segment_name, '/'); if (sep) { char cv = sep[0];
View file
gpac-1.0.0.tar.gz/src/media_tools/mpegts.c -> gpac-1.0.1.tar.gz/src/media_tools/mpegts.c
Changed
@@ -190,7 +190,7 @@ size -= 10; //TODO, handle more ID3 tags ? - if (ftag==ID3V2_FRAME_TXXX) { + if (ftag==GF_ID3V2_FRAME_TXXX) { u32 tpos = (u32) gf_bs_get_position(bs); char *text = data+tpos; add_text(output, output_size, output_pos, text, fsize); @@ -2077,6 +2077,7 @@ if (pes->temi_pending) { pes->temi_pending = 0; pes->temi_tc.pes_pts = pes->PTS; + pes->temi_tc.pid = pes->pid; if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_TEMI_TIMECODE, &pes->temi_tc); } @@ -2305,6 +2306,7 @@ char URL[255]; GF_M2TS_TemiLocationDescriptor temi_loc; memset(&temi_loc, 0, sizeof(GF_M2TS_TemiLocationDescriptor) ); + temi_loc.pid = pid; temi_loc.reload_external = gf_bs_read_int(bs, 1); temi_loc.is_announce = gf_bs_read_int(bs, 1); temi_loc.is_splicing = gf_bs_read_int(bs, 1); @@ -2789,6 +2791,7 @@ gf_m2ts_reset_parsers_for_program(ts, NULL); ts->pck_number = 0; + ts->buffer_size = 0; gf_m2ts_section_filter_reset(ts->cat); gf_m2ts_section_filter_reset(ts->pat);
View file
gpac-1.0.0.tar.gz/src/odf/odf_dump.c -> gpac-1.0.1.tar.gz/src/odf/odf_dump.c
Changed
@@ -873,7 +873,7 @@ GF_Err DumpRawUIConfig(GF_DefaultDescriptor *dsi, FILE *trace, u32 indent, Bool XMTDump, u32 oti) { - char devName[255]; + char devName[256]; u32 i; u64 len; GF_BitStream *bs;
View file
gpac-1.0.0.tar.gz/src/odf/odf_parse.c -> gpac-1.0.1.tar.gz/src/odf/odf_parse.c
Changed
@@ -452,8 +452,8 @@ OD_ParseBinData(val, &dsi->data, &dsi->dataLength); ret = 1; } else if (!strnicmp(val, "file:", 5)) { - gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength); - ret = 1; + if (gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength) == GF_OK) + ret = 1; } else if (!strlen(val)) ret = 1; } if (!stricmp(fieldName, "src")) { @@ -465,8 +465,8 @@ OD_ParseBinData(val, &dsi->data, &dsi->dataLength); ret = 1; } else if (!strnicmp(val, "file:", 5)) { - gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength); - ret = 1; + if (gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength) == GF_OK) + ret = 1; } } } @@ -491,8 +491,8 @@ OD_ParseBinData(val, &uic->ui_data, &uic->ui_data_length); ret = 1; } else if (!strnicmp(val, "file:", 5)) { - gf_file_load_data(val+5, (u8 **) &uic->ui_data, &uic->ui_data_length); - ret = 1; + if (gf_file_load_data(val+5, (u8 **) &uic->ui_data, &uic->ui_data_length)==GF_OK) + ret = 1; } else { #ifndef GPAC_MINIMAL_ODF ret = OD_ParseUIConfig(val, &uic->ui_data, &uic->ui_data_length);
View file
gpac-1.0.0.tar.gz/src/quickjs/quickjs.c -> gpac-1.0.1.tar.gz/src/quickjs/quickjs.c
Changed
@@ -206,7 +206,7 @@ #define JS_STACK_SIZE_MAX 65536 #define JS_STRING_LEN_MAX ((1 << 30) - 1) -#if defined(_WIN32) +#if defined(_WIN32) && !defined(__MINGW32__) #define __exception /* */ typedef int64_t ssize_t; #else @@ -15303,7 +15303,7 @@ goto fail; } - /* the constructor property must be first. It can be overriden by + /* the constructor property must be first. It can be overridden by computed property names */ if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, JS_DupValue(ctx, ctor),
View file
gpac-1.0.0.tar.gz/src/scene_manager/scene_engine.c -> gpac-1.0.1.tar.gz/src/scene_manager/scene_engine.c
Changed
@@ -1026,7 +1026,7 @@ /*since we're encoding in BIFS we must get MPEG-4 nodes only*/ seng->loader.flags = GF_SM_LOAD_MPEG4_STRICT; - /* assign a loader type only if it was not requested (e.g. DIMS should not be overriden by SVG) */ + /* assign a loader type only if it was not requested (e.g. DIMS should not be overridden by SVG) */ if (!seng->loader.type) { if (inputContext[0] == '<') { if (strstr(inputContext, "<svg ")) seng->loader.type = GF_SM_LOAD_SVG;
View file
gpac-1.0.0.tar.gz/src/scenegraph/qjs_common.h -> gpac-1.0.1.tar.gz/src/scenegraph/qjs_common.h
Changed
@@ -133,6 +133,8 @@ JSValue dom_event_remove_listener(JSContext *c, JSValueConst obj, int argc, JSValueConst *argv); JSValue xml_dom3_not_implemented(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +#ifndef GPAC_DISABLE_SVG + /*dom event listener interface, exported for XHR module*/ #define JS_DOM3_EVENT_TARGET_INTERFACE \ JS_CFUNC_DEF("addEventListenerNS", 3, dom_event_add_listener), \ @@ -141,6 +143,12 @@ JS_CFUNC_DEF("removeEventListener", 2, dom_event_remove_listener), \ JS_CFUNC_DEF("dispatchEvent", 1, xml_dom3_not_implemented), +#else + +#define JS_DOM3_EVENT_TARGET_INTERFACE + +#endif + /*defines a new global object "evt" of type Event*/ JSValue dom_js_define_event(struct JSContext *c); @@ -234,6 +242,7 @@ void qjs_module_init_xhr(JSContext *c); void qjs_module_init_evg(JSContext *c); void qjs_module_init_webgl(JSContext *c); +void qjs_module_init_gpaccore(JSContext *c); #ifdef __cplusplus
View file
gpac-1.0.0.tar.gz/src/scenegraph/svg_js.c -> gpac-1.0.1.tar.gz/src/scenegraph/svg_js.c
Changed
@@ -1971,7 +1971,7 @@ GF_Matrix2D *mx1, mx2; mx1 = (GF_Matrix2D *) JS_GetOpaque(obj, matrixClass.class_id); if (!mx1 || (argc!=2)) return JS_EXCEPTION; - if (!JS_ToFloat64(c, &scale, argv[0])) return JS_EXCEPTION; + if (JS_ToFloat64(c, &scale, argv[0])) return JS_EXCEPTION; gf_mx2d_init(mx2); mx2.m[0] = mx2.m[4] = FLT2FIX(scale); @@ -1986,7 +1986,7 @@ mx1 = (GF_Matrix2D *) JS_GetOpaque(obj, matrixClass.class_id); if (!mx1 || (argc!=2)) return JS_EXCEPTION; - if (!JS_ToFloat64(c, &angle, argv[0])) return JS_EXCEPTION; + if (JS_ToFloat64(c, &angle, argv[0])) return JS_EXCEPTION; gf_mx2d_init(mx2); gf_mx2d_add_rotation(&mx2, 0, 0, gf_mulfix(FLT2FIX(angle/180), GF_PI));
View file
gpac-1.0.0.tar.gz/src/scenegraph/vrml_js.c -> gpac-1.0.1.tar.gz/src/scenegraph/vrml_js.c
Changed
@@ -120,6 +120,7 @@ } \ } +#ifndef GPAC_DISABLE_PLAYER static Bool ScriptAction(JSContext *c, GF_SceneGraph *scene, u32 type, GF_Node *node, GF_JSAPIParam *param) { if (!scene) { @@ -130,6 +131,7 @@ return scene->script_action(scene->script_action_cbck, type, node, param); return 0; } +#endif// GPAC_DISABLE_PLAYER GF_JSClass SFNodeClass; #ifndef GPAC_DISABLE_VRML @@ -288,10 +290,10 @@ u32 buf_len; u8 *buf; JSValue func_val; - gf_file_load_data(module_name, &buf, &buf_len); + GF_Err e = gf_file_load_data(module_name, &buf, &buf_len); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", module_name); + if (e != GF_OK) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", module_name, gf_error_to_string(e) ); return NULL; } /* compile the module */ @@ -373,12 +375,17 @@ void gf_sg_script_to_node_field(struct JSContext *c, JSValue v, GF_FieldInfo *field, GF_Node *owner, GF_JSField *parent); JSValue gf_sg_script_to_qjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_Node *parent, Bool force_evaluate); +#ifndef GPAC_DISABLE_PLAYER static void JSScript_NodeModified(GF_SceneGraph *sg, GF_Node *node, GF_FieldInfo *info, GF_Node *script); +#endif + Bool JSScriptFromFile(GF_Node *node, const char *opt_file, Bool no_complain, JSValue *rval); +#ifndef GPAC_DISABLE_SVG static JSValue vrml_event_add_listener(JSContext *c, JSValueConst this_val, int argc, JSValueConst *argv); static JSValue vrml_event_remove_listener(JSContext *c, JSValueConst this_val, int argc, JSValueConst *argv); +#endif // GPAC_DISABLE_SVG void gf_js_call_gc(JSContext *c) { @@ -400,113 +407,6 @@ } -#ifndef GPAC_DISABLE_VRML - -/*MPEG4 & X3D tags (for node tables & script handling)*/ -#include <gpac/nodes_mpeg4.h> -#include <gpac/nodes_x3d.h> - -void SFColor_fromHSV(SFColor *col) -{ - Fixed f, q, t, p, hue, sat, val; - u32 i; - hue = col->red; - sat = col->green; - val = col->blue; - if (sat==0) { - col->red = col->green = col->blue = val; - return; - } - if (hue == FIX_ONE) hue = 0; - else hue *= 6; - i = FIX2INT( gf_floor(hue) ); - f = hue-i; - p = gf_mulfix(val, FIX_ONE - sat); - q = gf_mulfix(val, FIX_ONE - gf_mulfix(sat,f)); - t = gf_mulfix(val, FIX_ONE - gf_mulfix(sat, FIX_ONE - f)); - switch (i) { - case 0: - col->red = val; - col->green = t; - col->blue = p; - break; - case 1: - col->red = q; - col->green = val; - col->blue = p; - break; - case 2: - col->red = p; - col->green = val; - col->blue = t; - break; - case 3: - col->red = p; - col->green = q; - col->blue = val; - break; - case 4: - col->red = t; - col->green = p; - col->blue = val; - break; - case 5: - col->red = val; - col->green = p; - col->blue = q; - break; - } -} - -void SFColor_toHSV(SFColor *col) -{ - Fixed h, s; - Fixed _max = MAX(col->red, MAX(col->green, col->blue)); - Fixed _min = MIN(col->red, MAX(col->green, col->blue)); - - s = (_max == 0) ? 0 : gf_divfix(_max - _min, _max); - if (s != 0) { - Fixed rl = gf_divfix(_max - col->red, _max - _min); - Fixed gl = gf_divfix(_max - col->green, _max - _min); - Fixed bl = gf_divfix(_max - col->blue, _max - _min); - if (_max == col->red) { - if (_min == col->green) h = 60*(5+bl); - else h = 60*(1-gl); - } else if (_max == col->green) { - if (_min == col->blue) h = 60*(1+rl); - else h = 60*(3-bl); - } else { - if (_min == col->red) h = 60*(3+gl); - else h = 60*(5-rl); - } - } else { - h = 0; - } - col->red = h; - col->green = s; - col->blue = _max; -} - -static GFINLINE GF_JSField *NewJSField(JSContext *c) -{ - GF_JSField *ptr; - GF_SAFEALLOC(ptr, GF_JSField); - if (!ptr) return NULL; - ptr->js_ctx = c; - ptr->obj = JS_UNDEFINED; - return ptr; -} - -static GFINLINE M_Script *JS_GetScript(JSContext *c) -{ - return (M_Script *) JS_GetContextOpaque(c); -} -static GFINLINE GF_ScriptPriv *JS_GetScriptStack(JSContext *c) -{ - M_Script *script = (M_Script *) JS_GetContextOpaque(c); - return script->sgprivate->UserPrivate; -} - static JSValue js_print_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, u32 ltool, u32 error_type) { int i=0; @@ -544,9 +444,9 @@ } if (error_type==2) { #ifndef GPAC_DISABLE_LOG - GF_LOG(logl, ltool, (" Throw")); + GF_LOG(logl, ltool, ("Throw ")); #else - fprintf(stderr, " Throw"); + fprintf(stderr, "Throw "); #endif } @@ -558,6 +458,8 @@ gf_sys_format_help(stderr, GF_PRINTARG_HIGHLIGHT_FIRST, "%s\n", str); } else if (logl==-2) { gf_sys_format_help(stderr, 0, "%s\n", str); + } else if (!log_name || (logl<0)) { + fprintf(stderr, "%s%s", (first) ? "" : " ", str); } else { #ifndef GPAC_DISABLE_LOG GF_LOG(logl, ltool, ("%s%s", (first) ? "" : " ", str)); @@ -624,6 +526,114 @@ } } +#ifndef GPAC_DISABLE_VRML + +/*MPEG4 & X3D tags (for node tables & script handling)*/ +#include <gpac/nodes_mpeg4.h> +#include <gpac/nodes_x3d.h> + +void SFColor_fromHSV(SFColor *col) +{ + Fixed f, q, t, p, hue, sat, val; + u32 i; + hue = col->red; + sat = col->green; + val = col->blue; + if (sat==0) { + col->red = col->green = col->blue = val; + return; + } + if (hue == FIX_ONE) hue = 0; + else hue *= 6; + i = FIX2INT( gf_floor(hue) ); + f = hue-i; + p = gf_mulfix(val, FIX_ONE - sat); + q = gf_mulfix(val, FIX_ONE - gf_mulfix(sat,f)); + t = gf_mulfix(val, FIX_ONE - gf_mulfix(sat, FIX_ONE - f)); + switch (i) { + case 0: + col->red = val; + col->green = t; + col->blue = p; + break; + case 1: + col->red = q; + col->green = val; + col->blue = p; + break; + case 2: + col->red = p; + col->green = val; + col->blue = t; + break; + case 3: + col->red = p; + col->green = q; + col->blue = val; + break; + case 4: + col->red = t; + col->green = p; + col->blue = val; + break; + case 5: + col->red = val; + col->green = p; + col->blue = q; + break; + } +} + +void SFColor_toHSV(SFColor *col) +{ + Fixed h, s; + Fixed _max = MAX(col->red, MAX(col->green, col->blue)); + Fixed _min = MIN(col->red, MAX(col->green, col->blue)); + + s = (_max == 0) ? 0 : gf_divfix(_max - _min, _max); + if (s != 0) { + Fixed rl = gf_divfix(_max - col->red, _max - _min); + Fixed gl = gf_divfix(_max - col->green, _max - _min); + Fixed bl = gf_divfix(_max - col->blue, _max - _min); + if (_max == col->red) { + if (_min == col->green) h = 60*(5+bl); + else h = 60*(1-gl); + } else if (_max == col->green) { + if (_min == col->blue) h = 60*(1+rl); + else h = 60*(3-bl); + } else { + if (_min == col->red) h = 60*(3+gl); + else h = 60*(5-rl); + } + } else { + h = 0; + } + col->red = h; + col->green = s; + col->blue = _max; +} + +static GFINLINE GF_JSField *NewJSField(JSContext *c) +{ + GF_JSField *ptr; + GF_SAFEALLOC(ptr, GF_JSField); + if (!ptr) return NULL; + ptr->js_ctx = c; + ptr->obj = JS_UNDEFINED; + return ptr; +} + +static GFINLINE M_Script *JS_GetScript(JSContext *c) +{ + return (M_Script *) JS_GetContextOpaque(c); +} +static GFINLINE GF_ScriptPriv *JS_GetScriptStack(JSContext *c) +{ + M_Script *script = (M_Script *) JS_GetContextOpaque(c); + return script->sgprivate->UserPrivate; +} + + static JSValue getName(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { return JS_NewString(ctx, "GPAC RichMediaEngine"); @@ -4373,6 +4383,7 @@ JS_SetContextOpaque(priv->js_ctx, node); vrml_js_init_api(priv, node); + qjs_module_init_gpaccore(priv->js_ctx); qjs_module_init_scenejs(priv->js_ctx); qjs_module_init_storage(priv->js_ctx); @@ -4461,6 +4472,7 @@ } +#ifndef GPAC_DISABLE_PLAYER static void JSScript_NodeModified(GF_SceneGraph *sg, GF_Node *node, GF_FieldInfo *info, GF_Node *script) { u32 i; @@ -4575,6 +4587,7 @@ } } } +#endif GF_EXPORT void gf_sg_handle_dom_event_for_vrml(GF_Node *node, GF_DOM_Event *event, GF_Node *observer) @@ -4713,10 +4726,6 @@ /* * locking/try-locking the JS context - * we need to test whether the calling thread already has the lock on the script context - * if this is not the case (i.e. first lock on mutex), we switch JS context threads and - * call begin/end requests. Nesting begin/end request in a reentrant way crashes JS - * (mozilla doc is wrong here) * * */ GF_EXPORT @@ -4741,6 +4750,12 @@ return 0; } +JSRuntime *gf_js_get_rt() +{ + if (!js_rt) return NULL; + return js_rt->js_runtime; +} + #endif /* GPAC_HAS_QJS */ GF_Err gf_scene_execute_script(GF_SceneGraph *sg, const char *com)
View file
gpac-1.0.0.tar.gz/src/utils/Remotery.c -> gpac-1.0.1.tar.gz/src/utils/Remotery.c
Changed
@@ -49,7 +49,6 @@ #define RMT_IMPL #include <gpac/tools.h> - #ifdef RMT_PLATFORM_WINDOWS #pragma comment(lib, "ws2_32.lib") #endif @@ -92,7 +91,7 @@ #include <mach/mach.h> #include <sys/time.h> #else - #ifndef __FreeBSD__ + #if !defined(__FreeBSD__) && !defined(__OpenBSD__) #include <malloc.h> #endif #endif @@ -113,7 +112,7 @@ #ifdef RMT_PLATFORM_LINUX #include <time.h> - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__OpenBSD__) #include <pthread_np.h> #else #include <sys/prctl.h> @@ -248,14 +247,14 @@ clock_t time = clock(); // CLOCKS_PER_SEC is 128 on FreeBSD, causing div/0 - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__OpenBSD__) rmtU32 msTime = (rmtU32) (time * 1000 / CLOCKS_PER_SEC); #else rmtU32 msTime = (rmtU32) (time / (CLOCKS_PER_SEC / 1000)); #endif return msTime; - + #endif } @@ -702,7 +701,7 @@ RMT_UNREFERENCED_PARAMETER(nb_attempts); #ifdef RMT_PLATFORM_LINUX - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__OpenBSD__) char path[] = "/tmp/ring-buffer-XXXXXX"; #else char path[] = "/dev/shm/ring-buffer-XXXXXX"; @@ -791,7 +790,7 @@ if (buffer->file_map_handle == NULL) break; - + #ifndef _UWP // NON-UWP Windows Desktop Version // Reserve two contiguous pages of virtual memory @@ -804,7 +803,7 @@ // address range from underneath us so multiple attempts need to be made. VirtualFree(desired_addr, 0, MEM_RELEASE); - // Immediately try to point both pages at the file mapping + // Immediately try to point both pages at the file mapping if (MapViewOfFileEx(buffer->file_map_handle, FILE_MAP_ALL_ACCESS, 0, 0, size, desired_addr) == desired_addr && MapViewOfFileEx(buffer->file_map_handle, FILE_MAP_ALL_ACCESS, 0, 0, size, desired_addr + size) == desired_addr + size) { @@ -812,23 +811,23 @@ break; } -#else // UWP +#else // UWP // Implementation based on example from: https://docs.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc2 // // Notes - // - just replaced the non-uwp functions by the uwp variants. + // - just replaced the non-uwp functions by the uwp variants. // - Both versions could be rewritten to not need the try-loop, see the example mentioned above. I just keep it as is for now. // - Successfully tested on Hololens desired_addr = (rmtU8*) VirtualAlloc2FromApp(NULL, NULL, 2 * size,MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,PAGE_NOACCESS,NULL, 0); // Split the placeholder region into two regions of equal size. VirtualFree(desired_addr, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); - - // Immediately try to point both pages at the file mapping. + + // Immediately try to point both pages at the file mapping. if(MapViewOfFile3FromApp(buffer->file_map_handle,NULL, desired_addr, 0, size, MEM_REPLACE_PLACEHOLDER,PAGE_READWRITE,NULL,0)==desired_addr && MapViewOfFile3FromApp(buffer->file_map_handle,NULL, desired_addr+size, 0, size, MEM_REPLACE_PLACEHOLDER,PAGE_READWRITE,NULL,0)== desired_addr + size) { - buffer->ptr = desired_addr; + buffer->ptr = desired_addr; break; } #endif @@ -993,7 +992,7 @@ { // FIXME, don't we need to unmap the file views obtained in VirtualMirrorBuffer_Constructor, both for uwp/non-uwp // See example https://docs.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc2 - + CloseHandle(buffer->file_map_handle); buffer->file_map_handle = NULL; } @@ -1268,6 +1267,7 @@ strstr_s (char *dest, r_size_t dmax, const char *src, r_size_t slen, char **substring) { + if (substring == NULL) { return RCNEGATE(ESNULLP); } @@ -1307,9 +1307,9 @@ } while (*dest && dmax) { - int i; - r_size_t len; - r_size_t dlen; + r_size_t len; + r_size_t dlen; + int i; i = 0; len = slen; dlen = dmax; @@ -1829,7 +1829,6 @@ if (error != RMT_ERROR_NONE) return error; } - assert(buffer->data != NULL); // Copy all bytes memcpy(buffer->data + buffer->bytes_used, data, length); @@ -3145,7 +3144,7 @@ { r_size_t limit_host_len = strnlen_s(limit_host, 128); char* found = NULL; - if (strstr_s(host, (r_size_t) ( buffer_end - host), limit_host, limit_host_len, &found) != EOK) + if (strstr_s(host, (r_size_t) (buffer_end - host), limit_host, limit_host_len, &found) != EOK) return RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_HOST; } @@ -3153,14 +3152,14 @@ key = GetField(buffer, buffer_len, "Sec-WebSocket-Key:"); if (key == NULL) return RMT_ERROR_WEBSOCKET_HANDSHAKE_NO_KEY; - if (strstr_s(key, (r_size_t) ( buffer_end - key), "\r\n", 2, &key_end) != EOK) + if (strstr_s(key, (r_size_t) (buffer_end - key), "\r\n", 2, &key_end) != EOK) return RMT_ERROR_WEBSOCKET_HANDSHAKE_BAD_KEY; *key_end = 0; // Concatenate the browser's key with the WebSocket Protocol GUID and base64 encode // the hash, to prove to the browser that this is a bonafide WebSocket server buffer[0] = 0; - if (strncat_s(buffer, buffer_len, key, (r_size_t) ( key_end - key) ) != EOK) + if (strncat_s(buffer, buffer_len, key, (r_size_t) (key_end - key)) != EOK) return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL; if (strncat_s(buffer, buffer_len, websocket_guid, sizeof(websocket_guid)) != EOK) return RMT_ERROR_WEBSOCKET_HANDSHAKE_STRING_FAIL; @@ -3281,10 +3280,10 @@ char empty_frame_header[WEBSOCKET_MAX_FRAME_HEADER_SIZE]; assert(buffer != NULL); - + // Reset to start buffer->bytes_used = 0; - + // Allocate enough space for a maximum-sized frame header Buffer_Write(buffer, empty_frame_header, sizeof(empty_frame_header)); } @@ -3306,7 +3305,7 @@ rmtU8 frame_type = (rmtU8)web_socket->mode; dest[0] = final_fragment | frame_type; - + // Construct the frame header, correctly applying the narrowest size if (length <= 125) { @@ -3388,7 +3387,7 @@ if (size_bytes_remaining > 0) { - int i; + int i; // Receive the wider bytes of the length rmtU8 size_bytes[8]; error = TCPSocket_Receive(web_socket->tcp_socket, size_bytes, size_bytes_remaining, 20); @@ -4315,6 +4314,13 @@ +#if RMT_USE_D3D11 +typedef struct D3D11 D3D11; +static rmtError D3D11_Create(D3D11** d3d11); +static void D3D11_Destructor(D3D11* d3d11); +#endif + + typedef struct ThreadSampler { // Name to assign to the thread in the viewer @@ -4326,11 +4332,16 @@ // Table of all sample names encountered on this thread StringTable* names; +#if RMT_USE_D3D11 + D3D11* d3d11; +#endif + // Next in the global list of active thread samplers struct ThreadSampler* volatile next; } ThreadSampler; + static rmtError ThreadSampler_Constructor(ThreadSampler* thread_sampler) { rmtError error; @@ -4343,10 +4354,13 @@ thread_sampler->sample_trees[i] = NULL; thread_sampler->names = NULL; thread_sampler->next = NULL; + #if RMT_USE_D3D11 + thread_sampler->d3d11 = NULL; + #endif // Set the initial name to Thread0 etc. or use the existing Linux name. thread_sampler->name[0] = 0; - #if defined(RMT_PLATFORM_LINUX) && RMT_USE_POSIX_THREADNAMES && !defined(__FreeBSD__) + #if defined(RMT_PLATFORM_LINUX) && RMT_USE_POSIX_THREADNAMES && !defined(__FreeBSD__) && !defined(__OpenBSD__) prctl(PR_GET_NAME,thread_sampler->name,0,0,0); #else { @@ -4367,6 +4381,12 @@ if (error != RMT_ERROR_NONE) return error; + #if RMT_USE_D3D11 + error = D3D11_Create(&thread_sampler->d3d11); + if (error != RMT_ERROR_NONE) + return error; + #endif + return RMT_ERROR_NONE; } @@ -4377,6 +4397,10 @@ assert(ts != NULL); + #if RMT_USE_D3D11 + Delete(D3D11, ts->d3d11); + #endif + Delete(StringTable, ts->names); for (i = 0; i < SampleType_Count; i++) @@ -4453,13 +4477,6 @@ -#if RMT_USE_D3D11 -typedef struct D3D11 D3D11; -static rmtError D3D11_Create(D3D11** d3d11); -static void D3D11_Destructor(D3D11* d3d11); -#endif - - #if RMT_USE_OPENGL typedef struct OpenGL_t OpenGL; static rmtError OpenGL_Create(OpenGL** opengl); @@ -4500,10 +4517,6 @@ rmtCUDABind cuda; #endif -#if RMT_USE_D3D11 - D3D11* d3d11; -#endif - #if RMT_USE_OPENGL OpenGL* opengl; #endif @@ -4511,6 +4524,8 @@ #if RMT_USE_METAL Metal* metal; #endif + + rmtBool sampling_disabled; }; @@ -4587,7 +4602,7 @@ assert(rmt != NULL); assert(message != NULL); - + bin_buf = rmt->server->bin_buf; WebSocket_PrepareBuffer(bin_buf); Buffer_Write(bin_buf, message->payload, message->payload_size); @@ -4744,6 +4759,7 @@ error = Remotery_SendSampleTreeMessage(rmt, message); rmt_EndCPUSample(); break; + default: break; } @@ -4783,6 +4799,7 @@ FreeSampleTree(sample_tree->root_sample, sample_tree->allocator); break; } + default: break; } @@ -4961,10 +4978,6 @@ rmt->cuda.EventRecord = NULL; #endif - #if RMT_USE_D3D11 - rmt->d3d11 = NULL; - #endif - #if RMT_USE_OPENGL rmt->opengl = NULL; #endif @@ -4995,12 +5008,6 @@ if (error != RMT_ERROR_NONE) return error; - #if RMT_USE_D3D11 - error = D3D11_Create(&rmt->d3d11); - if (error != RMT_ERROR_NONE) - return error; - #endif - #if RMT_USE_OPENGL error = OpenGL_Create(&rmt->opengl); if (error != RMT_ERROR_NONE) @@ -5013,7 +5020,6 @@ return error; #endif - // Set as the global instance before creating any threads that uses it for sampling itself assert(g_Remotery == NULL); g_Remotery = rmt; @@ -5041,10 +5047,6 @@ g_RemoteryCreated = RMT_FALSE; } - #if RMT_USE_D3D11 - Delete(D3D11, rmt->d3d11); - #endif - #if RMT_USE_OPENGL Delete(OpenGL, rmt->opengl); #endif @@ -5082,7 +5084,7 @@ if (error != RMT_ERROR_NONE) return error; ts = *thread_sampler; - if (!ts) + if (!ts) return error; // Add to the beginning of the global linked list of thread samplers @@ -5207,7 +5209,7 @@ assert(g_RemoteryCreated == RMT_TRUE); assert(g_Remotery == remotery); Delete(Remotery, remotery); - assert(remotery==NULL); + assert(remotery==NULL); } @@ -5265,7 +5267,7 @@ char name_clamp[16]; name_clamp[0] = 0; strncat_s(name_clamp, sizeof(name_clamp), name, 15); - #ifdef __FreeBSD__ + #if defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), name_clamp); #else prctl(PR_SET_NAME,name_clamp,0,0,0); @@ -5273,13 +5275,16 @@ #endif } +#define CHECK_REMOTERY() \ + if ((g_Remotery==NULL) || g_Remotery->sampling_disabled)\ + return; + RMT_API void _rmt_SetCurrentThreadName(rmtPStr thread_name) { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() // Get data for this thread if (Remotery_GetThreadSampler(g_Remotery, &ts) != RMT_ERROR_NONE) @@ -5321,8 +5326,9 @@ unsigned char line_buffer[1024] = { 0 }; ThreadSampler* ts; - if (g_Remotery == NULL) - return; + //do not check for sampling enabled here + if (g_Remotery==NULL) + return; Remotery_GetThreadSampler(g_Remotery, &ts); @@ -5383,8 +5389,7 @@ ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() // TODO: Time how long the bits outside here cost and subtract them from the parent @@ -5408,8 +5413,7 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -5478,7 +5482,7 @@ // Basic spin lock on the map function itself while (AtomicCompareAndSwapPointer((long* volatile*)&rmt->map_message_queue_fn, NULL, (long*)map_message_queue_fn) == RMT_FALSE) msSleep(1); - + StoreReleasePointer((long* volatile*)&rmt->map_message_queue_data, (long*)data); // Wait until map completes @@ -5761,8 +5765,7 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -5803,8 +5806,7 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -5930,11 +5932,10 @@ Delete(rmtMessageQueue, d3d11->mq_to_d3d11_main); } -static HRESULT rmtD3D11Finish(rmtU64 *out_timestamp, double *out_frequency) +static HRESULT rmtD3D11Finish(ID3D11Device* device, ID3D11DeviceContext* context, + rmtU64 *out_timestamp, double *out_frequency) { HRESULT result; - ID3D11Device* device = g_Remotery->d3d11->device; - ID3D11DeviceContext* context = g_Remotery->d3d11->context; ID3D11Query* full_stall_fence; ID3D11Query* query_disjoint; D3D11_QUERY_DESC query_desc; @@ -6002,7 +6003,8 @@ return result; } -static HRESULT SyncD3D11CpuGpuTimes(rmtU64* out_first_timestamp, rmtU64* out_last_resync) +static HRESULT SyncD3D11CpuGpuTimes(ID3D11Device* device, ID3D11DeviceContext* context, + rmtU64* out_first_timestamp, rmtU64* out_last_resync) { rmtU64 cpu_time_start = 0; rmtU64 cpu_time_stop = 0; @@ -6012,7 +6014,7 @@ int i; HRESULT result; - result = rmtD3D11Finish(&gpu_base, &frequency); + result = rmtD3D11Finish(device, context, &gpu_base, &frequency); if (result != S_OK && result != S_FALSE) return result; @@ -6020,7 +6022,7 @@ { rmtU64 half_RTT; cpu_time_start = usTimer_Get(&g_Remotery->timer); - result = rmtD3D11Finish(&gpu_base, &frequency); + result = rmtD3D11Finish(device, context, &gpu_base, &frequency); cpu_time_stop = usTimer_Get(&g_Remotery->timer); if (result != S_OK && result != S_FALSE) @@ -6068,6 +6070,7 @@ static rmtError D3D11Timestamp_Constructor(D3D11Timestamp* stamp) { + ThreadSampler* ts; D3D11_QUERY_DESC timestamp_desc; D3D11_QUERY_DESC disjoint_desc; ID3D11Device* device; @@ -6084,9 +6087,10 @@ stamp->cpu_timestamp = 0; assert(g_Remotery != NULL); - assert(g_Remotery->d3d11 != NULL); - device = g_Remotery->d3d11->device; - last_error = &g_Remotery->d3d11->last_error; + assert(Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE); + assert(ts->d3d11 != NULL); + device = ts->d3d11->device; + last_error = &ts->d3d11->last_error; // Create start/end timestamp queries timestamp_desc.Query = D3D11_QUERY_TIMESTAMP; @@ -6144,7 +6148,9 @@ } -static HRESULT D3D11Timestamp_GetData(D3D11Timestamp* stamp, ID3D11DeviceContext* context, rmtU64* out_start, rmtU64* out_end, rmtU64* out_first_timestamp, rmtU64* out_last_resync) +static HRESULT D3D11Timestamp_GetData(D3D11Timestamp* stamp, ID3D11Device* device, + ID3D11DeviceContext* context, rmtU64* out_start, rmtU64* out_end, rmtU64* out_first_timestamp, + rmtU64* out_last_resync) { ID3D11Asynchronous* query_start; ID3D11Asynchronous* query_end; @@ -6181,7 +6187,7 @@ assert(out_first_timestamp != NULL); if (*out_first_timestamp == 0 || ((start - *out_first_timestamp) / frequency) < stamp->cpu_timestamp) { - result = SyncD3D11CpuGpuTimes(out_first_timestamp, out_last_resync); + result = SyncD3D11CpuGpuTimes(device, context, out_first_timestamp, out_last_resync); if (result != S_OK) return result; } @@ -6193,7 +6199,7 @@ else { #if RMT_D3D11_RESYNC_ON_DISJOINT - result = SyncD3D11CpuGpuTimes(out_first_timestamp, out_last_resync); + result = SyncD3D11CpuGpuTimes(device, context, out_first_timestamp, out_last_resync); if (result != S_OK) return result; #endif @@ -6240,40 +6246,48 @@ { if (g_Remotery != NULL) { - assert(g_Remotery->d3d11 != NULL); + ThreadSampler* ts; + if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) + { + assert(ts->d3d11 != NULL); - assert(device != NULL); - g_Remotery->d3d11->device = (ID3D11Device*)device; - assert(context != NULL); - g_Remotery->d3d11->context = (ID3D11DeviceContext*)context; + assert(device != NULL); + ts->d3d11->device = (ID3D11Device*)device; + assert(context != NULL); + ts->d3d11->context = (ID3D11DeviceContext*)context; + } } } -static void UpdateD3D11Frame(void); +static void UpdateD3D11Frame(ThreadSampler* ts); RMT_API void _rmt_UnbindD3D11(void) { if (g_Remotery != NULL) { - D3D11* d3d11 = g_Remotery->d3d11; - assert(d3d11 != NULL); + ThreadSampler* ts; + if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) + { + D3D11* d3d11 = ts->d3d11; + assert(d3d11 != NULL); - // Stall waiting for the D3D queue to empty into the Remotery queue - while (!rmtMessageQueue_IsEmpty(d3d11->mq_to_d3d11_main)) - UpdateD3D11Frame(); - - // There will be a whole bunch of D3D11 sample trees queued up the remotery queue that need releasing - FreePendingSampleTrees(g_Remotery, SampleType_D3D11, d3d11->flush_samples); - - // Inform sampler to not add any more samples - d3d11->device = NULL; - d3d11->context = NULL; + // Stall waiting for the D3D queue to empty into the Remotery queue + while (!rmtMessageQueue_IsEmpty(d3d11->mq_to_d3d11_main)) + UpdateD3D11Frame(ts); - // Forcefully delete sample tree on this thread to release time stamps from - // the same thread that created them - Remotery_DeleteSampleTree(g_Remotery, SampleType_D3D11); + // There will be a whole bunch of D3D11 sample trees queued up the remotery queue that need releasing + FreePendingSampleTrees(g_Remotery, SampleType_D3D11, d3d11->flush_samples); + + // Inform sampler to not add any more samples + d3d11->device = NULL; + d3d11->context = NULL; + + // Forcefully delete sample tree on this thread to release time stamps from + // the same thread that created them + Remotery_DeleteSampleTree(g_Remotery, SampleType_D3D11); + } } } @@ -6283,23 +6297,25 @@ ThreadSampler* ts; D3D11* d3d11; - if (g_Remotery == NULL) - return; - - // Has D3D11 been unbound? - d3d11 = g_Remotery->d3d11; - assert(d3d11 != NULL); - if (d3d11->device == NULL || d3d11->context == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { Sample* sample; - rmtU32 name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache); + rmtU32 name_hash; + SampleTree** d3d_tree; + + // Has D3D11 been unbound? + d3d11 = ts->d3d11; + assert(d3d11 != NULL); + if (d3d11->device == NULL || d3d11->context == NULL) + return; + + name_hash = ThreadSampler_GetNameHash(ts, name, hash_cache); // Create the D3D11 tree on-demand as the tree needs an up-front-created root. // This is not possible to create on initialisation as a D3D11 binding is not yet available. - SampleTree** d3d_tree = &ts->sample_trees[SampleType_D3D11]; + d3d_tree = &ts->sample_trees[SampleType_D3D11]; if (*d3d_tree == NULL) { rmtError error; @@ -6318,7 +6334,8 @@ } -static rmtBool GetD3D11SampleTimes(Sample* sample, rmtU64* out_first_timestamp, rmtU64* out_last_resync) +static rmtBool GetD3D11SampleTimes(Sample* sample, ThreadSampler* ts, rmtU64* out_first_timestamp, + rmtU64* out_last_resync) { Sample* child; @@ -6329,7 +6346,7 @@ { HRESULT result; - D3D11* d3d11 = g_Remotery->d3d11; + D3D11* d3d11 = ts->d3d11; assert(d3d11 != NULL); assert(out_last_resync != NULL); @@ -6341,7 +6358,7 @@ rmtU64 time_diff = (d3d_sample->timestamp->cpu_timestamp - *out_last_resync) / 1000000ULL; if (time_diff > RMT_GPU_CPU_SYNC_SECONDS) { - result = SyncD3D11CpuGpuTimes(out_first_timestamp, out_last_resync); + result = SyncD3D11CpuGpuTimes(d3d11->device, d3d11->context, out_first_timestamp, out_last_resync); if (result != S_OK) { d3d11->last_error = result; @@ -6353,6 +6370,7 @@ result = D3D11Timestamp_GetData( d3d_sample->timestamp, + d3d11->device, d3d11->context, &sample->us_start, &sample->us_end, @@ -6377,7 +6395,7 @@ // Get child sample times for (child = sample->first_child; child != NULL; child = child->next_sibling) { - if (!GetD3D11SampleTimes(child, out_first_timestamp, out_last_resync)) + if (!GetD3D11SampleTimes(child, ts, out_first_timestamp, out_last_resync)) return RMT_FALSE; } @@ -6385,14 +6403,13 @@ } -static void UpdateD3D11Frame(void) +static void UpdateD3D11Frame(ThreadSampler* ts) { D3D11* d3d11; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() - d3d11 = g_Remotery->d3d11; + d3d11 = ts->d3d11; assert(d3d11 != NULL); rmt_BeginCPUSample(rmt_UpdateD3D11Frame, 0); @@ -6415,7 +6432,7 @@ // Retrieve timing of all D3D11 samples // If they aren't ready leave the message unconsumed, holding up later frames and maintaining order - if (!GetD3D11SampleTimes(sample, &d3d11->first_timestamp, &d3d11->last_resync)) + if (!GetD3D11SampleTimes(sample, ts, &d3d11->first_timestamp, &d3d11->last_resync)) break; // Pass samples onto the remotery thread for sending to the viewer @@ -6432,19 +6449,20 @@ ThreadSampler* ts; D3D11* d3d11; - if (g_Remotery == NULL) - return; - - // Has D3D11 been unbound? - d3d11 = g_Remotery->d3d11; - assert(d3d11 != NULL); - if (d3d11->device == NULL || d3d11->context == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { + D3D11Sample* d3d_sample; + + // Has D3D11 been unbound? + d3d11 = ts->d3d11; + assert(d3d11 != NULL); + if (d3d11->device == NULL || d3d11->context == NULL) + return; + // Close the timestamp - D3D11Sample* d3d_sample = (D3D11Sample*)ts->sample_trees[SampleType_D3D11]->current_parent; + d3d_sample = (D3D11Sample*)ts->sample_trees[SampleType_D3D11]->current_parent; if (d3d_sample->base.recurse_depth > 0) { d3d_sample->base.recurse_depth--; @@ -6457,7 +6475,7 @@ // Send to the update loop for ready-polling if (ThreadSampler_Pop(ts, d3d11->mq_to_d3d11_main, (Sample*)d3d_sample)) // Perform ready-polling on popping of the root sample - UpdateD3D11Frame(); + UpdateD3D11Frame(ts); } } } @@ -6906,7 +6924,6 @@ rmtMessageQueue_ConsumeNextMessage(opengl->mq_to_opengl_main, message); } #endif - // There will be a whole bunch of OpenGL sample trees queued up the remotery queue that need releasing FreePendingSampleTrees(g_Remotery, SampleType_OpenGL, opengl->flush_samples); @@ -6928,11 +6945,8 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; - - if (g_Remotery->opengl->dll_handle == NULL) - return; + CHECK_REMOTERY() + if (g_Remotery->opengl->dll_handle == NULL) return; if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -6956,10 +6970,10 @@ OpenGLSample* ogl_sample = (OpenGLSample*)sample; OpenGLTimestamp_Begin(ogl_sample->timestamp); } + // Empty the error queue before using it for glGenQueries + while ( rmtglGetError() != GL_NO_ERROR) + ; } - // Empty the error queue before using it for glGenQueries - while ( rmtglGetError() != GL_NO_ERROR) - ; } @@ -7004,8 +7018,7 @@ { OpenGL* opengl; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() opengl = g_Remotery->opengl; assert(opengl != NULL); @@ -7046,11 +7059,8 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; - - if (g_Remotery->opengl->dll_handle == NULL) - return; + CHECK_REMOTERY() + if (g_Remotery->opengl->dll_handle == NULL) return; if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -7074,6 +7084,7 @@ // Empty the error queue before using it for glGenQueries while ( rmtglGetError() != GL_NO_ERROR) ; + } @@ -7267,8 +7278,7 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -7326,8 +7336,7 @@ { Metal* metal; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() metal = g_Remotery->metal; assert(metal != NULL); @@ -7368,8 +7377,7 @@ { ThreadSampler* ts; - if (g_Remotery == NULL) - return; + CHECK_REMOTERY() if (Remotery_GetThreadSampler(g_Remotery, &ts) == RMT_ERROR_NONE) { @@ -7383,7 +7391,7 @@ { if (metal_sample->timestamp != NULL) MetalTimestamp_End(metal_sample->timestamp); - + // Send to the update loop for ready-polling if (ThreadSampler_Pop(ts, g_Remotery->metal->mq_to_metal_main, (Sample*)metal_sample)) // Perform ready-polling on popping of the root sample @@ -7397,5 +7405,16 @@ #endif // RMT_USE_METAL +RMT_API void _rmt_EnableSampling(rmtBool enable) +{ + if (g_Remotery==NULL) return; + g_Remotery->sampling_disabled = !enable; +} +RMT_API rmtBool _rmt_SamplingEnabled() +{ + if (g_Remotery==NULL) return 0; + return !g_Remotery->sampling_disabled; +} + #endif // RMT_ENABLED
View file
gpac-1.0.0.tar.gz/src/utils/base_encoding.c -> gpac-1.0.1.tar.gz/src/utils/base_encoding.c
Changed
@@ -187,7 +187,7 @@ #define ZLIB_COMPRESS_SAFE 4 GF_EXPORT -GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger) +GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data) { z_stream stream; int err; @@ -223,6 +223,10 @@ GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[GZ] compressed data (%d) larger than input (%d)\n", (u32) stream.total_out, (u32) data_len )); } + if (out_comp_data) { + data = out_comp_data; + } + if (*max_size < stream.total_out) { *max_size = data_len*ZLIB_COMPRESS_SAFE; *data = (char*)gf_realloc(*data, *max_size * sizeof(char)); @@ -239,8 +243,7 @@ GF_EXPORT GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *max_size) { - return gf_gz_compress_payload_ex(data, data_len, max_size, 0, GF_FALSE); - + return gf_gz_compress_payload_ex(data, data_len, max_size, 0, GF_FALSE, NULL); } GF_EXPORT @@ -310,6 +313,11 @@ *max_size = 0; return GF_NOT_SUPPORTED; } +GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data) +{ + *max_size = 0; + return GF_NOT_SUPPORTED; +} #endif /*GPAC_DISABLE_ZLIB*/ @@ -438,7 +446,6 @@ *max_size = 0; return GF_NOT_SUPPORTED; } - #endif /*GPAC_HAS_LZMA*/ #endif /* GPAC_DISABLE_CORE_TOOLS*/
View file
gpac-1.0.0.tar.gz/src/utils/bitstream.c -> gpac-1.0.1.tar.gz/src/utils/bitstream.c
Changed
@@ -1192,7 +1192,7 @@ if (bs->cache_read) { u32 csize = bs->cache_read_size - bs->cache_read_pos; - if (csize>nbBytes) { + if (csize>=nbBytes) { bs->cache_read_pos += (u32) nbBytes; bs->position += nbBytes; return; @@ -1201,9 +1201,10 @@ bs->position += csize; bs->cache_read_pos = bs->cache_read_size; } - - gf_fseek(bs->stream, nbBytes, SEEK_CUR); + //weird msys2 bug resulting in broken seek on some files ?!? -the big is not happening when doing absolute seek +// gf_fseek(bs->stream, nbBytes, SEEK_CUR); bs->position += nbBytes; + gf_fseek(bs->stream, bs->position, SEEK_SET); return; } @@ -1467,6 +1468,19 @@ } GF_EXPORT +void gf_bs_write_u64_le(GF_BitStream *bs, u64 val) +{ + gf_bs_write_int(bs, val & 0xFF, 8); + gf_bs_write_int(bs, (val>>8) & 0xFF, 8); + gf_bs_write_int(bs, (val>>16) & 0xFF, 8); + gf_bs_write_int(bs, (val>>24) & 0xFF, 8); + gf_bs_write_int(bs, (val>>32) & 0xFF, 8); + gf_bs_write_int(bs, (val>>40) & 0xFF, 8); + gf_bs_write_int(bs, (val>>48) & 0xFF, 8); + gf_bs_write_int(bs, (val>>56) & 0xFF, 8); +} + +GF_EXPORT void gf_bs_write_u32_le(GF_BitStream *bs, u32 val) { gf_bs_write_int(bs, val & 0xFF, 8);
View file
gpac-1.0.0.tar.gz/src/utils/color.c -> gpac-1.0.1.tar.gz/src/utils/color.c
Changed
@@ -1807,8 +1807,6 @@ gf_yuv_load_lines_nv12_nv21(dst_bits, 4*width, pY, pU+1, pU, y_pitch, width, dst_yuv); } -static void gf_cmx_apply_argb(GF_ColorMatrix *_this, u8 *a_, u8 *r_, u8 *g_, u8 *b_); - //#define COLORKEY_MPEG4_STRICT static Bool format_is_yuv(u32 in_pf) @@ -2327,6 +2325,7 @@ return GF_OK; } +#endif // GPAC_DISABLE_PLAYER /* @@ -2429,7 +2428,8 @@ #define CLIP_COMP(val) { if (val<0) { val=0; } else if (val>FIX_ONE) { val=FIX_ONE;} } -static void gf_cmx_apply_argb(GF_ColorMatrix *_this, u8 *a_, u8 *r_, u8 *g_, u8 *b_) +GF_EXPORT +void gf_cmx_apply_argb(GF_ColorMatrix *_this, u8 *a_, u8 *r_, u8 *g_, u8 *b_) { Fixed _a, _r, _g, _b, a, r, g, b; if (!_this || _this->identity) return; @@ -2524,6 +2524,8 @@ } +#ifndef GPAC_DISABLE_PLAYER + //intrinsic code segfaults on 32 bit, need to check why #if defined(GPAC_64_BITS) @@ -4349,5 +4351,16 @@ return predefined_colors[i].name; } return NULL; +} + +GF_EXPORT +Bool gf_color_enum(u32 *idx, GF_Color *col, const char **color_name) +{ + u32 count = sizeof(predefined_colors) / sizeof(struct predef_col); + if (*idx>=count) return GF_FALSE; + if (col) *col = GF_COL_ARGB(0xFF, predefined_colors[*idx].r, predefined_colors[*idx].g, predefined_colors[*idx].b); + if (color_name) *color_name = predefined_colors[*idx].name; + (*idx)++; + return GF_TRUE; }
View file
gpac-1.0.0.tar.gz/src/utils/constants.c -> gpac-1.0.1.tar.gz/src/utils/constants.c
Changed
@@ -142,6 +142,9 @@ {GF_CODECID_VP9, 0, GF_STREAM_VISUAL, "VP9 Video", "vp9|ivf", NULL, "video/vp9"}, {GF_CODECID_VP10, 0, GF_STREAM_VISUAL, "VP10 Video", "vp10|ivf", NULL, "video/vp10"}, + {GF_CODECID_MPHA, 0, GF_STREAM_AUDIO, "MPEG-H Audio", "mpha", "mha1", "audio/x-mpegh"}, + {GF_CODECID_MHAS, 0, GF_STREAM_AUDIO, "MPEG-H AudioMux", "mhas", "mhm1", "audio/x-mhas"}, + {GF_CODECID_APCH, 0, GF_STREAM_VISUAL, "ProRes Video 422 HQ", "prores|apch", "apch", "video/prores"}, {GF_CODECID_APCO, 0, GF_STREAM_VISUAL, "ProRes Video 422 Proxy", "prores|apco", "apco", "video/prores", GF_CODECID_APCH}, {GF_CODECID_APCN, 0, GF_STREAM_VISUAL, "ProRes Video 422 STD", "prores|apcn", "apcn", "video/prores", GF_CODECID_APCH}, @@ -176,6 +179,8 @@ GF_CodecID gf_codec_id_from_isobmf(u32 isobmftype) { switch (isobmftype) { + case GF_ISOM_SUBTYPE_DVHE: + return GF_CODECID_HEVC; case GF_ISOM_SUBTYPE_3GP_AMR: return GF_CODECID_AMR; case GF_ISOM_SUBTYPE_3GP_AMR_WB: @@ -1283,3 +1288,152 @@ + + +static struct _itags { + const char *name; + u32 itag; + u32 id3tag; + u32 type; +} itunes_tags[] = { + + {"album", GF_ISOM_ITUNE_ALBUM, GF_ID3V2_FRAME_TALB, GF_ITAG_STR}, + {"artist", GF_ISOM_ITUNE_ARTIST, GF_ID3V2_FRAME_TPE1, GF_ITAG_STR}, + {"comment", GF_ISOM_ITUNE_COMMENT, 0, GF_ITAG_SUBSTR}, + {"complilation", GF_ISOM_ITUNE_COMPILATION, GF_ID3V2_FRAME_TCMP, GF_ITAG_BOOL}, + {"composer", GF_ISOM_ITUNE_COMPOSER, GF_ID3V2_FRAME_TCOM, GF_ITAG_STR}, + {"year", GF_ISOM_ITUNE_CREATED, GF_ID3V2_FRAME_TDRC, GF_ITAG_STR}, + {"disk", GF_ISOM_ITUNE_DISK, GF_ID3V2_FRAME_TPOS, GF_ITAG_STR}, + {"tool", GF_ISOM_ITUNE_TOOL, 0, GF_ITAG_STR}, + {"genre", GF_ISOM_ITUNE_GENRE, GF_ID3V2_FRAME_TCON, GF_ITAG_STR}, + {"contentgroup", GF_ISOM_ITUNE_GROUP, GF_ID3V2_FRAME_TIT1, GF_ITAG_STR}, + {"title", GF_ISOM_ITUNE_NAME, GF_ID3V2_FRAME_TIT2, GF_ITAG_STR}, + {"tempo", GF_ISOM_ITUNE_TEMPO, GF_ID3V2_FRAME_TBPM, GF_ITAG_STR}, + {"track", GF_ISOM_ITUNE_TRACK, 0, GF_ITAG_STR}, + {"tracknum", GF_ISOM_ITUNE_TRACKNUMBER, GF_ID3V2_FRAME_TRCK, GF_ITAG_STR}, + {"writer", GF_ISOM_ITUNE_WRITER, GF_ID3V2_FRAME_TEXT, GF_ITAG_STR}, + {"encoder", GF_ISOM_ITUNE_ENCODER, GF_ID3V2_FRAME_TSSE, GF_ITAG_STR}, + {"album_artist", GF_ISOM_ITUNE_ALBUM_ARTIST, GF_ID3V2_FRAME_TPE2, GF_ITAG_SUBSTR}, + {"gapless", GF_ISOM_ITUNE_GAPLESS, 0, GF_ITAG_BOOL}, + {"conductor", GF_ISOM_ITUNE_CONDUCTOR, GF_ID3V2_FRAME_TPE3, GF_ITAG_STR}, +}; + +GF_EXPORT +s32 gf_itags_find_by_id3tag(u32 id3tag) +{ + u32 i, count = GF_ARRAY_LENGTH(itunes_tags); + if (id3tag==GF_ID3V2_FRAME_TYER) id3tag = GF_ID3V2_FRAME_TDRC; + for (i=0; i<count; i++) { + if (itunes_tags[i].id3tag == id3tag) return i; + } + return -1; +} + +GF_EXPORT +s32 gf_itags_find_by_itag(u32 itag) +{ + u32 i, count = GF_ARRAY_LENGTH(itunes_tags); + for (i=0; i<count; i++) { + if (itunes_tags[i].itag == itag) return i; + } + return -1; +} + +GF_EXPORT +s32 gf_itags_find_by_name(const char *tag_name) +{ + u32 i, count = GF_ARRAY_LENGTH(itunes_tags); + for (i=0; i<count; i++) { + if (!strcmp(tag_name, itunes_tags[i].name)) { + return i; + } else if ((itunes_tags[i].type==GF_ITAG_SUBSTR) && !strnicmp(tag_name, itunes_tags[i].name, strlen(itunes_tags[i].name) )) { + return i; + } + } + return -1; +} + +GF_EXPORT +u32 gf_itags_get_type(u32 tag_idx) +{ + u32 count = GF_ARRAY_LENGTH(itunes_tags); + if (tag_idx>=count) return 0; + return itunes_tags[tag_idx].type; +} + +GF_EXPORT +const char *gf_itags_get_name(u32 tag_idx) +{ + u32 count = GF_ARRAY_LENGTH(itunes_tags); + if (tag_idx>=count) return NULL; + return itunes_tags[tag_idx].name; +} + +GF_EXPORT +u32 gf_itags_get_itag(u32 tag_idx) +{ + u32 count = GF_ARRAY_LENGTH(itunes_tags); + if (tag_idx>=count) return 0; + return itunes_tags[tag_idx].itag; +} + +GF_EXPORT +u32 gf_itags_get_id3tag(u32 tag_idx) +{ + u32 count = GF_ARRAY_LENGTH(itunes_tags); + if (tag_idx>=count) return 0; + return itunes_tags[tag_idx].id3tag; +} + +GF_EXPORT +const char *gf_itags_enum_tags(u32 *idx, u32 *itag, u32 *id3tag, u32 *type) +{ + u32 i, count = GF_ARRAY_LENGTH(itunes_tags); + if (!idx || (count<= *idx)) return NULL; + i = *idx; + (*idx) ++; + if (itag) *itag = itunes_tags[i].itag; + if (id3tag) *id3tag = itunes_tags[i].id3tag; + if (type) *type = itunes_tags[i].type; + return itunes_tags[i].name; +} + + +static const char* ID3v1Genres[] = { + "Blues", "Classic Rock", "Country", "Dance", "Disco", + "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", + "New Age", "Oldies", "Other", "Pop", "R&B", + "Rap", "Reggae", "Rock", "Techno", "Industrial", + "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", + "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", + "Fusion", "Trance", "Classical", "Instrumental", "Acid", + "House", "Game", "Sound Clip", "Gospel", "Noise", + "AlternRock", "Bass", "Soul", "Punk", "Space", + "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", + "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", + "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", + "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", + "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", + "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", + "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", + "Folk", "Folk/Rock", "National Folk", "Swing", +}; + +GF_EXPORT +const char *gf_id3_get_genre(u32 tag) +{ + if ((tag>0) && (tag <= (sizeof(ID3v1Genres)/sizeof(const char *)) )) { + return ID3v1Genres[tag-1]; + } + return "Unknown"; +} +GF_EXPORT +u32 gf_id3_get_genre_tag(const char *name) +{ + u32 i, count = sizeof(ID3v1Genres)/sizeof(const char *); + if (!name) return 0; + for (i=0; i<count; i++) { + if (!stricmp(ID3v1Genres[i], name)) return i+1; + } + return 0; +}
View file
gpac-1.0.0.tar.gz/src/utils/downloader.c -> gpac-1.0.1.tar.gz/src/utils/downloader.c
Changed
@@ -701,9 +701,12 @@ sess->last_error = GF_URL_ERROR; return; } + /* We found the existing session */ if (sess->cache_entry) { - /* We found the existing session */ - gf_cache_entry_set_delete_files_when_deleted(sess->cache_entry); + /*! indicate we can destroy file upon destruction, except if disabled at session level*/ + if (! (sess->flags & GF_NETIO_SESSION_KEEP_CACHE)) + gf_cache_entry_set_delete_files_when_deleted(sess->cache_entry); + if (0 == gf_cache_get_sessions_count_for_cache_entry(sess->cache_entry)) { gf_mx_p( sess->dm->cache_mx ); /* No session attached anymore... we can delete it */ @@ -3366,7 +3369,7 @@ if (!stricmp(hdrp->name, "Content-Length") ) { ContentLength = (u32) atoi(hdrp->value); - if (rsp_code<300) + if ((rsp_code<300) && sess->cache_entry) gf_cache_set_content_length(sess->cache_entry, ContentLength); }
View file
gpac-1.0.0.tar.gz/src/utils/module.c -> gpac-1.0.1.tar.gz/src/utils/module.c
Changed
@@ -269,7 +269,7 @@ directories = (char*)gf_opts_get_key("core", "mod-dirs"); if (! directories) { #ifndef GPAC_CONFIG_IOS - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Modules directories not found - check the \"ModulesDirectory\" key is set in the \"Core\" section\n")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("Modules directories not found - check the \"ModulesDirectory\" key is set in the \"Core\" section\n")); #endif return NULL; }
View file
gpac-1.0.0.tar.gz/src/utils/os_config_init.c -> gpac-1.0.1.tar.gz/src/utils/os_config_init.c
Changed
@@ -382,7 +382,6 @@ GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Couldn't find GPAC binaries install directory\n")); return 0; } - /*installed or symlink on system, user user home directory*/ if (!strnicmp(app_path, "/usr/", 5) || !strnicmp(app_path, "/opt/", 5)) { if (path_type==GF_PATH_SHARE) { @@ -412,11 +411,14 @@ /*GUI not found, look in gpac distribution if any */ if (get_default_install_path(app_path, GF_PATH_APP)) { + strcat(app_path, "/"); sep = strstr(app_path, "/bin/"); if (sep) { sep[0] = 0; strcat(app_path, "/share"); if (check_file_exists("gui/gui.bt", app_path, file_path)) return 1; + strcat(app_path, "/gpac"); + if (check_file_exists("gui/gui.bt", app_path, file_path)) return 1; } sep = strstr(app_path, "/build/"); if (sep) { @@ -439,6 +441,18 @@ /*modules not found*/ GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("Couldn't find any modules in standard path (app path %s)\n", app_path)); } + + /* look in distrib tree */ + if (get_default_install_path(app_path, GF_PATH_APP)) { + strcat(app_path, "/"); + sep = strstr(app_path, "/bin/"); + if (sep) { + sep[0] = 0; + strcat(app_path, "/lib/gpac"); + if (check_file_exists(TEST_MODULE, app_path, file_path)) return 1; + } + } + /*modules not found, look in ~/.gpac/modules/ */ if (get_default_install_path(app_path, GF_PATH_CFG)) { strcpy(app_path, file_path); @@ -511,6 +525,7 @@ static GF_Config *create_default_config(char *file_path, const char *profile) { + Bool moddir_found; GF_Config *cfg; char szProfilePath[GF_MAX_PATH]; char szPath[GF_MAX_PATH]; @@ -540,13 +555,9 @@ #ifndef GPAC_CONFIG_IOS - if (! get_default_install_path(szPath, GF_PATH_MODULES)) { - gf_file_delete(szPath); - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] default modules not found\n")); - return NULL; - } + moddir_found = get_default_install_path(szPath, GF_PATH_MODULES); #else - get_default_install_path(szPath, GF_PATH_APP); + moddir_found = get_default_install_path(szPath, GF_PATH_APP); #endif #if defined(GPAC_CONFIG_IOS) @@ -558,8 +569,11 @@ #endif - - gf_cfg_set_key(cfg, "core", "mod-dirs", szPath); + if (!moddir_found) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] default modules not found\n")); + } else { + gf_cfg_set_key(cfg, "core", "mod-dirs", szPath); + } #if defined(GPAC_CONFIG_IOS) gf_ios_refresh_cache_directory(cfg, file_path); @@ -1018,8 +1032,8 @@ GF_DEF_ARG("log-utc", "lu", "log UTC time in ms before each log line", NULL, NULL, GF_ARG_BOOL, GF_ARG_SUBSYS_LOG), GF_DEF_ARG("logs", NULL, "set log tools and levels. \n"\ " \n"\ - "You can independently log different tools involved in a session.\n"\ - "log_args is formatted as a ':'-separated list of `toolX[:toolZ]@levelX`\n"\ + "You can independently log different tools involved in a session. \n"\ + "log_args is formatted as a ':'-separated list of `toolX[:toolZ]@levelX` \n"\ "`levelX` can be one of:\n"\ "- quiet: skip logs\n"\ "- error: logs only error messages\n"\ @@ -1129,12 +1143,12 @@ GF_DEF_ARG("no-reservoir", NULL, "disable memory recycling for packets and properties. This uses much less memory but stresses the system memory allocator much more", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_FILTERS), GF_DEF_ARG("switch-vres", NULL, "select smallest video resolution larger than scene size, otherwise use current video resolution", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_VIDEO), - GF_DEF_ARG("hwvmem", NULL, "specify (2D rendering only) memory type of main video backbuffer. Depending on the scene type, this may drastically change the playback speed.\n" + GF_DEF_ARG("hwvmem", NULL, "specify (2D rendering only) memory type of main video backbuffer. Depending on the scene type, this may drastically change the playback speed\n" "- always: always on hardware\n" "- never: always on system memory\n" "- auto: selected by GPAC based on content type (graphics or video)", "auto", "auto|always|never", GF_ARG_INT, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_VIDEO), GF_DEF_ARG("pref-yuv4cc", NULL, "set prefered YUV 4CC for overlays (used by DirectX only)", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_VIDEO), - GF_DEF_ARG("yuv-overlay", NULL, "indicate YUV overlay is possible on the video card. Always overriden by video output module", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_HIDE|GF_ARG_SUBSYS_VIDEO), + GF_DEF_ARG("yuv-overlay", NULL, "indicate YUV overlay is possible on the video card. Always overridden by video output module", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_HIDE|GF_ARG_SUBSYS_VIDEO), GF_DEF_ARG("offscreen-yuv", NULL, "indicate if offscreen yuv->rgb is enabled. can be set to false to force disabling", NULL, NULL, GF_ARG_BOOL, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_VIDEO), GF_DEF_ARG("overlay-color-key", NULL, "color to use for overlay keying, hex format", NULL, NULL, GF_ARG_STRING, GF_ARG_HINT_EXPERT|GF_ARG_SUBSYS_VIDEO), GF_DEF_ARG("gl-bits-comp", NULL, "number of bits per color component in openGL", "8", NULL, GF_ARG_INT, GF_ARG_HINT_ADVANCED|GF_ARG_SUBSYS_VIDEO), @@ -1413,11 +1427,18 @@ fprintf(stderr, "\nWARNING: arg %s bad description format \"%s\", should not use tab\n", arg->name, arg->description); exit(1); } + u8 achar = arg->description[strlen(arg->description)-1]; if (achar == '.') { fprintf(stderr, "\nWARNING: arg %s bad description format \"%s\", should not end with .\n", arg->name, arg->description); exit(1); } + sep = strstr(arg->description, ".\n"); + if (sep) { + fprintf(stderr, "\nWARNING: arg %s bad description format \"%s\", should not contain .\\n", arg->name, arg->description); + exit(1); + } + sep = strchr(arg->description, ' '); if (sep) { sep--; @@ -1441,14 +1462,22 @@ } if (flags & GF_PRINTARG_MAN) { - fprintf(helpout, ".TP\n.B \\-%s", arg_name ? arg_name : arg->name); + fprintf(helpout, ".TP\n.B %s%s", (flags&GF_PRINTARG_NO_DASH) ? "" : "\\-", arg_name ? arg_name : arg->name); } else if (gen_doc==1) { - gf_sys_format_help(helpout, flags, "<a id=\"%s\">", arg_name ? arg_name : arg->name); - gf_sys_format_help(helpout, flags | GF_PRINTARG_HIGHLIGHT_FIRST, "-%s", arg_name ? arg_name : arg->name); - gf_sys_format_help(helpout, flags, "</a>"); + if (flags&GF_PRINTARG_NO_DASH) { + gf_sys_format_help(helpout, flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s", arg_name ? arg_name : arg->name); + } else { + gf_sys_format_help(helpout, flags, "<a id=\"%s\">", arg_name ? arg_name : arg->name); + gf_sys_format_help(helpout, flags | GF_PRINTARG_HIGHLIGHT_FIRST, "-%s", arg_name ? arg_name : arg->name); + gf_sys_format_help(helpout, flags, "</a>"); + } } else { - gf_sys_format_help(helpout, flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s-%s", (flags&GF_PRINTARG_ADD_DASH) ? "-" : "", arg_name ? arg_name : arg->name); + gf_sys_format_help(helpout, flags | GF_PRINTARG_HIGHLIGHT_FIRST, "%s%s%s", + (flags&GF_PRINTARG_ADD_DASH) ? "-" : "", + (flags&GF_PRINTARG_NO_DASH) ? "" : ((flags&GF_PRINTARG_COLON) ? ":" : "-"), + arg_name ? arg_name : arg->name + ); } if (arg->altname) { gf_sys_format_help(helpout, flags, ","); @@ -1757,6 +1786,7 @@ } if (i == TOK_LINKSTART) { + if (tid == TOK_OPTLINK) continue; if (gen_doc!=1) { char *link_end; skip_url = strstr(tok, "]("); @@ -1989,6 +2019,12 @@ u32 olen = (u32) strlen(orig); u32 dlen = (u32) strlen(dst); u32 *run; + + if ((olen>=3) && (olen<dlen) && !strncmp(orig, dst, olen)) + return GF_TRUE; + if ((dlen>=3) && (dlen<olen) && !strncmp(orig, dst, dlen)) + return GF_TRUE; + if (olen*2 < dlen) { char *s1 = strchr(orig, ':'); char *s2 = strchr(dst, ':');
View file
gpac-1.0.0.tar.gz/src/utils/os_divers.c -> gpac-1.0.1.tar.gz/src/utils/os_divers.c
Changed
@@ -79,7 +79,8 @@ #include <gpac/revision.h> #define GPAC_FULL_VERSION GPAC_VERSION "-rev" GPAC_GIT_REVISION -#define GPAC_COPYRIGHT "(c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io" +#define GPAC_COPYRIGHT "(c) 2000-2020 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io" + GF_EXPORT const char *gf_gpac_version() @@ -92,6 +93,16 @@ { return GPAC_COPYRIGHT; } +GF_EXPORT +const char *gf_gpac_copyright_cite() +{ + return GPAC_COPYRIGHT"\n\n" \ + "Please cite our work in your research:\n"\ + "\tGPAC Filters: https://doi.org/10.1145/3339825.3394929\n"\ + "\tGPAC: https://doi.org/10.1145/1291233.1291452\n"\ + ; + +} #ifndef WIN32 @@ -428,6 +439,10 @@ void gf_prompt_set_echo_off(Bool echo_off) { return; } +GF_Err gf_prompt_get_size(u32 *width, u32 *height) +{ + return GF_NOT_SUPPORTED; +} #else @@ -453,15 +468,35 @@ if (!ret) { DWORD err = GetLastError(); GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleMode() return with the following error code: %d\n", err)); + return; } if (echo_off) flags &= ~ENABLE_ECHO_INPUT; else flags |= ENABLE_ECHO_INPUT; SetConsoleMode(hStdin, flags); } + +GF_EXPORT +GF_Err gf_prompt_get_size(u32 *width, u32 *height) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + BOOL ret = GetConsoleScreenBufferInfo(hStdin, &info); + + if (!ret) { + DWORD err = GetLastError(); + GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleScreenBufferInfo() return with the following error code: %d\n", err)); + return GF_IO_ERR; + } + if (width) *width = info.dwSize.X; + if (height) *height = info.dwSize.Y; + return GF_OK; +} + #endif #else /*linux kbhit/getchar- borrowed on debian mailing lists, (author Mike Brownlow)*/ #include <termios.h> +#include <sys/ioctl.h> static struct termios t_orig, t_new; static s32 ch_peek = -1; @@ -534,6 +569,30 @@ return ch; } +GF_EXPORT +GF_Err gf_prompt_get_size(u32 *width, u32 *height) +{ +#if defined(TIOCGWINSZ) + struct winsize ws; + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != 0) return GF_IO_ERR; + + if (width) *width = ws.ws_col; + if (height) *height = ws.ws_row; + return GF_OK; +#elif defined(WIOCGETD) + struct uwdata w; + if (ioctl(2, WIOCGETD, &w) != 0) return GF_IO_ERR; + + if (width && (w.uw_width > 0)) + *width = w.uw_width / w.uw_hs; + if (height && (w.uw_height > 0)) + *height = w.uw_height / w.uw_vs; + return GF_OK; +#else + return GF_NOT_SUPPORTED; +#endif +} + #endif @@ -971,7 +1030,7 @@ u32 len; sprintf(szMsg, "{ \"type\": \"logs\", \"level\": \"%s\" \"tool\": \"%s\", \"value\": \"", gf_log_level_name(level), gf_log_tool_name(tool)); - len = strlen(szMsg); + len = (u32) strlen(szMsg); vsnprintf(szMsg, RMT_LOG_SIZE - len - 3, fmt, vlist); strcat(szMsg, "\"}"); @@ -1065,6 +1124,26 @@ #endif } +GF_EXPORT +void gf_sys_profiler_enable_sampling(Bool enable) +{ +#ifndef GPAC_DISABLE_REMOTERY + if (remotery_handle) { + rmt_EnableSampling(enable); + } +#endif +} + +GF_EXPORT +Bool gf_sys_profiler_sampling_enabled() +{ +#ifndef GPAC_DISABLE_REMOTERY + if (remotery_handle) { + return rmt_SamplingEnabled(); + } +#endif + return GF_FALSE; +} void gf_init_global_config(const char *profile); void gf_uninit_global_config(Bool discard_config); @@ -2483,6 +2562,22 @@ } GF_EXPORT +u64 gf_net_ntp_to_utc(u64 ntp) +{ + u64 current_time; + Double msec; + u32 sec = ntp>>32; + u32 frac = ntp & 0xFFFFFFFFUL; + + current_time = sec - GF_NTP_SEC_1900_TO_1970; + current_time *= 1000; + msec = frac*1000.0; + msec /= 0xFFFFFFFF; + current_time += (u64) msec; + return current_time; +} + +GF_EXPORT u64 gf_net_get_utc() { u64 current_time;
View file
gpac-1.0.0.tar.gz/src/utils/os_file.c -> gpac-1.0.1.tar.gz/src/utils/os_file.c
Changed
@@ -274,14 +274,29 @@ wchar_t* wname = gf_utf8_to_wcs(fileName); if (!wname) return GF_FALSE; res = (_waccess(wname, 4) == -1) ? GF_FALSE : GF_TRUE; + if (res == GF_TRUE) { + DWORD att; + att = GetFileAttributesW(wname); + if (att != INVALID_FILE_ATTRIBUTES && (att & FILE_ATTRIBUTE_DIRECTORY)) + res = GF_FALSE; + } gf_free(wname); return res; #elif defined(GPAC_CONFIG_LINUX) - return (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + Bool res = (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + if (res && gf_dir_exists(fileName)) + res = GF_FALSE; + return res; #elif defined(__DARWIN__) || defined(__APPLE__) - return (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + Bool res = (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + if (res && gf_dir_exists(fileName)) + res = GF_FALSE; + return res; #elif defined(GPAC_CONFIG_IOS) || defined(GPAC_CONFIG_ANDROID) - return (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + Bool res = (access(fileName, 4) == -1) ? GF_FALSE : GF_TRUE; + if (res && gf_dir_exists(fileName)) + res = GF_FALSE; + return res; #else FILE *f = gf_fopen(fileName, "r"); if (f) { @@ -559,8 +574,9 @@ #elif defined(WIN32) wchar_t path[GF_MAX_PATH], *file; wchar_t w_filter[GF_MAX_PATH]; - wchar_t w_dir[GF_MAX_PATH]; char *mbs_file, *mbs_item_path; + char _path[GF_MAX_PATH]; + const char* tmpdir; #else char path[GF_MAX_PATH], *file; #endif @@ -616,6 +632,11 @@ iFs.Close(); FlushItemList(); return GF_OK; +#elif defined(GPAC_CONFIG_ANDROID) + dir = getenv("EXTERNAL_STORAGE"); + if (!dir) dir = "/sdcard"; +#elif defined(GPAC_CONFIG_IOS) + dir = (char *) gf_opts_get_key("General", "iOSDocumentsDir"); #endif } @@ -633,23 +654,29 @@ CE_CharToWide(_path, path); CE_CharToWide((char *)filter, w_filter); #elif defined(WIN32) - { - const char* tmpdir = dir; - gf_utf8_mbstowcs(w_dir, sizeof(w_dir), &tmpdir); - } - switch (w_dir[wcslen(w_dir) - 1]) { + + strcpy(_path, dir); + switch (dir[strlen(dir)] - 1) { case '/': case '\\': - swprintf(path, MAX_PATH, L"%s*", w_dir); + snprintf(_path, MAX_PATH, "%s*", dir); break; default: - swprintf(path, MAX_PATH, L"%s%c*", w_dir, GF_PATH_SEPARATOR); + snprintf(_path, MAX_PATH, "%s%c*", dir, GF_PATH_SEPARATOR); break; } - { - const char* tmpfilter = filter; - gf_utf8_mbstowcs(w_filter, sizeof(w_filter), &tmpfilter); + + tmpdir = _path; + if (gf_utf8_mbstowcs(path, GF_MAX_PATH, &tmpdir) == (size_t)-1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot convert %s to UTF16: broken string\n", dir)); + return GF_BAD_PARAM; + } + tmpdir = filter; + if (gf_utf8_mbstowcs(w_filter, sizeof(w_filter), &tmpdir) == (size_t)-1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot convert %s to UTF16: broken string\n", filter)); + return GF_BAD_PARAM; } + #else strcpy(path, dir); if (path[strlen(path)-1] != '/') strcat(path, "/"); @@ -1146,7 +1173,7 @@ #if (_FILE_OFFSET_BITS >= 64) return (u64) ftello64(fp); #else - return (u64) gf_ftell(fp); + return (u64) ftell(fp); #endif #elif defined(WIN32) return (u64) _ftelli64(fp); @@ -1155,7 +1182,7 @@ #elif (defined(GPAC_CONFIG_FREEBSD) || defined(GPAC_CONFIG_DARWIN)) return (u64) ftello(fp); #else - return (u64) gf_ftell(fp); + return (u64) ftell(fp); #endif } @@ -1235,6 +1262,7 @@ GF_FileIO *gfio_ref; GF_FileIO *new_gfio; GF_Err e; + GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Open GFIO %s in mode %s\n", file_name, mode)); if (gfio_type==1) gfio_ref = gf_fileio_from_url(file_name); @@ -1259,6 +1287,7 @@ return (FILE *) new_gfio; } + GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Open file %s in mode %s\n", file_name, mode)); if (strchr(mode, 'w')) { char *fname = gf_strdup(file_name); char *sep = strchr(fname, '/');
View file
gpac-1.0.0.tar.gz/src/utils/os_module.c -> gpac-1.0.1.tar.gz/src/utils/os_module.c
Changed
@@ -314,6 +314,7 @@ load_static_modules(pm); for (i =0; i < pm->num_dirs; i++) { + GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("Refreshing list of modules in directory %s\n", pm->dirs[i])); #ifdef WIN32 gf_enum_directory(pm->dirs[i], GF_FALSE, enum_modules, pm, ".dll"); #elif defined(__APPLE__) @@ -323,7 +324,6 @@ gf_enum_directory(pm->dirs[i], 0, enum_modules, pm, ".dylib"); #endif #else - GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("Refreshing list of modules in directory %s...\n", pm->dirs[i])); #if defined(GPAC_CONFIG_WIN32) gf_enum_directory(pm->dirs[i], 0, enum_modules, pm, ".dll");
View file
gpac-1.0.0.tar.gz/src/utils/os_net.c -> gpac-1.0.1.tar.gz/src/utils/os_net.c
Changed
@@ -62,6 +62,8 @@ #endif +#include <errno.h> + #ifndef EISCONN /*common win32 redefs*/ #undef EAGAIN @@ -1845,7 +1847,7 @@ GF_EXPORT u32 gf_ntohl(u32 val) { - return htonl(val); + return ntohl(val); } GF_EXPORT @@ -1856,9 +1858,9 @@ GF_EXPORT -u16 gf_tohs(u16 val) +u16 gf_ntohs(u16 val) { - return htons(val); + return ntohs(val); } #endif /*GPAC_DISABLE_CORE_TOOLS*/
View file
gpac-1.0.0.tar.gz/static.mak -> gpac-1.0.1.tar.gz/static.mak
Changed
@@ -1,20 +1,20 @@ -NEED_LOCAL_LIB="no" +NEED_LOCAL_LIB=no LINKLIBS= -ifeq ($(DISABLE_CORE_TOOLS), no) +ifeq ($(DISABLE_CORE_TOOLS),no) #1 - zlib support -ifeq ($(CONFIG_ZLIB), local) +ifeq ($(CONFIG_ZLIB),local) CFLAGS+= -I"$(LOCAL_INC_PATH)/zlib" -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes endif -ifneq ($(CONFIG_ZLIB), no) +ifneq ($(CONFIG_ZLIB),no) LINKLIBS+=-lz endif #2 - ssl support -ifeq ($(HAS_OPENSSL), yes) +ifeq ($(HAS_OPENSSL),yes) LINKLIBS+=$(SSL_LIBS) endif @@ -23,7 +23,7 @@ else SCENEGRAPH_CFLAGS+=$(JS_FLAGS) ifeq ($(CONFIG_JS),local) -NEED_LOCAL_LIB="yes" +NEED_LOCAL_LIB=yes endif LINKLIBS+=$(JS_LIBS) endif @@ -31,12 +31,12 @@ endif #4 - JPEG support -ifeq ($(CONFIG_JPEG), no) +ifeq ($(CONFIG_JPEG),no) else LINKLIBS+= -ljpeg #local lib -ifeq ($(CONFIG_JPEG), local) -NEED_LOCAL_LIB="yes" +ifeq ($(CONFIG_JPEG),local) +NEED_LOCAL_LIB=yes MEDIATOOLS_CFLAGS+=-I"$(LOCAL_INC_PATH)/jpeg" FILTERS_CFLAGS+=-I"$(LOCAL_INC_PATH)/jpeg" endif @@ -44,11 +44,11 @@ #5 - PNG support -ifeq ($(CONFIG_PNG), no) +ifeq ($(CONFIG_PNG),no) else LINKLIBS+= -lpng -ifeq ($(CONFIG_PNG), local) -NEED_LOCAL_LIB="yes" +ifeq ($(CONFIG_PNG),local) +NEED_LOCAL_LIB=yes MEDIATOOLS_CFLAGS+=-I"$(LOCAL_INC_PATH)/png" FILTERS_CFLAGS+=-I"$(LOCAL_INC_PATH)/png" endif @@ -59,8 +59,8 @@ COMPOSITOR_CFLAGS= ## Add prefix before every lib -ifneq ($(prefix), /usr/local) -ifneq ($(prefix), /usr) +ifneq ($(prefix),/usr/local) +ifneq ($(prefix),/usr) EXTRALIBS+=-L$(prefix)/lib endif endif @@ -71,30 +71,30 @@ COMPOSITOR_CFLAGS+=$(OGL_INCLS) endif -ifeq ($(NEED_LOCAL_LIB), "yes") +ifeq ($(NEED_LOCAL_LIB),yes) EXTRALIBS+=-L../extra_lib/lib/gcc endif EXTRALIBS+=$(LINKLIBS) -ifeq ($(GPAC_USE_TINYGL), yes) +ifeq ($(GPAC_USE_TINYGL),yes) COMPOSITOR_CFLAGS+=-I"$(SRC_PATH)/../TinyGL/include" else COMPOSITOR_CFLAGS+=-DGPAC_HAS_GLU endif -ifeq ($(ENABLE_JOYSTICK), yes) +ifeq ($(ENABLE_JOYSTICK),yes) COMPOSITOR_CFLAGS+=-DENABLE_JOYSTICK endif ## libgpac media tools compilation options -ifeq ($(GPACREADONLY), yes) +ifeq ($(GPACREADONLY),yes) MEDIATOOLS_CFLAGS=-DGPAC_READ_ONLY endif -ifeq ($(GPAC_ENST), yes) +ifeq ($(GPAC_ENST),yes) OBJS+=$(LIBGPAC_ENST) EXTRALIBS+=-liconv MEDIATOOLS_CFLAGS+=-DGPAC_ENST_PRIVATE @@ -109,11 +109,11 @@ ## static modules # configure static modules -ifeq ($(STATIC_MODULES), yes) +ifeq ($(STATIC_MODULES),yes) CFLAGS+= -DGPAC_STATIC_MODULES -ifeq ($(CONFIG_ALSA), yes) +ifeq ($(CONFIG_ALSA),yes) OBJS+=../modules/alsa/alsa.o CFLAGS+=-DGPAC_HAS_ALSA EXTRALIBS+= -lasound @@ -121,13 +121,13 @@ OBJS+=../modules/validator/validator.o -ifneq ($(CONFIG_FT), no) +ifneq ($(CONFIG_FT),no) OBJS+=../modules/ft_font/ft_font.o EXTRALIBS+= $(FT_LIBS) CFLAGS+=-DGPAC_HAS_FREETYPE $(FT_CFLAGS) endif -ifeq ($(CONFIG_SDL), yes) +ifeq ($(CONFIG_SDL),yes) CFLAGS+=-DGPAC_HAS_SDL $(SDL_CFLAGS) EXTRALIBS+= $(SDL_LIBS) OBJS+=../modules/sdl_out/sdl_out.o ../modules/sdl_out/audio.o ../modules/sdl_out/video.o @@ -137,31 +137,31 @@ ifeq ($(CONFIG_X11),yes) OBJS+= ../modules/x11_out/x11_out.o CFLAGS+=-DGPAC_HAS_X11 -ifneq ($(X11_INC_PATH), ) +ifneq ($(X11_INC_PATH),) CFLAGS+=-I$(X11_INC_PATH) endif -ifneq ($(X11_LIB_PATH), ) +ifneq ($(X11_LIB_PATH),) EXTRALIBS+=-L$(X11_LIB_PATH) endif EXTRALIBS+=-lX11 -ifeq ($(USE_X11_XV), yes) +ifeq ($(USE_X11_XV),yes) CFLAGS+=-DGPAC_HAS_X11_XV EXTRALIBS+=-lXv endif -ifeq ($(USE_X11_XV), yes) +ifeq ($(USE_X11_XV),yes) CFLAGS+=-DGPAC_HAS_X11_XV EXTRALIBS+=-lXv endif -ifeq ($(USE_X11_SHM), yes) +ifeq ($(USE_X11_SHM),yes) CFLAGS+=-DGPAC_HAS_X11_SHM EXTRALIBS+=-lXext endif -ifeq ($(HAS_OPENGL), yes) +ifeq ($(HAS_OPENGL),yes) ifeq ($(CONFIG_DARWIN),yes) EXTRALIBS+=-lGL -lGLU endif @@ -171,13 +171,13 @@ endif -ifeq ($(CONFIG_JACK), yes) +ifeq ($(CONFIG_JACK),yes) OBJS+= ../modules/jack/jack.o CFLAGS+=-DGPAC_HAS_JACK EXTRALIBS+=-ljack endif -ifeq ($(CONFIG_PULSEAUDIO), yes) +ifeq ($(CONFIG_PULSEAUDIO),yes) OBJS+= ../modules/pulseaudio/pulseaudio.o CFLAGS+=-DGPAC_HAS_PULSEAUDIO EXTRALIBS+=-lpulse -lpulse-simple @@ -196,9 +196,9 @@ endif ifeq ($(CONFIG_DIRECTX),yes) -OBJS+= ../modules/dx_hw/dx_audio.o ../modules/dx_hw/dx_video.o ../modules/dx_hw/dx_window.o ../modules/dx_hw/dx_2d.o ../modules/dx_hw/copy_pixels.o +OBJS+= ../modules/dx_hw/dx_audio.o ../modules/dx_hw/dx_video.o ../modules/dx_hw/dx_window.o ../modules/dx_hw/dx_2d.o CFLAGS+=-DGPAC_HAS_DIRECTX -DDIRECTSOUND_VERSION=0x0500 -ifneq ($(DX_PATH), system) +ifneq ($(DX_PATH),system) EXTRALIBS+=-L$(DX_PATH)/lib CFLAGS+= -I$(DX_PATH)/include endif
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.