mf-h264-encoder.cpp 16 KB

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