mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 1879417 - part2 : resolve pending input promise when sample is popped. r=jolin
The problem is discovered when playing the file `red-46x48.mp4` in `test_playback_rate_playpause.html`. That file only contains ONE frame which is 1 second long. There is an issue within the media engine, which The won't return an output frame to us, unless we tell it the stream is ended. Therefore, after sending the only frame to the media engine, we need to (1) keep the media format reader to keep requesting data by resolving the pending promise when the input has been popped so that the format reader can read EOS. (2) send the ended event to the media engine in order to get the first frame. Differential Revision: https://phabricator.services.mozilla.com/D202336
This commit is contained in:
parent
3c2b7163fc
commit
46389a0493
@ -282,17 +282,8 @@ void MFMediaEngineStream::ReplySampleRequestIfPossible() {
|
||||
while (!mSampleRequestTokens.empty()) {
|
||||
mSampleRequestTokens.pop();
|
||||
}
|
||||
|
||||
SLOG("Notify end events");
|
||||
MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() == 0);
|
||||
MOZ_ASSERT(mSampleRequestTokens.empty());
|
||||
RETURN_VOID_IF_FAILED(mMediaEventQueue->QueueEventParamUnk(
|
||||
MEEndOfStream, GUID_NULL, S_OK, nullptr));
|
||||
mEndedEvent.Notify(TrackType());
|
||||
PROFILER_MARKER_TEXT(
|
||||
"MFMediaEngineStream:NotifyEnd", MEDIA_PLAYBACK, {},
|
||||
nsPrintfCString("stream=%s, id=%" PRIu64, GetDescriptionName().get(),
|
||||
mStreamId));
|
||||
NotifyEndEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -318,6 +309,18 @@ void MFMediaEngineStream::ReplySampleRequestIfPossible() {
|
||||
MEMediaSample, GUID_NULL, S_OK, inputSample.Get()));
|
||||
}
|
||||
|
||||
void MFMediaEngineStream::NotifyEndEvent() {
|
||||
AssertOnTaskQueue();
|
||||
SLOG("Notify end event");
|
||||
MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() == 0);
|
||||
RETURN_VOID_IF_FAILED(mMediaEventQueue->QueueEventParamUnk(
|
||||
MEEndOfStream, GUID_NULL, S_OK, nullptr));
|
||||
mEndedEvent.Notify(TrackType());
|
||||
PROFILER_MARKER_TEXT("MFMediaEngineStream:NotifyEnd", MEDIA_PLAYBACK, {},
|
||||
nsPrintfCString("stream=%s, id=%" PRIu64,
|
||||
GetDescriptionName().get(), mStreamId));
|
||||
}
|
||||
|
||||
bool MFMediaEngineStream::ShouldServeSamples() const {
|
||||
AssertOnTaskQueue();
|
||||
return mParentSource &&
|
||||
|
@ -133,11 +133,13 @@ class MFMediaEngineStream
|
||||
// should uses `mRawDataQueueForGeneratingOutput` to generate output.
|
||||
virtual already_AddRefed<MediaData> OutputDataInternal() = 0;
|
||||
|
||||
void SendRequestSampleEvent(bool aIsEnough);
|
||||
virtual void SendRequestSampleEvent(bool aIsEnough);
|
||||
|
||||
HRESULT AddEncryptAttributes(IMFSample* aSample,
|
||||
const CryptoSample& aCryptoConfig);
|
||||
|
||||
void NotifyEndEvent();
|
||||
|
||||
void AssertOnTaskQueue() const;
|
||||
void AssertOnMFThreadPool() const;
|
||||
|
||||
|
@ -287,6 +287,16 @@ RefPtr<MediaDataDecoder::DecodePromise> MFMediaEngineVideoStream::Drain() {
|
||||
MediaDataDecoder::DecodedData outputs;
|
||||
if (!IsDCompImageReady()) {
|
||||
LOGV("Waiting for dcomp image for draining");
|
||||
// A workaround for a special case where we have sent all input data to the
|
||||
// media engine, and waiting for an output. Sometime media engine would
|
||||
// never return the first frame to us, unless we notify it the end event,
|
||||
// which happens on the case where the video only contains one frame. If we
|
||||
// don't send end event to the media engine, the drain promise would be
|
||||
// pending forever.
|
||||
if (!mSampleRequestTokens.empty() &&
|
||||
mRawDataQueueForFeedingEngine.GetSize() == 0) {
|
||||
NotifyEndEvent();
|
||||
}
|
||||
return mPendingDrainPromise.Ensure(__func__);
|
||||
}
|
||||
return MFMediaEngineStream::Drain();
|
||||
@ -390,6 +400,18 @@ void MFMediaEngineVideoStream::ShutdownCleanUpOnTaskQueue() {
|
||||
__func__);
|
||||
}
|
||||
|
||||
void MFMediaEngineVideoStream::SendRequestSampleEvent(bool aIsEnough) {
|
||||
AssertOnTaskQueue();
|
||||
MFMediaEngineStream::SendRequestSampleEvent(aIsEnough);
|
||||
// We need more data to be sent in, we should resolve the promise to allow
|
||||
// more input data to be sent.
|
||||
if (!aIsEnough && !mVideoDecodeBeforeDcompPromise.IsEmpty()) {
|
||||
LOG("Resolved pending input promise to allow more input be sent in");
|
||||
mVideoDecodeBeforeDcompPromise.Resolve(MediaDataDecoder::DecodedData{},
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
bool MFMediaEngineVideoStream::IsEnded() const {
|
||||
AssertOnTaskQueue();
|
||||
// If a video only contains one frame, the media engine won't return a decoded
|
||||
|
@ -89,6 +89,8 @@ class MFMediaEngineVideoStream final : public MFMediaEngineStream {
|
||||
// data, which we actually don't need that many.
|
||||
bool ShouldDelayVideoDecodeBeforeDcompReady();
|
||||
|
||||
void SendRequestSampleEvent(bool aIsEnough) override;
|
||||
|
||||
// Task queue only members.
|
||||
HANDLE mDCompSurfaceHandle;
|
||||
bool mNeedRecreateImage;
|
||||
|
Loading…
Reference in New Issue
Block a user