2012-01-23 2 views
0

네트워크를 통해 파일을 스트리밍하는 오디오 응용 프로그램이 있습니다. 모든 것이 잘 작동하지만 한 가지. 백그라운드에서 다음 트랙을 자동으로 재생하려면 AudioQueueStop이 호출 된 후 CFReadStream이 초기화됩니다 (로그에서 볼 수 있음). 그러나 앱이 포 그라운드로 들어올 때까지 콜백이 호출되지 않습니다 (편집 : 실제로 한 번 호출 됨). 스트림 초기화에 대한 코드의 조각 :CFReadStream - 백그라운드에서 시작

//also tried main runloop just for test, no luck 
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); 

유선 것은 앱이 큐가 정지 된 후, 스트림이 초기화되고 작동하지만 콜백이 제대로 스트림이 전경 모드로 초기화 된 경우에만 호출된다는 것이다 .

CFReadStreamSetClient(stream, 
         kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, 
         MyReadStreamCallBack, 
         &context); 

반면에 응용 프로그램이 백그라운드로하고 다음 트랙은 같은과 (그러나 앱 위임에 자동으로되지 트리거 될 때, 콜백이 호출됩니다 여기에 콜백 코드의 조각이다 기능).

이 세 가지 경우의 차이점을 완전히 이해하지 못했습니다. 도움을 받으십시오.

편집. MyReadStreamCallBack 한 번만라고하면서

OSStatus status = AudioFileStreamOpen(self, MyAudioListener ... 

MyAudioListener 콜백이 호출되고.

ReadStream 콜백이 가장 자주 한 번도 호출되지 않는 2

편집, 한 번 내가 볼 수 있었는지의 최대이다.

한편

, 그리고 그 후 이전 AudioQueue이을 중지하고 다음 트랙 다음, 다른 AudioQueue이 열립니다 로컬 파일이다, 무슨 일이 일어나고 있는지의 오해로 나를 드라이브, 그것은 파일을 읽고 AudioFileReadPackets을 사용하면 다음 트랙 재생을 시작하기 위해 백그라운드에서 응용 프로그램을 깨울 필요가 없습니다. 은 백그라운드에서을 재생합니다.

답변

1

배경 대기 모드의 경우 오디오 대기열이 백그라운드에서 계속 실행됩니다. 하지만 일단 멈 추면 오디오 대기열이 백그라운드에서 실행되지 않는 것 같습니다. 하나의 콜백은 버퍼를 프라임하는 것일 뿐이므로 대기열은 포 그라운드로 가져온 직후에 시작할 수 있습니다.

내가 찾은 유일한 해결책은 배경에있을 때 이전 오디오 대기열을 멈추지 않고 이전 오디오 대기열에 새 오디오 데이터를 공급하는 것입니다. 그 사이에 콜백을 언더 플로우하지 않고 실행 중입니다.

+0

의 AudioQueue를 시작하고, 백그라운드에서 작동하는 이유의 의견 다음 트랙이 로컬에 저장되어있는 경우 비록 : 큐가 시작되면 내 솔루션 여기에 초기화 시작된 백그라운드 작업을 종료했다 다른 스트리머가 사용됩니다 (네트워크 콜백을 기다리지 않고 재귀 AudioFileReadPackets를 대신 사용합니다). –

+0

아마도 추측 할 만하지만 다음 트랙의 오디오 데이터를 즉시 사용할 수 있고 AQ가 실제로 완전히 멈추기 전에 (멈추라는 요청과 반대되는 경우) 실제로 멈추지 않습니다. – hotpaw2

+0

큰 도움이 참으로, 콜백이 버퍼 중 하나를 채우기에 충분한 데이터를 받고 AudioQueue를 시작할 때까지 네트워크 스 트리머의 백그라운드 작업을 추가하는 것으로 끝났습니다 (AudioQueueStart는 아직 시작되지 않았습니다. 재생할 데이터가 없음). 관심있는 모든 사람들을위한 코드 체계가 뒤 따릅니다. –

0

현재 해결 방법은 새 대기열을 시작할 데이터가있을 때까지 대기 할 백그라운드 작업을 추가하는 것입니다 (대기열 w/o 데이터는 -50 오류가 발생하고 hw 디코더는 중단됩니다).이 같은 데이터의 다운로드 조각을 hanlde하는 데 사용 StreamEnqueueBuffer 기능이었다

// ...whatever we need to be happy 


// start the background job 
UIDevice* device = [UIDevice currentDevice]; 
BOOL isBackgroundSupported = NO; 
if ([device respondsToSelector:@selector(isMultitaskingSupported)]) 
    isBackgroundSupported = device.multitaskingSupported; 

if(isBackgroundSupported && waitForQueueToStartBackgroundTask == UIBackgroundTaskInvalid) { 
    waitForQueueToStartbackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     [[UIApplication sharedApplication] endBackgroundTask:waitForQueueToStartBackgroundTask]; 
     waitForQueueToStartBackgroundTask = UIBackgroundTaskInvalid; 
    }]; 
} 

// Open the stream 
if (!CFReadStreamOpen(stream)) { 

당신은 천국을해야 저를 들어, AudioQueueStart 호출 곳 :

의이 같은 뭔가 openNetworkStream 기능이있다 트리머 재생 기능에 있다고 가정 해 봅시다 버퍼를 재생할 준비가되었거나 파일의 끝에 도달하면 (AudioQueueEnqueueBuffer),이 함수는 AudioQueue의 초기 시작 자이기도하므로 시작하기 위해 버퍼를 채워야합니다.

많은 도움이 될 것입니다
OSStatus StreamEnqueueBuffer(AudioNetworkStreamer* aStreamer) 

// wahtever you need to be happy with a filled buffer 

if (!aStreamer->didStart) {  // start the queue if it has not been started already 
    aStreamer->isBuffering = NO; 
    [aStreamer startQueue]; 

    UIDevice* device = [UIDevice currentDevice]; 
    BOOL isBackgroundSupported = NO; 
    if ([device respondsToSelector:@selector(isMultitaskingSupported)]) 
     isBackgroundSupported = device.multitaskingSupported; 

    if(isBackgroundSupported && aStreamer->waitForQueueToStartBackgroundTask == UIBackgroundTaskInvalid) { 
     [[UIApplication sharedApplication] endBackgroundTask:aStreamer->waitForQueueToStartBackgroundTask]; 
     aStreamer->waitForQueueToStartBackgroundTask = UIBackgroundTaskInvalid; 
    } 
} 

    // nandle mutexes, flags ... 
관련 문제