In my app calling [AVURLAsset isPlayableExtendedMIMEType:@"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\""]
returns YES
, which is expected.
If I run the exact same code in a unit test, then it returns NO
.
Both the app and the unit test are run with Xcode 5.0.2 on the iPhone Retina (4-inch) simulator running iOS 7.0.
- (void) testPlayableExtendedMIMEType
{
XCTAssertTrue([AVURLAsset class], @"");
XCTAssertTrue([AVURLAsset isPlayableExtendedMIMEType:@"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\""], @"");
}
The first assert passes but the second assert fails.
Why would this behavior be different in the unit test and in the app?
After reverse engineering how +[AVURLAsset isPlayableExtendedMIMEType:]
is implemented, I found the cause of the problem.
Here is a stack trace of what it is doing:
frame #0: 0x01b2861e CoreMedia`CelestialGetModelSpecificName
frame #1: 0x01b2885a CoreMedia`CelestialCFCreatePropertyListFromBundleIdentifier + 11
frame #2: 0x00050039 AVFoundation`__33+[AVURLAsset _avfValidationPlist]_block_invoke_0 + 39
frame #3: 0x02e99014 libdispatch.dylib`_dispatch_client_callout + 14
frame #4: 0x02e8b09f libdispatch.dylib`dispatch_once_f + 57
frame #5: 0x02e8b061 libdispatch.dylib`dispatch_once + 31
frame #6: 0x00050006 AVFoundation`+[AVURLAsset _avfValidationPlist] + 49
frame #7: 0x00050664 AVFoundation`+[AVURLAsset isPlayableExtendedMIMEType:] + 64
The CelestialCFCreatePropertyListFromBundleIdentifier
function tries to read a MediaValidator.plist
file inside the MediaToolbox
framework. The location of the plist file depends on the device model name. Here are the different MediaValidator.plist
files for the iOS 7 simulator.
MediaToolbox.framework
|-- J1
| `-- MediaValidator.plist
|-- K93
| `-- MediaValidator.plist
|-- N41
| `-- MediaValidator.plist
`-- N94
`-- MediaValidator.plist
When running the app, the CelestialGetModelSpecificName
function returns N41
, i.e. iPhone 5.
When running the unit tests, the CelestialGetModelSpecificName
function returns N88
, i.e. iPhone 3GS. As you can see, there is no N88
directory inside the MediaToolbox framework and this is why +[AVURLAsset isPlayableExtendedMIMEType:]
eventually fails.
A closer look at the CelestialGetModelSpecificName
function reveals the solution. The simulator reads the IPHONE_SIMULATOR_CLASS
environment variable in order to know what device is being simulated. If the IPHONE_SIMULATOR_CLASS
environment variable is not set, then it defaults to the hardcoded N88
value.
So in order for the test to pass, we just need to manually set the IPHONE_SIMULATOR_CLASS
environment variable to N41
since the unit test runner doesn’t set it automatically.
setenv("IPHONE_SIMULATOR_CLASS", "N41", 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With