源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

c#实现flv解析详解示例

  • 时间:2020-09-02 22:20 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:c#实现flv解析详解示例
先上效果图:
[img]http://files.jb51.net/file_images/article/201401/20140110113032.jpg?201401011365[/img]
 
工具类 在解析的过程中,我们会和byte做各种运算,所以我定义了一个byte工具类ByteUtils:
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace FLVParer.Utils {     class ByteUtils     {         public static uint ByteToUInt(byte[] bs, int length)         {             if (bs == null || bs.Length < length)                 return 0;             uint rtn = 0;             for (int i = 0; i < length; i++)             {                 rtn <<= 8;                 rtn |= bs[i];             }             return rtn;         }         public static double ByteToDouble(byte[] bs)         {             if (bs == null || bs.Length < 8)                 return 0;             byte[] b2 = new byte[8];             for (int i = 0; i < 8; i++)             {                 b2[i] = bs[7 - i];             }             return BitConverter.ToDouble(b2, 0);         }         public static short ReadUI16(Stream src)         {             byte[] bs = new byte[2];             if (src.Read(bs, 0, 2) <= 0)                 return 0;             return (short)((bs[0] << 8) | bs[1]);         }         public static uint ReadUI24(Stream src)         {             byte[] bs = new byte[3];             if (src.Read(bs, 0, 3) <= 0)                 throw new IOException("Stream end.");             return ByteToUInt(bs, 3);         }         public static uint ReadUI32(Stream src)         {             byte[] bs = new byte[4];             if (src.Read(bs, 0, 4) <= 0)                 throw new IOException("Stream end.");             return ByteToUInt(bs, 4);         }         public static string GetTime(uint time)         {             return (time / 60000).ToString() + ":"                 + (time / 1000 % 60).ToString("D2") + "."                 + (time % 1000).ToString("D3");         }     } }
FLV类 FLV类,主要的类,里面包括一个header和许多的tag,也就是一个FLV文件的结构:
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using FLVParer.Utils; namespace FLVParer.Model {     class FLV     {         public Header header { get; private set; }         List<Tag> tags;         public FLV(Stream stream)         {             header = new Header();             header.readHeader(stream);             stream.Seek(header.size, SeekOrigin.Begin);             tags = new List<Tag>();             while (stream.Position < stream.Length-4)             {                 tags.Add(readTag(stream));                            }         }         private Tag readTag(Stream stream)         {             Tag tag = null;             byte[] buf = new byte[4];             stream.Read(buf, 0, 4);             int type = stream.ReadByte();             switch (type)             {                 case 8:                     tag = new AudioTag();                     break;                 case 9:                     tag = new VideoTag();                     break;                 case 18:                     tag = new ScriptTag();                     break;             }             tag.presize = ByteUtils.ByteToUInt(buf, 4);             tag.datasize = ByteUtils.ReadUI24(stream);             tag.timestamp = ByteUtils.ReadUI24(stream);             tag.timestamp_ex = stream.ReadByte();             tag.streamid = ByteUtils.ReadUI24(stream);                        tag.readData(stream);                       return tag;         }     } }
Header类 Header类,保存FLV文件的头信息:
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using FLVParer.Utils; namespace FLVParer.Model {     class Header     {         public String type { get; private set; }         public int version { get; private set; }         public bool hasVideo { get; private set; }         public bool hasAudio { get; private set; }         public uint size { get; private set; }         public void readHeader(Stream stream)         {             byte[] buf = new byte[4];             stream.Read(buf, 0, 3);             type = Encoding.Default.GetString(buf);             stream.Read(buf, 0, 1);             version = buf[0];             stream.Read(buf, 0, 1);             buf[0] &= 0x0f;             if ((buf[0] & 0x01) == 1)             {                 hasVideo = true;             }             if ((buf[0] & 0x04) == 4)             {                 hasAudio = true;             }             stream.Read(buf, 0, 4);             size = ByteUtils.ByteToUInt(buf, 4);         }     } }
Tag类 Tag类是一个抽象类,因为tag的种类有三种,为了统一管理,抽象出Tag类:
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace FLVParer.Model {     enum TagType     {         video,         audio,         Script     }     abstract class Tag     {         public TagType tagType;//tag类型         public uint presize;//前一tag大小         public uint datasize;//数据区大小         public uint timestamp; //时间戳 单位ms         public int timestamp_ex;//时间戳扩展         public uint streamid;//ID         public long offset;//偏移量         public byte[] data;//数据         //对tag进行读取         public abstract void readData(Stream stream);     } }
ScriptTag类 脚本tag类,继承自Tag类,并添加成员变量Values,用于保存脚本信息:
[u]复制代码[/u] 代码如下:
using System.Collections.Generic; using System.Text; using System.IO; using FLVParer.Utils; namespace FLVParer.Model {     class ScriptTag : Tag     {         public List<KeyValuePair<string, object>> Values { get; private set; }         public ScriptTag()         {             tagType = TagType.Script;             Values = new List<KeyValuePair<string, object>>();         }         public override void readData(Stream stream)         {             offset = 0;             Values.Clear();             byte[] bs = new byte[3];             while (offset < this.datasize)             {                 stream.Read(bs, 0, 3);                 if (bs[0] == 0 && bs[1] == 0 && bs[2] == 9)                 {                     offset += 3;                     break;                 }                 stream.Seek(-3, SeekOrigin.Current);                 AddElement("#" + offset, ReadElement(stream));             }         }         private void AddElement(string key, object o)         {             Values.Add(new KeyValuePair<string, object>(key, o));         }         private object ReadElement(Stream src)         {             int type = src.ReadByte();             offset++;             switch (type)             {                 case 0: // Number - 8                     return ReadDouble(src);                 case 1: // Boolean - 1                     return ReadByte(src);                 case 2: // String - 2+n                     return ReadString(src);                 case 3: // Object                     return ReadObject(src);                 case 4: // MovieClip                     return ReadString(src);                 case 5: // Null                     break;                 case 6: // Undefined                     break;                 case 7: // Reference - 2                     return ReadUShort(src);                 case 8: // ECMA array                     return ReadArray(src);                 case 10: // Strict array                     return ReadStrictArray(src);                 case 11: // Date - 8+2                     return ReadDate(src);                 case 12: // Long string - 4+n                     return ReadLongString(src);             }             return null;         }         private object ReadObject(Stream src)         {             byte[] bs = new byte[3];             ScriptObject obj = new ScriptObject();             while (offset < this.datasize)             {                 src.Read(bs, 0, 3);                 if (bs[0] == 0 && bs[1] == 0 && bs[2] == 9)                 {                     offset += 3;                     break;                 }                 src.Seek(-3, SeekOrigin.Current);                 string key = ReadString(src);                 if (key[0] == 0)                     break;                 obj[key] = ReadElement(src);             }             return obj;         }         private double ReadDate(Stream src)         {             double d = ReadDouble(src);             src.Seek(2, SeekOrigin.Current);             offset += 2;             return d;         }         private ScriptObject ReadArray(Stream src)         {             byte[] buffer = new byte[4];             src.Read(buffer, 0, 4);             offset += 4;             uint count = ByteUtils.ByteToUInt(buffer, 4);             ScriptObject array = new ScriptObject();             for (uint i = 0; i < count; i++)             {                 string key = ReadString(src);                 array[key] = ReadElement(src);             }             src.Seek(3, SeekOrigin.Current); // 00 00 09             offset += 3;             return array;         }         private ScriptArray ReadStrictArray(Stream src)         {             byte[] bs = new byte[4];             src.Read(bs, 0, 4);             offset += 4;             ScriptArray array = new ScriptArray();             uint count = ByteUtils.ByteToUInt(bs, 4);             for (uint i = 0; i < count; i++)             {                 array.Add(ReadElement(src));             }             return array;         }         private double ReadDouble(Stream src)         {             byte[] buffer = new byte[8];             src.Read(buffer, 0, 8);             offset += 8;             return ByteUtils.ByteToDouble(buffer);         }         private byte ReadByte(Stream src)         {             offset++;             return (byte)src.ReadByte();         }         private string ReadString(Stream src)         {             byte[] bs = new byte[2];             src.Read(bs, 0, 2);             offset += 2;             int n = (int)ByteUtils.ByteToUInt(bs, 2);             bs = new byte[n];             src.Read(bs, 0, n);             offset += n;             return Encoding.ASCII.GetString(bs);         }         private string ReadLongString(Stream src)         {             byte[] bs = new byte[4];             src.Read(bs, 0, 4);             offset += 4;             int n = (int)ByteUtils.ByteToUInt(bs, 4);             bs = new byte[n];             src.Read(bs, 0, n);             offset += n;             return Encoding.ASCII.GetString(bs);         }         private ushort ReadUShort(Stream src)         {             byte[] buffer = new byte[2];             src.Read(buffer, 0, 2);             offset += 2;             return (ushort)ByteUtils.ByteToUInt(buffer, 2);         }     }     public class ScriptObject     {         public static int indent = 0;         private Dictionary<string, object> values = new Dictionary<string, object>();         public object this[string key]         {             get             {                 object o;                 values.TryGetValue(key, out o);                 return o;             }             set             {                 if (!values.ContainsKey(key))                 {                     values.Add(key, value);                 }             }         }         public override string ToString()         {             string str = "{\r\n";             ScriptObject.indent += 2;             foreach (KeyValuePair<string, object> kv in values)             {                 str += new string(' ', ScriptObject.indent)                           + kv.Key + ": " + kv.Value + "\r\n";             }             ScriptObject.indent -= 2;             //if (str.Length > 1)             //    str = str.Substring(0, str.Length - 1);             str += "}";             return str;         }     }     public class ScriptArray     {         private List<object> values = new List<object>();         public object this[int index]         {             get             {                 if (index >= 0 && index < values.Count)                     return values[index];                 return null;             }         }         public void Add(object o)         {             values.Add(o);         }         public override string ToString()         {             string str = "[";             int n = 0;             foreach (object o in values)             {                 if (n % 10 == 0)                     str += "\r\n";                 n++;                 str += o + ",";             }             if (str.Length > 1)                 str = str.Substring(0, str.Length - 1);             str += "\r\n]";             return str;         }     } }
VideoTag类 视频tag类:
[u]复制代码[/u] 代码如下:
using System.IO; namespace FLVParer.Model {     class VideoTag : Tag     {         public int frameType;//帧类型         public int encodeID;//编码ID         public VideoTag()         {             tagType = TagType.video;         }         public override void readData(Stream stream)         {             int info = stream.ReadByte();             frameType = info >> 4;             encodeID = info & 0x0f;             data = new byte[datasize - 1];             stream.Read(data, 0, (int)datasize - 1);         }     } }
AudioTag 类 音频tag类:
[u]复制代码[/u] 代码如下:
using System.IO; namespace FLVParer.Model {     class AudioTag : Tag     {         public int formate;//音频格式         public int rate;//采样率         public int size;//采样的长度         public int type;//音频类型         public AudioTag()         {             tagType = TagType.audio;         }         public override void readData(Stream stream)         {             int info = stream.ReadByte();             formate = info >> 4;             rate = (info & 0x0c) >> 2;             size = (info & 0x02) >> 1;             type = info & 0x01;             data = new byte[datasize - 1];             stream.Read(data, 0, (int)datasize - 1);         }     } }
使用方法 用法很简单,new出来的时候把FLV文件的stream对象传进去就行了,比如我这样的:
[u]复制代码[/u] 代码如下:
FLV flv = null; using (FileStream fs = new FileStream("t31_stract.flv", FileMode.Open, FileAccess.Read)) {     flv = new FLV(fs); }
之后就可以使用flv对象来分析当前flv的信息了。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部