summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wmf/MFTDecoder.h
blob: 7af99e550dff6323c8f7504600a96d0e285ec44a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#if !defined(MFTDecoder_h_)
#  define MFTDecoder_h_

#  include "WMF.h"
#  include "mozilla/ReentrantMonitor.h"
#  include "mozilla/RefPtr.h"
#  include "nsIThread.h"

namespace mozilla {

class MFTDecoder final {
  ~MFTDecoder();

 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFTDecoder)

  MFTDecoder();

  // Creates the MFT by COM class ID.
  //
  // Params:
  //  - aCLSID The COM class ID of the decoder.
  HRESULT Create(const GUID& aCLSID);

  // Creates the MFT by querying a category and media subtype.
  // First thing to do as part of setup.
  //
  // Params:
  //  - aCategory the GUID of the MFT category to use.
  //  - aInSubType the GUID of the input MFT media type to use.
  //    GUID_NULL may be used as a wildcard.
  //  - aOutSubType the GUID of the output MFT media type to use.
  //    GUID_NULL may be used as a wildcard.
  HRESULT Create(const GUID& aCategory, const GUID& aInSubtype,
                 const GUID& aOutSubtype);

  // Sets the input and output media types. Call after Init().
  //
  // Params:
  //  - aInputType needs at least major and minor types set.
  //  - aOutputType needs at least major and minor types set.
  //    This is used to select the matching output type out
  //    of all the available output types of the MFT.
  HRESULT SetMediaTypes(
      IMFMediaType* aInputType, IMFMediaType* aOutputType,
      std::function<HRESULT(IMFMediaType*)>&& aCallback =
          [](IMFMediaType* aOutput) { return S_OK; });

  // Returns the MFT's global IMFAttributes object.
  already_AddRefed<IMFAttributes> GetAttributes();

  // Returns the MFT's IMFAttributes object for an output stream.
  already_AddRefed<IMFAttributes> GetOutputStreamAttributes();

  // Retrieves the media type being input.
  HRESULT GetInputMediaType(RefPtr<IMFMediaType>& aMediaType);

  // Retrieves the media type being output. This may not be valid until
  //  the first sample is decoded.
  HRESULT GetOutputMediaType(RefPtr<IMFMediaType>& aMediaType);
  const GUID& GetOutputMediaSubType() const { return mOutputSubType; }

  // Submits data into the MFT for processing.
  //
  // Returns:
  //  - MF_E_NOTACCEPTING if the decoder can't accept input. The data
  //    must be resubmitted after Output() stops producing output.
  HRESULT Input(const uint8_t* aData, uint32_t aDataSize,
                int64_t aTimestampUsecs, int64_t aDurationUsecs);
  HRESULT Input(IMFSample* aSample);

  HRESULT CreateInputSample(const uint8_t* aData, uint32_t aDataSize,
                            int64_t aTimestampUsecs, int64_t aDurationUsecs,
                            RefPtr<IMFSample>* aOutSample);

  // Retrieves output from the MFT. Call this once Input() returns
  // MF_E_NOTACCEPTING. Some MFTs with hardware acceleration (the H.264
  // decoder MFT in particular) can't handle it if clients hold onto
  // references to the output IMFSample, so don't do that.
  //
  // Returns:
  //  - MF_E_TRANSFORM_STREAM_CHANGE if the underlying stream output
  //    type changed. Retrieve the output media type and reconfig client,
  //    else you may misinterpret the MFT's output.
  //  - MF_E_TRANSFORM_NEED_MORE_INPUT if no output can be produced
  //    due to lack of input.
  //  - S_OK if an output frame is produced.
  HRESULT Output(RefPtr<IMFSample>* aOutput);

  // Sends a flush message to the MFT. This causes it to discard all
  // input data. Use before seeking.
  HRESULT Flush();

  // Sends a message to the MFT.
  HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, ULONG_PTR aData);

  HRESULT FindDecoderOutputTypeWithSubtype(const GUID& aSubType);
  HRESULT FindDecoderOutputType();

 private:
  // Will search a suitable MediaType using aTypeToUse if set, if not will
  // use the current mOutputType.
  HRESULT SetDecoderOutputType(
      const GUID& aSubType, IMFMediaType* aTypeToUse,
      std::function<HRESULT(IMFMediaType*)>&& aCallback);
  HRESULT CreateOutputSample(RefPtr<IMFSample>* aOutSample);

  MFT_INPUT_STREAM_INFO mInputStreamInfo;
  MFT_OUTPUT_STREAM_INFO mOutputStreamInfo;

  RefPtr<IMFActivate> mActivate;
  RefPtr<IMFTransform> mDecoder;

  RefPtr<IMFMediaType> mOutputType;
  GUID mOutputSubType;

  // True if the IMFTransform allocates the samples that it returns.
  bool mMFTProvidesOutputSamples = false;

  // True if we need to mark the next sample as a discontinuity.
  bool mDiscontinuity = true;
};

}  // namespace mozilla

#endif