#include "libavutil/crc.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
+#include "libavutil/timer.h"
#ifdef __INTEL_COMPILER
#undef av_flatten
}
}
-static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
+static void encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]){
int x, y, p, i;
const int ring_size= s->avctx->context_model ? 3 : 2;
int16_t *sample[4][3];
+ int lbd= s->avctx->bits_per_raw_sample <= 8;
+ int bits= s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
+ int offset= 1 << bits;
s->run_index=0;
memset(s->sample_buffer, 0, ring_size*4*(w+6)*sizeof(*s->sample_buffer));
sample[p][i]= s->sample_buffer + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
for(x=0; x<w; x++){
- unsigned v= src[x + stride*y];
- int b= v&0xFF;
- int g= (v>>8)&0xFF;
- int r= (v>>16)&0xFF;
- int a= v>>24;
+ int b,g,r,av_uninit(a);
+ if(lbd){
+ unsigned v= *((uint32_t*)(src[0] + x*4 + stride[0]*y));
+ b= v&0xFF;
+ g= (v>>8)&0xFF;
+ r= (v>>16)&0xFF;
+ a= v>>24;
+ }else{
+ b= *((uint16_t*)(src[0] + x*2 + stride[0]*y));
+ g= *((uint16_t*)(src[1] + x*2 + stride[1]*y));
+ r= *((uint16_t*)(src[2] + x*2 + stride[2]*y));
+ }
b -= g;
r -= g;
g += (b + r)>>2;
- b += 0x100;
- r += 0x100;
+ b += offset;
+ r += offset;
// assert(g>=0 && b>=0 && r>=0);
// assert(g<256 && b<512 && r<512);
for(p=0; p<3 + s->transparency; p++){
sample[p][0][-1]= sample[p][1][0 ];
sample[p][1][ w]= sample[p][1][w-1];
- encode_line(s, w, sample[p], (p+1)/2, 9);
+ if (lbd)
+ encode_line(s, w, sample[p], (p+1)/2, 9);
+ else
+ encode_line(s, w, sample[p], (p+1)/2, bits+1);
}
}
}
ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
put_symbol(c, state, f->version, 0);
- if(f->version > 2)
+ if(f->version > 2) {
+ if(f->version == 3)
+ f->minor_version = 2;
put_symbol(c, state, f->minor_version, 0);
+ }
put_symbol(c, state, f->ac, 0);
if(f->ac>1){
for(i=1; i<256; i++){
case PIX_FMT_0RGB32:
s->colorspace= 1;
break;
+ case PIX_FMT_GBRP9:
+ if (!avctx->bits_per_raw_sample)
+ s->bits_per_raw_sample = 9;
+ case PIX_FMT_GBRP10:
+ if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
+ s->bits_per_raw_sample = 10;
+ case PIX_FMT_GBRP12:
+ if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
+ s->bits_per_raw_sample = 12;
+ case PIX_FMT_GBRP14:
+ if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
+ s->bits_per_raw_sample = 14;
+ else if (!s->bits_per_raw_sample)
+ s->bits_per_raw_sample = avctx->bits_per_raw_sample;
+ s->colorspace= 1;
+ s->chroma_planes= 1;
+ s->version= FFMAX(s->version, 1);
+ break;
default:
av_log(avctx, AV_LOG_ERROR, "format not supported\n");
return AVERROR_INVALIDDATA;
encode_slice_header(f, fs);
}
if(!fs->ac){
+ if(f->version > 2)
+ put_rac(&fs->c, (int[]){129}, 0);
fs->ac_byte_count = f->version > 2 || (!x&&!y) ? ff_rac_terminate(&fs->c) : 0;
init_put_bits(&fs->pb, fs->c.bytestream_start + fs->ac_byte_count, fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count);
}
if (fs->transparency)
encode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2);
}else{
- encode_rgb_frame(fs, (uint32_t*)(p->data[0]) + ps*x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
+ uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0],
+ p->data[1] + ps*x + y*p->linesize[1],
+ p->data[2] + ps*x + y*p->linesize[2]};
+ encode_rgb_frame(fs, planes, width, height, p->linesize);
}
emms_c();
int bytes;
if(fs->ac){
- uint8_t state=128;
+ uint8_t state=129;
put_rac(&fs->c, &state, 0);
bytes= ff_rac_terminate(&fs->c);
}else{
}
}
-static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
+static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]){
int x, y, p;
int16_t *sample[4][2];
+ int lbd= s->avctx->bits_per_raw_sample <= 8;
+ int bits= s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
+ int offset= 1 << bits;
for(x=0; x<4; x++){
sample[x][0] = s->sample_buffer + x*2 *(w+6) + 3;
sample[x][1] = s->sample_buffer + (x*2+1)*(w+6) + 3;
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
- decode_line(s, w, sample[p], (p+1)/2, 9);
+ if (lbd)
+ decode_line(s, w, sample[p], (p+1)/2, 9);
+ else
+ decode_line(s, w, sample[p], (p+1)/2, bits+1);
}
for(x=0; x<w; x++){
int g= sample[0][1][x];
// assert(g>=0 && b>=0 && r>=0);
// assert(g<256 && b<512 && r<512);
- b -= 0x100;
- r -= 0x100;
+ b -= offset;
+ r -= offset;
g -= (b + r)>>2;
b += g;
r += g;
- src[x + stride*y]= b + (g<<8) + (r<<16) + (a<<24);
+ if(lbd)
+ *((uint32_t*)(src[0] + x*4 + stride[0]*y))= b + (g<<8) + (r<<16) + (a<<24);
+ else{
+ *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b;
+ *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g;
+ *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r;
+ }
}
}
}
y= fs->slice_y;
if(!fs->ac){
+ if (f->version > 2)
+ get_rac(&fs->c, (int[]){129});
fs->ac_byte_count = f->version > 2 || (!x&&!y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0;
init_get_bits(&fs->gb,
fs->c.bytestream_start + fs->ac_byte_count,
if (fs->transparency)
decode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2);
}else{
- decode_rgb_frame(fs, (uint32_t*)p->data[0] + ps*x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
+ uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0],
+ p->data[1] + ps*x + y*p->linesize[1],
+ p->data[2] + ps*x + y*p->linesize[2]};
+ decode_rgb_frame(fs, planes, width, height, p->linesize);
}
if(fs->ac && f->version > 2) {
- int v = fs->c.bytestream_end - fs->c.bytestream - 3 - 5*f->ec;
- if(v != -1 && v!= 0) {
+ int v;
+ get_rac(&fs->c, (int[]){129});
+ v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5*f->ec;
+ if(v) {
av_log(f->avctx, AV_LOG_ERROR, "bytestream end mismatching by %d\n", v);
fs->slice_damaged = 1;
}
static int read_header(FFV1Context *f){
uint8_t state[CONTEXT_SIZE];
- int i, j, context_count;
+ int i, j, context_count = -1; //-1 to avoid warning
RangeCoder * const c= &f->slice_context[0]->c;
memset(state, 128, sizeof(state));
av_log(f->avctx, AV_LOG_ERROR, "chroma subsampling not supported in this colorspace\n");
return -1;
}
+ if(f->avctx->bits_per_raw_sample==9)
+ f->avctx->pix_fmt= PIX_FMT_GBRP9;
+ else if(f->avctx->bits_per_raw_sample==10)
+ f->avctx->pix_fmt= PIX_FMT_GBRP10;
+ else if(f->avctx->bits_per_raw_sample==12)
+ f->avctx->pix_fmt= PIX_FMT_GBRP12;
+ else if(f->avctx->bits_per_raw_sample==14)
+ f->avctx->pix_fmt= PIX_FMT_GBRP14;
+ else
if(f->transparency) f->avctx->pix_fmt= PIX_FMT_RGB32;
else f->avctx->pix_fmt= PIX_FMT_0RGB32;
}else{
}
if(f->version <= 2){
+ av_assert0(context_count>=0);
if(p->context_count < context_count){
av_freep(&p->state);
av_freep(&p->vlc_state);
#define OFFSET(x) offsetof(FFV1Context, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
- { "slicecrc", "Protect slices with CRCs", OFFSET(ec), AV_OPT_TYPE_INT, {-1}, -1, 1, VE},
+ { "slicecrc", "Protect slices with CRCs", OFFSET(ec), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE},
{NULL}
};
PIX_FMT_YUV410P, PIX_FMT_0RGB32, PIX_FMT_RGB32, PIX_FMT_YUV420P16,
PIX_FMT_YUV422P16, PIX_FMT_YUV444P16, PIX_FMT_YUV444P9, PIX_FMT_YUV422P9,
PIX_FMT_YUV420P9, PIX_FMT_YUV420P10, PIX_FMT_YUV422P10, PIX_FMT_YUV444P10,
- PIX_FMT_GRAY16, PIX_FMT_GRAY8,
+ PIX_FMT_GRAY16, PIX_FMT_GRAY8, PIX_FMT_GBRP9, PIX_FMT_GBRP10,
+ PIX_FMT_GBRP12, PIX_FMT_GBRP14,
PIX_FMT_NONE
},
.long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),