From 0af0a0eb6b5cf52b17f2597774e36f5aba52d4b3 Mon Sep 17 00:00:00 2001 From: Michael Dale Date: Thu, 23 Jul 2009 02:09:56 +0000 Subject: [PATCH] * Sequencer render updates ** created class/file mvFirefoggRender.js --- .../example_usage/SequencerPlayer_Render.html | 64 ++++++++ .../SequencerPlayer_Seeking.html | 78 ---------- js2/mwEmbed/libAddMedia/mvFirefogg.js | 44 ++++-- js2/mwEmbed/libEmbedVideo/embedVideo.js | 26 ++-- js2/mwEmbed/libEmbedVideo/nativeEmbed.js | 21 ++- js2/mwEmbed/libSequencer/mvFirefoggRender.js | 146 ++++++++++++++++++ js2/mwEmbed/libSequencer/mvPlayList.js | 26 +++- js2/mwEmbed/mv_embed.js | 26 +++- js2/mwEmbed/php/jsAutoloadLocalClasses.php | 1 + 9 files changed, 313 insertions(+), 119 deletions(-) create mode 100644 js2/mwEmbed/example_usage/SequencerPlayer_Render.html delete mode 100644 js2/mwEmbed/example_usage/SequencerPlayer_Seeking.html create mode 100644 js2/mwEmbed/libSequencer/mvFirefoggRender.js diff --git a/js2/mwEmbed/example_usage/SequencerPlayer_Render.html b/js2/mwEmbed/example_usage/SequencerPlayer_Render.html new file mode 100644 index 0000000000..96b96c8c13 --- /dev/null +++ b/js2/mwEmbed/example_usage/SequencerPlayer_Render.html @@ -0,0 +1,64 @@ + + + + mv_embed Seeking Example + + + + + + + + + + +loading render system ... + + + + + + diff --git a/js2/mwEmbed/example_usage/SequencerPlayer_Seeking.html b/js2/mwEmbed/example_usage/SequencerPlayer_Seeking.html deleted file mode 100644 index a420fb61e0..0000000000 --- a/js2/mwEmbed/example_usage/SequencerPlayer_Seeking.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - mv_embed Seeking Example - - - - - - -
- -
- - - position: - -
-
- - - diff --git a/js2/mwEmbed/libAddMedia/mvFirefogg.js b/js2/mwEmbed/libAddMedia/mvFirefogg.js index f1c019c112..2c56d9be4f 100644 --- a/js2/mwEmbed/libAddMedia/mvFirefogg.js +++ b/js2/mwEmbed/libAddMedia/mvFirefogg.js @@ -23,11 +23,19 @@ var firefogg_install_links = { }; var default_firefogg_options = { + //what to do when finished uploading 'upload_done_action':'redirect', + //if firefoog is enabled 'fogg_enabled':false, + //the api url to upload to 'api_url':null, + //the passthrough flag (enables un-modified uploads) 'passthrough': false, + //if we will be showing the encoder interface 'encoder_interface': false, + //if we want to limit the library functionality to "only firefoog" (no upload or progress bars) + 'only_fogg': false, + //callbacks: 'new_source_cb': false, //called on source name update passes along source name @@ -63,7 +71,7 @@ var mvFirefogg = function(iObj){ } mvFirefogg.prototype = { //extends mvBaseUploadInterface - min_firefogg_version : '0.9.8', + min_firefogg_version : '0.9.9', fogg_enabled : false, //if firefogg is enabled or not. encoder_settings:{ //@@todo allow server to set this 'maxSize': 400, @@ -92,21 +100,23 @@ mvFirefogg.prototype = { //extends mvBaseUploadInterface this[i] = default_firefogg_options[i]; } } - - var myBUI = new mvBaseUploadInterface( iObj ); - //standard extends code: - for(var i in myBUI){ - if(this[i]){ - this['pe_'+ i] = myBUI[i]; - }else{ - this[i] = myBUI[i]; + //check if we want to limit the usage: + if(!this.only_fogg){ + var myBUI = new mvBaseUploadInterface( iObj ); + + //standard extends code: + for(var i in myBUI){ + if(this[i]){ + this['pe_'+ i] = myBUI[i]; + }else{ + this[i] = myBUI[i]; + } } } - if(!this.selector){ - js_log('Error: firefogg: missing selector '); - } - //if detect + if(!this.selector){ + js_log('firefogg: missing selector '); + } }, doRewrite:function( callback ){ var _this = this; @@ -222,10 +232,10 @@ mvFirefogg.prototype = { //extends mvBaseUploadInterface }); }, firefoggCheck:function(){ - if(typeof(Firefogg) != 'undefined' && Firefogg().version >= '0.9.9'){ - this.fogg = new Firefogg(); - this.fogg_enabled = true; - return true; + if(typeof(Firefogg) != 'undefined' && Firefogg().version >= this.min_firefogg_version){ + this.fogg = new Firefogg(); + this.fogg_enabled = true; + return true; }else{ return false; } diff --git a/js2/mwEmbed/libEmbedVideo/embedVideo.js b/js2/mwEmbed/libEmbedVideo/embedVideo.js index 2c82944669..bf531b1f4e 100644 --- a/js2/mwEmbed/libEmbedVideo/embedVideo.js +++ b/js2/mwEmbed/libEmbedVideo/embedVideo.js @@ -454,7 +454,7 @@ var ctrlBuilder = { function(){ $j('#vol_container_' + embedObj.id).addClass('vol_container_top'); //set to "below" if playing and embedType != native - if(embedObj.isPlaying() && !embedObj.supports['overlays']){ + if(embedObj && embedObj.isPlaying() && !embedObj.supports['overlays']){ $j('#vol_container_' + embedObj.id).removeClass('vol_container_top').addClass('vol_container_below'); } @@ -1364,7 +1364,14 @@ embedVideo.prototype = { } //do play in 100ms (give things time to clear) setTimeout('$j(\'#' + this.id + '\').get(0).play()',100); - }, + }, + /* + * seeks to the requested time and issues a callback when ready + * (should be overwitten by client that supports frame serving) + */ + setCurrentTime:function( time, callback){ + js_log('error: base embed setCurrentTime can not frame serve (overide via plugin)'); + }, addPresTimeOffset:function(){ //add in the offset: if(this.seek_time_sec && this.seek_time_sec!=0){ @@ -1808,7 +1815,7 @@ embedVideo.prototype = { ''; - if(this.play_button==true) + if(this.play_button == true && this.controls == true) thumb_html+=this.getPlayButton(); thumb_html+=''; @@ -2370,11 +2377,12 @@ embedVideo.prototype = { //do head request if on the same domain return this.media_element.selected_source.URLTimeEncoding; }, - setSliderValue: function(perc, hide_progress){ - var this_id = (this.pc)?this.pc.pp.id:this.id; - var val = parseInt( perc*1000 ); - $j('#mv_play_head_'+this_id).slider('value', val); - + setSliderValue: function(perc, hide_progress){ + if(this.controls){ + var this_id = (this.pc)?this.pc.pp.id:this.id; + var val = parseInt( perc*1000 ); + $j('#mv_play_head_'+this_id).slider('value', val); + } //js_log('set#mv_seeker_slider_'+this_id + ' perc in: ' + perc + ' * ' + $j('#mv_seeker_'+this_id).width() + ' = set to: '+ val + ' - '+ Math.round(this.mv_seeker_width*perc) ); //js_log('op:' + offset_perc + ' *('+perc+' * ' + $j('#slider_'+id).width() + ')'); }, @@ -2746,7 +2754,7 @@ var embedTypes = { if (dummyvid.canPlayType && dummyvid.canPlayType("video/ogg;codecs=\"theora,vorbis\"") == "probably") { this.players.addPlayer( videoElementPlayer ); - } else if(this.supportedMimeType('video/ogg')) { + } else if(this.supportedMimeType( 'video/ogg' )) { /* older versions of safari do not support canPlayType, but xiph qt registers mimetype via quicktime plugin */ this.players.addPlayer( videoElementPlayer ); diff --git a/js2/mwEmbed/libEmbedVideo/nativeEmbed.js b/js2/mwEmbed/libEmbedVideo/nativeEmbed.js index f8adb18f37..c547dd88a6 100644 --- a/js2/mwEmbed/libEmbedVideo/nativeEmbed.js +++ b/js2/mwEmbed/libEmbedVideo/nativeEmbed.js @@ -120,21 +120,26 @@ var nativeEmbed = { setCurrentTime: function(pos, callback){ var _this = this; this.getVID(); - if(!this.vid) { - js_log('native:setCurrentTime: load video'); + if(!this.vid) { this.load(); var loaded = function(event) { js_log('native:setCurrentTime (after load): ' + pos + ' : dur: ' + this.getDuration()); _this.vid.currentTime = pos; - var once = function(event) { callback(); _this.vid.removeEventListener('seeked', once, false) }; + var once = function(event) { + callback(); + _this.vid.removeEventListener('seeked', once, false) + }; _this.vid.addEventListener('seeked', once, false); _this.removeEventListener('loadedmetadata', loaded, false); }; _this.addEventListener('loadedmetadata', loaded, false); } else { - js_log('native:setCurrentTime: ' + pos + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec ); + //js_log('native:setCurrentTime: ' + pos + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec ); _this.vid.currentTime = pos; - var once = function(event) { callback(); _this.vid.removeEventListener('seeked', once, false) }; + var once = function(event) { + callback(); + _this.vid.removeEventListener('seeked', once, false) + }; _this.vid.addEventListener('seeked', once, false); } }, @@ -169,7 +174,7 @@ var nativeEmbed = { * native callbacks for the video tag: */ oncanplaythrough : function(){ - js_log('f:oncanplaythrough'); + //js_log('f:oncanplaythrough'); this.getVID(); if( ! this.paused ) this.vid.play(); @@ -238,6 +243,10 @@ var nativeEmbed = { if(this.vid) return this.vid.volume; }, + getNativeDuration:function(){ + if(this.vid) + return this.vid.duration; + }, load:function(){ this.getVID(); if( !this.vid ){ diff --git a/js2/mwEmbed/libSequencer/mvFirefoggRender.js b/js2/mwEmbed/libSequencer/mvFirefoggRender.js new file mode 100644 index 0000000000..2f5fd2d99c --- /dev/null +++ b/js2/mwEmbed/libSequencer/mvFirefoggRender.js @@ -0,0 +1,146 @@ +/* + * hanndles driving the firefogg render system +*/ + +var mvFirefoggRender = function( iObj ) { + return this.init( iObj ); +}; +var default_render_options = { + "videoQuality" : 10, + "framerate" : 30, + "width" : 400, + "height" : 300 +} +var default_FirefoggRender_options = { + start_time:0, + //if we should save to disk (if false setup upload stuff below) + save_to_disk:true +} +//set up the mvPlaylist object +mvFirefoggRender.prototype = { + //default empty render options: + renderOptions: {}, + continue_rendering:false, + init:function( iObj ){ + var _this = this; + + //grab the mvFirefogg object to do basic tests + this.myFogg = new mvFirefogg({ + 'only_fogg':true + }); + + //check for firefogg: + if( this.myFogg.firefoggCheck() ){ + this.enabled = true; + }else{ + this.enabled = false; + return this; + } + + //set up local fogg pointer: + this.fogg = this.myFogg.fogg; + + //setup player instance + this.player = $j(iObj.player_target).get(0); + this.player_target = iObj.player_target; + + //setup the render options (with defaults) + for(var i in default_render_options){ + if( iObj['render_options'][i] ){ + this.renderOptions[ i ] = iObj['render_options'][i]; + }else{ + this.renderOptions[ i ] = default_render_options[i]; + } + } + //setup the application options (with defaults) + for(var i in default_FirefoggRender_options ){ + if( iObj[ i ] ){ + this[ i ] = iObj[ i ]; + }else{ + this[ i ] = default_FirefoggRender_options[i]; + } + } + //set up targets and local vars + + if( iObj.target_startRender ){ + $j(iObj.target_startRender).click(function(){ + js_log("Start render"); + _this.startRender(); + }) + this.target_startRender = iObj.target_startRender; + } + if( iObj.target_stopRender ){ + $j(iObj.target_stopRender).click(function(){ + _this.stopRender(); + }) + this.target_stopRender = iObj.target_stopRender; + } + if( iObj.target_timeStatus ){ + this.target_timeStatus = iObj.target_timeStatus; + } + }, + startRender:function(){ + var _this = this; + var t = this.start_time; + //get the interval from renderOptions framerate + var interval = 1 / this.renderOptions.framerate + + //issue a load request on the player: + this.player.load(); + + //init the Render + this.fogg.initRender( JSON.stringify( _this.renderOptions ), 'foggRender' ); + + //add audio if we had any: + + //request a target (should support rendering to temp location too) + this.fogg.saveVideoAs(); + + //set the continue rendering flag to true: + this.continue_rendering = true; + + //internal function to hanndle updates: + var doNextFrame = function(){ + $j(_this.target_timeStatus).val( " on " + (Math.round(t*10)/10) + " of "+ + (Math.round( _this.player.getDuration() * 10) / 10 ) ); + _this.player.setCurrentTime(t, function(){ + _this.fogg.addFrame( $j(_this.player_target).attr('id') ); + t += interval; + if(t >= _this.player.getDuration() ){ + _this.doFinalRender(); + }else{ + if(_this.continue_rendering){ + doNextFrame(); + }else{ + //else quit: + _this.doFinalRender(); + } + } + }); + } + doNextFrame(); + }, + stopRender:function(){ + this.continue_rendering=false; + }, + doFinalRender:function(){ + $j(this.target_timeStatus).val("doing final render"); + this.fogg.render(); + this.updateStatus(); + }, + updateStatus:function(){ + var _this = this; + var doUpdateStatus = function(){ + var rstatus = _this.fogg.renderstatus() + $j(_this.target_timeStatus).val(rstatus); + if(rstatus != 'done' && rstatus != 'rendering failed') { + setTimeout(doUpdateStatus, 100); + } else { + $j(_this.target_startRender).attr("disabled", false); + } + } + doUpdateStatus(); + } + + +} \ No newline at end of file diff --git a/js2/mwEmbed/libSequencer/mvPlayList.js b/js2/mwEmbed/libSequencer/mvPlayList.js index a140927d94..4c1d8fcd42 100644 --- a/js2/mwEmbed/libSequencer/mvPlayList.js +++ b/js2/mwEmbed/libSequencer/mvPlayList.js @@ -519,10 +519,12 @@ mvPlayList.prototype = { $j('#mv_time_'+this.id).html( value ); }, setSliderValue:function(value){ - if(this.cur_clip.embed){ - //js_log('calling original embed slider with val: '+value); - this.cur_clip.embed.pe_setSliderValue( value ); - //call seq playline update here + if( this.controls ){ + if(this.cur_clip.embed){ + //js_log('calling original embed slider with val: '+value); + this.cur_clip.embed.pe_setSliderValue( value ); + //call seq playline update here + } } }, getPlayHeadPos: function(prec_done){ @@ -718,7 +720,13 @@ mvPlayList.prototype = { } //start up the playlist monitor this.monitor(); - }, + }, + /* + * the load function loads all the clips in order + */ + load:function(){ + //do nothing right now) + }, toggleMute:function(){ this.cur_clip.embed.toggleMute(); }, @@ -828,10 +836,12 @@ mvPlayList.prototype = { if (_this.cur_clip.id != clip.id) { _this.updateCurrentClip( clip ); } - _this.cur_clip.embed.setCurrentTime(clipTime, callback); + _this.cur_clip.embed.setCurrentTime(clipTime, function(){ + if(callback) + callback(); + }); _this.currentTime = pos; - _this.doSmilActions(); - return ''; + _this.doSmilActions(); } currentOffset += nextTime; } diff --git a/js2/mwEmbed/mv_embed.js b/js2/mwEmbed/mv_embed.js index c770e31db8..159eaab17f 100644 --- a/js2/mwEmbed/mv_embed.js +++ b/js2/mwEmbed/mv_embed.js @@ -225,6 +225,7 @@ lcPaths( 'libEmbedVideo/', [ lcPaths( 'libSequencer/', [ 'mvPlayList', 'mvSequencer', + 'mvFirefoggRender', 'mvTimedEffectsEdit' ]) //libTimedText: @@ -894,6 +895,29 @@ function mv_jqueryBindings(){ } }); } + //takes a input player as the selector and exposes basic rendering controls + $.fn.firefoggRender = function( iObj, callback ){ + //check if we already have render loaded then just pass on updates/actions + var sElm = $j(this.selector).get(0); + if(sElm['fogg_render']){ + if(sElm['fogg_render']=='loading'){ + js_log("Error: called firefoggRender while loading"); + return false; + } + //call or update the property: + } + sElm['fogg_render']='loading'; + //add the selector: + iObj['player_target'] = this.selector; + mvJsLoader.doLoad([ + 'mvFirefogg', + 'mvFirefoggRender' + ],function(){ + sElm['fogg_render']= new mvFirefoggRender( iObj ); + if( callback && typeof callback == 'function' ) + callback( sElm['fogg_render'] ); + }); + } $.fn.baseUploadInterface = function(iObj){ mvJsLoader.doLoad([ @@ -969,7 +993,7 @@ function getURLParamReplace( url, opt ){ */ function seconds2npt(sec, show_ms){ if( isNaN( sec ) ){ - js_log("warning: trying to get npt time on NaN:" + sec); + //js_log("warning: trying to get npt time on NaN:" + sec); return '0:0:0'; } var hours = Math.floor(sec/ 3600); diff --git a/js2/mwEmbed/php/jsAutoloadLocalClasses.php b/js2/mwEmbed/php/jsAutoloadLocalClasses.php index a2c5736a1a..4af42942c3 100644 --- a/js2/mwEmbed/php/jsAutoloadLocalClasses.php +++ b/js2/mwEmbed/php/jsAutoloadLocalClasses.php @@ -84,6 +84,7 @@ $wgJSAutoloadLocalClasses['vlcEmbed'] = $wgMwEmbedDirectory . 'libEmbedVideo/ $wgJSAutoloadLocalClasses['mvPlayList'] = $wgMwEmbedDirectory . 'libSequencer/mvPlayList.js'; $wgJSAutoloadLocalClasses['mvSequencer'] = $wgMwEmbedDirectory . 'libSequencer/mvSequencer.js'; $wgJSAutoloadLocalClasses['mvSequencer'] = $wgMwEmbedDirectory . 'libSequencer/mvSequencer.js'; +$wgJSAutoloadLocalClasses['mvFirefoggRender'] = $wgMwEmbedDirectory . 'libSequencer/mvFirefoggRender.js'; // libTimedText: $wgJSAutoloadLocalClasses['mvTimedEffectsEdit'] = $wgMwEmbedDirectory . 'libTimedText/mvTimedEffectsEdit.js'; \ No newline at end of file -- 2.20.1