On Thu, Dec 18, 2014 at 01:35:05PM +0800, ahu wrote: [...] > configure | 11 > doc/examples/Makefile | 1 > doc/examples/libnvenc.c | 198 +++++++++ > ffmpeg.c | 2 > libavcodec/Makefile | 1 > libavcodec/allcodecs.c | 1 > libavcodec/libnvenc.c | 413 ++++++++++++++++++++ > libavcodec/libnvenc.h | 142 +++++++ > libavcodec/nvencoder.c | 864 > +++++++++++++++++++++++++++++++++++++++++++ > libavcodec/nvencoder.h | 98 ++++ > libavcodec/nvencoder_utils.c | 345 +++++++++++++++++ > libavcodec/nvencoder_utils.h | 30 + > libavformat/matroskaenc.c | 2 > libavformat/movenc.c | 6 > 14 files changed, 2109 insertions(+), 5 deletions(-) > 02de15b36b3a5f675e720ebac609d82831ef2d58 0001-add-libnvenc-support.patch > From 98dbd7bd1894dc438b8fe909373d6ec2f4ddb6f3 Mon Sep 17 00:00:00 2001 > From: agathah <a...@nvidia.com> > Date: Thu, 18 Dec 2014 12:01:15 +0800 > Subject: [PATCH] add libnvenc support > > --- > configure | 11 + > doc/examples/Makefile | 1 + > doc/examples/libnvenc.c | 198 ++++++++++ > ffmpeg.c | 2 +- > libavcodec/Makefile | 1 + > libavcodec/allcodecs.c | 1 + > libavcodec/libnvenc.c | 413 +++++++++++++++++++++ > libavcodec/libnvenc.h | 142 +++++++ > libavcodec/nvencoder.c | 864 > +++++++++++++++++++++++++++++++++++++++++++ > libavcodec/nvencoder.h | 98 +++++ > libavcodec/nvencoder_utils.c | 345 +++++++++++++++++ > libavcodec/nvencoder_utils.h | 30 ++ > libavformat/matroskaenc.c | 2 +- > libavformat/movenc.c | 6 +- > 14 files changed, 2109 insertions(+), 5 deletions(-) > create mode 100644 doc/examples/libnvenc.c > create mode 100644 libavcodec/libnvenc.c > create mode 100644 libavcodec/libnvenc.h > create mode 100644 libavcodec/nvencoder.c > create mode 100644 libavcodec/nvencoder.h > create mode 100644 libavcodec/nvencoder_utils.c > create mode 100644 libavcodec/nvencoder_utils.h > > diff --git a/configure b/configure > index 3328026..798db4c 100644 > --- a/configure > +++ b/configure > @@ -264,6 +264,7 @@ External library support: > --disable-lzma disable lzma [autodetect] > --enable-decklink enable Blackmagick DeckLink I/O support [no] > --enable-nvenc enable NVIDIA NVENC support [no] > + --enable-libnvenc enable NVIDIA NVENC support [no]
tabs are forbidden in ffmpeg git except makefiles [...] > +int main(int argc, char* argv[]) > +{ > + char* inputfile = NULL; > + char* preset = "default"; > + bool zerolatency = false; > + > + for(int i = 1; i < argc; i++) { the int i should be outside the for() for slightly improved compiler compatibility [...] > + enc_ctx->time_base.den = dec_ctx->time_base.den/2; > + enc_ctx->bit_rate = bitrate; > + enc_ctx->flags |= (oc->oformat->flags & AVFMT_GLOBALHEADER) ? > CODEC_FLAG_GLOBAL_HEADER : 0; > + av_opt_set(enc_ctx->priv_data, "preset", preset, 0); // "fast" = HP, > "slow" = HQ, default = LOW_LATENCY_DEFAULT > + if(zerolatency) { > + //use LOW_LATENCY preset > + av_opt_set(enc_ctx->priv_data, "tune", "zerolatency", 0); > + } > + > + ret = avcodec_open2(enc_ctx, enc, NULL); > + if (ret < 0) { > + printf("could not open codec\n"); > + return -1; > + } > + ret = avformat_write_header(oc, NULL); > + > + AVPacket dec_pkt; > + av_init_packet(&dec_pkt); > + dec_pkt.data = NULL; > + dec_pkt.size = 0; > + > + AVFrame *frame = avcodec_alloc_frame(); > + int got_frame = 0; mixed declarations and statements > + while(av_read_frame(fmt_ctx, &dec_pkt) >= 0) { > + if(dec_pkt.stream_index == video_stream_idx) { > + if(avcodec_decode_video2(dec_ctx, frame, &got_frame, &dec_pkt) < > 0) { > + printf("Error decoding frames!\n"); > + return -1; > + } > + if(got_frame) { > + AVPacket enc_pkt; > + int got_pkt = 0; > + av_init_packet(&enc_pkt); > + enc_pkt.data = NULL; > + enc_pkt.size = 0; > + if(avcodec_encode_video2(vst_enc->codec, &enc_pkt, frame, > &got_pkt) < 0) { > + printf("Error encoding frames!\n"); > + return -1; > + } > + > + if(got_pkt) { > + av_write_frame(oc, &enc_pkt); > + } > + > + av_free_packet(&enc_pkt); > + } > + } > + av_free_packet(&dec_pkt); > + } > + avcodec_free_frame(&frame); > + av_write_trailer(oc); > + > + avcodec_close(dec_ctx); > + avcodec_close(enc_ctx); > + avformat_close_input(&fmt_ctx); > + > + return 0; > +} > \ No newline at end of file git says it already [...] > +// ffmpeg-x264 param-to-string macros > +#define OPT_STRSTR(x, y)\ > + if (y)\ > + {\ > + x264_argv[x264_argc++] = av_strdup(x); \ > + x264_argv[x264_argc++] = av_strdup(y); \ > + } > +#define OPT_NUMSTR(x, y)\ > + if (y > 0)\ > + {\ > + x264_argv[x264_argc++] = av_strdup(x); \ > + x264_argv[x264_argc] = av_malloc(sizeof(char) * 32); \ > + sprintf(x264_argv[x264_argc++], "%u", y); \ this probably should be a snprintf() for saftey [...] > + // Enumerate input formats > + count = 0, count_ret = 0; > + nvenc_status = nvenc->api.nvEncGetInputFormatCount(nvenc->inst, > NV_ENC_CODEC_H264_GUID, &count); > + if (nvenc_status == NV_ENC_SUCCESS) > + { > + nvenc->buffer_fmts = > (NV_ENC_BUFFER_FORMAT*)malloc(sizeof(NV_ENC_BUFFER_FORMAT)* count); > + if (nvenc->buffer_fmts) > + { > + memset(nvenc->buffer_fmts, 0, sizeof(NV_ENC_BUFFER_FORMAT)* > count); av_mallocz() > + nvenc_status = nvenc->api.nvEncGetInputFormats(nvenc->inst, > NV_ENC_CODEC_H264_GUID, nvenc->buffer_fmts, count, &count_ret); > + if ((nvenc_status != NV_ENC_SUCCESS) || (count_ret == 0)) > + { > + return false; > + } > + nvenc->num_buffer_fmts = count_ret; > + } > + } > + > + return true; > +} > + > +static bool open(nvencoder_t *nvenc) > +{ > + NVENCSTATUS nvenc_status = NV_ENC_ERR_GENERIC; > + nvencodeapicreateinstance_t encodeapicreateinst; > + NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS open_encode_session_params; > + > + // Dynamically load NVENC library > + nvenc->lib = LoadLibrary(NVENCODEAPI_LIB); > + if (!nvenc->lib) > + { > + return false; > + } > + encodeapicreateinst = > + (nvencodeapicreateinstance_t)GetProcAddress(nvenc->lib, > "NvEncodeAPICreateInstance"); > + if (!encodeapicreateinst) > + { > + return false; > + } > + > + // Initialize function table > + nvenc->api.version = NV_ENCODE_API_FUNCTION_LIST_VER; > + nvenc_status = encodeapicreateinst(&nvenc->api); > + if (nvenc_status != NV_ENC_SUCCESS) > + { > + return false; > + } > + > + if (!init_device(nvenc)) > + { > + return false; > + } > + > + // Open encoder session > + memset(&open_encode_session_params, 0, > sizeof(open_encode_session_params)); > + open_encode_session_params.version = > NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER; > + open_encode_session_params.apiVersion = NVENCAPI_VERSION; > + open_encode_session_params.device = nvenc->device.ptr; > + open_encode_session_params.deviceType = nvenc->device.type; > + > + nvenc_status = > nvenc->api.nvEncOpenEncodeSessionEx(&open_encode_session_params, > &nvenc->inst); > + if (nvenc_status != NV_ENC_SUCCESS) > + { > + return false; > + } > + > + // Find encoder capabilities > + if (!query_caps(nvenc)) > + { > + return false; > + } > + > + return true; error codes are AVERROR* in FFmpeg non errors are >= 0 [...] > +static void close(nvencoder_t *nvenc) > +{ > + if (nvenc->buffer_fmts) > + { > + free(nvenc->buffer_fmts); > + nvenc->buffer_fmts = NULL; av_freep() [...] > +static bool map_x264_to_nvenc(NV_ENC_INITIALIZE_PARAMS *nvenc_init_params, > const x264_params_t *x264_params) > +{ > + uint32_t qp_ipdiff = (uint32_t)(6 * log2f(x264_params->ipratio > 0.f ? > x264_params->ipratio : 1.4f)); > + uint32_t qp_pbdiff = (uint32_t)(6 * log2f(x264_params->pbratio > 0.f ? > x264_params->pbratio : 1.3f)); > + > + // Preset > + if (x264_params->profile) > + { > + nvenc_init_params->encodeConfig->profileGUID = > map_profile(x264_params->profile); > + } > + if (x264_params->preset) > + { > + nvenc_init_params->presetGUID = map_preset(x264_params->preset); > + } > + if (x264_params->tune) > + { > + nvenc_init_params->presetGUID = map_tune(x264_params->tune, > &nvenc_init_params->presetGUID); > + } > + > + // Frame > + if ((x264_params->keyint > 0) || (x264_params->min_keyint > 0)) > + { > + if ((x264_params->keyint == 0) || (x264_params->keyint > > x264_params->min_keyint)) > + nvenc_init_params->encodeConfig->gopLength = > x264_params->min_keyint; > + else > + nvenc_init_params->encodeConfig->gopLength = x264_params->keyint; > + fprintf(stdout, "%s=%u\n", "gopLength", > nvenc_init_params->encodeConfig->gopLength); av_log() also see tools/patcheck [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Its not that you shouldnt use gotos but rather that you should write readable code and code with gotos often but not always is less readable
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel