Skip to content

Commit 15acfa2

Browse files
lippitmichaelni
authored andcommitted
ffv1: more than 8 bit per RGB channel
Add support for GBRP9, GBRP10, GBRP12 and GBRP14 pix formats in ffv1. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
1 parent 2b3b52d commit 15acfa2

File tree

1 file changed

+77
-17
lines changed

1 file changed

+77
-17
lines changed

libavcodec/ffv1.c

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "libavutil/crc.h"
3939
#include "libavutil/opt.h"
4040
#include "libavutil/imgutils.h"
41+
#include "libavutil/timer.h"
4142

4243
#ifdef __INTEL_COMPILER
4344
#undef av_flatten
@@ -579,10 +580,13 @@ static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride,
579580
}
580581
}
581582

582-
static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
583+
static void encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]){
583584
int x, y, p, i;
584585
const int ring_size= s->avctx->context_model ? 3 : 2;
585586
int16_t *sample[4][3];
587+
int lbd= s->avctx->bits_per_raw_sample <= 8;
588+
int bits= s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
589+
int offset= 1 << bits;
586590
s->run_index=0;
587591

588592
memset(s->sample_buffer, 0, ring_size*4*(w+6)*sizeof(*s->sample_buffer));
@@ -593,17 +597,24 @@ static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
593597
sample[p][i]= s->sample_buffer + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
594598

595599
for(x=0; x<w; x++){
596-
unsigned v= src[x + stride*y];
597-
int b= v&0xFF;
598-
int g= (v>>8)&0xFF;
599-
int r= (v>>16)&0xFF;
600-
int a= v>>24;
600+
int b,g,r,a;
601+
if(lbd){
602+
unsigned v= *((uint32_t*)(src[0] + x*4 + stride[0]*y));
603+
b= v&0xFF;
604+
g= (v>>8)&0xFF;
605+
r= (v>>16)&0xFF;
606+
a= v>>24;
607+
}else{
608+
b= *((uint16_t*)(src[0] + x*2 + stride[0]*y));
609+
g= *((uint16_t*)(src[1] + x*2 + stride[1]*y));
610+
r= *((uint16_t*)(src[2] + x*2 + stride[2]*y));
611+
}
601612

602613
b -= g;
603614
r -= g;
604615
g += (b + r)>>2;
605-
b += 0x100;
606-
r += 0x100;
616+
b += offset;
617+
r += offset;
607618

608619
// assert(g>=0 && b>=0 && r>=0);
609620
// assert(g<256 && b<512 && r<512);
@@ -615,7 +626,10 @@ static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
615626
for(p=0; p<3 + s->transparency; p++){
616627
sample[p][0][-1]= sample[p][1][0 ];
617628
sample[p][1][ w]= sample[p][1][w-1];
618-
encode_line(s, w, sample[p], (p+1)/2, 9);
629+
if (lbd)
630+
encode_line(s, w, sample[p], (p+1)/2, 9);
631+
else
632+
encode_line(s, w, sample[p], (p+1)/2, bits+1);
619633
}
620634
}
621635
}
@@ -980,6 +994,24 @@ static av_cold int encode_init(AVCodecContext *avctx)
980994
case PIX_FMT_0RGB32:
981995
s->colorspace= 1;
982996
break;
997+
case PIX_FMT_GBRP9:
998+
if (!avctx->bits_per_raw_sample)
999+
s->bits_per_raw_sample = 9;
1000+
case PIX_FMT_GBRP10:
1001+
if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
1002+
s->bits_per_raw_sample = 10;
1003+
case PIX_FMT_GBRP12:
1004+
if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
1005+
s->bits_per_raw_sample = 12;
1006+
case PIX_FMT_GBRP14:
1007+
if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
1008+
s->bits_per_raw_sample = 14;
1009+
else if (!s->bits_per_raw_sample)
1010+
s->bits_per_raw_sample = avctx->bits_per_raw_sample;
1011+
s->colorspace= 1;
1012+
s->chroma_planes= 1;
1013+
s->version= FFMAX(s->version, 1);
1014+
break;
9831015
default:
9841016
av_log(avctx, AV_LOG_ERROR, "format not supported\n");
9851017
return AVERROR_INVALIDDATA;
@@ -1225,7 +1257,10 @@ static int encode_slice(AVCodecContext *c, void *arg){
12251257
if (fs->transparency)
12261258
encode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2);
12271259
}else{
1228-
encode_rgb_frame(fs, (uint32_t*)(p->data[0]) + ps*x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
1260+
uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0],
1261+
p->data[1] + ps*x + y*p->linesize[1],
1262+
p->data[2] + ps*x + y*p->linesize[2]};
1263+
encode_rgb_frame(fs, planes, width, height, p->linesize);
12291264
}
12301265
emms_c();
12311266

@@ -1500,9 +1535,12 @@ static void decode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride,
15001535
}
15011536
}
15021537

1503-
static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
1538+
static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]){
15041539
int x, y, p;
15051540
int16_t *sample[4][2];
1541+
int lbd= s->avctx->bits_per_raw_sample <= 8;
1542+
int bits= s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
1543+
int offset= 1 << bits;
15061544
for(x=0; x<4; x++){
15071545
sample[x][0] = s->sample_buffer + x*2 *(w+6) + 3;
15081546
sample[x][1] = s->sample_buffer + (x*2+1)*(w+6) + 3;
@@ -1521,7 +1559,10 @@ static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
15211559

15221560
sample[p][1][-1]= sample[p][0][0 ];
15231561
sample[p][0][ w]= sample[p][0][w-1];
1524-
decode_line(s, w, sample[p], (p+1)/2, 9);
1562+
if (lbd)
1563+
decode_line(s, w, sample[p], (p+1)/2, 9);
1564+
else
1565+
decode_line(s, w, sample[p], (p+1)/2, bits+1);
15251566
}
15261567
for(x=0; x<w; x++){
15271568
int g= sample[0][1][x];
@@ -1532,13 +1573,19 @@ static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
15321573
// assert(g>=0 && b>=0 && r>=0);
15331574
// assert(g<256 && b<512 && r<512);
15341575

1535-
b -= 0x100;
1536-
r -= 0x100;
1576+
b -= offset;
1577+
r -= offset;
15371578
g -= (b + r)>>2;
15381579
b += g;
15391580
r += g;
15401581

1541-
src[x + stride*y]= b + (g<<8) + (r<<16) + (a<<24);
1582+
if(lbd)
1583+
*((uint32_t*)(src[0] + x*4 + stride[0]*y))= b + (g<<8) + (r<<16) + (a<<24);
1584+
else{
1585+
*((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b;
1586+
*((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g;
1587+
*((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r;
1588+
}
15421589
}
15431590
}
15441591
}
@@ -1646,7 +1693,10 @@ static int decode_slice(AVCodecContext *c, void *arg){
16461693
if (fs->transparency)
16471694
decode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2);
16481695
}else{
1649-
decode_rgb_frame(fs, (uint32_t*)p->data[0] + ps*x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
1696+
uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0],
1697+
p->data[1] + ps*x + y*p->linesize[1],
1698+
p->data[2] + ps*x + y*p->linesize[2]};
1699+
decode_rgb_frame(fs, planes, width, height, p->linesize);
16501700
}
16511701
if(fs->ac && f->version > 2) {
16521702
int v = fs->c.bytestream_end - fs->c.bytestream - 3 - 5*f->ec;
@@ -1871,6 +1921,15 @@ static int read_header(FFV1Context *f){
18711921
av_log(f->avctx, AV_LOG_ERROR, "chroma subsampling not supported in this colorspace\n");
18721922
return -1;
18731923
}
1924+
if(f->avctx->bits_per_raw_sample==9)
1925+
f->avctx->pix_fmt= PIX_FMT_GBRP9;
1926+
else if(f->avctx->bits_per_raw_sample==10)
1927+
f->avctx->pix_fmt= PIX_FMT_GBRP10;
1928+
else if(f->avctx->bits_per_raw_sample==12)
1929+
f->avctx->pix_fmt= PIX_FMT_GBRP12;
1930+
else if(f->avctx->bits_per_raw_sample==14)
1931+
f->avctx->pix_fmt= PIX_FMT_GBRP14;
1932+
else
18741933
if(f->transparency) f->avctx->pix_fmt= PIX_FMT_RGB32;
18751934
else f->avctx->pix_fmt= PIX_FMT_0RGB32;
18761935
}else{
@@ -2130,7 +2189,8 @@ AVCodec ff_ffv1_encoder = {
21302189
PIX_FMT_YUV410P, PIX_FMT_0RGB32, PIX_FMT_RGB32, PIX_FMT_YUV420P16,
21312190
PIX_FMT_YUV422P16, PIX_FMT_YUV444P16, PIX_FMT_YUV444P9, PIX_FMT_YUV422P9,
21322191
PIX_FMT_YUV420P9, PIX_FMT_YUV420P10, PIX_FMT_YUV422P10, PIX_FMT_YUV444P10,
2133-
PIX_FMT_GRAY16, PIX_FMT_GRAY8,
2192+
PIX_FMT_GRAY16, PIX_FMT_GRAY8, PIX_FMT_GBRP9, PIX_FMT_GBRP10,
2193+
PIX_FMT_GBRP12, PIX_FMT_GBRP14,
21342194
PIX_FMT_NONE
21352195
},
21362196
.long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),

0 commit comments

Comments
 (0)