[FFmpeg-devel] [PATCH v2 4/4] avcodec/nvenc: support for HEVC timecode passthrough
Timo Rothenpieler
timo at rothenpieler.org
Wed Jun 17 19:41:45 EEST 2020
On 17.06.2020 18:07, lance.lmwang at gmail.com wrote:
> 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++;
> + }
> + }
> + }
> + }
> +
Does all this really have to be in nvenc? It looks very generic to me,
and better put in some central location to be re-used by multiple codecs.
More information about the ffmpeg-devel
mailing list