From a1f9be017be460f5fb5f0eaf6c432cd28a328743 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 8 Jan 2025 19:21:50 -0500 Subject: [PATCH] Use QUADRA instead of AV_HWDEVICE_TYPE_NI_QUADRA which is an enum. Implement non WallClockTimestamps for encoding --- src/zm_videostore.cpp | 83 ++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index c2562bf58..6d2cf4f82 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -43,9 +43,11 @@ extern "C" { VideoStore::CodecData VideoStore::codec_data[] = { #if HAVE_LIBAVUTIL_HWCONTEXT_H && LIBAVCODEC_VERSION_CHECK(57, 107, 0, 107, 0) +#ifdef QUADRA { AV_CODEC_ID_H265, "h265", "h265_ni_quadra_enc", AV_PIX_FMT_YUV420P, AV_PIX_FMT_NI_QUAD, AV_HWDEVICE_TYPE_NI_QUADRA, "-1" }, { AV_CODEC_ID_H264, "h264", "h264_ni_quadra_enc", AV_PIX_FMT_YUV420P, AV_PIX_FMT_NI_QUAD, AV_HWDEVICE_TYPE_NI_QUADRA, "-1" }, { AV_CODEC_ID_AV1, "av1", "av1_ni_quadra_enc", AV_PIX_FMT_YUV420P, AV_PIX_FMT_NI_QUAD, AV_HWDEVICE_TYPE_NI_QUADRA, "-1" }, +#endif { AV_CODEC_ID_H265, "h265", "hevc_vaapi", AV_PIX_FMT_NV12, AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI, nullptr }, { AV_CODEC_ID_H265, "h265", "hevc_qsv", AV_PIX_FMT_YUV420P, AV_PIX_FMT_QSV, AV_HWDEVICE_TYPE_QSV, nullptr }, { AV_CODEC_ID_H265, "h265", "hevc_nvenc", AV_PIX_FMT_NV12, AV_PIX_FMT_NV12, AV_HWDEVICE_TYPE_NONE, nullptr }, @@ -472,7 +474,7 @@ bool VideoStore::open() { } // end foreach codec if (!video_out_codec) { - Error("Can't open video codec!"); + Error("Can't open any video codecs!"); return false; } // end if can't open codec Debug(2, "Success opening codec"); @@ -1160,22 +1162,11 @@ int VideoStore::writeVideoFramePacket(const std::shared_ptr zm_packet) chosen_codec_data->sw_pix_fmt, video_out_ctx->width, video_out_ctx->height - ); + ); } else if (!zm_packet->in_frame) { - Debug(4, "Have no in_frame"); - if (zm_packet->packet->size and !zm_packet->decoded) { - Debug(4, "Decoding"); - if (!zm_packet->decode(video_in_ctx)) { - Debug(2, "unable to decode yet."); - return 0; - } - // Go straight to out frame - swscale.Convert(zm_packet->in_frame.get(), out_frame); - } else { - Error("Have neither in_frame or image in packet %d!", - zm_packet->image_index); - return 0; - } // end if has packet or image + Debug(1, "Have neither in_frame or image in packet %d!", + zm_packet->image_index); + return 0; } else { // Have in_frame.... may need to convert it to out_frame swscale.Convert(zm_packet->in_frame.get(), zm_packet->out_frame.get()); @@ -1208,18 +1199,19 @@ int VideoStore::writeVideoFramePacket(const std::shared_ptr zm_packet) } // end if hwaccel #endif - if (video_first_pts == AV_NOPTS_VALUE) { - video_first_pts = static_cast(std::chrono::duration_cast(zm_packet->timestamp.time_since_epoch()).count()); - Debug(2, "No video_first_pts, set to (%" PRId64 ") secs(%.2f)", + if (monitor->WallClockTimestamps() or !(zm_packet->in_frame || zm_packet->packet)) { + if (video_first_pts == AV_NOPTS_VALUE) { + video_first_pts = static_cast(std::chrono::duration_cast(zm_packet->timestamp.time_since_epoch()).count()); + Debug(2, "No video_first_pts, set to (%" PRId64 ") secs(%.2f)", video_first_pts, FPSeconds(zm_packet->timestamp.time_since_epoch()).count()); - frame->pts = 0; - } else { - Microseconds useconds = std::chrono::duration_cast( - zm_packet->timestamp - SystemTimePoint(Microseconds(video_first_pts))); - frame->pts = av_rescale_q(useconds.count(), AV_TIME_BASE_Q, video_out_ctx->time_base); - Debug(2, + frame->pts = 0; + } else { + Microseconds useconds = std::chrono::duration_cast( + zm_packet->timestamp - SystemTimePoint(Microseconds(video_first_pts))); + frame->pts = av_rescale_q(useconds.count(), AV_TIME_BASE_Q, video_out_ctx->time_base); + Debug(2, "Setting pts for frame(%d) to (%" PRId64 ") from (zm_packet->timestamp(%" PRIi64 " - first %" PRId64 " us %" PRId64 " ) @ %d/%d", frame_count, frame->pts, @@ -1228,6 +1220,47 @@ int VideoStore::writeVideoFramePacket(const std::shared_ptr zm_packet) static_cast(std::chrono::duration_cast(useconds).count()), video_out_ctx->time_base.num, video_out_ctx->time_base.den); + } + } else { + if (zm_packet->in_frame) { + if (video_first_pts == AV_NOPTS_VALUE) { + video_first_pts = zm_packet->in_frame->pts; + Debug(2, "No video_first_pts, set to (%" PRId64 ")", video_first_pts); + frame->pts = 0; + } else { + frame->pts = av_rescale_q(zm_packet->in_frame->pts - video_first_pts, zm_packet->in_frame->time_base, video_out_ctx->time_base); + Debug(2, + "Setting pts for frame(%d) to (%" PRId64 ") from (zm_packet->in_frame(%" PRIi64 " - first %" PRId64 " ) @ %d/%d=>%d/%d", + frame_count, + frame->pts, + zm_packet->in_frame->pts, + video_first_pts, + zm_packet->in_frame->time_base.num, + zm_packet->in_frame->time_base.den, + video_out_ctx->time_base.num, + video_out_ctx->time_base.den); + } + } else if (zm_packet->packet) { + if (video_first_pts == AV_NOPTS_VALUE) { + video_first_pts = zm_packet->packet->pts; + Debug(2, "No video_first_pts, set to (%" PRId64 ")", video_first_pts); + frame->pts = 0; + } else { + frame->pts = av_rescale_q(zm_packet->packet->pts-video_first_pts, video_in_stream->time_base, video_out_ctx->time_base); + Debug(2, + "Setting pts for frame(%d) to (%" PRId64 ") from (zm_packet->in_frame(%" PRIi64 " - first %" PRId64 " ) @ %d/%d=>%d/%d", + frame_count, + frame->pts, + zm_packet->packet->pts, + video_first_pts, + video_in_stream->time_base.num, + video_in_stream->time_base.den, + video_out_ctx->time_base.num, + video_out_ctx->time_base.den); + } + } else { + Error("No pts from any source."); + } } // Some hwaccel codecs may get full if we only receive one pkt for one frame