diff options
author | Peter Schlaile <peter@schlaile.de> | 2008-06-03 01:35:57 +0400 |
---|---|---|
committer | Peter Schlaile <peter@schlaile.de> | 2008-06-03 01:35:57 +0400 |
commit | ca8aa8c901934dc0e3eb1b65618d40bfb65f9111 (patch) | |
tree | 72e3ea5d2f5e224a683e064d34f6ee47eff90c59 /extern/libredcode/codec.c | |
parent | 8a5f36219214b4a5b8348b8e200ef5aac2297963 (diff) |
== RED one (redcode) ==
This adds redcode (the file format of RED one, R3D) support to blender.
Seems to work fine with the footage I found on the web, but keep in
mind, that because of the unoptimized nature of libopenjpeg, frame
decoding isn't that fast.
It is also a rather challenging task, to make 4k-float-footage realtime :)
Diffstat (limited to 'extern/libredcode/codec.c')
-rw-r--r-- | extern/libredcode/codec.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/extern/libredcode/codec.c b/extern/libredcode/codec.c new file mode 100644 index 00000000000..e0b79119e80 --- /dev/null +++ b/extern/libredcode/codec.c @@ -0,0 +1,141 @@ +#include "codec.h" +#include "format.h" +#include "debayer.h" + +#include <openjpeg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[R3D ERR] %s", msg); +} + +static void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[R3D WARN] %s", msg); +} + +static void info_callback(const char *msg, void *client_data) { + (void)client_data; + fprintf(stdout, "[R3D INFO] %s", msg); +} + +#define J2K_CFMT 0 +#define JP2_CFMT 1 +#define JPT_CFMT 2 + +struct redcode_frame_raw * redcode_decode_video_raw( + struct redcode_frame * frame, int scale) +{ + struct redcode_frame_raw * rv = NULL; + opj_dparameters_t parameters; /* decompression parameters */ + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ + opj_cio_t *cio = NULL; + + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + opj_set_default_decoder_parameters(¶meters); + + parameters.decod_format = JP2_CFMT; + + if (scale == 2) { + parameters.cp_reduce = 1; + } else if (scale == 4) { + parameters.cp_reduce = 2; + } else if (scale == 8) { + parameters.cp_reduce = 3; + } + + /* JPEG 2000 compressed image data */ + + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_JP2); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); + + /* setup the decoder decoding parameters using the current image + and user parameters */ + opj_setup_decoder(dinfo, ¶meters); + + /* open a byte stream */ + cio = opj_cio_open((opj_common_ptr)dinfo, + frame->data + frame->offset, frame->length); + + image = opj_decode(dinfo, cio); + + if(!image) { + fprintf(stderr, + "ERROR -> j2k_to_image: failed to decode image!\n"); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); + return 0; + } + + /* close the byte stream */ + opj_cio_close(cio); + + /* free remaining structures */ + if(dinfo) { + opj_destroy_decompress(dinfo); + } + + if((image->numcomps * image->x1 * image->y1) == 0) { + opj_image_destroy(image); + return 0; + } + + rv = (struct redcode_frame_raw *) calloc( + 1, sizeof(struct redcode_frame_raw)); + + rv->data = image; + rv->width = image->comps[0].w; + rv->height = image->comps[0].h; + + return rv; +} + +int redcode_decode_video_float(struct redcode_frame_raw * frame, + float * out, int scale) +{ + int* planes[4]; + int i; + opj_image_t *image = (opj_image_t*) frame->data; + + if (image->numcomps != 4) { + fprintf(stderr, "R3D: need 4 planes, but got: %d\n", + image->numcomps); + return 0; + } + + for (i = 0; i < 4; i++) { + planes[i] = image->comps[i].data; + } + + if (scale == 1) { + redcode_ycbcr2rgb_fullscale( + planes, frame->width, frame->height, out); + } else if (scale == 2) { + redcode_ycbcr2rgb_halfscale( + planes, frame->width, frame->height, out); + } else if (scale == 4) { + redcode_ycbcr2rgb_quarterscale( + planes, frame->width, frame->height, out); + } + + opj_image_destroy(image); + + free(frame); + + return 1; +} + + + |