Remove an extra frame copy that wasn't needed. Only update the stored frame if the previous frame had been displayed. Don't render the same frame again if there's no new frame to update.

This commit is contained in:
Cameron Gutman 2013-11-21 09:55:57 -05:00
parent ab9b7b5164
commit c42d40b8f6
3 changed files with 20 additions and 39 deletions

View File

@ -12,12 +12,10 @@ AVCodec* decoder;
AVCodecContext* decoder_ctx; AVCodecContext* decoder_ctx;
AVFrame* yuv_frame; AVFrame* yuv_frame;
AVFrame* rgb_frame; AVFrame* rgb_frame;
AVFrame* rnd_frame;
AVFrame* dec_frame; AVFrame* dec_frame;
pthread_mutex_t mutex; pthread_mutex_t mutex;
char* rgb_frame_buf; char* rgb_frame_buf;
struct SwsContext* scaler_ctx; struct SwsContext* scaler_ctx;
int picture_new;
#define RENDER_PIX_FMT AV_PIX_FMT_RGBA #define RENDER_PIX_FMT AV_PIX_FMT_RGBA
#define BYTES_PER_PIXEL 4 #define BYTES_PER_PIXEL 4
@ -161,43 +159,31 @@ void nv_avc_destroy(void) {
av_free(rgb_frame_buf); av_free(rgb_frame_buf);
rgb_frame_buf = NULL; rgb_frame_buf = NULL;
} }
if (rnd_frame) {
av_frame_free(&rnd_frame);
rnd_frame = NULL;
}
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
void nv_avc_redraw(JNIEnv *env, jobject surface) { void nv_avc_redraw(JNIEnv *env, jobject surface) {
ANativeWindow* window; ANativeWindow* window;
ANativeWindow_Buffer buffer; ANativeWindow_Buffer buffer;
AVFrame *our_yuv_frame;
int err; int err;
// Free the old decoded frame
if (rnd_frame) {
av_frame_free(&rnd_frame);
}
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
// Check if there's a new frame // Check if there's a new frame
if (picture_new) { if (yuv_frame) {
// Clone the decoder's last frame // We now own the decoder's frame and are
rnd_frame = av_frame_clone(yuv_frame); // responsible for freeing it when we're done
our_yuv_frame = yuv_frame;
yuv_frame = NULL;
// The remaining processing can be done without the mutex // The remaining processing can be done without the mutex
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
if (rnd_frame == NULL) {
__android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC",
"Cloning failed");
return;
}
// Convert the YUV image to RGB // Convert the YUV image to RGB
err = sws_scale(scaler_ctx, err = sws_scale(scaler_ctx,
rnd_frame->data, our_yuv_frame->data,
rnd_frame->linesize, our_yuv_frame->linesize,
0, 0,
decoder_ctx->height, decoder_ctx->height,
rgb_frame->data, rgb_frame->data,
@ -205,14 +191,14 @@ void nv_avc_redraw(JNIEnv *env, jobject surface) {
if (err != decoder_ctx->height) { if (err != decoder_ctx->height) {
__android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC", __android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC",
"Scaling failed"); "Scaling failed");
return; goto free_frame_and_return;
} }
window = ANativeWindow_fromSurface(env, surface); window = ANativeWindow_fromSurface(env, surface);
if (window == NULL) { if (window == NULL) {
__android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC", __android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC",
"Failed to get window from surface"); "Failed to get window from surface");
return; goto free_frame_and_return;
} }
// Lock down a render buffer // Lock down a render buffer
@ -236,10 +222,12 @@ void nv_avc_redraw(JNIEnv *env, jobject surface) {
} }
ANativeWindow_release(window); ANativeWindow_release(window);
free_frame_and_return:
av_frame_free(&our_yuv_frame);
} }
else { else {
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
rnd_frame = NULL;
} }
} }
@ -272,25 +260,18 @@ int nv_avc_decode(unsigned char* indata, int inlen) {
} }
if (got_pic) { if (got_pic) {
// Update the frame if it's not being read pthread_mutex_lock(&mutex);
if (pthread_mutex_trylock(&mutex) == 0) {
// Free the old frame
if (yuv_frame) {
av_frame_free(&yuv_frame);
}
// Only clone this frame if the last frame was taken.
// This saves on extra copies for frames that don't get
// rendered.
if (yuv_frame == NULL) {
// Clone a new frame // Clone a new frame
yuv_frame = av_frame_clone(dec_frame); yuv_frame = av_frame_clone(dec_frame);
if (yuv_frame) {
picture_new = 1;
}
else {
picture_new = 0;
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
}
pkt.size -= err; pkt.size -= err;
pkt.data += err; pkt.data += err;

Binary file not shown.

Binary file not shown.