using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.IO;
using System.Windows.Forms;
namespace WindowsAzureMediaServicesSample
{
public class SampleCode5
{
private System.Timers.Timer jobTimer;
private string runningJobId = null;
private bool jobCompleted = false;
private IJob job;
private CloudMediaContext context = null;
public SampleCode5(CloudMediaContext context)
{
this.context = context;
this.context.Assets.OnUploadProgress += Assets_OnUploadProgress;
}
public void Run()
{
#region upload or find MP4 initial asset
IAsset asset = null;
if (!Configuration.SampleFile3AlreadyUploaded)
{
asset = context.Assets.Create(Configuration.SampleFile3LocalPath, AssetCreationOptions.None); // an MP4 file
}
else
{
foreach (var a in context.Assets)
{
foreach (var f in a.Files)
{
if (string.Compare(f.Name, Configuration.SampleFile3, false) == 0)
{
asset = a;
break;
}
}
if (asset != null) break;
}
}
#endregion
#region submit or find job 1: MP4 => Smooth Streaming
job = context.Jobs.Where(j => j.Name == Configuration.JobNameSampleCode5).SingleOrDefault<IJob>();
if (job == null)
{
Console.WriteLine("submitting job");
var q = from p in context.MediaProcessors
where p.Name == "Windows Azure Media Encoder"
select p;
IMediaProcessor processor = q.FirstOrDefault<IMediaProcessor>();
if (processor == null)
{
throw new ApplicationException("media processor for smooth streaming not found");
}
job = context.Jobs.Create(Configuration.JobNameSampleCode5);
ITask task = job.Tasks.AddNew("sample encoding task",
processor,
"H.264 IIS Smooth Streaming - HD 720p CBR" /* cf http://msdn.microsoft.com/en-us/library/jj129582.aspx */,
TaskCreationOptions.None);
task.InputMediaAssets.Add(asset);
IAsset task1OutputAsset = task.OutputMediaAssets.AddNew(
"Smooth Streaming Output", true, AssetCreationOptions.None);
var q2 = from p in context.MediaProcessors
where p.Name == "Smooth Streams to HLS Task"
select p;
IMediaProcessor processor2 = q2.FirstOrDefault<IMediaProcessor>();
if (processor2 == null)
{
throw new ApplicationException("media processor for HLS task not found");
}
string hlsConfiguration = File.ReadAllText("HLSConfiguration.xml");
ITask task2 = job.Tasks.AddNew("sample HLS task 2",
processor2, hlsConfiguration,
TaskCreationOptions.None);
task2.InputMediaAssets.Add(task1OutputAsset); // start from output assets of previous task
task2.OutputMediaAssets.AddNew("HLS Output", true, AssetCreationOptions.None);
job.Submit();
}
#endregion
WaitForJob();
// If the job completes, have the files available for smooth streaming
if (jobCompleted)
{
Console.WriteLine("publishing smooth streaming and HLS results");
IAccessPolicy streamingPolicy = context.AccessPolicies.Create("Streaming policy",
TimeSpan.FromDays(5), AccessPermissions.Read);
foreach (var t in job.Tasks)
{
foreach (var outputAsset in t.OutputMediaAssets)
{
Console.WriteLine("output asset: {0} has {1} file(s)", outputAsset.Name, outputAsset.Files.Count);
foreach (var f in outputAsset.Files.Where(x => x.Name.EndsWith(".ism")))
{
if (f.Name.Contains("m3u8"))
{
#region publish HLS to a WAMS origin
Console.WriteLine("will create a new locator for HLS");
IFileInfo manifestFile = f;
ILocator originLocator = context.Locators.CreateOriginLocator(
outputAsset, streamingPolicy, DateTime.UtcNow.AddMinutes(-5));
string urlForClientStreaming = originLocator.Path + manifestFile.Name
+ "/manifest(format=m3u8-aapl)";
Console.WriteLine("URL to manifest for client HSL streaming: ");
Console.WriteLine(urlForClientStreaming);
Clipboard.SetText(urlForClientStreaming);
Console.WriteLine("---");
Console.ReadLine();
#endregion
}
else
{
#region publish smooth streaming to a WAMS origin
IFileInfo manifestFile = f;
ILocator originLocator = context.Locators.CreateOriginLocator(
outputAsset, streamingPolicy, DateTime.UtcNow.AddMinutes(-5));
string urlForClientStreaming = originLocator.Path + manifestFile.Name + "/manifest";
Console.WriteLine("URL to manifest for client smooth streaming: ");
Console.WriteLine(urlForClientStreaming);
Clipboard.SetText(urlForClientStreaming);
Console.WriteLine("---");
Console.ReadLine();
#endregion
#region download smooth streaming files locally
//string localFileName = Path.Combine(Configuration.OutputFolder, f.Name);
//Console.WriteLine("Asset {0}, downloading to {1}", outputAsset.Id, localFileName);
//f.OnDownloadProgress += new EventHandler<DownloadProgressEventArgs>(f_OnDownloadProgress);
//f.DownloadToFile(localFileName);
#endregion
}
}
}
}
}
else
{
Console.WriteLine("Please check job again later.");
}
}
private void WaitForJob()
{
runningJobId = job.Id;
if (job.State == JobState.Finished)
{
jobCompleted = true;
Console.WriteLine("");
Console.WriteLine("********************");
Console.WriteLine("Job state is: " + job.State + ".");
foreach (var t in job.Tasks)
{
Console.WriteLine("task {0} state={1} duration={2}, PerfMessage={3}",
t.Name, t.State, t.RunningDuration, t.PerfMessage);
}
Console.WriteLine("Job completed successfully.");
return;
}
// Expected polling interval in milliseconds. Adjust this
// interval as needed based on estimated job completion times.
const int JobProgressInterval = 10000;
// Create a timer with the specified interval, and an event
// to check job progress. This is an optional workaround
// because job progress checking is not currently implemented.
this.jobTimer = new System.Timers.Timer(JobProgressInterval);
// Hook up an event handler.
jobTimer.Elapsed += new System.Timers.ElapsedEventHandler(jobTimer_Elapsed);
jobTimer.Start();
Console.WriteLine("Please wait, checking job status...");
// Wait for timer to elapse.
Console.ReadLine();
// After the job progress event, stop timer.
jobTimer.Stop();
// Refresh the reference to the job object.
context.Detach(job);
job = context.Jobs.Where(j => j.Id == runningJobId).SingleOrDefault();
}
void f_OnDownloadProgress(object sender, DownloadProgressEventArgs e)
{
Console.WriteLine("Download progress: {0:0.00} %, {1:0.00} MB / {2:0.00} MB",
e.Progress, Convert.ToDouble(e.BytesDownloaded) / (1024 * 1024), Convert.ToDouble(e.TotalBytes) / (1024 * 1024));
}
void jobTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Get a refreshed job reference each time the event fires.
IJob theJob = context.Jobs.Where(j => j.Id ==
runningJobId).SingleOrDefault();
// Check and handle various possible job states.
switch (theJob.State)
{
case JobState.Finished:
jobCompleted = true;
Console.WriteLine("");
Console.WriteLine("********************");
Console.WriteLine("Job state is: " + theJob.State + ".");
foreach (var t in theJob.Tasks)
{
Console.WriteLine("task {0} state={1} duration={2}, PerfMessage={3}",
t.Name, t.State, t.RunningDuration, t.PerfMessage);
}
Console.WriteLine("Job completed successfully.");
Console.WriteLine("Press Enter to complete the job.");
jobTimer.Stop();
break;
case JobState.Queued:
case JobState.Scheduled:
case JobState.Processing:
Console.WriteLine("Job state is: " + theJob.State + ".");
Console.WriteLine("Continue waiting for the job to complete, or " +
"press Enter in the console to exit without waiting.");
break;
case JobState.Error:
Console.WriteLine("Error:");
foreach (var t in theJob.Tasks)
{
Console.WriteLine("task {0} state={1}", t.Name, t.State);
Console.WriteLine("\tdetails:");
foreach (var d in t.ErrorDetails)
{
Console.WriteLine("\t{0}\t{1}", d.Code, d.Message);
}
Console.WriteLine("---");
//Console.WriteLine("task body: '{0}'", t.TaskBody);
}
jobTimer.Stop();
break;
default:
Console.WriteLine(theJob.State.ToString());
break;
}
// Detach the job to prevent the reference going stale.
context.Detach(theJob);
}
void Assets_OnUploadProgress(object sender, UploadProgressEventArgs e)
{
Console.WriteLine("Assets_OnUploadProgress: {0:0.00} %, {1} / {2}, {3:0.00} MB / {4:0.00} MB",
e.Progress, e.CurrentFile, e.TotalFiles,
Convert.ToDouble(e.BytesSent) / (1024 * 1024), Convert.ToDouble(e.TotalBytes / (1024 * 1024)));
}
}
}