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.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using skyscraper5.Skyscraper.IO;
|
||||||
using skyscraper8.Ietf.FLUTE;
|
using skyscraper8.Ietf.FLUTE;
|
||||||
|
|
||||||
namespace skyscraper8.ThreemediaOtt
|
namespace skyscraper8.ThreemediaOtt
|
||||||
@ -52,5 +53,41 @@ namespace skyscraper8.ThreemediaOtt
|
|||||||
|
|
||||||
return true;
|
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;
|
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()
|
public bool StopProcessingAfterThis()
|
||||||
|
|||||||
@ -55,5 +55,12 @@ namespace skyscraper8.ThreemediaOtt
|
|||||||
|
|
||||||
fragments = null;
|
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