mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1163486 - Update test to use new MP4Demuxer. r=bholley
This commit is contained in:
parent
d322b99ad7
commit
70882cfcd4
@ -4,32 +4,151 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
#include "MP4Demuxer.h"
|
||||
#include "MP4Stream.h"
|
||||
#include "MozPromise.h"
|
||||
#include "MediaDataDemuxer.h"
|
||||
#include "SharedThreadPool.h"
|
||||
#include "TaskQueue.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "MockMediaResource.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mp4_demuxer;
|
||||
|
||||
class AutoTaskQueue;
|
||||
|
||||
#define DO_FAIL []()->void { EXPECT_TRUE(false); }
|
||||
|
||||
class MP4DemuxerBinding
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MP4DemuxerBinding);
|
||||
|
||||
nsRefPtr<MockMediaResource> resource;
|
||||
Monitor mMonitor;
|
||||
nsRefPtr<MP4Demuxer> demuxer;
|
||||
nsRefPtr<MP4Demuxer> mDemuxer;
|
||||
nsRefPtr<TaskQueue> mTaskQueue;
|
||||
nsRefPtr<MediaTrackDemuxer> mAudioTrack;
|
||||
nsRefPtr<MediaTrackDemuxer> mVideoTrack;
|
||||
uint32_t mIndex;
|
||||
nsTArray<nsRefPtr<MediaRawData>> mSamples;
|
||||
nsTArray<int64_t> mKeyFrameTimecodes;
|
||||
MozPromiseHolder<GenericPromise> mCheckTrackKeyFramePromise;
|
||||
MozPromiseHolder<GenericPromise> mCheckTrackSamples;
|
||||
|
||||
explicit MP4DemuxerBinding(const char* aFileName = "dash_dashinit.mp4")
|
||||
: resource(new MockMediaResource(aFileName))
|
||||
, mMonitor("TestMP4Demuxer monitor")
|
||||
, demuxer(new MP4Demuxer(new MP4Stream(resource), &mMonitor))
|
||||
, mDemuxer(new MP4Demuxer(resource))
|
||||
, mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
|
||||
, mIndex(0)
|
||||
{
|
||||
EXPECT_EQ(NS_OK, resource->Open(nullptr));
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
void RunTestAndWait(const Function& aFunction)
|
||||
{
|
||||
Function func(aFunction);
|
||||
mDemuxer->Init()->Then(mTaskQueue, __func__, Move(func), DO_FAIL);
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise>
|
||||
CheckTrackKeyFrame(MediaTrackDemuxer* aTrackDemuxer)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
nsRefPtr<MediaTrackDemuxer> track = aTrackDemuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> self = this;
|
||||
|
||||
int64_t time = -1;
|
||||
while (mIndex < mSamples.Length()) {
|
||||
uint32_t i = mIndex++;
|
||||
if (mSamples[i]->mKeyframe) {
|
||||
time = mSamples[i]->mTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise> p = mCheckTrackKeyFramePromise.Ensure(__func__);
|
||||
|
||||
if (time == -1) {
|
||||
mCheckTrackKeyFramePromise.Resolve(true, __func__);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
DispatchTask(
|
||||
[track, time, self] () {
|
||||
track->Seek(media::TimeUnit::FromMicroseconds(time))->Then(self->mTaskQueue, __func__,
|
||||
[track, time, self] () {
|
||||
track->GetSamples()->Then(self->mTaskQueue, __func__,
|
||||
[track, time, self] (nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
|
||||
EXPECT_EQ(time, aSamples->mSamples[0]->mTime);
|
||||
self->CheckTrackKeyFrame(track);
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise>
|
||||
CheckTrackSamples(MediaTrackDemuxer* aTrackDemuxer)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
nsRefPtr<MediaTrackDemuxer> track = aTrackDemuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> self = this;
|
||||
|
||||
nsRefPtr<GenericPromise> p = mCheckTrackSamples.Ensure(__func__);
|
||||
|
||||
DispatchTask(
|
||||
[track, self] () {
|
||||
track->GetSamples()->Then(self->mTaskQueue, __func__,
|
||||
[track, self] (nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
|
||||
if (aSamples->mSamples.Length()) {
|
||||
self->mSamples.AppendElements(aSamples->mSamples);
|
||||
self->CheckTrackSamples(track);
|
||||
}
|
||||
},
|
||||
[self] (DemuxerFailureReason aReason) {
|
||||
if (aReason == DemuxerFailureReason::DEMUXER_ERROR) {
|
||||
EXPECT_TRUE(false);
|
||||
self->mCheckTrackSamples.Reject(NS_ERROR_FAILURE, __func__);
|
||||
} else if (aReason == DemuxerFailureReason::END_OF_STREAM) {
|
||||
EXPECT_TRUE(self->mSamples.Length() > 1);
|
||||
for (uint32_t i = 0; i < (self->mSamples.Length() - 1); i++) {
|
||||
EXPECT_LT(self->mSamples[i]->mTimecode, self->mSamples[i + 1]->mTimecode);
|
||||
if (self->mSamples[i]->mKeyframe) {
|
||||
self->mKeyFrameTimecodes.AppendElement(self->mSamples[i]->mTimecode);
|
||||
}
|
||||
}
|
||||
self->mCheckTrackSamples.Resolve(true, __func__);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename FunctionType>
|
||||
void
|
||||
DispatchTask(FunctionType aFun)
|
||||
{
|
||||
nsRefPtr<nsRunnable> r = NS_NewRunnableFunction(aFun);
|
||||
mTaskQueue->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
virtual ~MP4DemuxerBinding()
|
||||
{
|
||||
}
|
||||
@ -37,30 +156,20 @@ private:
|
||||
|
||||
TEST(MP4Demuxer, Seek)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding();
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding();
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
|
||||
nsTArray<nsRefPtr<MediaRawData>> samples;
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
samples.AppendElement(sample);
|
||||
if (samples.Length() >= 2) {
|
||||
EXPECT_LT(samples[samples.Length() - 2]->mTimecode,
|
||||
samples[samples.Length() - 1]->mTimecode);
|
||||
}
|
||||
}
|
||||
Microseconds keyFrame = 0;
|
||||
for (size_t i = 0; i < samples.Length(); i++) {
|
||||
if (samples[i]->mKeyframe) {
|
||||
keyFrame = samples[i]->mTimecode;
|
||||
}
|
||||
d->SeekVideo(samples[i]->mTime);
|
||||
sample = d->DemuxVideoSample();
|
||||
EXPECT_EQ(keyFrame, sample->mTimecode);
|
||||
}
|
||||
binding->RunTestAndWait([binding] () {
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->CheckTrackSamples(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
binding->CheckTrackKeyFrame(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
}, DO_FAIL);
|
||||
});
|
||||
}
|
||||
|
||||
static nsCString
|
||||
@ -87,14 +196,10 @@ ToCryptoString(const CryptoSample& aCrypto)
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef XP_WIN // VC2013 doesn't support C++11 array initialization.
|
||||
|
||||
TEST(MP4Demuxer, CENCFrag)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
|
||||
const char* video[] = {
|
||||
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000000 5,684 5,16980",
|
||||
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000450 5,1826",
|
||||
@ -158,13 +263,22 @@ TEST(MP4Demuxer, CENCFrag)
|
||||
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000019cd 5,2392",
|
||||
};
|
||||
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
size_t i = 0;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
nsCString text = ToCryptoString(sample->mCrypto);
|
||||
EXPECT_STREQ(video[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(video), i);
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
binding->RunTestAndWait([binding, video] () {
|
||||
// grab all video samples.
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->CheckTrackSamples(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding, video] () {
|
||||
for (uint32_t i = 0; i < binding->mSamples.Length(); i++) {
|
||||
nsCString text = ToCryptoString(binding->mSamples[i]->mCrypto);
|
||||
EXPECT_STREQ(video[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(video), binding->mSamples.Length());
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
});
|
||||
|
||||
const char* audio[] = {
|
||||
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000000 0,281",
|
||||
@ -262,42 +376,52 @@ TEST(MP4Demuxer, CENCFrag)
|
||||
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008cd 0,433",
|
||||
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008e9 0,481",
|
||||
};
|
||||
nsRefPtr<MP4DemuxerBinding> audiobinding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
i = 0;
|
||||
while (!!(sample = d->DemuxAudioSample())) {
|
||||
nsCString text = ToCryptoString(sample->mCrypto);
|
||||
EXPECT_STREQ(audio[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(audio), i);
|
||||
audiobinding->RunTestAndWait([audiobinding, audio] () {
|
||||
// grab all audio samples.
|
||||
audiobinding->mAudioTrack = audiobinding->mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
|
||||
audiobinding->CheckTrackSamples(audiobinding->mAudioTrack)
|
||||
->Then(audiobinding->mTaskQueue, __func__,
|
||||
[audiobinding, audio] () {
|
||||
EXPECT_TRUE(audiobinding->mSamples.Length() > 1);
|
||||
for (uint32_t i = 0; i < audiobinding->mSamples.Length(); i++) {
|
||||
nsCString text = ToCryptoString(audiobinding->mSamples[i]->mCrypto);
|
||||
EXPECT_STREQ(audio[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(audio), audiobinding->mSamples.Length());
|
||||
audiobinding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(MP4Demuxer, GetNextKeyframe)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
binding->RunTestAndWait([binding] () {
|
||||
// Insert a [0,end] buffered range, to simulate Moof's being buffered
|
||||
// via MSE.
|
||||
auto len = binding->resource->GetLength();
|
||||
binding->resource->MockAddBufferedRange(0, len);
|
||||
|
||||
// Insert a [0,end] buffered range, to simulate Moof's being buffered
|
||||
// via MSE.
|
||||
auto len = b->resource->GetLength();
|
||||
b->resource->MockAddBufferedRange(0, len);
|
||||
|
||||
// Rebuild the index so that it can be used to find the keyframes.
|
||||
nsTArray<MediaByteRange> ranges;
|
||||
EXPECT_TRUE(NS_SUCCEEDED(b->resource->GetCachedRanges(ranges)));
|
||||
d->UpdateIndex(ranges);
|
||||
|
||||
// gizmp-frag has two keyframes; one at dts=cts=0, and another at
|
||||
// dts=cts=1000000. Verify we get expected results.
|
||||
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
size_t i = 0;
|
||||
const int64_t keyframe = 1000000;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
int64_t expected = (sample->mTimecode < keyframe) ? keyframe : -1;
|
||||
EXPECT_EQ(d->GetNextKeyframeTime(), expected);
|
||||
i++;
|
||||
}
|
||||
// gizmp-frag has two keyframes; one at dts=cts=0, and another at
|
||||
// dts=cts=1000000. Verify we get expected results.
|
||||
media::TimeUnit time;
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->mVideoTrack->Reset();
|
||||
binding->mVideoTrack->GetNextRandomAccessPoint(&time);
|
||||
EXPECT_EQ(time.ToMicroseconds(), 0);
|
||||
binding->mVideoTrack->GetSamples()->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
media::TimeUnit time;
|
||||
binding->mVideoTrack->GetNextRandomAccessPoint(&time);
|
||||
EXPECT_EQ(time.ToMicroseconds(), 1000000);
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ UNIFIED_SOURCES += [
|
||||
'TestIntervalSet.cpp',
|
||||
'TestMozPromise.cpp',
|
||||
'TestMP3Demuxer.cpp',
|
||||
'TestMP4Demuxer.cpp',
|
||||
# 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
|
||||
'TestTrackEncoder.cpp',
|
||||
'TestVideoSegment.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user