nsRefPtr<MediaDecoderReader::SeekPromise> AppleMP3Reader::Seek(int64_t aTime, int64_t aEndTime) { MOZ_ASSERT(OnTaskQueue()); // Find the exact frame/packet that contains |aTime|. mCurrentAudioFrame = aTime * mAudioSampleRate / USECS_PER_S; SInt64 packet = mCurrentAudioFrame / mAudioFramesPerCompressedPacket; // |AudioFileStreamSeek| will pass back through |byteOffset| the byte offset // into the stream it expects next time it reads. SInt64 byteOffset; UInt32 flags = 0; OSStatus rv = AudioFileStreamSeek(mAudioFileStream, packet, &byteOffset, &flags); if (rv) { LOGE("Couldn't seek demuxer. Error code %x\n", rv); return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } LOGD("computed byte offset = %lld; estimated = %s\n", byteOffset, (flags & kAudioFileStreamSeekFlag_OffsetIsEstimated) ? "YES" : "NO"); mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, byteOffset); ResetDecode(); return SeekPromise::CreateAndResolve(aTime, __func__); }
void Audio_Stream::seekToTime(unsigned newSeekTime) { unsigned duration = durationInSeconds(); if (!(duration > 0)) { return; } if (state() == SEEKING) { return; } else { setState(SEEKING); } m_seekTime = newSeekTime; double offset = (double)newSeekTime / (double)duration; UInt64 seekByteOffset = m_dataOffset + offset * (contentLength() - m_dataOffset); HTTP_Stream_Position position; position.start = seekByteOffset; position.end = contentLength(); double packetDuration = m_srcFormat.mFramesPerPacket / m_srcFormat.mSampleRate; if (packetDuration > 0 && bitrate() > 0) { UInt32 ioFlags = 0; SInt64 packetAlignedByteOffset; SInt64 seekPacket = floor((double)newSeekTime / packetDuration); OSStatus err = AudioFileStreamSeek(m_audioFileStream, seekPacket, &packetAlignedByteOffset, &ioFlags); if (!err) { position.start = packetAlignedByteOffset + m_dataOffset; } } close(); AS_TRACE("Seeking position %llu\n", position.start); if (m_httpStream->open(position)) { AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__); m_httpStreamRunning = true; } else { AS_TRACE("%s: failed to open the fHTTP stream\n", __PRETTY_FUNCTION__); setState(FAILED); } }
SInt64 DZAudioQueuePlayer::seek(float time) { // Cannot seek if parameters not available or parser/queue not ready. if (this->_format.mSampleRate <= 0 || this->_format.mFramesPerPacket <= 0) { return -1; } if (this->_parser == NULL || this->_queue == NULL || this->_status == DZAudioQueuePlayerStatus_NotReady || this->_status == DZAudioQueuePlayerStatus_Error) { return -1; } // Get audio data offset. SInt64 dataOffset = 0; UInt32 propertySize = sizeof(dataOffset); if (dzDebugError(AudioFileStreamGetProperty(this->_parser, kAudioFileStreamProperty_DataOffset, &propertySize, &dataOffset), "Fail to get stream data offset.")) { return -1; } // Reset audio queue to clear the current queue buffer. if (dzDebugError(AudioQueueReset(this->_queue), "Fail to reset audio queue.")) { return -1; } // Get audio queue current time. AudioTimeStamp timeStamp; if (this->_status == DZAudioQueuePlayerStatus_ReadyToStart) { timeStamp.mSampleTime = 0; } else if (dzDebugError(AudioQueueGetCurrentTime(this->_queue, NULL, &(timeStamp), NULL), "Fail to get audio queue current time.")) { return -1; } // Calculate packet offset and so the byte offset. SInt64 packetOffset = round(time * this->_format.mSampleRate / this->_format.mFramesPerPacket); SInt64 byteOffset = 0; UInt32 ioFlag = 0; if (dzDebugError(AudioFileStreamSeek(this->_parser, packetOffset, &byteOffset, &ioFlag), "Fail to seek in audio file stream.")) { return -1; } this->_timeAmendment = time - timeStamp.mSampleTime / this->_format.mSampleRate; return byteOffset + dataOffset; }
void AppleMP3Reader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) { MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread"); NS_ASSERTION(aStartTime < aEndTime, "Seeking should happen over a positive range"); // Find the exact frame/packet that contains |aTime|. mCurrentAudioFrame = aTime * mAudioSampleRate / USECS_PER_S; SInt64 packet = mCurrentAudioFrame / mAudioFramesPerCompressedPacket; // |AudioFileStreamSeek| will pass back through |byteOffset| the byte offset // into the stream it expects next time it reads. SInt64 byteOffset; UInt32 flags = 0; OSStatus rv = AudioFileStreamSeek(mAudioFileStream, packet, &byteOffset, &flags); if (rv) { LOGE("Couldn't seek demuxer. Error code %x\n", rv); GetCallback()->OnSeekCompleted(NS_ERROR_FAILURE); return; } LOGD("computed byte offset = %lld; estimated = %s\n", byteOffset, (flags & kAudioFileStreamSeekFlag_OffsetIsEstimated) ? "YES" : "NO"); mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, byteOffset); ResetDecode(); GetCallback()->OnSeekCompleted(NS_OK); }