mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1294154: Handle case where WMF is unable to determine time and duration. r=mattwoodrow
The WMF decoder doesn't handle well the case where a single frame was given to decode. When draining, the output is a correctly decoded frame but with a time of 0 and a duration set at 1/30th. This is a workaround MozReview-Commit-ID: JbjgNmPXKIM --HG-- extra : rebase_source : f25a1fd503678383265ec5053b41f3116ff52da0
This commit is contained in:
parent
d98e95abb8
commit
747d2faea4
@ -37,12 +37,13 @@ public:
|
||||
virtual HRESULT Output(int64_t aStreamOffset,
|
||||
RefPtr<MediaData>& aOutput) = 0;
|
||||
|
||||
void Flush() {
|
||||
virtual void Flush()
|
||||
{
|
||||
mDecoder->Flush();
|
||||
mSeekTargetThreshold.reset();
|
||||
}
|
||||
|
||||
void Drain()
|
||||
virtual void Drain()
|
||||
{
|
||||
if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
|
||||
NS_WARNING("Failed to send DRAIN command to MFT");
|
||||
|
@ -525,6 +525,8 @@ WMFVideoMFTManager::Input(MediaRawData* aSample)
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr) && mLastInput != nullptr, hr);
|
||||
|
||||
mLastDuration = aSample->mDuration;
|
||||
mLastTime = aSample->mTime;
|
||||
mSamplesCount++;
|
||||
|
||||
// Forward sample data to the decoder.
|
||||
return mDecoder->Input(mLastInput);
|
||||
@ -832,6 +834,15 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||
HRESULT hr;
|
||||
aOutData = nullptr;
|
||||
int typeChangeCount = 0;
|
||||
bool wasDraining = mDraining;
|
||||
int64_t sampleCount = mSamplesCount;
|
||||
if (wasDraining) {
|
||||
mSamplesCount = 0;
|
||||
mDraining = false;
|
||||
}
|
||||
|
||||
media::TimeUnit pts;
|
||||
media::TimeUnit duration;
|
||||
|
||||
// Loop until we decode a sample, or an unexpected error that we can't
|
||||
// handle occurs.
|
||||
@ -873,12 +884,21 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pts = GetSampleTime(sample);
|
||||
duration = GetSampleDuration(sample);
|
||||
if (!pts.IsValid() || !duration.IsValid()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
if (wasDraining && sampleCount == 1 && pts == media::TimeUnit()) {
|
||||
// WMF is unable to calculate a duration if only a single sample
|
||||
// was parsed. Additionally, the pts always comes out at 0 under those
|
||||
// circumstances.
|
||||
// Seeing that we've only fed the decoder a single frame, the pts
|
||||
// and duration are known, it's of the last sample.
|
||||
pts = media::TimeUnit::FromMicroseconds(mLastTime);
|
||||
duration = media::TimeUnit::FromMicroseconds(mLastDuration);
|
||||
}
|
||||
if (mSeekTargetThreshold.isSome()) {
|
||||
media::TimeUnit pts = GetSampleTime(sample);
|
||||
media::TimeUnit duration = GetSampleDuration(sample);
|
||||
if (!pts.IsValid() || !duration.IsValid()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
if ((pts + duration) < mSeekTargetThreshold.ref()) {
|
||||
LOG("Dropping video frame which pts is smaller than seek target.");
|
||||
// It is necessary to clear the pointer to release the previous output
|
||||
@ -907,6 +927,9 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||
NS_ENSURE_TRUE(frame, E_FAIL);
|
||||
|
||||
aOutData = frame;
|
||||
// Set the potentially corrected pts and duration.
|
||||
aOutData->mTime = pts.ToMicroseconds();
|
||||
aOutData->mDuration = duration.ToMicroseconds();
|
||||
|
||||
if (mNullOutputCount) {
|
||||
mGotValidOutputAfterNullOutput = true;
|
||||
|
@ -49,6 +49,19 @@ public:
|
||||
? "wmf hardware video decoder" : "wmf software video decoder";
|
||||
}
|
||||
|
||||
void Flush() override
|
||||
{
|
||||
MFTManager::Flush();
|
||||
mDraining = false;
|
||||
mSamplesCount = 0;
|
||||
}
|
||||
|
||||
void Drain() override
|
||||
{
|
||||
MFTManager::Drain();
|
||||
mDraining = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool ValidateVideoInfo();
|
||||
@ -81,6 +94,9 @@ private:
|
||||
|
||||
RefPtr<IMFSample> mLastInput;
|
||||
float mLastDuration;
|
||||
int64_t mLastTime = 0;
|
||||
bool mDraining = false;
|
||||
int64_t mSamplesCount = 0;
|
||||
|
||||
bool mDXVAEnabled;
|
||||
const layers::LayersBackend mLayersBackend;
|
||||
|
Loading…
Reference in New Issue
Block a user