mirror of https://github.com/naudio/NAudio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
9.4 KiB
250 lines
9.4 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using NAudio.MediaFoundation;
|
|
using NAudio.Wave;
|
|
using NAudioWpfDemo.ViewModel;
|
|
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
|
|
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
|
|
|
|
namespace NAudioWpfDemo.MediaFoundationEncode
|
|
{
|
|
internal class MediaFoundationEncodeViewModel : ViewModelBase, IDisposable
|
|
{
|
|
private readonly Dictionary<Guid, List<MediaTypeViewModel>> allMediaTypes;
|
|
private EncoderViewModel selectedOutputFormat;
|
|
private MediaTypeViewModel selectedMediaType;
|
|
private string inputFile;
|
|
private string inputFormat;
|
|
private WaveFormat inputWaveFormat;
|
|
|
|
public List<EncoderViewModel> OutputFormats { get; }
|
|
public List<MediaTypeViewModel> SupportedMediaTypes { get; private set; }
|
|
public ICommand EncodeCommand { get; }
|
|
public ICommand SelectInputFileCommand { get; }
|
|
|
|
public MediaFoundationEncodeViewModel()
|
|
{
|
|
MediaFoundationApi.Startup();
|
|
allMediaTypes = new Dictionary<Guid, List<MediaTypeViewModel>>();
|
|
SupportedMediaTypes = new List<MediaTypeViewModel>();
|
|
EncodeCommand = new DelegateCommand(Encode);
|
|
SelectInputFileCommand = new DelegateCommand(SelectInputFile);
|
|
|
|
// TODO: fill this by asking the encoders what they can do
|
|
OutputFormats = new List<EncoderViewModel>
|
|
{
|
|
new EncoderViewModel() { Name = "AAC", Guid = AudioSubtypes.MFAudioFormat_AAC, Extension = ".mp4" }, // Windows 8 can do a .aac extension as well
|
|
new EncoderViewModel() { Name = "Windows Media Audio", Guid = AudioSubtypes.MFAudioFormat_WMAudioV8, Extension = ".wma" },
|
|
new EncoderViewModel() { Name = "Windows Media Audio Professional", Guid = AudioSubtypes.MFAudioFormat_WMAudioV9, Extension = ".wma" },
|
|
new EncoderViewModel() { Name = "MP3", Guid = AudioSubtypes.MFAudioFormat_MP3, Extension = ".mp3" },
|
|
new EncoderViewModel() { Name = "Windows Media Audio Voice", Guid = AudioSubtypes.MFAudioFormat_MSP1, Extension = ".wma" },
|
|
new EncoderViewModel() { Name = "Windows Media Audio Lossless", Guid = AudioSubtypes.MFAudioFormat_WMAudio_Lossless, Extension = ".wma" },
|
|
new EncoderViewModel() { Name = "FLAC", Guid = AudioSubtypes.MFAudioFormat_FLAC, Extension = ".flac" },
|
|
new EncoderViewModel() { Name = "Apple Lossless (ALAC)", Guid = AudioSubtypes.MFAudioFormat_ALAC, Extension = ".m4a" },
|
|
new EncoderViewModel() { Name = "Fake for testing", Guid = Guid.NewGuid(), Extension = ".xyz" }
|
|
};
|
|
SelectedOutputFormat = OutputFormats[0];
|
|
}
|
|
|
|
private void SelectInputFile()
|
|
{
|
|
var ofd = new OpenFileDialog();
|
|
ofd.Filter = "Audio files|*.mp3;*.wav;*.wma;*.aiff;*.aac";
|
|
if (ofd.ShowDialog() == true)
|
|
{
|
|
if (TryOpenInputFile(ofd.FileName))
|
|
{
|
|
InputFile = ofd.FileName;
|
|
SetMediaTypes();
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool TryOpenInputFile(string file)
|
|
{
|
|
bool isValid = false;
|
|
try
|
|
{
|
|
using (var reader = new MediaFoundationReader(file))
|
|
{
|
|
InputFormat = reader.WaveFormat.ToString();
|
|
inputWaveFormat = reader.WaveFormat;
|
|
}
|
|
isValid = true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MessageBox.Show($"Not a supported input file ({e.Message})");
|
|
}
|
|
return isValid;
|
|
}
|
|
|
|
public string InputFile
|
|
{
|
|
get => inputFile;
|
|
set
|
|
{
|
|
if (inputFile != value)
|
|
{
|
|
inputFile = value;
|
|
OnPropertyChanged(nameof(InputFile));
|
|
}
|
|
}
|
|
}
|
|
|
|
public string InputFormat
|
|
{
|
|
get => inputFormat;
|
|
set
|
|
{
|
|
if (inputFormat != value)
|
|
{
|
|
inputFormat = value;
|
|
OnPropertyChanged(nameof(InputFormat));
|
|
}
|
|
}
|
|
}
|
|
|
|
public EncoderViewModel SelectedOutputFormat
|
|
{
|
|
get => selectedOutputFormat;
|
|
set {
|
|
if (selectedOutputFormat != value)
|
|
{
|
|
selectedOutputFormat = value;
|
|
SetMediaTypes();
|
|
OnPropertyChanged("SelectedOutputFormat");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetMediaTypes()
|
|
{
|
|
if (!allMediaTypes.ContainsKey(SelectedOutputFormat.Guid))
|
|
{
|
|
TryGetSupportedMediaTypes();
|
|
}
|
|
FilterSupportedMediaTypes();
|
|
OnPropertyChanged(nameof(SupportedMediaTypes));
|
|
SelectedMediaType = SupportedMediaTypes.FirstOrDefault();
|
|
}
|
|
|
|
private void FilterSupportedMediaTypes()
|
|
{
|
|
//SupportedMediaTypes.Clear();
|
|
SupportedMediaTypes = new List<MediaTypeViewModel>();
|
|
if (inputWaveFormat == null)
|
|
{
|
|
SupportedMediaTypes.Add(new MediaTypeViewModel() {Name="Select an input file"});
|
|
return;
|
|
}
|
|
SupportedMediaTypes = allMediaTypes[SelectedOutputFormat.Guid]
|
|
.Where(m => m.MediaType != null)
|
|
.Where(m => m.MediaType.SampleRate == inputWaveFormat.SampleRate)
|
|
.Where(m => m.MediaType.ChannelCount == inputWaveFormat.Channels)
|
|
.ToList();
|
|
}
|
|
|
|
private void TryGetSupportedMediaTypes()
|
|
{
|
|
var list = MediaFoundationEncoder.GetOutputMediaTypes(SelectedOutputFormat.Guid)
|
|
.Select(mf => new MediaTypeViewModel(mf))
|
|
.ToList();
|
|
if (list.Count == 0)
|
|
{
|
|
list.Add(new MediaTypeViewModel() {Name = "Not Supported", Description = "No encoder found for this output type"});
|
|
}
|
|
allMediaTypes[SelectedOutputFormat.Guid] = list;
|
|
}
|
|
|
|
public MediaTypeViewModel SelectedMediaType
|
|
{
|
|
get => selectedMediaType;
|
|
set
|
|
{
|
|
if (selectedMediaType != value)
|
|
{
|
|
selectedMediaType = value;
|
|
OnPropertyChanged(nameof(SelectedMediaType));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Encode()
|
|
{
|
|
if (String.IsNullOrEmpty(InputFile) || !File.Exists(InputFile))
|
|
{
|
|
MessageBox.Show("Please select a valid input file to convert");
|
|
return;
|
|
}
|
|
if (SelectedMediaType == null || SelectedMediaType.MediaType == null)
|
|
{
|
|
MessageBox.Show("Please select a valid output format");
|
|
return;
|
|
}
|
|
|
|
using (var reader = new MediaFoundationReader(InputFile))
|
|
{
|
|
string outputUrl = SelectSaveFile(SelectedOutputFormat.Name, SelectedOutputFormat.Extension);
|
|
if (outputUrl == null) return;
|
|
using (var encoder = new MediaFoundationEncoder(SelectedMediaType.MediaType))
|
|
{
|
|
try
|
|
{
|
|
|
|
encoder.Encode(outputUrl, reader);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MessageBox.Show(e.Message, "Failed to encode");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private string SelectSaveFile(string formatName, string extension)
|
|
{
|
|
var sfd = new SaveFileDialog();
|
|
sfd.FileName = Path.GetFileNameWithoutExtension(InputFile) + " converted" + extension;
|
|
sfd.Filter = formatName + "|*" + extension;
|
|
//return (sfd.ShowDialog() == true) ? new Uri(sfd.FileName).AbsoluteUri : null;
|
|
return (sfd.ShowDialog() == true) ? sfd.FileName : null;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
MediaFoundationApi.Shutdown();
|
|
}
|
|
}
|
|
|
|
enum AacPayloadType
|
|
{
|
|
/// <summary>
|
|
/// The stream contains raw_data_block elements only.
|
|
/// </summary>
|
|
RawData = 0,
|
|
/// <summary>
|
|
/// Audio Data Transport Stream (ADTS). The stream contains an adts_sequence, as defined by MPEG-2.
|
|
/// </summary>
|
|
Adts = 1,
|
|
/// <summary>
|
|
/// Audio Data Interchange Format (ADIF). The stream contains an adif_sequence, as defined by MPEG-2.
|
|
/// </summary>
|
|
Adif = 2,
|
|
/// <summary>
|
|
/// The stream contains an MPEG-4 audio transport stream with a synchronization layer (LOAS) and a multiplex layer (LATM).
|
|
/// </summary>
|
|
LoasLatm = 3
|
|
}
|
|
|
|
internal class EncoderViewModel : ViewModelBase
|
|
{
|
|
public string Name { get; set; }
|
|
public Guid Guid { get; set; }
|
|
public string Extension { get; set; }
|
|
}
|
|
}
|