user244343
user244343

Reputation:

Why does MPMoviePlayerViewController fail on a movie that it should technically be able to play?

I'm initialising an MPMoviePlayerViewController to a source .mp4 on a server which supports Range requests and all that, and in fact the code I am using works fine on an iPhone 4, iPhone 3GS and iPad running iOS 4.

I have an iPhone 3G running iOS 4. The movie player class on this device begins to stream, and then immediately finishes playback. It doesn't error, though, it simply finishes playback as evidenced by printing the MPMoviePlaybackDidFinishNotification; it comes back with MPMoviePlayerPlaybackDidFinishReasonUserInfoKey = 0, which I take to mean MPMovieFinishReasonPlaybackEnded considering that's the first value of the enum. I've even tried setting a playback hint, MPMovieSourceType = MPMovieSourceTypeStreaming.

The issue is that if I navigate to the very same URL in Safari on the iPhone 3G, it streams and plays the movie without error. I'm totally stumped, and Google has so far turned up nothing specific to the 3G. Possible solutions include creating a custom AVFoundation implementation (not at all ideal) or using MPMoviePlayerController on 3G devices. If someone has guidance on switching based on the model of iPhone, not the version of iOS running, that would be great.

Using CFNotificationObserver callback registration, I have received the following notifications of interest:

Name: AVFileValidatorNotification_NotPlayable <-- likely the source of the issue
Info: Error = "Error
               Domain=NSOSStatusErrorDomain
               Code=-12621
               \"This movie could not be played.\" "

Name: FailedToBecomeReadyForInspection
Info: Properties = ( InitialSamples );
      Result = "-12621";

Name: AVController_ItemFailedToPlay
Info: "AVController_Error" = (the above Error object);
      "AVController_Item" = "<MPAVItem: 0x1b65d0>";

Name: MPAvControllerPlaybackStateChangedNotification
// Got several of these, the playback state changed as follows: 0 -> 2 -> 7 -> 0

Upvotes: 1

Views: 4562

Answers (2)

user244343
user244343

Reputation:

How's this for resolution: it "just works" now. What changed? I changed the Bundle ID of the app, I made a couple of interface tweaks elsewhere, but nothing from the actual presentation or setup of the movie player object changed. I haven't rebooted the phone; I did delete the app with the old Bundle ID though.

I'm not particularly happy that it randomly fixed itself, especially if reinstalling the app was all it took. It means that a couple of end users may encounter the same issue if the installation is "corrupted" in the same way mine may have been.

Upvotes: 1

Jonathan Grynspan
Jonathan Grynspan

Reputation: 43472

Debugging video playback is tricky. If you add a universal notification observer, you can see a lot more of what's happening behind the scenes:

CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), NULL, &someCallback, NULL, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);

With someCallback():

void someCallBack(
    CFNotificationCenterRef center,
    void *observer,
    CFStringRef name,
    const void *object,
    CFDictionaryRef userInfo
);

Notice I've used CFNotificationCenter here instead of NSNotificationCenter. Some of the notifications that get passed around use pointers in their arguments that cannot be coerced to id, so they cause crashes when a global observer is added via Cocoa. This isn't an issue at the Core Foundation level, where it is legal to use junk pointers for this purpose.

Edit: Based on the error you're getting--the video may be too high-quality for the decoder chip on the 3G (Safari may use a different decoding path that allows for more flexibility in its playback support.) Newer devices support higher-quality H.264 video, while older ones are limited in their formats. What's the resolution and H.264 profile of the video?

Also, if the video is installed onto the device directly, does it play?

Upvotes: 2

Related Questions