jetson_video_decoder.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. *
  10. */
  11. #include "sora/hwenc_jetson/jetson_video_decoder.h"
  12. #include <unistd.h>
  13. // WebRTC
  14. #include <modules/video_coding/include/video_error_codes.h>
  15. #include <rtc_base/checks.h>
  16. #include <rtc_base/logging.h>
  17. #include <rtc_base/time_utils.h>
  18. #include <system_wrappers/include/metrics.h>
  19. #include <third_party/libyuv/include/libyuv/convert.h>
  20. // L4T Multimedia API
  21. #include <nvbufsurface.h>
  22. #include <nvbufsurftransform.h>
  23. // Jetson Linux Multimedia API
  24. #include <NvBufSurface.h>
  25. #include <NvVideoDecoder.h>
  26. #include "jetson_util.h"
  27. #define INIT_ERROR(cond, desc) \
  28. if (cond) { \
  29. RTC_LOG(LS_ERROR) << __FUNCTION__ << desc; \
  30. Release(); \
  31. return WEBRTC_VIDEO_CODEC_ERROR; \
  32. }
  33. #define CHUNK_SIZE 4000000
  34. namespace sora {
  35. JetsonVideoDecoder::JetsonVideoDecoder(webrtc::VideoCodecType codec)
  36. : input_format_(VideoCodecToV4L2Format(codec)),
  37. decoder_(nullptr),
  38. decode_complete_callback_(nullptr),
  39. buffer_pool_(false, 300 /* max_number_of_buffers*/),
  40. eos_(false),
  41. got_error_(false),
  42. dst_dma_fd_(-1) {}
  43. JetsonVideoDecoder::~JetsonVideoDecoder() {
  44. Release();
  45. }
  46. bool JetsonVideoDecoder::IsSupported(webrtc::VideoCodecType codec) {
  47. auto decoder = NvVideoDecoder::createVideoDecoder("dec0");
  48. auto ret =
  49. decoder->setOutputPlaneFormat(VideoCodecToV4L2Format(codec), CHUNK_SIZE);
  50. delete decoder;
  51. return ret >= 0;
  52. }
  53. bool JetsonVideoDecoder::Configure(const Settings& settings) {
  54. if (JetsonConfigure() != WEBRTC_VIDEO_CODEC_OK) {
  55. RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to JetsonConfigure";
  56. return false;
  57. }
  58. return true;
  59. }
  60. int32_t JetsonVideoDecoder::Decode(const webrtc::EncodedImage& input_image,
  61. bool missing_frames,
  62. int64_t render_time_ms) {
  63. if (decoder_ == nullptr) {
  64. return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  65. }
  66. if (decode_complete_callback_ == NULL) {
  67. return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  68. }
  69. if (input_image.data() == NULL && input_image.size() > 0) {
  70. return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
  71. }
  72. struct v4l2_buffer v4l2_buf;
  73. struct v4l2_plane planes[MAX_PLANES];
  74. NvBuffer* buffer;
  75. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  76. memset(planes, 0, sizeof(planes));
  77. v4l2_buf.m.planes = planes;
  78. RTC_LOG(LS_INFO) << __FUNCTION__ << " output_plane.getNumBuffers: "
  79. << decoder_->output_plane.getNumBuffers()
  80. << " output_plane.getNumQueuedBuffers: "
  81. << decoder_->output_plane.getNumQueuedBuffers();
  82. if (decoder_->output_plane.getNumQueuedBuffers() ==
  83. decoder_->output_plane.getNumBuffers()) {
  84. if (decoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, -1) < 0) {
  85. RTC_LOG(LS_ERROR) << "Failed to dqBuffer at decoder output_plane";
  86. return WEBRTC_VIDEO_CODEC_ERROR;
  87. }
  88. } else {
  89. buffer = decoder_->output_plane.getNthBuffer(
  90. decoder_->output_plane.getNumQueuedBuffers());
  91. v4l2_buf.index = decoder_->output_plane.getNumQueuedBuffers();
  92. }
  93. memcpy(buffer->planes[0].data, input_image.data(), input_image.size());
  94. buffer->planes[0].bytesused = input_image.size();
  95. v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
  96. v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
  97. v4l2_buf.timestamp.tv_sec =
  98. input_image.RtpTimestamp() / rtc::kNumMicrosecsPerSec;
  99. v4l2_buf.timestamp.tv_usec =
  100. input_image.RtpTimestamp() % rtc::kNumMicrosecsPerSec;
  101. if (decoder_->output_plane.qBuffer(v4l2_buf, nullptr) < 0) {
  102. RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
  103. return WEBRTC_VIDEO_CODEC_ERROR;
  104. }
  105. RTC_LOG(LS_INFO) << __FUNCTION__
  106. << " timestamp:" << input_image.RtpTimestamp()
  107. << " bytesused:" << buffer->planes[0].bytesused;
  108. return WEBRTC_VIDEO_CODEC_OK;
  109. }
  110. int32_t JetsonVideoDecoder::RegisterDecodeCompleteCallback(
  111. webrtc::DecodedImageCallback* callback) {
  112. decode_complete_callback_ = callback;
  113. return WEBRTC_VIDEO_CODEC_OK;
  114. }
  115. int32_t JetsonVideoDecoder::Release() {
  116. JetsonRelease();
  117. buffer_pool_.Release();
  118. return WEBRTC_VIDEO_CODEC_OK;
  119. }
  120. const char* JetsonVideoDecoder::ImplementationName() const {
  121. return "Jetson Video";
  122. }
  123. int32_t JetsonVideoDecoder::JetsonConfigure() {
  124. int ret = 0;
  125. decoder_ = NvVideoDecoder::createVideoDecoder("dec0");
  126. INIT_ERROR(!decoder_, "Failed to createVideoDecoder");
  127. ret = decoder_->subscribeEvent(V4L2_EVENT_RESOLUTION_CHANGE, 0, 0);
  128. INIT_ERROR(ret < 0,
  129. "Failed to decoder subscribeEvent V4L2_EVENT_RESOLUTION_CHANGE");
  130. ret = decoder_->setOutputPlaneFormat(input_format_, CHUNK_SIZE);
  131. INIT_ERROR(ret < 0, "Failed to decoder setOutputPlaneFormat");
  132. // 入力されるのがフレーム単位でない場合は 1 を設定する
  133. ret = decoder_->setFrameInputMode(1);
  134. INIT_ERROR(ret < 0, "Failed to decoder setFrameInputMode");
  135. ret = decoder_->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
  136. INIT_ERROR(ret < 0, "Failed to setupPlane at decoder output_plane");
  137. ret = decoder_->subscribeEvent(V4L2_EVENT_EOS, 0, 0);
  138. INIT_ERROR(ret < 0, "Failed to subscribeEvent V4L2_EVENT_EOS");
  139. ret = decoder_->output_plane.setStreamStatus(true);
  140. INIT_ERROR(ret < 0, "Failed to setStreamStatus at decoder output_plane");
  141. if (capture_loop_.empty()) {
  142. eos_ = false;
  143. capture_loop_ = rtc::PlatformThread::SpawnJoinable(
  144. std::bind(JetsonVideoDecoder::CaptureLoopFunction, this), "CaptureLoop",
  145. rtc::ThreadAttributes().SetPriority(rtc::ThreadPriority::kHigh));
  146. }
  147. return WEBRTC_VIDEO_CODEC_OK;
  148. }
  149. bool JetsonVideoDecoder::JetsonRelease() {
  150. if (decoder_) {
  151. if (!capture_loop_.empty()) {
  152. eos_ = true;
  153. SendEOS(decoder_);
  154. while (decoder_->output_plane.getNumQueuedBuffers() > 0 && !got_error_ &&
  155. !decoder_->isInError()) {
  156. struct v4l2_buffer v4l2_buf;
  157. struct v4l2_plane planes[MAX_PLANES];
  158. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  159. memset(planes, 0, sizeof(planes));
  160. v4l2_buf.m.planes = planes;
  161. if (decoder_->output_plane.dqBuffer(v4l2_buf, NULL, NULL, -1) < 0) {
  162. RTC_LOG(LS_ERROR)
  163. << __FUNCTION__ << " Failed to dqBuffer at decoder output_plane";
  164. got_error_ = true;
  165. break;
  166. }
  167. }
  168. capture_loop_.Finalize();
  169. }
  170. delete decoder_;
  171. decoder_ = nullptr;
  172. }
  173. if (dst_dma_fd_ != -1) {
  174. NvBufSurf::NvDestroy(dst_dma_fd_);
  175. dst_dma_fd_ = -1;
  176. }
  177. return true;
  178. }
  179. void JetsonVideoDecoder::SendEOS(NvV4l2Element* element) {
  180. if (element->output_plane.getStreamStatus()) {
  181. struct v4l2_buffer v4l2_buf;
  182. struct v4l2_plane planes[MAX_PLANES];
  183. NvBuffer* buffer;
  184. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  185. memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
  186. v4l2_buf.m.planes = planes;
  187. while (element->output_plane.getNumQueuedBuffers() != 0) {
  188. if (element->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
  189. RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
  190. }
  191. }
  192. planes[0].bytesused = 0;
  193. if (element->output_plane.qBuffer(v4l2_buf, NULL) < 0) {
  194. RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
  195. }
  196. }
  197. }
  198. void JetsonVideoDecoder::CaptureLoopFunction(void* obj) {
  199. JetsonVideoDecoder* _this = static_cast<JetsonVideoDecoder*>(obj);
  200. _this->CaptureLoop();
  201. }
  202. void JetsonVideoDecoder::CaptureLoop() {
  203. struct v4l2_event event;
  204. int ret;
  205. do {
  206. ret = decoder_->dqEvent(event, 10);
  207. if (eos_) {
  208. return;
  209. }
  210. if (ret < 0) {
  211. if (errno == EAGAIN) {
  212. continue;
  213. } else {
  214. RTC_LOG(LS_ERROR) << __FUNCTION__ << " Failed to dqEvent at decoder";
  215. got_error_ = true;
  216. break;
  217. }
  218. }
  219. } while (event.type != V4L2_EVENT_RESOLUTION_CHANGE && !got_error_);
  220. if (!got_error_) {
  221. SetCapture();
  222. }
  223. while (!(eos_ || got_error_ || decoder_->isInError())) {
  224. ret = decoder_->dqEvent(event, false);
  225. if (ret == 0 && event.type == V4L2_EVENT_RESOLUTION_CHANGE) {
  226. SetCapture();
  227. continue;
  228. }
  229. NvBuffer* buffer;
  230. while (1) {
  231. struct v4l2_buffer v4l2_buf;
  232. struct v4l2_plane planes[MAX_PLANES];
  233. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  234. memset(planes, 0, sizeof(planes));
  235. v4l2_buf.m.planes = planes;
  236. // Dequeue a filled buffer
  237. if (decoder_->capture_plane.dqBuffer(v4l2_buf, &buffer, NULL, 0)) {
  238. if (errno == EAGAIN) {
  239. usleep(1000);
  240. } else {
  241. RTC_LOG(LS_ERROR)
  242. << __FUNCTION__ << " Failed to dqBuffer at decoder capture_plane";
  243. got_error_ = true;
  244. }
  245. break;
  246. }
  247. uint64_t pts = v4l2_buf.timestamp.tv_sec * rtc::kNumMicrosecsPerSec +
  248. v4l2_buf.timestamp.tv_usec;
  249. NvBufSurf::NvCommonTransformParams transform_params;
  250. memset(&transform_params, 0, sizeof(transform_params));
  251. transform_params.src_top = capture_crop_->c.top;
  252. transform_params.src_left = capture_crop_->c.left;
  253. transform_params.src_width = capture_crop_->c.width;
  254. transform_params.src_height = capture_crop_->c.height;
  255. transform_params.dst_top = 0;
  256. transform_params.dst_left = 0;
  257. transform_params.dst_width = capture_crop_->c.width;
  258. transform_params.dst_height = capture_crop_->c.height;
  259. transform_params.flag = NVBUFSURF_TRANSFORM_FILTER;
  260. transform_params.flip = NvBufSurfTransform_None;
  261. transform_params.filter = NvBufSurfTransformInter_Algo3;
  262. // 何が来ても YUV420 に変換する
  263. ret = NvBufSurf::NvTransform(&transform_params, buffer->planes[0].fd,
  264. dst_dma_fd_);
  265. if (ret == -1) {
  266. RTC_LOG(LS_ERROR) << __FUNCTION__ << " Transform failed";
  267. break;
  268. }
  269. rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer =
  270. buffer_pool_.CreateI420Buffer(capture_crop_->c.width,
  271. capture_crop_->c.height);
  272. if (!i420_buffer.get()) {
  273. // Pool has too many pending frames.
  274. RTC_HISTOGRAM_BOOLEAN(
  275. "WebRTC.Video.LibvpxVp8Decoder.TooManyPendingFrames", 1);
  276. got_error_ = true;
  277. break;
  278. }
  279. void* src_data;
  280. uint8_t* dst_data;
  281. int dst_stride;
  282. for (uint32_t i = 0; i < MAX_PLANES; i++) {
  283. if (i == 0) {
  284. dst_data = i420_buffer->MutableDataY();
  285. dst_stride = i420_buffer->StrideY();
  286. } else if (i == 1) {
  287. dst_data = i420_buffer->MutableDataU();
  288. dst_stride = i420_buffer->StrideU();
  289. } else if (i == 2) {
  290. dst_data = i420_buffer->MutableDataV();
  291. dst_stride = i420_buffer->StrideV();
  292. } else {
  293. break;
  294. }
  295. NvBufSurface* dst_surf = 0;
  296. if (NvBufSurfaceFromFd(dst_dma_fd_, (void**)(&dst_surf)) == -1) {
  297. RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to NvBufSurfaceFromFd";
  298. break;
  299. }
  300. ret = NvBufSurfaceMap(dst_surf, 0, i, NVBUF_MAP_READ);
  301. NvBufSurfaceSyncForCpu(dst_surf, 0, i);
  302. src_data = dst_surf->surfaceList[0].mappedAddr.addr[i];
  303. NvBufSurfacePlaneParams params = dst_surf->surfaceList[0].planeParams;
  304. for (uint32_t j = 0; j < params.height[i]; j++) {
  305. memcpy(dst_data + j * dst_stride,
  306. (char*)src_data + j * params.pitch[i], params.width[i]);
  307. }
  308. NvBufSurfaceUnMap(dst_surf, 0, i);
  309. }
  310. webrtc::VideoFrame decoded_image =
  311. webrtc::VideoFrame::Builder()
  312. .set_video_frame_buffer(i420_buffer)
  313. .set_timestamp_rtp(pts)
  314. .build();
  315. decode_complete_callback_->Decoded(decoded_image, absl::nullopt,
  316. absl::nullopt);
  317. if (decoder_->capture_plane.qBuffer(v4l2_buf, NULL) < 0) {
  318. RTC_LOG(LS_ERROR) << __FUNCTION__
  319. << "Failed to qBuffer at capture_plane";
  320. got_error_ = true;
  321. break;
  322. }
  323. }
  324. }
  325. }
  326. int JetsonVideoDecoder::SetCapture() {
  327. int32_t ret;
  328. struct v4l2_format format;
  329. ret = decoder_->capture_plane.getFormat(format);
  330. INIT_ERROR(ret < 0, "Failed to getFormat at capture_plane");
  331. capture_crop_.reset(new v4l2_crop());
  332. ret = decoder_->capture_plane.getCrop(*capture_crop_.get());
  333. INIT_ERROR(ret < 0, "Failed to getCrop at capture_plane");
  334. RTC_LOG(LS_INFO) << __FUNCTION__ << " plane format "
  335. << format.fmt.pix_mp.pixelformat << " "
  336. << format.fmt.pix_mp.width << "x"
  337. << format.fmt.pix_mp.height;
  338. RTC_LOG(LS_INFO) << __FUNCTION__ << " crop " << capture_crop_->c.top << "x"
  339. << capture_crop_->c.left << " " << capture_crop_->c.width
  340. << "x" << format.fmt.pix_mp.height;
  341. if (dst_dma_fd_ != -1) {
  342. NvBufSurf::NvDestroy(dst_dma_fd_);
  343. dst_dma_fd_ = -1;
  344. }
  345. NvBufSurf::NvCommonAllocateParams cParams;
  346. cParams.width = capture_crop_->c.width;
  347. cParams.height = capture_crop_->c.height;
  348. cParams.layout = NVBUF_LAYOUT_PITCH;
  349. cParams.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
  350. cParams.memtag = NvBufSurfaceTag_VIDEO_DEC;
  351. cParams.memType = NVBUF_MEM_SURFACE_ARRAY;
  352. ret = NvBufSurf::NvAllocate(&cParams, 1, &dst_dma_fd_);
  353. INIT_ERROR(ret == -1, "failed to NvBufSurfaceAllocate");
  354. decoder_->capture_plane.deinitPlane();
  355. ret = decoder_->setCapturePlaneFormat(format.fmt.pix_mp.pixelformat,
  356. format.fmt.pix_mp.width,
  357. format.fmt.pix_mp.height);
  358. INIT_ERROR(ret < 0, "Failed to setCapturePlaneFormat at capture_plane");
  359. int32_t min_capture_buffer_size;
  360. ret = decoder_->getMinimumCapturePlaneBuffers(min_capture_buffer_size);
  361. INIT_ERROR(ret < 0, "Failed to getMinimumCapturePlaneBuffers");
  362. ret = decoder_->capture_plane.setupPlane(
  363. V4L2_MEMORY_MMAP, min_capture_buffer_size + 5, false, false);
  364. INIT_ERROR(ret < 0, "Failed to setupPlane at capture_plane");
  365. ret = decoder_->capture_plane.setStreamStatus(true);
  366. INIT_ERROR(ret < 0, "Failed to setStreamStatus at decoder capture_plane");
  367. for (uint32_t i = 0; i < decoder_->capture_plane.getNumBuffers(); i++) {
  368. struct v4l2_buffer v4l2_buf;
  369. struct v4l2_plane planes[MAX_PLANES];
  370. memset(&v4l2_buf, 0, sizeof(v4l2_buf));
  371. memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
  372. v4l2_buf.index = i;
  373. v4l2_buf.m.planes = planes;
  374. v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  375. v4l2_buf.memory = V4L2_MEMORY_MMAP;
  376. ret = decoder_->capture_plane.qBuffer(v4l2_buf, NULL);
  377. INIT_ERROR(ret < 0, "Failed to qBuffer at encoder capture_plane");
  378. }
  379. return WEBRTC_VIDEO_CODEC_OK;
  380. }
  381. } // namespace sora