我正在开发一个音频项目,并且对 AudioQueueGetCurrentTime() 检索到的时间戳的含义有疑问。
根据 Apple 开发人员文档,以下计算给出了正在播放的音频时间(自 AudioQueueStart 以来):
- (Float64) GetCurrentTime {
AudioTimeStamp c;
AudioQueueGetCurrentTime(playState.queue, NULL, &c, NULL);
return c.mSampleTime / _av->audio.sample_rate;
}
但是,在我正在做的一个项目中,我注意到AudioQueue的fillAudioBuffer回调函数内部有以下代码:
static void fillAudioBuffer(AudioQueueRef queue, AudioQueueBufferRef buffer){
int lengthCopied = INT32_MAX;
int dts= 0;
int isDone = 0;
buffer->mAudioDataByteSize = 0;
buffer->mPacketDescriptionCount = 0;
OSStatus err = 0;
AudioTimeStamp bufferStartTime;
AudioQueueGetCurrentTime(queue, NULL, &bufferStartTime, NULL);
while(buffer->mPacketDescriptionCount < numPacketsToRead && lengthCopied > 0){
if (buffer->mAudioDataByteSize) {
break;
}
lengthCopied = getNextAudio(_av,buffer->mAudioDataBytesCapacity-buffer->mAudioDataByteSize, (uint8_t*)buffer->mAudioData+buffer->mAudioDataByteSize,&dts,&isDone);
if(!lengthCopied || isDone) break;
if(aqStartDts < 0) aqStartDts = dts;
if (dts>0) currentDts = dts;
if(buffer->mPacketDescriptionCount ==0){
bufferStartTime.mFlags = kAudioTimeStampSampleTimeValid;
bufferStartTime.mSampleTime = (Float64)(dts-aqStartDts) * _av->audio.frame_size;
if (bufferStartTime.mSampleTime <0 ) bufferStartTime.mSampleTime = 0;
PMSG2("AQHandler.m fillAudioBuffer: DTS for %x: %lf time base: %lf StartDTS: %d\n", (unsigned int)buffer, bufferStartTime.mSampleTime, _av->audio.time_base, aqStartDts);
}
buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mStartOffset = buffer->mAudioDataByteSize;
buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mDataByteSize = lengthCopied;
buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mVariableFramesInPacket = _av->audio.frame_size;
buffer->mPacketDescriptionCount++;
buffer->mAudioDataByteSize += lengthCopied;
}
#ifdef DEBUG
int audioBufferCount, audioBufferTotal, videoBufferCount, videoBufferTotal;
bufferCheck(_av,&videoBufferCount, &videoBufferTotal, &audioBufferCount, &audioBufferTotal);
PMSG2("AQHandler.m fillAudioBuffer: Video Buffer: %d/%d Audio Buffer: %d/%d\n", videoBufferCount, videoBufferTotal, audioBufferCount, audioBufferTotal);
PMSG2("AQHandler.m fillAudioBuffer: Bytes copied for buffer 0x%x: %d\n",(unsigned int)buffer, (int)buffer->mAudioDataByteSize );
#endif
if(buffer->mAudioDataByteSize){
if(err=AudioQueueEnqueueBufferWithParameters(queue, buffer, 0, NULL, 0, 0, 0, NULL, &bufferStartTime, NULL))
{
#ifdef DEBUG
char sErr[10];
PMSG2(@"AQHandler.m fillAudioBuffer: Could not enqueue buffer 0x%x: %d %s.", buffer, err, FormatError(sErr, err));
#endif
}
}
}
根据
AudioQueueEnqueueBufferWithParameters
的文档和作者使用的变量命名,bufferStartTime
似乎代表新填充的音频缓冲区开始播放的时间,即队列中当前所有音频播放完毕的时间然后新的音频开始。这种解释表明 bufferStartTime
与当前正在播放的音频的时间不同。
我已经浏览了很多相关的问题,但我仍然有一些疑问..我目前正在修复我的项目中的音视频同步问题,并且Apple开发者文档(或者可能是我的搜索)中没有太多详细信息缺乏技能)。
有人可以澄清在这种情况下 AudioQueueGetCurrentTime() 返回的时间戳的确切含义吗?是当前音频结束播放的时间,还是新音频开始播放的时间?任何详细解释这一点的其他资源或文档也将不胜感激。
您想知道的代码实际上并没有使用
AudioQueueGetCurrentTime()
返回的时间,尽管它有时会覆盖然后记录结果。
我将 this doco 解释为
AudioQueueGetCurrentTime
应返回 AudioQueue
输出(或捕获,如果您使用输入变体)的样本数,或者如果该数量为负数,则返回 中的样本数队列计划开始的未来(事实上AudioQueueStart()
确实有一个可选的开始时间,所以这是令人放心的一致)。
负时间戳恶作剧让我相信这不是
AudioQueue
实际消耗的样本数量,但这没关系,因为你已经知道你提供了多少样本(可能是代码中的 dts-aqStartDts
) ).