Skip to content

Commit

Permalink
修复可能出现416的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
changsanjiang committed Dec 27, 2021
1 parent 6ac723f commit 3ba3ffa
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 28 deletions.
2 changes: 1 addition & 1 deletion SJAudioPlayer.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'SJAudioPlayer'
s.version = '1.0.2'
s.version = '1.0.3'
s.summary = 'iOS MP3 Audio Player using AVAudioEngine.'

# This description is used to generate tags and improve search results.
Expand Down
3 changes: 3 additions & 0 deletions SJAudioPlayer/Core/Common/APError.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef NS_ENUM(NSUInteger, APErrorCode) {
APContentReaderErrorCouldNotOpenFile,
APContentReaderErrorFileFailedToSeek,
APContentReaderErrorFileFailedToReadData,
APContentReaderErrorHTTPResponseInvalid,

APContentParserErrorCouldNotOpenStream,
APContentParserErrorFailedToParseBytes,
Expand All @@ -41,6 +42,8 @@ FOUNDATION_EXTERN NSString *const APErrorUserInfoAudioEngineKey;
FOUNDATION_EXTERN NSString *const APErrorUserInfoExceptionKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoFileTotalLengthKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoFileSeekOffsetKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoHTTPTaskKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoHTTPResponseKey;
FOUNDATION_EXTERN NSString *const APErrorUserInfoErrorStatusKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoInputFormatKey;
FOUNDATION_EXPORT NSString *const APErrorUserInfoOutputFormatKey;
Expand Down
4 changes: 4 additions & 0 deletions SJAudioPlayer/Core/Common/APError.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
NSString *const APErrorUserInfoExceptionKey = @"exception";
NSString *const APErrorUserInfoFileTotalLengthKey = @"totalLength";
NSString *const APErrorUserInfoFileSeekOffsetKey = @"offset";
NSString *const APErrorUserInfoHTTPTaskKey = @"task";
NSString *const APErrorUserInfoHTTPResponseKey = @"response";
NSString *const APErrorUserInfoErrorStatusKey = @"status";
NSString *const APErrorUserInfoInputFormatKey = @"inputFormat";
NSString *const APErrorUserInfoOutputFormatKey = @"outputFormat";
Expand Down Expand Up @@ -102,6 +104,8 @@ + (NSError *)ap_errorWithCode:(APErrorCode)code userInfo:(NSDictionary *)userInf
return @"Failed to seek";
case APContentReaderErrorFileFailedToReadData:
return @"Failed to read data";
case APContentReaderErrorHTTPResponseInvalid:
return @"Invalid HTTP response";
case APContentParserErrorCouldNotOpenStream:
return @"Could not open stream for parsing";
case APContentParserErrorFailedToParseBytes:
Expand Down
5 changes: 5 additions & 0 deletions SJAudioPlayer/Core/Item/Core/Parser/APAudioContentParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ - (UInt64)_expectedOffsetForTime:(NSTimeInterval)time framePosition:(AVAudioFram
if ( startPosition != NULL ) {
*startPosition = framePosition;
}

UInt64 countOfBytesTotalLength = _reader.countOfBytesTotalLength;
if ( nBytesOffset > countOfBytesTotalLength ) {
nBytesOffset = countOfBytesTotalLength;
}
return nBytesOffset;
}

Expand Down
76 changes: 49 additions & 27 deletions SJAudioPlayer/Core/Item/Core/Parser/Core/APAudioContentReader.m
Original file line number Diff line number Diff line change
Expand Up @@ -391,10 +391,15 @@ @implementation APAudioContentFileProvider {
NSMutableArray<APAudioContentFile *> *_files;
}
static dispatch_semaphore_t ap_semaphore;
static NSString *ap_cacheFolder;
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ap_semaphore = dispatch_semaphore_create(1);
ap_cacheFolder = [NSTemporaryDirectory() stringByAppendingPathComponent:@"com.APAudioPlaybackController.cache"];
if ( [NSFileManager.defaultManager fileExistsAtPath:ap_cacheFolder] ) {
[NSFileManager.defaultManager removeItemAtPath:ap_cacheFolder error:NULL];
}
});
}

Expand Down Expand Up @@ -436,8 +441,8 @@ - (nullable APAudioContentFile *)createFileAtOffset:(UInt64)offset error:(NSErro
int index = 0;
dispatch_semaphore_wait(ap_semaphore, DISPATCH_TIME_FOREVER);
while ( true ) {
NSString *path = [NSString stringWithFormat:@"com.APAudioPlaybackController.cache/%@/%d", foldername, index];
NSString *directory = [NSTemporaryDirectory() stringByAppendingPathComponent:path];
NSString *path = [NSString stringWithFormat:@"%@/%d", foldername, index];
NSString *directory = [ap_cacheFolder stringByAppendingPathComponent:path];
if ( [NSFileManager.defaultManager fileExistsAtPath:directory] ) {
index += 1;
continue;
Expand Down Expand Up @@ -518,6 +523,7 @@ @implementation APAudioContentDownloadLine {
NSDictionary *_Nullable _HTTPAdditionalHeaders;
APAudioContentDownloadItem *_Nullable _curItem; // 当前下载的项目
NSInteger _retryCount;
NSMutableDictionary<NSNumber *, NSError *> *_responseError;
}

static dispatch_semaphore_t ap_semaphore;
Expand All @@ -535,6 +541,7 @@ - (instancetype)initWithURL:(NSURL *)URL HTTPAdditionalHeaders:(NSDictionary *)H
_HTTPAdditionalHeaders = HTTPAdditionalHeaders;
_queue = queue;
_delegate = delegate;
_responseError = NSMutableDictionary.dictionary;
}
return self;
}
Expand Down Expand Up @@ -676,29 +683,39 @@ - (void)_cancel {
#pragma mark - APAudioContentDownloaderTaskDelegate

- (void)downloadTask:(NSURLSessionTask *)task didReceiveResponse:(NSHTTPURLResponse *)response {
APContentDownloadLineDebugLog(@"%@: <%p>.didReceiveData { task: %lu, response: %@ }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, response);

dispatch_sync(_queue, ^{
dispatch_async(_queue, ^{
if ( task.taskIdentifier != self->_curItem.task.taskIdentifier ) return;

if ( _countOfBytesTotalLength == 0 ) {
NSDictionary *responseHeaders = response.allHeaderFields;
NSString *bytes = responseHeaders[@"Content-Range"] ?: responseHeaders[@"content-range"];
if ( bytes.length != 0 ) {
NSString *prefix = @"bytes ";
NSString *rangeString = [bytes substringWithRange:NSMakeRange(prefix.length, bytes.length - prefix.length)];
NSArray<NSString *> *components = [rangeString componentsSeparatedByString:@"-"];
_countOfBytesTotalLength = [components.lastObject.lastPathComponent longLongValue];
APContentDownloadLineDebugLog(@"%@: <%p>.didReceiveData { task: %lu, response: %@ }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, response);

if ( self->_countOfBytesTotalLength == 0 ) {
if ( response.statusCode == 206 ) {
NSDictionary *responseHeaders = response.allHeaderFields;
NSString *bytes = responseHeaders[@"Content-Range"] ?: responseHeaders[@"content-range"];
if ( bytes.length != 0 ) {
NSString *prefix = @"bytes ";
NSString *rangeString = [bytes substringWithRange:NSMakeRange(prefix.length, bytes.length - prefix.length)];
NSArray<NSString *> *components = [rangeString componentsSeparatedByString:@"-"];
self->_countOfBytesTotalLength = [components.lastObject.lastPathComponent longLongValue];
}
}
else {
self->_responseError[@(task.taskIdentifier)] = [NSError ap_errorWithCode:APContentReaderErrorHTTPResponseInvalid userInfo:@{
APErrorUserInfoHTTPTaskKey : task,
APErrorUserInfoHTTPResponseKey : response,
NSLocalizedDescriptionKey : APErrorLocalizedDescription(APContentReaderErrorHTTPResponseInvalid)
}];
[task cancel];
}
}
});
}

- (void)downloadTask:(NSURLSessionTask *)task didReceiveData:(NSData *)data {
APContentDownloadLineDebugLog(@"%@: <%p>.didReceiveData { task: %lu, length: %lu }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, (unsigned long)data.length);

dispatch_async(_queue, ^{
if ( task.taskIdentifier != self->_curItem.task.taskIdentifier ) return;
if ( self->_responseError[@(task.taskIdentifier)] != nil ) return;
APContentDownloadLineDebugLog(@"%@: <%p>.didReceiveData { task: %lu, length: %lu }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, (unsigned long)data.length);

NSError *error = nil;
APAudioContentFile *file = self->_curItem.file;
if ( file != nil && ![file writeData:data error:&error] ) {
Expand All @@ -710,16 +727,21 @@ - (void)downloadTask:(NSURLSessionTask *)task didReceiveData:(NSData *)data {
}

- (void)downloadTask:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
APContentDownloadLineDebugLog(@"%@: <%p>.didCompleteWithError { task: %lu, error: %@ }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, error);

dispatch_sync(_queue, ^{
dispatch_async(_queue, ^{
if ( task.taskIdentifier != self->_curItem.task.taskIdentifier ) return;
NSError *mError = error;
if ( self->_responseError[@(task.taskIdentifier)] != nil ) {
mError = self->_responseError[@(task.taskIdentifier)];
self->_responseError[@(task.taskIdentifier)] = nil;
}
APContentDownloadLineDebugLog(@"%@: <%p>.didCompleteWithError { task: %lu, error: %@ }\n", NSStringFromClass(self.class), self, (unsigned long)task.taskIdentifier, mError);

APAudioContentFile *file = self->_curItem.file;
if ( error != nil ) {
if ( error.code != NSURLErrorCancelled ) {
if ( _retryCount < APDownload_MaxRetryCount ) {
_retryCount += 1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(APDownload_RetryAfter * NSEC_PER_SEC)), _queue, ^{
if ( mError != nil ) {
if ( mError.code != NSURLErrorCancelled ) {
if ( self->_retryCount < APDownload_MaxRetryCount ) {
self->_retryCount += 1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(APDownload_RetryAfter * NSEC_PER_SEC)), self->_queue, ^{
if ( self->_curItem.task.taskIdentifier != task.taskIdentifier ) return;
#ifdef DEBUG
printf("%s.retry: %ld\n", NSStringFromClass(self.class).UTF8String, (long)self->_retryCount);
Expand All @@ -728,9 +750,9 @@ - (void)downloadTask:(NSURLSessionTask *)task didCompleteWithError:(NSError *)er
});
}
else {
_curItem = nil;
_retryCount = 0;
[self _onError:error]; // error
self->_curItem = nil;
self->_retryCount = 0;
[self _onError:mError]; // error
}
}
return;
Expand Down

0 comments on commit 3ba3ffa

Please sign in to comment.