Bug 670055 - Seek video to exact audio sample. r=kinetik

This commit is contained in:
Chris Pearce 2011-07-09 13:10:40 +12:00
Родитель 371b57bace
Коммит 68f912bb40
1 изменённых файлов: 48 добавлений и 5 удалений

Просмотреть файл

@ -310,6 +310,10 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
if (HasAudio()) {
// Decode audio forward to the seek target.
PRInt64 targetSample = 0;
if (!UsecsToSamples(aTarget, mInfo.mAudioRate, targetSample)) {
return NS_ERROR_FAILURE;
}
PRBool eof = PR_FALSE;
while (HasAudio() && !eof) {
while (!eof && mAudioQueue.GetSize() == 0) {
@ -322,14 +326,53 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
}
}
}
nsAutoPtr<SoundData> audio(mAudioQueue.PeekFront());
if (audio && audio->mTime + audio->mDuration <= aTarget) {
mAudioQueue.PopFront();
const SoundData* audio = mAudioQueue.PeekFront();
if (!audio)
break;
PRInt64 startSample = 0;
if (!UsecsToSamples(audio->mTime, mInfo.mAudioRate, startSample)) {
return NS_ERROR_FAILURE;
}
if (startSample + audio->mSamples <= targetSample) {
// Our seek target lies after the samples in this SoundData. Pop it
// off the queue, and keep decoding forwards.
delete mAudioQueue.PopFront();
audio = nsnull;
} else {
audio.forget();
continue;
}
// The seek target lies somewhere in this SoundData's samples, strip off
// any samples which lie before the seek target, so we'll begin playback
// exactly at the seek target.
NS_ASSERTION(targetSample >= startSample, "Target must at or be after data start.");
NS_ASSERTION(startSample + audio->mSamples > targetSample, "Data must end after target.");
PRInt64 samplesToPrune = targetSample - startSample;
if (samplesToPrune > audio->mSamples) {
// We've messed up somehow. Don't try to trim samples, the |samples|
// variable below will overflow.
NS_WARNING("Can't prune more samples that we have!");
break;
}
PRUint32 samples = audio->mSamples - static_cast<PRUint32>(samplesToPrune);
PRUint32 channels = audio->mChannels;
nsAutoArrayPtr<SoundDataValue> audioData(new SoundDataValue[samples * channels]);
memcpy(audioData.get(),
audio->mAudioData.get() + (samplesToPrune * channels),
samples * channels * sizeof(SoundDataValue));
PRInt64 duration;
if (!SamplesToUsecs(samples, mInfo.mAudioRate, duration)) {
return NS_ERROR_FAILURE;
}
nsAutoPtr<SoundData> data(new SoundData(audio->mOffset,
aTarget,
duration,
samples,
audioData.forget(),
channels));
delete mAudioQueue.PopFront();
mAudioQueue.PushFront(data.forget());
break;
}
}
return NS_OK;