Skip to content

Instantly share code, notes, and snippets.

@JeromeMartinez
Last active October 8, 2018 09:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JeromeMartinez/d75739988eb698a6a232e25ca6de7d8d to your computer and use it in GitHub Desktop.
Save JeromeMartinez/d75739988eb698a6a232e25ca6de7d8d to your computer and use it in GitHub Desktop.
FFV1-CFA
libavcodec/ffv1.c | 3 +++
libavcodec/ffv1.h | 3 +++
libavcodec/ffv1dec.c | 32 +++++++++++++++++++++++++++++++-
libavcodec/ffv1dec_template.c | 18 +++++++++++++++++-
libavcodec/ffv1enc.c | 39 ++++++++++++++++++++++++++++++++++++++-
libavcodec/ffv1enc_template.c | 18 +++++++++++++++++-
6 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index a14dd2aab2..7286f821d9 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -70,6 +70,9 @@ av_cold int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs)
fs->plane_count = f->plane_count;
fs->transparency = f->transparency;
+ fs->bayer_code = f->bayer_code;
+ fs->width_scale = f->width_scale;
+ fs->height_scale = f->height_scale;
for (j = 0; j < f->plane_count; j++) {
PlaneContext *const p = &fs->plane[j];
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 653138b070..a40201995b 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -93,6 +93,9 @@ typedef struct FFV1Context {
int flags;
int picture_number;
int key_frame;
+ int bayer_code;
+ int width_scale;
+ int height_scale;
ThreadFrame picture, last_picture;
struct FFV1Context *fsrc;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 261e0cf70c..a936b10beb 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -340,7 +340,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame32(fs, planes, width, height, p->linesize);
+ decode_rgb_frame32(fs, planes, width/f->width_scale, height/f->height_scale, p->linesize);
} else {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
@@ -443,6 +443,13 @@ static int read_extra_header(FFV1Context *f)
}
f->colorspace = get_symbol(c, state, 0); //YUV cs type
+ if (f->colorspace == 2) {
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ f->bayer_code = 1;
+ }
f->avctx->bits_per_raw_sample = get_symbol(c, state, 0);
f->chroma_planes = get_rac(c, state);
f->chroma_h_shift = get_symbol(c, state, 0);
@@ -557,6 +564,13 @@ static int read_header(FFV1Context *f)
}
colorspace = get_symbol(c, state, 0); //YUV cs type
+ if (colorspace == 2) {
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ get_symbol(c, state, 0);
+ f->bayer_code = 1;
+ }
bits_per_raw_sample = f->version > 0 ? get_symbol(c, state, 0) : f->avctx->bits_per_raw_sample;
chroma_planes = get_rac(c, state);
chroma_h_shift = get_symbol(c, state, 0);
@@ -722,6 +736,19 @@ static int read_header(FFV1Context *f)
f->avctx->pix_fmt = AV_PIX_FMT_GBRAP16;
f->use32bit = 1;
}
+ } else if (f->colorspace == 2) {
+ if (f->chroma_h_shift || f->chroma_v_shift) {
+ av_log(f->avctx, AV_LOG_ERROR,
+ "chroma subsampling not supported in this colorspace\n");
+ return AVERROR(ENOSYS);
+ }
+ if ( f->avctx->bits_per_raw_sample == 16 && f->transparency) {
+ f->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE;
+ f->bayer_code = 1;
+ f->width_scale = 2;
+ f->height_scale = 2;
+ f->use32bit = 1;
+ }
} else {
av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
return AVERROR(ENOSYS);
@@ -1021,6 +1048,9 @@ static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsr
fsdst->plane_count = fsrc->plane_count;
fsdst->ac = fsrc->ac;
fsdst->colorspace = fsrc->colorspace;
+ fsdst->bayer_code = fsrc->bayer_code;
+ fsdst->width_scale = fsrc->width_scale;
+ fsdst->height_scale = fsrc->height_scale;
fsdst->ec = fsrc->ec;
fsdst->intra = fsrc->intra;
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index fecdbd0025..b304dcfd30 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -115,6 +115,7 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int
int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
int offset = 1 << bits;
int transparency = s->transparency;
+ int bayer_code = s->bayer_code;
for (x = 0; x < 4; x++) {
sample[x][0] = RENAME(s->sample_buffer) + x * 2 * (w + 6) + 3;
@@ -156,7 +157,22 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int
r += g;
}
- if (lbd)
+ if (bayer_code)
+ {
+ uint16_t *bayer[2];
+ bayer[0] = ((uint16_t*)(src[0] + (x*2 + stride[0]*y) * 2));
+ bayer[1] = ((uint16_t*)((uint8_t*)bayer[0] + stride[0]));
+ switch (bayer_code)
+ {
+ case 1 :
+ bayer[0][0] = r;
+ bayer[0][1] = g;
+ bayer[1][1] = b;
+ bayer[1][0] = a + g - offset;
+ break;
+ }
+ }
+ else if (lbd)
*((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + ((unsigned)g<<8) + ((unsigned)r<<16) + ((unsigned)a<<24);
else if (sizeof(TYPE) == 4 || transparency) {
*((uint16_t*)(src[0] + x*2 + stride[0]*y)) = g;
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index f5eb0feb4e..90bb2e707b 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -351,6 +351,17 @@ static void write_header(FFV1Context *f)
f->state_transition[i] - c->one_state[i], 1);
}
put_symbol(c, state, f->colorspace, 0); //YUV cs type
+ if (f->colorspace == 2) {
+ switch (f->bayer_code)
+ {
+ case 1: // RGGB
+ put_symbol(c, state, 0, 0); // R
+ put_symbol(c, state, 1, 0); // G
+ put_symbol(c, state, 1, 0); // G
+ put_symbol(c, state, 2, 0); // B
+ break;
+ }
+ }
if (f->version > 0)
put_symbol(c, state, f->bits_per_raw_sample, 0);
put_rac(c, state, f->chroma_planes);
@@ -415,6 +426,17 @@ static int write_extradata(FFV1Context *f)
put_symbol(c, state, f->state_transition[i] - c->one_state[i], 1);
put_symbol(c, state, f->colorspace, 0); // YUV cs type
+ if (f->colorspace == 2) {
+ switch (f->bayer_code)
+ {
+ case 1: // RGGB
+ put_symbol(c, state, 0, 0); // R
+ put_symbol(c, state, 1, 0); // G
+ put_symbol(c, state, 1, 0); // G
+ put_symbol(c, state, 2, 0); // B
+ break;
+ }
+ }
put_symbol(c, state, f->bits_per_raw_sample, 0);
put_rac(c, state, f->chroma_planes);
put_symbol(c, state, f->chroma_h_shift, 0);
@@ -561,6 +583,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
s->ac = AC_RANGE_DEFAULT_TAB;
s->plane_count = 3;
+ s->bayer_code = 0;
+ s->width_scale = 1;
+ s->height_scale = 1;
switch(avctx->pix_fmt) {
case AV_PIX_FMT_GRAY9:
case AV_PIX_FMT_YUV444P9:
@@ -684,6 +709,17 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
s->version = FFMAX(s->version, 1);
break;
+ case AV_PIX_FMT_BAYER_RGGB16LE:
+ s->bits_per_raw_sample = 16;
+ s->transparency = 1;
+ s->colorspace = 2;
+ s->bayer_code = 1;
+ s->width_scale = 2;
+ s->height_scale = 2;
+ s->chroma_planes = 1;
+ s->use32bit = 1;
+ s->version = FFMAX(s->version, 1);
+ break;
default:
av_log(avctx, AV_LOG_ERROR, "format not supported\n");
return AVERROR(ENOSYS);
@@ -1091,7 +1127,7 @@ retry:
ret = encode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
ret |= encode_plane(fs, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
- ret = encode_rgb_frame32(fs, planes, width, height, p->linesize);
+ ret = encode_rgb_frame32(fs, planes, width/f->width_scale, height/f->height_scale, p->linesize);
} else {
ret = encode_rgb_frame(fs, planes, width, height, p->linesize);
}
@@ -1345,6 +1381,7 @@ AVCodec ff_ffv1_encoder = {
AV_PIX_FMT_GRAY9,
AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14,
AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12,
+ AV_PIX_FMT_BAYER_RGGB16LE,
AV_PIX_FMT_NONE
},
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index bc0add5ed7..5009f0f8d0 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -134,6 +134,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
int offset = 1 << bits;
int transparency = s->transparency;
int packed_size = (3 + transparency)*2;
+ int bayer_code = s->bayer_code;
s->run_index = 0;
@@ -147,7 +148,22 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
for (x = 0; x < w; x++) {
int b, g, r, av_uninit(a);
- if (lbd) {
+ if (bayer_code)
+ {
+ uint16_t *bayer[2];
+ bayer[0] = ((uint16_t*)(src[0] + (x*2 + stride[0]*y) *2));
+ bayer[1] = ((uint16_t*)((uint8_t*)bayer[0] + stride[0]));
+ switch (bayer_code)
+ {
+ case 1 :
+ r = bayer[0][0];
+ g = bayer[0][1];
+ b = bayer[1][1];
+ a = bayer[1][0] - g + offset;
+ break;
+ }
+ }
+ else if (lbd) {
unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y));
b = v & 0xFF;
g = (v >> 8) & 0xFF;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment