Began parsing Threemedia OTT fragments.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m14s
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m14s
This commit is contained in:
parent
6e5bf2d2db
commit
124bc001aa
90
skyscraper8/ThreemediaOtt/ThreemediaBaseStream.cs
Normal file
90
skyscraper8/ThreemediaOtt/ThreemediaBaseStream.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.ThreemediaOtt
|
||||
{
|
||||
internal abstract class ThreemediaBaseStream : Stream
|
||||
{
|
||||
public override void Flush()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > calculatedLength)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value), value, String.Format("This stream is capped at {0}", calculatedLength));
|
||||
}
|
||||
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
long newPosition;
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
newPosition = offset;
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
newPosition = Position + offset;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
newPosition = Length + offset;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException(String.Format("Unknown seek operation: {0}", origin));
|
||||
}
|
||||
|
||||
if (newPosition < 0 || newPosition > calculatedLength)
|
||||
{
|
||||
throw new IOException("An attempt was made to move the file pointer before the beginning or past the end of the stream.");
|
||||
}
|
||||
|
||||
SeekHook();
|
||||
|
||||
return newPosition;
|
||||
}
|
||||
|
||||
protected abstract void SeekHook();
|
||||
|
||||
private bool lengthSet;
|
||||
private long calculatedLength;
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
if (lengthSet)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
else
|
||||
{
|
||||
calculatedLength = value;
|
||||
lengthSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
public override bool CanSeek => true;
|
||||
public override bool CanWrite => false;
|
||||
public override long Length => calculatedLength;
|
||||
|
||||
protected long _internalPosition;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper8.Ietf.FLUTE;
|
||||
|
||||
namespace skyscraper8.ThreemediaOtt
|
||||
@ -52,5 +53,41 @@ namespace skyscraper8.ThreemediaOtt
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ThreemediaContentFragmentStream CreateStream()
|
||||
{
|
||||
byte[] lastBlock = blocks[blocks.Length - 1];
|
||||
|
||||
MemoryStream lastBlockStream = new MemoryStream(lastBlock, false);
|
||||
lastBlockStream.Position = lastBlockStream.Length - 8;
|
||||
int footerLength = (int)lastBlockStream.ReadUInt32BE();
|
||||
int footerOffset = (int)(lastBlockStream.Length - 8 - footerLength);
|
||||
|
||||
Dictionary<string, string> footer = ExtractFooter(lastBlock, footerLength, footerOffset);
|
||||
|
||||
int[] blockSizes = Array.ConvertAll(blocks, (x) => x.Length);
|
||||
blockSizes[blocks.Length - 1] = footerOffset;
|
||||
|
||||
ThreemediaContentFragmentStream result = new ThreemediaContentFragmentStream(blocks, blockSizes, footer);
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Dictionary<string, string> ExtractFooter(byte[] lastBlock, int footerLength, int footerOffset)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(lastBlock, footerOffset, footerLength, false);
|
||||
StreamReader sr = new StreamReader(ms, Encoding.ASCII);
|
||||
Dictionary<string, string> result = new Dictionary<string, string>();
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string? line = sr.ReadLine();
|
||||
int seperator = line.IndexOf(':');
|
||||
string key = line.Substring(0, seperator);
|
||||
string value = line.Substring(seperator + 1);
|
||||
result.Add(key, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
skyscraper8/ThreemediaOtt/ThreemediaContentFragmentStream.cs
Normal file
58
skyscraper8/ThreemediaOtt/ThreemediaContentFragmentStream.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.ThreemediaOtt
|
||||
{
|
||||
internal class ThreemediaContentFragmentStream : ThreemediaBaseStream
|
||||
{
|
||||
private readonly byte[][] _blocks;
|
||||
private readonly int[] _blockSizes;
|
||||
|
||||
private int _currentBlockIndex;
|
||||
private int _currentBlockPosition;
|
||||
|
||||
public ThreemediaContentFragmentStream(byte[][] blocks, int[] blockSizes, Dictionary<string, string> footer)
|
||||
{
|
||||
_blocks = blocks ?? throw new ArgumentNullException(nameof(blocks));
|
||||
_blockSizes = blockSizes ?? throw new ArgumentNullException(nameof(blockSizes));
|
||||
|
||||
if (_blocks.Length != _blockSizes.Length)
|
||||
{
|
||||
throw new ArgumentException("Blocks and blockSizes arrays must have the same length.");
|
||||
}
|
||||
|
||||
// Calculate total stream length based on the valid payloads
|
||||
SetLength(_blockSizes.Sum(x => (long)x));
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void SeekHook()
|
||||
{
|
||||
long remainingOffset = _internalPosition;
|
||||
_currentBlockIndex = 0;
|
||||
_currentBlockPosition = 0;
|
||||
|
||||
while (_currentBlockIndex < _blocks.Length && remainingOffset > 0)
|
||||
{
|
||||
int blockSize = _blockSizes[_currentBlockIndex];
|
||||
if (remainingOffset >= blockSize)
|
||||
{
|
||||
remainingOffset -= blockSize;
|
||||
_currentBlockIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentBlockPosition = (int)remainingOffset;
|
||||
remainingOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,12 @@ namespace skyscraper8.ThreemediaOtt
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
ThreemediaSessionStream stream = selectedSession.CreateStream();
|
||||
|
||||
FileStream fs = File.OpenWrite("test.bin");
|
||||
stream.CopyTo(fs);
|
||||
fs.Flush(true);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public bool StopProcessingAfterThis()
|
||||
|
||||
@ -55,5 +55,12 @@ namespace skyscraper8.ThreemediaOtt
|
||||
|
||||
fragments = null;
|
||||
}
|
||||
|
||||
public ThreemediaSessionStream CreateStream()
|
||||
{
|
||||
ThreemediaContentFragmentStream[] fragmentStreams = Array.ConvertAll(fragments, (x) => x.CreateStream());
|
||||
ThreemediaSessionStream stream = new ThreemediaSessionStream(fragmentStreams);
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
skyscraper8/ThreemediaOtt/ThreemediaSessionStream.cs
Normal file
26
skyscraper8/ThreemediaOtt/ThreemediaSessionStream.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.ThreemediaOtt
|
||||
{
|
||||
internal class ThreemediaSessionStream : ThreemediaBaseStream
|
||||
{
|
||||
public ThreemediaSessionStream(ThreemediaContentFragmentStream[] fragmentStreams)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void SeekHook()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user