/FlvPropertySheet/FlvTag/FlvTagReader.cs
http://tsanie-shellextension.googlecode.com/ · C# · 166 lines · 148 code · 17 blank · 1 comment · 27 complexity · cdd897ee65d635b8f4ae4382b6df72bd MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.IO;
- using Tsanie.ShellExtension;
- using Tsanie.ShellExtension.Util;
-
- namespace Tsanie.FlvTag {
- public class FlvTagReader {
-
- #region - Fields -
-
- private string _filename;
- private long _length;
- private long _seek;
- private uint _duration;
- private double _rate;
- private ScriptTag _metaTag;
- private List<FlvTag> _tags;
- private int _maxTagSize;
-
- private Predicate<FlvTag> _predicate;
- private Action<long> _maximumGetted;
- private Action<int> _done;
-
- #endregion
-
- #region - Properties -
-
- public Predicate<FlvTag> Predicate { set { _predicate = value; } }
- public Action<long> MaximumGetted { set { _maximumGetted = value; } }
- public Action<int> Done { set { _done = value; } }
- public long Length { get { return _length; } }
- public long Seek { get { return _seek; } }
- public uint Duration { get { return _duration; } }
- public double Rate { get { return _rate; } }
- public List<FlvTag> Tags { get { return _tags; } }
- public string Filename { get { return _filename; } }
- public ScriptTag MetaTag { get { return _metaTag; } }
- public int MaxTagSize { get { return _maxTagSize; } }
-
- #endregion
-
- public FlvTagReader(string filename) {
- _filename = filename;
- _length = 0;
- _seek = 0;
- _duration = 0;
- _rate = 0;
- _metaTag = null;
- _tags = new List<FlvTag>();
- _predicate = (t) => true;
- }
-
- #region - Public Methods -
-
- public Thread StartRead() {
- if (_filename == null)
- return null;
- FileStream fs = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- _length = fs.Length;
- _maximumGetted.SafeRun(_length);
- FLVHeader header = FLVHeader.ReadHeader(fs);
- if (!header.IsFlv)
- return null;
- Thread thread = new Thread(delegate() {
- try {
- fs.Seek(header.Length, SeekOrigin.Begin);
- _tags.Clear();
- FlvTag tag;
- while ((tag = FlvTag.ReadTag(fs)) != null) {
- if (tag is ScriptTag)
- _metaTag = tag as ScriptTag;
- _tags.Add(tag);
- if (_duration < tag.TimeStamp)
- _duration = tag.TimeStamp;
- if (_maxTagSize < tag.DataSize)
- _maxTagSize = tag.DataSize;
- _seek += tag.DataSize;
- if (!_predicate.SafeRun(tag))
- break;
- }
- if (_tags.Count > 1) {
- _length = _length - _tags[1].Offset + 11;
- _rate = (_duration == 0 ? 0 : _length * 8 / _duration);
- }
- #if TRACE
- Common.OutputDebugString("StartRead(void):: read {0} tag(s).", _tags.Count);
- #endif
- } catch (Exception e) {
- Common.OutputDebugString("StartRead(void):: {0} - {1}", e.GetType().FullName, e.Message);
- } finally {
- fs.Close();
- fs = null;
- _done.SafeRun(_tags.Count);
- }
- });
- thread.Name = "thread_ReadFile_" + _filename;
- thread.Start();
- return thread;
- }
- public void Remove(int index) {
- if (index < 0 || index >= _tags.Count)
- return;
- FlvTag tag = _tags[index];
- if (_duration <= tag.TimeStamp)
- RefreshDuration();
- _length -= tag.DataSize + 11;
- _tags.RemoveAt(index);
- }
- public void RefreshDuration() {
- uint max = 0;
- foreach (FlvTag t in _tags)
- if (max < t.TimeStamp)
- max = t.TimeStamp;
- _duration = max;
- _rate = (_duration == 0 ? 0 : _length * 8 / _duration);
- }
-
- #endregion
-
- }
-
- class FLVHeader {
- private byte[] signature;
- private byte version;
- private byte typeflag;
- private int dataoffset;
-
- private FLVHeader() {
- signature = new byte[3];
- version = 0;
- typeflag = 0;
- dataoffset = 0;
- }
- public static FLVHeader ReadHeader(Stream stream) {
- FLVHeader header = new FLVHeader();
- byte[] buffer = new byte[4];
- stream.Read(header.signature, 0, 3);
- stream.Read(buffer, 0, 1);
- header.version = buffer[0];
- stream.Read(buffer, 0, 1);
- header.typeflag = buffer[0];
- try {
- header.dataoffset = (int)stream.ReadUI32();
- } catch { }
- return header;
- }
-
- public bool IsFlv {
- get {
- if (signature == null || signature.Length != 3)
- return false;
- // 'FLV'
- return (signature[0] == 0x46) && (signature[1] == 0x4C) && (signature[2] == 0x56);
- }
- }
- public int Version { get { return version; } }
- public bool HasVideo { get { return (typeflag & 0x1) == 0x1; } }
- public bool HasAudio { get { return (typeflag & 0x4) == 0x4; } }
- public int Length { get { return dataoffset; } }
- }
-
- }