r38607 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r38606‎ | r38607 | r38608 >
Date:01:20, 5 August 2008
Author:dale
Status:old
Tags:
Comment:
flvserver mostly working
Modified paths:
  • /branches/MetavidWiki-exp/MetavidWiki/skins/mv_embed/flvServer/MvFlv.php (added) (history)

Diff [purge]

Index: branches/MetavidWiki-exp/MetavidWiki/skins/mv_embed/flvServer/MvFlv.php
@@ -0,0 +1,269 @@
 2+<?php
 3+
 4+include_once 'FLV/FLV.php';
 5+
 6+define('MAX_FLV_TS', 16777.216);//it appears tag times restart after 16777.216 seconds;
 7+define('KEY_FRAME_DISTANCE', 2); //max keyframe distance
 8+
 9+//define('META_KFDATA_EXT', '.KfMeta'); //file extension for cached keframe metadata
 10+define('META_DATA_EXT', '.meta'); //basic cached meta
 11+
 12+class MyFLV extends FLV {
 13+
 14+ /**
 15+ * On audio-only files the frame index will use this as minimum gap
 16+ */
 17+ private $audioFrameGap = 3;
 18+
 19+ private $origMetaOfs = 0;
 20+ private $origMetaSize = 0;
 21+ private $origMetaData;
 22+ private $compMetaData;
 23+
 24+ //added segment vars:
 25+ private $fullMeta=null;
 26+ private $mDuration=null;
 27+
 28+ function playTimeReq($start_time_sec, $end_time_sec=null){
 29+ //print "play $start_time_sec to $end_time_sec";
 30+ //@@todo cache byte offsets in memcache if avaliable
 31+ if( $end_time_sec)
 32+ $this->mDuration = $end_time_sec - $start_time_sec;
 33+ //print "SET metaDuration to: " . $this->metaDuration . "\n";
 34+ //print_r($fullMeta);
 35+ $meta =& $this->getKeyFrameMetaData();
 36+ //print_r($meta);
 37+ //die;
 38+ $start_byte=$end_byte=null;
 39+ if($start_time_sec==0 && $end_time_sec==null)$this->play();
 40+ $start_time_ms = $start_time_sec*1000;
 41+ $end_time_ms = ($end_time_sec==null)?null:$end_time_sec*1000;
 42+
 43+ for($i=0;$i<count($meta['times']);$i++){
 44+ //set to the keyframe right before a keyframe of the requested start time
 45+ if($meta['times'][$i]>=$start_time_ms && $start_byte==null){
 46+ $start_byte=(isset($meta['times'][$i-1]))?$meta['filepositions'][$i-1]:$meta['filepositions'][$i];
 47+ if($end_time_ms==null)break;
 48+ }
 49+ //set to the keyframe right after the keyframe of the end time:
 50+ if($end_time_ms!=null){
 51+ if($meta['times'][$i]>=$end_time_ms){
 52+ $end_byte= $meta['filepositions'][$i];
 53+ break;
 54+ }
 55+ }
 56+ }
 57+ //print " bytes: $start_byte $end_byte ";
 58+ //die;
 59+ $this->play($start_byte, $end_byte);
 60+ }
 61+ function computeMetaData()
 62+ {
 63+ ini_set("max_execution_time","0");//computeMetaData can take some time
 64+ $this->compMetaData = array();
 65+ $this->compMetaData['metadatacreator'] = 'FLV Tools';
 66+ $this->compMetaData['metadatadate'] = gmdate('Y-m-d\TH:i:s') . '.000Z';
 67+ $this->compMetaData['keyframes'] = array();
 68+ $this->compMetaData['keyframes']['filepositions'] = array();
 69+ $this->compMetaData['keyframes']['times'] = array();
 70+
 71+ $this->origMetaOfs = 0;
 72+ $this->origMetaSize = 0;
 73+ $this->origMetaData = null;
 74+
 75+ $skipTagTypes = array();
 76+ while ($tag = $this->getTag( $skipTagTypes ))
 77+ {
 78+ // pre-calculate the timestamp as seconds
 79+ $ts = $tag->timestamp/1000;
 80+ if ($tag->timestamp > 0 && $tag->type==FLV_Tag::TYPE_VIDEO ){
 81+ $ts = (MAX_FLV_TS*$this->wrapTimeCount) + $ts;
 82+ if($ts < $this->compMetaData['lasttimestamp']){
 83+ $this->wrapTimeCount++;
 84+ $ts = MAX_FLV_TS + $ts;
 85+ }
 86+ //print "set end time to $ts \n";
 87+ $this->compMetaData['lasttimestamp'] = $ts;
 88+ }
 89+
 90+ switch ($tag->type)
 91+ {
 92+ case FLV_Tag::TYPE_VIDEO :
 93+
 94+ //Optimization, extract the frametype without analyzing the tag body
 95+ if ((ord($tag->body[0]) >> 4) == FLV_Tag_Video::FRAME_KEYFRAME)
 96+ {
 97+ $this->compMetaData['keyframes']['filepositions'][] = $this->getTagOffset();
 98+ $this->compMetaData['keyframes']['times'][] = $ts;
 99+ }
 100+
 101+ if ( !in_array(FLV_TAG::TYPE_VIDEO, $skipTagTypes) )
 102+ {
 103+ $this->compMetaData['width'] = $tag->width;
 104+ $this->compMetaData['height'] = $tag->height;
 105+ $this->compMetaData['videocodecid'] = $tag->codec;
 106+ //Processing one video tag is enough
 107+ array_push( $skipTagTypes, FLV_Tag::TYPE_VIDEO );
 108+ }
 109+ break;
 110+
 111+ case FLV_Tag::TYPE_AUDIO :
 112+
 113+ //Save audio frame positions when there is no video
 114+ if (!$flv->hasVideo && $ts - $oldTs > $this->audioFrameGap)
 115+ {
 116+ $this->compMetaData['keyframes']['filepositions'][] = $this->getTagOffset();
 117+ $this->compMetaData['keyframes']['times'][] = $ts;
 118+ $oldTs = $ts;
 119+ }
 120+
 121+ if ( !in_array( FLV_Tag::TYPE_AUDIO, $skipTagTypes) )
 122+ {
 123+ $this->compMetaData['audiocodecid'] = $tag->codec;
 124+ $this->compMetaData['audiofreqid'] = $tag->frequency;
 125+ $this->compMetaData['audiodepthid'] = $tag->depth;
 126+ $this->compMetaData['audiomodeid'] = $tag->mode;
 127+
 128+ //Processing one audio tag is enough
 129+ array_push( $skipTagTypes, FLV_Tag::TYPE_AUDIO );
 130+ }
 131+
 132+ break;
 133+
 134+ case FLV_Tag::TYPE_DATA :
 135+ if ($tag->name == 'onMetaData')
 136+ {
 137+ $this->origMetaOfs = $this->getTagOffset();
 138+ $this->origMetaSize = $tag->size + self::TAG_HEADER_SIZE;
 139+ $this->origMetaData = $tag->value;
 140+ }
 141+ break;
 142+ }
 143+
 144+ //Does this actually help with memory allocation?
 145+ unset($tag);
 146+ }
 147+
 148+ if (! empty($this->compMetaData['keyframes']['times']))
 149+ $this->compMetaData['lastkeyframetimestamp'] = $this->compMetaData['keyframes']['times'][ count($this->compMetaData['keyframes']['times'])-1 ];
 150+
 151+ $this->compMetaData['duration'] = $this->compMetaData['lasttimestamp'];
 152+
 153+ return $this->compMetaData;
 154+ }
 155+
 156+ function setMetaData( $metadata, $origMetaOfs = 0, $origMetaSize = 0 )
 157+ {
 158+ $this->compMetaData = $metadata;
 159+ $this->origMetaOfs = $origMetaOfs;
 160+ $this->origMetaSize = $origMetaSize;
 161+ }
 162+ /* returns merged metadata*/
 163+ function getMetaData()
 164+ {
 165+ if($this->fullMeta)return $this->fullMeta;
 166+ if(is_file($this->fname . META_DATA_EXT)){
 167+ $this->fullMeta = unserialize(file_get_contents ($this->fname . META_DATA_EXT));
 168+ }else{
 169+ $this->computeMetaData();
 170+ if (! is_array($this->origMetaData)){
 171+ $this->fullMeta = $this->compMetaData;
 172+ }else{
 173+ $this->fullMeta = array_merge( $this->origMetaData, $this->compMetaData );
 174+ }
 175+
 176+ //save fullMeta to file (fix keyfames)
 177+ foreach($this->compMetaData['keyframes']['times'] as $inx=>&$ts){
 178+ $ts = (int)($ts*1000);
 179+ }
 180+ if(!file_put_contents($this->fname . META_DATA_EXT, serialize($this->compMetaData))){
 181+ throw( new FLV_FileException('Unable to write out cached keyframe output') );
 182+ }
 183+ }
 184+ return $this->fullMeta;
 185+ }
 186+ function getKeyFrameMetaData(){
 187+ $meta = & $this->getMetaData();
 188+ return $meta['keyframes'];
 189+ }
 190+ function getSegmentMetaData(){
 191+ //pull base cached metadata
 192+ //update duration & return new array
 193+ $meta = & $this->getMetaData();
 194+ $meta['keyframes']=array();
 195+ //@@todo update all the other metadata to match segment outupt
 196+ return $meta;
 197+ }
 198+
 199+ function play( $from = 0, $play_to=null )
 200+ {
 201+ fseek($this->fp, 0);
 202+
 203+ // get original file header just in case it has any special flag
 204+ echo fread($this->fp, $this->bodyOfs + 4);
 205+
 206+ // output the metadata if available
 207+ $meta = $this->getSegmentMetaData();
 208+ if (! empty($meta))
 209+ {
 210+ //serialize the metadata as an AMF stream
 211+ include_once 'FLV/Util/AMFSerialize.php';
 212+ $amf = new FLV_Util_AMFSerialize();
 213+
 214+ $serMeta = $amf->serialize('onMetaData');
 215+ $serMeta.= $amf->serialize($meta);
 216+
 217+ //Data tag mark
 218+ $out = pack('C', FLV_Tag::TYPE_DATA);
 219+ //Size of the data tag (BUG: limited to 64Kb)
 220+ $out.= pack('Cn', 0, strlen($serMeta));
 221+ //Timestamp
 222+ $out.= pack('N', 0);
 223+ //StreamID
 224+ $out.= pack('Cn', 0, 0);
 225+
 226+ echo $out;
 227+ echo $serMeta;
 228+
 229+ // PrevTagSize for the metadata
 230+ echo pack('N', strlen($serMeta) + strlen($out) );
 231+ }
 232+
 233+ $chunkSize = 4096;
 234+ $skippedOrigMeta = empty($this->origMetaSize);
 235+ //seek to offset point:
 236+ fseek($this->fp, $from);
 237+ while (! feof($this->fp))
 238+ {
 239+ // if the original metadata is pressent and not yet skipped...
 240+ if (! $skippedOrigMeta)
 241+ {
 242+ $pos = ftell($this->fp);
 243+
 244+ // check if we are going to output it in this loop step
 245+ if ( $pos <= $this->origMetaOfs &&
 246+ $pos + $chunkSize > $this->origMetaOfs )
 247+ {
 248+ // output the bytes just before the original metadata tag
 249+ if ($this->origMetaOfs - $pos > 0)
 250+ echo fread($this->fp, $this->origMetaOfs - $pos);
 251+
 252+ // position the file pointer just after the metadata tag
 253+ fseek($this->fp, $this->origMetaOfs + $this->origMetaSize);
 254+
 255+ $skippedOrigMeta = true;
 256+ continue;
 257+ }
 258+ }
 259+ if($play_to!=null){
 260+ if(ftell($this->fp)+$chunkSize > $play_to){
 261+ $read_amount = (ftell($this->fp)+$chunkSize)-$play_to;
 262+ echo fread($this->fp, $read_amount);
 263+ break;
 264+ }
 265+ }
 266+ echo fread($this->fp, $chunkSize);
 267+ }
 268+ }
 269+}
 270+?>
\ No newline at end of file

Status & tagging log