mf-h264-encoder.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #pragma once
  2. #include <obs-module.h>
  3. #define WIN32_MEAN_AND_LEAN
  4. #include <Windows.h>
  5. #undef WIN32_MEAN_AND_LEAN
  6. #include <mfapi.h>
  7. #include <mfidl.h>
  8. #include <wmcodecdsp.h>
  9. #include <vector>
  10. #include <queue>
  11. #include <memory>
  12. #include <atomic>
  13. #include <util/windows/ComPtr.hpp>
  14. #include "mf-encoder-descriptor.hpp"
  15. #include "mf-common.hpp"
  16. namespace MF {
  17. enum H264Profile {
  18. H264ProfileBaseline,
  19. H264ProfileMain,
  20. H264ProfileHigh
  21. };
  22. enum H264RateControl {
  23. H264RateControlCBR,
  24. H264RateControlConstrainedVBR,
  25. H264RateControlVBR,
  26. H264RateControlCQP
  27. };
  28. struct H264QP {
  29. UINT16 defaultQp;
  30. UINT16 i;
  31. UINT16 p;
  32. UINT16 b;
  33. UINT64 Pack(bool packDefault) {
  34. int shift = packDefault ? 0 : 16;
  35. UINT64 packedQp;
  36. if (packDefault)
  37. packedQp = defaultQp;
  38. packedQp |= i << shift;
  39. shift += 16;
  40. packedQp |= p << shift;
  41. shift += 16;
  42. packedQp |= b << shift;
  43. return packedQp;
  44. }
  45. };
  46. enum H264EntropyEncoding {
  47. H264EntropyEncodingCABLC,
  48. H264EntropyEncodingCABAC
  49. };
  50. struct H264Frame {
  51. public:
  52. H264Frame(bool keyframe, UINT64 pts, UINT64 dts,
  53. std::unique_ptr<std::vector<uint8_t>> data)
  54. : keyframe(keyframe), pts(pts), dts(dts),
  55. data(std::move(data))
  56. {}
  57. bool Keyframe() { return keyframe; }
  58. BYTE *Data() { return data.get()->data(); }
  59. DWORD DataLength() { return (DWORD)data.get()->size(); }
  60. INT64 Pts() { return pts; }
  61. INT64 Dts() { return dts; }
  62. private:
  63. H264Frame(H264Frame const&) = delete;
  64. H264Frame& operator=(H264Frame const&) = delete;
  65. private:
  66. bool keyframe;
  67. INT64 pts;
  68. INT64 dts;
  69. std::unique_ptr<std::vector<uint8_t>> data;
  70. };
  71. class H264Encoder {
  72. public:
  73. H264Encoder(const obs_encoder_t *encoder,
  74. std::shared_ptr<EncoderDescriptor> descriptor,
  75. UINT32 width,
  76. UINT32 height,
  77. UINT32 framerateNum,
  78. UINT32 framerateDen,
  79. H264Profile profile,
  80. UINT32 bitrate);
  81. ~H264Encoder();
  82. bool Initialize(std::function<bool(void)> func);
  83. bool ProcessInput(UINT8 **data, UINT32 *linesize, UINT64 pts,
  84. Status *status);
  85. bool ProcessOutput(UINT8 **data, UINT32 *dataLength,
  86. UINT64 *pts, UINT64 *dts, bool *keyframe,
  87. Status *status);
  88. bool ExtraData(UINT8 **data, UINT32 *dataLength);
  89. const obs_encoder_t *ObsEncoder() { return encoder; }
  90. public:
  91. bool SetBitrate(UINT32 bitrate);
  92. bool SetQP(H264QP &qp);
  93. bool SetMaxBitrate(UINT32 maxBitrate);
  94. bool SetRateControl(H264RateControl rateControl);
  95. bool SetKeyframeInterval(UINT32 seconds);
  96. bool SetLowLatency(bool lowLatency);
  97. bool SetBufferSize(UINT32 bufferSize);
  98. bool SetBFrameCount(UINT32 bFrames);
  99. bool SetEntropyEncoding(H264EntropyEncoding entropyEncoding);
  100. bool SetMinQP(UINT32 minQp);
  101. bool SetMaxQP(UINT32 maxQp);
  102. private:
  103. H264Encoder(H264Encoder const&) = delete;
  104. H264Encoder& operator=(H264Encoder const&) = delete;
  105. private:
  106. HRESULT InitializeEventGenerator();
  107. HRESULT InitializeExtraData();
  108. HRESULT CreateMediaTypes(ComPtr<IMFMediaType> &inputType,
  109. ComPtr<IMFMediaType> &outputType);
  110. HRESULT EnsureCapacity(ComPtr<IMFSample> &sample, DWORD length);
  111. HRESULT CreateEmptySample(ComPtr<IMFSample> &sample,
  112. ComPtr<IMFMediaBuffer> &buffer, DWORD length);
  113. HRESULT ProcessInput(ComPtr<IMFSample> &sample);
  114. HRESULT ProcessOutput();
  115. HRESULT DrainEvent(bool block);
  116. HRESULT DrainEvents();
  117. private:
  118. const obs_encoder_t *encoder;
  119. std::shared_ptr<EncoderDescriptor> descriptor;
  120. const UINT32 width;
  121. const UINT32 height;
  122. const UINT32 framerateNum;
  123. const UINT32 framerateDen;
  124. const UINT32 initialBitrate;
  125. const H264Profile profile;
  126. bool createOutputSample;
  127. ComPtr<IMFTransform> transform;
  128. ComPtr<ICodecAPI> codecApi;
  129. std::vector<BYTE> extraData;
  130. // The frame returned by ProcessOutput
  131. // Valid until the next call to ProcessOutput
  132. std::unique_ptr<H264Frame> activeFrame;
  133. // Queued input samples that the encoder was not ready
  134. // to process
  135. std::queue<ComPtr<IMFSample>> inputSamples;
  136. // Queued output samples that have not been returned from
  137. // ProcessOutput yet
  138. std::queue<std::unique_ptr<H264Frame>> encodedFrames;
  139. ComPtr<IMFMediaEventGenerator> eventGenerator;
  140. std::atomic<UINT32> inputRequests = 0;
  141. std::atomic<UINT32> outputRequests = 0;
  142. std::atomic<UINT32> pendingRequests = 0;
  143. };
  144. }