SimpleFlvWriter 一个动态生成flv的类

来源:互联网 发布:淘宝充值平台怎么样 编辑:程序博客网 时间:2024/05/16 10:34
 
/*SimpleFlvWriter.asLee Felarcahttp://www.zeropointnine.com/blog5-2007v0.8Singleton class to create uncompressed FLV files.Does not handle audio. Feel free to extend.Source code licensed under a Creative Commons Attribution 3.0 License.http://creativecommons.org/licenses/by/3.0/Some Rights Reserved.EXAMPLE USAGE:var myWriter:SimpleFlvWriter = SimpleFlvWriter.getInstance();myWriter.createFile(myFile, 320,240, 30, 120);myWriter.saveFrame( myBitmapData1 );myWriter.saveFrame( myBitmapData2 );myWriter.saveFrame( myBitmapData3 ); // etc.myWriter.closeFile();*/package{    import flash.filesystem.File;    import flash.filesystem.FileMode;    import flash.filesystem.FileStream;    import flash.display.BitmapData;    import flash.utils.ByteArray;public class SimpleFlvWriter{static private var _instance:SimpleFlvWriter;private var frameWidth:int;private var frameHeight:int;private var frameRate:Number;private var duration:Number;private var fs:FileStream = new FileStream();private var f:File;private const blockWidth:int = 32;private const blockHeight:int = 32;private var previousTagSize:uint = 0;private var iteration:int = 0;private var bmp:BitmapData;public static function getInstance():SimpleFlvWriter {if(SimpleFlvWriter._instance == null) SimpleFlvWriter._instance = new SimpleFlvWriter(new SingletonEnforcer());return SimpleFlvWriter._instance;}public function SimpleFlvWriter(singletonEnforcer:SingletonEnforcer){}public function createFile(pFile:File, pWidth:int, pHeight:int, pFramesPerSecond:Number, pDurationInSeconds:Number=0):void{/*Parameters:pFile: The file which will be created and written topWidth: Video heightpWidth: Video widthpFramesPerSecond: Determines framerate of created videopDurationInSeconds: Duration of video file to be created. Used for metadata only. Optional.*/frameWidth = pWidth;frameHeight = pHeight;frameRate = pFramesPerSecond;duration = pDurationInSeconds;f = pFile;fs.openAsync(f, FileMode.WRITE);// create headerfs.writeBytes( header() );// create metadata tagfs.writeUnsignedInt( previousTagSize );fs.writeBytes( flvTagOnMetaData() );}public function saveFrame(pBitmapData:BitmapData):void{// bitmap dimensions should of course match parameters passed to createFile()bmp = pBitmapData;fs.writeUnsignedInt( previousTagSize );fs.writeBytes( flvTagVideo() );}public function closeFile():void{fs.close();}private function header():ByteArray{var ba:ByteArray = new ByteArray();ba.writeByte(0x46) // 'F'ba.writeByte(0x4C) // 'L'ba.writeByte(0x56) // 'V'ba.writeByte(0x01) // Version 1ba.writeByte(0x01) // misc flags - video stream onlyba.writeUnsignedInt(0x09) // header lengthreturn ba;}private function flvTagVideo():ByteArray{var tag:ByteArray = new ByteArray();var dat:ByteArray = videoData();var timeStamp:uint = uint(1000/frameRate * iteration++);// tag 'header'tag.writeByte( 0x09 ); // tagType = videowriteUI24(tag, dat.length); // data sizewriteUI24(tag, timeStamp);// timestamp in mstag.writeByte(0);// timestamp extended, not using *** writeUI24(tag, 0);// streamID always 0// videodatatag.writeBytes( dat );previousTagSize = tag.length;return tag;}private function videoData():ByteArray{var v:ByteArray = new ByteArray;// VIDEODATA 'header'v.writeByte(0x13); // frametype (1) + codecid (3)// SCREENVIDEOPACKET 'header'// blockwidth/16-1 (4bits) + imagewidth (12bits)writeUI4_12(v, int(blockWidth/16) - 1,  frameWidth);// blockheight/16-1 (4bits) + imageheight (12bits)writeUI4_12(v, int(blockHeight/16) - 1, frameHeight);// VIDEODATA > SCREENVIDEOPACKET > IMAGEBLOCKS:var yMax:int = int(frameHeight/blockHeight);var yRemainder:int = frameHeight % blockHeight; if (yRemainder > 0) yMax += 1;var xMax:int = int(frameWidth/blockWidth);var xRemainder:int = frameWidth % blockWidth;if (xRemainder > 0) xMax += 1;for (var y1:int = 0; y1 < yMax; y1++){for (var x1:int = 0; x1 < xMax; x1++) {// create blockvar block:ByteArray = new ByteArray();var yLimit:int = blockHeight;if (yRemainder > 0 && y1 + 1 == yMax) yLimit = yRemainder;for (var y2:int = 0; y2 < yLimit; y2++) {var xLimit:int = blockWidth;if (xRemainder > 0 && x1 + 1 == xMax) xLimit = xRemainder;for (var x2:int = 0; x2 < xLimit; x2++) {var px:int = (x1 * blockWidth) + x2;var py:int = frameHeight - ((y1 * blockHeight) + y2); // (flv's save from bottom to top)var p:uint = bmp.getPixel(px, py);block.writeByte( p & 0xff ); // blueblock.writeByte( p >> 8 & 0xff ); // greenblock.writeByte( p >> 16 ); // red}}block.compress();writeUI16(v, block.length); // write block length (UI16)v.writeBytes( block ); // write block}}return v;}private function flvTagOnMetaData():ByteArray{var tag:ByteArray = new ByteArray();var dat:ByteArray = metaData();// tag 'header'tag.writeByte( 18 ); // tagType = script datawriteUI24(tag, dat.length); // data sizewriteUI24(tag, 0);// timestamp should be 0 for onMetaData tagtag.writeByte(0);// timestamp extendedwriteUI24(tag, 0);// streamID always 0// data tagtag.writeBytes( dat );previousTagSize = tag.length;return tag;}private function metaData():ByteArray{// onMetaData info goes in a ScriptDataObject of data type 'ECMA Array'var b:ByteArray = new ByteArray();// ObjectNameType (always 2)b.writeByte(2);// ObjectName (type SCRIPTDATASTRING):writeUI16(b, "onMetaData".length); // StringLengthb.writeUTFBytes( "onMetaData" ); // StringData// ObjectData (type SCRIPTDATAVALUE):b.writeByte(8); // Type (ECMA array = 8)b.writeUnsignedInt(7) // // Elements in array// SCRIPTDATAVARIABLES...if (duration > 0) {writeUI16(b, "duration".length);b.writeUTFBytes("duration");b.writeByte(0); b.writeDouble(duration);}writeUI16(b, "width".length);b.writeUTFBytes("width");b.writeByte(0); b.writeDouble(frameWidth);writeUI16(b, "height".length);b.writeUTFBytes("height");b.writeByte(0); b.writeDouble(frameHeight);writeUI16(b, "framerate".length);b.writeUTFBytes("framerate");b.writeByte(0); b.writeDouble(frameRate);writeUI16(b, "videocodecid".length);b.writeUTFBytes("videocodecid");b.writeByte(0); b.writeDouble(3); // 'Screen Video' = 3writeUI16(b, "canSeekToEnd".length);b.writeUTFBytes("canSeekToEnd");b.writeByte(1); b.writeByte(int(true));var mdc:String = "SimpleFLVWriter.as v0.8 zeropointnine.com";writeUI16(b, "metadatacreator".length);b.writeUTFBytes("metadatacreator");b.writeByte(2); writeUI16(b, mdc.length);b.writeUTFBytes(mdc);// VariableEndMarker1 (type UI24 - always 9)writeUI24(b, 9);return b;}private function writeUI24(stream:*, p:uint):void{var byte1:int = p >> 16;var byte2:int = p >> 8 & 0xff;var byte3:int = p & 0xff;stream.writeByte(byte1);stream.writeByte(byte2);stream.writeByte(byte3);}private function writeUI16(stream:*, p:uint):void{stream.writeByte( p >> 8 )stream.writeByte( p & 0xff );}private function writeUI4_12(stream:*, p1:uint, p2:uint):void{// writes a 4-bit value followed by a 12-bit value in two sequential bytesvar byte1a:int = p1 << 4;var byte1b:int = p2 >> 8;var byte1:int = byte1a + byte1b;var byte2:int = p2 & 0xff;stream.writeByte(byte1);stream.writeByte(byte2);}}}class SingletonEnforcer {}/*FLV structure summary:headerprevioustagsizeflvtag[info]videodata[info]screenvideopacket[info]imageblocksimageblocks...previoustagsizeflvtag...FLV file format:headerlast tag sizeFLVTAG:tagtypedatasizetimestamptimestampextendedstreamiddata [VIDEODATA]:frametypecodecidvideodata [SCREENVIDEOPACKET]:blockwidthub[4]imagewidthub[12]blockheightub[4]imageheightub[12]imageblocks [IMAGEBLOCKS[]]:datasizeub[16] <same as 'ub16', i think>data..last tag sizeFLVTAGetc.*/
原创粉丝点击