iOS Developing Note Part6 VideoPlayBack

Daily word: rascal

According to the experience about Video player development in cctv.com,any kind of the videoplayback function developing wouldn’t be a problem to me, I think.

My target is to make a videoplay component which can play videoclip inside UITableViewCell, and if you tap on fullscreen button, the videoscreen is gonna become fullscreen and rotate 90˚, no doubt, we need a transition effect to make it smoothly. like this:
VideoPlayBack in UITableViewCell
Yes I can just use the recommended way from Apple, MPMoviePlayerController or AVPlayer

MPMoviePlayerController

It’s an old and more like a 1-package deal solution for simple videoplay controller.

1
2
3
4
5
6
7
8
9
10
11
12
13

MPMoviePlayerController *player =
[[MPMoviePlayerController alloc] initWithContentURL: myURL];
[player prepareToPlay];

//as a subview mode
[player.view setFrame: myView.bounds];
[myView addSubview: player.view];
//as a present viewcontroller
[self.navigationController presentViewController:player animated:YES completion:nil];

[player play];

AVPlayer

Compare to MPMoviePlayerController AVPlayer is a suggested way by offical site, because it’s
more flexible to achieve your customer’s complex requirement. If you need a fully customize player, you want to make some mechanism under your control, you’d better take this way.

1
2
AVPlayer *avPlayer = [[AVPlayer alloc] initWithURL:itemURL];
[avPlayer play];

Both of them support streaming video play, audio play.

Because I need a framework which can be integrated quickly, I took this lib instead of building up a interface by my self.

NSURLProtocol

One of the task in my project is to add token infomation for all the related urls.

The most appropriate way is to implement NSURLProtocol. This is the way to customize your url request, all like here, implement your UIWebView Cache.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

#import "TWHttpURLProtocol.h"
@implementation TWHttpURLProtocol

#pragma mark - NSURLProtocol

+ (BOOL) canInitWithRequest:(NSURLRequest *)req{

if ([NSURLProtocol propertyForKey:@"MyURLProtocolHandledKey" inRequest:req]) {
return NO;
}
BOOL isAwsRequest = [self request:req contains:@"bbs.lndspd.com"];

return isAwsRequest;
}
+ (BOOL) request:(NSURLRequest*)request contains:(NSString*)domain {
NSString *str = [[request URL] absoluteString];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", domain];
return [pred evaluateWithObject:str];
}

+ (NSURLRequest*) canonicalRequestForRequest:(NSURLRequest *)req{

NSMutableDictionary *newheaders = [NSMutableDictionary dictionaryWithDictionary:req.allHTTPHeaderFields];
//modify headers whatever you like here
// [newheaders removeObjectForKey:@"X-Requested-With"];
// [newheaders setObject:@"*/*" forKey:@"Accept"];
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:req.URL];
for (NSString *key in newheaders) {
[newRequest setValue:newheaders[key] forHTTPHeaderField:key];
}
return newRequest;
}


- (void) startLoading{
NSLog(@"=========%@",self.request);
//catch up the request before send
NSMutableURLRequest *newRequest = [self.request mutableCopy];
[NSURLProtocol setProperty:@YES forKey:@"MyURLProtocolHandledKey" inRequest:newRequest];
self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
}
- (void) stopLoading{
NSLog(@"stopLoading");
}
@end

A reference blog “Drop-in Offline Caching for UIWebView (and NSURLProtocol)”, and “NSURLProtocol Tutorial”.

Global Position of a UITableViewCell

If I wanna make a VideoView scales and rotates smoothly, no layers cover it,and from a right place zooms, then zooms in to the original position and size. I should do these.

  1. Add the videoView to a toppest display layer, here’s the code to get it.
    1
    2
    UIWindow *theWindow = [[UIApplication sharedApplication] keyWindow];
    [theWindow addSubview:videoController.view];
  2. iOS provided a way to locate a UITableViewCell’s absolute position:
    1
    2
    3
    4
     UITableView *tableView = //the tableView you're using
    NSIndexPath *indexPath = //the index is under selected
    CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
    CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];

Screen record and convert to GIF on Mac OSX

Here is the solution, might be not so handy, but totally free, and authoritative. I transfer the key part here:

To capture the video (filesize: 19MB), using the free “QuickTime Player” application:
Open “Quicktime Player”,
Go to File -> New Screen Recording
Selected screen portion by dragging a rectangle, recorded 13 second video.
Go to File -> Export -> As Movie
Saved the video in full quality with the filename in.mov
To convert in.mov into out.gif (filesize: 48KB), open Terminal to the folder with in.mov and run the following command:

1
ffmpeg -i VideoPlaybackInTableCell.mov -s 374x664 -pix_fmt rgb24 -r 10 -f gif - | gifsicle --optimize=3 --delay=3 > out.gif

Install ffmpeg by brew:

1
2
brew install ffmpeg 
brew install gifsicle