mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
BluRay playlist (mpls) files support
This commit is contained in:
@@ -8,6 +8,12 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
[AudioDecoderClass("cuetools", "m2ts", 2)]
|
[AudioDecoderClass("cuetools", "m2ts", 2)]
|
||||||
public class BDLPCMReader : IAudioSource
|
public class BDLPCMReader : IAudioSource
|
||||||
{
|
{
|
||||||
|
public unsafe BDLPCMReader(string path, Stream IO, ushort pid)
|
||||||
|
: this(path, IO)
|
||||||
|
{
|
||||||
|
settings.Pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe BDLPCMReader(string path, Stream IO)
|
public unsafe BDLPCMReader(string path, Stream IO)
|
||||||
{
|
{
|
||||||
_path = path;
|
_path = path;
|
||||||
@@ -83,11 +89,29 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
get {
|
get {
|
||||||
if (chosenStream == null)
|
if (chosenStream == null)
|
||||||
{
|
{
|
||||||
if (settings.Stream != null)
|
if (settings.Pid.HasValue)
|
||||||
|
{
|
||||||
|
if (streams.ContainsKey(settings.Pid.Value))
|
||||||
|
{
|
||||||
|
var s = streams[settings.Pid.Value];
|
||||||
|
if (s.is_opened)
|
||||||
|
{
|
||||||
|
chosenStream = s;
|
||||||
|
if (chosenStream.pcm == null)
|
||||||
|
{
|
||||||
|
demux_ts_packets(null, 0);
|
||||||
|
}
|
||||||
|
return chosenStream.pcm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception("Pid can be " +
|
||||||
|
string.Join(", ", (new List<ushort>(streams.Keys)).FindAll(pid => streams[pid].is_opened).ConvertAll(pid => pid.ToString()).ToArray()));
|
||||||
|
}
|
||||||
|
if (settings.Stream.HasValue)
|
||||||
{
|
{
|
||||||
foreach (var s in streams)
|
foreach (var s in streams)
|
||||||
{
|
{
|
||||||
if (s.Value.is_opened && s.Value.streamId.ToString() == settings.Stream)
|
if (s.Value.is_opened && s.Value.streamId == settings.Stream.Value)
|
||||||
{
|
{
|
||||||
chosenStream = s.Value;
|
chosenStream = s.Value;
|
||||||
if (chosenStream.pcm == null)
|
if (chosenStream.pcm == null)
|
||||||
@@ -97,9 +121,11 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
return chosenStream.pcm;
|
return chosenStream.pcm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw new Exception("Stream can be " +
|
||||||
|
string.Join(", ", (new List<TsStream>(streams.Values)).FindAll(s => s.is_opened).ConvertAll(s => s.streamId.ToString()).ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("multiple streams present, please specify");
|
throw new Exception("multiple streams present, please specify Pid or Stream");
|
||||||
}
|
}
|
||||||
return chosenStream.pcm;
|
return chosenStream.pcm;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
public string Stream { get; set; }
|
public int? Stream { get; set; }
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public ushort? Pid { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BDLPCMReader.cs" />
|
<Compile Include="BDLPCMReader.cs" />
|
||||||
<Compile Include="BDLPCMReaderSettings.cs" />
|
<Compile Include="BDLPCMReaderSettings.cs" />
|
||||||
|
<Compile Include="MPLSReader.cs" />
|
||||||
<Compile Include="FrameReader.cs" />
|
<Compile Include="FrameReader.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="TsStream.cs" />
|
<Compile Include="TsStream.cs" />
|
||||||
|
|||||||
@@ -18,6 +18,13 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
end_m = ptr + len;
|
end_m = ptr + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal FrameReader(FrameReader src, long len)
|
||||||
|
{
|
||||||
|
if (src.ptr_m + len > src.end_m) throw new IndexOutOfRangeException();
|
||||||
|
ptr_m = src.ptr_m;
|
||||||
|
end_m = src.ptr_m + len;
|
||||||
|
}
|
||||||
|
|
||||||
internal void read_bytes(byte* dst, int len)
|
internal void read_bytes(byte* dst, int len)
|
||||||
{
|
{
|
||||||
if (ptr_m + len > end_m) throw new IndexOutOfRangeException();
|
if (ptr_m + len > end_m) throw new IndexOutOfRangeException();
|
||||||
@@ -25,6 +32,14 @@ namespace CUETools.Codecs.BDLPCM
|
|||||||
ptr_m += len;
|
ptr_m += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal byte[] read_bytes(int len)
|
||||||
|
{
|
||||||
|
var res = new byte[len];
|
||||||
|
fixed (byte* ptr = &res[0])
|
||||||
|
read_bytes(ptr, len);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
internal byte read_byte()
|
internal byte read_byte()
|
||||||
{
|
{
|
||||||
if (ptr_m + 1 > end_m) throw new IndexOutOfRangeException();
|
if (ptr_m + 1 > end_m) throw new IndexOutOfRangeException();
|
||||||
|
|||||||
461
CUETools.Codecs.BDLPCM/MPLSReader.cs
Normal file
461
CUETools.Codecs.BDLPCM/MPLSReader.cs
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace CUETools.Codecs.BDLPCM
|
||||||
|
{
|
||||||
|
[AudioDecoderClass("cuetools", "mpls", 2)]
|
||||||
|
public class MPLSReader : IAudioSource
|
||||||
|
{
|
||||||
|
public unsafe MPLSReader(string path, Stream IO)
|
||||||
|
{
|
||||||
|
settings = new BDLPCMReaderSettings();
|
||||||
|
_path = path;
|
||||||
|
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);
|
||||||
|
int length = (int)_IO.Length;
|
||||||
|
contents = new byte[length];
|
||||||
|
if (_IO.Read(contents, 0, length) != length) throw new Exception("");
|
||||||
|
fixed (byte* ptr = &contents[0])
|
||||||
|
{
|
||||||
|
FrameReader fr = new FrameReader(ptr, length);
|
||||||
|
hdr_m = parseHeader(fr);
|
||||||
|
fr = new FrameReader(ptr + hdr_m.list_pos, length - hdr_m.list_pos);
|
||||||
|
parsePlaylist(fr);
|
||||||
|
fr = new FrameReader(ptr + hdr_m.mark_pos, length - hdr_m.mark_pos);
|
||||||
|
parsePlaylistMarks(fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void openEntries()
|
||||||
|
{
|
||||||
|
readers = new List<BDLPCMReader>();
|
||||||
|
var pids = new List<ushort>();
|
||||||
|
foreach (var item in hdr_m.play_item)
|
||||||
|
foreach (var audio in item.audio)
|
||||||
|
{
|
||||||
|
if (audio.coding_type != 0x80 /* LPCM */) continue;
|
||||||
|
pids.Add(audio.pid);
|
||||||
|
}
|
||||||
|
ushort chosenPid;
|
||||||
|
if (settings.Pid.HasValue)
|
||||||
|
{
|
||||||
|
if (!pids.Contains(settings.Pid.Value))
|
||||||
|
throw new Exception("Pid can be " +
|
||||||
|
string.Join(", ", pids.ConvertAll(pid => pid.ToString()).ToArray()));
|
||||||
|
chosenPid = settings.Pid.Value;
|
||||||
|
}
|
||||||
|
else if (settings.Stream.HasValue)
|
||||||
|
{
|
||||||
|
if (settings.Stream.Value < 0 || settings.Stream.Value >= pids.Count)
|
||||||
|
throw new Exception("Stream can be 0.." + (pids.Count - 1).ToString());
|
||||||
|
chosenPid = pids[settings.Stream.Value];
|
||||||
|
}
|
||||||
|
else throw new Exception("multiple streams present, please specify Pid or Stream");
|
||||||
|
foreach (var item in hdr_m.play_item)
|
||||||
|
foreach (var audio in item.audio)
|
||||||
|
{
|
||||||
|
if (audio.coding_type != 0x80 /* LPCM */) continue;
|
||||||
|
if (audio.pid == chosenPid)
|
||||||
|
{
|
||||||
|
var parent = Directory.GetParent(System.IO.Path.GetDirectoryName(_path));
|
||||||
|
var m2ts = System.IO.Path.Combine(
|
||||||
|
System.IO.Path.Combine(parent.FullName, "STREAM"),
|
||||||
|
item.clip_id + ".m2ts");
|
||||||
|
var entry = new BDLPCMReader(m2ts, null, chosenPid);
|
||||||
|
readers.Add(entry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentReader = readers[0];
|
||||||
|
pcm = currentReader.PCM;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPLSHeader parseHeader(FrameReader fr)
|
||||||
|
{
|
||||||
|
var hdr = new MPLSHeader();
|
||||||
|
hdr.play_item = new List<MPLSPlaylistItem>();
|
||||||
|
hdr.play_mark = new List<MPLSPlaylistMark>();
|
||||||
|
long length = fr.Length;
|
||||||
|
hdr.type_indicator = fr.read_uint();
|
||||||
|
hdr.type_indicator2 = fr.read_uint();
|
||||||
|
hdr.list_pos = fr.read_uint();
|
||||||
|
hdr.mark_pos = fr.read_uint();
|
||||||
|
hdr.ext_pos = fr.read_uint();
|
||||||
|
if (hdr.type_indicator != 0x4d504c53 /*MPLS*/) throw new NotSupportedException();
|
||||||
|
if (hdr.type_indicator2 != 0x30313030 && hdr.type_indicator2 != 0x30323030) throw new NotSupportedException();
|
||||||
|
if (hdr.list_pos > length || hdr.mark_pos > length || hdr.ext_pos > length) throw new NotSupportedException();
|
||||||
|
return hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void parsePlaylist(FrameReader parentFr)
|
||||||
|
{
|
||||||
|
uint len = parentFr.read_uint();
|
||||||
|
FrameReader fr = new FrameReader(parentFr, len);
|
||||||
|
parentFr.skip(len);
|
||||||
|
ushort reserved = fr.read_ushort();
|
||||||
|
hdr_m.list_count = fr.read_ushort();
|
||||||
|
hdr_m.sub_count = fr.read_ushort();
|
||||||
|
for (int i = 0; i < hdr_m.list_count; i++)
|
||||||
|
hdr_m.play_item.Add(parsePlaylistItem(fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void parsePlaylistMarks(FrameReader parentFr)
|
||||||
|
{
|
||||||
|
uint len = parentFr.read_uint();
|
||||||
|
FrameReader fr = new FrameReader(parentFr, len);
|
||||||
|
parentFr.skip(len);
|
||||||
|
hdr_m.mark_count = fr.read_ushort();
|
||||||
|
for (int ii = 0; ii < hdr_m.mark_count; ii++)
|
||||||
|
hdr_m.play_mark.Add(parsePlaylistMark(fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
MPLSPlaylistItem parsePlaylistItem(FrameReader parentFr)
|
||||||
|
{
|
||||||
|
var item = new MPLSPlaylistItem();
|
||||||
|
item.video = new List<MPLSStream>();
|
||||||
|
item.audio = new List<MPLSStream>();
|
||||||
|
item.pg = new List<MPLSStream>();
|
||||||
|
|
||||||
|
// PlayItem Length
|
||||||
|
ushort len = parentFr.read_ushort();
|
||||||
|
FrameReader fr = new FrameReader(parentFr, len);
|
||||||
|
parentFr.skip(len);
|
||||||
|
|
||||||
|
// Primary Clip identifer
|
||||||
|
var clip_id = fr.read_bytes(5);
|
||||||
|
item.clip_id = Encoding.UTF8.GetString(clip_id, 0, clip_id.Length);
|
||||||
|
|
||||||
|
// skip the redundant "M2TS" CodecIdentifier
|
||||||
|
uint codecId = fr.read_uint();
|
||||||
|
if (codecId != 0x4D325453) throw new NotSupportedException("Incorrect CodecIdentifier");
|
||||||
|
|
||||||
|
ushort flags = fr.read_ushort();
|
||||||
|
bool is_multi_angle = ((flags >> 4) & 1) != 0;
|
||||||
|
item.connection_condition = (byte)(flags & 15);
|
||||||
|
if (item.connection_condition != 0x01 &&
|
||||||
|
item.connection_condition != 0x05 &&
|
||||||
|
item.connection_condition != 0x06)
|
||||||
|
throw new NotSupportedException("Unexpected connection condition");
|
||||||
|
|
||||||
|
item.stc_id = fr.read_byte();
|
||||||
|
item.in_time = fr.read_uint();
|
||||||
|
item.out_time = fr.read_uint();
|
||||||
|
|
||||||
|
// Skip UO_mask_table, random_access_flag, reserved, still_mode
|
||||||
|
// and still_time
|
||||||
|
fr.skip(12);
|
||||||
|
|
||||||
|
if (is_multi_angle)
|
||||||
|
{
|
||||||
|
byte num_angles = fr.read_byte();
|
||||||
|
// skip reserved, is_different_audio, is_seamless_angle_change
|
||||||
|
fr.skip(1);
|
||||||
|
for (int ii = 1; ii < num_angles; ii++)
|
||||||
|
{
|
||||||
|
// Drop clip_id, clip_codec_id, stc_id
|
||||||
|
fr.skip(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip STN len
|
||||||
|
fr.skip(2);
|
||||||
|
|
||||||
|
// Skip 2 reserved bytes
|
||||||
|
fr.skip(2);
|
||||||
|
|
||||||
|
item.num_video = fr.read_byte();
|
||||||
|
item.num_audio = fr.read_byte();
|
||||||
|
item.num_pg = fr.read_byte();
|
||||||
|
item.num_ig = fr.read_byte();
|
||||||
|
item.num_secondary_audio = fr.read_byte();
|
||||||
|
item.num_secondary_video = fr.read_byte();
|
||||||
|
item.num_pip_pg = fr.read_byte();
|
||||||
|
|
||||||
|
// 5 reserve bytes
|
||||||
|
fr.skip(5);
|
||||||
|
|
||||||
|
for (int ii = 0; ii < item.num_video; ii++)
|
||||||
|
item.video.Add(parseStream(fr));
|
||||||
|
for (int ii = 0; ii < item.num_audio; ii++)
|
||||||
|
item.audio.Add(parseStream(fr));
|
||||||
|
for ( int ii = 0; ii < item.num_pg; ii++)
|
||||||
|
item.pg.Add(parseStream(fr));
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPLSStream parseStream(FrameReader parentFr)
|
||||||
|
{
|
||||||
|
MPLSStream s = new MPLSStream();
|
||||||
|
|
||||||
|
byte len = parentFr.read_byte();
|
||||||
|
FrameReader fr = new FrameReader(parentFr, len);
|
||||||
|
parentFr.skip(len);
|
||||||
|
|
||||||
|
s.stream_type = fr.read_byte();
|
||||||
|
switch (s.stream_type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
s.pid = fr.read_ushort();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
s.subpath_id = fr.read_byte();
|
||||||
|
s.subclip_id = fr.read_byte();
|
||||||
|
s.pid = fr.read_ushort();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
s.subpath_id = fr.read_byte();
|
||||||
|
s.pid = fr.read_ushort();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("unrecognized stream type");
|
||||||
|
};
|
||||||
|
|
||||||
|
len = parentFr.read_byte();
|
||||||
|
fr = new FrameReader(parentFr, len);
|
||||||
|
parentFr.skip(len);
|
||||||
|
|
||||||
|
s.coding_type = fr.read_byte();
|
||||||
|
//value_map_t codec_map[] = {
|
||||||
|
// {0x01, "MPEG-1 Video"},
|
||||||
|
// {0x02, "MPEG-2 Video"},
|
||||||
|
// {0x03, "MPEG-1 Audio"},
|
||||||
|
// {0x04, "MPEG-2 Audio"},
|
||||||
|
// {0x80, "LPCM"},
|
||||||
|
// {0x81, "AC-3"},
|
||||||
|
// {0x82, "DTS"},
|
||||||
|
// {0x83, "TrueHD"},
|
||||||
|
// {0x84, "AC-3 Plus"},
|
||||||
|
// {0x85, "DTS-HD"},
|
||||||
|
// {0x86, "DTS-HD Master"},
|
||||||
|
// {0xea, "VC-1"},
|
||||||
|
// {0x1b, "H.264"},
|
||||||
|
// {0x90, "Presentation Graphics"},
|
||||||
|
// {0x91, "Interactive Graphics"},
|
||||||
|
// {0x92, "Text Subtitle"},
|
||||||
|
// {0, NULL}
|
||||||
|
//};
|
||||||
|
if (s.coding_type == 0x01
|
||||||
|
|| s.coding_type == 0x02
|
||||||
|
|| s.coding_type == 0xea
|
||||||
|
|| s.coding_type == 0x1b)
|
||||||
|
{
|
||||||
|
byte fmt = fr.read_byte();
|
||||||
|
s.format = (byte)(fmt >> 4);
|
||||||
|
s.rate = (byte)(fmt & 15);
|
||||||
|
}
|
||||||
|
else if (s.coding_type == 0x03
|
||||||
|
|| s.coding_type == 0x04
|
||||||
|
|| s.coding_type == 0x80
|
||||||
|
|| s.coding_type == 0x81
|
||||||
|
|| s.coding_type == 0x82
|
||||||
|
|| s.coding_type == 0x83
|
||||||
|
|| s.coding_type == 0x84
|
||||||
|
|| s.coding_type == 0x85
|
||||||
|
|| s.coding_type == 0x86)
|
||||||
|
{
|
||||||
|
// Audio
|
||||||
|
//value_map_t audio_format_map[] = {
|
||||||
|
// {0, "Reserved1"},
|
||||||
|
// {1, "Mono"},
|
||||||
|
// {2, "Reserved2"},
|
||||||
|
// {3, "Stereo"},
|
||||||
|
// {4, "Reserved3"},
|
||||||
|
// {5, "Reserved4"},
|
||||||
|
// {6, "Multi Channel"},
|
||||||
|
// {12, "Combo"},
|
||||||
|
// {0, NULL}
|
||||||
|
//};
|
||||||
|
//value_map_t audio_rate_map[] = {
|
||||||
|
// {0, "Reserved1"},
|
||||||
|
// {1, "48 Khz"},
|
||||||
|
// {2, "Reserved2"},
|
||||||
|
// {3, "Reserved3"},
|
||||||
|
// {4, "96 Khz"},
|
||||||
|
// {5, "192 Khz"},
|
||||||
|
// {12, "48/192 Khz"},
|
||||||
|
// {14, "48/96 Khz"},
|
||||||
|
// {0, NULL}
|
||||||
|
//};
|
||||||
|
byte fmt = fr.read_byte();
|
||||||
|
s.format = (byte)(fmt >> 4);
|
||||||
|
s.rate = (byte)(fmt & 15);
|
||||||
|
s.lang = fr.read_bytes(3);
|
||||||
|
}
|
||||||
|
else if (s.coding_type == 0x90
|
||||||
|
|| s.coding_type == 0x91)
|
||||||
|
{
|
||||||
|
s.lang = fr.read_bytes(3);
|
||||||
|
}
|
||||||
|
else if (s.coding_type == 0x92)
|
||||||
|
{
|
||||||
|
s.char_code = fr.read_byte();
|
||||||
|
s.lang = fr.read_bytes(3);
|
||||||
|
}
|
||||||
|
else throw new Exception("unrecognized stream type");
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPLSPlaylistMark parsePlaylistMark(FrameReader fr)
|
||||||
|
{
|
||||||
|
var mark = new MPLSPlaylistMark();
|
||||||
|
mark.mark_id = fr.read_byte();
|
||||||
|
mark.mark_type = fr.read_byte();
|
||||||
|
mark.play_item_ref = fr.read_ushort();
|
||||||
|
mark.time = fr.read_uint();
|
||||||
|
mark.entry_es_pid = fr.read_ushort();
|
||||||
|
mark.duration = fr.read_uint();
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioDecoderSettings Settings { get { return settings; } }
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
foreach (var rdr in readers)
|
||||||
|
{
|
||||||
|
rdr.Close();
|
||||||
|
}
|
||||||
|
readers = null;
|
||||||
|
currentReader = null;
|
||||||
|
_IO = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Remaining
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
long res = 0;
|
||||||
|
foreach (var rdr in readers)
|
||||||
|
{
|
||||||
|
res += rdr.Position;
|
||||||
|
if (rdr == currentReader) break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe AudioPCMConfig PCM
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
if (readers == null) openEntries();
|
||||||
|
return pcm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get { return _path; } }
|
||||||
|
|
||||||
|
public unsafe int Read(AudioBuffer buff, int maxLength)
|
||||||
|
{
|
||||||
|
if (readers == null) openEntries();
|
||||||
|
int res = currentReader.Read(buff, maxLength);
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
bool nextOne = false;
|
||||||
|
foreach (var rdr in readers)
|
||||||
|
{
|
||||||
|
if (nextOne)
|
||||||
|
{
|
||||||
|
currentReader = rdr;
|
||||||
|
return currentReader.Read(buff, maxLength);
|
||||||
|
}
|
||||||
|
nextOne = (rdr == currentReader);
|
||||||
|
}
|
||||||
|
currentReader = null;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
string _path;
|
||||||
|
Stream _IO;
|
||||||
|
byte[] contents;
|
||||||
|
|
||||||
|
AudioPCMConfig pcm;
|
||||||
|
List<BDLPCMReader> readers;
|
||||||
|
BDLPCMReader currentReader;
|
||||||
|
MPLSHeader hdr_m;
|
||||||
|
BDLPCMReaderSettings settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct MPLSPlaylistMark
|
||||||
|
{
|
||||||
|
public byte mark_id;
|
||||||
|
public byte mark_type;
|
||||||
|
public ushort play_item_ref;
|
||||||
|
public uint time;
|
||||||
|
public ushort entry_es_pid;
|
||||||
|
public uint duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct MPLSStream
|
||||||
|
{
|
||||||
|
public byte stream_type;
|
||||||
|
public byte coding_type;
|
||||||
|
public ushort pid;
|
||||||
|
public byte subpath_id;
|
||||||
|
public byte subclip_id;
|
||||||
|
public byte format;
|
||||||
|
public byte rate;
|
||||||
|
public byte char_code;
|
||||||
|
public byte[] lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct MPLSPlaylistItem
|
||||||
|
{
|
||||||
|
public string clip_id;
|
||||||
|
public byte connection_condition;
|
||||||
|
public byte stc_id;
|
||||||
|
public uint in_time;
|
||||||
|
public uint out_time;
|
||||||
|
|
||||||
|
public byte num_video;
|
||||||
|
public byte num_audio;
|
||||||
|
public byte num_pg;
|
||||||
|
public byte num_ig;
|
||||||
|
public byte num_secondary_audio;
|
||||||
|
public byte num_secondary_video;
|
||||||
|
public byte num_pip_pg;
|
||||||
|
public List<MPLSStream> video;
|
||||||
|
public List<MPLSStream> audio;
|
||||||
|
public List<MPLSStream> pg;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct MPLSHeader
|
||||||
|
{
|
||||||
|
public uint type_indicator;
|
||||||
|
public uint type_indicator2;
|
||||||
|
public uint list_pos;
|
||||||
|
public uint mark_pos;
|
||||||
|
public uint ext_pos;
|
||||||
|
|
||||||
|
public ushort list_count;
|
||||||
|
public ushort sub_count;
|
||||||
|
public ushort mark_count;
|
||||||
|
|
||||||
|
public List<MPLSPlaylistItem> play_item;
|
||||||
|
public List<MPLSPlaylistMark> play_mark;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,6 +73,7 @@ namespace CUETools.Codecs
|
|||||||
formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("ape", true), null, decoders.GetDefault("ape", true)));
|
formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("ape", true), null, decoders.GetDefault("ape", true)));
|
||||||
formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, true, encoders.GetDefault("tta", true), null, decoders.GetDefault("tta", true)));
|
formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, true, encoders.GetDefault("tta", true), null, decoders.GetDefault("tta", true)));
|
||||||
formats.Add("m2ts", new CUEToolsFormat("m2ts", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("m2ts", true)));
|
formats.Add("m2ts", new CUEToolsFormat("m2ts", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("m2ts", true)));
|
||||||
|
formats.Add("mpls", new CUEToolsFormat("mpls", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("mpls", true)));
|
||||||
formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, false, true, encoders.GetDefault("wav", true), null, decoders.GetDefault("wav", true)));
|
formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, false, true, encoders.GetDefault("wav", true), null, decoders.GetDefault("wav", true)));
|
||||||
formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("m4a", true), encoders.GetDefault("m4a", false), decoders.GetDefault("m4a", true)));
|
formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("m4a", true), encoders.GetDefault("m4a", false), decoders.GetDefault("m4a", true)));
|
||||||
formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, encoders.GetDefault("tak", true), null, decoders.GetDefault("tak", true)));
|
formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, encoders.GetDefault("tak", true), null, decoders.GetDefault("tak", true)));
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ namespace CUETools.Converter
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.Error.WriteLine("CUETools.Converter, Copyright (C) 2009-2013 Grigory Chudov.");
|
Console.Error.WriteLine("CUETools.Converter, Copyright (C) 2009-2018 Grigory Chudov.");
|
||||||
Console.Error.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to");
|
Console.Error.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to");
|
||||||
Console.Error.WriteLine("the extent permitted by law. <http://www.gnu.org/licenses/> for details.");
|
Console.Error.WriteLine("the extent permitted by law. <http://www.gnu.org/licenses/> for details.");
|
||||||
if (!ok || sourceFile == null || destFile == null)
|
if (!ok || sourceFile == null || destFile == null)
|
||||||
@@ -159,7 +159,8 @@ namespace CUETools.Converter
|
|||||||
var property = TypeDescriptor.GetProperties(decoderSettings).Find(decOpt.Key, true);
|
var property = TypeDescriptor.GetProperties(decoderSettings).Find(decOpt.Key, true);
|
||||||
if (property == null)
|
if (property == null)
|
||||||
throw new Exception(String.Format("{0} doesn't have a property named {1}.", audioSource.GetType().Name, decOpt.Key));
|
throw new Exception(String.Format("{0} doesn't have a property named {1}.", audioSource.GetType().Name, decOpt.Key));
|
||||||
property.SetValue(decoderSettings, decOpt.Value);
|
property.SetValue(decoderSettings,
|
||||||
|
TypeDescriptor.GetConverter(property.PropertyType).ConvertFromString(decOpt.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
|
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
|
||||||
|
|||||||
Reference in New Issue
Block a user