[FFmpeg-devel] [PATCH v2 4/4] avcodec/nvenc: support for HEVC timecode passthrough
lance.lmwang at gmail.com
lance.lmwang at gmail.com
Wed Jun 17 19:07:10 EEST 2020
From: Limin Wang <lance.lmwang at gmail.com>
Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
---
I failed to find any document about nvenc so that I can update for new option.
libavcodec/nvenc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/nvenc.h | 1 +
libavcodec/nvenc_hevc.c | 1 +
3 files changed, 55 insertions(+)
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index e4356ce..68b212a 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -22,6 +22,8 @@
#include "config.h"
#include "nvenc.h"
+#include "hevc_sei.h"
+#include "put_bits.h"
#include "libavutil/hwcontext_cuda.h"
#include "libavutil/hwcontext.h"
@@ -2068,6 +2070,15 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
}
}
+static unsigned bcd2uint(uint8_t bcd)
+{
+ unsigned low = bcd & 0xf;
+ unsigned high = bcd >> 4;
+ if (low > 9 || high > 9)
+ return 0;
+ return low + 10*high;
+}
+
int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{
NVENCSTATUS nv_status;
@@ -2156,6 +2167,48 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
}
}
+ if (ctx->tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) {
+ AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE);
+ if (sd) {
+ uint32_t *tc = (uint32_t*)sd->data;
+ int m = tc[0] & 3;
+ if (tc) {
+ sei_data[sei_count].payloadSize = sizeof(uint32_t) * 4;
+ sei_data[sei_count].payloadType = HEVC_SEI_TYPE_TIME_CODE;
+ sei_data[sei_count].payload = av_mallocz(sei_data[sei_count].payloadSize);
+ if (sei_data[sei_count].payload) {
+ PutBitContext pb;
+
+ init_put_bits(&pb, sei_data[sei_count].payload, sei_data[sei_count].payloadSize);
+ put_bits(&pb, 2, m); // num_clock_ts
+
+ for (int j = 1; j <= m; j++) {
+ uint32_t tcsmpte = tc[j];
+ unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours
+ unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes
+ unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds
+ unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames
+ unsigned drop = tcsmpte & 1<<30 && !0; // 1-bit drop if not arbitrary bit
+
+ put_bits(&pb, 1, 1); // clock_timestamp_flag
+ put_bits(&pb, 1, 1); // units_field_based_flag
+ put_bits(&pb, 5, 0); // counting_type
+ put_bits(&pb, 1, 1); // full_timestamp_flag
+ put_bits(&pb, 1, 0); // discontinuity_flag
+ put_bits(&pb, 1, drop);
+ put_bits(&pb, 9, ff);
+ put_bits(&pb, 6, ss);
+ put_bits(&pb, 6, mm);
+ put_bits(&pb, 5, hh);
+ put_bits(&pb, 5, 0);
+ }
+ flush_put_bits(&pb);
+ sei_count++;
+ }
+ }
+ }
+ }
+
nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, sei_count);
} else {
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index 7a415a4..f1adaeb 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -196,6 +196,7 @@ typedef struct NvencContext
int coder;
int b_ref_mode;
int a53_cc;
+ int tc;
int dpb_size;
} NvencContext;
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 7f12b56..6eef613 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -129,6 +129,7 @@ static const AVOption options[] = {
{ "each", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" },
{ "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" },
#endif
+ { "tc", "Use timecode (if available)", OFFSET(tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
{ "dpb_size", "Specifies the DPB size used for encoding (0 means automatic)",
OFFSET(dpb_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
{ NULL }
--
1.8.3.1
More information about the ffmpeg-devel
mailing list