Friday, August 22, 2008

Code Review Vol. 3.01 - WMEncode and DRM Walkthrough


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)



Up until this point it's fairly standard WMEncoder SDK code - create a sourcegroup collection, create a sourcegroup, and add a video or audio source to the source group - but here we introduce the DRM element. It follows the same template



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)



Essentially the DRM set up follows the same format as the Encoder, create a ProfileCollection, create a profile object which references the literal .drm profile file that I had exported from the DRM server. A DRMContentAuthor is pulled from the base WMEncoder object and everything is imported into that.



' 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



For the longest time the code didn't work. Until I found out that I needed to put a slight wait before encoding. And even while its encoding down below inside the while loop it still needs a pause between each iteration to register events and change states when necessary.



'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



Here I grab the .drm file from the filesystem and load it into the WMEncProfile2 object.



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




And here is the engine - I essentially read the directory that was set aside as the publishing directory, where all raw files to be encoded and distributed were deposited, and encode and drm them.



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


And that's it. Pretty straightforward, but by automating the encoding process and combining it with the DRMing process I was anble to integrate that into the automated workflow that I was building as the infrastructure to the overall Music Choice broadband product.

No comments: