IAudioTitleSet

This commit is contained in:
Grigory Chudov
2018-04-30 22:32:49 -04:00
parent b6c3256d32
commit 47d1b09814
5 changed files with 127 additions and 92 deletions

View File

@@ -6,7 +6,7 @@ using static CUETools.Codecs.AudioPCMConfig;
namespace CUETools.Codecs.MPEG.ATSI namespace CUETools.Codecs.MPEG.ATSI
{ {
public class AudioDecoder : IAudioSource, IAudioContainer public class AudioDecoder : IAudioSource, IAudioTitleSet
{ {
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO) public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
{ {
@@ -331,7 +331,7 @@ namespace CUETools.Codecs.MPEG.ATSI
public ushort codec; public ushort codec;
public uint format; public uint format;
public byte StreamId public int StreamId
{ {
get get
{ {
@@ -342,64 +342,6 @@ namespace CUETools.Codecs.MPEG.ATSI
} }
} }
public string CodecString
{
get
{
switch (StreamId)
{
case DVDA.PCM_STREAM_ID: return "RAW/PCM";
case DVDA.MLP_STREAM_ID: return "MLP";
default: return StreamId.ToString();
}
//switch (codec)
//{
// case 0x000: return "RAW/PCM";
// case 0x100: return "MLP";
// default: return codec.ToString();
//}
}
}
public AudioPCMConfig PCM
{
get
{
if (track_sector.Count < 1) return null;
if (track_sector[0].dvdaBlock == null) return null;
return new AudioPCMConfig(
track_sector[0].dvdaBlock.gr1_bits,
track_sector[0].dvdaBlock.channels,
track_sector[0].dvdaBlock.gr1_frequency);
}
}
public string RateString
{
get
{
var sr = PCM.SampleRate;
if (sr % 1000 == 0) return $"{sr / 1000}KHz";
if (sr % 100 == 0) return $"{sr / 100}.{(sr / 100) % 10}KHz";
return $"{sr}Hz";
}
}
public string FormatString
{
get
{
if (track_sector.Count < 1) return "?";
if (track_sector[0].dvdaBlock == null) return "?";
switch (track_sector[0].dvdaBlock.ch_assignment)
{
case 0: return "mono";
case 1: return "stereo";
default: return "multi-channel";
}
}
}
public List<TimeSpan> Chapters public List<TimeSpan> Chapters
{ {
get get
@@ -436,6 +378,40 @@ namespace CUETools.Codecs.MPEG.ATSI
} }
} }
public AudioPCMConfig PCM
{
get
{
if (track_sector.Count < 1) return null;
if (track_sector[0].dvdaBlock == null) return null;
return new AudioPCMConfig(
track_sector[0].dvdaBlock.gr1_bits,
track_sector[0].dvdaBlock.channels,
track_sector[0].dvdaBlock.gr1_frequency);
}
}
public string Codec
{
get
{
switch (StreamId)
{
case DVDA.PCM_STREAM_ID: return "RAW/PCM";
case DVDA.MLP_STREAM_ID: return "MLP";
default: return StreamId.ToString();
}
//switch (codec)
//{
// case 0x000: return "RAW/PCM";
// case 0x100: return "MLP";
// default: return codec.ToString();
//}
}
}
public string Language => "";
public List<ATSITrackTimestamp> track_timestamp; public List<ATSITrackTimestamp> track_timestamp;
public List<ATSITrackSector> track_sector; public List<ATSITrackSector> track_sector;
} }

View File

@@ -5,7 +5,7 @@ using System.IO;
namespace CUETools.Codecs.MPEG.MPLS namespace CUETools.Codecs.MPEG.MPLS
{ {
public class AudioDecoder : IAudioSource, IAudioContainer public class AudioDecoder : IAudioSource, IAudioTitleSet
{ {
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO) public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
{ {
@@ -392,7 +392,7 @@ namespace CUETools.Codecs.MPEG.MPLS
foreach (var item in hdr_m.play_item) foreach (var item in hdr_m.play_item)
foreach (var audio in item.audio) foreach (var audio in item.audio)
{ {
if (audio.coding_type != 0x80 /* LPCM */) continue; //if (audio.coding_type != 0x80 /* LPCM */) continue;
titles.Add(new AudioTitle(this, audio.pid)); titles.Add(new AudioTitle(this, audio.pid));
} }
return titles; return titles;
@@ -461,6 +461,44 @@ namespace CUETools.Codecs.MPEG.MPLS
} }
public List<TimeSpan> Chapters => source.Chapters; public List<TimeSpan> Chapters => source.Chapters;
public AudioPCMConfig PCM
{
get
{
var s = FirstStream;
int channelCount = s.format == 1 ? 1 : s.format == 3 ? 2 : s.format == 6 ? 5 : 0;
int sampleRate = s.rate == 1 ? 48000 : s.rate == 4 ? 96000 : s.rate == 5 ? 192000 : s.rate == 12 ? 192000 : s.rate == 14 ? 96000 : 0;
int bitsPerSample = 0;
return new AudioPCMConfig(bitsPerSample, channelCount, sampleRate);
}
}
public string Codec
{
get
{
var s = FirstStream;
return s != null ? s.CodecString : "?";
}
}
public string Language
{
get
{
var s = FirstStream;
return s != null ? s.LanguageString : "?";
}
}
public int StreamId => pid;
MPLSStream FirstStream
{
get
{
MPLSStream result = null;
source.MPLSHeader.play_item.ForEach(i => i.audio.FindAll(a => a.pid == pid).ForEach(x => result = x));
return result;
}
}
AudioDecoder source; AudioDecoder source;
int pid; int pid;
@@ -476,7 +514,7 @@ namespace CUETools.Codecs.MPEG.MPLS
public uint duration; public uint duration;
} }
public struct MPLSStream public class MPLSStream
{ {
public byte stream_type; public byte stream_type;
public byte coding_type; public byte coding_type;

View File

@@ -56,13 +56,4 @@ namespace CUETools.Codecs.MPEG
savedBufferSize = 0; savedBufferSize = 0;
} }
}; };
public class AudioDescription
{
public int StreamId;
public string CodecString;
public string LanguageString;
public string FormatString;
public string RateString;
};
} }

View File

@@ -22,25 +22,61 @@ namespace CUETools.Codecs
public interface IAudioTitle public interface IAudioTitle
{ {
List<TimeSpan> Chapters { get; } List<TimeSpan> Chapters { get; }
AudioPCMConfig PCM { get; }
string Codec { get; }
string Language { get; }
int StreamId { get; }
//IAudioSource Open { get; } //IAudioSource Open { get; }
} }
public interface IAudioContainer public interface IAudioTitleSet
{ {
List<IAudioTitle> AudioTitles { get; } List<IAudioTitle> AudioTitles { get; }
} }
public class NoContainerAudioTitle : IAudioTitle public static class IAudioTitleExtensions
{ {
public NoContainerAudioTitle(IAudioSource source) { this.source = source; } public static TimeSpan GetDuration(this IAudioTitle title)
{
var chapters = title.Chapters;
return chapters[chapters.Count - 1];
}
public static string GetRateString(this IAudioTitle title)
{
var sr = title.PCM.SampleRate;
if (sr % 1000 == 0) return $"{sr / 1000}KHz";
if (sr % 100 == 0) return $"{sr / 100}.{(sr / 100) % 10}KHz";
return $"{sr}Hz";
}
public static string GetFormatString(this IAudioTitle title)
{
switch (title.PCM.ChannelCount)
{
case 1: return "mono";
case 2: return "stereo";
default: return "multi-channel";
}
}
}
public class SingleAudioTitle : IAudioTitle
{
public SingleAudioTitle(IAudioSource source) { this.source = source; }
public List<TimeSpan> Chapters => new List<TimeSpan> { TimeSpan.Zero, source.Duration }; public List<TimeSpan> Chapters => new List<TimeSpan> { TimeSpan.Zero, source.Duration };
public AudioPCMConfig PCM => source.PCM;
public string Codec => source.Settings.Extension;
public string Language => "";
public int StreamId => 0;
IAudioSource source; IAudioSource source;
} }
public class NoContainer : IAudioContainer public class SingleAudioTitleSet : IAudioTitleSet
{ {
public NoContainer(IAudioSource source) { this.source = source; } public SingleAudioTitleSet(IAudioSource source) { this.source = source; }
public List<IAudioTitle> AudioTitles => new List<IAudioTitle> { new NoContainerAudioTitle(source) }; public List<IAudioTitle> AudioTitles => new List<IAudioTitle> { new SingleAudioTitle(source) };
IAudioSource source; IAudioSource source;
} }
} }

View File

@@ -130,10 +130,10 @@ namespace CUETools.eac3to
#endif #endif
{ {
IAudioSource audioSource = null; IAudioSource audioSource = null;
IAudioContainer audioContainer = null; IAudioTitleSet audioContainer = null;
IAudioDest audioDest = null; IAudioDest audioDest = null;
var videos = new List<Codecs.MPEG.MPLS.MPLSStream>(); var videos = new List<Codecs.MPEG.MPLS.MPLSStream>();
var audios = new List<Codecs.MPEG.AudioDescription>(); List<IAudioTitle> audios = null;
List<TimeSpan> chapters = null; List<TimeSpan> chapters = null;
TagLib.UserDefined.AdditionalFileTypes.Config = config; TagLib.UserDefined.AdditionalFileTypes.Config = config;
@@ -160,29 +160,23 @@ namespace CUETools.eac3to
TypeDescriptor.GetConverter(property.PropertyType).ConvertFromString(decOpt.Value)); TypeDescriptor.GetConverter(property.PropertyType).ConvertFromString(decOpt.Value));
} }
audioSource = decoderSettings.Open(sourceFile); audioSource = decoderSettings.Open(sourceFile);
audioContainer = audioSource as IAudioContainer; audioContainer = audioSource as IAudioTitleSet;
if (audioContainer == null) audioContainer = new NoContainer(audioSource); if (audioContainer == null) audioContainer = new SingleAudioTitleSet(audioSource);
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
int frameRate = 0; int frameRate = 0;
bool interlaced = false; bool interlaced = false;
audioContainer.AudioTitles.ForEach(t => chapters = t.Chapters); audios = audioContainer.AudioTitles;
audios.ForEach(t => chapters = t.Chapters);
if (audioSource is Codecs.MPEG.MPLS.AudioDecoder) if (audioSource is Codecs.MPEG.MPLS.AudioDecoder)
{ {
var mpls = audioSource as Codecs.MPEG.MPLS.AudioDecoder; var mpls = audioSource as Codecs.MPEG.MPLS.AudioDecoder;
mpls.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); })); mpls.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); }));
mpls.MPLSHeader.play_item.ForEach(i => i.audio.ForEach(v => { if (!audios.Exists(v1 => v1.StreamId == v.pid)) audios.Add(new Codecs.MPEG.AudioDescription() { StreamId = v.pid, CodecString = v.CodecString, LanguageString = v.LanguageString, FormatString = v.FormatString, RateString = v.RateString }); }));
}
else
if (audioSource is Codecs.MPEG.ATSI.AudioDecoder)
{
var atsi = audioSource as Codecs.MPEG.ATSI.AudioDecoder;
atsi.ATSIHeader.titles.ForEach(t => audios.Add(new Codecs.MPEG.AudioDescription() { StreamId = 0/*!*/, CodecString = t.CodecString, FormatString = t.FormatString, RateString = t.RateString }));
} }
videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; }); videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; });
Console.Error.Write($@"M2TS, { Console.Error.Write($@"M2TS, {
videos.Count} video track{(videos.Count != 1 ? "s" : "")}, { videos.Count} video track{(videos.Count != 1 ? "s" : "")}, {
audios.Count} audio track{(audios.Count != 1 ? "s" : "")}, { audios.Count} audio track{(audios.Count != 1 ? "s" : "")}, {
CDImageLayout.TimeToString(audioSource.Duration, "{0:0}:{1:00}:{2:00}")}, { CDImageLayout.TimeToString(audios[0].GetDuration(), "{0:0}:{1:00}:{2:00}")}, {
(frameRate * (interlaced ? 2 : 1))}{ (frameRate * (interlaced ? 2 : 1))}{
(interlaced ? "i" : "p")}"); (interlaced ? "i" : "p")}");
Console.Error.WriteLine(); Console.Error.WriteLine();
@@ -213,7 +207,7 @@ namespace CUETools.eac3to
Console.Error.Write(id++); Console.Error.Write(id++);
Console.Error.Write(": "); Console.Error.Write(": ");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.CodecString, audio.LanguageString, audio.FormatString, audio.RateString); Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.Codec, audio.Language, audio.GetFormatString(), audio.GetRateString());
} }
} }
} }