H.264 : VTDecompressionSessionDecodeFrame fails with code 12909 - ios

I'm displaying RTSP streams from IP cameras. I want to replace this method avcodec_decode_video2 with VideoToolbox framework. I'm kinda new with video data processing so I'm a little lost...
I've tested both solutions from here and here, but I end up with a failure for this method VTDecompressionSessionDecodeFrame.
Error Domain=NSOSStatusErrorDomain Code=-12909 "The operation couldn’t be completed. (OSStatus error -12909.)" - -12909
I suspect this is coming from the session because if I call this VTDecompressionSessionCanAcceptFormatDescription right after creating the session, the result is NO.
Here is how is created my session :
VTDecompressionOutputCallbackRecord callback;
callback.decompressionOutputCallback = decompressionSessionDecodeFrameCallback;
callback.decompressionOutputRefCon = (__bridge void *)self;
NSDictionary *destinationImageBufferAttributes =[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],(id)kCVPixelBufferOpenGLESCompatibilityKey,[NSNumber numberWithInt:kCVPixelFormatType_32RGBA],(id)kCVPixelBufferPixelFormatTypeKey,nil];
OSStatus status = VTDecompressionSessionCreate(kCFAllocatorDefault, _formatDesc, NULL,
(__bridge CFDictionaryRef)destinationImageBufferAttributes,
&callback, &_decompressionSession);
I'm also not sure about the data to use. I have a choice between AVPacket.data, AVCodecContext.extradata, AVPacket.buf->data. Can anyone tell me which one should I use (maybe there is another one) ?
Thx in advance,
PS.: This is my first post ; let me know if it is not correctly presented/explained.

I've succeeded to get one successful status for this method. Turns out that I had indexes issues and the code I pasted had some bugs (at least, it wasn't adapted for my situation, specially for managing NALU types 1 and 5).
I have another issues because all the other calls returns a failure but I think I must post another question.

Related

Can't read or create UIManagedDocuments anymore

I have a big issue in my app, which prevents creating new documents and reading them, whereas it worked well until now.
I didn't change anything, and it started bugging from a build to another.
This is the code I'm using:
CLProject *project = [[CLProject alloc] initWithFileURL:projectURL];
NSLog (#"Will save project at URL: %#", projectURL);
[project saveToURL:projectURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
NSLog (#"Project saved: %d", success);
[...]
}];
CLProject is a subclass of UIManagedDocument.
The first NSLog is called, but not the second one. Instead I get an error :
2018-02-14 19:21:03.597495+0100 CamList[2247:750786] Will save project
at URL:
file:///var/mobile/Containers/Data/Application/151E38F5-2214-4876-A188-2AB8B5E8CF6A/Documents/Projects/715A0087-F2EF-439B-A2DD-8E878EF8A973.camlist
2018-02-14 19:21:03.783397+0100 CamList[2247:750886] [default] [ERROR]
Could not get attribute values for item
/var/mobile/Containers/Data/Application/151E38F5-2214-4876-A188-2AB8B5E8CF6A/Documents/Projects/715A0087-F2EF-439B-A2DD-8E878EF8A973.camlist
(n). Error: Error Domain=NSFileProviderInternalErrorDomain Code=1 "The
reader is not permitted to access the URL."
UserInfo={NSLocalizedDescription=The reader is not permitted to access
the URL.}
But it doesn't crash, the app keeps running (but nothing happens because the completion block never gets called).
What I don't understand is that everything was working fine and I haven't changed anything...
Can you help me??
Thanks
Well, it seems to work fine again this morning... Nothing to understand. My iPhone had to be tired...

OSStatus error code -34018

I am using SecItemCopyMatching to access the iOS keychain. About 1 in a hundred times I get a -34018 result code right after relaunching the app from the background. The documentation states:
The assigned error space for Keychain Services is discontinuous:
–25240 through –25279 and –25290 through –25329. Keychain Item
Services may also return noErr (0) or paramErr (–50), or CSSM result
codes
So it seems that -34018 is a 'CSSM result code'. I have followed the suggested link but could not find result codes.
What it the -34018 result code? How can I get more reliable keychain access?
- (NSData *)getKeychainData:(NSString *)key
{
NSDictionary *query = #{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecReturnData:#YES
};
CFDataRef result = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:#"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
After some research, I found this: http://opensource.apple.com/source/Security/Security-55471/sec/Security/SecBasePriv.h
So -34018 is errSecMissingEntitlement and the comment says
Internal error when a required entitlement isn't present.
Do you experience this error while running your unit tests? If so, this might help: https://stackoverflow.com/a/22305193/171933
This issue on github says that it only seems to happen while debugging from Xcode: https://github.com/soffes/sskeychain/issues/97 (also see https://stackoverflow.com/a/28256591/171933)
Hopefully some of this will help!
I've been just researching the same error.
The gist of it is that the security service apple uses in order to communicate with the key chain, in rare cases, when the user's device is low on memory, crashes and taking away the app ability to talk to the keychain which results the dreadful -34018.
This is not happening only while running through Xcode like some may claim.
This is the most recent data regarding the issue taken from the Apple developer forums by one of the Apple staff:
UPDATE: We have finally been able to reproduce the -34018 error on iOS
8.3. This is the first step in identifying the root cause and then coming up with a fix.
As usual, we can't commit to a release timeframe, but this has
affected many developers and we really want to get this resolved.
Earlier I suggested adding a small delay in
application:didFinishLaunchingWithOptions and
applicationDidBecomeActive: before accessing the keychain as a
workaround. However, that doesn't actually appear to help. That means
that there's no known workaround at this time other than relaunching
the app.
The issue appears to be related to memory pressure, so perhaps being
more aggressive in handling memory warnings may alleviate the problem.
From Another Apple staff member:
Keychain engineering is well aware of how important this issue is.
The primary problem has been reproducing the failure here at Apple.
We're now able to do that (largely thanks to the work you guys have put in filing and following up on your bug reports).
From Another Apple staff member on Mar 22, 2016:
OK, here’s the latest. This is a complex problem with multiple
possible causes: Some instances of the problem are caused by incorrect
app signing. You can easily distinguish this case because the problem
is 100% reproducible. Some instances of the problem are caused by a
bug in how iOS supports app development (r. 23,991,853). Debugging
this was complicated by the fact that another bug in the OS (r.
23,770,418) masked its effect, meaning the problem only cropped up
when the device was under memory pressure. We believe these problems
were resolved in iOS 9.3. We suspect that there may be yet more causes
of this problem. So, if you see this problem on a user device (one
that hasn’t been talked to by Xcode) that’s running iOS 9.3 or later,
please do file a bug report about it. Try to include the device
system log in your bug report (I realise that can be tricky when
dealing with customer devices; one option is to ask the customer to
install Apple Configurator, which lets them view the system log). And
if you do file a bug, please post your bug number, just for the
record. On behalf of Apple I’d like to thank everyone for their
efforts in helping to track down this rather horrid issue. Share and
Enjoy
Unfortunately there are no known workarounds and the issue is still not fixed in 9.3.2 Beta 1 (13F51a)
This code works for me:
static const UInt8 kKeychainItemIdentifier[] = "com.apple.dts.KeychainUI\0";
- (NSData *)getKeychainData:(NSString *)key
{
NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier length:strlen((const char *)kKeychainItemIdentifier)];
NSDictionary *query = #{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount: key,
(__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrGeneric: keychainItemID
};
CFDataRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:#"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
The main difference with OP's code is the addition of a Generic Attribute to the query. The Keychain Item Identifier is the default from apple. The reason behind this comes to differentiate possible different keychain items from each other. This is one way to make a more the keychain items access more reliable. Basically, in other words, this makes sure you access apple's default keychain.
After trying many of the fixes in stack overflow, things still didn't work for me.
What worked was switching the Keychain Sharing Capability in Xcode. Built and run and it worked right away.

AFNetworking 2 AFHTTPRequestOperation failure block stripping keys from error userInfo

I have just updated my app from AFNetworking 1.3.3 to 2.0.1, which required rewriting my network client that used to subclass AFHTTPClient.
I swapped out AFHTTPClient for AFHTTRequestOperationManager (I need to support iOS 6) and everything works fine apart from this:
The server gives me a JSON error string with the details of the error in:
error.userInfo.localizedRecoverySuggestion
However, this key (localizedRecoverySuggestion) is no longer in my NSError object.
Does anybody any idea how I can access it? Or what part of AFNetworking is stripping it out? The server is still sending it, it just doesn't make it as for as the error object in my POST: etc methods.
I've spent some time on this and I'm struggling to find where the issue is.
After a spot of debugging, it looks like the data takes the following path through AFNetworking:
AFURLConnectionManager connection:didReceiveData:
AFURLResponseSerialization validateResponse:data:error:
At which point it is thrown away.
So as a quick fix I just added an extra dictionary entry to that method where userInfo is created as follows:
NSLocalizedRecoverySuggestionErrorKey: [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
This is obviously a complete hack, but if anyone could give a pointer on how to accomplish this correctly, I'd be very grateful.

NSData dataWithContentsOfURL: not returning data for URL that shows in browser

I am making an iOS client for the Stack Exchange API. After a long, drawn out fight I finally managed to implement authentication - which gives me a token I stick into a URL. When the token is valid, the URL looks like this:
https://api.stackexchange.com/2.1/me/associated?key=_____MY_SECRET_KEY______&access_token=_____ACCESS_TOKEN_:)_____
which, when valid, brings me to this JSON in a webpage:
{"items":[{"site_name":"Stack Overflow","site_url":"http://stackoverflow.com","user_id":1849664,"reputation":4220,"account_id":1703573,"creation_date":1353769269,"badge_counts":{"gold":8,"silver":12,"bronze":36},"last_access_date":1375455434,"answer_count":242,"question_count":26},{"site_name":"Server Fault","site_url":"http://serverfault.com","user_id":162327,"reputation":117,"account_id":1703573,"creation_date":1362072291,"badge_counts":{"gold":0,"silver":0,"bronze":9},"last_access_date":1374722580,"answer_count":0,"question_count":4},...
And I get the correct JSON with this code:
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.stackexchange.com/2.1/me/associated?key=__SECRET_KEY_:)__&access_token=%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"token"]]];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if (jsonData)
{
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
}
When I manually invalidate the token, however, the URL still looks the same, and the page in a browser displays this:
{"error_id":403,"error_name":"access_denied","error_message":"`key` is not valid for passed `access_token`, token not found."}
However, dataWithContentsOfURL: is always nil. Why? What am I doing wrong?
I do get an NSError returned:
Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x1dd1e9f0 {NSURL=https://api.stackexchange.com/2.1/me/associated?key=key((&access_token=to‌​ken))}
NSCocoaErrorDomain Code=256 actually means a "file system or file I/O related error whose reason is unknown".
Why you get this error is likely because using dataWithContentsOfURL: will not work with that remote URL - or maybe because of the query params which contain the authentication and the token. Thus, you get the "weird" error.
In general, NSData's dataWithContentsOfURL: should only be use to access local file resources.
In order to solve your problem, you should improve your code in two steps:
1) Use NSURLConnection's convenient class method
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
The block defines what to do with the response data when the request finished. Generally, first check the error parameter, then status code of the response and Content-type - in this order.
2) Replace the former with your own instance method (or one from a third party) with a similar signature but which is much more sophisticated.
Approach #2 enables you to implement and use the following important features
Cancellation
customize authentication in every aspects
load body data to files
process received chunks simultaneous
perform multiple requests in a queue which controls the number of simultaneous connections
and a couple more.
Approach #2 is oftentimes implemented as a subclass of NSOperation and encapsulates a NSURLConnection object (which you need to cancel the connection).
You'll find answers of how to use NSURLConnection in asynchronous mode implementing the delegates. Also, there are third party solutions.
You might find the official documentation invaluable, too:
Using NSURLConnection
For a quick start, you may take a look at my "Simple GET request" class on Gist:
SimpleGetHTTPRequest
This class is NOT based on NSOperation, but it can be modified easily. Consult the official documentation of NSOperation how to make a subclass. This is basically easy, but has a few important things (KVO) which you should get correct.
In my case, adding AppTransportSecuritySettings dictionary into info.plist and setting key AllowArbitraryLoads to true.
Fixed my problem...
Hope it helps new developers.
Your URL might be having a space that's why it returns nil.Just replace the space in URL with a '+' :
stringByReplacingOccurrencesOfString:#" " withString:#"+"
I had this problem when I changed my folder structure. It gave me other NSError codes such as 512 and 4 for any file operations (local and web). The solution was to delete my IOS Simulator folders (Library\Developer\CoreSimulator).
If you are trying to access a remote url via HTTP and using XCode 7 or later you may get a NSCocoaErrorDomain returned from [NSData dataWithContentsOfURL:].
The root cause of this may actually be your "App Transport Security Settings". By default iOS doesn't allow arbitrary loading of URLS.

In iOS Core Audio - what's the best way of looking up OSStatus errors ( ie -43?)

What's the best way to look up the meaning of OSStatus errors ( i.e. -43 ) in Core Audio? Is there a way to process them in your iOS code so they can be formatted to show up with a brief explanation in the console?
After a quick look around, the best way so far seems to be to use the Unix command line tool - macerror - and type in the error code as an argument: not sure if it's possible to call & get the results of a macerror query from my Obj-C code in iOS into a console print out.
A recent article in IOS Dev Weekly linked to a great webpage that allows you to search for all OSStatus codes. Definitely worth bookmarking.
A bit late to the party, but I just noticed that at least one error code (560226676) is actual a four-letter code; it can be represented as '!dat' in big-endian. Searching for that gives kAudioDeviceUnsupportedFormatError.
IOW, it can't hurt to print error codes with a little function like this:
char *OSTStr( OSType type )
{
static union OSTStr {
uint32_t four;
char str[5];
} ltype;
ltype.four = EndianU32_BtoN(type);
ltype.str[4] = '\0';
return ltype.str;
}

Resources