6

I'm currently programming an app that extracts frames from a movie clip. I designed it so that the extraction will be done on a separate thread to prevent the application from freezing. The extraction process itself is taking a lot of resources, but works fine when used in the simulator. However, there are problems when building it for the iPad. When I perform another action (I'm telling my AV player to play while I extract frames), the thread unexpectedly stops working, and I believe it's being killed.

I assume it's becauase I'm using a lot of resources, but not entirely sure.

Here are my questions: 1. How can I tell if/why my thread stopping? 2. If it's really from over processing what should I do? I really need this action to be implemented.

Heres some code im using: To create the thread:

[NSThread detachNewThreadSelector:@selector(startReading) toTarget:self withObject:nil];

I'll post any information you need, Thanks so much!

Update I'm using GCD now and it populates the threads for me. However the OS still kills the threads.

I know exactly when is it happening. when i tell my [AVplayer play]; it kills the thread.

This issue is only happening in the actual iPad and not on the simulator

Or Ron
  • 2,313
  • 20
  • 34
  • If you have to ask, try using a higher level abstraction instead, like dispatch queues (GCD) or operation queues (NSOperationQueue). See [The Move Away from Threads](http://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/ConcurrencyandApplicationDesign/ConcurrencyandApplicationDesign.html#//apple_ref/doc/uid/TP40008091-CH100-SW8) for an extended discussion, or look for a [GCD](http://stackoverflow.com/questions/7941860/#7941898) or [NSOperationQueue](http://stackoverflow.com/questions/830218/) example. It's very useful stuff. – Jano Nov 07 '11 at 22:52
  • 1
    does your app crash ? if so what does the crash report say ? are you sure AVPlayer is threadsafe ? because if you are calling [AVplayer play] and accessing it at the same time in a background thread, that might be the problem. – JeanLuc Nov 14 '11 at 21:51
  • Is your extraction thread running as a background thread? I'm learning Objective-C but, if you are able to run it as a background thread can help not being killed by the OS. – Only You Nov 18 '11 at 00:08

3 Answers3

1

It sounds to me like you are trying to decode two video clips at the same time. Due to the hardware based decoding nature of the iPad, it can only support one decode process at a time. When you play a new item the old will be cancelled. This would explain why it works in the simulator, but not on the device.

As for a solution, you can switch to a pure software decoder like libav (GPL) or the CoreAVC SDK (commercial). That way you won't interfere with the HW decoder for playback.

Gil
  • 3,529
  • 1
  • 19
  • 22
0

When something works in the simulator and doesn't work on a device, one obvious explanation is a resource constraint issue for sure. But sometimes the simulator fails to accurately simulate other aspects of the device's functioning too. So I wondered if there could be any other interpretation to the situation. One possibility occurred to me that it could be competition for a limited asset—access to the AV Asset—which means that when you start playing it, it is no longer available to be processed as well (and for some reason a bug in the simulator does not display this limitation.)

In the AV Foundation Programming Guide, under "Playing Assets" Apple states:

Although ultimately you want to play an asset, you don’t provide assets directly to an AVPlayer object. Instead, you provide an instance of AVPlayerItem. A player item manages the presentation state of an asset with which it is associated. A player item contains player item tracks—instances of AVPlayerItemTrack—that correspond to the tracks in the asset.

This abstraction means that you can play a given asset using different players simultaneously, but rendered in different ways by each player. Using the item tracks, you can, for example, disable a particular track during playback (you might not want to play the sound component).

So I wondered—are you using AVPlayerItems to access your assets, that would let both operations happen at once? If so, at least that specific direction is ruled out. But if not, could be worth investigating to see if it fixes the problem.

Could be grasping at straws. But might lead somewhere.

Community
  • 1
  • 1
Duncan Babbage
  • 19,972
  • 4
  • 56
  • 93
  • Now i know for fact that when I read frames from the asset after I initiated an AVPlayer with this asset the thread is stoping but how can I Bypass that? – Or Ron Nov 14 '11 at 22:03
  • If you are not accessing the asset through an AVPlayerItem, you should provide one AVPlayerItem instance to play the asset, and a second AVPlayerItem instance to read frames from the asset. This should allow both to occur concurrently. – Duncan Babbage Nov 14 '11 at 23:56
  • I am using AVPlayer asset to play the asset but not to read the frames. For that im using AVAssetReader Which is initiated with the asset itself. How would u suggest doing that? – Or Ron Nov 15 '11 at 08:14
0

In section 'Setting the stack size of a thread' of Apple's Threading Programming Guide, page 27 says:

In iOS and Mac OS X v10.5 and later, allocate and initialize an NSThread object (do not use detachNewThreadSelector: toTarget: withObject: method)

Even though in page 22 says detachNewThreadSelector is one of the ways to create threads using NSThread.

And it gives this example in page 23 of how to start your thread:

NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(myThreadMainMethod:) object:nil];
[myThread start];

According to the guide that will create a detached thread in your app. Try creating your thread this way and see if the OS stops killing your thread.

For reference here is the link to the guide

http://developer.apple.com/library/ios/iPad/#documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/10000057i-CH15-SW2

It also mentions in page 29 that if your app uses the managed memory model, which seems you are, creating an autorelease pool in your thread entry routine should be the first thing you do and similarly destroying it the last thing your thread does. Not sure not having this would cause the kill of your thread but verify you do this.

Having a try/catch block in your thread entry routine may not solve the kill problem but, will avoid your app exiting if an error occurs in your thread.

I forgot to mention this other design tip that can help you with resource constraints, as Duncan mentioned. According to the guide page 18:

Avoid Shared Data Structures

The simplest and easiest way to avoid thread-related resource conflicts is to give each thread in your program its own copy of whatever data it needs. Parallel code works best when you minimize the communication and resource contention among your threads.

Which, I think you can do that in your app. In addition to doing what Duncan mentioned "don't provide assets directly to an AVPlayer object but instead provide an instance of AVPlayerItem", do it creating separate instances for each of your threads, one AVPlayerItem instance for the player thread and one AVPlayerItem instance for the extraction thread.

Only You
  • 2,051
  • 1
  • 21
  • 34