]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ffv1.c
diracyasm: fix win64
[ffmpeg] / libavcodec / ffv1.c
index 5547661776feec142e84d5306e1a32da71c45986..e8fccb66ead90cd79a6c3d61cc4bb5b8cf524d5a 100644 (file)
@@ -38,6 +38,7 @@
 #include "libavutil/crc.h"
 #include "libavutil/opt.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/timer.h"
 
 #ifdef __INTEL_COMPILER
 #undef av_flatten
@@ -579,10 +580,13 @@ static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride,
     }
 }
 
-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));
@@ -593,17 +597,24 @@ static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
                 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);
@@ -615,7 +626,10 @@ static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
         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);
         }
     }
 }
@@ -801,8 +815,11 @@ static int write_extra_header(FFV1Context *f){
     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++){
@@ -980,6 +997,24 @@ static av_cold int encode_init(AVCodecContext *avctx)
     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;
@@ -1206,6 +1241,8 @@ static int encode_slice(AVCodecContext *c, void *arg){
         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);
     }
@@ -1225,7 +1262,10 @@ static int encode_slice(AVCodecContext *c, void *arg){
         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();
 
@@ -1286,7 +1326,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         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{
@@ -1500,9 +1540,12 @@ static void decode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride,
     }
 }
 
-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;
@@ -1521,7 +1564,10 @@ static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
 
             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];
@@ -1532,13 +1578,19 @@ static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int st
 //            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;
+            }
         }
     }
 }
@@ -1625,6 +1677,8 @@ static int decode_slice(AVCodecContext *c, void *arg){
     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,
@@ -1646,11 +1700,16 @@ static int decode_slice(AVCodecContext *c, void *arg){
         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;
         }
@@ -1781,7 +1840,7 @@ static int read_extra_header(FFV1Context *f){
 
 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));
@@ -1871,6 +1930,15 @@ static int read_header(FFV1Context *f){
             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{
@@ -1943,6 +2011,7 @@ static int read_header(FFV1Context *f){
             }
 
             if(f->version <= 2){
+                av_assert0(context_count>=0);
                 if(p->context_count < context_count){
                     av_freep(&p->state);
                     av_freep(&p->vlc_state);
@@ -2098,7 +2167,7 @@ AVCodec ff_ffv1_decoder = {
 #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}
 };
 
@@ -2130,7 +2199,8 @@ AVCodec ff_ffv1_encoder = {
         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"),