public static void CopyTo(MatroskaDocument doc, Stream outputStream, OggOpusAudioStreamDemuxerSettings?settings = null) { if (doc == null) { throw new ArgumentNullException(nameof(doc)); } if (doc.Segment.Clusters == null) { throw new ArgumentNullException(nameof(doc.Segment.Clusters)); } if (outputStream == null) { throw new ArgumentNullException(nameof(outputStream)); } settings ??= new OggOpusAudioStreamDemuxerSettings(); var validator = new OggOpusValidator(); validator.ValidateAndThrow((settings, doc)); var opusAudio = doc.Segment.Tracks.TrackEntries.First(t => t.TrackNumber == settings.AudioTrackNumber); ushort preSkip = GetPreSkipFromCodecPrivate(opusAudio); var sampleRate = (int)opusAudio.Audio.SamplingFrequency; var channels = (int)opusAudio.Audio.Channels; var oggPageWriter = new OggPageWriter(outputStream, settings.AudioStreamSerial); var oggOpusHeaderWriter = new OggOpusHeaderWriter(oggPageWriter); // Write OpusHeader (+ OpusTags) oggOpusHeaderWriter.WriteHeaders(channels, sampleRate, preSkip); // Loop OggSegments byte segmentParts = 0; var oggPageWithSegments = new List <SegmentEntry>(); void WriteOggPageAndResetParts(OggHeaderType oggHeaderType) { // Write Ogg Page oggPageWriter.WriteOggPage(oggHeaderType, segmentParts, oggPageWithSegments); // Reset data segmentParts = 0; oggPageWithSegments.Clear(); } // Loop SegmentEntries foreach (var oggSegmentEntry in ConvertClustersToSegmentTable(doc.Segment.Clusters, sampleRate, settings.AudioTrackNumber)) { oggPageWithSegments.Add(oggSegmentEntry); segmentParts = (byte)(segmentParts + oggSegmentEntry.SegmentBytes.Length); if (segmentParts >= settings.MaxSegmentPartsPerOggPage) { WriteOggPageAndResetParts(oggPageWithSegments.Any(o => o.IsLast) ? OggHeaderType.EndOfStream : OggHeaderType.None); } } if (segmentParts > 0) { WriteOggPageAndResetParts(OggHeaderType.EndOfStream); } oggPageWriter.Flush(); }
public OggOpusHeaderWriter(OggPageWriter oggPageWriter) { _oggPageWriter = oggPageWriter; }