Add configurable ffmpeg performance options

This commit is contained in:
Cameron Gutman 2013-11-24 21:46:47 -05:00
parent c8b94217cf
commit fb8b6fd7f5
7 changed files with 72 additions and 21 deletions

View File

@ -20,15 +20,24 @@ struct SwsContext* scaler_ctx;
#define RENDER_PIX_FMT AV_PIX_FMT_RGBA
#define BYTES_PER_PIXEL 4
#define VERY_LOW_PERF 0
#define LOW_PERF 1
#define MED_PERF 2
#define HIGH_PERF 3
// Disables the deblocking filter at the cost of image quality
#define DISABLE_LOOP_FILTER 0x1
// Uses the low latency decode flag (disables multithreading)
#define LOW_LATENCY_DECODE 0x2
// Threads process each slice, rather than each frame
#define SLICE_THREADING 0x4
// Uses nonstandard speedup tricks
#define FAST_DECODE 0x8
// Uses bilinear filtering instead of bicubic
#define BILINEAR_FILTERING 0x10
// Uses a faster bilinear filtering with lower image quality
#define FAST_BILINEAR_FILTERING 0x20
// This function must be called before
// any other decoding functions
int nv_avc_init(int width, int height, int perf_lvl) {
int nv_avc_init(int width, int height, int perf_lvl, int thread_count) {
int err;
int filtering;
pthread_mutex_init(&mutex, NULL);
@ -53,24 +62,25 @@ int nv_avc_init(int width, int height, int perf_lvl) {
// Show frames even before a reference frame
decoder_ctx->flags2 |= CODEC_FLAG2_SHOW_ALL;
if (perf_lvl <= LOW_PERF) {
if (perf_lvl & DISABLE_LOOP_FILTER) {
// Skip the loop filter for performance reasons
decoder_ctx->skip_loop_filter = AVDISCARD_ALL;
}
if (perf_lvl <= MED_PERF) {
// Run 2 threads for decoding
decoder_ctx->thread_count = 2;
decoder_ctx->thread_type = FF_THREAD_FRAME;
// Use some tricks to make things faster
decoder_ctx->flags2 |= CODEC_FLAG2_FAST;
}
else {
if (perf_lvl & LOW_LATENCY_DECODE) {
// Use low delay single threaded encoding
decoder_ctx->flags |= CODEC_FLAG_LOW_DELAY;
}
if (perf_lvl & SLICE_THREADING) {
decoder_ctx->thread_type = FF_THREAD_SLICE;
}
else {
decoder_ctx->thread_type = FF_THREAD_FRAME;
}
decoder_ctx->thread_count = thread_count;
decoder_ctx->width = width;
decoder_ctx->height = height;
decoder_ctx->pix_fmt = PIX_FMT_YUV420P;
@ -114,13 +124,23 @@ int nv_avc_init(int width, int height, int perf_lvl) {
return err;
}
if (perf_lvl & FAST_BILINEAR_FILTERING) {
filtering = SWS_FAST_BILINEAR;
}
else if (perf_lvl & BILINEAR_FILTERING) {
filtering = SWS_BILINEAR;
}
else {
filtering = SWS_BICUBIC;
}
scaler_ctx = sws_getContext(decoder_ctx->width,
decoder_ctx->height,
decoder_ctx->pix_fmt,
decoder_ctx->width,
decoder_ctx->height,
RENDER_PIX_FMT,
SWS_BICUBIC,
filtering,
NULL, NULL, NULL);
if (scaler_ctx == NULL) {
__android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC",

View File

@ -1,6 +1,6 @@
#include <jni.h>
int nv_avc_init(int width, int height, int perf_lvl);
int nv_avc_init(int width, int height, int perf_lvl, int thread_count);
void nv_avc_destroy(void);
void nv_avc_redraw(JNIEnv *env, jobject surface);
int nv_avc_decode(unsigned char* indata, int inlen);

View File

@ -7,9 +7,9 @@
// any other decoding functions
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_av_video_AvcDecoder_init(JNIEnv *env, jobject this, jint width,
jint height, jint perflvl)
jint height, jint perflvl, jint threadcount)
{
return nv_avc_init(width, height, perflvl);
return nv_avc_init(width, height, perflvl, threadcount);
}
// This function must be called after

Binary file not shown.

Binary file not shown.

View File

@ -15,7 +15,20 @@ public class AvcDecoder {
System.loadLibrary("nv_avc_dec");
}
public static native int init(int width, int height, int perflvl);
/** Disables the deblocking filter at the cost of image quality */
public static final int DISABLE_LOOP_FILTER = 0x1;
/** Uses the low latency decode flag (disables multithreading) */
public static final int LOW_LATENCY_DECODE = 0x2;
/** Threads process each slice, rather than each frame */
public static final int SLICE_THREADING = 0x4;
/** Uses nonstandard speedup tricks */
public static final int FAST_DECODE = 0x8;
/** Uses bilinear filtering instead of bicubic */
public static final int BILINEAR_FILTERING = 0x10;
/** Uses a faster bilinear filtering with lower image quality */
public static final int FAST_BILINEAR_FILTERING = 0x20;
public static native int init(int width, int height, int perflvl, int threadcount);
public static native void destroy();
public static native void redraw(Surface surface);
public static native int decode(byte[] indata, int inoff, int inlen);

View File

@ -73,7 +73,25 @@ public class CpuDecoderRenderer implements DecoderRenderer {
this.renderTarget = renderTarget;
this.perfLevel = findOptimalPerformanceLevel();
int err = AvcDecoder.init(width, height, perfLevel);
int flags = 0;
switch (perfLevel) {
case LOW_PERF:
flags = AvcDecoder.DISABLE_LOOP_FILTER |
AvcDecoder.FAST_BILINEAR_FILTERING |
AvcDecoder.FAST_DECODE |
AvcDecoder.LOW_LATENCY_DECODE;
break;
case MED_PERF:
flags = AvcDecoder.LOW_LATENCY_DECODE |
AvcDecoder.FAST_DECODE |
AvcDecoder.BILINEAR_FILTERING;
break;
case HIGH_PERF:
flags = AvcDecoder.LOW_LATENCY_DECODE;
break;
}
int err = AvcDecoder.init(width, height, flags, 2);
if (err != 0) {
throw new IllegalStateException("AVC decoder initialization failure: "+err);
}