--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -146,17 +146,20 @@ public:
* Call this to reevaluate whether we should start/stop due to our owner
* document being active, inactive, visible or hidden.
*/
virtual void NotifyOwnerDocumentActivityChanged();
// Called by the video decoder object, on the main thread,
// when it has read the metadata containing video dimensions,
// etc.
- virtual void MetadataLoaded(const MediaInfo* aInfo,
+ virtual void MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
const MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
// Called by the video decoder object, on the main thread,
// when it has read the first frame of the video
// aResourceFullyLoaded should be true if the resource has been
// fully loaded and the caller will call ResourceLoaded next.
virtual void FirstFrameLoaded(bool aResourceFullyLoaded) MOZ_FINAL MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -2871,33 +2871,36 @@ void HTMLMediaElement::ProcessMediaFragm
}
if (parser.HasStartTime()) {
SetCurrentTime(parser.GetStartTime());
mFragmentStart = parser.GetStartTime();
}
}
-void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
+void HTMLMediaElement::MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
const MetadataTags* aTags)
{
- mHasAudio = aInfo->HasAudio();
+ mHasAudio = aHasAudio;
mTags = aTags;
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
ProcessMediaFragmentURI();
mDecoder->SetFragmentEndTime(mFragmentEnd);
}
// If this element had a video track, but consists only of an audio track now,
// delete the VideoFrameContainer. This happens when the src is changed to an
// audio only file.
- if (!aInfo->HasVideo() && mVideoFrameContainer) {
+ if (!aHasVideo && mVideoFrameContainer) {
// call ForgetElement() such that callbacks from |mVideoFrameContainer|
// won't reach us anymore.
mVideoFrameContainer->ForgetElement();
mVideoFrameContainer = nullptr;
}
}
void HTMLMediaElement::FirstFrameLoaded(bool aResourceFullyLoaded)
--- a/content/media/AbstractMediaDecoder.h
+++ b/content/media/AbstractMediaDecoder.h
@@ -3,17 +3,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AbstractMediaDecoder_h_
#define AbstractMediaDecoder_h_
#include "mozilla/Attributes.h"
-#include "MediaInfo.h"
#include "nsISupports.h"
#include "nsDataHashtable.h"
#include "nsThreadUtils.h"
namespace mozilla
{
namespace layers
@@ -85,18 +84,18 @@ public:
virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;
// Return true if the media layer supports seeking.
virtual bool IsTransportSeekable() = 0;
// Return true if the transport layer supports seeking.
virtual bool IsMediaSeekable() = 0;
- virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) = 0;
- virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) = 0;
+ virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0;
+ virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0;
// Set the media end time in microseconds
virtual void SetMediaEndTime(int64_t aTime) = 0;
// Make the decoder state machine update the playback position. Called by
// the reader on the decoder thread (Assertions for this checked by
// mDecoderStateMachine). This must be called with the decode monitor
// held.
@@ -132,37 +131,40 @@ public:
}
private:
AbstractMediaDecoder* mDecoder;
uint32_t& mParsed;
uint32_t& mDecoded;
};
};
-class MetadataEventRunner : public nsRunnable
+class AudioMetadataEventRunner : public nsRunnable
{
private:
nsRefPtr<AbstractMediaDecoder> mDecoder;
public:
- MetadataEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo, MetadataTags* aTags)
- : mDecoder(aDecoder),
- mInfo(aInfo),
- mTags(aTags)
+ AudioMetadataEventRunner(AbstractMediaDecoder* aDecoder, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags)
+ : mDecoder(aDecoder),
+ mChannels(aChannels),
+ mRate(aRate),
+ mHasAudio(aHasAudio),
+ mHasVideo(aHasVideo),
+ mTags(aTags)
{}
NS_IMETHOD Run() MOZ_OVERRIDE
{
- mDecoder->MetadataLoaded(mInfo, mTags);
+ mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio, mHasVideo, mTags);
return NS_OK;
}
- // The ownership is transferred to MediaDecoder.
- MediaInfo* mInfo;
-
- // The ownership is transferred to its owning element.
+ int mChannels;
+ int mRate;
+ bool mHasAudio;
+ bool mHasVideo;
MetadataTags* mTags;
};
}
#endif
--- a/content/media/BufferDecoder.cpp
+++ b/content/media/BufferDecoder.cpp
@@ -142,23 +142,23 @@ BufferDecoder::IsTransportSeekable()
bool
BufferDecoder::IsMediaSeekable()
{
return false;
}
void
-BufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+BufferDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags)
{
// ignore
}
void
-BufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
+BufferDecoder::QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags)
{
// ignore
}
void
BufferDecoder::SetMediaEndTime(int64_t aTime)
{
// ignore
--- a/content/media/BufferDecoder.h
+++ b/content/media/BufferDecoder.h
@@ -55,18 +55,18 @@ public:
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_OVERRIDE;
virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
virtual bool IsTransportSeekable() MOZ_OVERRIDE;
virtual bool IsMediaSeekable() MOZ_OVERRIDE;
- virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_OVERRIDE;
- virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_OVERRIDE;
+ virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_OVERRIDE;
+ virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_OVERRIDE;
virtual void SetMediaEndTime(int64_t aTime) MOZ_OVERRIDE;
virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_OVERRIDE;
virtual void OnReadMetadataCompleted() MOZ_OVERRIDE;
virtual MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -648,33 +648,36 @@ double MediaDecoder::GetCurrentTime()
already_AddRefed<nsIPrincipal> MediaDecoder::GetCurrentPrincipal()
{
MOZ_ASSERT(NS_IsMainThread());
return mResource ? mResource->GetCurrentPrincipal() : nullptr;
}
void MediaDecoder::QueueMetadata(int64_t aPublishTime,
- MediaInfo* aInfo,
+ int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags)
{
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
GetReentrantMonitor().AssertCurrentThreadIn();
- mDecoderStateMachine->QueueMetadata(aPublishTime, aInfo, aTags);
+ mDecoderStateMachine->QueueMetadata(aPublishTime, aChannels, aRate, aHasAudio, aHasVideo, aTags);
}
bool
MediaDecoder::IsDataCachedToEndOfResource()
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
return (mResource &&
mResource->IsDataCachedToEndOfResource(mDecoderPosition));
}
-void MediaDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown) {
return;
}
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
@@ -692,17 +695,17 @@ void MediaDecoder::MetadataLoaded(MediaI
if (mDuration == -1) {
SetInfinite(true);
}
if (mOwner) {
// Make sure the element and the frame (if any) are told about
// our new size.
Invalidate();
- mOwner->MetadataLoaded(aInfo, aTags);
+ mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
}
if (!mCalledResourceLoaded) {
StartProgress();
} else if (mOwner) {
// Resource was loaded during metadata loading, when progress
// events are being ignored. Fire the final progress event.
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -746,17 +746,20 @@ public:
void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
// Send a new set of metadata to the state machine, to be dispatched to the
// main thread to be presented when the |currentTime| of the media is greater
// or equal to aPublishTime.
void QueueMetadata(int64_t aPublishTime,
- MediaInfo* aInfo,
+ int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags);
/******
* The following methods must only be called on the main
* thread.
******/
// Change to a new play state. This updates the mState variable and
@@ -769,17 +772,20 @@ public:
virtual void ApplyStateToStateMachine(PlayState aState);
// May be called by the reader to notify this decoder that the metadata from
// the media file has been read. Call on the decode thread only.
void OnReadMetadataCompleted() MOZ_OVERRIDE { }
// Called when the metadata from the media file has been loaded by the
// state machine. Call on the main thread only.
- virtual void MetadataLoaded(MediaInfo* aInfo,
+ virtual void MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags);
// Called when the first frame has been loaded.
// Call on the main thread only.
void FirstFrameLoaded();
// Returns true if the resource has been loaded. Acquires the monitor.
// Call from any thread.
--- a/content/media/MediaDecoderOwner.h
+++ b/content/media/MediaDecoderOwner.h
@@ -44,17 +44,20 @@ public:
}
// Return true if decoding should be paused
virtual bool GetPaused() = 0;
// Called by the video decoder object, on the main thread,
// when it has read the metadata containing video dimensions,
// etc.
- virtual void MetadataLoaded(const MediaInfo* aInfo,
+ virtual void MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
const MetadataTags* aTags) = 0;
// Called by the video decoder object, on the main thread,
// when it has read the first frame of the video
// aResourceFullyLoaded should be true if the resource has been
// fully loaded and the caller will call ResourceLoaded next.
virtual void FirstFrameLoaded(bool aResourceFullyLoaded) = 0;
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1978,20 +1978,23 @@ MediaDecoderStateMachine::FinishDecodeMe
// We're playing audio only. We don't need to worry about slow video
// decodes causing audio underruns, so don't buffer so much audio in
// order to reduce memory usage.
mAmpleAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
}
// Inform the element that we've loaded the metadata and the first frame.
- nsAutoPtr<MediaInfo> info(new MediaInfo());
- *info = mInfo;
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
- new MetadataEventRunner(mDecoder, info.forget(), mMetadataTags.forget());
+ new AudioMetadataEventRunner(mDecoder,
+ mInfo.mAudio.mChannels,
+ mInfo.mAudio.mRate,
+ HasAudio(),
+ HasVideo(),
+ mMetadataTags.forget());
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
if (mState == DECODER_STATE_DECODING_METADATA) {
DECODER_LOG(PR_LOG_DEBUG, "Changed state from DECODING_METADATA to DECODING");
StartDecoding();
}
// For very short media the metadata decode can decode the entire media.
@@ -3090,24 +3093,30 @@ MediaDecoderStateMachine::SetMinimizePre
bool MediaDecoderStateMachine::IsShutdown()
{
AssertCurrentThreadInMonitor();
return GetState() == DECODER_STATE_SHUTDOWN;
}
void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime,
- MediaInfo* aInfo,
+ int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags)
{
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
AssertCurrentThreadInMonitor();
TimedMetadata* metadata = new TimedMetadata;
metadata->mPublishTime = aPublishTime;
- metadata->mInfo = aInfo;
+ metadata->mChannels = aChannels;
+ metadata->mRate = aRate;
+ metadata->mHasAudio = aHasAudio;
+ metadata->mHasVideo = aHasVideo;
metadata->mTags = aTags;
mMetadataManager.QueueMetadata(metadata);
}
void MediaDecoderStateMachine::OnAudioEndTimeUpdate(int64_t aAudioEndTime)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(aAudioEndTime >= mAudioEndTime);
--- a/content/media/MediaDecoderStateMachine.h
+++ b/content/media/MediaDecoderStateMachine.h
@@ -318,17 +318,17 @@ public:
void FinishStreamData();
bool HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs);
bool HaveEnoughDecodedVideo();
// Returns true if the state machine has shutdown or is in the process of
// shutting down. The decoder monitor must be held while calling this.
bool IsShutdown();
- void QueueMetadata(int64_t aPublishTime, MediaInfo* aInfo, MetadataTags* aTags);
+ void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags);
// Returns true if we're currently playing. The decoder monitor must
// be held.
bool IsPlaying();
// Called when the reader may have acquired the hardware resources required
// to begin decoding. The state machine may move into DECODING_METADATA if
// appropriate. The decoder monitor must be held while calling this.
--- a/content/media/MediaMetadataManager.h
+++ b/content/media/MediaMetadataManager.h
@@ -17,20 +17,24 @@ namespace mozilla {
// metadata should start to be reported.
class TimedMetadata : public LinkedListElement<TimedMetadata> {
public:
// The time, in microseconds, at which those metadata should be available.
int64_t mPublishTime;
// The metadata. The ownership is transfered to the element when dispatching to
// the main threads.
nsAutoPtr<MetadataTags> mTags;
- // The media info, including the info of audio tracks and video tracks.
- // The ownership is transfered to MediaDecoder when dispatching to the
- // main thread.
- nsAutoPtr<MediaInfo> mInfo;
+ // The sample rate of this media.
+ int mRate;
+ // The number of channel of this media.
+ int mChannels;
+ // True if this media has an audio track.
+ bool mHasAudio;
+ // True if this media has a video track.
+ bool mHasVideo;
};
// This class encapsulate the logic to give the metadata from the reader to
// the content, at the right time.
class MediaMetadataManager
{
public:
~MediaMetadataManager() {
@@ -42,19 +46,22 @@ namespace mozilla {
void QueueMetadata(TimedMetadata* aMetadata) {
mMetadataQueue.insertBack(aMetadata);
}
void DispatchMetadataIfNeeded(AbstractMediaDecoder* aDecoder, double aCurrentTime) {
TimedMetadata* metadata = mMetadataQueue.getFirst();
while (metadata && aCurrentTime >= static_cast<double>(metadata->mPublishTime) / USECS_PER_S) {
nsCOMPtr<nsIRunnable> metadataUpdatedEvent =
- new MetadataEventRunner(aDecoder,
- metadata->mInfo.forget(),
- metadata->mTags.forget());
+ new AudioMetadataEventRunner(aDecoder,
+ metadata->mChannels,
+ metadata->mRate,
+ metadata->mHasAudio,
+ metadata->mHasVideo,
+ metadata->mTags.forget());
NS_DispatchToMainThread(metadataUpdatedEvent);
delete mMetadataQueue.popFirst();
metadata = mMetadataQueue.getFirst();
}
}
protected:
LinkedList<TimedMetadata> mMetadataQueue;
};
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -622,16 +622,18 @@ void OggReader::SetChained(bool aIsChain
bool OggReader::ReadOggChain()
{
bool chained = false;
#ifdef MOZ_OPUS
OpusState* newOpusState = nullptr;
#endif /* MOZ_OPUS */
VorbisState* newVorbisState = nullptr;
+ int channels = 0;
+ long rate = 0;
MetadataTags* tags = nullptr;
if (HasVideo() || HasSkeleton() || !HasAudio()) {
return false;
}
ogg_page page;
if (!ReadOggPage(&page) || !ogg_page_bos(&page)) {
@@ -666,53 +668,53 @@ bool OggReader::ReadOggChain()
state = mCodecStore.Get(serial);
NS_ENSURE_TRUE(state != nullptr, false);
if (NS_FAILED(state->PageIn(&page))) {
return false;
}
- nsAutoPtr<MediaInfo> info(new MediaInfo());
if ((newVorbisState && ReadHeaders(newVorbisState)) &&
(mVorbisState->mInfo.rate == newVorbisState->mInfo.rate) &&
(mVorbisState->mInfo.channels == newVorbisState->mInfo.channels)) {
mVorbisState->Reset();
mVorbisState = newVorbisState;
mVorbisSerial = mVorbisState->mSerial;
LOG(PR_LOG_DEBUG, ("New vorbis ogg link, serial=%d\n", mVorbisSerial));
chained = true;
- info->mAudio.mRate = mVorbisState->mInfo.rate;
- info->mAudio.mChannels = mVorbisState->mInfo.channels;
+ rate = mVorbisState->mInfo.rate;
+ channels = mVorbisState->mInfo.channels;
tags = mVorbisState->GetTags();
}
#ifdef MOZ_OPUS
if ((newOpusState && ReadHeaders(newOpusState)) &&
(mOpusState->mRate == newOpusState->mRate) &&
(mOpusState->mChannels == newOpusState->mChannels)) {
mOpusState->Reset();
mOpusState = newOpusState;
mOpusSerial = mOpusState->mSerial;
chained = true;
- info->mAudio.mRate = mOpusState->mRate;
- info->mAudio.mChannels = mOpusState->mChannels;
+ rate = mOpusState->mRate;
+ channels = mOpusState->mChannels;
tags = mOpusState->GetTags();
}
#endif
if (chained) {
SetChained(true);
{
- info->mAudio.mHasAudio = HasAudio();
- info->mVideo.mHasVideo = HasVideo();
- int rate = info->mAudio.mRate;
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->QueueMetadata((mDecodedAudioFrames * USECS_PER_S) / rate,
- info.forget(), tags);
+ channels,
+ rate,
+ HasAudio(),
+ HasVideo(),
+ tags);
}
return true;
}
return false;
}
nsresult OggReader::DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold)
--- a/content/media/omx/MediaOmxDecoder.cpp
+++ b/content/media/omx/MediaOmxDecoder.cpp
@@ -50,21 +50,24 @@ MediaDecoderStateMachine* MediaOmxDecode
}
void MediaOmxDecoder::SetCanOffloadAudio(bool aCanOffloadAudio)
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mCanOffloadAudio = aCanOffloadAudio;
}
-void MediaOmxDecoder::MetadataLoaded(MediaInfo* aInfo,
+void MediaOmxDecoder::MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags)
{
MOZ_ASSERT(NS_IsMainThread());
- MediaDecoder::MetadataLoaded(aInfo, aTags);
+ MediaDecoder::MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() ||
mInitialPlaybackRate != 1.0) {
DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed",
__PRETTY_FUNCTION__));
return;
}
--- a/content/media/omx/MediaOmxDecoder.h
+++ b/content/media/omx/MediaOmxDecoder.h
@@ -16,17 +16,20 @@ namespace mozilla {
class MediaOmxDecoder : public MediaDecoder
{
typedef android::MediaSource MediaSource;
public:
MediaOmxDecoder();
virtual MediaDecoder* Clone();
virtual MediaDecoderStateMachine* CreateStateMachine();
- virtual void MetadataLoaded(MediaInfo* aInfo,
+ virtual void MetadataLoaded(int aChannels,
+ int aRate,
+ bool aHasAudio,
+ bool aHasVideo,
MetadataTags* aTags);
virtual void ChangeState(PlayState aState);
virtual void ApplyStateToStateMachine(PlayState aState);
virtual void SetVolume(double aVolume);
virtual void PlaybackPositionChanged();
virtual void UpdateReadyStateForData();
virtual void SetElementVisibility(bool aIsVisible);
virtual void SetCanOffloadAudio(bool aCanOffloadAudio);