mf-h264-encoder.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. #include <obs-module.h>
  2. #include <util/profiler.hpp>
  3. #include "mf-common.hpp"
  4. #include "mf-h264-encoder.hpp"
  5. #include <codecapi.h>
  6. #include <mferror.h>
  7. using namespace MF;
  8. static eAVEncH264VProfile MapProfile(H264Profile profile)
  9. {
  10. switch (profile) {
  11. case H264ProfileBaseline: return eAVEncH264VProfile_Base;
  12. case H264ProfileMain: return eAVEncH264VProfile_Main;
  13. case H264ProfileHigh: return eAVEncH264VProfile_High;
  14. default: return eAVEncH264VProfile_Base;
  15. }
  16. }
  17. static eAVEncCommonRateControlMode MapRateControl(H264RateControl rc)
  18. {
  19. switch (rc) {
  20. case H264RateControlCBR:
  21. return eAVEncCommonRateControlMode_CBR;
  22. case H264RateControlConstrainedVBR:
  23. return eAVEncCommonRateControlMode_PeakConstrainedVBR;
  24. case H264RateControlVBR:
  25. return eAVEncCommonRateControlMode_UnconstrainedVBR;
  26. case H264RateControlCQP:
  27. return eAVEncCommonRateControlMode_Quality;
  28. default:
  29. return eAVEncCommonRateControlMode_CBR;
  30. }
  31. }
  32. static UINT32 MapQpToQuality(H264QP &qp)
  33. {
  34. return 100 - (UINT32)floor(100.0 / 51.0 * qp.defaultQp + 0.5f);
  35. }
  36. static bool ProcessNV12(std::function<void(UINT32 height, INT32 plane)> func,
  37. UINT32 height)
  38. {
  39. INT32 plane = 0;
  40. func(height, plane++);
  41. func(height / 2, plane);
  42. return true;
  43. }
  44. H264Encoder::H264Encoder(const obs_encoder_t *encoder,
  45. std::shared_ptr<EncoderDescriptor> descriptor,
  46. UINT32 width,
  47. UINT32 height,
  48. UINT32 framerateNum,
  49. UINT32 framerateDen,
  50. H264Profile profile,
  51. UINT32 bitrate)
  52. : encoder(encoder),
  53. descriptor(descriptor),
  54. width(width),
  55. height(height),
  56. framerateNum(framerateNum),
  57. framerateDen(framerateDen),
  58. initialBitrate(bitrate),
  59. profile(profile)
  60. {}
  61. H264Encoder::~H264Encoder()
  62. {
  63. HRESULT hr;
  64. if (!descriptor->Async() || !eventGenerator || !pendingRequests)
  65. return;
  66. // Make sure all events have finished before releasing, and drain
  67. // all output requests until it makes an input request.
  68. // If you do not do this, you risk it releasing while there's still
  69. // encoder activity, which can cause a crash with certain interfaces.
  70. while (inputRequests == 0) {
  71. hr = ProcessOutput();
  72. if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT && FAILED(hr)) {
  73. MF_LOG_COM(LOG_ERROR, "H264Encoder::~H264Encoder: "
  74. "ProcessOutput()", hr);
  75. break;
  76. }
  77. if (inputRequests == 0)
  78. Sleep(1);
  79. }
  80. }
  81. HRESULT H264Encoder::CreateMediaTypes(ComPtr<IMFMediaType> &i,
  82. ComPtr<IMFMediaType> &o)
  83. {
  84. HRESULT hr;
  85. HRC(MFCreateMediaType(&i));
  86. HRC(MFCreateMediaType(&o));
  87. HRC(i->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
  88. HRC(i->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12));
  89. HRC(MFSetAttributeSize(i, MF_MT_FRAME_SIZE, width, height));
  90. HRC(MFSetAttributeRatio(i, MF_MT_FRAME_RATE, framerateNum,
  91. framerateDen));
  92. HRC(i->SetUINT32(MF_MT_INTERLACE_MODE,
  93. MFVideoInterlaceMode::MFVideoInterlace_Progressive));
  94. HRC(MFSetAttributeRatio(i, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
  95. HRC(o->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
  96. HRC(o->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
  97. HRC(MFSetAttributeSize(o, MF_MT_FRAME_SIZE, width, height));
  98. HRC(MFSetAttributeRatio(o, MF_MT_FRAME_RATE, framerateNum,
  99. framerateDen));
  100. HRC(o->SetUINT32(MF_MT_AVG_BITRATE, initialBitrate * 1000));
  101. HRC(o->SetUINT32(MF_MT_INTERLACE_MODE,
  102. MFVideoInterlaceMode::MFVideoInterlace_Progressive));
  103. HRC(MFSetAttributeRatio(o, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
  104. HRC(o->SetUINT32(MF_MT_MPEG2_LEVEL, (UINT32)-1));
  105. HRC(o->SetUINT32(MF_MT_MPEG2_PROFILE, MapProfile(profile)));
  106. return S_OK;
  107. fail:
  108. return hr;
  109. }
  110. HRESULT H264Encoder::DrainEvents()
  111. {
  112. HRESULT hr;
  113. while ((hr = DrainEvent(false)) == S_OK);
  114. if (hr == MF_E_NO_EVENTS_AVAILABLE)
  115. hr = S_OK;
  116. return hr;
  117. }
  118. HRESULT H264Encoder::DrainEvent(bool block)
  119. {
  120. HRESULT hr, eventStatus;
  121. ComPtr<IMFMediaEvent> event;
  122. MediaEventType type;
  123. hr = eventGenerator->GetEvent(
  124. block ? 0 : MF_EVENT_FLAG_NO_WAIT, &event);
  125. if (hr != MF_E_NO_EVENTS_AVAILABLE && FAILED(hr))
  126. goto fail;
  127. if (hr == MF_E_NO_EVENTS_AVAILABLE)
  128. return hr;
  129. HRC(event->GetType(&type));
  130. HRC(event->GetStatus(&eventStatus));
  131. if (SUCCEEDED(eventStatus)) {
  132. if (type == METransformNeedInput) {
  133. inputRequests++;
  134. }
  135. else if (type == METransformHaveOutput) {
  136. outputRequests++;
  137. }
  138. }
  139. return S_OK;
  140. fail:
  141. return hr;
  142. }
  143. HRESULT H264Encoder::InitializeEventGenerator()
  144. {
  145. HRESULT hr;
  146. HRC(transform->QueryInterface(&eventGenerator));
  147. return S_OK;
  148. fail:
  149. return hr;
  150. }
  151. HRESULT H264Encoder::InitializeExtraData()
  152. {
  153. HRESULT hr;
  154. ComPtr<IMFMediaType> inputType;
  155. UINT32 headerSize;
  156. extraData.clear();
  157. HRC(transform->GetOutputCurrentType(0, &inputType));
  158. HRC(inputType->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &headerSize));
  159. extraData.resize(headerSize);
  160. HRC(inputType->GetBlob(MF_MT_MPEG_SEQUENCE_HEADER, extraData.data(),
  161. headerSize, NULL));
  162. return S_OK;
  163. fail:
  164. return hr;
  165. }
  166. static HRESULT SetCodecProperty(ComPtr<ICodecAPI> &codecApi, GUID guid,
  167. bool value)
  168. {
  169. VARIANT v;
  170. v.vt = VT_BOOL;
  171. v.boolVal = value ? VARIANT_TRUE : VARIANT_FALSE;
  172. return codecApi->SetValue(&guid, &v);
  173. }
  174. static HRESULT SetCodecProperty(ComPtr<ICodecAPI> &codecApi, GUID guid,
  175. UINT32 value)
  176. {
  177. VARIANT v;
  178. v.vt = VT_UI4;
  179. v.ulVal = value;
  180. return codecApi->SetValue(&guid, &v);
  181. }
  182. static HRESULT SetCodecProperty(ComPtr<ICodecAPI> &codecApi, GUID guid,
  183. UINT64 value)
  184. {
  185. VARIANT v;
  186. v.vt = VT_UI8;
  187. v.ullVal = value;
  188. return codecApi->SetValue(&guid, &v);
  189. }
  190. bool H264Encoder::SetBitrate(UINT32 bitrate)
  191. {
  192. HRESULT hr;
  193. if (codecApi) {
  194. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  195. CODECAPI_AVEncCommonMeanBitRate,
  196. UINT32(bitrate * 1000)));
  197. }
  198. return true;
  199. fail:
  200. return false;
  201. }
  202. bool H264Encoder::SetQP(H264QP &qp)
  203. {
  204. HRESULT hr;
  205. if (codecApi) {
  206. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  207. CODECAPI_AVEncCommonQuality,
  208. UINT32(MapQpToQuality(qp))));
  209. HRL(SetCodecProperty(codecApi,
  210. CODECAPI_AVEncVideoEncodeQP,
  211. UINT64(qp.Pack(true))));
  212. HRL(SetCodecProperty(codecApi,
  213. CODECAPI_AVEncVideoEncodeFrameTypeQP,
  214. UINT64(qp.Pack(false))));
  215. }
  216. return true;
  217. fail:
  218. return false;
  219. }
  220. bool H264Encoder::SetMinQP(UINT32 minQp)
  221. {
  222. HRESULT hr;
  223. if (codecApi) {
  224. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  225. CODECAPI_AVEncVideoMinQP,
  226. UINT32(minQp)));
  227. }
  228. return true;
  229. fail:
  230. return false;
  231. }
  232. bool H264Encoder::SetMaxQP(UINT32 maxQp)
  233. {
  234. HRESULT hr;
  235. if (codecApi) {
  236. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  237. CODECAPI_AVEncVideoMaxQP,
  238. UINT32(maxQp)));
  239. }
  240. return true;
  241. fail:
  242. return false;
  243. }
  244. bool H264Encoder::SetRateControl(H264RateControl rateControl)
  245. {
  246. HRESULT hr;
  247. if (codecApi) {
  248. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  249. CODECAPI_AVEncCommonRateControlMode,
  250. UINT32(MapRateControl(rateControl))));
  251. }
  252. return true;
  253. fail:
  254. return false;
  255. }
  256. bool H264Encoder::SetKeyframeInterval(UINT32 seconds)
  257. {
  258. HRESULT hr;
  259. if (codecApi) {
  260. float gopSize = float(framerateNum) / framerateDen * seconds;
  261. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  262. CODECAPI_AVEncMPVGOPSize,
  263. UINT32(gopSize)));
  264. }
  265. return true;
  266. fail:
  267. return false;
  268. }
  269. bool H264Encoder::SetMaxBitrate(UINT32 maxBitrate)
  270. {
  271. HRESULT hr;
  272. if (codecApi) {
  273. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  274. CODECAPI_AVEncCommonMaxBitRate,
  275. UINT32(maxBitrate * 1000)));
  276. }
  277. return true;
  278. fail:
  279. return false;
  280. }
  281. bool H264Encoder::SetLowLatency(bool lowLatency)
  282. {
  283. HRESULT hr;
  284. if (codecApi) {
  285. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  286. CODECAPI_AVEncCommonLowLatency,
  287. lowLatency));
  288. }
  289. return true;
  290. fail:
  291. return false;
  292. }
  293. bool H264Encoder::SetBufferSize(UINT32 bufferSize)
  294. {
  295. HRESULT hr;
  296. if (codecApi) {
  297. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  298. CODECAPI_AVEncCommonBufferSize,
  299. UINT32(bufferSize * 1000)));
  300. }
  301. return true;
  302. fail:
  303. return false;
  304. }
  305. bool H264Encoder::SetBFrameCount(UINT32 bFrames)
  306. {
  307. HRESULT hr;
  308. if (codecApi) {
  309. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  310. CODECAPI_AVEncMPVDefaultBPictureCount,
  311. UINT32(bFrames)));
  312. }
  313. return true;
  314. fail:
  315. return false;
  316. }
  317. bool H264Encoder::SetEntropyEncoding(H264EntropyEncoding entropyEncoding)
  318. {
  319. HRESULT hr;
  320. if (codecApi) {
  321. HR_CHECK(LOG_WARNING, SetCodecProperty(codecApi,
  322. CODECAPI_AVEncH264CABACEnable,
  323. entropyEncoding == H264EntropyEncodingCABAC));
  324. }
  325. return true;
  326. fail:
  327. return false;
  328. }
  329. bool H264Encoder::Initialize(std::function<bool(void)> func)
  330. {
  331. ProfileScope("H264Encoder::Initialize");
  332. HRESULT hr;
  333. ComPtr<IMFMediaType> inputType, outputType;
  334. ComPtr<IMFAttributes> transformAttributes;
  335. MFT_OUTPUT_STREAM_INFO streamInfo = {0};
  336. HRC(CoCreateInstance(descriptor->Guid(), NULL, CLSCTX_INPROC_SERVER,
  337. IID_PPV_ARGS(&transform)));
  338. HRC(CreateMediaTypes(inputType, outputType));
  339. if (descriptor->Async()) {
  340. HRC(transform->GetAttributes(&transformAttributes));
  341. HRC(transformAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK,
  342. TRUE));
  343. }
  344. HRC(transform->QueryInterface(&codecApi));
  345. if (func && !func()) {
  346. MF_LOG(LOG_ERROR, "Failed setting custom properties");
  347. goto fail;
  348. }
  349. MF_LOG(LOG_INFO, "Activating encoder: %s",
  350. typeNames[(int)descriptor->Type()]);
  351. MF_LOG(LOG_INFO, " Setting output type to transform:");
  352. LogMediaType(outputType.Get());
  353. HRC(transform->SetOutputType(0, outputType.Get(), 0));
  354. MF_LOG(LOG_INFO, " Setting input type to transform:");
  355. LogMediaType(inputType.Get());
  356. HRC(transform->SetInputType(0, inputType.Get(), 0));
  357. HRC(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING,
  358. NULL));
  359. HRC(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM,
  360. NULL));
  361. if (descriptor->Async())
  362. HRC(InitializeEventGenerator());
  363. HRC(transform->GetOutputStreamInfo(0, &streamInfo));
  364. createOutputSample = !(streamInfo.dwFlags &
  365. (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES |
  366. MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES));
  367. return true;
  368. fail:
  369. return false;
  370. }
  371. bool H264Encoder::ExtraData(UINT8 **data, UINT32 *dataLength)
  372. {
  373. if (extraData.empty())
  374. return false;
  375. *data = extraData.data();
  376. *dataLength = (UINT32)extraData.size();
  377. return true;
  378. }
  379. HRESULT H264Encoder::CreateEmptySample(ComPtr<IMFSample> &sample,
  380. ComPtr<IMFMediaBuffer> &buffer, DWORD length)
  381. {
  382. HRESULT hr;
  383. HRC(MFCreateSample(&sample));
  384. HRC(MFCreateMemoryBuffer(length, &buffer));
  385. HRC(sample->AddBuffer(buffer.Get()));
  386. return S_OK;
  387. fail:
  388. return hr;
  389. }
  390. HRESULT H264Encoder::EnsureCapacity(ComPtr<IMFSample> &sample, DWORD length)
  391. {
  392. HRESULT hr;
  393. ComPtr<IMFMediaBuffer> buffer;
  394. DWORD currentLength;
  395. if (!sample) {
  396. HRC(CreateEmptySample(sample, buffer, length));
  397. }
  398. else {
  399. HRC(sample->GetBufferByIndex(0, &buffer));
  400. }
  401. HRC(buffer->GetMaxLength(&currentLength));
  402. if (currentLength < length) {
  403. HRC(sample->RemoveAllBuffers());
  404. HRC(MFCreateMemoryBuffer(length, &buffer));
  405. HRC(sample->AddBuffer(buffer));
  406. }
  407. else {
  408. buffer->SetCurrentLength(0);
  409. }
  410. return S_OK;
  411. fail:
  412. return hr;
  413. }
  414. HRESULT H264Encoder::ProcessInput(ComPtr<IMFSample> &sample)
  415. {
  416. ProfileScope("H264Encoder::ProcessInput(sample)");
  417. HRESULT hr = S_OK;
  418. if (descriptor->Async()) {
  419. if (inputRequests == 1 && inputSamples.empty()) {
  420. inputRequests--;
  421. return transform->ProcessInput(0, sample, 0);
  422. }
  423. inputSamples.push(sample);
  424. while (inputRequests > 0) {
  425. if (inputSamples.empty())
  426. return hr;
  427. ComPtr<IMFSample> queuedSample = inputSamples.front();
  428. inputSamples.pop();
  429. inputRequests--;
  430. HRC(transform->ProcessInput(0, queuedSample, 0));
  431. }
  432. } else {
  433. return transform->ProcessInput(0, sample, 0);
  434. }
  435. fail:
  436. return hr;
  437. }
  438. bool H264Encoder::ProcessInput(UINT8 **data, UINT32 *linesize, UINT64 pts,
  439. Status *status)
  440. {
  441. ProfileScope("H264Encoder::ProcessInput");
  442. HRESULT hr;
  443. ComPtr<IMFSample> sample;
  444. ComPtr<IMFMediaBuffer> buffer;
  445. BYTE *bufferData;
  446. UINT64 sampleDur;
  447. UINT32 imageSize;
  448. HRC(MFCalculateImageSize(MFVideoFormat_NV12, width, height, &imageSize));
  449. HRC(CreateEmptySample(sample, buffer, imageSize));
  450. {
  451. ProfileScope("H264EncoderCopyInputSample");
  452. HRC(buffer->Lock(&bufferData, NULL, NULL));
  453. ProcessNV12([&, this](DWORD height, int plane) {
  454. MFCopyImage(bufferData, width, data[plane],
  455. linesize[plane], width, height);
  456. bufferData += width * height;
  457. }, height);
  458. }
  459. HRC(buffer->Unlock());
  460. HRC(buffer->SetCurrentLength(imageSize));
  461. MFFrameRateToAverageTimePerFrame(framerateNum, framerateDen, &sampleDur);
  462. HRC(sample->SetSampleTime(pts * sampleDur));
  463. HRC(sample->SetSampleDuration(sampleDur));
  464. if (descriptor->Async()) {
  465. HRC(DrainEvents());
  466. while (outputRequests > 0 && (hr = ProcessOutput()) == S_OK);
  467. if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT && FAILED(hr)) {
  468. MF_LOG_COM(LOG_ERROR, "ProcessOutput()", hr);
  469. goto fail;
  470. }
  471. while (inputRequests == 0) {
  472. hr = DrainEvent(false);
  473. if (hr == MF_E_NO_EVENTS_AVAILABLE) {
  474. Sleep(1);
  475. continue;
  476. }
  477. if (FAILED(hr)) {
  478. MF_LOG_COM(LOG_ERROR, "DrainEvent()", hr);
  479. goto fail;
  480. }
  481. if (outputRequests > 0) {
  482. hr = ProcessOutput();
  483. if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT &&
  484. FAILED(hr))
  485. goto fail;
  486. }
  487. }
  488. }
  489. HRC(ProcessInput(sample));
  490. pendingRequests++;
  491. *status = SUCCESS;
  492. return true;
  493. fail:
  494. *status = FAILURE;
  495. return false;
  496. }
  497. HRESULT H264Encoder::ProcessOutput()
  498. {
  499. HRESULT hr;
  500. ComPtr<IMFSample> sample;
  501. MFT_OUTPUT_STREAM_INFO outputInfo = { 0 };
  502. DWORD outputStatus = 0;
  503. MFT_OUTPUT_DATA_BUFFER output = { 0 };
  504. ComPtr<IMFMediaBuffer> buffer;
  505. BYTE *bufferData;
  506. DWORD bufferLength;
  507. INT64 samplePts;
  508. INT64 sampleDts;
  509. INT64 sampleDur;
  510. std::unique_ptr<std::vector<BYTE>> data(new std::vector<BYTE>());
  511. ComPtr<IMFMediaType> type;
  512. std::unique_ptr<H264Frame> frame;
  513. if (descriptor->Async()) {
  514. HRC(DrainEvents());
  515. if (outputRequests == 0)
  516. return S_OK;
  517. outputRequests--;
  518. }
  519. if (createOutputSample) {
  520. HRC(transform->GetOutputStreamInfo(0, &outputInfo));
  521. HRC(CreateEmptySample(sample, buffer, outputInfo.cbSize));
  522. output.pSample = sample;
  523. } else {
  524. output.pSample = NULL;
  525. }
  526. while (true) {
  527. hr = transform->ProcessOutput(0, 1, &output,
  528. &outputStatus);
  529. ComPtr<IMFCollection> events(output.pEvents);
  530. if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
  531. return hr;
  532. if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
  533. HRC(transform->GetOutputAvailableType(0, 0, &type));
  534. HRC(transform->SetOutputType(0, type, 0));
  535. MF_LOG(LOG_INFO, "Updating output type to transform");
  536. LogMediaType(type);
  537. if (descriptor->Async() && outputRequests > 0) {
  538. outputRequests--;
  539. continue;
  540. } else {
  541. return MF_E_TRANSFORM_NEED_MORE_INPUT;
  542. }
  543. }
  544. if (hr != S_OK) {
  545. MF_LOG_COM(LOG_ERROR, "transform->ProcessOutput()",
  546. hr);
  547. return hr;
  548. }
  549. break;
  550. }
  551. if (!createOutputSample)
  552. sample.Set(output.pSample);
  553. HRC(sample->GetBufferByIndex(0, &buffer));
  554. bool keyframe = !!MFGetAttributeUINT32(sample,
  555. MFSampleExtension_CleanPoint, FALSE);
  556. HRC(buffer->Lock(&bufferData, NULL, &bufferLength));
  557. if (keyframe && extraData.empty())
  558. HRC(InitializeExtraData());
  559. data->reserve(bufferLength + extraData.size());
  560. if (keyframe)
  561. data->insert(data->end(), extraData.begin(), extraData.end());
  562. data->insert(data->end(), &bufferData[0], &bufferData[bufferLength]);
  563. HRC(buffer->Unlock());
  564. HRC(sample->GetSampleDuration(&sampleDur));
  565. HRC(sample->GetSampleTime(&samplePts));
  566. sampleDts = MFGetAttributeUINT64(sample,
  567. MFSampleExtension_DecodeTimestamp, samplePts);
  568. frame.reset(new H264Frame(keyframe,
  569. samplePts / sampleDur,
  570. sampleDts / sampleDur,
  571. std::move(data)));
  572. encodedFrames.push(std::move(frame));
  573. return S_OK;
  574. fail:
  575. return hr;
  576. }
  577. bool H264Encoder::ProcessOutput(UINT8 **data, UINT32 *dataLength,
  578. UINT64 *pts, UINT64 *dts, bool *keyframe, Status *status)
  579. {
  580. ProfileScope("H264Encoder::ProcessOutput");
  581. HRESULT hr;
  582. hr = ProcessOutput();
  583. if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT || encodedFrames.empty()) {
  584. *status = NEED_MORE_INPUT;
  585. return true;
  586. }
  587. if (FAILED(hr) && encodedFrames.empty()) {
  588. *status = FAILURE;
  589. return false;
  590. }
  591. activeFrame = std::move(encodedFrames.front());
  592. encodedFrames.pop();
  593. *data = activeFrame.get()->Data();
  594. *dataLength = activeFrame.get()->DataLength();
  595. *pts = activeFrame.get()->Pts();
  596. *dts = activeFrame.get()->Dts();
  597. *keyframe = activeFrame.get()->Keyframe();
  598. *status = SUCCESS;
  599. pendingRequests--;
  600. return true;
  601. }