Playing Video on iOS4 with the MediaPlayer Framework

Playing Video on iOS4 with the MediaPlayer Framework

Tutorial Details
  • Technology: iOS 4
  • Difficulty: Beginner
  • Completion Time: 30 - 45 Minutes

This tutorial is a step-by-step overview of how to integrate the MediaPlayer framework and work with the MPMoviePlayerController class in iOS4. With this knowledge, you will be able to playback fullscreen media in your own applications or display videos as a custom sized subview in your own view controllers. Read on for more!

Project Setup & Overview

This tutorial will use a simple application called “BigBuckBunny” to demonstrate using the MediaPlayer framework and the MPMoviePlayerController class for the iOS 4 SDK. This app will play a sample clip from the 2008, creative-commons animated short film Big Buck Bunny. By downloading the demo project attached to this post, you will be able to precisely follow all steps in this tutorial. However, if you already have an iPhone project that you would like to play your own movies within, you should still be able to follow along in your own code with only slight modifications to these steps. The download attached to this post contains two versions of the project: BigBuckBunny-Start should be used if you would like to integrate all the steps as you go along, and BigBuckBunny-Completed is the end result of this tutorial.

Step 1: Import the MediaPlayer Framework

CTRL + Click (or right click) on the “Frameworks” folder in the “Groups & Files” pane in Xcode. Select Add > Existing Frameworks from the drop-down menu.

Add MediaPlayer Framework

Select “MediaPlayer.framework” from the list of options presented, and click “Add.”

Add MediaPlayer Framework

Step 2: Import the MediaPlayer Framework and Declare the playMovie Method

Now that you have added the media player framework into your project, you need to actually import the code in that framework into the view controller that will be responsible for playing the movie. Go to the BigBuckBunnyViewController.h file, and insert the following line of code below the UIKit #import line:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

This line of code will make the view controller aware of all that the MediaPlayer.framework has to offer.

Next, we need to declare an instance method of our view controller that will trigger movie playback. Just above the @end statement in the header file, add this line:

-(IBAction)playMovie:(id)sender;

With our playMovie method declared, we are ready to begin writing our view controller implementation code.

Step 3: Implement the playMovie Method

Open the BigBuckBunnyViewController.m file. Implement the playMovie method with the following lines of code:

-(IBAction)playMovie:(id)sender
{
    NSString *filepath   =   [[NSBundle mainBundle] pathForResource:@"big-buck-bunny-clip" ofType:@"m4v"];
    NSURL    *fileURL    =   [NSURL fileURLWithPath:filepath];
    MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [self.view addSubview:moviePlayerController.view];
    moviePlayerController.fullscreen = YES;
    [moviePlayerController play];
}

On line 3, we create an NSString containing the file path to our movie file. On line 4, we use that file path to create an NSURL to our local movie. On line 5 we implement this by passing the NSURL into the initWithContentURL: method of the MPMoviePlayerController object. Notice how we allocated memory for the movie player on this line; we will need to release that later! On line 6, we add the MPMoviePlayerController view to our custom view controller subview so it will appear on screen, on line 7 we specify that we want the video to play in fullscreen mode, and on line 8 we begin playback of the movie.

Before we can test our code, we need to link our button’s “Touch Up Inside” action with the playMovie method. To do this, open BigBuckBunnyViewController.xib in Interface Builder. CTRL + Click (or right click) on the custom UIButton in the center of the screen to display the actions for this element. Drag from the circle next to “Touch Up Inside” to the “File’s Owner” object, and then select the “playMovie:” text that appears. Save your progress in Interface Builder before switching back to Xcode.

MediaPlayer Framework Button Connection

NOTE: You must actually select playMovie when it appears to complete this step. Be sure to save your changes!

If you build and debug the project at this point, you’ll see that movie playback is working as expected when you tap the custom UIButton. However, don’t celebrate just yet, because we aren’t quite done.

As mentioned previously, we explicitly allocate memory for the moviePlayerController object, but we haven’t yet released that memory. This is an interesting scenario. We can’t explicitly release the object in the method we allocated it in because our movie will still be playing at the time this method completes execution. It also isn’t safe to autorelease the object because we don’t know if our movie will still be playing the next time the autorelease pool is drained. Fortunately, the MPMoviePlayerController object is prebuilt to handle this scenario, and will dispatch a notification called MPMoviePlayerPlaybackDidFinishNotification to the NSNotificationCenter when playback completes. In order to receive this notification, we must register an “observer” to respond to that specific notification. To do so, modify our playMovie method as follows:

    NSString *filepath   =   [[NSBundle mainBundle] pathForResource:@"big-buck-bunny-clip" ofType:@"m4v"];
    NSURL    *fileURL    =   [NSURL fileURLWithPath:filepath];
    MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                                        selector:@selector(moviePlaybackComplete:)
                                                                            name:MPMoviePlayerPlaybackDidFinishNotification
                                                                           object:moviePlayerController];
    [self.view addSubview:moviePlayerController.view];
    moviePlayerController.fullscreen = YES;
    [moviePlayerController play];

We now need to create moviePlaybackComplete:, the selector we just registered. Add the following underneath the playMovie method:

- (void)moviePlaybackComplete:(NSNotification *)notification
{
    MPMoviePlayerController *moviePlayerController = [notification object];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                                                                object:moviePlayerController];
    [moviePlayerController.view removeFromSuperview];
    [moviePlayerController release];
}

Remember the “object” parameter that we set to moviePlayerController in the playMovie method above? Whatever object you set for that value is sent along with the notification later. On line 3, we are retrieving that object with the [notification object] statement and referencing it with a new MPMoviePlayerController pointer. Next, on line 4, we again send a message to the NSNotificationCenter, this time removing the observer we registered in playMovie. On line 8 we cleanup our custom view controller by removing the moviePlayerController view from our display, and on line 9 we finish out by releasing the memory we originally allocated in the playMovie method.

At this point, our implementation file should look like this:

#import "BigBuckBunnyViewController.h"
@implementation BigBuckBunnyViewController
-(IBAction)playMovie:(id)sender
{
    NSString *filepath   =   [[NSBundle mainBundle] pathForResource:@"big-buck-bunny-clip" ofType:@"m4v"];
    NSURL    *fileURL    =   [NSURL fileURLWithPath:filepath];
    MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                                       selector:@selector(moviePlaybackComplete:)
                                                                           name:MPMoviePlayerPlaybackDidFinishNotification
                                                                          object:moviePlayerController];
    [self.view addSubview:moviePlayerController.view];
    moviePlayerController.fullscreen = YES;
    [moviePlayerController play];
}
- (void)moviePlaybackComplete:(NSNotification *)notification
{
    MPMoviePlayerController *moviePlayerController = [notification object];
    [[NSNotificationCenter defaultCenter] removeObserver:self
										 name:MPMoviePlayerPlaybackDidFinishNotification
                                                                                object:moviePlayerController];
    [moviePlayerController.view removeFromSuperview];
    [moviePlayerController release];
}
- (void)dealloc {
    [super dealloc];
}
@end

Congratulations! You should now have a working movie player in your application. The rest of this tutorial is dedicated to customization of the player.

Step 4: Customize the Movie Display Size

Your work in the previous step enabled you to play movies in fullscreen mode. However, the great part about the MPMoviePlayerController enhancements in iOS 4 is that you can now specify a custom display size for playback within your own view controllers. To take advantage of this, modify the playMovie method as follows:

    [moviePlayerController.view setFrame:CGRectMake(38, 100, 250, 163)];
    [self.view addSubview:moviePlayerController.view];
    //moviePlayerController.fullscreen = YES;
    [moviePlayerController play];

On line 1 we create a custom frame size for the movie playback with the CGRectMake function. The values I have entered were taken from Interface Builder and match the origin, height, and width of the custom UIButton we use to play the movie. Note that I also commented out the fullscreen command on line 4.

If you build and go with your project code now, you should see that clicking the button will now play the video within our custom view controller, right on top of the UIButton. This works well enough, but what if you want to move the button around a bit to find the right look? It’s a bit cumbersome to constantly copy the literal CGRect values all the time. Update the playMovie method to do this dynamically:

-(IBAction)playMovie:(id)sender
{
    UIButton *playButton = (UIButton *) sender;
    NSString *filepath   =   [[NSBundle mainBundle] pathForResource:@"big-buck-bunny-clip" ofType:@"m4v"];
    NSURL    *fileURL    =   [NSURL fileURLWithPath:filepath];
    MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                                       selector:@selector(moviePlaybackComplete:)
                                                                           name:MPMoviePlayerPlaybackDidFinishNotification
                                                                          object:moviePlayerController];
    [moviePlayerController.view setFrame:CGRectMake(playButton.frame.origin.x,
                                                                                     playButton.frame.origin.y,
                                                                                 playButton.frame.size.width,
                                                                              playButton.frame.size.height)];
    [self.view addSubview:moviePlayerController.view];
    //moviePlayerController.fullscreen = YES;
    [moviePlayerController play];
}

On line 3 above, we typecast the “sender” parameter to a UIButton object as we know that is the kind of object that will be sending this message to our view controller. We then access this object directly to get the X and Y origin of the button as well as the button width and height. With the code above implemented, we are free to move the UIButton anywhere on the canvas and not have to worry about constantly updating our CGRectMake function call.

A Word on Scaling Mode

When displaying video in a custom rectangle, you will sometimes need to modify the scalingMode property of the MPMoviePlayerController object. Setting this property will determine how the movie image adapts to fill the playback size you have defined. The available scaling mode settings are as follows:

  • MPMovieScalingModeNone
  • MPMovieScalingModeAspectFit
  • MPMovieScalingModeAspectFill
  • MPMovieScalingModeFill

Each of the above options functions as you might expect, with MPMovieScalingModeAspectFill and MPMovieScalingModeFill likely being the two most commonly used modifications. The default scaling mode is MPMovieScalingModeAspectFit.

To experiment with this property in our code, insert the following line just before the [moviePlayerController play] statement:

    moviePlayerController.scalingMode = MPMovieScalingModeFill;

You will see that our video now fills all available space in the playback rectangle.

Conclusion

This tutorial has presented a fundamental introduction to using the MPMoviePlayerController class with the MediaPlayer framework. The MPMoviePlayerController class has additional options that we haven’t covered here, but I’ll leave the exploration of those as an exercise for the reader. With the foundation from this tutorial in place, you should be able to begin experimenting on your own! Please leave any feedback or questions you may have in the comments section below. Also feel free to send in questions or comments via either my personal twitter @markhammonds or the official Mobiletuts+ twitter account @mobtuts. Thanks for reading, and best of luck on your own projects!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.peewee1002.co.uk Peter Sawyer

    Wow you don’t know quite how useful this timing was.

    I was searching for this around 2 days ago.

    • http://mobile.tutsplus.com Mark Hammonds
      Author

      Glad you found it helpful. :) If you end up launching a project that this tut helped you out with, feel free to leave a link after it goes live!

  • http://www.twitter.com/CodyRob Cody Robertson

    Looks like you guys forgot to close some heading tags. ;)

    Very nice tutorial though, will come in handy soon.

  • NJanf

    Thank you so much for this tutorial! :)
    Could you possibly make a tutorial on how to:
    1. Hide controls
    2. Stop video with no controls (by touching the screen)
    3. Looping videos
    These are 3 very requested tutorials that are hard to find online.

    • Jhooy

      I would like a looping video tutorial as well.
      Can’t really find one that works. The most tutorials out there are not compatible with iOS 4.

  • Andy

    I can’t seem to find the MoviePlayerExampleViewController.m in the project files. Am I missing something? Possibly not looking in the right place.

    • http://mobile.tutsplus.com Mark Hammonds
      Author

      Hi Andy,

      My mistake. In my original draft, the application had been called simply “MoviePlayerExample,” but I later changed the project title to “BigBuckBunny.” As such, the implementation file you need to open is actually “BigBuckBunnyViewController.m,” and I’ve updated the text to reflect this.

      Hope that helps!

      Cheers,
      Mark Hammonds

  • Bram

    He man very nice tutorial!

    i really needed this, but is there a simple way to automatically view the video in landscape mode?

    because my video is based on that view.

    Thanks anyway!

    Bram

  • Eduardo Ballesteros

    Thanks for your tutorial.
    But, how to rotate the videoplayer to horizontal????

    Thanks

    • http://no Emiliano

      just add this code in the controller!!!
      // Override to allow orientations other than the default portrait orientation.
      - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
      // Return YES for supported orientations

      return YES;
      }

  • nyckidd

    Hey great tutorial….need more tuts about the memory leak though. Any plans on a video playlist tutorial ?

    • http://no Emiliano

      For the bandwith problem and memory leaks use playlist!!

      1. First encode movie at several bitrate (use quicktime for example)
      2. Use the macosX tools media file segmenter in a Terminal windows.
      mediafilesegmenter -I -f /test/testWifi -i testWifi.m3u8 /Movies/videoWifi.mp4
      mediafilesegmenter -I -f /test/testCell -i testCell.m3u8 /Movies/videoCell.mp4
      3. use the playlist creator
      variantplaylistcreator -o test.m3u8 ./testCell/testCell.m3u8 ./testCell/videoCell.plist ./testWifi/testWifi.m3u8 ./testWifi/videoWifi.plist
      4. Upload the directory test with all the file in your http server
      5. in Your code just open the file path to the playlist
      NSString *filepath =@”http://yourserver/test/test.m3u8″;
      NSURL *fileURL = [NSURL URLWithString:filepath];

      e voilà..

      you can download the segmenter in the devCenter-download-quicktime

  • Albert

    I have downloaded the source code. The movie can play, but no audio. Is it any problem for the code?

  • Jhon

    Thanks Marks, Excellent Tutorial………Thank you very much…..

  • Jhonny

    Excellent thanks mark, by the way…¿It possible autostart the same video?. When the viewController is executing, this video is autostart..

    Thanks again Mark…

  • MLee

    Great tutorial..
    How would you load a list of videos from a plist? I’ve done it for streaming videos but can’t figure out who to do it for local video files.

    Thanks

  • Matteo

    Hey! Very very good tutorial!! I’m from Switzerland so my english is not good! Hehehe! I’d like to know, how can I play Movie from an URL, I have to play video on an app from vimeo, maybe you know this! Please help me!! Matteo!

    • James Lavender

      Did you ever resolve this?

  • Larry

    It won’t let me connect the custom button to the File’s owner in step 3. I noticed that your button’s window says “custom button” while mine is “round rect button” I drag the touch up inside circle to the file’s owner icon button it won’t accept it. Please help!

  • Larry

    hi, im trying to get my images into the Interface Builder’s library. I cannot seem to get anything into the library. Can anyone help?

    thank you

  • Larry

    when i build and run my icon appears just fine but when i click it it opens and then instanly loops back to the icon page with all the other app icons. what am i doing wrong?

  • Perra.P

    I’m also intrested in a tutorial to save a .mp4 video file from url to the documents folder.

    Regards
    Perra.P

  • ruchi

    Hi,
    Thanks alot for this nice tutorial. I am beginner in iphone…. it was very helpful to increase my understanding.
    Query :- I am searching for “How to record video and play it back in the simulator” (not on device).

    I will be grateful to you if any helpful material will be there.

  • Ferry

    Great tutorial, this article helps me a lot

    Need some help how to play video streaming or download from site using xml

    Thanks alot for the info

  • myk

    Firstly, great tutorial. I am new to Xcode and this gave me a great “foot in the door”

    I have since implemented this as a subview for a table list containing a bunch of videos. Still plays great but does not stop playing when I switch back to the root view using a navigation controller.

    How do I release the video before it has stopped playing (ie viewDidUnload, viewWillDisapear, dealloc etc.)

    I am guessing it has something to do with this implementation of Notification but cannot work it out…..

    Anyway, thanks again for a great tutorial.

    • Chris

      @myk

      Did you ever figure that out?

  • http://www.millerf.com Fab

    Hi,

    I need to play 2 files one after the other… ANy idea how to without having a black screen in between? I even tried with 2 player without success :(

    Cheers for the tutorial anyway!!!

  • http://www.alloymarketing.com Ultramog

    Thanks a lot this is just what I need to get started in iOS.

    I haven’t been able to get a streaming mp4 URL working. Xcode reports a nil filepath value when I attempt to set it with a full streaming URL. Do I need to set a base URL and concatenate that with the filename?

    Thanks!

  • John

    Thank You so so much!!!!!!!! Been messing with this for 2 days and your instructions worked.

  • Andrew

    Hey Matt,

    I had this working earlier, but then when I try to build for the simulator, I get the error:

    Undefined symbols for architecture i386:
    “_OBJC_CLASS_$_MPMoviePlayerController”, referenced from:
    objc-class-ref in BigRedViewController.o
    ld: symbol(s) not found for architecture i386
    collect2: ld returned 1 exit status

    Note: BigRed is my project name

    I have added mediaplayer.framework to my framework folder, and yet it doesn’t seem to be referencing. Please let me know, I would really appreciate it.

    • Adam

      Did you ever get this resolved. I just started using Xcode recently and have encountered the same problem. I am running Xcode 4.2.1 for iOS 5

    • Jasoni

      Double check you adde the mediaplayer framework. This errors shows when the correct framewrok is not added, you probably added the avfoundation framewrok instead.

  • Ben

    This is great and working fine for me in iOS 4.3. Like some of the other people on here, I’d like to know there any way to stop a black screen flashing up before the video plays? I want to have a static image as my button that you click to kick start seamlessly into video without a break. Is this possible?

    Also as others have mentioned a video playlist tutorial would be great – keep up the good work guys!

  • Stef

    Hi,

    Always when i push the button, the simulator stops.
    In the code [themMovie play] is highlithed and says Thread1 : Stopped at breakpoint 4.

    But i have never set a breakpoint?

    any help ?

  • Prabhu

    Thanks for the tutorial…it was good…I am having a problem with the media player controller and was wondering if you could help :).
    I have a UIViewController (viewA) in view and a MPMoviePlayerController(control style – Embedded, backgroundColor – clearColor) as a subview. The movie plays without any flaw. The movie also plays in a given frame size. Life is great till here.
    Now, while the video is playing, if the user taps the fullscreen button, i get only the audio of the movie playing and the view of “viewA”.
    What do i do to show the video?

  • Stephanie

    Very nice tutorial. I’m having trouble when it goes fullscreen though. I have my viewcontroller, and a UIView subview that is the frame I want my video to play in. I add the movieplayercontroller as a subview to the container uiview. It plays fine, but when the user clicks full screen, how do I proceed? The controls end up all messed up with the status bar on top of the done button. The rest of my app has no status bar and a very different done button look. Can I customize the full screen view? If not, how can I at least make it so the status bar doesn’t overlap the done button?

    Thanks very much.

  • Andy

    I am running XCode 4.3 for iOS 5.1. I have had to delete the following because of Xcode 4.3 and new features added in.

    [moviePlayerController release];
    }

    - (void)dealloc {
    [super dealloc];

    When I run the program in the simulator on 5.1 all I get is a black screen. Do you have a solution or an updated code for iOS 5.1 and Xcode 4.3?
    Any help would be much appreciated.
    Thank you!!

  • AL

    For iOS 5.1 you have to declare moviePlayerController on BigBuckBunnyViewController.h :
    //
    // BigBuckBunnyViewController.h
    // BigBuckBunny

    #import
    #import

    @interface BigBuckBunnyViewController : UIViewController {

    }

    -(IBAction)playMovie:(id)sender;
    @property(nonatomic,retain)MPMoviePlayerController *moviePlayerController;
    @end

    and undeclared them on BigBuckBunnyViewController.m

  • skompdev

    Great tutorial.

    I’d love to see this same example but not using an XIB file.

  • http://www.amirgraphix.com amir

    Hi,
    thanks for tutorial, how about if we want to play video from source with that streaming live such as http://ca.live.imamhussein.tv:1935/live2/iht02/playlist.m3u8

    can give us tutorial on that or the source for doing so.

    please

  • Tanveer

    Hi there,
    i’m new to iOS, i want to play a video in my ipad app. i’m working with iOS 5. i tried all the above code but failed to get result. is there any changes to made for iOS5.?
    Please help.!
    Thanks,
    Tanveer

  • Scott

    Thanks!

  • Vasyares

    Thx!
    to Tanveer:
    in iOS5 with ARC you need to declare your player variable
    as property
    like @property (strong, nonatomic) MPMoviePlayerController *moviePlayer

  • http://www.greetings4u.net/ Greetings

    Thanks a lot. Very useful.

  • Francisco Ramos

    For all the people who had issues running this with ARC check out this video. It runs through a similar example but is updated for iOS 6. https://www.youtube.com/watch?v=sTp4sjfbNao

  • James Lavender

    Hi Thanks for a good tutorial. I was wondering how to get the data from a raw url. Thanks in advanced.