зеркало из https://github.com/mozilla/gecko-dev.git
Bug 910897 - Use MP3FrameParser in DirectShow in order to calculate the duration. r=padenot
This commit is contained in:
Родитель
c3c6d3fde3
Коммит
bd28d7d80f
|
@ -75,7 +75,7 @@ public:
|
|||
// Sets the duration of the media in microseconds. The MediaDecoder
|
||||
// fires a durationchange event to its owner (e.g., an HTML audio
|
||||
// tag).
|
||||
virtual void UpdateMediaDuration(int64_t aDuration) = 0;
|
||||
virtual void UpdateEstimatedMediaDuration(int64_t aDuration) = 0;
|
||||
|
||||
// Set the media as being seekable or not.
|
||||
virtual void SetMediaSeekable(bool aMediaSeekable) = 0;
|
||||
|
|
|
@ -109,7 +109,7 @@ BufferDecoder::SetMediaDuration(int64_t aDuration)
|
|||
}
|
||||
|
||||
void
|
||||
BufferDecoder::UpdateMediaDuration(int64_t aDuration)
|
||||
BufferDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
|
||||
void UpdateMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
|
||||
void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -1272,10 +1272,14 @@ void MediaDecoder::SetMediaDuration(int64_t aDuration)
|
|||
GetStateMachine()->SetDuration(aDuration);
|
||||
}
|
||||
|
||||
void MediaDecoder::UpdateMediaDuration(int64_t aDuration)
|
||||
void MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mPlayState <= PLAY_STATE_LOADING) {
|
||||
return;
|
||||
}
|
||||
NS_ENSURE_TRUE_VOID(GetStateMachine());
|
||||
GetStateMachine()->UpdateDuration(aDuration);
|
||||
GetStateMachine()->UpdateEstimatedDuration(aDuration);
|
||||
}
|
||||
|
||||
void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {
|
||||
|
|
|
@ -497,8 +497,18 @@ public:
|
|||
// from a content header. Must be called from the main thread only.
|
||||
virtual void SetDuration(double aDuration);
|
||||
|
||||
// Sets the initial duration of the media. Called while the media metadata
|
||||
// is being read and the decode is being setup.
|
||||
void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
void UpdateMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
// Updates the media duration. This is called while the media is being
|
||||
// played, calls before the media has reached loaded metadata are ignored.
|
||||
// The duration is assumed to be an estimate, and so a degree of
|
||||
// instability is expected; if the incoming duration is not significantly
|
||||
// different from the existing duration, the change request is ignored.
|
||||
// If the incoming duration is significantly different, the duration is
|
||||
// changed, this causes a durationchanged event to fire to the media
|
||||
// element.
|
||||
void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
||||
|
||||
// Set a flag indicating whether seeking is supported
|
||||
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
||||
|
|
|
@ -118,6 +118,12 @@ PR_STATIC_ASSERT(QUICK_BUFFERING_LOW_DATA_USECS <= AMPLE_AUDIO_USECS);
|
|||
// This value has been chosen empirically.
|
||||
static const uint32_t AUDIOSTREAM_MIN_WRITE_BEFORE_START_USECS = 200000;
|
||||
|
||||
// The amount of instability we tollerate in calls to
|
||||
// MediaDecoderStateMachine::UpdateEstimatedDuration(); changes of duration
|
||||
// less than this are ignored, as they're assumed to be the result of
|
||||
// instability in the duration estimation.
|
||||
static const int64_t ESTIMATED_DURATION_FUZZ_FACTOR_USECS = USECS_PER_S / 2;
|
||||
|
||||
static TimeDuration UsecsToDuration(int64_t aUsecs) {
|
||||
return TimeDuration::FromMilliseconds(static_cast<double>(aUsecs) / USECS_PER_MS);
|
||||
}
|
||||
|
@ -1444,9 +1450,12 @@ void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
|
|||
}
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::UpdateDuration(int64_t aDuration)
|
||||
void MediaDecoderStateMachine::UpdateEstimatedDuration(int64_t aDuration)
|
||||
{
|
||||
if (aDuration != GetDuration()) {
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
int64_t duration = GetDuration();
|
||||
if (aDuration != duration &&
|
||||
abs(aDuration - duration) > ESTIMATED_DURATION_FUZZ_FACTOR_USECS) {
|
||||
SetDuration(aDuration);
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DurationChanged);
|
||||
|
|
|
@ -160,9 +160,12 @@ public:
|
|||
// aEndTime is in microseconds.
|
||||
void SetMediaEndTime(int64_t aEndTime);
|
||||
|
||||
// Called from decode thread to update the duration. Can result in
|
||||
// a durationchangeevent. aDuration is in microseconds.
|
||||
void UpdateDuration(int64_t aDuration);
|
||||
// Called from main thread to update the duration with an estimated value.
|
||||
// The duration is only changed if its significantly different than the
|
||||
// the current duration, as the incoming duration is an estimate and so
|
||||
// often is unstable as more data is read and the estimate is updated.
|
||||
// Can result in a durationchangeevent. aDuration is in microseconds.
|
||||
void UpdateEstimatedDuration(int64_t aDuration);
|
||||
|
||||
// Functions used by assertions to ensure we're calling things
|
||||
// on the appropriate threads.
|
||||
|
|
|
@ -36,12 +36,14 @@ GetDirectShowLog() {
|
|||
|
||||
DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder)
|
||||
: MediaDecoderReader(aDecoder),
|
||||
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
|
||||
#ifdef DEBUG
|
||||
mRotRegister(0),
|
||||
#endif
|
||||
mNumChannels(0),
|
||||
mAudioRate(0),
|
||||
mBytesPerSample(0)
|
||||
mBytesPerSample(0),
|
||||
mDuration(0)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||
MOZ_COUNT_CTOR(DirectShowReader);
|
||||
|
@ -366,4 +368,21 @@ DirectShowReader::OnDecodeThreadFinish()
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
void
|
||||
DirectShowReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
|
||||
int64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mDuration) {
|
||||
mDuration = duration;
|
||||
MOZ_ASSERT(mDecoder);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mDecoder->UpdateEstimatedMediaDuration(mDuration);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Windows.h" // HRESULT, DWORD
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "MP3FrameParser.h"
|
||||
|
||||
class IGraphBuilder;
|
||||
class IMediaControl;
|
||||
|
@ -70,6 +71,10 @@ public:
|
|||
void OnDecodeThreadStart() MOZ_OVERRIDE;
|
||||
void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
||||
|
||||
void NotifyDataArrived(const char* aBuffer,
|
||||
uint32_t aLength,
|
||||
int64_t aOffset) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
// Calls mAudioQueue.Finish(), and notifies the filter graph that playback
|
||||
|
@ -91,6 +96,11 @@ private:
|
|||
// The graph will block while this is blocked, i.e. it will pause decoding.
|
||||
RefPtr<AudioSinkFilter> mAudioSinkFilter;
|
||||
|
||||
// Some MP3s are variable bitrate, so DirectShow's duration estimation
|
||||
// can make its duration estimation based on the wrong bitrate. So we parse
|
||||
// the MP3 frames to get a more accuate estimate of the duration.
|
||||
MP3FrameParser mMP3FrameParser;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Used to add/remove the filter graph to the Running Object Table. You can
|
||||
// connect GraphEdit/GraphStudio to the graph to observe and/or debug its
|
||||
|
@ -106,6 +116,9 @@ private:
|
|||
|
||||
// Number of bytes per sample. Can be either 1 or 2.
|
||||
uint32_t mBytesPerSample;
|
||||
|
||||
// Duration of the stream, in microseconds.
|
||||
int64_t mDuration;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -632,7 +632,7 @@ void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_
|
|||
|
||||
MOZ_ASSERT(mDecoder);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mDecoder->UpdateMediaDuration(mDurationUs);
|
||||
mDecoder->UpdateEstimatedMediaDuration(mDurationUs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче