예제 #1
0
HRESULT
MFTDecoder::SetMediaTypes(IMFMediaType* aInputType,
                          const GUID& aOutputSubType)
{
  mOutputSubtype = aOutputSubType;

  // Set the input type to the one the caller gave us...
  HRESULT hr = mDecoder->SetInputType(0, aInputType, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = SetDecoderOutputType();
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  mMFTProvidesOutputSamples = IsFlagSet(mOutputStreamInfo.dwFlags, MFT_OUTPUT_STREAM_PROVIDES_SAMPLES);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  return S_OK;
}
예제 #2
0
HRESULT
MFTDecoder::SetMediaTypes(IMFMediaType* aInputType,
                          IMFMediaType* aOutputType,
                          ConfigureOutputCallback aCallback,
                          void* aData)
{
  mOutputType = aOutputType;

  // Set the input type to the one the caller gave us...
  HRESULT hr = mDecoder->SetInputType(0, aInputType, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = SetDecoderOutputType(aCallback, aData);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  return S_OK;
}
예제 #3
0
HRESULT
WMFAACDecoder::GetOutputSample(IMFSample** aOutSample)
{
  HRESULT hr;
  // We allocate samples for MFT output.
  MFT_OUTPUT_DATA_BUFFER output = {0};

  CComPtr<IMFSample> sample = nullptr;
  hr = CreateOutputSample(&sample);
  ENSURE(SUCCEEDED(hr), hr);

  output.pSample = sample;

  DWORD status = 0;
  hr = mDecoder->ProcessOutput(0, 1, &output, &status);
  CComPtr<IMFCollection> events = output.pEvents; // Ensure this is released.

  if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
    // Type change. Probably geometric apperature change.
    hr = SetDecoderOutputType();
    ENSURE(SUCCEEDED(hr), hr);

    return GetOutputSample(aOutSample);
  } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT || !sample) {
    return MF_E_TRANSFORM_NEED_MORE_INPUT;
  }
  // Treat other errors as fatal.
  ENSURE(SUCCEEDED(hr), hr);

  assert(sample);

  *aOutSample = sample.Detach();
  return S_OK;
}
예제 #4
0
HRESULT
WMFAACDecoder::Init(int32_t aChannelCount,
                    int32_t aSampleRate,
                    BYTE* aAACAudioSpecificConfig,
                    UINT32 aAudioConfigLength)
{
  HRESULT hr;

  // AAC decoder is in msauddecmft on Win8, and msmpeg2adec in earlier versions.
  hr = CreateMFT(CLSID_CMSAACDecMFT,
                 WMFDecoderDllNameFor(AAC),
                 mDecoder);
  if (FAILED(hr)) {
    hr = CreateMFT(CLSID_CMSAACDecMFT,
                   WMFDecoderDllNameFor(AAC),
                   mDecoder);
    if (FAILED(hr)) {
      LOG("Failed to create AAC decoder\n");
      return E_FAIL;
    }
  }

  BYTE* userData = nullptr;
  UINT32 userDataLength;
  hr = AACAudioSpecificConfigToUserData(aAACAudioSpecificConfig,
                                        aAudioConfigLength,
                                        &userData,
                                        &userDataLength);
  ENSURE(SUCCEEDED(hr), hr);
  hr = SetDecoderInputType(aChannelCount, aSampleRate, userData, userDataLength);
  delete userData;
  ENSURE(SUCCEEDED(hr), hr);

  hr = SetDecoderOutputType();
  ENSURE(SUCCEEDED(hr), hr);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
  ENSURE(SUCCEEDED(hr), hr);

  hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
  ENSURE(SUCCEEDED(hr), hr);

  hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo);
  ENSURE(SUCCEEDED(hr), hr);

  hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo);
  ENSURE(SUCCEEDED(hr), hr);

  return S_OK;
}
예제 #5
0
HRESULT
MFTDecoder::Output(RefPtr<IMFSample>* aOutput)
{
  NS_ENSURE_TRUE(mDecoder != nullptr, E_POINTER);

  HRESULT hr;

  MFT_OUTPUT_DATA_BUFFER output = {0};

  RefPtr<IMFSample> sample;
  if (!mMFTProvidesOutputSamples) {
    hr = CreateOutputSample(&sample);
    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
    output.pSample = sample;
  }

  DWORD status = 0;
  hr = mDecoder->ProcessOutput(0, 1, &output, &status);
  if (output.pEvents) {
    // We must release this, as per the IMFTransform::ProcessOutput()
    // MSDN documentation.
    output.pEvents->Release();
    output.pEvents = nullptr;
  }

  if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
    // Type change, probably geometric aperature change.
    // Reconfigure decoder output type, so that GetOutputMediaType()
    // returns the new type, and return the error code to caller.
    // This is an expected failure, so don't warn on encountering it.
    hr = SetDecoderOutputType();
    NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
    // Return the error, so that the caller knows to retry.
    return MF_E_TRANSFORM_STREAM_CHANGE;
  }

  if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
    // Not enough input to produce output. This is an expected failure,
    // so don't warn on encountering it.
    return hr;
  }
  // Treat other errors as unexpected, and warn.
  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

  MOZ_ASSERT(output.pSample);

  if (mDiscontinuity) {
    output.pSample->SetUINT32(MFSampleExtension_Discontinuity, TRUE);
    mDiscontinuity = false;
  }

  *aOutput = output.pSample; // AddRefs
  if (mMFTProvidesOutputSamples) {
    // If the MFT is providing samples, we must release the sample here.
    // Typically only the H.264 MFT provides samples when using DXVA,
    // and it always re-uses the same sample, so if we don't release it
    // MFT::ProcessOutput() deadlocks waiting for the sample to be released.
    output.pSample->Release();
    output.pSample = nullptr;
  }

  return S_OK;
}