import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1261900: [webm] Use block duration if known. r=kinetik (0455c4de93)
- Bug 1261900: [MSE] P2. Prevent assertion if first media segment contains no usable frames. r=gerald (a1cdf83be3)
- Bug 1261900: P3. Re-add MediaDataDemuxer::GetEvictionOffset() API. r=gerald (fc45da3ca8)
- Bug 1261900: [MSE] P4. Only evict no longer used data from resource. r=gerald (d3e3c59f4c)
- Bug 1261900: [MSE/webm] P5. Re-add WebMTrackDemuxer::GetEvictionOffset. r=gerald (ee8fd8e5dc)
- Bug 1261900: [MSE/webm] P6. Don't unnecessarily calculate the next keyframe time. r=kinetik (aa9345d6eb)
- Bug 1261900: [webm] P9. Prevent null deref when webm logs are turned on. r=kinetik (dfe061a463)
- Bug 1261900 - Allow WebMDemuxer to resume demuxing even after encountering EOS. r=jya (65bd6409fd)
- Bug 1274445: [webm] P1. Track separately audio track from video track. r=kinetik (35f04cd778)
- Bug 1274445: P2. Don't unnecessarily reset the decoder context. r=kamidphish (eaa0d94c25)
- Bug 1275807 - Remove remaining use of FlushableTaskQueue. r=cpearce. (d0834f0a03)
- Bug 1272225. Part 3 - remove use of FlushableTaskQueue. r=jya. (ed25bc636f)
- Bug 1274205 - remove use of FlushableTaskQueue. r=bechen. (9f340e7a97)
- Bug 1274214 - remove use of FlushableTaskQueue. r=kaku. (1c90ec8e7f)
- Bug 1266644 - Remove unused codes. r=jesup r=pehrsons (ffb303f3ee)
- Bug 1266647 - Clean NotifyQueuedTrackChange to only notify when command is track create and track end. r=jesup r=pehrsons (2ed23f22f0)
This commit is contained in:
2024-10-08 23:53:21 +08:00
parent 93f846cd1f
commit 81a1b46bb3
30 changed files with 353 additions and 314 deletions
+1
View File
@@ -4,6 +4,7 @@
* 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/. */
#include "mozilla/SharedThreadPool.h"
#include "FileBlockCache.h"
#include "VideoUtils.h"
#include "prio.h"
-57
View File
@@ -1,57 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "FlushableTaskQueue.h"
namespace mozilla {
void
FlushableTaskQueue::Flush()
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
FlushLocked();
AwaitIdleLocked();
}
nsresult
FlushableTaskQueue::FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable)
{
nsCOMPtr<nsIRunnable> r = aRunnable;
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
FlushLocked();
nsresult rv = DispatchLocked(/* passed by ref */r, IgnoreFlushing, AssertDispatchSuccess);
NS_ENSURE_SUCCESS(rv, rv);
AwaitIdleLocked();
}
// If the ownership of |r| is not transferred in DispatchLocked() due to
// dispatch failure, it will be deleted here outside the lock. We do so
// since the destructor of the runnable might access TaskQueue and result
// in deadlocks.
return NS_OK;
}
void
FlushableTaskQueue::FlushLocked()
{
// Make sure there are no tasks for this queue waiting in the caller's tail
// dispatcher.
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
mQueueMonitor.AssertCurrentThreadOwns();
MOZ_ASSERT(mIsFlushing);
// Clear the tasks. If this strikes you as awful, stop using a
// FlushableTaskQueue.
while (!mTasks.empty()) {
mTasks.pop();
}
}
} // namespace mozilla
-53
View File
@@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 FlushableTaskQueue_h_
#define FlushableTaskQueue_h_
#include "mozilla/TaskQueue.h"
//
// WARNING: THIS CLASS IS DEPRECATED AND GOING AWAY. DO NOT USE IT!
//
namespace mozilla {
class FlushableTaskQueue : public TaskQueue
{
public:
explicit FlushableTaskQueue(already_AddRefed<SharedThreadPool> aPool) : TaskQueue(Move(aPool)) {}
nsresult FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable);
void Flush();
bool IsDispatchReliable() override { return false; }
private:
class MOZ_STACK_CLASS AutoSetFlushing
{
public:
explicit AutoSetFlushing(FlushableTaskQueue* aTaskQueue) : mTaskQueue(aTaskQueue)
{
mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns();
mTaskQueue->mIsFlushing = true;
}
~AutoSetFlushing()
{
mTaskQueue->mQueueMonitor.AssertCurrentThreadOwns();
mTaskQueue->mIsFlushing = false;
}
private:
FlushableTaskQueue* mTaskQueue;
};
void FlushLocked();
};
} // namespace mozilla
#endif // FlushableTaskQueue_h_
+7
View File
@@ -201,6 +201,13 @@ public:
virtual media::TimeIntervals GetBuffered() = 0;
// By default, it is assumed that the entire resource can be evicted once
// all samples have been demuxed.
virtual int64_t GetEvictionOffset(const media::TimeUnit& aTime)
{
return INT64_MAX;
}
// If the MediaTrackDemuxer and MediaDataDemuxer hold cross references.
// BreakCycles must be overridden.
virtual void BreakCycles()
+2 -4
View File
@@ -174,9 +174,9 @@ MediaFormatReader::Init()
InitLayersBackendType();
mAudio.mTaskQueue =
new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
mVideo.mTaskQueue =
new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
return NS_OK;
}
@@ -1336,7 +1336,6 @@ MediaFormatReader::ResetDecode(TargetQueues aQueues)
if (HasVideo()) {
mVideo.ResetDemuxer();
mVideo.ResetState();
Reset(TrackInfo::kVideoTrack);
if (mVideo.HasPromise()) {
mVideo.RejectPromise(CANCELED, __func__);
@@ -1345,7 +1344,6 @@ MediaFormatReader::ResetDecode(TargetQueues aQueues)
if (HasAudio() && aQueues == AUDIO_VIDEO) {
mAudio.ResetDemuxer();
mAudio.ResetState();
Reset(TrackInfo::kAudioTrack);
if (mAudio.HasPromise()) {
mAudio.RejectPromise(CANCELED, __func__);
+1 -1
View File
@@ -257,7 +257,7 @@ private:
RefPtr<MediaTrackDemuxer> mTrackDemuxer;
// TaskQueue on which decoder can choose to decode.
// Only non-null up until the decoder is created.
RefPtr<FlushableTaskQueue> mTaskQueue;
RefPtr<TaskQueue> mTaskQueue;
// Callback that receives output and error notifications from the decoder.
nsAutoPtr<DecoderCallback> mCallback;
+49 -3
View File
@@ -205,12 +205,58 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
for (int32_t i = aStream->mUpdateTracks.Length() - 1; i >= 0; --i) {
SourceMediaStream::TrackData* data = &aStream->mUpdateTracks[i];
aStream->ApplyTrackDisabling(data->mID, data->mData);
// Dealing with NotifyQueuedTrackChanges and NotifyQueuedAudioData part.
// The logic is different from the manipulating of aStream->mTracks part.
// So it is not combined with the manipulating of aStream->mTracks part.
StreamTime offset = (data->mCommands & SourceMediaStream::TRACK_CREATE)
? data->mStart : aStream->mTracks.FindTrack(data->mID)->GetSegment()->GetDuration();
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
// Audio case.
if (data->mData->GetType() == MediaSegment::AUDIO) {
if (data->mCommands) {
MOZ_ASSERT(!(data->mCommands & SourceMediaStream::TRACK_UNUSED));
for (MediaStreamListener* l : aStream->mListeners) {
if (data->mCommands & SourceMediaStream::TRACK_END) {
l->NotifyQueuedAudioData(this, data->mID,
offset, *(static_cast<AudioSegment*>(data->mData.get())));
}
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
l->NotifyQueuedAudioData(this, data->mID,
offset, *(static_cast<AudioSegment*>(data->mData.get())));
}
}
} else {
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyQueuedAudioData(this, data->mID,
offset, *(static_cast<AudioSegment*>(data->mData.get())));
}
}
}
// Video case.
if (data->mData->GetType() == MediaSegment::VIDEO) {
if (data->mCommands) {
MOZ_ASSERT(!(data->mCommands & SourceMediaStream::TRACK_UNUSED));
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
}
} else {
// Fixme: This part will be removed in the bug 1201363. It will be
// removed in changeset "Do not copy video segment to StreamTracks in
// TrackUnionStream."
// Dealing with video and not TRACK_CREATE and TRACK_END case.
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
}
}
}
for (TrackBound<MediaStreamTrackListener>& b : aStream->mTrackListeners) {
if (b.mTrackID != data->mID) {
continue;
+15 -13
View File
@@ -159,9 +159,11 @@ public:
*/
virtual void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent aEvent) {}
// maskable flags, not a simple enumerated value
enum {
TRACK_EVENT_CREATED = 0x01,
TRACK_EVENT_ENDED = 0x02
TRACK_EVENT_ENDED = 0x02,
TRACK_EVENT_UNUSED = ~(TRACK_EVENT_ENDED | TRACK_EVENT_CREATED),
};
/**
* Notify that changes to one of the stream tracks have been queued.
@@ -179,6 +181,16 @@ public:
MediaStream* aInputStream = nullptr,
TrackID aInputTrackID = TRACK_INVALID) {}
/**
* Notify queued audio data. Only audio data need to be queued. The video data
* will be notified by MediaStreamVideoSink::SetCurrentFrame.
*/
virtual void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
const AudioSegment& aQueuedMedia,
MediaStream* aInputStream = nullptr,
TrackID aInputTrackID = TRACK_INVALID) {}
/**
* Notify that all new tracks this iteration have been created.
* This is to ensure that tracks added atomically to MediaStreamGraph
@@ -1078,19 +1090,10 @@ public:
friend class MediaStreamGraphImpl;
protected:
struct ThreadAndRunnable {
void Init(TaskQueue* aTarget, nsIRunnable* aRunnable)
{
mTarget = aTarget;
mRunnable = aRunnable;
}
RefPtr<TaskQueue> mTarget;
nsCOMPtr<nsIRunnable> mRunnable;
};
enum TrackCommands {
TRACK_CREATE = MediaStreamListener::TRACK_EVENT_CREATED,
TRACK_END = MediaStreamListener::TRACK_EVENT_ENDED
TRACK_END = MediaStreamListener::TRACK_EVENT_ENDED,
TRACK_UNUSED = MediaStreamListener::TRACK_EVENT_UNUSED,
};
/**
* Data for each track that hasn't ended.
@@ -1455,7 +1458,6 @@ public:
// IdealAudioBlockSize()/AudioStream::PreferredSampleRate(). A stream that
// never blocks and has a track with the ideal audio rate will produce audio
// in multiples of the block size.
//
// Initializing an graph that outputs audio can be quite long on some
// platforms. Code that want to output audio at some point can express the
+11 -4
View File
@@ -324,10 +324,17 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
ApplyTrackDisabling(outputTrack->GetID(), segment);
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
MediaStreamListener* l = mListeners[j];
l->NotifyQueuedTrackChanges(Graph(), outputTrack->GetID(),
outputStart, 0, *segment,
map->mInputPort->GetSource(),
map->mInputTrackID);
// Separate Audio and Video.
if (segment->GetType() == MediaSegment::AUDIO) {
l->NotifyQueuedAudioData(Graph(), outputTrack->GetID(),
outputStart, *static_cast<AudioSegment*>(segment));
} else {
// This part will be removed in bug 1201363.
l->NotifyQueuedTrackChanges(Graph(), outputTrack->GetID(),
outputStart, 0, *segment,
map->mInputPort->GetSource(),
map->mInputTrackID);
}
}
for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
if (b.mTrackID != outputTrack->GetID()) {
-8
View File
@@ -295,14 +295,6 @@ CreateMediaDecodeTaskQueue()
return queue.forget();
}
already_AddRefed<FlushableTaskQueue>
CreateFlushableMediaDecodeTaskQueue()
{
RefPtr<FlushableTaskQueue> queue = new FlushableTaskQueue(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
return queue.forget();
}
void
SimpleTimer::Cancel() {
if (mTimer) {
-4
View File
@@ -7,7 +7,6 @@
#ifndef VideoUtils_h
#define VideoUtils_h
#include "FlushableTaskQueue.h"
#include "mozilla/Attributes.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/MozPromise.h"
@@ -268,9 +267,6 @@ GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength);
already_AddRefed<TaskQueue>
CreateMediaDecodeTaskQueue();
already_AddRefed<FlushableTaskQueue>
CreateFlushableMediaDecodeTaskQueue();
// Iteratively invokes aWork until aCondition returns true, or aWork returns false.
// Use this rather than a while loop to avoid bogarting the task queue.
template<class Work, class Condition>
+11
View File
@@ -105,6 +105,17 @@ MediaEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
}
}
void
MediaEncoder::NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
const AudioSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID)
{
mAudioEncoder->NotifyQueuedTrackChanges(aGraph, aID, aTrackOffset, 0,
aQueuedMedia);
}
void
MediaEncoder::NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event)
+11 -1
View File
@@ -130,7 +130,17 @@ public :
TrackID aInputTrackID) override;
/**
* Notified the stream is being removed.
* Notifed by the control loop of MediaStreamGraph; aQueueMedia is the audio
* data in the form of an AudioSegment.
*/
void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
const AudioSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID) override;
/**
* * Notified the stream is being removed.
*/
void NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event) override;
+3 -3
View File
@@ -220,7 +220,7 @@ static const uint8_t sTestH264ExtraData[] = {
static already_AddRefed<MediaDataDecoder>
CreateTestH264Decoder(layers::LayersBackend aBackend,
VideoInfo& aConfig,
FlushableTaskQueue* aTaskQueue)
TaskQueue* aTaskQueue)
{
aConfig.mMimeType = "video/avc";
aConfig.mId = 1;
@@ -253,8 +253,8 @@ MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject*
return nullptr;
}
RefPtr<FlushableTaskQueue> taskQueue =
new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
RefPtr<TaskQueue> taskQueue =
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
VideoInfo config;
RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config, taskQueue));
if (!decoder) {
+20 -6
View File
@@ -1301,9 +1301,21 @@ TrackBuffersManager::CompleteCodedFrameProcessing()
// 6. Remove the media segment bytes from the beginning of the input buffer.
// Clear our demuxer from any already processed data.
// As we have handled a complete media segment, it is safe to evict all data
// from the resource.
mCurrentInputBuffer->EvictAll();
int64_t safeToEvict = std::min(
HasVideo()
? mVideoTracks.mDemuxer->GetEvictionOffset(mVideoTracks.mLastParsedEndTime)
: INT64_MAX,
HasAudio()
? mAudioTracks.mDemuxer->GetEvictionOffset(mAudioTracks.mLastParsedEndTime)
: INT64_MAX);
ErrorResult rv;
mCurrentInputBuffer->EvictBefore(safeToEvict, rv);
if (rv.Failed()) {
rv.SuppressException();
RejectProcessing(NS_ERROR_OUT_OF_MEMORY, __func__);
return;
}
mInputDemuxer->NotifyDataRemoved();
RecreateParser(true);
@@ -1666,9 +1678,11 @@ TrackBuffersManager::InsertFrames(TrackBuffer& aSamples,
// We allow a fuzz factor in our interval of half a frame length,
// as fuzz is +/- value, giving an effective leeway of a full frame
// length.
TimeIntervals range(aIntervals);
range.SetFuzz(trackBuffer.mLongestFrameDuration / 2);
trackBuffer.mSanitizedBufferedRanges += range;
if (aIntervals.Length()) {
TimeIntervals range(aIntervals);
range.SetFuzz(trackBuffer.mLongestFrameDuration / 2);
trackBuffer.mSanitizedBufferedRanges += range;
}
}
void
-2
View File
@@ -99,7 +99,6 @@ EXPORTS += [
'DOMMediaStream.h',
'EncodedBufferCache.h',
'FileBlockCache.h',
'FlushableTaskQueue.h',
'FrameStatistics.h',
'Intervals.h',
'Latency.h',
@@ -209,7 +208,6 @@ UNIFIED_SOURCES += [
'DOMMediaStream.cpp',
'EncodedBufferCache.cpp',
'FileBlockCache.cpp',
'FlushableTaskQueue.cpp',
'GetUserMediaRequest.cpp',
'GraphDriver.cpp',
'Latency.cpp',
+2 -2
View File
@@ -19,11 +19,11 @@
namespace mozilla {
AppleATDecoder::AppleATDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mConfig(aConfig)
, mFileStreamError(false)
, mTaskQueue(aAudioTaskQueue)
, mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mConverter(nullptr)
, mStream(nullptr)
+3 -3
View File
@@ -16,13 +16,13 @@
namespace mozilla {
class FlushableTaskQueue;
class TaskQueue;
class MediaDataDecoderCallback;
class AppleATDecoder : public MediaDataDecoder {
public:
AppleATDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aVideoTaskQueue,
TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
virtual ~AppleATDecoder();
@@ -47,7 +47,7 @@ public:
bool mFileStreamError;
private:
RefPtr<FlushableTaskQueue> mTaskQueue;
const RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
AudioConverterRef mConverter;
AudioStreamBasicDescription mOutputFormat;
@@ -28,7 +28,7 @@ GonkDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
{
RefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkVideoDecoderManager(aImageContainer, aConfig),
aVideoTaskQueue, aCallback);
aCallback);
return decoder.forget();
}
@@ -40,7 +40,7 @@ GonkDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
{
RefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig),
aAudioTaskQueue, aCallback);
aCallback);
return decoder.forget();
}
@@ -330,7 +330,6 @@ GonkDecoderManager::OnTaskLooper()
#endif
GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mManager(aManager)
{
@@ -186,7 +186,6 @@ private:
class GonkMediaDataDecoder : public MediaDataDecoder {
public:
GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
~GonkMediaDataDecoder();
@@ -69,7 +69,7 @@ protected:
class WMFMediaDataDecoder : public MediaDataDecoder {
public:
WMFMediaDataDecoder(MFTManager* aOutputSource,
TaskQueue* aAudioTaskQueue,
TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback);
~WMFMediaDataDecoder();
@@ -116,7 +116,7 @@ private:
// different configuration (typically resolution change).
void ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig);
RefPtr<TaskQueue> mTaskQueue;
const RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
nsAutoPtr<MFTManager> mMFTManager;
+14 -1
View File
@@ -19,7 +19,12 @@ namespace mozilla {
class NesteggPacketHolder {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NesteggPacketHolder)
NesteggPacketHolder() : mPacket(nullptr), mOffset(-1), mTimestamp(-1), mIsKeyframe(false) {}
NesteggPacketHolder()
: mPacket(nullptr)
, mOffset(-1)
, mTimestamp(-1)
, mDuration(-1)
, mIsKeyframe(false) {}
bool Init(nestegg_packet* aPacket, int64_t aOffset, unsigned aTrack, bool aIsKeyframe)
{
@@ -36,12 +41,17 @@ public:
mTrack = aTrack;
mIsKeyframe = aIsKeyframe;
uint64_t duration_ns;
if (!nestegg_packet_duration(aPacket, &duration_ns)) {
mDuration = duration_ns / 1000;
}
return true;
}
nestegg_packet* Packet() { MOZ_ASSERT(IsInitialized()); return mPacket; }
int64_t Offset() { MOZ_ASSERT(IsInitialized()); return mOffset; }
int64_t Timestamp() { MOZ_ASSERT(IsInitialized()); return mTimestamp; }
int64_t Duration() { MOZ_ASSERT(IsInitialized()); return mDuration; }
unsigned Track() { MOZ_ASSERT(IsInitialized()); return mTrack; }
bool IsKeyframe() { MOZ_ASSERT(IsInitialized()); return mIsKeyframe; }
@@ -62,6 +72,9 @@ private:
// Packet presentation timestamp in microseconds.
int64_t mTimestamp;
// Packet duration in microseconds; -1 if unknown or retrieval failed.
int64_t mDuration;
// Track ID.
unsigned mTrack;
+127 -94
View File
@@ -51,12 +51,13 @@ static int webmdemux_read(void* aBuffer, size_t aLength, void* aUserData)
{
MOZ_ASSERT(aUserData);
MOZ_ASSERT(aLength < UINT32_MAX);
WebMDemuxer* demuxer = reinterpret_cast<WebMDemuxer*>(aUserData);
WebMDemuxer::NestEggContext* context =
reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
uint32_t count = aLength;
if (demuxer->IsMediaSource()) {
int64_t length = demuxer->GetEndDataOffset();
int64_t position = demuxer->GetResource()->Tell();
MOZ_ASSERT(position <= demuxer->GetResource()->GetLength());
if (context->IsMediaSource()) {
int64_t length = context->GetEndDataOffset();
int64_t position = context->GetResource()->Tell();
MOZ_ASSERT(position <= context->GetResource()->GetLength());
MOZ_ASSERT(position <= length);
if (length >= 0 && count + position > length) {
count = length - position;
@@ -65,7 +66,7 @@ static int webmdemux_read(void* aBuffer, size_t aLength, void* aUserData)
}
uint32_t bytes = 0;
nsresult rv =
demuxer->GetResource()->Read(static_cast<char*>(aBuffer), count, &bytes);
context->GetResource()->Read(static_cast<char*>(aBuffer), count, &bytes);
bool eof = bytes < aLength;
return NS_FAILED(rv) ? -1 : eof ? 0 : 1;
}
@@ -73,16 +74,16 @@ static int webmdemux_read(void* aBuffer, size_t aLength, void* aUserData)
static int webmdemux_seek(int64_t aOffset, int aWhence, void* aUserData)
{
MOZ_ASSERT(aUserData);
WebMDemuxer* demuxer = reinterpret_cast<WebMDemuxer*>(aUserData);
nsresult rv = demuxer->GetResource()->Seek(aWhence, aOffset);
WebMDemuxer::NestEggContext* context = reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
nsresult rv = context->GetResource()->Seek(aWhence, aOffset);
return NS_SUCCEEDED(rv) ? 0 : -1;
}
static int64_t webmdemux_tell(void* aUserData)
{
MOZ_ASSERT(aUserData);
WebMDemuxer* demuxer = reinterpret_cast<WebMDemuxer*>(aUserData);
return demuxer->GetResource()->Tell();
WebMDemuxer::NestEggContext* context = reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
return context->GetResource()->Tell();
}
static void webmdemux_log(nestegg* aContext,
@@ -127,6 +128,28 @@ static void webmdemux_log(nestegg* aContext,
va_end(args);
}
WebMDemuxer::NestEggContext::~NestEggContext()
{
if (mContext) {
nestegg_destroy(mContext);
}
}
int
WebMDemuxer::NestEggContext::Init()
{
nestegg_io io;
io.read = webmdemux_read;
io.seek = webmdemux_seek;
io.tell = webmdemux_tell;
io.userdata = this;
// While reading the metadata, we do not really care about which nestegg
// context is being used so long that they are both initialised.
// For reading the metadata however, we will use mVideoContext.
return nestegg_init(&mContext, io, &webmdemux_log,
mParent->IsMediaSource() ? mResource.GetLength() : -1);
}
WebMDemuxer::WebMDemuxer(MediaResource* aResource)
: WebMDemuxer(aResource, false)
@@ -134,10 +157,10 @@ WebMDemuxer::WebMDemuxer(MediaResource* aResource)
}
WebMDemuxer::WebMDemuxer(MediaResource* aResource, bool aIsMediaSource)
: mResource(aResource)
: mVideoContext(this, aResource)
, mAudioContext(this, aResource)
, mBufferedState(nullptr)
, mInitData(nullptr)
, mContext(nullptr)
, mVideoTrack(0)
, mAudioTrack(0)
, mSeekPreroll(0)
@@ -153,8 +176,8 @@ WebMDemuxer::WebMDemuxer(MediaResource* aResource, bool aIsMediaSource)
WebMDemuxer::~WebMDemuxer()
{
Reset();
Cleanup();
Reset(TrackInfo::kVideoTrack);
Reset(TrackInfo::kAudioTrack);
}
RefPtr<WebMDemuxer::InitPromise>
@@ -228,39 +251,34 @@ WebMDemuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber)
}
nsresult
WebMDemuxer::Reset()
WebMDemuxer::Reset(TrackInfo::TrackType aType)
{
mVideoPackets.Reset();
mAudioPackets.Reset();
return NS_OK;
}
void
WebMDemuxer::Cleanup()
{
if (mContext) {
nestegg_destroy(mContext);
mContext = nullptr;
if (aType == TrackInfo::kVideoTrack) {
mVideoPackets.Reset();
} else {
mAudioPackets.Reset();
}
mBufferedState = nullptr;
return NS_OK;
}
nsresult
WebMDemuxer::ReadMetadata()
{
nestegg_io io;
io.read = webmdemux_read;
io.seek = webmdemux_seek;
io.tell = webmdemux_tell;
io.userdata = this;
int r = nestegg_init(&mContext, io, &webmdemux_log,
IsMediaSource() ? mResource.GetLength() : -1);
int r = mVideoContext.Init();
if (r == -1) {
return NS_ERROR_FAILURE;
}
if (mAudioContext.Init() == -1) {
return NS_ERROR_FAILURE;
}
// For reading the metadata we can only use the video resource/context.
MediaResourceIndex& resource = Resource(TrackInfo::kVideoTrack);
nestegg* context = Context(TrackInfo::kVideoTrack);
{
// Check how much data nestegg read and force feed it to BufferedState.
RefPtr<MediaByteBuffer> buffer = mResource.MediaReadAt(0, mResource.Tell());
RefPtr<MediaByteBuffer> buffer = resource.MediaReadAt(0, resource.Tell());
if (!buffer) {
return NS_ERROR_FAILURE;
}
@@ -268,33 +286,33 @@ WebMDemuxer::ReadMetadata()
if (mBufferedState->GetInitEndOffset() < 0) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mBufferedState->GetInitEndOffset() <= mResource.Tell());
MOZ_ASSERT(mBufferedState->GetInitEndOffset() <= resource.Tell());
}
mInitData = mResource.MediaReadAt(0, mBufferedState->GetInitEndOffset());
mInitData = resource.MediaReadAt(0, mBufferedState->GetInitEndOffset());
if (!mInitData ||
mInitData->Length() != size_t(mBufferedState->GetInitEndOffset())) {
return NS_ERROR_FAILURE;
}
unsigned int ntracks = 0;
r = nestegg_track_count(mContext, &ntracks);
r = nestegg_track_count(context, &ntracks);
if (r == -1) {
return NS_ERROR_FAILURE;
}
for (unsigned int track = 0; track < ntracks; ++track) {
int id = nestegg_track_codec_id(mContext, track);
int id = nestegg_track_codec_id(context, track);
if (id == -1) {
return NS_ERROR_FAILURE;
}
int type = nestegg_track_type(mContext, track);
int type = nestegg_track_type(context, track);
if (type == NESTEGG_TRACK_VIDEO && !mHasVideo) {
nestegg_video_params params;
r = nestegg_track_video_params(mContext, track, &params);
r = nestegg_track_video_params(context, track, &params);
if (r == -1) {
return NS_ERROR_FAILURE;
}
mVideoCodec = nestegg_track_codec_id(mContext, track);
mVideoCodec = nestegg_track_codec_id(context, track);
switch(mVideoCodec) {
case NESTEGG_CODEC_VP8:
mInfo.mVideo.mMimeType = "video/webm; codecs=vp8";
@@ -360,13 +378,13 @@ WebMDemuxer::ReadMetadata()
break;
}
uint64_t duration = 0;
r = nestegg_duration(mContext, &duration);
r = nestegg_duration(context, &duration);
if (!r) {
mInfo.mVideo.mDuration = media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
}
} else if (type == NESTEGG_TRACK_AUDIO && !mHasAudio) {
nestegg_audio_params params;
r = nestegg_track_audio_params(mContext, track, &params);
r = nestegg_track_audio_params(context, track, &params);
if (r == -1) {
return NS_ERROR_FAILURE;
}
@@ -374,7 +392,7 @@ WebMDemuxer::ReadMetadata()
mAudioTrack = track;
mHasAudio = true;
mCodecDelay = media::TimeUnit::FromNanoseconds(params.codec_delay).ToMicroseconds();
mAudioCodec = nestegg_track_codec_id(mContext, track);
mAudioCodec = nestegg_track_codec_id(context, track);
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
mInfo.mAudio.mMimeType = "audio/webm; codecs=vorbis";
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
@@ -388,7 +406,7 @@ WebMDemuxer::ReadMetadata()
mInfo.mAudio.mChannels = params.channels;
unsigned int nheaders = 0;
r = nestegg_track_codec_data_count(mContext, track, &nheaders);
r = nestegg_track_codec_data_count(context, track, &nheaders);
if (r == -1) {
return NS_ERROR_FAILURE;
}
@@ -398,7 +416,7 @@ WebMDemuxer::ReadMetadata()
for (uint32_t header = 0; header < nheaders; ++header) {
unsigned char* data = 0;
size_t length = 0;
r = nestegg_track_codec_data(mContext, track, header, &data, &length);
r = nestegg_track_codec_data(context, track, header, &data, &length);
if (r == -1) {
return NS_ERROR_FAILURE;
}
@@ -422,7 +440,7 @@ WebMDemuxer::ReadMetadata()
headerLens[0]);
}
uint64_t duration = 0;
r = nestegg_duration(mContext, &duration);
r = nestegg_duration(context, &duration);
if (!r) {
mInfo.mAudio.mDuration = media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
}
@@ -434,13 +452,15 @@ WebMDemuxer::ReadMetadata()
bool
WebMDemuxer::IsSeekable() const
{
return mContext && nestegg_has_cues(mContext);
return Context(TrackInfo::kVideoTrack) &&
nestegg_has_cues(Context(TrackInfo::kVideoTrack));
}
bool
WebMDemuxer::IsSeekableOnlyInBufferedRanges() const
{
return mContext && !nestegg_has_cues(mContext);
return Context(TrackInfo::kVideoTrack) &&
!nestegg_has_cues(Context(TrackInfo::kVideoTrack));
}
void
@@ -449,7 +469,8 @@ WebMDemuxer::EnsureUpToDateIndex()
if (!mNeedReIndex || !mInitData) {
return;
}
AutoPinned<MediaResource> resource(mResource.GetResource());
AutoPinned<MediaResource> resource(
Resource(TrackInfo::kVideoTrack).GetResource());
MediaByteRangeSet byteRanges;
nsresult rv = resource->GetCachedRanges(byteRanges);
if (NS_FAILED(rv) || !byteRanges.Length()) {
@@ -463,7 +484,7 @@ WebMDemuxer::EnsureUpToDateIndex()
return;
}
mLastWebMBlockOffset = mBufferedState->GetLastBlockOffset();
MOZ_ASSERT(mLastWebMBlockOffset <= mResource.GetLength());
MOZ_ASSERT(mLastWebMBlockOffset <= resource->GetLength());
}
void
@@ -510,8 +531,9 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
return false;
}
int64_t tstamp = holder->Timestamp();
int64_t duration = holder->Duration();
// The end time of this frame is the start time of the next frame. Fetch
// The end time of this frame is the start time of the next frame. Fetch
// the timestamp of the next packet for this track. If we've reached the
// end of the resource, use the file's duration as the end time of this
// video frame.
@@ -521,6 +543,8 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
if (next_holder) {
next_tstamp = next_holder->Timestamp();
PushAudioPacket(next_holder);
} else if (duration >= 0) {
next_tstamp = tstamp + duration;
} else if (!mIsMediaSource ||
(mIsMediaSource && mLastAudioFrameTime.isSome())) {
next_tstamp = tstamp;
@@ -534,6 +558,8 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
if (next_holder) {
next_tstamp = next_holder->Timestamp();
PushVideoPacket(next_holder);
} else if (duration >= 0) {
next_tstamp = tstamp + duration;
} else if (!mIsMediaSource ||
(mIsMediaSource && mLastVideoFrameTime.isSome())) {
next_tstamp = tstamp;
@@ -616,56 +642,45 @@ WebMDemuxer::NextPacket(TrackInfo::TrackType aType)
{
bool isVideo = aType == TrackInfo::kVideoTrack;
// The packet queue that packets will be pushed on if they
// are not the type we are interested in.
WebMPacketQueue& otherPackets = isVideo ? mAudioPackets : mVideoPackets;
// The packet queue for the type that we are interested in.
WebMPacketQueue &packets = isVideo ? mVideoPackets : mAudioPackets;
// Flag to indicate that we do need to playback these types of
// packets.
bool hasType = isVideo ? mHasVideo : mHasAudio;
// Flag to indicate that we do need to playback the other type
// of track.
bool hasOtherType = isVideo ? mHasAudio : mHasVideo;
if (!hasType) {
return nullptr;
}
// Track we are interested in
uint32_t ourTrack = isVideo ? mVideoTrack : mAudioTrack;
// Value of other track
uint32_t otherTrack = isVideo ? mAudioTrack : mVideoTrack;
// The packet queue for the type that we are interested in.
WebMPacketQueue &packets = isVideo ? mVideoPackets : mAudioPackets;
if (packets.GetSize() > 0) {
return packets.PopFront();
}
// Track we are interested in
uint32_t ourTrack = isVideo ? mVideoTrack : mAudioTrack;
do {
RefPtr<NesteggPacketHolder> holder = DemuxPacket();
RefPtr<NesteggPacketHolder> holder = DemuxPacket(aType);
if (!holder) {
return nullptr;
}
if (hasOtherType && otherTrack == holder->Track()) {
// Save the packet for when we want these packets
otherPackets.Push(holder);
continue;
}
// The packet is for the track we want to play
if (hasType && ourTrack == holder->Track()) {
if (ourTrack == holder->Track()) {
return holder;
}
} while (true);
}
RefPtr<NesteggPacketHolder>
WebMDemuxer::DemuxPacket()
WebMDemuxer::DemuxPacket(TrackInfo::TrackType aType)
{
nestegg_packet* packet;
int r = nestegg_read_packet(mContext, &packet);
if (r <= 0) {
int r = nestegg_read_packet(Context(aType), &packet);
if (r == 0) {
nestegg_read_reset(Context(aType));
return nullptr;
} else if (r < 0) {
return nullptr;
}
@@ -675,7 +690,7 @@ WebMDemuxer::DemuxPacket()
return nullptr;
}
int64_t offset = mResource.Tell();
int64_t offset = Resource(aType).Tell();
RefPtr<NesteggPacketHolder> holder = new NesteggPacketHolder();
if (!holder->Init(packet, offset, track, false)) {
return nullptr;
@@ -697,13 +712,14 @@ WebMDemuxer::PushVideoPacket(NesteggPacketHolder* aItem)
}
nsresult
WebMDemuxer::SeekInternal(const media::TimeUnit& aTarget)
WebMDemuxer::SeekInternal(TrackInfo::TrackType aType,
const media::TimeUnit& aTarget)
{
EnsureUpToDateIndex();
uint32_t trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
uint64_t target = aTarget.ToNanoseconds();
if (NS_FAILED(Reset())) {
if (NS_FAILED(Reset(aType))) {
return NS_ERROR_FAILURE;
}
@@ -724,7 +740,7 @@ WebMDemuxer::SeekInternal(const media::TimeUnit& aTarget)
media::TimeUnit::FromNanoseconds(startTime).ToSeconds(),
media::TimeUnit::FromNanoseconds(target).ToSeconds());
}
int r = nestegg_track_seek(mContext, trackToSeek, target);
int r = nestegg_track_seek(Context(aType), trackToSeek, target);
if (r == -1) {
WEBM_DEBUG("track_seek for track %u to %f failed, r=%d", trackToSeek,
media::TimeUnit::FromNanoseconds(target).ToSeconds(), r);
@@ -736,7 +752,7 @@ WebMDemuxer::SeekInternal(const media::TimeUnit& aTarget)
return NS_ERROR_FAILURE;
}
r = nestegg_offset_seek(mContext, offset);
r = nestegg_offset_seek(Context(aType), offset);
if (r == -1) {
WEBM_DEBUG("and nestegg_offset_seek to %" PRIu64 " failed", offset);
return NS_ERROR_FAILURE;
@@ -744,8 +760,11 @@ WebMDemuxer::SeekInternal(const media::TimeUnit& aTarget)
WEBM_DEBUG("got offset from buffered state: %" PRIu64 "", offset);
}
mLastAudioFrameTime.reset();
mLastVideoFrameTime.reset();
if (aType == TrackInfo::kAudioTrack) {
mLastAudioFrameTime.reset();
} else {
mLastVideoFrameTime.reset();
}
return NS_OK;
}
@@ -754,7 +773,8 @@ media::TimeIntervals
WebMDemuxer::GetBuffered()
{
EnsureUpToDateIndex();
AutoPinned<MediaResource> resource(mResource.GetResource());
AutoPinned<MediaResource> resource(
Resource(TrackInfo::kVideoTrack).GetResource());
media::TimeIntervals buffered;
@@ -765,7 +785,7 @@ WebMDemuxer::GetBuffered()
}
uint64_t duration = 0;
uint64_t startOffset = 0;
if (!nestegg_duration(mContext, &duration)) {
if (!nestegg_duration(Context(TrackInfo::kVideoTrack), &duration)) {
if(mBufferedState->GetStartTime(&startOffset)) {
duration += startOffset;
}
@@ -835,7 +855,7 @@ WebMTrackDemuxer::Seek(media::TimeUnit aTime)
media::TimeUnit seekTime = aTime;
mSamples.Reset();
mParent->SeekInternal(aTime);
mParent->SeekInternal(mType, aTime);
mParent->GetNextPacket(mType, &mSamples);
mNeedKeyframe = true;
@@ -892,7 +912,7 @@ WebMTrackDemuxer::GetSamples(int32_t aNumSamples)
void
WebMTrackDemuxer::SetNextKeyFrameTime()
{
if (mType != TrackInfo::kVideoTrack) {
if (mType != TrackInfo::kVideoTrack || mParent->IsMediaSource()) {
return;
}
@@ -956,7 +976,7 @@ WebMTrackDemuxer::Reset()
mNeedKeyframe = true;
if (buffered.Length()) {
WEBM_DEBUG("Seek to start point: %f", buffered.Start(0).ToSeconds());
mParent->SeekInternal(buffered.Start(0));
mParent->SeekInternal(mType, buffered.Start(0));
SetNextKeyFrameTime();
} else {
mNextKeyframeTime.reset();
@@ -991,11 +1011,13 @@ WebMTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
uint32_t parsed = 0;
bool found = false;
RefPtr<MediaRawData> sample;
int64_t sampleTime;
WEBM_DEBUG("TimeThreshold: %f", aTimeThreshold.ToSeconds());
while (!found && (sample = NextSample())) {
parsed++;
if (sample->mKeyframe && sample->mTime >= aTimeThreshold.ToMicroseconds()) {
sampleTime = sample->mTime;
if (sample->mKeyframe && sampleTime >= aTimeThreshold.ToMicroseconds()) {
found = true;
mSamples.Reset();
mSamples.PushFront(sample.forget());
@@ -1004,7 +1026,7 @@ WebMTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
SetNextKeyFrameTime();
if (found) {
WEBM_DEBUG("next sample: %f (parsed: %d)",
media::TimeUnit::FromMicroseconds(sample->mTime).ToSeconds(),
media::TimeUnit::FromMicroseconds(sampleTime).ToSeconds(),
parsed);
return SkipAccessPointPromise::CreateAndResolve(parsed, __func__);
} else {
@@ -1025,5 +1047,16 @@ WebMTrackDemuxer::BreakCycles()
mParent = nullptr;
}
int64_t
WebMTrackDemuxer::GetEvictionOffset(const media::TimeUnit& aTime)
{
int64_t offset;
if (!mParent->GetOffsetForTime(aTime.ToNanoseconds(), &offset)) {
return 0;
}
return offset;
}
#undef WEBM_DEBUG
} // namespace mozilla
+53 -20
View File
@@ -107,7 +107,7 @@ public:
// Demux next WebM packet and append samples to MediaRawDataQueue
bool GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSamples);
nsresult Reset();
nsresult Reset(TrackInfo::TrackType aType);
// Pushes a packet to the front of the audio packet queue.
void PushAudioPacket(NesteggPacketHolder* aItem);
@@ -116,33 +116,54 @@ public:
void PushVideoPacket(NesteggPacketHolder* aItem);
// Public accessor for nestegg callbacks
MediaResourceIndex* GetResource()
{
return &mResource;
}
int64_t GetEndDataOffset() const
{
return (!mIsMediaSource || mLastWebMBlockOffset < 0)
? mResource.GetLength() : mLastWebMBlockOffset;
}
int64_t IsMediaSource() const
bool IsMediaSource() const
{
return mIsMediaSource;
}
int64_t LastWebMBlockOffset() const
{
return mLastWebMBlockOffset;
}
struct NestEggContext {
NestEggContext(WebMDemuxer* aParent, MediaResource* aResource)
: mParent(aParent)
, mResource(aResource)
, mContext(nullptr) {}
~NestEggContext();
int Init();
// Public accessor for nestegg callbacks
bool IsMediaSource() const { return mParent->IsMediaSource(); }
MediaResourceIndex* GetResource() { return &mResource; }
int64_t GetEndDataOffset() const
{
return (!mParent->IsMediaSource() || mParent->LastWebMBlockOffset() < 0)
? mResource.GetLength() : mParent->LastWebMBlockOffset();
}
WebMDemuxer* mParent;
MediaResourceIndex mResource;
nestegg* mContext;
};
private:
friend class WebMTrackDemuxer;
~WebMDemuxer();
void Cleanup();
void InitBufferedState();
nsresult ReadMetadata();
void NotifyDataArrived() override;
void NotifyDataRemoved() override;
void EnsureUpToDateIndex();
media::TimeIntervals GetBuffered();
nsresult SeekInternal(const media::TimeUnit& aTarget);
nsresult SeekInternal(TrackInfo::TrackType aType,
const media::TimeUnit& aTarget);
// Read a packet from the nestegg file. Returns nullptr if all packets for
// the particular track have been read. Pass TrackInfo::kVideoTrack or
@@ -151,9 +172,23 @@ private:
// Internal method that demuxes the next packet from the stream. The caller
// is responsible for making sure it doesn't get lost.
RefPtr<NesteggPacketHolder> DemuxPacket();
RefPtr<NesteggPacketHolder> DemuxPacket(TrackInfo::TrackType aType);
// libnestegg audio and video context for webm container.
// Access on reader's thread only.
NestEggContext mVideoContext;
NestEggContext mAudioContext;
MediaResourceIndex& Resource(TrackInfo::TrackType aType)
{
return aType == TrackInfo::kVideoTrack
? mVideoContext.mResource : mAudioContext.mResource;
}
nestegg* Context(TrackInfo::TrackType aType) const
{
return aType == TrackInfo::kVideoTrack
? mVideoContext.mContext : mAudioContext.mContext;
}
MediaResourceIndex mResource;
MediaInfo mInfo;
nsTArray<RefPtr<WebMTrackDemuxer>> mDemuxers;
@@ -162,10 +197,6 @@ private:
RefPtr<WebMBufferedState> mBufferedState;
RefPtr<MediaByteBuffer> mInitData;
// libnestegg context for webm container.
// Access on reader's thread for main demuxer,
// or main thread for cloned demuxer
nestegg* mContext;
// Queue of video and audio packets that have been read but not decoded.
WebMPacketQueue mVideoPackets;
@@ -230,6 +261,8 @@ public:
media::TimeIntervals GetBuffered() override;
int64_t GetEvictionOffset(const media::TimeUnit& aTime) override;
void BreakCycles() override;
private:
@@ -26,13 +26,11 @@ SpeechStreamListener::~SpeechStreamListener()
}
void
SpeechStreamListener::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
TrackID aID,
StreamTime aTrackOffset,
uint32_t aTrackEvents,
const MediaSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID)
SpeechStreamListener::NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
const AudioSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID)
{
AudioSegment* audio = const_cast<AudioSegment*>(
static_cast<const AudioSegment*>(&aQueuedMedia));
@@ -24,12 +24,11 @@ public:
explicit SpeechStreamListener(SpeechRecognition* aRecognition);
~SpeechStreamListener();
void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
uint32_t aTrackEvents,
const MediaSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID) override;
void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
StreamTime aTrackOffset,
const AudioSegment& aQueuedMedia,
MediaStream* aInputStream,
TrackID aInputTrackID) override;
void NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event) override;
+3 -1
View File
@@ -10,11 +10,13 @@ nestegg_free_packet
nestegg_init
nestegg_offset_seek
nestegg_packet_count
nestegg_packet_discard_padding
nestegg_packet_data
nestegg_packet_discard_padding
nestegg_packet_duration
nestegg_packet_track
nestegg_packet_tstamp
nestegg_read_packet
nestegg_read_reset
nestegg_track_audio_params
nestegg_track_codec_data
nestegg_track_codec_data_count
@@ -1976,13 +1976,6 @@ public:
}
// Implement MediaStreamListener
void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
StreamTime offset,
uint32_t events,
const MediaSegment& queued_media,
MediaStream* input_stream,
TrackID input_tid) override {}
void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) override
{
MOZ_ASSERT(source_);
@@ -2138,14 +2131,7 @@ public:
#endif
}
// Implement MediaStreamListener
void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
StreamTime offset,
uint32_t events,
const MediaSegment& queued_media,
MediaStream* input_stream,
TrackID input_tid) override {}
void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) override
{
ReentrantMonitorAutoEnter enter(monitor_);
@@ -93,8 +93,13 @@ public:
uint32_t aTrackEvents,
const mozilla::MediaSegment& aQueuedMedia,
Fake_MediaStream* aInputStream,
mozilla::TrackID aInputTrackID) = 0;
mozilla::TrackID aInputTrackID) {}
virtual void NotifyPull(mozilla::MediaStreamGraph* aGraph, mozilla::StreamTime aDesiredTime) = 0;
virtual void NotifyQueuedAudioData(mozilla::MediaStreamGraph* aGraph, mozilla::TrackID aID,
mozilla::StreamTime aTrackOffset,
const mozilla::AudioSegment& aQueuedMedia,
Fake_MediaStream* aInputStream,
mozilla::TrackID aInputTrackID) {}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStreamListener)
};