Bug 1228939 - 1. add mSeekable to MediaInfo. 2. use MediaEventSource to notify the decoder when the media is not seekable. 3. remove unused code. r=jya.

This commit is contained in:
JW Wang 2015-12-02 15:42:32 +08:00
Родитель c257b89d86
Коммит e4cbe0c128
26 изменённых файлов: 45 добавлений и 125 удалений

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

@ -85,16 +85,6 @@ public:
NS_DispatchToMainThread(r);
}
// Set the media as being seekable or not.
virtual void SetMediaSeekable(bool aMediaSeekable) = 0;
void DispatchSetMediaSeekable(bool aMediaSeekable)
{
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &AbstractMediaDecoder::SetMediaSeekable, aMediaSeekable);
NS_DispatchToMainThread(r);
}
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;

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

@ -617,6 +617,7 @@ MediaDecoder::Shutdown()
mFirstFrameLoadedListener.Disconnect();
mOnPlaybackEvent.Disconnect();
mOnSeekingStart.Disconnect();
mOnMediaNotSeekable.Disconnect();
}
// Force any outstanding seek and byterange requests to complete
@ -728,6 +729,8 @@ MediaDecoder::SetStateMachineParameters()
AbstractThread::MainThread(), this, &MediaDecoder::OnPlaybackEvent);
mOnSeekingStart = mDecoderStateMachine->OnSeekingStart().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::SeekingStarted);
mOnMediaNotSeekable = mDecoderStateMachine->OnMediaNotSeekable().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnMediaNotSeekable);
}
void
@ -841,6 +844,7 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
aInfo->HasAudio(), aInfo->HasVideo());
SetMediaSeekable(aInfo->mMediaSeekable);
mInfo = aInfo.forget();
ConstructMediaTracks();

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

@ -471,7 +471,7 @@ public:
virtual void SetElementVisibility(bool aIsVisible) {}
// Set a flag indicating whether seeking is supported
virtual void SetMediaSeekable(bool aMediaSeekable) override;
void SetMediaSeekable(bool aMediaSeekable);
// Returns true if this media supports seeking. False for example for WebM
// files without an index and chained ogg files.
@ -804,6 +804,11 @@ private:
void OnPlaybackEvent(MediaEventType aEvent);
void OnMediaNotSeekable()
{
SetMediaSeekable(false);
}
MediaEventProducer<void> mDataArrivedEvent;
// The state machine object for handling the decoding. It is safe to
@ -927,6 +932,7 @@ protected:
MediaEventListener mOnPlaybackEvent;
MediaEventListener mOnSeekingStart;
MediaEventListener mOnMediaNotSeekable;
protected:
// Whether the state machine is shut down.

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

@ -239,10 +239,6 @@ public:
return &mBuffered;
}
// Indicates if the media is seekable.
// ReadMetada should be called before calling this method.
virtual bool IsMediaSeekable() = 0;
void DispatchSetStartTime(int64_t aStartTime)
{
RefPtr<MediaDecoderReader> self = this;
@ -279,6 +275,9 @@ public:
return mTimedMetadataEvent;
}
// Notified by the OggReader during playback when chained ogg is detected.
MediaEventSource<void>& OnMediaNotSeekable() { return mOnMediaNotSeekable; }
protected:
virtual ~MediaDecoderReader();
@ -369,6 +368,9 @@ protected:
// Used to send TimedMetadata to the listener.
TimedMetadataEventProducer mTimedMetadataEvent;
// Notify if this media is not seekable.
MediaEventProducer<void> mOnMediaNotSeekable;
private:
// Does any spinup that needs to happen on this task queue. This runs on a
// different thread than Init, and there should not be ordering dependencies

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

@ -1909,7 +1909,6 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
// Set mode to PLAYBACK after reading metadata.
mResource->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
mDecoder->DispatchSetMediaSeekable(mReader->IsMediaSeekable());
mInfo = aMetadata->mInfo;
mMetadataTags = aMetadata->mTags.forget();
RefPtr<MediaDecoderStateMachine> self = this;

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

@ -232,6 +232,10 @@ public:
return mMetadataManager.TimedMetadataEvent();
}
MediaEventSource<void>& OnMediaNotSeekable() {
return mReader->OnMediaNotSeekable();
}
MediaEventSourceExc<nsAutoPtr<MediaInfo>,
nsAutoPtr<MetadataTags>,
MediaDecoderEventVisibility>&

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

@ -65,7 +65,6 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
, mLastReportedNumDecodedFrames(0)
, mLayersBackendType(aLayersBackend)
, mInitDone(false)
, mSeekable(false)
, mIsEncrypted(false)
, mTrackDemuxersMayBlock(false)
, mHardwareAccelerationDisabled(false)
@ -324,7 +323,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
mInfo.mMetadataDuration = Some(TimeUnit::FromMicroseconds(duration));
}
mSeekable = mDemuxer->IsSeekable();
mInfo.mMediaSeekable = mDemuxer->IsSeekable();
if (!videoActive && !audioActive) {
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
@ -1331,7 +1330,7 @@ MediaFormatReader::Seek(int64_t aTime, int64_t aUnused)
MOZ_DIAGNOSTIC_ASSERT(mVideo.mTimeThreshold.isNothing());
MOZ_DIAGNOSTIC_ASSERT(mAudio.mTimeThreshold.isNothing());
if (!mSeekable) {
if (!mInfo.mMediaSeekable) {
LOG("Seek() END (Unseekable)");
return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}

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

@ -49,11 +49,6 @@ public:
RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aUnused) override;
bool IsMediaSeekable() override
{
return mSeekable;
}
protected:
void NotifyDataArrivedInternal() override;
@ -396,9 +391,6 @@ private:
// True if we've read the streams' metadata.
bool mInitDone;
MozPromiseHolder<MetadataPromise> mMetadataPromise;
// Accessed from multiple thread, in particular the MediaDecoderStateMachine,
// however the value doesn't change after reading the metadata.
bool mSeekable;
bool IsEncrypted()
{
return mIsEncrypted;

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

@ -400,6 +400,9 @@ public:
// a duration until we know the start time, so we need to track it separately.
media::NullableTimeUnit mUnadjustedMetadataEndTime;
// True if the media is seekable (i.e. supports random access).
bool mMediaSeekable = true;
EncryptionInfo mCrypto;
};

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

@ -48,12 +48,6 @@ public:
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold);
virtual bool IsMediaSeekable()
{
// not used
return true;
}
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags);
virtual RefPtr<SeekPromise>

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

@ -190,6 +190,7 @@ DirectShowReader::ReadMetadata(MediaInfo* aInfo,
DWORD seekCaps = 0;
hr = mMediaSeeking->GetCapabilities(&seekCaps);
mInfo.mMediaSeekable = SUCCEEDED(hr) && (AM_SEEKING_CanSeekAbsolute & seekCaps);
int64_t duration = mMP3FrameParser.GetDuration();
if (SUCCEEDED(hr)) {
@ -210,15 +211,6 @@ DirectShowReader::ReadMetadata(MediaInfo* aInfo,
return NS_OK;
}
bool
DirectShowReader::IsMediaSeekable()
{
DWORD seekCaps = 0;
HRESULT hr = mMediaSeeking->GetCapabilities(&seekCaps);
return ((AM_SEEKING_CanSeekAbsolute & seekCaps) ==
AM_SEEKING_CanSeekAbsolute);
}
inline float
UnsignedByteToAudioSample(uint8_t aValue)
{

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

@ -56,12 +56,8 @@ public:
protected:
void NotifyDataArrivedInternal() override;
public:
bool IsMediaSeekable() override;
private:
// Notifies the filter graph that playback is complete. aStatus is
// the code to send to the filter graph. Always returns false, so
// that we can just "return Finish()" from DecodeAudioData().

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

@ -468,12 +468,15 @@ nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
/* report the duration */
gint64 duration;
bool isMediaSeekable = false;
if (isMP3 && mMP3FrameParser.IsMP3()) {
// The MP3FrameParser has reported a duration; use that over the gstreamer
// reported duration for inter-platform consistency.
mUseParserDuration = true;
mLastParserDuration = mMP3FrameParser.GetDuration();
mInfo.mMetadataDuration.emplace(TimeUnit::FromMicroseconds(mLastParserDuration));
isMediaSeekable = true;
} else {
LOG(LogLevel::Debug, "querying duration");
// Otherwise use the gstreamer duration.
@ -488,9 +491,12 @@ nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
LOG(LogLevel::Debug, "have duration %" GST_TIME_FORMAT, GST_TIME_ARGS(duration));
duration = GST_TIME_AS_USECONDS (duration);
mInfo.mMetadataDuration.emplace(TimeUnit::FromMicroseconds(duration));
isMediaSeekable = true;
}
}
mInfo.mMediaSeekable = isMediaSeekable;
int n_video = 0, n_audio = 0;
g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, nullptr);
@ -518,28 +524,6 @@ nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
return NS_OK;
}
bool
GStreamerReader::IsMediaSeekable()
{
if (mUseParserDuration) {
return true;
}
gint64 duration;
#if GST_VERSION_MAJOR >= 1
if (gst_element_query_duration(GST_ELEMENT(mPlayBin), GST_FORMAT_TIME,
&duration)) {
#else
GstFormat format = GST_FORMAT_TIME;
if (gst_element_query_duration(GST_ELEMENT(mPlayBin), &format, &duration) &&
format == GST_FORMAT_TIME) {
#endif
return true;
}
return false;
}
nsresult GStreamerReader::CheckSupportedFormats()
{
bool done = false;

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

@ -54,11 +54,10 @@ public:
protected:
virtual void NotifyDataArrivedInternal() override;
public:
layers::ImageContainer* GetImageContainer() { return mDecoder->GetImageContainer(); }
virtual bool IsMediaSeekable() override;
private:
bool HasAudio() { return mInfo.HasAudio(); }
bool HasVideo() { return mInfo.HasVideo(); }

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

@ -486,20 +486,17 @@ nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
} else {
return NS_ERROR_FAILURE;
}
{
ReentrantMonitorAutoEnter mon(mMonitor);
mInfo.mMediaSeekable = !mIsChained;
}
*aInfo = mInfo;
return NS_OK;
}
bool
OggReader::IsMediaSeekable()
{
if (mIsChained) {
return false;
}
return true;
}
nsresult OggReader::DecodeVorbis(ogg_packet* aPacket) {
NS_ASSERTION(aPacket->granulepos != -1, "Must know vorbis granulepos!");
@ -712,7 +709,7 @@ void OggReader::SetChained(bool aIsChained) {
ReentrantMonitorAutoEnter mon(mMonitor);
mIsChained = aIsChained;
}
mDecoder->DispatchSetMediaSeekable(false);
mOnMediaNotSeekable.Notify();
}
bool OggReader::ReadOggChain()

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

@ -66,8 +66,6 @@ public:
Seek(int64_t aTime, int64_t aEndTime) override;
virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
private:
bool HasAudio() {
return (mVorbisState != 0 && mVorbisState->mActive) ||

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

@ -310,6 +310,8 @@ void MediaOmxReader::HandleResourceAllocated()
mInfo.mAudio.mRate = sampleRate;
}
mInfo.mMediaSeekable = mExtractor->flags() & MediaExtractor::CAN_SEEK;
RefPtr<MetadataHolder> metadata = new MetadataHolder();
metadata->mInfo = mInfo;
metadata->mTags = nullptr;
@ -321,13 +323,6 @@ void MediaOmxReader::HandleResourceAllocated()
mMetadataPromise.Resolve(metadata, __func__);
}
bool
MediaOmxReader::IsMediaSeekable()
{
// Check the MediaExtract flag if the source is seekable.
return (mExtractor->flags() & MediaExtractor::CAN_SEEK);
}
bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold)
{

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

@ -92,8 +92,6 @@ public:
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
virtual bool IsMediaSeekable() override;
virtual void SetIdle() override;
virtual RefPtr<ShutdownPromise> Shutdown() override;

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

@ -101,13 +101,6 @@ nsresult RawReader::ReadMetadata(MediaInfo* aInfo,
return NS_OK;
}
bool
RawReader::IsMediaSeekable()
{
// not used
return true;
}
bool RawReader::DecodeAudioData()
{
MOZ_ASSERT(OnTaskQueue());

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

@ -33,8 +33,6 @@ public:
virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
private:
bool ReadFromResource(uint8_t *aBuf, uint32_t aLength);

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

@ -145,13 +145,6 @@ nsresult WaveReader::ReadMetadata(MediaInfo* aInfo,
return NS_OK;
}
bool
WaveReader::IsMediaSeekable()
{
// not used
return true;
}
template <typename T> T UnsignedByteToAudioSample(uint8_t aValue);
template <typename T> T SignedShortToAudioSample(int16_t aValue);

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

@ -33,8 +33,6 @@ public:
virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
private:
bool ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead = nullptr);
bool LoadRIFFChunk();

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

@ -46,12 +46,6 @@ BufferDecoder::NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
// ignore
}
void
BufferDecoder::SetMediaSeekable(bool aMediaSeekable)
{
// ignore
}
VideoFrameContainer*
BufferDecoder::GetVideoFrameContainer()
{

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

@ -36,8 +36,6 @@ public:
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
uint32_t aDropped) final override;
virtual void SetMediaSeekable(bool aMediaSeekable) final override;
virtual VideoFrameContainer* GetVideoFrameContainer() final override;
virtual layers::ImageContainer* GetImageContainer() final override;

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

@ -402,17 +402,13 @@ WebMReader::RetrieveWebMMetadata(MediaInfo* aInfo)
}
}
mInfo.mMediaSeekable = nestegg_has_cues(mContext);
*aInfo = mInfo;
return NS_OK;
}
bool
WebMReader::IsMediaSeekable()
{
return mContext && nestegg_has_cues(mContext);
}
bool WebMReader::DecodeAudioPacket(NesteggPacketHolder* aHolder)
{
MOZ_ASSERT(OnTaskQueue());

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

@ -92,8 +92,6 @@ public:
virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
// Value passed to NextPacket to determine if we are reading a video or an
// audio packet.
enum TrackType {