Skip to content

Instantly share code, notes, and snippets.

@JeromeMartinez
Created October 18, 2018 12:08
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/7751c50ba72988c6c53938e830bd784d to your computer and use it in GitHub Desktop.
Save JeromeMartinez/7751c50ba72988c6c53938e830bd784d to your computer and use it in GitHub Desktop.
FFV1-CFA-test_mergedG1G2
libavcodec/ffv1.c | 5 ++++-
libavcodec/ffv1.h | 3 +++
libavcodec/ffv1dec.c | 32 +++++++++++++++++++++++++++++-
libavcodec/ffv1dec_template.c | 36 +++++++++++++++++++++++++---------
libavcodec/ffv1enc.c | 45 ++++++++++++++++++++++++++++++++++++++++++-
libavcodec/ffv1enc_template.c | 35 +++++++++++++++++++++++++--------
6 files changed, 136 insertions(+), 20 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index a14dd2aab2..4e750620bb 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];
@@ -142,7 +145,7 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
fs->slice_x = sxs;
fs->slice_y = sys;
- fs->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
+ fs->sample_buffer = av_malloc_array((fs->width*2 + 6), 3 * MAX_PLANES *
sizeof(*fs->sample_buffer));
fs->sample_buffer32 = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
sizeof(*fs->sample_buffer32));
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..440284e1ca 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..445ca1367f 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -115,15 +115,16 @@ 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;
- sample[x][1] = RENAME(s->sample_buffer) + (x * 2 + 1) * (w + 6) + 3;
+ sample[x][0] = RENAME(s->sample_buffer) + x * 2 * (w*2 + 6) + 3;
+ sample[x][1] = RENAME(s->sample_buffer) + (x * 2 + 1) * (w*2 + 6) + 3;
}
s->run_index = 0;
- memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer)));
+ memset(RENAME(s->sample_buffer), 0, 8 * (w*2 + 6) * sizeof(*RENAME(s->sample_buffer)));
for (y = 0; y < h; y++) {
for (p = 0; p < 3 + transparency; p++) {
@@ -134,20 +135,21 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int
sample[p][1] = temp;
sample[p][1][-1]= sample[p][0][0 ];
- sample[p][0][ w]= sample[p][0][w-1];
+ sample[p][0][ w*(p?1:2)]= sample[p][0][w*(p?1:2)-1];
if (lbd && s->slice_coding_mode == 0)
ret = RENAME(decode_line)(s, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(s, w*(p?1:2), sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
for (x = 0; x < w; x++) {
- int g = sample[0][1][x];
+ int a = sample[0][1][x*2];
int b = sample[1][1][x];
int r = sample[2][1][x];
- int a = sample[3][1][x];
+ int g = sample[0][1][x*2+1];
+ /*
if (s->slice_coding_mode != 1) {
b -= offset;
r -= offset;
@@ -155,8 +157,24 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int
b += g;
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;
+ 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..a953c0237a 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 = 0;
+ 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);
}
@@ -1174,6 +1210,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
maxsize = AV_INPUT_BUFFER_MIN_SIZE + avctx->width*avctx->height*3LL*4;
if (maxsize > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - 32) {
+ printf("*** %lli\n", AV_INPUT_BUFFER_MIN_SIZE);
+ printf("*** %lli\n", avctx->width);
+ printf("*** %lli\n", avctx->height);
+ printf("*** %lli\n", maxsize);
+ printf("*** %lli\n", INT_MAX);
+ printf("*** %lli\n", AV_INPUT_BUFFER_PADDING_SIZE);
av_log(avctx, AV_LOG_WARNING, "Cannot allocate worst case packet size, the encoding could fail\n");
maxsize = INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - 32;
}
@@ -1345,6 +1387,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..05a5dd065d 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -134,20 +134,36 @@ 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;
memset(RENAME(s->sample_buffer), 0, ring_size * MAX_PLANES *
- (w + 6) * sizeof(*RENAME(s->sample_buffer)));
+ (w*2 + 6) * sizeof(*RENAME(s->sample_buffer)));
for (y = 0; y < h; y++) {
for (i = 0; i < ring_size; i++)
for (p = 0; p < MAX_PLANES; p++)
- sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
+ sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w*2+6) + ((h+i-y)%ring_size)*(w*2+6) + 3;
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];
+ break;
+ }
+ }
+ else if (lbd) {
unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y));
b = v & 0xFF;
g = (v >> 8) & 0xFF;
@@ -172,6 +188,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
}
+ /*
if (s->slice_coding_mode != 1) {
b -= g;
r -= g;
@@ -179,20 +196,22 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
b += offset;
r += offset;
}
+ */
- sample[0][0][x] = g;
+ sample[0][0][x*2] = a;
+ sample[0][0][x*2+1] = g;
sample[1][0][x] = b;
sample[2][0][x] = r;
- sample[3][0][x] = a;
+ sample[3][0][x] = 0;
}
for (p = 0; p < 3 + transparency; p++) {
int ret;
sample[p][0][-1] = sample[p][1][0 ];
- sample[p][1][ w] = sample[p][1][w-1];
+ sample[p][1][ w*(p?1:2)] = sample[p][1][w*(p?1:2)-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, 9);
+ ret = RENAME(encode_line)(s, w*(p?1:2), sample[p], (p + 1) / 2, 9);
else
- ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(s, w*(p?1:2), sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment