Platforms to show: All Mac Windows Linux Cross-Platform
/AVFoundation/Transcode parallel
Required plugins for this example: MBS Main Plugin, MBS MacClassic Plugin, MBS AVFoundation Plugin, MBS Util Plugin, MBS MacCG Plugin, MBS MacCF Plugin, MBS MacBase Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /AVFoundation/Transcode parallel
This example is the version from Fri, 23th May 2013.
Project "Transcode parallel.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Löschen"
Const kFileQuit = "Beenden"
Const kFileQuitShortcut = ""
EventHandler Sub Open()
if AVFoundation.available = false then
MsgBox "Please run on Mac OS X 10.7 and newer."
quit
end if
AVFoundation = new MyAVFoundation
dim f as FolderItem = SpecialFolder.Desktop.Child("test.m4a")
if f.Exists = false then
MsgBox "This example needs a test.m4a file on your desktop."
quit
end if
Run f, 1, ".m4a", AVFoundationMBS.AVFileTypeMPEG4, AVFoundationMBS.kAudioFormatMPEG4AAC
Run f, 2, ".m4a", AVFoundationMBS.AVFileTypeMPEG4, AVFoundationMBS.kAudioFormatMPEG4AAC
Run f, 1, ".wav", AVFoundationMBS.AVFileTypeWAVE, AVFoundationMBS.kAudioFormatLinearPCM
Run f, 2, ".wav", AVFoundationMBS.AVFileTypeWAVE, AVFoundationMBS.kAudioFormatLinearPCM
Run f, 1, " Apple Lossless.m4a", AVFoundationMBS.AVFileTypeAppleM4A, AVFoundationMBS.kAudioFormatAppleLossless
Run f, 2, " Apple Lossless.m4a", AVFoundationMBS.AVFileTypeAppleM4A, AVFoundationMBS.kAudioFormatAppleLossless
End EventHandler
Sub Log(s as string)
LogWindow.list.addrow s
End Sub
Sub MoveFileToTrash(f as FolderItem)
dim r as FolderItem
call MacFileOperationMBS.MoveObjectToTrashSync(f, r, MacFileOperationMBS.kFSFileOperationDefaultOptions)
End Sub
Sub Run(file as folderitem, channels as integer, extension as string, OutputFileType as string, format as string)
dim songAsset as AVURLAssetMBS = AVURLAssetMBS.URLAssetWithFile(file)
dim assetError as NSErrorMBS
dim assetReader as AVAssetReaderMBS = AVAssetReaderMBS.assetReaderWithAsset(songAsset, assetError)
if assetError<>nil then
dim e as string = assetError.localizedDescription
log "Error: "+e
break
Return
end if
dim audioSettings as Dictionary = nil // no settings
dim tracks() as AVAssetTrackMBS = songAsset.tracks
dim assetReaderOutput as AVAssetReaderAudioMixOutputMBS = AVAssetReaderAudioMixOutputMBS.assetReaderAudioMixOutputWithAudioTracks(tracks, audioSettings)
if not assetReader.canAddOutput(assetReaderOutput) then
break
log "can't add reader output... die!"
return
end if
assetReader.addOutput(assetReaderOutput)
dim exportFile as folderitem = SpecialFolder.Desktop.Child("test"+str(channels)+extension)
if exportFile<>Nil then
MoveFileToTrash exportFile
exportFile = SpecialFolder.Desktop.Child("test"+str(channels)+extension)
end if
dim assetWriter as AVAssetWriterMBS = AVAssetWriterMBS.assetWriterWithFile(exportFile, outputFileType, assetError)
if assetError<>nil then
dim e as string = assetError.localizedDescription
log "Error: "+e
break
Return
end if
dim channelLayout as new QTAudioChannelLayoutMBS
if channels = 1 then
channelLayout.ChannelLayoutTag = QTAudioChannelLayoutMBS.kAudioChannelLayoutTag_Mono
elseif channels = 2 then
channelLayout.ChannelLayoutTag = QTAudioChannelLayoutMBS.kAudioChannelLayoutTag_Stereo
else
break
end if
dim outputSettings as new Dictionary
if format = AVFoundationMBS.kAudioFormatLinearPCM then // uncompressed needs extra values
outputSettings.Value(AVFoundationMBS.AVLinearPCMBitDepthKey) = 16
outputSettings.Value(AVFoundationMBS.AVLinearPCMIsNonInterleaved) = false
outputSettings.Value(AVFoundationMBS.AVLinearPCMIsFloatKey) = false
outputSettings.Value(AVFoundationMBS.AVLinearPCMIsBigEndianKey) = false
end if
if format = AVFoundationMBS.kAudioFormatAppleLossless then
outputSettings.Value(AVFoundationMBS.AVEncoderBitDepthHintKey) = 16
end if
outputSettings.Value(AVFoundationMBS.AVFormatIDKey) = OSTypeFromStringMBS(format)
outputSettings.Value(AVFoundationMBS.AVSampleRateKey) = 44100.0
outputSettings.Value(AVFoundationMBS.AVNumberOfChannelsKey) = channels
outputSettings.Value(AVFoundationMBS.AVChannelLayoutKey) = channelLayout.Memory
dim assetWriterInput as AVAssetWriterInputMBS = AVAssetWriterInputMBS.assetWriterInputWithMediaType(AVFoundationMBS.AVMediaTypeAudio, outputSettings)
if assetWriter.canAddInput(assetWriterInput) then
assetWriter.addInput(assetWriterInput)
else
break
log "can't add asset writer input... die!"
return
end if
assetWriterInput.expectsMediaDataInRealTime = false
call assetWriter.startWriting
assetReader.startReading
dim soundTrack as AVAssetTrackMBS = tracks(0)
dim startTime as CMTimeMBS = CMTimeMBS.Make(0, soundTrack.naturalTimeScale)
assetWriter.startSessionAtSourceTime(startTime)
// keep all the objects around in a global object for this job
dim t as new TranscodeOperation
t.assetReader = assetReader
t.assetWriter = assetWriter
t.assetWriterInput = assetWriterInput
t.assetReaderOutput = assetReaderOutput
t.exportFile = exportFile
log "Starting conversion "+str(t.id)+"..."
// here we pass ID for job so we can later find it back
assetWriterInput.requestMediaDataWhenReadyOnQueue(assetWriterInput, AssetReaderOutput, t.id)
End Sub
Property AVFoundation As MyAVFoundation
End Class
Class LogWindow Inherits Window
Control List Inherits Listbox
ControlInstance List Inherits Listbox
End Control
End Class
MenuBar MenuBar1
MenuItem FileMenu = "&Ablage"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Bearbeiten"
MenuItem EditUndo = "&Rückgängig"
MenuItem UntitledMenu1 = "-"
MenuItem EditCut = "&Ausschneiden"
MenuItem EditCopy = "&Kopieren"
MenuItem EditPaste = "&Einfügen"
MenuItem EditClear = "#App.kEditClear"
MenuItem UntitledMenu0 = "-"
MenuItem EditSelectAll = "&Alles auswählen"
End MenuBar
Class MyAVFoundation Inherits AVFoundationMBS
EventHandler Sub requestMediaDataWhenReadyOnQueueFinished(tag as integer)
logwindow.List.AddRow "Finished "+str(tag)
// we do all the stuff with IDs and operations for this. To find the object here!
dim t as TranscodeOperation = TranscodeOperation.Operation(tag)
t.close
End EventHandler
End Class
Class TranscodeOperation
Sub Cleanup()
if assetWriter<>nil then
call assetWriter.finishWriting
end if
if assetReader<>nil then
assetReader.cancelReading
end if
app.log "Done. File size is "+str(exportFile.Length)+" bytes."
// release a lot of stuff
assetReader = nil
assetReaderOutput = nil
assetWriter = nil
assetWriterInput = nil
Close
End Sub
Sub Close()
// remove from global list
dim n as integer = Operations.IndexOf(self)
if n>=0 then
Operations.Remove n
end if
End Sub
Sub Constructor()
// get a new ID
static IDCounter as integer
IDCounter = IDCounter + 1
ID = IDCounter
Operations.Append self
End Sub
Shared Function Operation(ID as integer) As TranscodeOperation
for each o as TranscodeOperation in Operations
if o.ID = ID then
Return o
end if
next
End Function
Property ID As integer
Property Private Shared Operations() As TranscodeOperation
Property assetReader As AVAssetReaderMBS
Property assetReaderOutput As AVAssetReaderOutputMBS
Property assetWriter As AVAssetWriterMBS
Property assetWriterInput As AVAssetWriterInputMBS
Property exportFile As FolderItem
End Class
End Project
See also:
The items on this page are in the following plugins: MBS AVFoundation Plugin.