1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef WMFMediaDataEncoder_h_
8 #define WMFMediaDataEncoder_h_
9 
10 #include "MFTEncoder.h"
11 #include "PlatformEncoderModule.h"
12 #include "TimeUnits.h"
13 
14 namespace mozilla {
15 
16 bool CanCreateWMFEncoder(MediaDataEncoder::CodecType aCodec);
17 
18 template <typename ConfigType>
19 class WMFMediaDataEncoder final : public MediaDataEncoder {
20  public:
21   WMFMediaDataEncoder(const ConfigType& aConfig, RefPtr<TaskQueue> aTaskQueue);
22 
23   RefPtr<InitPromise> Init() override;
24   RefPtr<EncodePromise> Encode(const MediaData* aSample) override;
25   RefPtr<EncodePromise> Drain() override;
26   RefPtr<ShutdownPromise> Shutdown() override;
27   RefPtr<GenericPromise> SetBitrate(Rate aBitsPerSec) override;
28 
29   nsCString GetDescriptionName() const override;
30 
31  private:
32   // Automatically lock/unlock IMFMediaBuffer.
33   class LockBuffer final {
34    public:
LockBuffer(RefPtr<IMFMediaBuffer> & aBuffer)35     explicit LockBuffer(RefPtr<IMFMediaBuffer>& aBuffer) : mBuffer(aBuffer) {
36       mResult = mBuffer->Lock(&mBytes, &mCapacity, &mLength);
37     }
38 
~LockBuffer()39     ~LockBuffer() {
40       if (SUCCEEDED(mResult)) {
41         mBuffer->Unlock();
42       }
43     }
44 
Data()45     BYTE* Data() { return mBytes; }
Capacity()46     DWORD Capacity() { return mCapacity; }
Length()47     DWORD Length() { return mLength; }
Result()48     HRESULT Result() { return mResult; }
49 
50    private:
51     RefPtr<IMFMediaBuffer> mBuffer;
52     BYTE* mBytes;
53     DWORD mCapacity;
54     DWORD mLength;
55     HRESULT mResult;
56   };
57 
58   RefPtr<InitPromise> ProcessInit();
59   HRESULT InitMFTEncoder(RefPtr<MFTEncoder>& aEncoder);
60 
61   RefPtr<EncodePromise> ProcessEncode(RefPtr<const VideoData>&& aSample);
62   already_AddRefed<IMFSample> ConvertToNV12InputSample(
63       RefPtr<const VideoData>&& aData);
64   RefPtr<EncodePromise> ProcessOutputSamples(
65       nsTArray<RefPtr<IMFSample>>& aSamples);
66   already_AddRefed<MediaRawData> IMFSampleToMediaData(
67       RefPtr<IMFSample>& aSample);
68   bool WriteFrameData(RefPtr<MediaRawData>& aDest, LockBuffer& aSrc,
69                       bool aIsKeyframe);
70 
AssertOnTaskQueue()71   void AssertOnTaskQueue() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); }
72 
73   const ConfigType mConfig;
74   const RefPtr<TaskQueue> mTaskQueue;
75   RefPtr<MFTEncoder> mEncoder;
76   // SPS/PPS NALUs for realtime usage, avcC otherwise.
77   RefPtr<MediaByteBuffer> mConfigData;
78 };
79 
80 }  // namespace mozilla
81 
82 #endif
83