From 604eb9b973f8797aada147be02379e2834319dfa Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 22 Nov 2011 17:27:02 +0100 Subject: [PATCH] Can dupe extension. --- dynamic.c | 4 ++++ libsnes.hpp | 2 ++ record/ffemu.c | 25 ++++++++++++++++--------- record/ffemu.h | 1 + ssnes.c | 7 ++++++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/dynamic.c b/dynamic.c index ea65640873..29364a9d3d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -311,6 +311,10 @@ static bool environment_cb(unsigned cmd, void *data) g_extern.system.timing_set = true; break; + case SNES_ENVIRONMENT_GET_CAN_DUPE: + *(bool*)data = true; + break; + default: return false; } diff --git a/libsnes.hpp b/libsnes.hpp index c88592ce07..07483e8258 100755 --- a/libsnes.hpp +++ b/libsnes.hpp @@ -73,6 +73,8 @@ extern "C" { #define SNES_ENVIRONMENT_GET_OVERSCAN 3 // bool * -- Boolean value whether or not the implementation should use overscan. #define SNES_ENVIRONMENT_SET_TIMING 4 // const struct snes_system_timing * -- Set exact timings of the system. // Used primarily for video recording. +#define SNES_ENVIRONMENT_GET_CAN_DUPE 5 // bool * -- Boolean value whether or not SSNES supports frame duping, + // passing NULL to video frame callback. struct snes_geometry { diff --git a/record/ffemu.c b/record/ffemu.c index 8e8b0b4a58..a38bf496e9 100644 --- a/record/ffemu.c +++ b/record/ffemu.c @@ -430,12 +430,16 @@ bool ffemu_push_video(ffemu_t *handle, const struct ffemu_video_data *data) // Tightly pack our frame to conserve memory. libsnes tends to use a very large pitch. struct ffemu_video_data attr_data = *data; - attr_data.pitch = attr_data.width * handle->video.pix_size; + + if (attr_data.is_dupe) + attr_data.width = attr_data.height = attr_data.pitch = 0; + else + attr_data.pitch = attr_data.width * handle->video.pix_size; fifo_write(handle->attr_fifo, &attr_data, sizeof(attr_data)); unsigned offset = 0; - for (unsigned y = 0; y < data->height; y++, offset += data->pitch) + for (unsigned y = 0; y < attr_data.height; y++, offset += data->pitch) fifo_write(handle->video_fifo, (const uint8_t*)data->data + offset, attr_data.pitch); slock_unlock(handle->lock); @@ -481,14 +485,17 @@ bool ffemu_push_audio(ffemu_t *handle, const struct ffemu_audio_data *data) static bool ffemu_push_video_thread(ffemu_t *handle, const struct ffemu_video_data *data) { - handle->video.sws_ctx = sws_getCachedContext(handle->video.sws_ctx, data->width, data->height, handle->video.fmt, - handle->params.out_width, handle->params.out_height, handle->video.pix_fmt, SWS_POINT, - NULL, NULL, NULL); + if (!data->is_dupe) + { + handle->video.sws_ctx = sws_getCachedContext(handle->video.sws_ctx, data->width, data->height, handle->video.fmt, + handle->params.out_width, handle->params.out_height, handle->video.pix_fmt, SWS_POINT, + NULL, NULL, NULL); - int linesize = data->pitch; + int linesize = data->pitch; - sws_scale(handle->video.sws_ctx, (const uint8_t* const*)&data->data, &linesize, 0, - data->height, handle->video.conv_frame->data, handle->video.conv_frame->linesize); + sws_scale(handle->video.sws_ctx, (const uint8_t* const*)&data->data, &linesize, 0, + data->height, handle->video.conv_frame->data, handle->video.conv_frame->linesize); + } handle->video.conv_frame->pts = handle->video.frame_cnt; @@ -600,8 +607,8 @@ bool ffemu_finalize(ffemu_t *handle) fifo_read(handle->attr_fifo, &attr_buf, sizeof(attr_buf)); fifo_read(handle->video_fifo, video_buf, attr_buf.height * attr_buf.pitch); attr_buf.data = video_buf; - ffemu_push_video_thread(handle, &attr_buf); + did_work = true; } } while (did_work); diff --git a/record/ffemu.h b/record/ffemu.h index 7afae44ba4..14f699709d 100644 --- a/record/ffemu.h +++ b/record/ffemu.h @@ -44,6 +44,7 @@ struct ffemu_video_data unsigned width; unsigned height; unsigned pitch; + bool is_dupe; }; struct ffemu_audio_data diff --git a/ssnes.c b/ssnes.c index 0fe6f85b8b..e69d2319d4 100644 --- a/ssnes.c +++ b/ssnes.c @@ -161,23 +161,28 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height) if (!g_extern.video_active) return; + bool is_dupe = !data; adjust_crop(&data, &height); // Slightly messy code, // but we really need to do processing before blocking on VSync for best possible scheduling. #ifdef HAVE_FFMPEG - if (g_extern.recording && (!g_extern.filter.active || !g_settings.video.post_filter_record)) + if (g_extern.recording && (!g_extern.filter.active || !g_settings.video.post_filter_record || is_dupe)) { struct ffemu_video_data ffemu_data = { .data = data, .pitch = lines_to_pitch(height), .width = width, .height = height, + .is_dupe = is_dupe }; ffemu_push_video(g_extern.rec, &ffemu_data); } #endif + if (!data) + return; + const char *msg = msg_queue_pull(g_extern.msg_queue); #ifdef HAVE_DYLIB