jetson_nv_encoder.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. #include <limits>
  2. #include <string>
  3. // WebRTC
  4. #include <common_video/libyuv/include/webrtc_libyuv.h>
  5. #include <modules/video_coding/codecs/h264/include/h264.h>
  6. #include <modules/video_coding/include/video_codec_interface.h>
  7. #include <modules/video_coding/include/video_error_codes.h>
  8. // #include <modules/video_coding/svc/create_scalability_structure.h>
  9. #include <rtc_base/checks.h>
  10. #include <rtc_base/logging.h>
  11. #include <rtc_base/time_utils.h>
  12. #include <system_wrappers/include/metrics.h>
  13. // libyuv
  14. #include <libyuv/convert.h>
  15. #include <libyuv/convert_from.h>
  16. #include <libyuv/video_common.h>
  17. // L4T Multimedia API
  18. #include "NvBufSurface.h"
  19. #include "NvVideoEncoder.h"
  20. #include "nvbufsurface.h"
  21. #include "nvbufsurftransform.h"
  22. #include "jetson_nv_encoder.h"
  23. #define H264HWENC_HEADER_DEBUG 0
  24. #define INIT_ERROR(cond, desc) \
  25. if (cond) { \
  26. RTC_LOG(LS_ERROR) << __FUNCTION__ << desc; \
  27. Release(); \
  28. return WEBRTC_VIDEO_CODEC_ERROR; \
  29. }
  30. namespace webrtc {
  31. JetsonVideoEncoder::JetsonVideoEncoder(const cricket::VideoCodec& codec)
  32. : callback_(nullptr),
  33. encoder_(nullptr),
  34. configured_framerate_(30),
  35. use_native_(false),
  36. use_dmabuff_(false) {}
  37. JetsonVideoEncoder::~JetsonVideoEncoder() {
  38. Release();
  39. }
  40. // bool JetsonVideoEncoder::IsSupported(webrtc::VideoCodecType codec) {
  41. // //SuppressErrors sup;
  42. // printf("----------------------------------------------------------------------------------issupported\n");
  43. // auto encoder = NvVideoEncoder::createVideoEncoder("enc0");
  44. // // auto ret = encoder->setCapturePlaneFormat(VideoCodecToV4L2Format(codec), 1024,
  45. // // 768, 2 * 1024 * 1024);
  46. // auto ret = encoder->setCapturePlaneFormat(V4L2_PIX_FMT_H264, 1280,
  47. // 720, 2 * 1024 * 1024);
  48. // delete encoder;
  49. // return ret >= 0;
  50. // }
  51. int32_t JetsonVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
  52. int32_t number_of_cores,
  53. size_t max_payload_size) {
  54. RTC_DCHECK(codec_settings);
  55. int32_t release_ret = Release();
  56. if (release_ret != WEBRTC_VIDEO_CODEC_OK) {
  57. return release_ret;
  58. }
  59. if (&codec_ != codec_settings) {
  60. codec_ = *codec_settings;
  61. }
  62. width_ = codec_settings->width;
  63. height_ = codec_settings->height;
  64. target_bitrate_bps_ = codec_settings->startBitrate * 1000;
  65. // std::cout << "g=heig " << width_ << height_ << target_bitrate_bps_ << std::endl;
  66. key_frame_interval_ = codec_settings->H264().keyFrameInterval;
  67. framerate_ = codec_settings->maxFramerate;
  68. RTC_LOG(LS_INFO) << "InitEncode " << framerate_ << "fps "
  69. << target_bitrate_bps_ << "bit/sec "
  70. << codec_settings->maxBitrate << "kbit/sec ";
  71. // Initialize encoded image.
  72. encoded_image_.timing_.flags =
  73. webrtc::VideoSendTiming::TimingFrameFlags::kInvalid;
  74. encoded_image_.content_type_ =
  75. (codec_settings->mode == webrtc::VideoCodecMode::kScreensharing)
  76. ? webrtc::VideoContentType::SCREENSHARE
  77. : webrtc::VideoContentType::UNSPECIFIED;
  78. gof_idx_ = 0;
  79. RTC_LOG(LS_INFO) << __FUNCTION__ << " End";
  80. return WEBRTC_VIDEO_CODEC_OK;
  81. }
  82. int32_t JetsonVideoEncoder::Release() {
  83. JetsonRelease();
  84. return WEBRTC_VIDEO_CODEC_OK;
  85. }
  86. int32_t JetsonVideoEncoder::JetsonConfigure() {
  87. int ret = 0;
  88. bool use_converter =
  89. use_native_ && (width_ != raw_width_ || height_ != raw_height_ ||
  90. decode_pixfmt_ != V4L2_PIX_FMT_YUV420M);
  91. encoder_ = NvVideoEncoder::createVideoEncoder("enc0");
  92. INIT_ERROR(!encoder_, "Failed to createVideoEncoder");
  93. ret =encoder_->setCapturePlaneFormat(V4L2_PIX_FMT_H264,width_, height_, 2 * 1024 * 1024);
  94. printf("width_;%d, height_:%d\n",width_,height_);
  95. INIT_ERROR(ret < 0, "Failed to encoder setCapturePlaneFormat");
  96. ret = encoder_->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, width_, height_);
  97. INIT_ERROR(ret < 0, "Failed to encoder setOutputPlaneFormat");
  98. if (codec_.codecType == webrtc::kVideoCodecH264) {
  99. // printf("000000000000000000000000000000000000000000000009876542345678992534567890789657463656789065456789087654345678909456780\n");
  100. // ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
  101. ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
  102. INIT_ERROR(ret < 0, "Failed to setProfile");
  103. // ret = encoder_->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
  104. ret = encoder_->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_2_1);
  105. // INIT_ERROR(ret < 0, "Failed to setLevel");
  106. ret = encoder_->setNumBFrames(0);
  107. INIT_ERROR(ret < 0, "Failed to setNumBFrames");
  108. ret = encoder_->setInsertSpsPpsAtIdrEnabled(true);
  109. INIT_ERROR(ret < 0, "Failed to setInsertSpsPpsAtIdrEnabled");
  110. ret = encoder_->setInsertVuiEnabled(true);
  111. INIT_ERROR(ret < 0, "Failed to setInsertSpsPpsAtIdrEnabled");
  112. ret = encoder_->setHWPresetType(V4L2_ENC_HW_PRESET_FAST);
  113. // ret = encoder_->setHWPresetType(V4L2_ENC_HW_PRESET_ULTRAFAST);
  114. INIT_ERROR(ret < 0, "Failed to setHWPresetType");
  115. }
  116. ret = encoder_->setRateControlMode(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
  117. INIT_ERROR(ret < 0, "Failed to setRateControlMode");
  118. bitrate_adjuster_.reset(new webrtc::BitrateAdjuster(.5, .95));
  119. bitrate_adjuster_->SetTargetBitrateBps(target_bitrate_bps_);
  120. SetBitrateBps(target_bitrate_bps_);
  121. ret = encoder_->setIDRInterval(key_frame_interval_);
  122. INIT_ERROR(ret < 0, "Failed to setIDRInterval");
  123. // ret = encoder_->setIFrameInterval(0);
  124. ret = encoder_->setIFrameInterval(0);
  125. INIT_ERROR(ret < 0, "Failed to setIFrameInterval");
  126. // ret = encoder_->setFrameRate(framerate_, 1);
  127. ret = encoder_->setFrameRate(30, 1);
  128. INIT_ERROR(ret < 0, "Failed to setFrameRate");
  129. // if (use_native_) {
  130. // std::cout << "use native -------------------------------------------\n" << std::endl;
  131. // if (use_dmabuff_ || use_converter) {
  132. // std::cout << "use use_converter -------------------------------------------\n" << std::endl;
  133. // ret = encoder_->output_plane.reqbufs(V4L2_MEMORY_DMABUF, 10);
  134. // INIT_ERROR(ret < 0, "Failed to reqbufs at encoder output_plane");
  135. // int fd;
  136. // NvBufSurf::NvCommonAllocateParams cParams;
  137. // cParams.width = width_;
  138. // cParams.height = height_;
  139. // cParams.layout = NVBUF_LAYOUT_PITCH;
  140. // cParams.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
  141. // cParams.memtag = NvBufSurfaceTag_VIDEO_ENC;
  142. // cParams.memType = NVBUF_MEM_SURFACE_ARRAY;
  143. // for (uint32_t i = 0; i < encoder_->output_plane.getNumBuffers(); i++) {
  144. // ret = NvBufSurf::NvAllocate(&cParams, 1, &fd);
  145. // INIT_ERROR(ret, "Failed to create NvBuffer");
  146. // RTC_LOG(LS_ERROR) << "NvBufferCreateEx i:" << i << " fd:" << fd;
  147. // output_plane_fd_[i] = fd;
  148. // }
  149. // } else {
  150. // ret = encoder_->output_plane.setupPlane(V4L2_MEMORY_USERPTR, 1, false,
  151. // false);
  152. // INIT_ERROR(ret < 0, "Failed to setupPlane at encoder output_plane");
  153. // }
  154. // } else {
  155. ret = encoder_->output_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
  156. INIT_ERROR(ret < 0, "Failed to setupPlane at encoder output_plane");
  157. // }
  158. ret = encoder_->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
  159. INIT_ERROR(ret < 0, "Failed to setupPlane at capture_plane");
  160. ret = encoder_->subscribeEvent(V4L2_EVENT_EOS, 0, 0);
  161. INIT_ERROR(ret < 0, "Failed to subscribeEvent V4L2_EVENT_EOS");
  162. ret = encoder_->output_plane.setStreamStatus(true);
  163. INIT_ERROR(ret < 0, "Failed to setStreamStatus at encoder output_plane");
  164. ret = encoder_->capture_plane.setStreamStatus(true);
  165. INIT_ERROR(ret < 0, "Failed to setStreamStatus at encoder capture_plane");
  166. encoder_->capture_plane.setDQThreadCallback(EncodeFinishedCallbackFunction);
  167. encoder_->capture_plane.startDQThread(this);
  168. for (uint32_t i = 0; i < encoder_->capture_plane.getNumBuffers(); i++) {
  169. struct v4l2_buffer v4l2_buf;
  170. struct v4l2_plane planes[MAX_PLANES];
  171. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  172. memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
  173. v4l2_buf.index = i;
  174. v4l2_buf.m.planes = planes;
  175. ret = encoder_->capture_plane.qBuffer(v4l2_buf, NULL);
  176. INIT_ERROR(ret < 0, "Failed to qBuffer at encoder capture_plane");
  177. }
  178. configured_framerate_ = framerate_;
  179. return WEBRTC_VIDEO_CODEC_OK;
  180. }
  181. void JetsonVideoEncoder::JetsonRelease() {
  182. if (!encoder_)
  183. return;
  184. SendEOS();
  185. encoder_->capture_plane.waitForDQThread(2000);
  186. encoder_->capture_plane.deinitPlane();
  187. if (use_dmabuff_) {
  188. for (uint32_t i = 0; i < encoder_->output_plane.getNumBuffers(); i++) {
  189. if (encoder_->output_plane.unmapOutputBuffers(i, output_plane_fd_[i]) <
  190. 0) {
  191. RTC_LOG(LS_ERROR)
  192. << "Failed to unmapOutputBuffers at encoder output_plane";
  193. }
  194. if (NvBufSurf::NvDestroy(output_plane_fd_[i]) < 0) {
  195. RTC_LOG(LS_ERROR)
  196. << "Failed to NvBufferDestroy at encoder output_plane";
  197. }
  198. }
  199. } else {
  200. encoder_->output_plane.deinitPlane();
  201. }
  202. delete encoder_;
  203. encoder_ = nullptr;
  204. }
  205. void JetsonVideoEncoder::SendEOS() {
  206. if (encoder_->output_plane.getStreamStatus()) {
  207. struct v4l2_buffer v4l2_buf;
  208. struct v4l2_plane planes[MAX_PLANES];
  209. NvBuffer* buffer;
  210. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  211. memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
  212. v4l2_buf.m.planes = planes;
  213. if (encoder_->output_plane.getNumQueuedBuffers() ==
  214. encoder_->output_plane.getNumBuffers()) {
  215. if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
  216. RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
  217. }
  218. }
  219. planes[0].bytesused = 0;
  220. for (int i = 0; i < buffer->n_planes; i++) {
  221. buffer->planes[i].bytesused = 0;
  222. }
  223. if (encoder_->output_plane.qBuffer(v4l2_buf, NULL) < 0) {
  224. RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
  225. }
  226. }
  227. }
  228. bool JetsonVideoEncoder::EncodeFinishedCallbackFunction(
  229. struct v4l2_buffer* v4l2_buf,
  230. NvBuffer* buffer,
  231. NvBuffer* shared_buffer,
  232. void* data) {
  233. return ((JetsonVideoEncoder*)data)
  234. ->EncodeFinishedCallback(v4l2_buf, buffer, shared_buffer);
  235. }
  236. bool JetsonVideoEncoder::EncodeFinishedCallback(struct v4l2_buffer* v4l2_buf,
  237. NvBuffer* buffer,
  238. NvBuffer* shared_buffer) {
  239. if (!v4l2_buf) {
  240. RTC_LOG(LS_INFO) << __FUNCTION__ << " v4l2_buf is null";
  241. return false;
  242. }
  243. if (buffer->planes[0].bytesused == 0) {
  244. RTC_LOG(LS_INFO) << __FUNCTION__ << " buffer size is zero";
  245. return false;
  246. }
  247. uint64_t timestamp = v4l2_buf->timestamp.tv_sec * rtc::kNumMicrosecsPerSec +
  248. v4l2_buf->timestamp.tv_usec;
  249. std::unique_ptr<FrameParams> params;
  250. {
  251. webrtc::MutexLock lock(&frame_params_lock_);
  252. do {
  253. if (frame_params_.empty()) {
  254. RTC_LOG(LS_WARNING)
  255. << __FUNCTION__
  256. << "Frame parameter is not found. SkipFrame timestamp:"
  257. << timestamp;
  258. return true;
  259. }
  260. params = std::move(frame_params_.front());
  261. frame_params_.pop();
  262. } while (params->timestamp_us < timestamp);
  263. if (params->timestamp_us != timestamp) {
  264. RTC_LOG(LS_WARNING)
  265. << __FUNCTION__
  266. << "Frame parameter is not found. SkipFrame timestamp:" << timestamp;
  267. return true;
  268. }
  269. }
  270. v4l2_ctrl_videoenc_outputbuf_metadata enc_metadata;
  271. if (encoder_->getMetadata(v4l2_buf->index, enc_metadata) != 0) {
  272. RTC_LOG(LS_WARNING) << __FUNCTION__
  273. << "getMetadata failed. SkipFrame timestamp:"
  274. << timestamp;
  275. return true;
  276. }
  277. SendFrame(buffer->planes[0].data, buffer->planes[0].bytesused,
  278. std::move(params), &enc_metadata);
  279. if (encoder_->capture_plane.qBuffer(*v4l2_buf, NULL) < 0) {
  280. RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to qBuffer at capture_plane";
  281. return false;
  282. }
  283. return true;
  284. }
  285. int32_t JetsonVideoEncoder::RegisterEncodeCompleteCallback(
  286. webrtc::EncodedImageCallback* callback) {
  287. callback_ = callback;
  288. return WEBRTC_VIDEO_CODEC_OK;
  289. }
  290. void JetsonVideoEncoder::SetRates(const RateControlParameters& parameters) {
  291. // printf("SetRatesSetRatesSetRatesSetRatesSetRatesSetRatesSetRates\n");
  292. if (encoder_ == nullptr)
  293. return;
  294. if (parameters.bitrate.get_sum_bps() <= 0 || parameters.framerate_fps <= 0)
  295. return;
  296. RTC_LOG(LS_INFO) << __FUNCTION__ << " framerate:" << parameters.framerate_fps
  297. << " bitrate:" << parameters.bitrate.ToString();
  298. // if (svc_controller_) {
  299. // svc_controller_->OnRatesUpdated(parameters.bitrate);
  300. // }
  301. framerate_ = parameters.framerate_fps;
  302. target_bitrate_bps_ = parameters.bitrate.get_sum_bps();
  303. bitrate_adjuster_->SetTargetBitrateBps(target_bitrate_bps_);
  304. return;
  305. }
  306. void JetsonVideoEncoder::SetFramerate(uint32_t framerate) {
  307. if (configured_framerate_ == framerate) {
  308. return;
  309. }
  310. RTC_LOG(LS_INFO) << __FUNCTION__ << " " << framerate << "fps";
  311. if (encoder_->setFrameRate(framerate, 1) < 0) {
  312. RTC_LOG(LS_ERROR) << "Failed to set bitrate";
  313. return;
  314. }
  315. configured_framerate_ = framerate;
  316. }
  317. void JetsonVideoEncoder::SetBitrateBps(uint32_t bitrate_bps) {
  318. if (bitrate_bps < 300000 || (configured_bitrate_bps_ == bitrate_bps &&
  319. configured_framerate_ == framerate_)) {
  320. return;
  321. }
  322. configured_bitrate_bps_ = bitrate_bps;
  323. if (encoder_->setBitrate(bitrate_bps) < 0) {
  324. RTC_LOG(LS_ERROR) << "Failed to setBitrate";
  325. return;
  326. }
  327. }
  328. webrtc::VideoEncoder::EncoderInfo JetsonVideoEncoder::GetEncoderInfo() const {
  329. EncoderInfo info;
  330. info.supports_native_handle = true;
  331. info.implementation_name = "Jetson Video Encoder";
  332. static const int kLowH264QpThreshold = 24; //34
  333. static const int kHighH264QpThreshold = 37; //40
  334. info.scaling_settings = VideoEncoder::ScalingSettings(kLowH264QpThreshold,
  335. kHighH264QpThreshold);
  336. return info;
  337. }
  338. int32_t JetsonVideoEncoder::Encode(
  339. const webrtc::VideoFrame& input_frame,
  340. const std::vector<webrtc::VideoFrameType>* frame_types) {
  341. // printf("encode encode \n");
  342. if (!callback_) {
  343. RTC_LOG(LS_WARNING)
  344. << "InitEncode() has been called, but a callback function "
  345. << "has not been set with RegisterEncodeCompleteCallback()";
  346. return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  347. }
  348. int fd = 0;
  349. webrtc::VideoType video_type;
  350. uint8_t* native_data;
  351. rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer =
  352. input_frame.video_frame_buffer();
  353. // std::shared_ptr<JetsonJpegDecoder> decoder;
  354. if (frame_buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) {
  355. use_native_ = true;
  356. } else {
  357. use_native_ = false;
  358. }
  359. if (encoder_ == nullptr) {
  360. if (JetsonConfigure() != WEBRTC_VIDEO_CODEC_OK) {
  361. RTC_LOG(LS_ERROR) << "Failed to JetsonConfigure";
  362. return WEBRTC_VIDEO_CODEC_ERROR;
  363. }
  364. }
  365. bool force_key_frame = false;
  366. if (frame_types != nullptr) {
  367. RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1));
  368. if ((*frame_types)[0] == webrtc::VideoFrameType::kEmptyFrame) {
  369. return WEBRTC_VIDEO_CODEC_OK;
  370. }
  371. if ((*frame_types)[0] == webrtc::VideoFrameType::kVideoFrameKey) {
  372. if (encoder_->forceIDR() < 0) {
  373. RTC_LOG(LS_ERROR) << "Failed to forceIDR";
  374. }
  375. }
  376. }
  377. SetFramerate(framerate_);
  378. SetBitrateBps(bitrate_adjuster_->GetAdjustedBitrateBps());
  379. {
  380. webrtc::MutexLock lock(&frame_params_lock_);
  381. frame_params_.push(absl::make_unique<FrameParams>(
  382. frame_buffer->width(), frame_buffer->height(),
  383. input_frame.render_time_ms(), input_frame.ntp_time_ms(),
  384. input_frame.timestamp_us(), input_frame.timestamp(),
  385. // input_frame.rotation(), input_frame.color_space(), decoder));
  386. input_frame.rotation(), input_frame.color_space()));
  387. }
  388. struct v4l2_buffer v4l2_buf;
  389. struct v4l2_plane planes[MAX_PLANES];
  390. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  391. memset(planes, 0, sizeof(planes));
  392. v4l2_buf.m.planes = planes;
  393. if (use_native_) {
  394. NvBuffer* buffer;
  395. if (encoder_->output_plane.getNumQueuedBuffers() ==
  396. encoder_->output_plane.getNumBuffers()) {
  397. if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
  398. RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
  399. return WEBRTC_VIDEO_CODEC_ERROR;
  400. }
  401. } else {
  402. buffer = encoder_->output_plane.getNthBuffer(
  403. encoder_->output_plane.getNumQueuedBuffers());
  404. v4l2_buf.index = encoder_->output_plane.getNumQueuedBuffers();
  405. }
  406. int src_dma_fd = -1;
  407. if (use_dmabuff_) {
  408. src_dma_fd = fd;
  409. } else if (video_type == webrtc::VideoType::kYUY2 ||
  410. video_type == webrtc::VideoType::kUYVY) {
  411. buffer->planes[0].bytesused = buffer->planes[0].fmt.width *
  412. buffer->planes[0].fmt.bytesperpixel *
  413. buffer->planes[0].fmt.height;
  414. buffer->planes[0].data = native_data;
  415. } else if (video_type == webrtc::VideoType::kI420) {
  416. size_t offset = 0;
  417. for (int i = 0; i < buffer->n_planes; i++) {
  418. buffer->planes[i].bytesused = buffer->planes[i].fmt.width *
  419. buffer->planes[i].fmt.bytesperpixel *
  420. buffer->planes[i].fmt.height;
  421. buffer->planes[i].data = native_data + offset;
  422. offset += buffer->planes[i].bytesused;
  423. }
  424. } else if (video_type == webrtc::VideoType::kYV12) {
  425. size_t offset = 0;
  426. buffer->planes[0].bytesused = buffer->planes[0].fmt.width *
  427. buffer->planes[0].fmt.bytesperpixel *
  428. buffer->planes[0].fmt.height;
  429. buffer->planes[0].data = native_data;
  430. offset += buffer->planes[0].bytesused;
  431. buffer->planes[2].bytesused = buffer->planes[1].fmt.width *
  432. buffer->planes[1].fmt.bytesperpixel *
  433. buffer->planes[1].fmt.height;
  434. buffer->planes[2].data = native_data + offset;
  435. offset += buffer->planes[2].bytesused;
  436. buffer->planes[1].bytesused = buffer->planes[2].fmt.width *
  437. buffer->planes[2].fmt.bytesperpixel *
  438. buffer->planes[2].fmt.height;
  439. buffer->planes[1].data = native_data + offset;
  440. } else {
  441. RTC_LOG(LS_ERROR) << "Unsupported webrtc::VideoType";
  442. return WEBRTC_VIDEO_CODEC_ERROR;
  443. }
  444. NvBufSurf::NvCommonTransformParams transform_params;
  445. /* Indicates which of the transform parameters are valid */
  446. memset(&transform_params, 0, sizeof(transform_params));
  447. transform_params.src_top = 0;
  448. transform_params.src_left = 0;
  449. transform_params.src_width = raw_width_;
  450. transform_params.src_height = raw_height_;
  451. transform_params.dst_top = 0;
  452. transform_params.dst_left = 0;
  453. transform_params.dst_width = width_;
  454. transform_params.dst_height = height_;
  455. transform_params.flag =
  456. (NvBufSurfTransform_Transform_Flag)(NVBUFSURF_TRANSFORM_FILTER |
  457. NVBUFSURF_TRANSFORM_CROP_SRC);
  458. transform_params.flip = NvBufSurfTransform_None;
  459. transform_params.filter = NvBufSurfTransformInter_Bilinear;
  460. if (NvBufSurf::NvTransform(&transform_params, src_dma_fd,
  461. output_plane_fd_[v4l2_buf.index])) {
  462. RTC_LOG(LS_ERROR) << "Failed to NvBufferTransform";
  463. return WEBRTC_VIDEO_CODEC_ERROR;
  464. }
  465. planes[0].m.fd = output_plane_fd_[v4l2_buf.index];
  466. planes[0].bytesused = 1234;
  467. v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
  468. v4l2_buf.memory = V4L2_MEMORY_DMABUF;
  469. v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
  470. v4l2_buf.timestamp.tv_sec =
  471. input_frame.timestamp_us() / rtc::kNumMicrosecsPerSec;
  472. v4l2_buf.timestamp.tv_usec =
  473. input_frame.timestamp_us() % rtc::kNumMicrosecsPerSec;
  474. if (encoder_->output_plane.qBuffer(v4l2_buf, nullptr) < 0) {
  475. RTC_LOG(LS_ERROR) << "Failed to qBuffer at converter output_plane";
  476. return WEBRTC_VIDEO_CODEC_ERROR;
  477. }
  478. } else {
  479. NvBuffer* buffer;
  480. RTC_LOG(LS_VERBOSE) << __FUNCTION__ << " output_plane.getNumBuffers: "
  481. << encoder_->output_plane.getNumBuffers()
  482. << " output_plane.getNumQueuedBuffers: "
  483. << encoder_->output_plane.getNumQueuedBuffers();
  484. if (encoder_->output_plane.getNumQueuedBuffers() ==
  485. encoder_->output_plane.getNumBuffers()) {
  486. if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
  487. RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
  488. return WEBRTC_VIDEO_CODEC_ERROR;
  489. }
  490. } else {
  491. buffer = encoder_->output_plane.getNthBuffer(
  492. encoder_->output_plane.getNumQueuedBuffers());
  493. v4l2_buf.index = encoder_->output_plane.getNumQueuedBuffers();
  494. }
  495. rtc::scoped_refptr<const webrtc::I420BufferInterface> i420_buffer =
  496. frame_buffer->ToI420();
  497. for (uint32_t i = 0; i < buffer->n_planes; i++) {
  498. const uint8_t* source_data;
  499. int source_stride;
  500. if (i == 0) {
  501. source_data = i420_buffer->DataY();
  502. source_stride = i420_buffer->StrideY();
  503. } else if (i == 1) {
  504. source_data = i420_buffer->DataU();
  505. source_stride = i420_buffer->StrideU();
  506. } else if (i == 2) {
  507. source_data = i420_buffer->DataV();
  508. source_stride = i420_buffer->StrideV();
  509. } else {
  510. break;
  511. }
  512. NvBuffer::NvBufferPlane& plane = buffer->planes[i];
  513. std::streamsize bytes_to_read = plane.fmt.bytesperpixel * plane.fmt.width;
  514. uint8_t* input_data = plane.data;
  515. plane.bytesused = 0;
  516. for (uint32_t j = 0; j < plane.fmt.height; j++) {
  517. memcpy(input_data, source_data + (source_stride * j), bytes_to_read);
  518. input_data += plane.fmt.stride;
  519. }
  520. plane.bytesused = plane.fmt.stride * plane.fmt.height;
  521. }
  522. v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
  523. v4l2_buf.timestamp.tv_sec =
  524. input_frame.timestamp_us() / rtc::kNumMicrosecsPerSec;
  525. v4l2_buf.timestamp.tv_usec =
  526. input_frame.timestamp_us() % rtc::kNumMicrosecsPerSec;
  527. for (int i = 0; i < MAX_PLANES; i++) {
  528. NvBufSurface* surf = 0;
  529. if (NvBufSurfaceFromFd(buffer->planes[i].fd, (void**)(&surf)) == -1) {
  530. RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to NvBufSurfaceFromFd";
  531. return WEBRTC_VIDEO_CODEC_ERROR;
  532. }
  533. if (NvBufSurfaceSyncForDevice(surf, 0, i) == -1) {
  534. RTC_LOG(LS_ERROR) << "Failed to NvBufSurfaceSyncForDevice";
  535. return WEBRTC_VIDEO_CODEC_ERROR;
  536. }
  537. }
  538. if (encoder_->output_plane.qBuffer(v4l2_buf, nullptr) < 0) {
  539. RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
  540. return WEBRTC_VIDEO_CODEC_ERROR;
  541. }
  542. }
  543. return WEBRTC_VIDEO_CODEC_OK;
  544. }
  545. int32_t JetsonVideoEncoder::SendFrame(
  546. unsigned char* buffer,
  547. size_t size,
  548. std::unique_ptr<FrameParams> params,
  549. v4l2_ctrl_videoenc_outputbuf_metadata* enc_metadata) {
  550. if (!callback_) {
  551. RTC_LOG(LS_WARNING)
  552. << "InitEncode() has been called, but a callback function "
  553. << "has not been set with RegisterEncodeCompleteCallback()";
  554. return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  555. }
  556. // encoded_image_.SetRtpTimestamp(params->timestamp_rtp);
  557. encoded_image_.SetTimestamp(params->timestamp_rtp);
  558. encoded_image_.SetColorSpace(params->color_space);
  559. encoded_image_._encodedWidth = params->width;
  560. encoded_image_._encodedHeight = params->height;
  561. encoded_image_.capture_time_ms_ = params->render_time_ms;
  562. encoded_image_.ntp_time_ms_ = params->ntp_time_ms;
  563. encoded_image_.rotation_ = params->rotation;
  564. encoded_image_.qp_ = enc_metadata->AvgQP;
  565. // if (enc_metadata->KeyFrame) {
  566. // encoded_image_.SetFrameType(webrtc::VideoFrameType::kVideoFrameKey);
  567. // } else {
  568. // encoded_image_.SetFrameType(webrtc::VideoFrameType::kVideoFrameDelta);
  569. // }
  570. if (enc_metadata->KeyFrame) {
  571. encoded_image_._frameType= webrtc::VideoFrameType::kVideoFrameKey;
  572. } else {
  573. encoded_image_._frameType= webrtc::VideoFrameType::kVideoFrameDelta;
  574. }
  575. webrtc::CodecSpecificInfo codec_specific;
  576. codec_specific.codecType = codec_.codecType;
  577. auto encoded_image_buffer =
  578. webrtc::EncodedImageBuffer::Create(buffer, size);
  579. encoded_image_.SetEncodedData(encoded_image_buffer);
  580. codec_specific.codecSpecific.H264.packetization_mode =
  581. webrtc::H264PacketizationMode::NonInterleaved;
  582. // webrtc::H264PacketizationMode::SingleNalUnit;
  583. RTC_LOG(LS_VERBOSE) << "key_frame=" << enc_metadata->KeyFrame
  584. << " size=" << size << " qp=" << encoded_image_.qp_;
  585. webrtc::EncodedImageCallback::Result result =
  586. callback_->OnEncodedImage(encoded_image_, &codec_specific);
  587. if (result.error != webrtc::EncodedImageCallback::Result::OK) {
  588. RTC_LOG(LS_ERROR) << __FUNCTION__
  589. << " OnEncodedImage failed error:" << result.error;
  590. return WEBRTC_VIDEO_CODEC_ERROR;
  591. }
  592. bitrate_adjuster_->Update(size);
  593. return WEBRTC_VIDEO_CODEC_OK;
  594. }
  595. } // namespace webrtc