Wednesday, August 20, 2008

Code Review Vol. 3 - Encode and DRM Audio and Video Content With Windows Media Encoder SDK and VB.Net

Here is a snippet of code I wrote several years ago to encode and DRM content to WMV format. Back when I worked at Music Choice one of my initial tasks was to come up with a DRM solution for all videos on the web. My initial solution was clunky, basically following Microsoft's sample code - what little there actually was for the subject. But over time I revisited the solution and came up with a more elegant solution. Essentially I encapsulated the transcoding and DRMing of raw content to WMVs to a single console application. I exported a DRM profile from our DRM servers and used that to generate the DRM envelope. The console application was included in the automated work flow when new content was distributed to our clients.


Imports WMEncoderLib
Imports System.Windows.Forms
Imports System.IO


Module Module1
Dim WithEvents Encoder As WMEncoder
Dim glbQuitBool As Boolean = False
Dim baseURL As String
Dim DRMProfilePass As String = "XXX"
Dim DRMProfile As String = "ExportProfile.drm"


Sub Main()
Init()
SearchDir(baseURL)
End Sub

Sub Init()
Dim sr As StreamReader = New StreamReader("baseLoc.ini")
Dim line As String
line = sr.ReadLine()
sr.Close()
baseURL = line
End Sub

Function DoEncode(ByVal sourceFile As String, ByVal outputFile As String, ByVal thisProfile As WMEncProfile2, ByVal fileType As String) As Boolean
Try
Encoder = New WMEncoder
Dim SrcGrpColl As IWMEncSourceGroupCollection = Encoder.SourceGroupCollection
Dim SrcGrp As IWMEncSourceGroup = SrcGrpColl.Add("SG_1")
Dim newFile As IWMEncFile = Encoder.File

If fileType = "video" Then
Dim vidFile As IWMEncVideoSource = SrcGrp.AddSource(2)
vidFile.SetInput(sourceFile)
End If


Dim audFile As IWMEncAudioSource = SrcGrp.AddSource(1)

Dim DRM As IWMDRMContentAuthor
Dim DRMProColl As IWMDRMProfileCollection
Dim tempDRMPro As IWMDRMProfile

DRM = Encoder.EncoderDRMContentAuthor

' Retrieve the collection of DRM profiles.
DRMProColl = DRM.DRMProfileCollection

'First remove any DRM Profiles that may still linger
tempDRMPro = DRMProColl.Item(0)
DRM.RemoveDRMProfile(tempDRMPro.ID)

' Import a DRM profile.
DRM.ImportDRMProfile(DRMProfilePass, DRMProfile)

DRMProColl = DRM.DRMProfileCollection
Dim DRMPro As IWMDRMProfile
DRMPro = DRMProColl.Item(0)

' Set the current DRM profile into the encoding session.
Dim vKeyID As Object = "XXXXX"
DRM.SetSessionDRMProfile(DRMPro.ID, vKeyID)

Dim newProfile As WMEncProfile2 = New WMEncProfile2
audFile.SetInput(sourceFile)
newFile.LocalFileName = outputFile
newProfile = thisProfile

' newProfile.LoadFromFile(thisProfile)
SrcGrp.Profile = newProfile
Encoder.AutoStop = True
Encoder.RemoteAdmin = True
Encoder.PrepareToEncode(True)
Encoder.Start()

Dim x As Integer

'HACK - needs this to actually work, bug in WM SDK
For x = 0 To 30
Application.DoEvents()
x = x + 1
Next


While Encoder.RunState = WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING
Dim temp = Encoder.RunState
Dim y As Integer
For y = 0 To 300
y = y + 1
Next
Application.DoEvents()
End While

Encoder.Stop()
Return True

Catch ex As Exception
Console.WriteLine(ex)
Dim errFile As String = outputFile + ".error"
File.Create(errFile)
File.Delete(outputFile)
Return False
End Try

Encoder = Nothing

End Function



Function RetrieveProfile(ByVal nFile) As WMEncProfile2
Try
Dim BasicEdit As WMEncBasicEdit
BasicEdit = New WMEncBasicEdit

' Specify the input, output, and configuration files.
BasicEdit.MediaFile = nFile

' Retrieve the duration of the input file, in seconds.
Dim lFileDur As Long
lFileDur = BasicEdit.Duration / 1000

' Retrieve the profile used by the input file.
Dim Pro As WMEncProfile2
Pro = BasicEdit.Profile

Return Pro
Catch ex As Exception
Console.WriteLine(ex)
End Try


End Function

Sub SearchDir(ByVal dir)
'Environment.CurrentDirectory
Dim di As New DirectoryInfo(dir)
' Create an array representing the files in the current directory.
Dim fi As FileInfo() = di.GetFiles()
Dim tempFile As FileInfo
For Each tempFile In fi
Dim currentProfile As WMEncProfile2
Dim currentSourceFile As String = baseURL + "\" + tempFile.Name
Dim currentOutputFile As String = baseURL + "\DRMed\" + tempFile.Name
Dim currentFType As String
Dim currentFTypeArr = Split(tempFile.Name, ".")
If currentFTypeArr(1) = "wma" Then
currentFType = "audio"
ElseIf currentFTypeArr(1) = "wmv" Then
currentFType = "video"
End If

currentProfile = RetrieveProfile(currentSourceFile)
DoEncode(currentSourceFile, currentOutputFile, currentProfile, currentFType)
Next tempFile

End Sub


End Module

No comments: