http://www.mediawiki.org/wiki/Special:Code/MediaWiki/69006

Revision: 69006
Author:   dale
Date:     2010-07-04 15:52:19 +0000 (Sun, 04 Jul 2010)

Log Message:
-----------
added audio track layout support to render
commented out some render time debug lines

Modified Paths:
--------------
    
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js
    
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js
    branches/MwEmbedStandAlone/modules/Sequencer/mw.FirefoggRender.js
    branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js
    branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js
    branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js
    branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js
    branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoCrossfadeSmil.xml

Modified: 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js
===================================================================
--- 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js
    2010-07-04 15:29:52 UTC (rev 69005)
+++ 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js
    2010-07-04 15:52:19 UTC (rev 69006)
@@ -339,7 +339,7 @@
                        .loadingSpinner()
                );
 
-               if( mw.getConfig( 'EmbedPlayer.kalturaAttribution' ) == true ){
+               if( mw.getConfig( 'EmbedPlayer.KalturaAttribution' ) == true ){
                        $target.append( 
                                $j( '<div />' )
                                .addClass( 'k-attribution' )

Modified: 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js
===================================================================
--- 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js 
    2010-07-04 15:29:52 UTC (rev 69005)
+++ 
branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js 
    2010-07-04 15:52:19 UTC (rev 69006)
@@ -162,7 +162,7 @@
                        this.supportedComponets['timedText'] = true;
                }               
                // Check for kalturaAttribution         
-               if( mw.getConfig( 'EmbedPlayer.KalturaAttribution' ) ){         
                                         
+               if( mw.getConfig( 'EmbedPlayer.KalturaAttribution' ) ){         
        
                        this.supportedComponets[ 'kalturaAttribution' ] = true;
                }
                

Modified: branches/MwEmbedStandAlone/modules/Sequencer/mw.FirefoggRender.js
===================================================================
--- branches/MwEmbedStandAlone/modules/Sequencer/mw.FirefoggRender.js   
2010-07-04 15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/Sequencer/mw.FirefoggRender.js   
2010-07-04 15:52:19 UTC (rev 69006)
@@ -81,7 +81,9 @@
                
                
        },
-       
+       getPlayer: function(){
+               return $j( this.playerTarget ).get( 0 );
+       },
        // Start rendering
        doRender: function() {
                var _this = this;
@@ -94,16 +96,30 @@
                
                // Set the continue rendering flag to true:
                this.continueRendering = true;
-               
-               // Get the player:
-               this.player = $j( this.playerTarget ).get( 0 );
 
                // Set a target file:
                mw.log( "Firefogg Render Settings:" + JSON.stringify( 
_this.renderOptions ) );
                this.fogg.initRender(  JSON.stringify( _this.renderOptions ), 
'foggRender.ogv' );                               
                        
                // Add audio if we had any:
+               var audioSet = this.getPlayer().getAudioTimeSet();              
+               var previusAudioTime = 0;
+               for( var i=0; i < audioSet.length ; i++) {
+                       var currentAudio = audioSet[i];
+                       // Check if we need to add silence
+                       if( currentAudio.startTime > previusAudioTime ){
+                               mw.log("FirefoggRender::addSilence " + ( 
currentAudio.startTime - previusAudioTime ));
+                               this.fogg.addSilence( currentAudio.startTime - 
previusAudioTime );
+                       }
+                       // Add the block of audio from the url
+                       mw.log("FirefoggRender::addAudioUrl " + 
currentAudio.src + 
+                                       ', ' + currentAudio.offset + ', ' + 
currentAudio.duration );
+                       this.fogg.addAudioUrl( currentAudio.src, 
currentAudio.offset, currentAudio.duration );
 
+                       // Update previusAudioTime
+                       previusAudioTime = currentAudio.startTime + 
currentAudio.duration;
+               }
+               
                // Now issue the save video as call
                _this.fogg.saveVideoAs();
                
@@ -120,14 +136,14 @@
                        ( Math.round( _this.player.getDuration() * 10 ) / 10 ) 
);
                */
                
-               _this.player.setCurrentTime( _this.renderTime, function() {     
                                                        
+               _this.getPlayer().setCurrentTime( _this.renderTime, function() 
{                                                                
                        
                        _this.fogg.addFrame( $j( _this.playerTarget ).attr( 
'id' ) );
                        $j( _this.statusTarget ).text( "AddFrame::" + ( 
Math.round( _this.renderTime * 1000 ) / 1000 ) );
                        
                        _this.renderTime += _this.interval;
                         
-                       if ( _this.renderTime >= _this.player.getDuration() || 
! _this.continueRendering ) {
+                       if ( _this.renderTime >= 
_this.getPlayer().getDuration() || ! _this.continueRendering ) {
                                _this.doFinalRender();
                        } else {                        
                                // Don't block on render requests

Modified: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js
===================================================================
--- branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js 
2010-07-04 15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/SmilPlayer/mw.EmbedPlayerSmil.js 
2010-07-04 15:52:19 UTC (rev 69006)
@@ -79,7 +79,7 @@
                var _this = this;
                this.getSmil( function( smil ){ 
                        smil.renderTime( time, function(){
-                               mw.log( "setCurrentTime:: renderTime callback" 
);
+                               //mw.log( "setCurrentTime:: renderTime 
callback" );
                                $j('#loadingSpinner_' + _this.id ).remove();
                                
                                _this.monitor();
@@ -277,9 +277,9 @@
         * tracks from movie files. 
         */
        getAudioTimeSet: function(){
-               if(!this.smil)
+               if(!this.smil){
                        return null;
-               
+               }               
                return this.smil.getAudioTimeSet();             
        }
        

Modified: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js
===================================================================
--- branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js    2010-07-04 
15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/SmilPlayer/mw.Smil.js    2010-07-04 
15:52:19 UTC (rev 69006)
@@ -152,6 +152,13 @@
        },
        
        /**
+        * Get the set of audio ranges for flattening. 
+        */
+       getAudioTimeSet: function(){
+               return this.getBody().getFlatAudioTimeLine();
+       },
+       
+       /**
         * Pass on the request to start buffering the entire sequence of clips 
         */
        startBuffer: function(){
@@ -234,17 +241,10 @@
                
        /**
         * Some Smil Utility functions
-        */
+        */     
        
        /**
-        * Returns a set of audio ranges for flattening. 
-        */
-       getAudioTimeSet: function( ){
-               return {};
-       },
-       
-       /**
-       * maps a smil element id to a html safe id 
+       * maps a smil element id to a html 'safer' id 
        * as a decedent subname of the embedPlayer parent
        *
        * @param {Object} smilElement Element to get id for
@@ -280,9 +280,15 @@
                        return;
                }
                // Get the smil type
-               var smilType = $j( smilElement ).get(0).nodeName.toLowerCase(); 
+               var smilType = $j( smilElement ).get(0).nodeName.toLowerCase();
+               
+               if( this.getBody().smilBlockTypeMap[ smilType ] != 'ref' ){
+                       mw.log("Error: trying to get ref type of node that is 
not a ref" + smilType);
+                       return null; 
+               }
+               
+               // If the smilType is ref, check for a content type
                if( smilType == 'ref' ){
-                       // If the smilType is ref, check for a content type
                        switch( $j( smilElement ).attr( 'type' ) ) {
                                case 'text/html':
                                        smilType = 'cdata_html';
@@ -292,6 +298,9 @@
                                case 'video/webm':
                                        smilType = 'video';
                                break;
+                               case 'audio/ogg':
+                                       smilType = 'audio';
+                               break;
                        }
                }
                return smilType;

Modified: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js
===================================================================
--- branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js        
2010-07-04 15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBody.js        
2010-07-04 15:52:19 UTC (rev 69006)
@@ -21,6 +21,16 @@
        // This lets us cache a valid element list for a given amount of time
        cacheElementList: {},
        
+       smilBlockTypeMap: {
+               'body':'seq',
+               'ref' : 'ref',
+               'animation':'ref',
+               'audio' : 'ref',
+               'img' : 'ref',
+               'textstream' : 'ref',
+               'video' : 'ref'
+       },
+       
        // Constructor: 
        init: function( smilObject ){
                this.smil = smilObject;
@@ -57,7 +67,8 @@
        },
        
        /**
-       * Render the body elements for a given time, use layout engine to draw 
elements 
+       * Render the body elements for a given time, use layout engine to draw 
elements
+       * @param time  
        */
        renderTime: function( time, deltaTime ){
                var _this = this;
@@ -98,59 +109,172 @@
        },
        
        /**
-       * Check if we have a valid element cache: 
-       * XXX not yet working.
-       */
-       isValidElementCache: function( time ){
-               if( time > this.cacheElementList.validStart && time > 
this.cacheElementList.validEnd ) {
-                       return this.cacheElementList.elements; 
+        * Firefogg flattener can presently only sequence flat sequence of audio
+        * Also See: http://www.firefogg.org/dev/render.html
+        * 
+        * Note if we could "blend" or play two audio files at the same time
+        *  none of this would be needed 
+        *  
+        *  ie this code should be replaced once we add improved audio support
+        * 
+        * @return {Object} an array of audio with the following properties: 
+        *      start The start offset of the audio asset. 
+        *      duration Duration of the audio asset
+        *      src The source url, if set to false, silence is inserted for 
duration
+        *      type Used internally to let audio overlay video.
+        */
+       getFlatAudioTimeLine: function(){
+               var _this = this;
+               
+               // Setup some flags:
+               var maxAudioTime =0;
+               
+               var elementsWithAudio = [];             
+               var audioTimeline = [];
+               
+               // xxx could probably do this a bit cleaner
+               var getEarliest = function ( audioTimeline ){
+                       var smallTime = null;
+                       var smallIndex = null
+                       for( var i =0; i < audioTimeline.length; i++ ){
+                               if( smallTime === null ){
+                                       smallTime = 
audioTimeline[i]['startTime'];
+                                       smallIndex = i;
+                               }
+                               
+                               if( audioTimeline[i]['startTime'] < smallTime ){
+                                       smallTime = 
audioTimeline[i]['startTime'];
+                                       smallIndex = i;
+                               }
+                       }
+                       return smallIndex = i;
                }
+               // Build an audio timeline starting from the top level node: 
+               this.getRefElementsRecurse( this.$dom, 0, function( $node ){
+                       var nodeType = _this.smil.getRefType( $node ) ;
+                       // Check if the node is audio ( first in wins / "audio" 
wins over video) 
+                       if( nodeType == 'audio' || nodeType == 'video' ) {
+                               var audioObj = {
+                                       'type' : nodeType,
+                                       'src' : _this.smil.getAssetUrl ( 
$node.attr('src') ),
+                                       'duration' : _this.getNodeDuration( 
$node ),
+                                       'startTime' : $node.data( 'startOffset' 
),
+                                       'offset' : 0 // have to add in 
media-offset support
+                               };
+                               
+                               // If audioTimeline is empty insert directly 
+                               if( audioTimeline.length == 0 ){
+                                       audioTimeline.push( audioObj )
+                                       return ;
+                               }
+                               
+                               // fill time
+                               var addedAudioFlag = false;
+                               for( var i = 0; i < audioTimeline.length; i++ ){
+                                       var currentAudioObj = audioTimeline[i];
+                                       var audioEndTime = 
audioObj['startTime'] + audioObj['duration']; 
+                                       var currentAudioEndTime = 
currentAudioObj['startTime'] + currentAudioObj['duration'];
+                                       if( audioObj['startTime'] < 
currentAudioObj['startTime']  ){
+                                               addedAudioFlag = true;
+                                               var beforeAudioObj = $j.extend( 
audioObj, {
+                                                       'duration': ( 
currentAudioObj['startTime'] - audioObj['startTime'] )
+                                               });
+                                               // Add before
+                                               audioTimeline.splice( i, 0, 
beforeAudioObj );
+                                               
+                                               // Update the audioObj if it 
extends past the currentAudioObject                                
+                                               if(  audioEndTime > 
currentAudioEndTime){                                               
+                                                       audioObj['startTime'] = 
currentAudioEndTime;
+                                                       audioObj['duration'] = 
audioEndTime - currentAudioEndTime;
+                                               } else {
+                                                       // done adding audioObj
+                                                       break;
+                                               }
+                                       }
+                               }
+                               // add audioObject to end ( currentAudioObj has 
latest startTime
+                               if( ! addedAudioFlag &&  audioEndTime > 
currentAudioEndTime ){
+                                       var audioObjDuration = ( audioEndTime - 
currentAudioEndTime );
+                                       if( currentAudioEndTime + 
audioObjDuration > _this.getDuration() ){
+                                               audioObjDuration = 
_this.getDuration() - currentAudioEndTime;
+                                       }
+                                       audioTimeline.push( $j.extend( 
audioObj, {
+                                                       'duration': 
audioObjDuration,
+                                                       'startTime' : 
currentAudioEndTime
+                                               })
+                                       );
+                               }
+                               
+                               // Keep audioTimeline sorted via startTime
+                               audioTimeline.sort( function( a, b){
+                                       return a.startTime - b.startTime;
+                               });
+                       }
+               });
+               
+               return audioTimeline;
        },
        
        /**
         * Gets all the elements for a given time. 
+        * 
+        * Note this gets called all the time we may need to build a more 
efficient structure to access this info
         */ 
        getElementsForTime: function ( time , inRangeCallback, 
outOfRangeCallback ) {
-               var startOffset = 0;
+               var _this = this;
                if( !time ) {
                        time =0;
                }               
-               // Empty out the requested element set:                 
-               this.getElementsForTimeRecurse( this.$dom, time, startOffset, 
inRangeCallback, outOfRangeCallback);
+               // Recurse on every ref element and run relevant callbacks
+               this.getRefElementsRecurse( this.$dom, 0, function( $node ){
+                       var startOffset = $node.data( 'startOffset' );
+                       var nodeDuration = _this.getNodeDuration( $node );
+                       
+                       // Check if element is in range: 
+                       if( time >= startOffset && time <= ( startOffset + 
nodeDuration) ){
+                               if( typeof inRangeCallback == 'function' ){
+                                       inRangeCallback( $node );
+                               }       
+                       } else {
+                               if( typeof outOfRangeCallback == 'function'){
+                                       outOfRangeCallback( $node );
+                               }
+                       }
+               });
        },
        
        /**
         * getElementsForTimeRecurse
         * @param {Object} $node Node to recursively search for elements in the 
given time range
         */ 
-       getElementsForTimeRecurse: function( $node, time, startOffset, 
inRangeCallback, outOfRangeCallback){
+       
+       /**
+        * Recurse over all body elements, issues a callback on all ref and 
smilText nodes
+        * adds startOffset info for easy timeline checks.
+        */
+       getRefElementsRecurse: function( $node, startOffset, callback ){
                var _this = this;
-               // Setup local pointers:
-               var nodeDuration = this.getNodeDuration( $node );
+               // Setup local pointers:                
                var nodeType = this.getNodeSmilType( $node );
-               var nodeParentType = this.getNodeSmilType( $node.parent() );    
        
-                                                               
-                               
-               // If 'par' or 'seq' recurse to get elements for layout
+               
+               // If 'par' or 'seq' recurse on children 
                if( nodeType == 'par' || nodeType == 'seq' ) {
                        if( $node.children().length ) { 
                                $node.children().each( function( inx, childNode 
){
                                        // mw.log(" recurse:: startOffset:" + 
nodeType  + ' start offset:' + startOffset );
-                                       var childDur = 
_this.getElementsForTimeRecurse( 
-                                               $j( childNode ), 
-                                               time, 
-                                               startOffset, 
-                                               inRangeCallback, 
-                                               outOfRangeCallback 
+                                       var childDur = 
_this.getRefElementsRecurse( 
+                                               $j( childNode ),  
+                                               startOffset,
+                                               callback
                                        );
                                        // If element parent is a 'seq' 
increment startOffset as we recurse for each child
                                        if( nodeType == 'seq' ) {
                                                //mw.log(" Parent Seq:: add 
child dur: " + childDur );
                                                startOffset += childDur;
-                                       }                                       
+                                       }                       
                                });
                        }                       
-               }                                                       
+               }
                
                // If the nodeType is "ref" or smilText run the callback
                if( nodeType == 'ref' || nodeType == 'smilText' ) {             
@@ -161,26 +285,17 @@
                        }
                        
                        // Add the parent startOffset 
-                       $node.data( 'startOffset', startOffset );               
                                
+                       $node.data( 'startOffset', startOffset );               
                        
-                       // Check if element is in range: 
-                       if( time >= startOffset && time <= ( startOffset + 
nodeDuration) ){
-                               if( typeof inRangeCallback == 'function' ){
-                                       inRangeCallback( $node );
-                               }       
-                       } else {
-                               if( typeof outOfRangeCallback == 'function'){
-                                       outOfRangeCallback( $node );
-                               }
-                       }
-               }               
+                       callback( $node )
+               }
                // Return the node Duration for tracking startOffset
                return this.getNodeDuration( $node );
        },
        
        /**
         * Returns the smil body duration
-        * ( wraps getDurationRecurse to get top level duration ) 
+        * ( wraps getDurationRecurse to get top level node duration ) 
         */     
        getDuration: function(){                
                this.duration = this.getNodeDuration( this.$dom );      
@@ -215,7 +330,7 @@
                                        $node.data( 'implictDuration', 
$node.data('implictDuration') + childDuration );                         
                                }                       
                                // With par blocks ImplictDuration is longest 
duration child
-                               if( blockType == 'par' ){
+                               if( blockType == 'par' ) {
                                        if( childDuration > $node.data( 
'implictDuration' ) ){
                                                $node.data( 'implictDuration',  
childDuration); 
                                        }
@@ -255,18 +370,10 @@
         */
        getNodeSmilType: function( $node ){
                var blockType = $j( $node ).get(0).nodeName;
-               var blockMap = {
-                       'body':'seq',
-                       'ref' : 'ref',
-                       'animation':'ref',
-                       'audio' : 'ref',
-                       'img' : 'ref',
-                       'textstream' : 'ref',
-                       'video' : 'ref'
+               
+               if( this.smilBlockTypeMap[ blockType ] ){
+                       blockType = this.smilBlockTypeMap[ blockType ];
                }
-               if( blockMap[ blockType ] ){
-                       blockType = blockMap[ blockType ];
-               }
                return blockType;
        }       
 }
\ No newline at end of file

Modified: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js
===================================================================
--- branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js      
2010-07-04 15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilLayout.js      
2010-07-04 15:52:19 UTC (rev 69006)
@@ -158,6 +158,9 @@
                        case 'video': 
                                return this.getSmilVideoHtml( smilElement );
                        break;
+                       case 'audio':
+                               return this.getSmilAudioHtml( smilElement );
+                       break;
                        // Smil Text: http://www.w3.org/TR/SMIL/smil-text.html 
( obviously we support a subset )
                        case 'smiltext':
                                return this.getSmilTextHtml( smilElement );
@@ -181,16 +184,28 @@
        /**
        * Return the video
        */
-       getSmilVideoHtml: function( videoElement ){
+       getSmilVideoHtml: function( smilElement ){
                return $j('<video />')
                        .attr( {
-                               'id' : this.smil.getAssetId( videoElement ), 
-                               'src' : this.smil.getAssetUrl( $j( videoElement 
).attr( 'src' ) )
+                               'id' : this.smil.getAssetId( smilElement ), 
+                               'src' : this.smil.getAssetUrl( $j( smilElement 
).attr( 'src' ) )
                        } )
                        .addClass( 'smilFillWindow' )
        },
        
        /**
+        * Return audio element ( by default audio tracks are hidden )
+        */
+       getSmilAudioHtml: function ( smilElement ){
+               return $j('<audio />')
+               .attr( {
+                       'id' : this.smil.getAssetId( smilElement ), 
+                       'src' : this.smil.getAssetUrl( $j( smilElement ).attr( 
'src' ) )
+               } )
+               .css( 'display', 'none');
+       },
+       
+       /**
         * Get Smil CDATA ( passed through jQuery .clean as part of fragment 
creation )
         * XXX Security XXX 
         * Here we are parsing in SMIL -> HTML should be careful about XSS or 
script elevation 

Modified: 
branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoCrossfadeSmil.xml
===================================================================
--- branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoCrossfadeSmil.xml  
2010-07-04 15:29:52 UTC (rev 69005)
+++ branches/MwEmbedStandAlone/modules/SmilPlayer/tests/VideoCrossfadeSmil.xml  
2010-07-04 15:52:19 UTC (rev 69006)
@@ -17,7 +17,12 @@
   </head>
   <body>
     <par>
-     
+    
+    <audio 
src="http://upload.wikimedia.org/wikipedia/commons/5/5a/La_Donna_E_Mobile_Rigoletto.ogg";
+       begin="1s"
+       dur="10s"
+    />
+    
        <video 
src="http://upload.wikimedia.org/wikipedia/commons/d/d3/Okapia_johnstoni5.ogg";  
         
                transIn="fromGreen"     
                type="video/ogg"        
@@ -27,7 +32,7 @@
        />      
        
     <video 
src="http://upload.wikimedia.org/wikipedia/commons/0/0d/B-36_bomber.ogg";    
-       begin="5s"                      
+       begin="5s"              
        transIn="xFade"
                        
                fill="transition" 



_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to