mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
[webm] Treat demuxing errors differently than EOS
Otherwise the WebM demuxer makes no difference between a genuine EOS and encountering an error.
This commit is contained in:
parent
dfcff1dfbc
commit
64b9480493
2 changed files with 75 additions and 41 deletions
|
|
@ -547,7 +547,7 @@ WebMDemuxer::GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber) {
|
|||
return crypto;
|
||||
}
|
||||
|
||||
bool
|
||||
nsresult
|
||||
WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSamples)
|
||||
{
|
||||
if (mIsMediaSource) {
|
||||
|
|
@ -555,17 +555,18 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
EnsureUpToDateIndex();
|
||||
}
|
||||
|
||||
RefPtr<NesteggPacketHolder> holder(NextPacket(aType));
|
||||
RefPtr<NesteggPacketHolder> holder;
|
||||
nsresult rv = NextPacket(aType, holder);
|
||||
|
||||
if (!holder) {
|
||||
return false;
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
int r = 0;
|
||||
unsigned int count = 0;
|
||||
r = nestegg_packet_count(holder->Packet(), &count);
|
||||
if (r == -1) {
|
||||
return false;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
int64_t tstamp = holder->Timestamp();
|
||||
int64_t duration = holder->Duration();
|
||||
|
|
@ -576,7 +577,11 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
// video frame.
|
||||
int64_t next_tstamp = INT64_MIN;
|
||||
if (aType == TrackInfo::kAudioTrack) {
|
||||
RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
|
||||
RefPtr<NesteggPacketHolder> next_holder;
|
||||
rv = NextPacket(aType, next_holder);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
|
||||
return rv;
|
||||
}
|
||||
if (next_holder) {
|
||||
next_tstamp = next_holder->Timestamp();
|
||||
PushAudioPacket(next_holder);
|
||||
|
|
@ -591,7 +596,11 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
}
|
||||
mLastAudioFrameTime = Some(tstamp);
|
||||
} else if (aType == TrackInfo::kVideoTrack) {
|
||||
RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
|
||||
RefPtr<NesteggPacketHolder> next_holder;
|
||||
rv = NextPacket(aType, next_holder);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
|
||||
return rv;
|
||||
}
|
||||
if (next_holder) {
|
||||
next_tstamp = next_holder->Timestamp();
|
||||
PushVideoPacket(next_holder);
|
||||
|
|
@ -608,7 +617,7 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
}
|
||||
|
||||
if (mIsMediaSource && next_tstamp == INT64_MIN) {
|
||||
return false;
|
||||
return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
|
||||
}
|
||||
|
||||
int64_t discardPadding = 0;
|
||||
|
|
@ -624,7 +633,7 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
r = nestegg_packet_data(holder->Packet(), i, &data, &length);
|
||||
if (r == -1) {
|
||||
WEBM_DEBUG("nestegg_packet_data failed r=%d", r);
|
||||
return false;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
bool isKeyframe = false;
|
||||
if (aType == TrackInfo::kAudioTrack) {
|
||||
|
|
@ -668,7 +677,7 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
RefPtr<MediaRawData> sample = new MediaRawData(data, length);
|
||||
if (length && !sample->Data()) {
|
||||
// OOM.
|
||||
return false;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
sample->mTimecode = tstamp;
|
||||
sample->mTime = tstamp;
|
||||
|
|
@ -721,11 +730,12 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl
|
|||
}
|
||||
aSamples->Push(sample);
|
||||
}
|
||||
return true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<NesteggPacketHolder>
|
||||
WebMDemuxer::NextPacket(TrackInfo::TrackType aType)
|
||||
nsresult
|
||||
WebMDemuxer::NextPacket(TrackInfo::TrackType aType,
|
||||
RefPtr<NesteggPacketHolder>& aPacket)
|
||||
{
|
||||
bool isVideo = aType == TrackInfo::kVideoTrack;
|
||||
|
||||
|
|
@ -734,56 +744,64 @@ WebMDemuxer::NextPacket(TrackInfo::TrackType aType)
|
|||
bool hasType = isVideo ? mHasVideo : mHasAudio;
|
||||
|
||||
if (!hasType) {
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
|
||||
// The packet queue for the type that we are interested in.
|
||||
WebMPacketQueue &packets = isVideo ? mVideoPackets : mAudioPackets;
|
||||
|
||||
if (packets.GetSize() > 0) {
|
||||
return packets.PopFront();
|
||||
aPacket = packets.PopFront();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Track we are interested in
|
||||
uint32_t ourTrack = isVideo ? mVideoTrack : mAudioTrack;
|
||||
|
||||
do {
|
||||
RefPtr<NesteggPacketHolder> holder = DemuxPacket(aType);
|
||||
RefPtr<NesteggPacketHolder> holder;
|
||||
nsresult rv = DemuxPacket(aType, holder);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!holder) {
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
|
||||
if (ourTrack == holder->Track()) {
|
||||
return holder;
|
||||
aPacket = holder;
|
||||
return NS_OK;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
RefPtr<NesteggPacketHolder>
|
||||
WebMDemuxer::DemuxPacket(TrackInfo::TrackType aType)
|
||||
nsresult
|
||||
WebMDemuxer::DemuxPacket(TrackInfo::TrackType aType,
|
||||
RefPtr<NesteggPacketHolder>& aPacket)
|
||||
{
|
||||
nestegg_packet* packet;
|
||||
int r = nestegg_read_packet(Context(aType), &packet);
|
||||
if (r == 0) {
|
||||
nestegg_read_reset(Context(aType));
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
|
||||
} else if (r < 0) {
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
|
||||
unsigned int track = 0;
|
||||
r = nestegg_packet_track(packet, &track);
|
||||
if (r == -1) {
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
|
||||
int64_t offset = Resource(aType).Tell();
|
||||
RefPtr<NesteggPacketHolder> holder = new NesteggPacketHolder();
|
||||
if (!holder->Init(packet, offset, track, false)) {
|
||||
return nullptr;
|
||||
return NS_ERROR_DOM_MEDIA_DEMUXER_ERR;
|
||||
}
|
||||
|
||||
return holder;
|
||||
aPacket = holder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -943,7 +961,10 @@ WebMTrackDemuxer::Seek(media::TimeUnit aTime)
|
|||
media::TimeUnit seekTime = aTime;
|
||||
mSamples.Reset();
|
||||
mParent->SeekInternal(mType, aTime);
|
||||
mParent->GetNextPacket(mType, &mSamples);
|
||||
nsresult rv = mParent->GetNextPacket(mType, &mSamples);
|
||||
if (NS_FAILED(rv)) {
|
||||
return SeekPromise::CreateAndReject(rv, __func__);
|
||||
}
|
||||
mNeedKeyframe = true;
|
||||
|
||||
// Check what time we actually seeked to.
|
||||
|
|
@ -956,15 +977,18 @@ WebMTrackDemuxer::Seek(media::TimeUnit aTime)
|
|||
return SeekPromise::CreateAndResolve(seekTime, __func__);
|
||||
}
|
||||
|
||||
RefPtr<MediaRawData>
|
||||
WebMTrackDemuxer::NextSample()
|
||||
nsresult
|
||||
WebMTrackDemuxer::NextSample(RefPtr<MediaRawData>& aData)
|
||||
{
|
||||
while (mSamples.GetSize() < 1 && mParent->GetNextPacket(mType, &mSamples)) {
|
||||
nsresult rv;
|
||||
while (mSamples.GetSize() < 1 &&
|
||||
NS_SUCCEEDED((rv = mParent->GetNextPacket(mType, &mSamples)))) {
|
||||
}
|
||||
if (mSamples.GetSize()) {
|
||||
return mSamples.PopFront();
|
||||
aData = mSamples.PopFront();
|
||||
return NS_OK;
|
||||
}
|
||||
return nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
RefPtr<WebMTrackDemuxer::SamplesPromise>
|
||||
|
|
@ -973,9 +997,12 @@ WebMTrackDemuxer::GetSamples(int32_t aNumSamples)
|
|||
RefPtr<SamplesHolder> samples = new SamplesHolder;
|
||||
MOZ_ASSERT(aNumSamples);
|
||||
|
||||
nsresult rv = NS_ERROR_DOM_MEDIA_END_OF_STREAM;
|
||||
|
||||
while (aNumSamples) {
|
||||
RefPtr<MediaRawData> sample(NextSample());
|
||||
if (!sample) {
|
||||
RefPtr<MediaRawData> sample;
|
||||
rv = NextSample(sample);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
if (mNeedKeyframe && !sample->mKeyframe) {
|
||||
|
|
@ -987,7 +1014,7 @@ WebMTrackDemuxer::GetSamples(int32_t aNumSamples)
|
|||
}
|
||||
|
||||
if (samples->mSamples.IsEmpty()) {
|
||||
return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
|
||||
return SamplesPromise::CreateAndReject(rv, __func__);
|
||||
} else {
|
||||
UpdateSamples(samples->mSamples);
|
||||
return SamplesPromise::CreateAndResolve(samples, __func__);
|
||||
|
|
@ -1022,7 +1049,8 @@ WebMTrackDemuxer::SetNextKeyFrameTime()
|
|||
}
|
||||
// Demux and buffer frames until we find a keyframe.
|
||||
RefPtr<MediaRawData> sample;
|
||||
while (!foundKeyframe && (sample = NextSample())) {
|
||||
nsresult rv = NS_OK;
|
||||
while (!foundKeyframe && NS_SUCCEEDED((rv = NextSample(sample)))) {
|
||||
if (sample->mKeyframe) {
|
||||
frameTime = sample->mTime;
|
||||
foundKeyframe = true;
|
||||
|
|
@ -1104,10 +1132,11 @@ WebMTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
|
|||
uint32_t parsed = 0;
|
||||
bool found = false;
|
||||
RefPtr<MediaRawData> sample;
|
||||
nsresult rv = NS_OK;
|
||||
int64_t sampleTime;
|
||||
|
||||
WEBM_DEBUG("TimeThreshold: %f", aTimeThreshold.ToSeconds());
|
||||
while (!found && (sample = NextSample())) {
|
||||
while (!found && NS_SUCCEEDED((rv = NextSample(sample)))) {
|
||||
parsed++;
|
||||
sampleTime = sample->mTime;
|
||||
if (sample->mKeyframe && sampleTime >= aTimeThreshold.ToMicroseconds()) {
|
||||
|
|
@ -1116,7 +1145,9 @@ WebMTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
|
|||
mSamples.PushFront(sample.forget());
|
||||
}
|
||||
}
|
||||
SetNextKeyFrameTime();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetNextKeyFrameTime();
|
||||
}
|
||||
if (found) {
|
||||
WEBM_DEBUG("next sample: %f (parsed: %d)",
|
||||
media::TimeUnit::FromMicroseconds(sampleTime).ToSeconds(),
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ public:
|
|||
bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
|
||||
|
||||
// Demux next WebM packet and append samples to MediaRawDataQueue
|
||||
bool GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSamples);
|
||||
nsresult GetNextPacket(TrackInfo::TrackType aType,
|
||||
MediaRawDataQueue *aSamples);
|
||||
|
||||
nsresult Reset(TrackInfo::TrackType aType);
|
||||
|
||||
|
|
@ -175,11 +176,13 @@ private:
|
|||
// Read a packet from the nestegg file. Returns nullptr if all packets for
|
||||
// the particular track have been read. Pass TrackInfo::kVideoTrack or
|
||||
// TrackInfo::kVideoTrack to indicate the type of the packet we want to read.
|
||||
RefPtr<NesteggPacketHolder> NextPacket(TrackInfo::TrackType aType);
|
||||
nsresult NextPacket(TrackInfo::TrackType aType,
|
||||
RefPtr<NesteggPacketHolder>& aPacket);
|
||||
|
||||
// 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(TrackInfo::TrackType aType);
|
||||
nsresult DemuxPacket(TrackInfo::TrackType aType,
|
||||
RefPtr<NesteggPacketHolder>& aPacket);
|
||||
|
||||
// libnestegg audio and video context for webm container.
|
||||
// Access on reader's thread only.
|
||||
|
|
@ -275,7 +278,7 @@ private:
|
|||
~WebMTrackDemuxer();
|
||||
void UpdateSamples(nsTArray<RefPtr<MediaRawData>>& aSamples);
|
||||
void SetNextKeyFrameTime();
|
||||
RefPtr<MediaRawData> NextSample ();
|
||||
nsresult NextSample(RefPtr<MediaRawData>& aData);
|
||||
RefPtr<WebMDemuxer> mParent;
|
||||
TrackInfo::TrackType mType;
|
||||
UniquePtr<TrackInfo> mInfo;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue