123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- #include <limits>
- #include <string>
- // WebRTC
- #include <common_video/libyuv/include/webrtc_libyuv.h>
- #include <modules/video_coding/codecs/h264/include/h264.h>
- #include <modules/video_coding/include/video_codec_interface.h>
- #include <modules/video_coding/include/video_error_codes.h>
- // #include <modules/video_coding/svc/create_scalability_structure.h>
- #include <rtc_base/checks.h>
- #include <rtc_base/logging.h>
- #include <rtc_base/time_utils.h>
- #include <system_wrappers/include/metrics.h>
- // libyuv
- #include <libyuv/convert.h>
- #include <libyuv/convert_from.h>
- #include <libyuv/video_common.h>
- // L4T Multimedia API
- #include "NvBufSurface.h"
- #include "NvVideoEncoder.h"
- #include "nvbufsurface.h"
- #include "nvbufsurftransform.h"
- #include "jetson_nv_encoder.h"
- #define H264HWENC_HEADER_DEBUG 0
- #define INIT_ERROR(cond, desc) \
- if (cond) { \
- RTC_LOG(LS_ERROR) << __FUNCTION__ << desc; \
- Release(); \
- return WEBRTC_VIDEO_CODEC_ERROR; \
- }
- namespace webrtc {
- JetsonVideoEncoder::JetsonVideoEncoder(const cricket::VideoCodec& codec)
- : callback_(nullptr),
- encoder_(nullptr),
- configured_framerate_(30),
- use_native_(true),
- use_dmabuff_(true) {}
- JetsonVideoEncoder::~JetsonVideoEncoder() {
- Release();
- }
- // bool JetsonVideoEncoder::IsSupported(webrtc::VideoCodecType codec) {
- // //SuppressErrors sup;
- // printf("----------------------------------------------------------------------------------issupported\n");
- // auto encoder = NvVideoEncoder::createVideoEncoder("enc0");
- // // auto ret = encoder->setCapturePlaneFormat(VideoCodecToV4L2Format(codec), 1024,
- // // 768, 2 * 1024 * 1024);
- // auto ret = encoder->setCapturePlaneFormat(V4L2_PIX_FMT_H264, 1280,
- // 720, 2 * 1024 * 1024);
- // delete encoder;
- // return ret >= 0;
- // }
- int32_t JetsonVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
- int32_t number_of_cores,
- size_t max_payload_size) {
- RTC_DCHECK(codec_settings);
- int32_t release_ret = Release();
- if (release_ret != WEBRTC_VIDEO_CODEC_OK) {
- return release_ret;
- }
- if (&codec_ != codec_settings) {
- codec_ = *codec_settings;
- }
- width_ = codec_settings->width;
- height_ = codec_settings->height;
- target_bitrate_bps_ = codec_settings->startBitrate * 1000;
- // std::cout << "g=heig " << width_ << height_ << target_bitrate_bps_ << std::endl;
- key_frame_interval_ = codec_settings->H264().keyFrameInterval;
- framerate_ = codec_settings->maxFramerate;
- // std::cout << "---------------------------------------------framerate_" << framerate_ << std::endl;
- RTC_LOG(LS_INFO) << "InitEncode " << framerate_ << "fps "
- << target_bitrate_bps_ << "bit/sec "
- << codec_settings->maxBitrate << "kbit/sec ";
- // Initialize encoded image.
- encoded_image_.timing_.flags =
- webrtc::VideoSendTiming::TimingFrameFlags::kInvalid;
- encoded_image_.content_type_ =
- (codec_settings->mode == webrtc::VideoCodecMode::kScreensharing)
- ? webrtc::VideoContentType::SCREENSHARE
- : webrtc::VideoContentType::UNSPECIFIED;
- gof_idx_ = 0;
- RTC_LOG(LS_INFO) << __FUNCTION__ << " End";
- return WEBRTC_VIDEO_CODEC_OK;
- }
- int32_t JetsonVideoEncoder::Release() {
- JetsonRelease();
- return WEBRTC_VIDEO_CODEC_OK;
- }
- int32_t JetsonVideoEncoder::JetsonConfigure() {
- int ret = 0;
- bool use_converter =
- use_native_ && (width_ != raw_width_ || height_ != raw_height_ ||
- decode_pixfmt_ != V4L2_PIX_FMT_YUV420M);
- encoder_ = NvVideoEncoder::createVideoEncoder("enc0");
- INIT_ERROR(!encoder_, "Failed to createVideoEncoder");
- ret =encoder_->setCapturePlaneFormat(V4L2_PIX_FMT_H264,width_, height_, 2 * 1024 * 1024);
- printf("width_;%d, height_:%d\n",width_,height_);
- INIT_ERROR(ret < 0, "Failed to encoder setCapturePlaneFormat");
- ret = encoder_->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, width_, height_);
- INIT_ERROR(ret < 0, "Failed to encoder setOutputPlaneFormat");
- // ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
- ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN);
- // ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10);
- // ret = encoder_->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
- INIT_ERROR(ret < 0, "Failed to setProfile");
- // ret = encoder_->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
- ret = encoder_->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_2_1);
- // INIT_ERROR(ret < 0, "Failed to setLevel");
- ret = encoder_->setNumBFrames(0);
- // ret = encoder_->setNumBFrames(1);
- INIT_ERROR(ret < 0, "Failed to setNumBFrames");
- ret = encoder_->setInsertSpsPpsAtIdrEnabled(true);
- // ret = encoder_->setInsertSpsPpsAtIdrEnabled(false);
- INIT_ERROR(ret < 0, "Failed to setInsertSpsPpsAtIdrEnabled");
- ret = encoder_->setInsertVuiEnabled(true);
- // ret = encoder_->setInsertVuiEnabled(false);
- INIT_ERROR(ret < 0, "Failed to setInsertSpsPpsAtIdrEnabled");
- // ret = encoder_->setHWPresetType(V4L2_ENC_HW_PRESET_FAST);
- ret = encoder_->setHWPresetType(V4L2_ENC_HW_PRESET_ULTRAFAST);
- // ret = encoder_->setHWPresetType(V4L2_ENC_HW_PRESET_SLOW);
- INIT_ERROR(ret < 0, "Failed to setHWPresetType");
- bitrate_adjuster_.reset(new webrtc::BitrateAdjuster(.5, .95));
- bitrate_adjuster_->SetTargetBitrateBps(target_bitrate_bps_);
- SetBitrateBps(target_bitrate_bps_);
- ret = encoder_->setIDRInterval(key_frame_interval_);
- INIT_ERROR(ret < 0, "Failed to setIDRInterval");
- // ret = encoder_->setIFrameInterval(key_frame_interval_);
- ret = encoder_->setIFrameInterval(0);
- INIT_ERROR(ret < 0, "Failed to setIFrameInterval");
- //
- // ret = encoder_->setFrameRate(framerate_, 1);
- ret = encoder_->setFrameRate(30, 1);
- INIT_ERROR(ret < 0, "Failed to setFrameRate");
- if (use_native_) {
- std::cout << "use native -------------------------------------------\n" << std::endl;
- if (use_dmabuff_ || use_converter) {
- std::cout << "use use_converter -------------------------------------------\n" << std::endl;
- ret = encoder_->output_plane.reqbufs(V4L2_MEMORY_DMABUF, 10);
- INIT_ERROR(ret < 0, "Failed to reqbufs at encoder output_plane");
- int fd;
- NvBufSurf::NvCommonAllocateParams cParams;
- cParams.width = width_;
- cParams.height = height_;
- cParams.layout = NVBUF_LAYOUT_PITCH;
- cParams.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
- cParams.memtag = NvBufSurfaceTag_VIDEO_ENC;
- cParams.memType = NVBUF_MEM_SURFACE_ARRAY;
- for (uint32_t i = 0; i < encoder_->output_plane.getNumBuffers(); i++) {
- ret = NvBufSurf::NvAllocate(&cParams, 1, &fd);
- INIT_ERROR(ret, "Failed to create NvBuffer");
- RTC_LOG(LS_ERROR) << "NvBufferCreateEx i:" << i << " fd:" << fd;
- output_plane_fd_[i] = fd;
- }
- }
- else {
- std::cout << "V4L2_MEMORY_USERPTR-------------------\n" << std::endl;
- ret = encoder_->output_plane.setupPlane(V4L2_MEMORY_USERPTR, 1, false,
- false);
- INIT_ERROR(ret < 0, "Failed to setupPlane at encoder output_plane");
- }
- } else {
- std::cout << "V4L2_MEMORY_MMAP-------------------\n" << std::endl;
- ret = encoder_->output_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
- INIT_ERROR(ret < 0, "Failed to setupPlane at encoder output_plane");
- }
- ret = encoder_->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
- INIT_ERROR(ret < 0, "Failed to setupPlane at capture_plane");
- ret = encoder_->subscribeEvent(V4L2_EVENT_EOS, 0, 0);
- INIT_ERROR(ret < 0, "Failed to subscribeEvent V4L2_EVENT_EOS");
- ret = encoder_->output_plane.setStreamStatus(true);
- INIT_ERROR(ret < 0, "Failed to setStreamStatus at encoder output_plane");
- ret = encoder_->capture_plane.setStreamStatus(true);
- INIT_ERROR(ret < 0, "Failed to setStreamStatus at encoder capture_plane");
- encoder_->capture_plane.setDQThreadCallback(EncodeFinishedCallbackFunction);
- encoder_->capture_plane.startDQThread(this);
- for (uint32_t i = 0; i < encoder_->capture_plane.getNumBuffers(); i++) {
- struct v4l2_buffer v4l2_buf;
- struct v4l2_plane planes[MAX_PLANES];
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
- v4l2_buf.index = i;
- v4l2_buf.m.planes = planes;
- ret = encoder_->capture_plane.qBuffer(v4l2_buf, NULL);
- INIT_ERROR(ret < 0, "Failed to qBuffer at encoder capture_plane");
- }
- configured_framerate_ = framerate_;
- return WEBRTC_VIDEO_CODEC_OK;
- }
- void JetsonVideoEncoder::JetsonRelease() {
- if (!encoder_)
- return;
- SendEOS();
- encoder_->capture_plane.waitForDQThread(2000);
- encoder_->capture_plane.deinitPlane();
- if (use_dmabuff_) {
- for (uint32_t i = 0; i < encoder_->output_plane.getNumBuffers(); i++) {
- if (encoder_->output_plane.unmapOutputBuffers(i, output_plane_fd_[i]) <
- 0) {
- RTC_LOG(LS_ERROR)
- << "Failed to unmapOutputBuffers at encoder output_plane";
- }
- if (NvBufSurf::NvDestroy(output_plane_fd_[i]) < 0) {
- RTC_LOG(LS_ERROR)
- << "Failed to NvBufferDestroy at encoder output_plane";
- }
- }
- } else {
- encoder_->output_plane.deinitPlane();
- }
- delete encoder_;
- encoder_ = nullptr;
- }
- void JetsonVideoEncoder::SendEOS() {
- if (encoder_->output_plane.getStreamStatus()) {
- struct v4l2_buffer v4l2_buf;
- struct v4l2_plane planes[MAX_PLANES];
- NvBuffer* buffer;
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
- v4l2_buf.m.planes = planes;
- if (encoder_->output_plane.getNumQueuedBuffers() ==
- encoder_->output_plane.getNumBuffers()) {
- if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
- }
- }
- planes[0].bytesused = 0;
- for (int i = 0; i < buffer->n_planes; i++) {
- buffer->planes[i].bytesused = 0;
- }
- if (encoder_->output_plane.qBuffer(v4l2_buf, NULL) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
- }
- }
- }
- bool JetsonVideoEncoder::EncodeFinishedCallbackFunction(
- struct v4l2_buffer* v4l2_buf,
- NvBuffer* buffer,
- NvBuffer* shared_buffer,
- void* data) {
- return ((JetsonVideoEncoder*)data)
- ->EncodeFinishedCallback(v4l2_buf, buffer, shared_buffer);
- }
- bool JetsonVideoEncoder::EncodeFinishedCallback(struct v4l2_buffer* v4l2_buf,
- NvBuffer* buffer,
- NvBuffer* shared_buffer) {
- if (!v4l2_buf) {
- RTC_LOG(LS_INFO) << __FUNCTION__ << " v4l2_buf is null";
- return false;
- }
- if (buffer->planes[0].bytesused == 0) {
- RTC_LOG(LS_INFO) << __FUNCTION__ << " buffer size is zero";
- return false;
- }
- uint64_t timestamp = v4l2_buf->timestamp.tv_sec * rtc::kNumMicrosecsPerSec +
- v4l2_buf->timestamp.tv_usec;
- std::unique_ptr<FrameParams> params;
- {
- webrtc::MutexLock lock(&frame_params_lock_);
- do {
- if (frame_params_.empty()) {
- RTC_LOG(LS_WARNING)
- << __FUNCTION__
- << "Frame parameter is not found. SkipFrame timestamp:"
- << timestamp;
- return true;
- }
- params = std::move(frame_params_.front());
- frame_params_.pop();
- } while (params->timestamp_us < timestamp);
- if (params->timestamp_us != timestamp) {
- RTC_LOG(LS_WARNING)
- << __FUNCTION__
- << "Frame parameter is not found. SkipFrame timestamp:" << timestamp;
- return true;
- }
- }
- v4l2_ctrl_videoenc_outputbuf_metadata enc_metadata;
- if (encoder_->getMetadata(v4l2_buf->index, enc_metadata) != 0) {
- RTC_LOG(LS_WARNING) << __FUNCTION__
- << "getMetadata failed. SkipFrame timestamp:"
- << timestamp;
- return true;
- }
- SendFrame(buffer->planes[0].data, buffer->planes[0].bytesused,
- std::move(params), &enc_metadata);
- if (encoder_->capture_plane.qBuffer(*v4l2_buf, NULL) < 0) {
- RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to qBuffer at capture_plane";
- return false;
- }
- return true;
- }
- int32_t JetsonVideoEncoder::RegisterEncodeCompleteCallback(
- webrtc::EncodedImageCallback* callback) {
- callback_ = callback;
- return WEBRTC_VIDEO_CODEC_OK;
- }
- void JetsonVideoEncoder::SetRates(const RateControlParameters& parameters) {
- // printf("SetRatesSetRatesSetRatesSetRatesSetRatesSetRatesSetRates\n");
- if (encoder_ == nullptr)
- return;
- if (parameters.bitrate.get_sum_bps() <= 0 || parameters.framerate_fps <= 0)
- return;
- RTC_LOG(LS_INFO) << __FUNCTION__ << " framerate:" << parameters.framerate_fps
- << " bitrate:" << parameters.bitrate.ToString();
- // if (svc_controller_) {
- // svc_controller_->OnRatesUpdated(parameters.bitrate);
- // }
- framerate_ = parameters.framerate_fps;
- target_bitrate_bps_ = parameters.bitrate.get_sum_bps();
- bitrate_adjuster_->SetTargetBitrateBps(target_bitrate_bps_);
- return;
- }
- void JetsonVideoEncoder::SetFramerate(uint32_t framerate) {
- if (configured_framerate_ == framerate) {
- return;
- }
- RTC_LOG(LS_INFO) << __FUNCTION__ << " " << framerate << "fps";
- if (encoder_->setFrameRate(framerate, 1) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to set bitrate";
- return;
- }
- configured_framerate_ = framerate;
- }
- void JetsonVideoEncoder::SetBitrateBps(uint32_t bitrate_bps) {
- if (bitrate_bps < 300000 || (configured_bitrate_bps_ == bitrate_bps &&
- configured_framerate_ == framerate_)) {
- return;
- }
- configured_bitrate_bps_ = bitrate_bps;
- if (encoder_->setBitrate(bitrate_bps) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to setBitrate";
- return;
- }
- }
- webrtc::VideoEncoder::EncoderInfo JetsonVideoEncoder::GetEncoderInfo() const {
- EncoderInfo info;
- info.supports_native_handle = true;
- info.implementation_name = "Jetson Video Encoder";
- static const int kLowH264QpThreshold = 24; //34
- static const int kHighH264QpThreshold = 37; //40
- info.scaling_settings = VideoEncoder::ScalingSettings(kLowH264QpThreshold,
- kHighH264QpThreshold);
- return info;
- }
- int32_t JetsonVideoEncoder::Encode(
- const webrtc::VideoFrame& input_frame,
- const std::vector<webrtc::VideoFrameType>* frame_types) {
- // printf("encode encode \n");
- if (!callback_) {
- RTC_LOG(LS_WARNING)
- << "InitEncode() has been called, but a callback function "
- << "has not been set with RegisterEncodeCompleteCallback()";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
- }
- int fd = 0;
- webrtc::VideoType video_type;
- uint8_t* native_data;
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer =
- input_frame.video_frame_buffer();
- // std::shared_ptr<JetsonJpegDecoder> decoder;
- if (frame_buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) {
- use_native_ = true;
-
- } else {
- use_native_ = false;
- }
- if (encoder_ == nullptr) {
- if (JetsonConfigure() != WEBRTC_VIDEO_CODEC_OK) {
- RTC_LOG(LS_ERROR) << "Failed to JetsonConfigure";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- }
- bool force_key_frame = false;
- if (frame_types != nullptr) {
- RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1));
- if ((*frame_types)[0] == webrtc::VideoFrameType::kEmptyFrame) {
- return WEBRTC_VIDEO_CODEC_OK;
- }
- if ((*frame_types)[0] == webrtc::VideoFrameType::kVideoFrameKey) {
- if (encoder_->forceIDR() < 0) {
- RTC_LOG(LS_ERROR) << "Failed to forceIDR";
- }
- }
- }
- SetFramerate(framerate_);
- SetBitrateBps(bitrate_adjuster_->GetAdjustedBitrateBps());
- {
- webrtc::MutexLock lock(&frame_params_lock_);
- frame_params_.push(absl::make_unique<FrameParams>(
- frame_buffer->width(), frame_buffer->height(),
- input_frame.render_time_ms(), input_frame.ntp_time_ms(),
- input_frame.timestamp_us(), input_frame.timestamp(),
- // input_frame.rotation(), input_frame.color_space(), decoder));
- input_frame.rotation(), input_frame.color_space()));
- }
- struct v4l2_buffer v4l2_buf;
- struct v4l2_plane planes[MAX_PLANES];
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- memset(planes, 0, sizeof(planes));
- v4l2_buf.m.planes = planes;
- if (use_native_) {
- NvBuffer* buffer;
- if (encoder_->output_plane.getNumQueuedBuffers() ==
- encoder_->output_plane.getNumBuffers()) {
- if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- } else {
- buffer = encoder_->output_plane.getNthBuffer(
- encoder_->output_plane.getNumQueuedBuffers());
- v4l2_buf.index = encoder_->output_plane.getNumQueuedBuffers();
- }
- int src_dma_fd = -1;
- if (use_dmabuff_) {
- src_dma_fd = fd;
- } else if (video_type == webrtc::VideoType::kYUY2 ||
- video_type == webrtc::VideoType::kUYVY) {
- buffer->planes[0].bytesused = buffer->planes[0].fmt.width *
- buffer->planes[0].fmt.bytesperpixel *
- buffer->planes[0].fmt.height;
- buffer->planes[0].data = native_data;
- } else if (video_type == webrtc::VideoType::kI420) {
- size_t offset = 0;
- for (int i = 0; i < buffer->n_planes; i++) {
- buffer->planes[i].bytesused = buffer->planes[i].fmt.width *
- buffer->planes[i].fmt.bytesperpixel *
- buffer->planes[i].fmt.height;
- buffer->planes[i].data = native_data + offset;
- offset += buffer->planes[i].bytesused;
- }
- } else if (video_type == webrtc::VideoType::kYV12) {
- size_t offset = 0;
- buffer->planes[0].bytesused = buffer->planes[0].fmt.width *
- buffer->planes[0].fmt.bytesperpixel *
- buffer->planes[0].fmt.height;
- buffer->planes[0].data = native_data;
- offset += buffer->planes[0].bytesused;
- buffer->planes[2].bytesused = buffer->planes[1].fmt.width *
- buffer->planes[1].fmt.bytesperpixel *
- buffer->planes[1].fmt.height;
- buffer->planes[2].data = native_data + offset;
- offset += buffer->planes[2].bytesused;
- buffer->planes[1].bytesused = buffer->planes[2].fmt.width *
- buffer->planes[2].fmt.bytesperpixel *
- buffer->planes[2].fmt.height;
- buffer->planes[1].data = native_data + offset;
- } else {
- RTC_LOG(LS_ERROR) << "Unsupported webrtc::VideoType";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- NvBufSurf::NvCommonTransformParams transform_params;
- /* Indicates which of the transform parameters are valid */
- memset(&transform_params, 0, sizeof(transform_params));
- transform_params.src_top = 0;
- transform_params.src_left = 0;
- transform_params.src_width = raw_width_;
- transform_params.src_height = raw_height_;
- transform_params.dst_top = 0;
- transform_params.dst_left = 0;
- transform_params.dst_width = width_;
- transform_params.dst_height = height_;
- transform_params.flag =
- (NvBufSurfTransform_Transform_Flag)(NVBUFSURF_TRANSFORM_FILTER |
- NVBUFSURF_TRANSFORM_CROP_SRC);
- transform_params.flip = NvBufSurfTransform_None;
- transform_params.filter = NvBufSurfTransformInter_Bilinear;
- if (NvBufSurf::NvTransform(&transform_params, src_dma_fd,
- output_plane_fd_[v4l2_buf.index])) {
- RTC_LOG(LS_ERROR) << "Failed to NvBufferTransform";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- planes[0].m.fd = output_plane_fd_[v4l2_buf.index];
- planes[0].bytesused = 1234;
- v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- v4l2_buf.memory = V4L2_MEMORY_DMABUF;
- v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
- v4l2_buf.timestamp.tv_sec =
- input_frame.timestamp_us() / rtc::kNumMicrosecsPerSec;
- v4l2_buf.timestamp.tv_usec =
- input_frame.timestamp_us() % rtc::kNumMicrosecsPerSec;
- if (encoder_->output_plane.qBuffer(v4l2_buf, nullptr) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to qBuffer at converter output_plane";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- } else {
- NvBuffer* buffer;
- RTC_LOG(LS_VERBOSE) << __FUNCTION__ << " output_plane.getNumBuffers: "
- << encoder_->output_plane.getNumBuffers()
- << " output_plane.getNumQueuedBuffers: "
- << encoder_->output_plane.getNumQueuedBuffers();
- if (encoder_->output_plane.getNumQueuedBuffers() ==
- encoder_->output_plane.getNumBuffers()) {
- if (encoder_->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to dqBuffer at encoder output_plane";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- } else {
- buffer = encoder_->output_plane.getNthBuffer(
- encoder_->output_plane.getNumQueuedBuffers());
- v4l2_buf.index = encoder_->output_plane.getNumQueuedBuffers();
- }
- rtc::scoped_refptr<const webrtc::I420BufferInterface> i420_buffer =
- frame_buffer->ToI420();
- for (uint32_t i = 0; i < buffer->n_planes; i++) {
- const uint8_t* source_data;
- int source_stride;
- if (i == 0) {
- source_data = i420_buffer->DataY();
- source_stride = i420_buffer->StrideY();
- } else if (i == 1) {
- source_data = i420_buffer->DataU();
- source_stride = i420_buffer->StrideU();
- } else if (i == 2) {
- source_data = i420_buffer->DataV();
- source_stride = i420_buffer->StrideV();
- } else {
- break;
- }
- NvBuffer::NvBufferPlane& plane = buffer->planes[i];
- std::streamsize bytes_to_read = plane.fmt.bytesperpixel * plane.fmt.width;
- uint8_t* input_data = plane.data;
- plane.bytesused = 0;
- for (uint32_t j = 0; j < plane.fmt.height; j++) {
- memcpy(input_data, source_data + (source_stride * j), bytes_to_read);
- input_data += plane.fmt.stride;
- }
- plane.bytesused = plane.fmt.stride * plane.fmt.height;
- }
- v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
- v4l2_buf.timestamp.tv_sec =
- input_frame.timestamp_us() / rtc::kNumMicrosecsPerSec;
- v4l2_buf.timestamp.tv_usec =
- input_frame.timestamp_us() % rtc::kNumMicrosecsPerSec;
- for (int i = 0; i < MAX_PLANES; i++) {
- NvBufSurface* surf = 0;
- if (NvBufSurfaceFromFd(buffer->planes[i].fd, (void**)(&surf)) == -1) {
- RTC_LOG(LS_ERROR) << __FUNCTION__ << "Failed to NvBufSurfaceFromFd";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- if (NvBufSurfaceSyncForDevice(surf, 0, i) == -1) {
- RTC_LOG(LS_ERROR) << "Failed to NvBufSurfaceSyncForDevice";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- }
- if (encoder_->output_plane.qBuffer(v4l2_buf, nullptr) < 0) {
- RTC_LOG(LS_ERROR) << "Failed to qBuffer at encoder output_plane";
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- }
- return WEBRTC_VIDEO_CODEC_OK;
- }
- int32_t JetsonVideoEncoder::SendFrame(
- unsigned char* buffer,
- size_t size,
- std::unique_ptr<FrameParams> params,
- v4l2_ctrl_videoenc_outputbuf_metadata* enc_metadata) {
- if (!callback_) {
- RTC_LOG(LS_WARNING)
- << "InitEncode() has been called, but a callback function "
- << "has not been set with RegisterEncodeCompleteCallback()";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
- }
- // encoded_image_.SetRtpTimestamp(params->timestamp_rtp);
- encoded_image_.SetTimestamp(params->timestamp_rtp);
- encoded_image_.SetColorSpace(params->color_space);
- encoded_image_._encodedWidth = params->width;
- encoded_image_._encodedHeight = params->height;
- encoded_image_.capture_time_ms_ = params->render_time_ms;
- encoded_image_.ntp_time_ms_ = params->ntp_time_ms;
- encoded_image_.rotation_ = params->rotation;
- encoded_image_.qp_ = enc_metadata->AvgQP;
- // if (enc_metadata->KeyFrame) {
- // encoded_image_.SetFrameType(webrtc::VideoFrameType::kVideoFrameKey);
- // } else {
- // encoded_image_.SetFrameType(webrtc::VideoFrameType::kVideoFrameDelta);
- // }
- if (enc_metadata->KeyFrame) {
- encoded_image_._frameType= webrtc::VideoFrameType::kVideoFrameKey;
- } else {
- encoded_image_._frameType= webrtc::VideoFrameType::kVideoFrameDelta;
- }
- webrtc::CodecSpecificInfo codec_specific;
- codec_specific.codecType = codec_.codecType;
- auto encoded_image_buffer =
- webrtc::EncodedImageBuffer::Create(buffer, size);
- encoded_image_.SetEncodedData(encoded_image_buffer);
- codec_specific.codecSpecific.H264.packetization_mode =
- webrtc::H264PacketizationMode::NonInterleaved;
- // webrtc::H264PacketizationMode::SingleNalUnit;
-
- RTC_LOG(LS_VERBOSE) << "key_frame=" << enc_metadata->KeyFrame
- << " size=" << size << " qp=" << encoded_image_.qp_;
- webrtc::EncodedImageCallback::Result result =
- callback_->OnEncodedImage(encoded_image_, &codec_specific);
- if (result.error != webrtc::EncodedImageCallback::Result::OK) {
- RTC_LOG(LS_ERROR) << __FUNCTION__
- << " OnEncodedImage failed error:" << result.error;
- return WEBRTC_VIDEO_CODEC_ERROR;
- }
- bitrate_adjuster_->Update(size);
- return WEBRTC_VIDEO_CODEC_OK;
- }
- } // namespace webrtc
|