зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
c257b89d86
Коммит
e4cbe0c128
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче