Buffering Problems in Avqueueplayer - ios

I have a list of urls to be played from an avqueueplayer . I am loading the tracks and playable keys and adding the AVplayeritems into the Queue player one by one after each Item has finished playing.
Iam handling the buffering states of the player using the following code
for (NSValue *time in player.currentItem.loadedTimeRanges)
{
CMTimeRange range;
[time getValue:&range];
CGFloat seekTimeInSeconds = [self playerTimeToSeek];
CMTime timeSeek = CMTimeMakeWithSeconds(seekTimeInSeconds, NSEC_PER_SEC);
bufferReady = CMTimeRangeContainsTime(range, timeSeek);
NSLog(#"%f , %f ",CMTimeGetSeconds(range.start), CMTimeGetSeconds(range.duration));
if (CMTimeGetSeconds(range.duration)==0)
{
[self.player seekToTime: CMTimeMakeWithSeconds(seekTimeInSeconds, NSEC_PER_SEC) ];
}
if ((seekTimeInSeconds) >= CMTimeGetSeconds(self.player.currentItem.duration)) //
{
bufferReady = YES;
}
if (bufferReady)
{
//if (self.bufferEmptyOccured || change|| self.bufferNeedsUpdate)
{
[self manageBufferSufficientState];
self.bufferNeedsUpdate = NO;
}
self.bufferEmptyOccured = NO;
break;
}
}
if (!player.currentItem && self.nowPlayingAudioRecord[#"AudioItem"])
{
{
bufferReady = YES;
//if (self.bufferEmptyOccured||change || self.bufferNeedsUpdate)
{
[self manageBufferSufficientState];
self.bufferNeedsUpdate = NO;
}
self.bufferEmptyOccured = NO;
}
}
if (self.nowPlayingAudioRecord &&! self.nowPlayingAudioRecord[#"AudioItem"])
{
bufferReady = NO;
}
if (!bufferReady)
{
//if (!self.bufferEmptyOccured || change || self.bufferNeedsUpdate)
{
[self manageBufferEmptyState];
if (self.bufferNeedsUpdate)
{
self.bufferNeedsUpdate = NO;
}
}
self.bufferEmptyOccured = YES;
}
});
and 'playertimetoseek' method determines the time to which the player has to seek in case buffer is ready. This is because each of my urls need to be played at a predefined time to be played.
This method is called regularly once every 0.6 secs by using a timer to verify the buffering status
It works well normally , but for some reason , a few urls never get buffered ( each audio is of 10-20 sec duration) within the duration of the audio and the log gets printed as
2013-11-21 18:51:02.404 myapp[523:1000b] 1.009063 , 0.000000
2013-11-21 18:51:03.003 myapp[523:1000b] 1.608808 , 0.000000
2013-11-21 18:51:03.606 myapp[523:1000b] 2.208690 , 0.000000
2013-11-21 18:51:04.203 myapp[523:1000b] 2.811525 , 0.000000
2013-11-21 18:51:04.804 myapp[523:1000b] 3.408591 , 0.000000
2013-11-21 18:51:05.403 myapp[523:1000b] 4.009229 , 0.000000
2013-11-21 18:51:06.003 myapp[523:1000b] 4.608602 , 0.000000
2013-11-21 18:51:06.604 myapp[523:1000b] 5.208743 , 0.000000
2013-11-21 18:51:07.204 myapp[523:1000b] 5.809145 , 0.000000
2013-11-21 18:51:07.803 myapp[523:1000b] 6.409183 , 0.000000
2013-11-21 18:51:08.404 myapp[523:1000b] 7.008626 , 0.000000
2013-11-21 18:51:09.003 myapp[523:1000b] 7.609262 , 0.000000
2013-11-21 18:51:09.604 myapp[523:1000b] 8.208768 , 0.000000
2013-11-21 18:51:10.203 myapp[523:1000b] 8.809213 , 0.000000
2013-11-21 18:51:10.804 myapp[523:1000b] 9.408639 , 0.000001
2013-11-21 18:51:11.404 myapp[523:1000b] 9.408639 , 0.000001
2013-11-21 18:51:12.007 myapp[523:1000b] 10.579592 , 0.000000
Note that I am on a decent network and the audio bitrate is 128Kbps. Why could this be happening ? Is there any specific reason for this ?
EDIT:: In a few other cases the logs are as below :
2013-11-21 20:53:33.970 myApp[819:605b] 2.358489 , 0.000000
2013-11-21 20:53:34.570 myApp[819:605b] 2.958184 , 0.000000
2013-11-21 20:53:35.170 myApp[819:605b] 3.558097 , 0.000000
2013-11-21 20:53:35.770 myApp[819:605b] 4.158253 , 0.000000
2013-11-21 20:53:36.371 myApp[819:605b] 4.758271 , 0.000000
2013-11-21 20:53:36.970 myApp[819:605b] 5.358620 , 0.000000
2013-11-21 20:53:37.570 myApp[819:605b] 5.958164 , 0.000000
2013-11-21 20:53:38.170 myApp[819:605b] 6.558318 , 0.000000
2013-11-21 20:53:38.770 myApp[819:605b] 7.158033 , 0.000000
2013-11-21 20:53:39.371 myApp[819:605b] 7.758199 , 0.000009
2013-11-21 20:53:39.971 myApp[819:605b] 7.758199 , 0.417969
2013-11-21 20:53:40.571 myApp[819:605b] 7.758199 , 9.247356
2013-11-21 20:53:41.171 myApp[819:605b] 9.978836 , 19.095449
2013-11-21 20:53:41.770 myApp[819:605b] 9.978836 , 19.095449
2013-11-21 20:53:42.371 myApp[819:605b] 9.978836 , 19.095449
2013-11-21 20:53:42.971 myApp[819:605b] 9.978836 , 19.095449
2013-11-21 20:53:43.573 myApp[819:605b] 9.978836 , 19.095449
2013-11-21 20:53:44.171 myApp[819:605b] 9.978836 , 19.095449
How does this happen . It hasn't buffered anything until 20:53:39.971 and buffered almost everything within 0.6 seconds . How exactly does buffering work ?

Related

Inverse Discrete Fourier Transform with Real to Real functions

I have a DFT (real_to_complex) output (5x8) that I want to inverse transform using r2r (real to real) functions, instead of iDFT, because the coefficients are all favorably real:
[0.000000] [0.000000] [0.000000] [0.000000] [0.000000]
[0.000000] [-0.000039] [-5.228421] [1.999998] [0.000000]
[0.000000] [10.456858] [-0.000000] [-0.329559] [0.000000]
[0.000000] [-6.000002] [0.494339] [-0.000000] [0.000000]
[0.000000] [0.000000] [0.000000] [0.000000] [0.000000]
[0.000000] [12.000002] [-2.471695] [2.402020] [0.000000]
[0.000000] [-31.370562] [4.000000] [-1.647797] [0.000000]
[0.000000] [81.597977] [-15.685284] [4.000000] [0.000000]
The problem is with symmetry, the X-axis is fine; following the pattern of odd-symmetric DST-I 0,a,b,c,0,-c,-b,-a (we don't see the -c,-b,-a because this is "real_to_complex" output ). However, the Y-axis is not following DST pattern or the DCT-I pattern a,b,c,d,e,d,c,b. I don't see it being symmetric however, because the coefficients are real and the output is real, we should be able to calculate this with only real values.
The iDFT 8x8 output is the following:
[1.694307] [1.331561] [0.590346] [-1.331561] [-2.874999] [-1.331561] [0.590346] [1.331561]
[1.331561] [1.625000] [1.256080] [-0.281785] [-2.168437] [-1.968213] [-0.419204] [0.624999]
[0.590346] [1.580797] [2.125001] [1.212098] [-0.840346] [-2.048974] [-1.875001] [-0.743921]
[-1.331561] [1.031788] [2.951028] [4.125000] [2.168437] [-1.875002] [-3.787904] [-3.281786]
[-2.874999] [-2.168437] [-0.840346] [2.168437] [4.555690] [2.168437] [-0.840346] [-2.168437]
[-1.331561] [-3.281786] [-3.787904] [-1.875002] [2.168437] [4.125000] [2.951028] [1.031788]
[0.590346] [-0.743921] [-1.875001] [-2.048974] [-0.840346] [1.212098] [2.125001] [1.580797]
[1.331561] [0.624999] [-0.419204] [-1.968213] [-2.168437] [-0.281785] [1.256080] [1.625000]
The complex_to_real DFT assumes complex conjugate symmetry for the 8*5 matrix.
When we expand this matrix into 8-point DFTs of Columns and Rows, the columns do not meet the odd symmetry criteria [0,a,b,c,0,-c,-b,-a] and as such seek contribution from the cosine basis, producing a complex value.
However when we examine the columns in frequency space, there is somewhat an odd symmetry amongst complex values.
In Matlab we define the matrix R1 as follows:
0 0 0 0 0 0 0 0
0 -0.000039 -5.228421 1.999998 0 -1.999998 5.228421 0.000039
0 10.456858 -0 -0.329559 0 0.329559 0 -10.456858
0 -6.000002 0.494339 -0 0 0 -0.494339 6.000002
0 0 0 0 0 0 0 0
0 12.000002 -2.471695 2.40202 0 -2.40202 2.471695 -12.000002
0 -31.370562 4 -1.647797 0 1.647797 -4 31.370562
0 81.597977 -15.685284 4 0 -4 15.685284 -81.597977
Then the colFFR2=ifft(R1 ) produces the output;
0.000000 + 0.000000i 8.335529 + 0.000000i -2.361383 + 0.000000i 0.8030828 + 0.000000i 0.000000 + 0.000000i -0.8030828 + 0.000000i 2.361383 + 0.000000i -8.335529 + 0.000000i
0.000000 + 0.000000i 6.681977 - 3.574877i -1.673753 + 0.6864277i 0.3180193 - 0.2243077i 0.000000 + 0.000000i -0.3180193 + 0.2243077i 1.673753 - 0.6864277i -6.681977 + 3.574877i
0.000000 + 0.000000i 2.614213 - 7.949751i -0.5000000 + 0.9363536i 0.2471695 + 0.05025225i 0.000000 + 0.000000i -0.2471695 - 0.05025225i 0.5000000 - 0.9363536i -2.614213 + 7.949751i
0.000000 + 0.000000i -6.681977 - 14.03173i 1.673753 + 1.686428i -0.3180193 - 0.5538672i 0.000000 + 0.000000i 0.3180193 + 0.5538672i -1.673753 - 1.686428i 6.681977 + 14.03173i
0.000000 + 0.000000i -13.56396 + 0.000000i 3.361383 + 0.000000i -1.297422 + 0.000000i 0.000000 + 0.000000i 1.297422 + 0.000000i -3.361383 + 0.000000i 13.56396 + 0.000000i
0.000000 + 0.000000i -6.681977 + 14.03173i 1.673753 - 1.686428i -0.3180193 + 0.5538672i 0.000000 + 0.000000i 0.3180193 - 0.5538672i -1.673753 + 1.686428i 6.681977 - 14.03173i
0.000000 + 0.000000i 2.614213 + 7.949751i -0.5000000 - 0.9363536i 0.2471695 - 0.05025225i 0.000000 + 0.000000i -0.2471695 + 0.05025225i 0.5000000 + 0.9363536i -2.614213 - 7.949751i
0.000000 + 0.000000i 6.681977 + 3.574877i -1.673753 - 0.6864277i 0.3180193 + 0.2243077i 0.000000 + 0.000000i -0.3180193 - 0.2243077i 1.673753 + 0.6864277i -6.681977 - 3.574877i
Finally ifft(colFFR2.', 'symmetric') provides the matching iDFT.

Progress on CloudKit/CKAsset upload [duplicate]

I want to save Event and Image (for event) records. I want to show uploading progress in UI.
Event is little object with text and location.
Image is big object with photo as UIImage.
Image record is first item in array, event is second.
I create CKModifyRecordsOperation and set two CKRecord objects to recordsToSave
Than I set perRecordProgressBlock:
[operation setPerRecordProgressBlock:^(CKRecord *record, double progress) {
NSLog(#"#record: %# progress: %f", record.recordType, progress);
}];
And perRecordCompletionBlock:
[operation setPerRecordCompletionBlock:^(CKRecord *record, NSError *error) {
NSLog(#"#recordSaved: %# e: %#", record.recordType, error);
}];
I expect to see a lot of rows with progress for two records like:
#record: ImageRecord progress: 0.050000
#record: ImageRecord progress: 0.100000
#record: ImageRecord progress: 0.150000
...
#record: ImageRecord progress: 1.000000
#recordSaved: ImageRecord e: (null)
#record: EventRecord progress: 0.050000
...
#record: EventRecord progress: 1.000000
#recordSaved: EventRecord e: (null)
But really in console output I see:
#record: ImageRecord progress: 0.000000
#record: ImageRecord progress: 0.447357
#record: ImageRecord progress: 1.000000
#record: ImageRecord progress: 1.000000
#recordSaved: Event e: (null)
#recordSaved: ImageRecord e: (null)
What should I do?
The documentation for the CKModifyRecordOperation states:
The operation object executes this block zero or more times for each record in the recordsToSave property.
So if the save action for an object takes little time, then it could happen that you won't get a progress callback. As far as I know there is no way to influence the frequency of progress notifications.

How to sort by NSDate in a custom array in Swift

I'm trying to sort an array like this one by "dateRanges", that is a NSDate object.
- [0]
- name : "BREAKFAST"
- dateRanges
- [0]
- [0] : 2015-06-18 08:00:00 +0000
- [1]
- [0] : 2015-06-19 19:00:00 +0000
- hours
- [0] : 2
- [1] : 2
- [1]
- name : "LUNCH"
- dateRanges
- [0]
- [0] : 2015-06-16 08:00:00 +0000
- hours
- [0] : 8
- [2]
- name : "DINNER"
- dateRanges
- [0]
- [0] : 2015-06-17 06:30:00 +0000
- [1]
- [0] : 2015-06-30 16:00:00 +0000
- [2]
- [0] : 2015-06-12 17:00:00 +0000
- [3]
- [0] : 2015-06-29 09:30:00 +0000
- hours
- [0] : 1
- [1] : 2
- [2] : 3
- [3] : 3
What I do is to call to:
extension NSDate: Comparable { }
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
result.sortInPlace({ $0.dateRanges[0][0].compare($1.dateRanges[0][0]) == NSComparisonResult.OrderedAscending })
but the output gets like this:
- [0]
- name : "LUNCH"
- dateRanges
- [0]
- [0] : 2015-06-16 08:00:00 +0000
- hours
- [0] : 8
- [1]
- name : "DINNER"
- dateRanges
- [0]
- [0] : 2015-06-17 06:30:00 +0000
- [1]
- [0] : 2015-06-30 16:00:00 +0000
- [2]
- [0] : 2015-06-12 17:00:00 +0000
- [3]
- [0] : 2015-06-29 09:30:00 +0000
- hours
- [0] : 1
- [1] : 2
- [2] : 3
- [3] : 3
- [2]
- name : "BREAKFAST"
- dateRanges
- [0]
- [0] : 2015-06-18 08:00:00 +0000
- [1]
- [0] : 2015-06-19 19:00:00 +0000
- hours
- [0] : 2
- [1] : 2
As you can see, it only sorts by the dateRanges[0][0] indexes, (obviously because I'm asking it in the sortInPlace method), but I would like to know how to sort this array by dateRanges regardless of the indexes.
The expected result should be:
- [0]
- name : "LUNCH"
- dateRanges
- [0]
- [0] : 2015-06-16 08:00:00 +0000
- hours
- [0] : 8
- [1]
- name : "DINNER"
- dateRanges
- [0]
- [0] : 2015-06-12 17:00:00 +0000
- [1]
- [0] : 2015-06-17 06:30:00 +0000
- [2]
- [0] : 2015-06-29 09:30:00 +0000
- [3]
- [0] : 2015-06-30 16:00:00 +0000
- hours
- [0] : 1
- [1] : 2
- [2] : 3
- [3] : 3
- [2]
- name : "BREAKFAST"
- dateRanges
- [0]
- [0] : 2015-06-18 08:00:00 +0000
- [1]
- [0] : 2015-06-19 19:00:00 +0000
- hours
- [0] : 2
- [1] : 2
As i looked closely at your desired result it seems like it is not sorted in any way and you still get sorted by 0 indexes. So if this are really your goals all you need to do is:
MyArray.sortByZeroIndices() //here you use your code
for item in MyArray {
item.dateRanges.sort(<) // sort every internal array
}

Make UIProgressView as a count down timer

I've implemented a UIProgressView as a count down timer, its value is decreased from 1.0 to 0.0 in 1.5 seconds.
It already worked but the problem is the time it took was longer than 1.5
seconds, it was about 2.0 - 2.5 seconds until the progress view value reach 0.0
For it to run in just 1.5, I decreased the value of the progress by 0.001 each time it's called. The decrease method is call after 0.0015 second interval.
Below is how I do it. I don't know if there's anything wrong that make it run longer than just 1.5 seconds?
- (void)decreaseProgress {
if (currentProgress > 0.0000f) {
currentProgress -= 0.001f;
[_timeLineProgress setProgress:currentProgress animated:YES];
[self performSelector:#selector(decreaseProgress) withObject:self afterDelay:0.0015 inModes:#[NSDefaultRunLoopMode]];
} else {
[self stopTimer];
}
}
To animate the progress, try this code in your decreaseProgress method
[UIView animateWithDuration:1.5 animations:^{
[_timeLineProgress setProgress:0.0 animated:YES];
}];
You're attempting to update the progress view 1000 times in 1.5 seconds. That's way too fast, since the screen only updates 60 times per second. In other words, you're updating the progress bar more than 10 times between each time that the progress bar is actually redrawn on the screen.
Instead I would suggest 15 updates at 0.1 second intervals, and change the progress bar by 1/15 each time.
One way to check how well the code is performing is to use the CACurrentMediaTime function to get timestamps. Here's some sample code that demonstrates how to do that. The progressStart variable is the timestamp when the button press event occurred, and the NSLog prints the amount of time elapsed relative to the start time.
An important feature of the code is that the performSelector method is called as early as possible in the updateProgress method, to minimize slippage.
#interface ViewController ()
{
CFTimeInterval progressStart;
int progressCount;
}
#property (weak, nonatomic) IBOutlet UIProgressView *progressView;
#end
- (void)updateProgress
{
if ( progressCount > 0 )
[self performSelector:#selector(updateProgress) withObject:nil afterDelay:0.1];
self.progressView.progress = progressCount / 15.0;
NSLog( #"%2d %.3lf", progressCount, CACurrentMediaTime() - progressStart );
progressCount--;
}
- (IBAction)someButtonPressed
{
self.progressView.progress = 1.0;
progressStart = CACurrentMediaTime();
progressCount = 15;
[self updateProgress];
}
And here are the results from a typical run
2015-07-01 13:05:57.610 Progress[8354:907] 15 0.000
2015-07-01 13:05:57.711 Progress[8354:907] 14 0.101
2015-07-01 13:05:57.813 Progress[8354:907] 13 0.203
2015-07-01 13:05:57.914 Progress[8354:907] 12 0.304
2015-07-01 13:05:58.015 Progress[8354:907] 11 0.405
2015-07-01 13:05:58.116 Progress[8354:907] 10 0.506
2015-07-01 13:05:58.218 Progress[8354:907] 9 0.608
2015-07-01 13:05:58.319 Progress[8354:907] 8 0.709
2015-07-01 13:05:58.420 Progress[8354:907] 7 0.810
2015-07-01 13:05:58.520 Progress[8354:907] 6 0.910
2015-07-01 13:05:58.621 Progress[8354:907] 5 1.011
2015-07-01 13:05:58.722 Progress[8354:907] 4 1.112
2015-07-01 13:05:58.823 Progress[8354:907] 3 1.213
2015-07-01 13:05:58.924 Progress[8354:907] 2 1.314
2015-07-01 13:05:59.024 Progress[8354:907] 1 1.415
2015-07-01 13:05:59.125 Progress[8354:907] 0 1.515
Note that the performSelector:afterDelay method has about 1 millisecond of slippage on each event. The total slippage was 15 milliseconds. The device screen update rate is 60 frames/sec, which is 16.7 msec/frame. So the total slippage was less than one frame time, and won't be noticeable to the user.
As rmaddy pointed out in the comments, using an NSTimer allows you to avoid most of the slippage. However, the last timer event could still slip by an arbitrary amount of time.

CloudKit records saving progress

I want to save Event and Image (for event) records. I want to show uploading progress in UI.
Event is little object with text and location.
Image is big object with photo as UIImage.
Image record is first item in array, event is second.
I create CKModifyRecordsOperation and set two CKRecord objects to recordsToSave
Than I set perRecordProgressBlock:
[operation setPerRecordProgressBlock:^(CKRecord *record, double progress) {
NSLog(#"#record: %# progress: %f", record.recordType, progress);
}];
And perRecordCompletionBlock:
[operation setPerRecordCompletionBlock:^(CKRecord *record, NSError *error) {
NSLog(#"#recordSaved: %# e: %#", record.recordType, error);
}];
I expect to see a lot of rows with progress for two records like:
#record: ImageRecord progress: 0.050000
#record: ImageRecord progress: 0.100000
#record: ImageRecord progress: 0.150000
...
#record: ImageRecord progress: 1.000000
#recordSaved: ImageRecord e: (null)
#record: EventRecord progress: 0.050000
...
#record: EventRecord progress: 1.000000
#recordSaved: EventRecord e: (null)
But really in console output I see:
#record: ImageRecord progress: 0.000000
#record: ImageRecord progress: 0.447357
#record: ImageRecord progress: 1.000000
#record: ImageRecord progress: 1.000000
#recordSaved: Event e: (null)
#recordSaved: ImageRecord e: (null)
What should I do?
The documentation for the CKModifyRecordOperation states:
The operation object executes this block zero or more times for each record in the recordsToSave property.
So if the save action for an object takes little time, then it could happen that you won't get a progress callback. As far as I know there is no way to influence the frequency of progress notifications.

Resources