Skip to content

Commit

Permalink
Added caching!
Browse files Browse the repository at this point in the history
Now caches frames in the background, and when a frame is requested it checks if it has already has been cached(with AMaZE demosaic), and if it has, it gives it, if not it does a simple bilinear debayer for quickness.
  • Loading branch information
ilia3101 authored Jul 15, 2017
1 parent 37ac099 commit e07ce5e
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 59 deletions.
10 changes: 7 additions & 3 deletions platform/cocoa/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ appname = "MLV App"

# List of all objects to link
objects = main.o video_mlv.o debayer.o amaze_demosaic.o raw_processing.o \
main_methods.o useful_methods.o background_thread.o matrix.o camera_matrices.o
main_methods.o useful_methods.o background_thread.o matrix.o \
camera_matrices.o frame_caching.o

# Compiler
CC = gcc # Normal

# Flags for link and objects
mainflags = -O3 -Ofast
linkflags = $(mainflags) -mmacosx-version-min=10.5
cflags := $(mainflags) -c
linkflags = $(mainflags) -mmacosx-version-min=10.6 -lm -pthread
cflags := $(mainflags) -c -mmacosx-version-min=10.6

# Link all objects with main flags
main : $(objects)
Expand All @@ -33,6 +34,9 @@ useful_methods.o : gui_stuff/useful_methods.m
video_mlv.o : ../../src/mlv/video_mlv.c
$(CC) $(cflags) ../../src/mlv/video_mlv.c

frame_caching.o : ../../src/mlv/frame_caching.c
$(CC) $(cflags) ../../src/mlv/frame_caching.c

camera_matrices.o : ../../src/mlv/camera_matrices.c
$(CC) $(cflags) ../../src/mlv/camera_matrices.c

Expand Down
21 changes: 11 additions & 10 deletions platform/cocoa/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
/* To pause frame drawing, above 0 = paused */
int dontDraw;

/* How much cache */
int cacheSizeMB;


int main(int argc, char * argv[])
{
Expand All @@ -62,7 +65,7 @@ int main(int argc, char * argv[])
}


int NSApplicationMain()
int NSApplicationMain(int argc, const char * argv[])
{
/* Don't draw as there's no clip loaded */
dontDraw = 1;
Expand Down Expand Up @@ -96,10 +99,9 @@ int NSApplicationMain()

/* App title with build info */
{
char * host_name = malloc( 1024 );
char host_name[1024];
gethostname(host_name, 1023); /* Computer's name */
[window setTitle: [NSString stringWithFormat: @ APP_NAME " (" __DATE__ " " __TIME__ " @%s)", host_name]];
free(host_name);
[window setTitle: [NSString stringWithFormat: @ APP_NAME " (" __DATE__ " " __TIME__ " @%s)", host_name]];
}


Expand Down Expand Up @@ -180,8 +182,11 @@ int NSApplicationMain()
processingSetExposureStops(processingSettings, 1.2);
/* Link video with processing settings */
setMlvProcessing(videoMLV, processingSettings);
/* Limit frame cache to 38% of RAM size (its fast anyway) */
setMlvRawCacheLimit(videoMLV, (int)(MAC_RAM * 0.38));
/* Limit frame cache to suitable amount of RAM (~33% at 8GB and below ~50% at 16GB and up and up) */
cacheSizeMB = (int)(0.66666f * (float)(MAC_RAM - 4000));
if (MAC_RAM < 7500) cacheSizeMB = MAC_RAM * 0.33;
NSLog(@"Cache size = %iMB, or %i percent of RAM", cacheSizeMB, (int)((float)cacheSizeMB / (float)MAC_RAM * 100));
setMlvRawCacheLimitMegaBytes(videoMLV, cacheSizeMB);

/*
*******************************************************************************
Expand Down Expand Up @@ -227,15 +232,12 @@ int NSApplicationMain()
[previewWindow setAutoresizingMask: (NSViewHeightSizable | NSViewWidthSizable) ];
// [previewWindow setTarget:previewWindow];

/* Don't know what fuckery this is */
rawImageObject = [[NSImage alloc] initWithSize: NSMakeSize(1880,1056) ];
[rawImageObject addRepresentation:rawBitmap];


[previewWindow setImage: rawImageObject];
[[window contentView] addSubview: previewWindow];


/* Slider for moving thourhg the clip */
NSSlider * timelineSlider = [
[NSSlider alloc]
Expand All @@ -250,7 +252,6 @@ int NSApplicationMain()
[[window contentView] addSubview: timelineSlider];



/* Start the FPS timer on background thread */
beginFrameDrawing();

Expand Down
7 changes: 4 additions & 3 deletions platform/cocoa/main_methods.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
/* What frame we r on */
extern int currentFrameIndex;

/* We always set MLV object to this amount of cache */
extern int cacheSizeMB;

/* Button methods */

Expand Down Expand Up @@ -98,7 +100,7 @@ -(void)openMlvDialog
setMlvProcessing(videoMLV, processingSettings);

/* Limit frame cache to 38% of RAM size (its fast anyway) */
setMlvRawCacheLimit(videoMLV, (int)(MAC_RAM * 0.38));
setMlvRawCacheLimitMegaBytes(videoMLV, (uint64_t)(cacheSizeMB));
/* Tell it how many cores we habe so it can be optimal */
setMlvCpuCores(videoMLV, MAC_CORES);

Expand Down Expand Up @@ -147,6 +149,7 @@ -(void)openMlvDialog
} ];
}

/* (unfinished btw) */
-(void)exportBmpSequence
{
/* Create open panel */
Expand Down Expand Up @@ -214,8 +217,6 @@ -(void)saturationSliderMethod
double saturationSliderValue = [self doubleValue] * 2.0;
double saturationValue = pow( saturationSliderValue, log(3.6)/log(2.0) );

NSLog(@"saturationValue: %f", saturationValue);

/* Yea whatever */
processingSetSaturation(processingSettings, saturationValue);

Expand Down
4 changes: 2 additions & 2 deletions src/debayer/debayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ void debayerAmaze(uint16_t * debayerto, float * bayerdata, int width, int height
float ** blue2d = (float **)malloc(height * sizeof(float *));
for (int y = 0; y < height; ++y) blue2d[y] = (float *)(blue1d+(y*width));

/* If threads is 1 just do a normal amaze */
if (threads == 1)
/* If threads is < 2 just do a normal amaze */
if (threads < 2)
{
/* run the Amaze */
demosaic( & (amazeinfo_t) {
Expand Down
125 changes: 125 additions & 0 deletions src/mlv/frame_caching.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* Yeas, we have another background thread */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>

#include "video_mlv.h"
#include "../debayer/debayer.h"

#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))

/* Hmmmm, did anyone need 2 ways of doing this? */

/* What I call MegaBytes is actually MebiBytes! I'm so upset to find that out :( */
void setMlvRawCacheLimitMegaBytes(mlvObject_t * video, uint64_t megaByteLimit)
{
uint64_t frame_size = getMlvWidth(video) * getMlvHeight(video) * sizeof(uint16_t) * 3;
uint64_t bytes_limit = megaByteLimit * (1 << 20);

video->cache_limit_mb = megaByteLimit;
video->cache_limit_bytes = bytes_limit;

/* Protection against zero division, cuz that causes "Floating point exception: 8"...
* ...LOL there's not even a floating point in sight */
if (frame_size != 0 && video->is_active)
{
uint64_t frame_limit = (uint64_t)bytes_limit / (uint64_t)frame_size;
video->cache_limit_frames = frame_limit;

printf("\nEnough memory allowed to cache %i frames (%i MiB)\n\n", (int)frame_limit, (int)megaByteLimit);

/* Begin updating cached frames */
if (!video->is_caching)
{
pthread_create(&video->cache_thread, NULL, (void *)cache_mlv_frames, (void *)video);
}
}
}

void setMlvRawCacheLimitFrames(mlvObject_t * video, uint64_t frameLimit)
{
uint64_t frame_size = getMlvWidth(video) * getMlvHeight(video) * sizeof(uint16_t) * 3;

/* Do only if clip is loaded */
if (frame_size != 0 && video->is_active)
{
uint64_t bytes_limit = frame_size * frameLimit;
uint64_t mbyte_limit = bytes_limit / (1 << 20);

video->cache_limit_bytes = bytes_limit;
video->cache_limit_mb = mbyte_limit;
video->cache_limit_frames = frameLimit;

/* Begin updating cached frames */
if (!video->is_caching)
{
/* cache on bg thread */
pthread_create(&video->cache_thread, NULL, (void *)cache_mlv_frames, (void *)video);
}
}
}

/* Will run in background, caching all frames until it is done,
* and will be called again on a change */
/* TODO: add removing old/un-needed frames ability */
void cache_mlv_frames(mlvObject_t * video)
{
int width = getMlvWidth(video);
int height = getMlvHeight(video);
int threads = getMlvCpuCores(video) / 2 + 1;
int cache_frames = MIN((int)video->cache_limit_frames, (int)video->frames);
size_t frame_size_rgb = width * height * sizeof(uint16_t) * 3;

float * raw_frame = malloc( getMlvWidth(video) * getMlvHeight(video) * sizeof(float) );

video->is_caching = 1;

printf("\nTotal frames %i, Cache limit frames: %i\n\n", (int)video->frames, (int)video->cache_limit_frames);

/* Cache until done */
for (int frame_index = 0; frame_index < cache_frames; ++frame_index)
{
/* Only debayer if frame is not already cached and has not been requested to stop */
if (!video->cached_frames[frame_index] && !video->stop_caching)
{
video->rgb_raw_frames[frame_index] = (uint16_t *)malloc( frame_size_rgb );

/* debayer_type 1, we want to cache AMaZE frames */
get_mlv_raw_frame_debayered(video, frame_index, raw_frame, video->rgb_raw_frames[frame_index], 1);

video->cached_frames[frame_index] = 1;

printf("Debayered frame %i/%i has been cached.\n", frame_index, cache_frames);
}
}

free(raw_frame);

video->is_caching = 0;
}

/* Gets a freshly debayered frame every time ( temp memory should be Width * Height * sizeof(float) ) */
void get_mlv_raw_frame_debayered( mlvObject_t * video,
int frame_index,
float * temp_memory,
uint16_t * output_frame,
int debayer_type ) /* 0=bilinear 1=amaze */
{
int width = getMlvWidth(video);
int height = getMlvHeight(video);

/* Get the raw data in B&W */
getMlvRawFrameFloat(video, frame_index, temp_memory);

if (debayer_type)
{
/* Debayer AMAZEly - using some of the cores (why this fixes the PHAT pink stripes? ...how would i know) */
debayerAmaze(output_frame, temp_memory, width, height, getMlvCpuCores(video) / 2 + 1);
}
else
{
/* Debayer quickly (bilinearly) */
debayerBasic(output_frame, temp_memory, width, height, 1);
}
}
28 changes: 25 additions & 3 deletions src/mlv/mlv_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
/* TO have processingObject_t */
#include "../processing/processing_object.h"

/* I guess this has to happen for pthread_t */
#include "pthread.h"


/* An awkward structure for handling an MLV
* Would be difficult to adapt for .RAW
* ToDo: adapt for .M00 .M01 stuff */
Expand All @@ -15,6 +19,9 @@ typedef struct {
int filenum;
int block_num; /* How many file blocks in MLV file */

/* 0=no, 1=yes, mlv file open */
int is_active;

/* MLV/Lite file(s) */
FILE * file;

Expand Down Expand Up @@ -42,11 +49,26 @@ typedef struct {
processingObject_t * processing;


/* Cache area - "PRIVATE", used by getMlvProcessedFrame and things (or will be...) */
/************************************************************
*** CACHE AREA - used by getMlvProcessedFrame and things ***
************************************************************/

/* 0 = no, 1 = (yes... cache thread is alive right now) */
int is_caching;
pthread_t cache_thread;

int cache_limit_mb; /* How many MB of frames can be cached...
/* Will be set to 1 for cache thread to stop (probably only by freeMlvObject) */
int stop_caching;

/* Basically how much we can cache(can be set by MB or frames or bytes) */
uint64_t cache_limit_bytes;
uint64_t cache_limit_frames;
uint64_t cache_limit_mb; /* How many MB of frames can be cached...
* Debayered frames are cached with 16 bit channel bitdepth (48bpp) */
int cache_start_frame;

/* Not used, cache always starts at frame zero... for now */
uint64_t cache_start_frame;

uint8_t * cached_frames; /* Basically an array with as many elements as frames,
* for each frame: 0(false) = frame is cached, 1 or more(true) = frame is cached */
uint16_t ** rgb_raw_frames; /* Pointers to 16/48bpp debayered RGB frames */
Expand Down
Loading

0 comments on commit e07ce5e

Please sign in to comment.