mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 910897 - Use MP3FrameParser in DirectShow in order to calculate the duration. r=padenot
This commit is contained in:
parent
c3c6d3fde3
commit
bd28d7d80f
@ -75,7 +75,7 @@ public:
|
|||||||
// Sets the duration of the media in microseconds. The MediaDecoder
|
// Sets the duration of the media in microseconds. The MediaDecoder
|
||||||
// fires a durationchange event to its owner (e.g., an HTML audio
|
// fires a durationchange event to its owner (e.g., an HTML audio
|
||||||
// tag).
|
// tag).
|
||||||
virtual void UpdateMediaDuration(int64_t aDuration) = 0;
|
virtual void UpdateEstimatedMediaDuration(int64_t aDuration) = 0;
|
||||||
|
|
||||||
// Set the media as being seekable or not.
|
// Set the media as being seekable or not.
|
||||||
virtual void SetMediaSeekable(bool aMediaSeekable) = 0;
|
virtual void SetMediaSeekable(bool aMediaSeekable) = 0;
|
||||||
|
@ -109,7 +109,7 @@ BufferDecoder::SetMediaDuration(int64_t aDuration)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BufferDecoder::UpdateMediaDuration(int64_t aDuration)
|
BufferDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
|
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;
|
void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
@ -1272,10 +1272,14 @@ void MediaDecoder::SetMediaDuration(int64_t aDuration)
|
|||||||
GetStateMachine()->SetDuration(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());
|
NS_ENSURE_TRUE_VOID(GetStateMachine());
|
||||||
GetStateMachine()->UpdateDuration(aDuration);
|
GetStateMachine()->UpdateEstimatedDuration(aDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {
|
void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {
|
||||||
|
@ -497,8 +497,18 @@ public:
|
|||||||
// from a content header. Must be called from the main thread only.
|
// from a content header. Must be called from the main thread only.
|
||||||
virtual void SetDuration(double aDuration);
|
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 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
|
// Set a flag indicating whether seeking is supported
|
||||||
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
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.
|
// This value has been chosen empirically.
|
||||||
static const uint32_t AUDIOSTREAM_MIN_WRITE_BEFORE_START_USECS = 200000;
|
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) {
|
static TimeDuration UsecsToDuration(int64_t aUsecs) {
|
||||||
return TimeDuration::FromMilliseconds(static_cast<double>(aUsecs) / USECS_PER_MS);
|
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);
|
SetDuration(aDuration);
|
||||||
nsCOMPtr<nsIRunnable> event =
|
nsCOMPtr<nsIRunnable> event =
|
||||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DurationChanged);
|
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DurationChanged);
|
||||||
|
@ -160,9 +160,12 @@ public:
|
|||||||
// aEndTime is in microseconds.
|
// aEndTime is in microseconds.
|
||||||
void SetMediaEndTime(int64_t aEndTime);
|
void SetMediaEndTime(int64_t aEndTime);
|
||||||
|
|
||||||
// Called from decode thread to update the duration. Can result in
|
// Called from main thread to update the duration with an estimated value.
|
||||||
// a durationchangeevent. aDuration is in microseconds.
|
// The duration is only changed if its significantly different than the
|
||||||
void UpdateDuration(int64_t aDuration);
|
// 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
|
// Functions used by assertions to ensure we're calling things
|
||||||
// on the appropriate threads.
|
// on the appropriate threads.
|
||||||
|
@ -36,12 +36,14 @@ GetDirectShowLog() {
|
|||||||
|
|
||||||
DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder)
|
DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder)
|
||||||
: MediaDecoderReader(aDecoder),
|
: MediaDecoderReader(aDecoder),
|
||||||
|
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mRotRegister(0),
|
mRotRegister(0),
|
||||||
#endif
|
#endif
|
||||||
mNumChannels(0),
|
mNumChannels(0),
|
||||||
mAudioRate(0),
|
mAudioRate(0),
|
||||||
mBytesPerSample(0)
|
mBytesPerSample(0),
|
||||||
|
mDuration(0)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||||
MOZ_COUNT_CTOR(DirectShowReader);
|
MOZ_COUNT_CTOR(DirectShowReader);
|
||||||
@ -366,4 +368,21 @@ DirectShowReader::OnDecodeThreadFinish()
|
|||||||
CoUninitialize();
|
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
|
} // namespace mozilla
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "Windows.h" // HRESULT, DWORD
|
#include "Windows.h" // HRESULT, DWORD
|
||||||
#include "MediaDecoderReader.h"
|
#include "MediaDecoderReader.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "MP3FrameParser.h"
|
||||||
|
|
||||||
class IGraphBuilder;
|
class IGraphBuilder;
|
||||||
class IMediaControl;
|
class IMediaControl;
|
||||||
@ -70,6 +71,10 @@ public:
|
|||||||
void OnDecodeThreadStart() MOZ_OVERRIDE;
|
void OnDecodeThreadStart() MOZ_OVERRIDE;
|
||||||
void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void NotifyDataArrived(const char* aBuffer,
|
||||||
|
uint32_t aLength,
|
||||||
|
int64_t aOffset) MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Calls mAudioQueue.Finish(), and notifies the filter graph that playback
|
// 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.
|
// The graph will block while this is blocked, i.e. it will pause decoding.
|
||||||
RefPtr<AudioSinkFilter> mAudioSinkFilter;
|
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
|
#ifdef DEBUG
|
||||||
// Used to add/remove the filter graph to the Running Object Table. You can
|
// 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
|
// 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.
|
// Number of bytes per sample. Can be either 1 or 2.
|
||||||
uint32_t mBytesPerSample;
|
uint32_t mBytesPerSample;
|
||||||
|
|
||||||
|
// Duration of the stream, in microseconds.
|
||||||
|
int64_t mDuration;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -632,7 +632,7 @@ void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_
|
|||||||
|
|
||||||
MOZ_ASSERT(mDecoder);
|
MOZ_ASSERT(mDecoder);
|
||||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
mDecoder->UpdateMediaDuration(mDurationUs);
|
mDecoder->UpdateEstimatedMediaDuration(mDurationUs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user