Can't get SPC key for DRM video - AVPlayer [Swift] - swift

We have successfully integrated video DRM logic using AVAssetResourceLoaderDelegate.
It worked well. But lately, after playing the same movie several times in a row, we started getting this error when trying to get SPC.
do {
let spcData = try loadingRequest.streamingContentKeyRequestData(forApp: certificateData, contentIdentifier: assetIDData, options: [AVAssetResourceLoadingRequestStreamingContentKeyRequestRequiresPersistentKey: true as AnyObject])
return spcData
} catch {
print(error)
return nil
}
Error:
Domain=AVFoundationErrorDomain Code=-11879 "(null)" UserInfo={NSUnderlyingError=0x2805f9980 {Error Domain=NSOSStatusErrorDomain Code=-15841 "(null)"}}
I found that this code -11879 means that the request has been canceled.
I don't know what the second code means.
Why is the device not issuing more SPCs for content?
Maybe it's cached and needs to be updated somehow.

Related

Firebase Phone Authentication works on Simulator but not phone

I finally decided its time for testflight with my app. Authentication works perfectly in the simulator. I've tried it with test numbers (works great), I've tried it with my phone (sends verification code), and I've tried it with my parents phone (a device that has never been set up with my firebase) and it worked great.
As soon as I set it up on my device and tried to authenticate the same way, I encountered an error
here is the very simple code I took straight from firebase docs
public func startAuth(phoneNumber: String, completion: #escaping (Bool) -> Void) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { [weak self] verificationId, error in
guard error == nil else {
print("error verifying phone numer, Error: \n\(error!)")
completion(false)
return
}
self?.verificationId = verificationId
completion(true)
}
}
When running in the simulator, it works great, when running on my phone, I get this error:
error verifying phone numer, Error:
Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={FIRAuthErrorUserInfoNameKey=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information., NSUnderlyingError=0x283f43c30 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={NSUnderlyingError=0x283f9bae0 {Error Domain=com.google.HTTPStatus Code=503 "(null)" UserInfo={data={length = 207, bytes = 0x7b0a2020 22657272 6f72223a 207b0a20 ... 5d0a2020 7d0a7d0a }, data_content_type=application/json; charset=UTF-8}}, FIRAuthErrorUserInfoDeserializedResponseKey={
code = 503;
errors = (
{
domain = global;
message = "Error code: 33";
reason = backendError;
}
);
message = "Error code: 33";
}}}}
I've tried adding the firebase auth SDK: https://github.com/firebase/firebase-ios-sdk to the project and I get an error in a random file that says "redfinition of module 'Firebase'" and other stack overflow posts say to just delete the SDK and it'll solve your issue.
I'm really confused, why does it only work in the simulator and not my device?
Is the SDK really the solution and I need to find another way around the redefinition issue?
Thanks for your help in advance!

AVAssetWiter status failed when appending audio sample buffer to AVAssetwriterInput - OSX, Swift

I am trying to record screen with audio in OSX with AVFoundation, When i record video is working perfectly. But when adding audio input and appending it to AVAssetWriterInput, the asset writer status changes to .failed.
if let sampleBuffer = sampleBuffer {
if CMSampleBufferDataIsReady(sampleBuffer) {
if assetWriter.status == .unknown {
let startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: startTime)
}
if assetWriter.status == .failed {
print("writer error \(String(describing: assetWriter.error?.localizedDescription))")
return false
}
if isVideo {
if videoInputWriter.isReadyForMoreMediaData {
videoInputWriter.append(sampleBuffer)
return true
}
} else {
if audioInputWriter.isReadyForMoreMediaData {
audioInputWriter.append(sampleBuffer)
return true
}
}
}
}
The error message is
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x600002841320 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}}
Welcome!
I'm guessing, but it seems you are using the same callback for processing the audio and video samples. The problem might be that audio and video samples will be delivered concurrently in different queues (threads), which means that assetWriter.startSession(atSourceTime: startTime) could be accidentally executed multiple times in different threads—which is not allowed.
You need to somehow (atomically) protect that call, for instance by using a separate synchronization queue. Alternatively, you could only start the session with the first video buffer that arrives and ignore any audio buffer that comes before that (which would also prevent accidental black frames at the beginning of the video).

Getting the error code and description from a session.dataTask call

I am calling some APIs from my app. I'd like to get and process the error code. There seems to be a lot of information on how to retrieve and process the response codes, but very little on the error code. I'd like to access the error code in case, say the user has no internet connection so the call to the API fails. I am using this code:
session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in
if let error = error {
print("Tide Station API call failed with error \(error)")
return
}
if let response = response as? HTTPURLResponse {
print("Tide Station API call response is \(response.statusCode)")
}
if let data = data
{
do {
let result = try JSONDecoder().decode(TideStations.self, from: data)
self.tideStations = result.stations
print("\(result.stations.count) Tide Stations successfully loaded")
self.showTideStationsOnMap()
} catch {
print("Error while stations parsing: \(error)")
}
}
}).resume()
Which generates the following output in the debug area when my device is is airplane mode, i.e. I am forcing one sure way of the API call failing: (note I have bolded the area from my error handling print statement)
2020-02-26 17:57:58.235368+0000 APITest[5464:2590011] Task <006E7876-214F-41E3-8BDE-26960AF1F554>.<1> finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={NSUnderlyingError=0x283a918f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https://api.sunrise-sunset.org/json?lat=57.5081&lng=-1.7841&date=2020-06-21&formatted=0, NSErrorFailingURLKey=https://api.sunrise-sunset.org/json?lat=57.5081&lng=-1.7841&date=2020-06-21&formatted=0, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=The Internet connection appears to be offline.}
Astronomical Times API call failed with error Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={NSUnderlyingError=0x283a918f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https://api.sunrise-sunset.org/json?lat=57.5081&lng=-1.7841&date=2020-06-21&formatted=0, NSErrorFailingURLKey=https://api.sunrise-sunset.org/json?lat=57.5081&lng=-1.7841&date=2020-06-21&formatted=0, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=The Internet connection appears to be offline.}
In this example, I want to extract from this the fact that the internet connection appears down and advise the user. I would have thought that there would be similar support for error code extraction as there is for result code extraction. Would it be more normal to just say an error occurred (easy to detect) and handle elsewhere (e.g. detect no internet before calling the API)? If so, what shout I be guarding for?
The Error class in swift does not contain the error code and the error domain in it. However, if you print the error you can definitely see the error code and domain in the logs.
You can access those by simply casting the Swift's Error to the old Objective-C NSError. This classes are toll-free bridgeable, so there is no need to check if the cast fails or forcefully perform the cast with as!. Simply do:
let nsError = error as NSError
print("Error code is: \(nsError.code)")

Error on PHPhotoLibrary, cannot save video

I am trying to save a video in my photo library. But sometimes I get an error: The operation couldn’t be completed. (PHPhotosErrorDomain error -1.)
This is my code:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: exporter!.outputURL!)
}) { saved, error in
if saved {
print("video saved to camera roll")
} else {
print(error?.localizedDescription)
}
}
I was able to resolve this by removing the AVVideoQualityKey within AVVideoCompressionPropertiesKey in my video output settings for AVAssetWriter.

CNContactStore execute fails

I am working out how to use the Contacts framework, however some fairly simple code to create a contact is failing with an unexpected result. This is my code:
let Store = CNContactStore()
Store.requestAccess(for: .contacts, completionHandler:{ success, error in
if success {
let Contact = CNMutableContact()
Contact.givenName = "Dave"
Contact.familyName = "Nottage"
let SaveRequest = CNSaveRequest()
SaveRequest.add(Contact, toContainerWithIdentifier: nil)
do {
try Store.execute(SaveRequest)
print("Success")
}
catch let error as NSError {
print(error.localizedDescription)
}
} else {
print("No access")
}
})
..and this is the result:
2019-02-22 10:30:56.050344+1030 ContactsTest[30329:25254955] [default] Unable to load Info.plist exceptions (eGPUOverrides)
2019-02-22 10:30:57.973724+1030 ContactsTest[30329:25254955] Could not get real path for Address Book lock folder: open() for F_GETPATH failed.
2019-02-22 10:30:57.973954+1030 ContactsTest[30329:25254955] Unable to open file lock: <ABProcessSharedLock: 0x600001752ac0: name=(null), lockFilePath=(null), localLock=<NSRecursiveLock: 0x600002914a80>{recursion count = 0, name = nil}, fileDescriptor=-1> Error Domain=NSPOSIXErrorDomain Code=14 "Bad address" UserInfo={ABFileDescriptor=-1}
The operation couldn’t be completed. (Foundation._GenericObjCError error 0.)
Any ideas on what might be causing this?
Edit: Note also that this is being compiled for macOS 10.14 SDK, and is running on macOS 10.14.3
The answer is to check the Contacts checkbox of App Data in the App Sandbox section in Capabilities and turn on the switch for App Sandbox.
Make sure you added key NSContactsUsageDescription in Info.plist.
Please refer to link.
Important
An iOS app linked on or after iOS 10.0 must include in its Info.plist
file the usage description keys for the types of data it needs to
access or it will crash. To access Contacts data specifically, it must
include NSContactsUsageDescription.