Skip to content

Commit

Permalink
Add nvenc support
Browse files Browse the repository at this point in the history
  • Loading branch information
agathah committed Oct 24, 2014
1 parent 57ab775 commit 3b5a7bd
Show file tree
Hide file tree
Showing 14 changed files with 1,984 additions and 4 deletions.
9 changes: 9 additions & 0 deletions configure
Expand Up @@ -221,6 +221,7 @@ External library support:
--enable-libmp3lame enable MP3 encoding via libmp3lame [no]
--enable-libnut enable NUT (de)muxing via libnut,
native (de)muxer exists [no]
--enable-libnvenc enable NVIDIA NVENC encoder [no]
--enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]
--enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]
--enable-libopencv enable video filtering via libopencv [no]
Expand Down Expand Up @@ -1352,6 +1353,7 @@ EXTERNAL_LIBRARY_LIST="
libmodplug
libmp3lame
libnut
libnvenc
libopencore_amrnb
libopencore_amrwb
libopencv
Expand Down Expand Up @@ -2338,6 +2340,7 @@ libilbc_encoder_deps="libilbc"
libmodplug_demuxer_deps="libmodplug"
libmp3lame_encoder_deps="libmp3lame"
libmp3lame_encoder_select="audio_frame_queue"
libnvenc_encoder_deps="libnvenc"
libopencore_amrnb_decoder_deps="libopencore_amrnb"
libopencore_amrnb_encoder_deps="libopencore_amrnb"
libopencore_amrnb_encoder_select="audio_frame_queue"
Expand Down Expand Up @@ -4328,6 +4331,7 @@ die_license_disabled nonfree libaacplus
die_license_disabled nonfree libfaac
enabled gpl && die_license_disabled_gpl nonfree libfdk_aac
enabled gpl && die_license_disabled_gpl nonfree openssl
enabled gpl && die_license_disabled_gpl nonfree libnvenc

die_license_disabled version3 libopencore_amrnb
die_license_disabled version3 libopencore_amrwb
Expand Down Expand Up @@ -4839,6 +4843,11 @@ enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -li
enabled libmodplug && require_pkg_config libmodplug libmodplug/modplug.h ModPlug_Load
enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
enabled libnut && require libnut libnut.h nut_demuxer_init -lnut
enabled libnvenc && { { check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h header not found"; } &&
{ check_header cuda.h || die "ERROR: cuda.h header not found"; } &&
{ { check_lib2 "windows.h" LoadLibrary; } ||
{ check_lib2 "dlfcn.h" dlopen -ldl; } ||
die "ERROR: LoadLibrary/dlopen not found for avisynth"; } }
enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
enabled libopencv && require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader
Expand Down
1 change: 1 addition & 0 deletions doc/examples/Makefile
Expand Up @@ -19,6 +19,7 @@ EXAMPLES= avio_reading \
filtering_audio \
metadata \
muxing \
libnvenc \
remuxing \
resampling_audio \
scaling_video \
Expand Down
177 changes: 177 additions & 0 deletions doc/examples/libnvenc.c
@@ -0,0 +1,177 @@
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif

#if _WIN32
#define __STDC_CONSTANT_MACROS
#endif

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>

#include <stdio.h>
#include <assert.h>
#include <string.h>

int main(int argc, char* argv[])
{
char* inputfile = NULL;
char* preset = "default";
bool zerolatency = false;

for(int i = 1; i < argc; i++) {
if(strcmp(argv[i], "-input") == 0) {
inputfile = argv[++i];
}
else if(strcmp(argv[i], "-preset") == 0) {
preset = argv[++i];
}
else if(strcmp(argv[i], "-zerolatency") == 0) {
zerolatency = true;
}
}

if(inputfile == NULL) {
printf("Usage: libnvenc_sample -input your.input -preset [default]/slow/fast\n");
return 0;
}

//ffmpeg decoder
av_register_all();
//init decode context
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *dec_ctx = NULL;

if(avformat_open_input(&fmt_ctx, inputfile, NULL, NULL) < 0)
{
printf("can't open the file %s\n", inputfile);
return -1;
}

if(avformat_find_stream_info(fmt_ctx, NULL)<0)
{
printf("can't find suitable codec parameters\n");
return -1;
}

AVStream *vst_dec;
AVCodec *dec = NULL;
int ret;
int video_stream_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (video_stream_idx < 0) {
printf("Could not find video stream in input file!\n");
return -1;
}
else {
vst_dec = fmt_ctx->streams[video_stream_idx];

dec_ctx = vst_dec->codec;
dec = avcodec_find_decoder(dec_ctx->codec_id);

if (!dec) {
fprintf(stderr, "Failed to find %s codec\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}

if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
fprintf(stderr, "Failed to open %s codec\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}
}

// encode context
AVFormatContext* oc;
const char* filename = "out.mp4";
avformat_alloc_output_context2(&oc, NULL, NULL, filename);
if (!oc) {
printf("FFMPEG: avformat_alloc_context error\n");
return -1;
}

if ((ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) {
fprintf(stderr, "Could not open '%s'\n", filename);
return -1;
}

AVCodec* enc = avcodec_find_encoder_by_name("libnvenc");
if(!enc) {
printf("Could not find libnvenc\n");
printf("Please run ./configure --enable-libnvenc and make ffmpeg again\n");
return -1;
}
AVStream* vst_enc = avformat_new_stream(oc, enc);
if (!vst_enc) {
printf("FFMPEG: Could not alloc video stream");
return -1;
}

AVCodecContext* enc_ctx = vst_enc->codec;

double bitrate = (double)5000000 * (dec_ctx->width * dec_ctx->height) / (1280*720);
enc_ctx->codec_id = enc->id;
enc_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
enc_ctx->width = dec_ctx->width;
enc_ctx->height = dec_ctx->height;
enc_ctx->pix_fmt = dec_ctx->pix_fmt;
enc_ctx->time_base.num = dec_ctx->time_base.num;
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;
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;
}
11 changes: 11 additions & 0 deletions ffmpeg.c.rej
@@ -0,0 +1,11 @@
--- ffmpeg.c
+++ ffmpeg.c
@@ -2644,7 +2644,7 @@
ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option
av_mul_q(ost->frame_aspect_ratio, (AVRational){ codec->height, codec->width }) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
- if (!strncmp(ost->enc->name, "libx264", 7) &&
+ if ((!strncmp(ost->enc->name, "libx264", 7) || !strncmp(ost->enc->name, "libnvenc", 8)) &&
codec->pix_fmt == AV_PIX_FMT_NONE &&
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
av_log(NULL, AV_LOG_WARNING,
1 change: 1 addition & 0 deletions libavcodec/Makefile
Expand Up @@ -730,6 +730,7 @@ OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsmenc.o
OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o
OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o
OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o
OBJS-$(CONFIG_LIBNVENC_ENCODER) += libnvenc.o nvencoder.o nvencoder_utils.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o
Expand Down
1 change: 1 addition & 0 deletions libavcodec/allcodecs.c
Expand Up @@ -506,6 +506,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCDEC (LIBILBC, libilbc);
REGISTER_ENCODER(LIBMP3LAME, libmp3lame);
REGISTER_ENCODER(LIBNVENC, libnvenc);
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb);
REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb);
REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg);
Expand Down

0 comments on commit 3b5a7bd

Please sign in to comment.