Question

I am downloading the video and saved it in some directory so user can play that file afterwards.

It works well in all the cases like when download stopped and resume again due to some network fluctation. But sometimes file downloaded completely but not playing in MPMoviePlayerViewController.

I am using ASIHTTPRequest to download video file in background.

Observation: May be while downloading, network fluctuates some times and file may be corrupted.

Question: How can I came to know that downloaded file is corrupted? (via MPMoviePlayerViewControll)

Any suggestions? Below is the code to play:

@ACB... I used your code, but it always going in else condition:

    playerViewController = [[MPMoviePlayerViewController alloc]initWithContentURL:url];

    player = [playerViewController moviePlayer];
    player.movieSourceType = MPMovieSourceTypeFile;
    [player prepareToPlay];

    if(player.loadState == MPMovieLoadStatePlayable)
    {
        playerViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
        [self presentMoviePlayerViewControllerAnimated:playerViewController];


        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerInterruptByUser:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:playerViewController.moviePlayer];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:playerViewController.moviePlayer];

        //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinished:) name:UIApplicationDidEnterBackgroundNotification object:playerViewController.moviePlayer];

        [player play];
    }
    else
    {
        corruptVideoAlert = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Corrupt Video", nil) message:NSLocalizedString(@"This video is corrupted due to some network error. We suggest you to download again. Do you want to download it again?", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"NO", nil) otherButtonTitles:NSLocalizedString(@"YES", nil),nil];
        [corruptVideoAlert show];
        [corruptVideoAlert release];
    }
Was it helpful?

Solution

I found the similar problem, and I resolve this issue. Try below code:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerPlayingErrorNotification:) name:MPMoviePlayerPlaybackDidFinishNotification object:playerViewController.moviePlayer];

 -(void)playerPlayingErrorNotification:(NSNotification*)notif
{

    NSNumber* reason = [[notif userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
    switch ([reason intValue]) {
        case MPMovieFinishReasonPlaybackEnded:
            NSLog(@"Playback Ended");        
            break;
        case MPMovieFinishReasonPlaybackError:
            NSLog(@"Playback Error");
            [self performSelector:@selector(CorruptVideoAlertView) withObject:nil afterDelay:1.0];
            break;
        case MPMovieFinishReasonUserExited:
            NSLog(@"User Exited");
            break;
        default:
            break;
    }
}

Accept it if it works for you too. Hav a nice day.

OTHER TIPS

Use

if(moviePlayer.loadState == MPMovieLoadStatePlayable)

and check if it is playable. You can use MPMoviePlayerLoadStateDidChangeNotification if required. For more details check apple documentation.

You can try it like this,

playerViewController = [[MPMoviePlayerViewController alloc]initWithContentURL:url];

player = [playerViewController moviePlayer];
player.movieSourceType = MPMovieSourceTypeFile;
[player prepareToPlay];

playerViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentMoviePlayerViewControllerAnimated:playerViewController];


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerInterruptByUser:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:playerViewController.moviePlayer];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:playerViewController.moviePlayer];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadStateChanged:) name:MPMoviePlayerLoadStateDidChangeNotification object:playerViewController.moviePlayer];

    //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinished:) name:UIApplicationDidEnterBackgroundNotification object:playerViewController.moviePlayer];

In loadStateChanged: method do the following,

if(player.loadState == MPMovieLoadStatePlayable)
{
 [player play];
}
else
{
    corruptVideoAlert = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"Corrupt Video", nil) message:NSLocalizedString(@"This video is corrupted due to some network error. We suggest you to download again. Do you want to download it again?", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"NO", nil) otherButtonTitles:NSLocalizedString(@"YES", nil),nil];
    [corruptVideoAlert show];
    [corruptVideoAlert release];
}

For my scenario, I ended up recording the expected content length of the video coming in and made sure that the file size matches up when you try to play the video.

In this sense, it was faster for me to decide whether or not I should even play the video. If the file sizes didn't match, I just restart the download.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top