GPUImageMovie not playing video file when initWithPlayerItem - gpuimage

I am using GPUImageMovie with initWithPlayerItem and its not starting the movie file on startProcessing. It was working fine with initWithUrl but I need playback controls for the player as told in this thread. I am using the following code
-(void)loadVideo
{
_playerItem = [[AVPlayerItem alloc]initWithURL:movieURL];
_player = [AVPlayer playerWithPlayerItem:_playerItem];
movieFile = [[GPUImageMovie alloc] initWithPlayerItem:_playerItem];
movieFile.runBenchmark = YES;
movieFile.playAtActualSpeed = YES;
filter = [[TSFilter alloc] init];
_movieView = [[GPUImageView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_movieView];
[self.view sendSubviewToBack:_movieView];
[movieFile addTarget:filter];
[filter addTarget:_movieView];
_player.rate = 1.0;
[movieFile startProcessing];
[_player play];
}

And finally after spent a lot of time I found the solution to this silly problem. I came to that solution when I tried bundled file instead of a file in a document directory. I think it is the bug in AVPlayerItem:initWithUrl method that is not working with the NSUrl value from document directory. Let me explain it in detail
When I get the Url of the file from document directory its value is
/var/mobile/Applications/7B3229B0-D18E-405D-BBA0-E9D57F2842C4/Documents/SkyFall_clip.m4v
but if I bundled this file and get the url from [NSBundle mainBundle] then its value is
file:///var/mobile/Applications/7B3229B0-D18E-405D-BBA0-E9D57F2842C4/Documents/SkyFall_clip.m4v
So I found that "file://" keyword is missing in the url for the document directory file. So i just append "file://" in the beginning of the url and it starts working. Although this should not be the case because both are the valid NSUrl and working for other classes like UIImage.
Note: Implement the string append operation is such a way that it append only if it is missing.

Related

download Route me online tiles into database

working on iPhone osm maps app (Route me).well initialising and downloading online maps was easy but real problem lies in saving the tiles through the code while u are online and reuse them while you are offline.i checked blogs regarding the same but everyone is saving the images externally and importing it in project and then showing them,which is not my requirement.please help me to save the tile image route me picks from online source
here is how i am using online route me maps
-(void) viewDidLoad
{
[RMMapView class];
mapView.contents.tileSource = [[RMOpenStreetMapSource alloc] init];
currentMarker = [[RMMarker alloc]initWithUIImage:[UIImage imageNamed:#"radarLocatorLite.png"] anchorPoint:CGPointMake(0.5, 0.5)];
markerManager = [mapView markerManager];
locationManager.delegate=self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest ;
locationManager.distanceFilter =0;
[mapView.contents setZoom:17.0f];
[markerManager addMarker:currentMarker AtLatLong:currentLocation.coordinate];
[self initCompassView];
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentLocation =newLocation;
[mapView moveToLatLong:newLocation.coordinate];
[markerManager moveMarker:currentMarker AtLatLon: newLocation.coordinate];
[currentRoutePath addLineToLatLong:newLocation.coordinate];
[[mapView.contents overlay] addSublayer:currentRoutePath];
// NSLog(#"i reached inside location update%f",currentRoutePath.lineWidth);
}
I have an iOS app that uses static map images saved in a sqlite database. There are some references as to how to do that, but it took me lots of trial-and-error effort to make sense of them and make it work.
It seems that you should be able to have a sqlite database and save the downloaded images into it as your app downloads them. Then you'd have to know what tile source to use: the sqlite database if the app is offline, the OSM site when online.
The structure of the database is:
tilekey text // a hash that route-me uses to locate the correct tile
zoom integer
row integer
col integer
zoom integer
image blob this stores the actual image of the map
I use a Python script to populate the database, as I want the app to always use the static map images from the database, never to use a real-time download from OSM.
Please let me know if you'd like more information, but if you search for using static maps with route-me, you should find how this is done. Good luck!
finally resolved problem by just a minor change in few places
Step 1: Go to this site "http://shiki.me/blog/offline-maps-in-ios-using-openstreetmap-and-route-me/" and follow instructions to download tile images from online and create of zip of the folder.remember the tile images folder are in order ->zoom level folder->x coord foler->y coord image respectively.
step 2: unzip the zip file in ur app at some folder
step 3:go to the file "RMAbstractMercatorWebSource.m" in map view project
and replace the following folders
-(NSString*) tileFile: (RMTile) tile
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Tiles"];
NSString *absPath=[NSString stringWithFormat:#"%#/%d/%d/%d.png", path,tile.zoom, tile.x, tile.y];
NSLog(#"file path >>>.............%#",absPath);
return absPath;
}//I unzipped the zip file at tiles folder
-(NSString*) tilePath
{
return nil;
}
-(RMTileImage *)tileImage:(RMTile)tile
{
RMTileImage *image;
tile = [tileProjection normaliseTile:tile];
NSString *file = [self tileFile:tile];
if(file && [[NSFileManager defaultManager] fileExistsAtPath:file])
{
image = [RMTileImage imageForTile:tile fromFile:file];
}
else if(networkOperations)
{
image = [RMTileImage imageForTile:tile withURL:[self tileURL:tile]];
}
else
{
image = [RMTileImage dummyTile:tile];
}
return image;
}
this in turns first look in cache then check the specified directory and finally go for online osm tile images

GPUImage terminates due to [AVAssetWriter startWriting] Cannot call method when status is 3'

I am having an issue running GPUImage. I have modified SimpleVideoFileFilter program(replaced the filter with a chromakeyfilter) and am using my own video. My program is terminating due to the following error:
[AVAssetWriter startWriting] Cannot call method when status is 3'
I have gone through the forums but not sure why the moviewriter is closing and then someone is writing to it.
I am using iPhone4 running iOS 7.0
Any clues are greatly appreciated. Thanks much!
Check whether your destination file exists already. If it does, remove it.
I was trying to add the file to a directory which did not exist. Example : /Videos/Video.mov , leaving it just /Video.mov worked.
Ok, I have a few ideas for you.
When you say "it just shows a frame and never plays the video" we have a good indication that your entire processing pipeline from start to finish is functional exactly once, then stops working.
That tells us that you are stringing things together correctly, but some of the components don't exist longer than a single frame buffer cycle, and subsequently the whole process stops.
it looks like filter and movieWriter are scoped to the class (I'm assuming they're not properties from the lack of an underscore, _filter and _movieWriter). So they will live on after this method has finished (correct me if I'm wrong...)
I think where you are encountering trouble is your (GPUImageView*)displayView
This should probably be declared as a class property (although it could work as just a variable) and then instantiated through the nib or the viewDidLoad method of the view controller.
As you have it now, this line: GPUImageView* filterView = (GPUImageView*)displayView; is making an assignment for filterView which is not used (and therefore unnecessary). It's not clear if displayView really is an instance of GPUImageView or if it will still be in existence when the current method finishes. (in fact you say it "is a UIView that I have programmatically created")
displayView will have to be a subclass of GPUImageView for this whole thing to work, and it will have to be scoped to the class, and not the method.
Declare it like this:
#property (strong, nonatomic)GPUImageView* displayView;
and then instantiate it and add it to your view hierarchy from within viewDidLoad
movieFile1 = [[GPUImageMovie alloc] initWithURL:movieFileURL1];
movieFile2 = [[GPUImageMovie alloc] initWithURL:movieFileURL2];
movieFile2.runBenchmark = YES;
movieFile2.playAtActualSpeed = NO;
filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[(GPUImageChromaKeyBlendFilter *)filter setColorToReplaceRed:0.0 green:1.0 blue:0.0];
[(GPUImageChromaKeyBlendFilter *)filter setThresholdSensitivity:0.4];
GPUImageView *filterView = (GPUImageView*)displayView;
[filter addTarget:displayView];
[movieFile1 addTarget:filter];
[movieFile2 addTarget:filter];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1920.0, 1280.0)];
[filter addTarget:movieWriter];
movieWriter.shouldPassthroughAudio = YES;
movieFile1.audioEncodingTarget = movieWriter;
[movieFile1 enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile1 startProcessing];
[movieFile2 startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
if (outputPath) {
finalURL = [[stongObj tempFileURL] copy];
DebugLog(#"Start Filter Processing :%#",finalURL);
DebugLog(#"movieUrl :%#",movieUrl);
// [CSUtils removeChuckFilePaths:#[outputPath]];
//Create Image Movie Object
_movieFile = [[GPUImageMovie alloc] initWithURL:outputPath];
//_movieFile = [[GPUImageMovie alloc] initWithURL:[[NSBundle mainBundle] URLForResource:#"videoviewdemo" withExtension:#"mp4"]];
_movieFile.runBenchmark = NO;
_movieFile.playAtActualSpeed = YES;
_movieFile.delegate = self;
//Movie Writer Object
_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:finalURL size:CGSizeMake([UIScreen mainScreen].bounds.size.height,[UIScreen mainScreen].bounds.size.height)];
//_movieWriter.delegate = self;
//Create Selecetive GPU Image Filter
[stongObj setGpuOutputFilter:selectedVideoFilterType];
//Create Group Filter
groupFilter = [[GPUImageFilterGroup alloc] init];
[groupFilter addTarget:imageOutputFilter];
// Only Single Filter is implemented.
//Apply Initial and Terminal Filter
[(GPUImageFilterGroup *)groupFilter setInitialFilters:[NSArray arrayWithObject:imageOutputFilter]];
[(GPUImageFilterGroup *)groupFilter setTerminalFilter:imageOutputFilter];
//_movieWriter -> groupFilter ->_movieFile
[_movieFile addTarget:groupFilter];
[groupFilter addTarget:_movieWriter];
_movieWriter.shouldPassthroughAudio = YES;
_movieFile.audioEncodingTarget = _movieWriter;
[_movieFile enableSynchronizedEncodingUsingMovieWriter:_movieWriter];
//Start Recording
[_movieWriter startRecording];
//Start Processing
[_movieFile startProcessing];
__weak typeof(self) weekSelf=self;
[_movieWriter setCompletionBlock:^{
__strong typeof(self) stongSelf=weekSelf;
DebugLog(#"Movie Write Completed");
//Finish Recording.
[stongSelf.movieWriter finishRecording];
//Release all object
// [self releaseAllObject];
//remove movieUrl,audioUrl,outputPath
[CSUtils removeChuckFiles:#[movieUrl,audioUrl,outputPath]];
}];
[_movieFile startProcessing]; app get crash in iOS 8 on this line but working fine on iOS 7
#Seasia Creative ,I have no enough reputation to add a comment by that list,I create a new list to answer U.
I check the output URL,console log "/var~~~~/tmpmerge.mp4",so i realize that ,i miss a "/" --->"/var~~~~/tmp/merge.mp4".
If the url is no correct, project runs into the same error.
hope to help some.

Saving video files to iCloud

I am currently trying to save video files to iCloud. I am using Core Data to save filename strings (filename.MOV) for each video, to then retrieve them from the ubiquity container. It all works locally (files save, and can be accessed from their URLs), but I am struggling to obtain the videos over iCloud. The Core Data syncs, so I have access to the file names, but when I try to obtain the video from the URL, I am unable to.
This is how I save the video after obtaining its url (videoURL below) from UIImagePicker, and creating a unique string from the current date:
NSString *videoFileName = [stringFromDate stringByAppendingPathExtension:#"MOV"];
NSURL *ubiquityContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSURL *saveToURL = [ubiquityContainer URLByAppendingPathComponent:videoFileName];
BOOL ok;
ok = [[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:videoURL destinationURL:saveToURL error:nil];
if (!ok) NSLog(#"error saving");
I then have a Core Data table view to list all of the videos. Here I observe changes in the Core Data to sync with iCloud and reload (this all still works fine):
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadFetchedResults:)
name:#"SomethingChanged"
object:[[UIApplication sharedApplication] delegate]];
}
- (void)reloadFetchedResults:(NSNotification*)note {
[self performFetch];
}
At this point, I want the ubiquity container to update, so that when I choose a video, and segue to a view controller to watch it, the video file can be found. (self.video is my Core Data video entity) (asset is is the video asset, which I can play back)
NSURL *ubiquityContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
ubiquityContainer = [ubiquityContainer URLByAppendingPathComponent:self.video.url];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:ubiquityContainer options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
This is where I run in to trouble. On the device where I took the video it works, but on another device, no file is found (objectAtIndex:0 is beyond bounds).
This is the metadata query I call at view did load:
NSMetadataQuery * query = [[NSMetadataQuery alloc] init];
NSString * filePattern = [NSString stringWithFormat:#"%#", self.video.url];
[query setPredicate:[NSPredicate predicateWithFormat:#"%K LIKE %#",
NSMetadataItemFSNameKey, filePattern]];
[query startQuery];
My metadata query may be at fault, or there may be more issues. Any help would be greatly appreciated!
I assume you are on iOS, which means on your second device the media file hasn't been downloaded (iOS doesn't download iCloud files until you actually access them, OS X downloads everything - see the docs).
To ensure the file is on the device use startDownloadingUbiquitousItemAtURL:error: or coordinateReadingItemAtURL:options:error:byAccessor: if you want to know when it's done (in the Accessor block). You will need to call the later anyway to do your coordinated read, so the first method has limited usefulness.

CoreData autosaving and not loading all data after autosave

I have an NSPersistentDocument subclass using NSManagedObject subclasses for my data.
When a new document is opened, I do some initializing of data structures (trivial amount of populating fields). What I've noticed is that the Untitled document gets autosaved, and when the application re-opens, that document gets loaded. If the application quits, the user doesn't (by default) get prompted with the save dialog. If the window closes, the user does.
First question:
I want to call up the save dialog when the user quits the application. I don't want this Untitled document hanging around (under normal circumstances). I either want it saved or trashed.
I attempted to fill out:
- (void)applicationWillTerminate:(NSNotification *)aNotification
In order to trigger the document to be saved. Calling save: on the context at this point gives an error. From what I can tell, this is because the user hasn't yet saved the file on their own. In addition, calling [self close]; or [[self windowForSheet] close]; close the window without saving.
How can I force the save dialog to come up? How can I trash the untitled document?
Second question (no, I can't count):
Since when the application starts, there may or may not be an Untitled document to deal with, I'm trying to keep track of the state in another model. I've already found that the initial data (to which I referred earlier) is present when the Untitled document came up. My other model has some metadata, including a success flag/state for the populated data. Once the populated data is all in place and correct, the state indicates as such. Unfortunately, while my populated data is being loaded when the app starts with a pre-existing Untitled document, the metadata class is not.
Please excuse the roughness of the code, at this point, I'm mucking it up until I can see that it's working how I want before I polish it back off:
- (bool) createGameState {
NSEntityDescription* description = [NSEntityDescription entityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:description];
NSError *error = nil;
NSArray *array = [[self managedObjectContext] executeFetchRequest:req error:&error];
[req release];
req = nil;
GameState* result = nil;
if (array) {
NSUInteger count = [array count];
if (!count) {
// Create the new GameState.
DebugLog(#"Creating GameState");
result = [NSEntityDescription insertNewObjectForEntityForName:[GameState name] inManagedObjectContext:[self managedObjectContext]];
[result setIsLoaded:[NSNumber numberWithBool:NO]];
} else {
if (count > 1) {
NSLog(#"WARNING: Potentially Corrupt Game State. found: %lu", count);
}
result = [array objectAtIndex:0];
if ([result isLoaded]) {
[self variantLoaded];
} else {
// In this case, we have an aborted set-up. Since the game isn't
// playable, just refuse to create the GameState. This will
// force the user to create a new game.
return NO;
}
}
} else {
DebugLog(#"error: %#", error);
}
[game setState:result];
return result;
}
Note that array is always present, and count is always zero. No, I'm not explicitly calling save: anywhere. I'm relying on the standard auto-save, or the user performing a save.
EDIT:
I installed the Core Data Editor app. It turns out the issue isn't on saving the data, but on loading it. (Note: Due to another issue, the app saves as binary when instructed to save as XML, which causes much head banging.)
I've broken it down to the simplest code, which should pick up all objects of type GameState in an array. It retrieves none, despite there clearly being objects of the appropriate type in the saved file:
NSManagedObjectContext* moc = [self managedObjectContext];
NSEntityDescription* entity = [NSEntityDescription entityForName:#"GameState" inManagedObjectContext:moc];
NSFetchRequest* req = [[NSFetchRequest alloc] init];
[req setEntity:entity];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:req error:&error];
Array is not null, but [array count] is 0.
At this point, I'm guessing it's something simple that I'm overlooking.
Second EDIT:
I added -com.apple.CoreData.SQLDebug 5 and saved as SQLite. The call to executeFetchRequest does not generate any debug logs. I do see the INSERT INTO ZGAMESTATE entry show up in the logs. It seems that executeFetchRequest is not getting passed to the backend.
Third EDIT (this one burns):
I created a new xcode project, using core data (as I had with the other). I copied just this one function (stubbing where necessary) and plopped a call to it in windowControllerDidLoadNib. In this new project, the code above works.
Found the problem.
I errantly was loading objects in Document's - (id) init call. Moved to windowControllerDidLoadNib (which is what I did in the test version) and it worked fine.

How can I send attachments using iphone mail-core api?

I'm working on a project in which I'm using the mail-core iphone api to send and retrieve mail. I have tried a lot of things, but have been unable to find any solution. I've tried searching but haven't found any solution. Could someone explain how to use the mail-core api to send attachments?. If anybody knows how to do that please let me know.
I haven't tested this but if you look at the header for CTCoreMessage, it does have a method addAttachment:. Argument for this is a CTCoreAttachment object.
Add this only and only after you setBody or setHTMLBody:
// Set Attachments
NSString *filePrefix = [[NSBundle mainBundle] bundlePath];
NSString *path = [NSString stringWithFormat:#"%#/%#",filePrefix,#"TestData/DSC_6201.jpg"];
NSLog(#"path:%#", path);
CTCoreAttachment *attach = [[CTCoreAttachment alloc] initWithContentsOfFile:path];
if ([attach data]==nil) {
NSLog(#"Error: attachment data is nil");
}
[myMessage addAttachment:attach];
Here, you should add TestData folder with image to your project as a folder reference

Resources