亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

c#實現flv解析詳解示例

2020-01-24 02:55:56
字體:
來源:轉載
供稿:網友

先上效果圖:

 
工具類

在解析的過程中,我們會和byte做各種運算,所以我定義了一個byte工具類ByteUtils:

復制代碼 代碼如下:

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文件的結構:

復制代碼 代碼如下:

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文件的頭信息:

復制代碼 代碼如下:

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類:

復制代碼 代碼如下:

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,用于保存腳本信息:

復制代碼 代碼如下:

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類:

復制代碼 代碼如下:

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類:

復制代碼 代碼如下:

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對象傳進去就行了,比如我這樣的:

復制代碼 代碼如下:

FLV flv = null;
using (FileStream fs = new FileStream("t31_stract.flv", FileMode.Open, FileAccess.Read))
{
    flv = new FLV(fs);
}

之后就可以使用flv對象來分析當前flv的信息了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情亚洲国产| 亚洲精品一区二区三区婷婷月| 色噜噜狠狠狠综合曰曰曰| 精品国产一区二区三区久久| 国模精品视频一区二区| 欧美日韩视频在线| 亚洲精品国产综合区久久久久久久| 国产精品天天狠天天看| 秋霞av国产精品一区| 精品国产鲁一鲁一区二区张丽| 日韩成人av在线| 欧美精品电影免费在线观看| 欧美人与性动交a欧美精品| 国产一区二区日韩| 亚洲综合日韩在线| 欧美日韩色婷婷| 欧美日韩在线免费观看| 青青精品视频播放| 欧美视频国产精品| 国产精品夜色7777狼人| 26uuu亚洲伊人春色| 亚洲天堂影视av| 57pao国产精品一区| 精品国产区一区二区三区在线观看| 成人中文字幕+乱码+中文字幕| 久久国产精品久久国产精品| 日韩精品在线影院| 68精品国产免费久久久久久婷婷| 日韩av色在线| 欧美午夜电影在线| 欧美国产在线电影| 日韩大片在线观看视频| 国产va免费精品高清在线| 欧美电影院免费观看| 夜夜狂射影院欧美极品| 亚洲激情成人网| 亚洲精品国产综合区久久久久久久| 日韩亚洲成人av在线| 中文字幕亚洲图片| 亚洲成人av片在线观看| 国产日韩欧美夫妻视频在线观看| 成人久久一区二区三区| 8x拔播拔播x8国产精品| 国内精品400部情侣激情| 欧美与欧洲交xxxx免费观看| 欧美激情奇米色| 98精品在线视频| 久久久综合av| www.99久久热国产日韩欧美.com| 91精品中文在线| 这里只有精品久久| 国产精品国产亚洲伊人久久| 中日韩美女免费视频网址在线观看| 97在线视频免费看| 色婷婷久久一区二区| 高清一区二区三区日本久| 中文国产成人精品久久一| 精品久久久久久久久国产字幕| 国产视频福利一区| 岛国视频午夜一区免费在线观看| 在线观看亚洲区| 精品av在线播放| 国产精品18久久久久久首页狼| 久久久精品一区二区| 国产欧美一区二区三区久久人妖| 国产香蕉精品视频一区二区三区| 日韩精品在线看| 亚洲激情小视频| 亚洲第一综合天堂另类专| 久久精品国产精品| 91久久精品美女高潮| 国内成人精品一区| 日韩av免费在线观看| 伊人久久久久久久久久| 日韩精品亚洲视频| 日韩中文理论片| 日韩精品在线免费观看| 亚洲色图18p| 国产深夜精品福利| 欧美日韩国产黄| 97色在线视频| 亚洲a成v人在线观看| 国产午夜精品全部视频在线播放| 亚洲人成自拍网站| 亚洲精品视频久久| 狠狠躁夜夜躁久久躁别揉| 最近2019中文免费高清视频观看www99| xxxx欧美18另类的高清| 欧美成人三级视频网站| 91免费版网站入口| 日韩精品中文字| xvideos国产精品| 欧日韩不卡在线视频| 亚洲第一精品福利| 成人h片在线播放免费网站| 国产精品1区2区在线观看| 国产综合久久久久| 日韩电影在线观看永久视频免费网站| 69影院欧美专区视频| 久久久久久久久久久久久久久久久久av| 亚洲欧美日韩精品久久| 日韩中文字幕在线| 97在线视频免费| 免费91麻豆精品国产自产在线观看| 91国产美女在线观看| 久久视频在线免费观看| 成人性生交大片免费看视频直播| 2019亚洲日韩新视频| 精品一区二区三区四区在线| 亚洲网站在线观看| 国产精品久久久久久亚洲影视| 色综合久久中文字幕综合网小说| 久久免费视频网| 中文字幕欧美视频在线| 欧美激情视频三区| 91久久久亚洲精品| 亚洲成人999| 蜜臀久久99精品久久久无需会员| 欧美夫妻性视频| 久久91亚洲人成电影网站| 久久伊人免费视频| 欧美最猛性xxxxx(亚洲精品)| 国产精品久久久久aaaa九色| 亚洲国产成人一区| 亚洲图片欧美日产| 欧美午夜女人视频在线| 在线性视频日韩欧美| 久久视频在线直播| 日韩av不卡电影| 91亚洲精品久久久久久久久久久久| 国产一区二区三区日韩欧美| 欧美性猛交丰臀xxxxx网站| 美女性感视频久久久| 色妞色视频一区二区三区四区| 欧美激情第1页| 久久视频免费在线播放| xvideos国产精品| 日韩av观看网址| 欧美xxxx18国产| 日韩国产高清污视频在线观看| 国产精品日韩精品| 中文字幕亚洲色图| 久久伊人精品一区二区三区| 中文字幕在线精品| 欧美激情亚洲国产| 5278欧美一区二区三区| 久久视频精品在线| 久久久久久国产精品三级玉女聊斋| 国产aⅴ夜夜欢一区二区三区| 欧美亚洲在线播放| 伊人伊成久久人综合网站| 51色欧美片视频在线观看| 日韩电影中文字幕在线| 国产精品久久久久久久天堂| 欧美极品少妇与黑人| 国产精品久在线观看| 色婷婷久久av| 久久久久久久影视| 国产精品美女免费视频| 亚洲性夜色噜噜噜7777| 成人97在线观看视频| 中文精品99久久国产香蕉| 亚洲四色影视在线观看| 亚洲片av在线|