| /* |
| * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> |
| * |
| * This file is part of FFmpeg. |
| * |
| * FFmpeg is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * FFmpeg is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with FFmpeg; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "avcodec.h" |
| #include "dsputil.h" |
| #include "snow.h" |
| |
| #include "rangecoder.h" |
| #include "mathops.h" |
| |
| #include "mpegvideo.h" |
| |
| #undef NDEBUG |
| #include <assert.h> |
| |
| static const int8_t quant3[256]={ |
| 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, |
| }; |
| static const int8_t quant3b[256]={ |
| 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
| }; |
| static const int8_t quant3bA[256]={ |
| 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, |
| }; |
| static const int8_t quant5[256]={ |
| 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-1, |
| }; |
| static const int8_t quant7[256]={ |
| 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, |
| -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1, |
| }; |
| static const int8_t quant9[256]={ |
| 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3,-3,-3,-3, |
| -3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-1,-1, |
| }; |
| static const int8_t quant11[256]={ |
| 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-4,-4, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, |
| -4,-4,-4,-4,-4,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-1, |
| }; |
| static const int8_t quant13[256]={ |
| 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, |
| 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| -6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, |
| -6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, |
| -6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, |
| -6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, |
| -6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, |
| -4,-4,-4,-4,-4,-4,-4,-4,-4,-3,-3,-3,-3,-2,-2,-1, |
| }; |
| |
| #if 0 //64*cubic |
| static const uint8_t obmc32[1024]={ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, |
| 0, 0, 0, 4, 4, 4, 4, 8, 8, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 8, 8, 4, 4, 4, 4, 0, 0, 0, |
| 0, 0, 4, 4, 8, 8, 12, 16, 16, 20, 24, 24, 28, 28, 32, 32, 32, 32, 28, 28, 24, 24, 20, 16, 16, 12, 8, 8, 4, 4, 0, 0, |
| 0, 0, 4, 8, 8, 12, 16, 24, 28, 32, 36, 40, 44, 48, 48, 48, 48, 48, 48, 44, 40, 36, 32, 28, 24, 16, 12, 8, 8, 4, 0, 0, |
| 0, 4, 4, 8, 12, 20, 24, 32, 40, 44, 52, 56, 60, 64, 68, 72, 72, 68, 64, 60, 56, 52, 44, 40, 32, 24, 20, 12, 8, 4, 4, 0, |
| 0, 4, 4, 12, 16, 24, 32, 40, 52, 60, 68, 76, 80, 88, 88, 92, 92, 88, 88, 80, 76, 68, 60, 52, 40, 32, 24, 16, 12, 4, 4, 0, |
| 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, 84, 92,100,108,112,116,116,112,108,100, 92, 84, 76, 64, 52, 40, 32, 24, 16, 8, 4, 0, |
| 0, 4, 8, 16, 28, 40, 52, 64, 76, 88,100,112,124,132,136,140,140,136,132,124,112,100, 88, 76, 64, 52, 40, 28, 16, 8, 4, 0, |
| 0, 4, 12, 20, 32, 44, 60, 76, 88,104,120,132,144,152,160,164,164,160,152,144,132,120,104, 88, 76, 60, 44, 32, 20, 12, 4, 0, |
| 0, 4, 12, 24, 36, 48, 68, 84,100,120,136,152,164,176,180,184,184,180,176,164,152,136,120,100, 84, 68, 48, 36, 24, 12, 4, 0, |
| 0, 4, 12, 24, 40, 56, 76, 92,112,132,152,168,180,192,204,208,208,204,192,180,168,152,132,112, 92, 76, 56, 40, 24, 12, 4, 0, |
| 0, 4, 16, 28, 44, 60, 80,100,124,144,164,180,196,208,220,224,224,220,208,196,180,164,144,124,100, 80, 60, 44, 28, 16, 4, 0, |
| 0, 8, 16, 28, 48, 64, 88,108,132,152,176,192,208,224,232,240,240,232,224,208,192,176,152,132,108, 88, 64, 48, 28, 16, 8, 0, |
| 0, 4, 16, 32, 48, 68, 88,112,136,160,180,204,220,232,244,248,248,244,232,220,204,180,160,136,112, 88, 68, 48, 32, 16, 4, 0, |
| 1, 8, 16, 32, 48, 72, 92,116,140,164,184,208,224,240,248,255,255,248,240,224,208,184,164,140,116, 92, 72, 48, 32, 16, 8, 1, |
| 1, 8, 16, 32, 48, 72, 92,116,140,164,184,208,224,240,248,255,255,248,240,224,208,184,164,140,116, 92, 72, 48, 32, 16, 8, 1, |
| 0, 4, 16, 32, 48, 68, 88,112,136,160,180,204,220,232,244,248,248,244,232,220,204,180,160,136,112, 88, 68, 48, 32, 16, 4, 0, |
| 0, 8, 16, 28, 48, 64, 88,108,132,152,176,192,208,224,232,240,240,232,224,208,192,176,152,132,108, 88, 64, 48, 28, 16, 8, 0, |
| 0, 4, 16, 28, 44, 60, 80,100,124,144,164,180,196,208,220,224,224,220,208,196,180,164,144,124,100, 80, 60, 44, 28, 16, 4, 0, |
| 0, 4, 12, 24, 40, 56, 76, 92,112,132,152,168,180,192,204,208,208,204,192,180,168,152,132,112, 92, 76, 56, 40, 24, 12, 4, 0, |
| 0, 4, 12, 24, 36, 48, 68, 84,100,120,136,152,164,176,180,184,184,180,176,164,152,136,120,100, 84, 68, 48, 36, 24, 12, 4, 0, |
| 0, 4, 12, 20, 32, 44, 60, 76, 88,104,120,132,144,152,160,164,164,160,152,144,132,120,104, 88, 76, 60, 44, 32, 20, 12, 4, 0, |
| 0, 4, 8, 16, 28, 40, 52, 64, 76, 88,100,112,124,132,136,140,140,136,132,124,112,100, 88, 76, 64, 52, 40, 28, 16, 8, 4, 0, |
| 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, 84, 92,100,108,112,116,116,112,108,100, 92, 84, 76, 64, 52, 40, 32, 24, 16, 8, 4, 0, |
| 0, 4, 4, 12, 16, 24, 32, 40, 52, 60, 68, 76, 80, 88, 88, 92, 92, 88, 88, 80, 76, 68, 60, 52, 40, 32, 24, 16, 12, 4, 4, 0, |
| 0, 4, 4, 8, 12, 20, 24, 32, 40, 44, 52, 56, 60, 64, 68, 72, 72, 68, 64, 60, 56, 52, 44, 40, 32, 24, 20, 12, 8, 4, 4, 0, |
| 0, 0, 4, 8, 8, 12, 16, 24, 28, 32, 36, 40, 44, 48, 48, 48, 48, 48, 48, 44, 40, 36, 32, 28, 24, 16, 12, 8, 8, 4, 0, 0, |
| 0, 0, 4, 4, 8, 8, 12, 16, 16, 20, 24, 24, 28, 28, 32, 32, 32, 32, 28, 28, 24, 24, 20, 16, 16, 12, 8, 8, 4, 4, 0, 0, |
| 0, 0, 0, 4, 4, 4, 4, 8, 8, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16, 16, 12, 12, 12, 8, 8, 4, 4, 4, 4, 0, 0, 0, |
| 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| //error:0.000022 |
| }; |
| static const uint8_t obmc16[256]={ |
| 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 0, 4, 4, 8, 16, 20, 20, 24, 24, 20, 20, 16, 8, 4, 4, 0, |
| 0, 4, 16, 24, 36, 44, 52, 60, 60, 52, 44, 36, 24, 16, 4, 0, |
| 0, 8, 24, 44, 60, 80, 96,104,104, 96, 80, 60, 44, 24, 8, 0, |
| 0, 16, 36, 60, 92,116,136,152,152,136,116, 92, 60, 36, 16, 0, |
| 0, 20, 44, 80,116,152,180,196,196,180,152,116, 80, 44, 20, 0, |
| 4, 20, 52, 96,136,180,212,228,228,212,180,136, 96, 52, 20, 4, |
| 4, 24, 60,104,152,196,228,248,248,228,196,152,104, 60, 24, 4, |
| 4, 24, 60,104,152,196,228,248,248,228,196,152,104, 60, 24, 4, |
| 4, 20, 52, 96,136,180,212,228,228,212,180,136, 96, 52, 20, 4, |
| 0, 20, 44, 80,116,152,180,196,196,180,152,116, 80, 44, 20, 0, |
| 0, 16, 36, 60, 92,116,136,152,152,136,116, 92, 60, 36, 16, 0, |
| 0, 8, 24, 44, 60, 80, 96,104,104, 96, 80, 60, 44, 24, 8, 0, |
| 0, 4, 16, 24, 36, 44, 52, 60, 60, 52, 44, 36, 24, 16, 4, 0, |
| 0, 4, 4, 8, 16, 20, 20, 24, 24, 20, 20, 16, 8, 4, 4, 0, |
| 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| //error:0.000033 |
| }; |
| #elif 1 // 64*linear |
| static const uint8_t obmc32[1024]={ |
| 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, |
| 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, |
| 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, |
| 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, |
| 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, |
| 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, |
| 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, |
| 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, |
| 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, |
| 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, |
| 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, |
| 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, |
| 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, |
| 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, |
| 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, |
| 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, |
| 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, |
| 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, |
| 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, |
| 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, |
| 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, |
| 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, |
| 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, |
| 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, |
| 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, |
| 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, |
| 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, |
| 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, |
| 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, |
| 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, |
| 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, |
| 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, |
| //error:0.000020 |
| }; |
| static const uint8_t obmc16[256]={ |
| 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, |
| 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, |
| 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, |
| 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, |
| 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, |
| 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, |
| 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, |
| 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, |
| 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, |
| 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, |
| 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, |
| 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, |
| 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, |
| 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, |
| 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, |
| 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, |
| //error:0.000015 |
| }; |
| #else //64*cos |
| static const uint8_t obmc32[1024]={ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 4, 4, 4, 4, 8, 8, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 8, 8, 4, 4, 4, 4, 0, 0, 0, |
| 0, 0, 4, 4, 4, 8, 8, 12, 16, 20, 20, 24, 28, 28, 28, 28, 28, 28, 28, 28, 24, 20, 20, 16, 12, 8, 8, 4, 4, 4, 0, 0, |
| 0, 0, 4, 4, 8, 12, 16, 20, 24, 28, 36, 40, 44, 44, 48, 48, 48, 48, 44, 44, 40, 36, 28, 24, 20, 16, 12, 8, 4, 4, 0, 0, |
| 0, 0, 4, 8, 12, 20, 24, 32, 36, 44, 48, 56, 60, 64, 68, 68, 68, 68, 64, 60, 56, 48, 44, 36, 32, 24, 20, 12, 8, 4, 0, 0, |
| 0, 4, 4, 8, 16, 24, 32, 40, 48, 60, 68, 76, 80, 84, 88, 92, 92, 88, 84, 80, 76, 68, 60, 48, 40, 32, 24, 16, 8, 4, 4, 0, |
| 0, 4, 8, 12, 20, 32, 40, 52, 64, 76, 84, 96,104,108,112,116,116,112,108,104, 96, 84, 76, 64, 52, 40, 32, 20, 12, 8, 4, 0, |
| 0, 4, 8, 16, 24, 36, 48, 64, 76, 92,104,116,124,132,136,140,140,136,132,124,116,104, 92, 76, 64, 48, 36, 24, 16, 8, 4, 0, |
| 0, 4, 12, 20, 28, 44, 60, 76, 92,104,120,136,148,156,160,164,164,160,156,148,136,120,104, 92, 76, 60, 44, 28, 20, 12, 4, 0, |
| 0, 4, 12, 20, 36, 48, 68, 84,104,120,140,152,168,176,184,188,188,184,176,168,152,140,120,104, 84, 68, 48, 36, 20, 12, 4, 0, |
| 0, 4, 12, 24, 36, 56, 76, 96,116,136,152,172,184,196,204,208,208,204,196,184,172,152,136,116, 96, 76, 56, 36, 24, 12, 4, 0, |
| 0, 4, 12, 24, 44, 60, 80,104,124,148,168,184,200,212,224,228,228,224,212,200,184,168,148,124,104, 80, 60, 44, 24, 12, 4, 0, |
| 0, 4, 12, 28, 44, 64, 84,108,132,156,176,196,212,228,236,240,240,236,228,212,196,176,156,132,108, 84, 64, 44, 28, 12, 4, 0, |
| 0, 4, 16, 28, 48, 68, 88,112,136,160,184,204,224,236,244,252,252,244,236,224,204,184,160,136,112, 88, 68, 48, 28, 16, 4, 0, |
| 1, 4, 16, 28, 48, 68, 92,116,140,164,188,208,228,240,252,255,255,252,240,228,208,188,164,140,116, 92, 68, 48, 28, 16, 4, 1, |
| 1, 4, 16, 28, 48, 68, 92,116,140,164,188,208,228,240,252,255,255,252,240,228,208,188,164,140,116, 92, 68, 48, 28, 16, 4, 1, |
| 0, 4, 16, 28, 48, 68, 88,112,136,160,184,204,224,236,244,252,252,244,236,224,204,184,160,136,112, 88, 68, 48, 28, 16, 4, 0, |
| 0, 4, 12, 28, 44, 64, 84,108,132,156,176,196,212,228,236,240,240,236,228,212,196,176,156,132,108, 84, 64, 44, 28, 12, 4, 0, |
| 0, 4, 12, 24, 44, 60, 80,104,124,148,168,184,200,212,224,228,228,224,212,200,184,168,148,124,104, 80, 60, 44, 24, 12, 4, 0, |
| 0, 4, 12, 24, 36, 56, 76, 96,116,136,152,172,184,196,204,208,208,204,196,184,172,152,136,116, 96, 76, 56, 36, 24, 12, 4, 0, |
| 0, 4, 12, 20, 36, 48, 68, 84,104,120,140,152,168,176,184,188,188,184,176,168,152,140,120,104, 84, 68, 48, 36, 20, 12, 4, 0, |
| 0, 4, 12, 20, 28, 44, 60, 76, 92,104,120,136,148,156,160,164,164,160,156,148,136,120,104, 92, 76, 60, 44, 28, 20, 12, 4, 0, |
| 0, 4, 8, 16, 24, 36, 48, 64, 76, 92,104,116,124,132,136,140,140,136,132,124,116,104, 92, 76, 64, 48, 36, 24, 16, 8, 4, 0, |
| 0, 4, 8, 12, 20, 32, 40, 52, 64, 76, 84, 96,104,108,112,116,116,112,108,104, 96, 84, 76, 64, 52, 40, 32, 20, 12, 8, 4, 0, |
| 0, 4, 4, 8, 16, 24, 32, 40, 48, 60, 68, 76, 80, 84, 88, 92, 92, 88, 84, 80, 76, 68, 60, 48, 40, 32, 24, 16, 8, 4, 4, 0, |
| 0, 0, 4, 8, 12, 20, 24, 32, 36, 44, 48, 56, 60, 64, 68, 68, 68, 68, 64, 60, 56, 48, 44, 36, 32, 24, 20, 12, 8, 4, 0, 0, |
| 0, 0, 4, 4, 8, 12, 16, 20, 24, 28, 36, 40, 44, 44, 48, 48, 48, 48, 44, 44, 40, 36, 28, 24, 20, 16, 12, 8, 4, 4, 0, 0, |
| 0, 0, 4, 4, 4, 8, 8, 12, 16, 20, 20, 24, 28, 28, 28, 28, 28, 28, 28, 28, 24, 20, 20, 16, 12, 8, 8, 4, 4, 4, 0, 0, |
| 0, 0, 0, 4, 4, 4, 4, 8, 8, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 12, 12, 12, 12, 8, 8, 4, 4, 4, 4, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| //error:0.000022 |
| }; |
| static const uint8_t obmc16[256]={ |
| 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, |
| 0, 0, 4, 8, 12, 16, 20, 20, 20, 20, 16, 12, 8, 4, 0, 0, |
| 0, 4, 12, 24, 32, 44, 52, 56, 56, 52, 44, 32, 24, 12, 4, 0, |
| 0, 8, 24, 40, 60, 80, 96,104,104, 96, 80, 60, 40, 24, 8, 0, |
| 0, 12, 32, 64, 92,120,140,152,152,140,120, 92, 64, 32, 12, 0, |
| 4, 16, 44, 80,120,156,184,196,196,184,156,120, 80, 44, 16, 4, |
| 4, 20, 52, 96,140,184,216,232,232,216,184,140, 96, 52, 20, 4, |
| 0, 20, 56,104,152,196,232,252,252,232,196,152,104, 56, 20, 0, |
| 0, 20, 56,104,152,196,232,252,252,232,196,152,104, 56, 20, 0, |
| 4, 20, 52, 96,140,184,216,232,232,216,184,140, 96, 52, 20, 4, |
| 4, 16, 44, 80,120,156,184,196,196,184,156,120, 80, 44, 16, 4, |
| 0, 12, 32, 64, 92,120,140,152,152,140,120, 92, 64, 32, 12, 0, |
| 0, 8, 24, 40, 60, 80, 96,104,104, 96, 80, 60, 40, 24, 8, 0, |
| 0, 4, 12, 24, 32, 44, 52, 56, 56, 52, 44, 32, 24, 12, 4, 0, |
| 0, 0, 4, 8, 12, 16, 20, 20, 20, 20, 16, 12, 8, 4, 0, 0, |
| 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, |
| //error:0.000022 |
| }; |
| #endif /* 0 */ |
| |
| //linear *64 |
| static const uint8_t obmc8[64]={ |
| 4, 12, 20, 28, 28, 20, 12, 4, |
| 12, 36, 60, 84, 84, 60, 36, 12, |
| 20, 60,100,140,140,100, 60, 20, |
| 28, 84,140,196,196,140, 84, 28, |
| 28, 84,140,196,196,140, 84, 28, |
| 20, 60,100,140,140,100, 60, 20, |
| 12, 36, 60, 84, 84, 60, 36, 12, |
| 4, 12, 20, 28, 28, 20, 12, 4, |
| //error:0.000000 |
| }; |
| |
| //linear *64 |
| static const uint8_t obmc4[16]={ |
| 16, 48, 48, 16, |
| 48,144,144, 48, |
| 48,144,144, 48, |
| 16, 48, 48, 16, |
| //error:0.000000 |
| }; |
| |
| static const uint8_t * const obmc_tab[4]={ |
| obmc32, obmc16, obmc8, obmc4 |
| }; |
| |
| static int scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES]; |
| |
| typedef struct BlockNode{ |
| int16_t mx; |
| int16_t my; |
| uint8_t ref; |
| uint8_t color[3]; |
| uint8_t type; |
| //#define TYPE_SPLIT 1 |
| #define BLOCK_INTRA 1 |
| #define BLOCK_OPT 2 |
| //#define TYPE_NOCOLOR 4 |
| uint8_t level; //FIXME merge into type? |
| }BlockNode; |
| |
| static const BlockNode null_block= { //FIXME add border maybe |
| .color= {128,128,128}, |
| .mx= 0, |
| .my= 0, |
| .ref= 0, |
| .type= 0, |
| .level= 0, |
| }; |
| |
| #define LOG2_MB_SIZE 4 |
| #define MB_SIZE (1<<LOG2_MB_SIZE) |
| #define ENCODER_EXTRA_BITS 4 |
| #define HTAPS_MAX 8 |
| |
| typedef struct x_and_coeff{ |
| int16_t x; |
| uint16_t coeff; |
| } x_and_coeff; |
| |
| typedef struct SubBand{ |
| int level; |
| int stride; |
| int width; |
| int height; |
| int qlog; ///< log(qscale)/log[2^(1/6)] |
| DWTELEM *buf; |
| IDWTELEM *ibuf; |
| int buf_x_offset; |
| int buf_y_offset; |
| int stride_line; ///< Stride measured in lines, not pixels. |
| x_and_coeff * x_coeff; |
| struct SubBand *parent; |
| uint8_t state[/*7*2*/ 7 + 512][32]; |
| }SubBand; |
| |
| typedef struct Plane{ |
| int width; |
| int height; |
| SubBand band[MAX_DECOMPOSITIONS][4]; |
| |
| int htaps; |
| int8_t hcoeff[HTAPS_MAX/2]; |
| int diag_mc; |
| int fast_mc; |
| |
| int last_htaps; |
| int8_t last_hcoeff[HTAPS_MAX/2]; |
| int last_diag_mc; |
| }Plane; |
| |
| typedef struct SnowContext{ |
| // MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX) |
| |
| AVCodecContext *avctx; |
| RangeCoder c; |
| DSPContext dsp; |
| AVFrame new_picture; |
| AVFrame input_picture; ///< new_picture with the internal linesizes |
| AVFrame current_picture; |
| AVFrame last_picture[MAX_REF_FRAMES]; |
| uint8_t *halfpel_plane[MAX_REF_FRAMES][4][4]; |
| AVFrame mconly_picture; |
| // uint8_t q_context[16]; |
| uint8_t header_state[32]; |
| uint8_t block_state[128 + 32*128]; |
| int keyframe; |
| int always_reset; |
| int version; |
| int spatial_decomposition_type; |
| int last_spatial_decomposition_type; |
| int temporal_decomposition_type; |
| int spatial_decomposition_count; |
| int last_spatial_decomposition_count; |
| int temporal_decomposition_count; |
| int max_ref_frames; |
| int ref_frames; |
| int16_t (*ref_mvs[MAX_REF_FRAMES])[2]; |
| uint32_t *ref_scores[MAX_REF_FRAMES]; |
| DWTELEM *spatial_dwt_buffer; |
| IDWTELEM *spatial_idwt_buffer; |
| int colorspace_type; |
| int chroma_h_shift; |
| int chroma_v_shift; |
| int spatial_scalability; |
| int qlog; |
| int last_qlog; |
| int lambda; |
| int lambda2; |
| int pass1_rc; |
| int mv_scale; |
| int last_mv_scale; |
| int qbias; |
| int last_qbias; |
| #define QBIAS_SHIFT 3 |
| int b_width; |
| int b_height; |
| int block_max_depth; |
| int last_block_max_depth; |
| Plane plane[MAX_PLANES]; |
| BlockNode *block; |
| #define ME_CACHE_SIZE 1024 |
| int me_cache[ME_CACHE_SIZE]; |
| int me_cache_generation; |
| slice_buffer sb; |
| |
| MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX) |
| |
| uint8_t *scratchbuf; |
| }SnowContext; |
| |
| typedef struct { |
| IDWTELEM *b0; |
| IDWTELEM *b1; |
| IDWTELEM *b2; |
| IDWTELEM *b3; |
| int y; |
| } DWTCompose; |
| |
| #define slice_buffer_get_line(slice_buf, line_num) ((slice_buf)->line[line_num] ? (slice_buf)->line[line_num] : slice_buffer_load_line((slice_buf), (line_num))) |
| //#define slice_buffer_get_line(slice_buf, line_num) (slice_buffer_load_line((slice_buf), (line_num))) |
| |
| static void iterative_me(SnowContext *s); |
| |
| static void slice_buffer_init(slice_buffer * buf, int line_count, int max_allocated_lines, int line_width, IDWTELEM * base_buffer) |
| { |
| int i; |
| |
| buf->base_buffer = base_buffer; |
| buf->line_count = line_count; |
| buf->line_width = line_width; |
| buf->data_count = max_allocated_lines; |
| buf->line = av_mallocz (sizeof(IDWTELEM *) * line_count); |
| buf->data_stack = av_malloc (sizeof(IDWTELEM *) * max_allocated_lines); |
| |
| for(i = 0; i < max_allocated_lines; i++){ |
| buf->data_stack[i] = av_malloc (sizeof(IDWTELEM) * line_width); |
| } |
| |
| buf->data_stack_top = max_allocated_lines - 1; |
| } |
| |
| static IDWTELEM * slice_buffer_load_line(slice_buffer * buf, int line) |
| { |
| int offset; |
| IDWTELEM * buffer; |
| |
| assert(buf->data_stack_top >= 0); |
| // assert(!buf->line[line]); |
| if (buf->line[line]) |
| return buf->line[line]; |
| |
| offset = buf->line_width * line; |
| buffer = buf->data_stack[buf->data_stack_top]; |
| buf->data_stack_top--; |
| buf->line[line] = buffer; |
| |
| return buffer; |
| } |
| |
| static void slice_buffer_release(slice_buffer * buf, int line) |
| { |
| int offset; |
| IDWTELEM * buffer; |
| |
| assert(line >= 0 && line < buf->line_count); |
| assert(buf->line[line]); |
| |
| offset = buf->line_width * line; |
| buffer = buf->line[line]; |
| buf->data_stack_top++; |
| buf->data_stack[buf->data_stack_top] = buffer; |
| buf->line[line] = NULL; |
| } |
| |
| static void slice_buffer_flush(slice_buffer * buf) |
| { |
| int i; |
| for(i = 0; i < buf->line_count; i++){ |
| if (buf->line[i]) |
| slice_buffer_release(buf, i); |
| } |
| } |
| |
| static void slice_buffer_destroy(slice_buffer * buf) |
| { |
| int i; |
| slice_buffer_flush(buf); |
| |
| for(i = buf->data_count - 1; i >= 0; i--){ |
| av_freep(&buf->data_stack[i]); |
| } |
| av_freep(&buf->data_stack); |
| av_freep(&buf->line); |
| } |
| |
| #ifdef __sgi |
| // Avoid a name clash on SGI IRIX |
| #undef qexp |
| #endif |
| #define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0 |
| static uint8_t qexp[QROOT]; |
| |
| static inline int mirror(int v, int m){ |
| while((unsigned)v > (unsigned)m){ |
| v=-v; |
| if(v<0) v+= 2*m; |
| } |
| return v; |
| } |
| |
| static inline void put_symbol(RangeCoder *c, uint8_t *state, int v, int is_signed){ |
| int i; |
| |
| if(v){ |
| const int a= FFABS(v); |
| const int e= av_log2(a); |
| #if 1 |
| const int el= FFMIN(e, 10); |
| put_rac(c, state+0, 0); |
| |
| for(i=0; i<el; i++){ |
| put_rac(c, state+1+i, 1); //1..10 |
| } |
| for(; i<e; i++){ |
| put_rac(c, state+1+9, 1); //1..10 |
| } |
| put_rac(c, state+1+FFMIN(i,9), 0); |
| |
| for(i=e-1; i>=el; i--){ |
| put_rac(c, state+22+9, (a>>i)&1); //22..31 |
| } |
| for(; i>=0; i--){ |
| put_rac(c, state+22+i, (a>>i)&1); //22..31 |
| } |
| |
| if(is_signed) |
| put_rac(c, state+11 + el, v < 0); //11..21 |
| #else |
| |
| put_rac(c, state+0, 0); |
| if(e<=9){ |
| for(i=0; i<e; i++){ |
| put_rac(c, state+1+i, 1); //1..10 |
| } |
| put_rac(c, state+1+i, 0); |
| |
| for(i=e-1; i>=0; i--){ |
| put_rac(c, state+22+i, (a>>i)&1); //22..31 |
| } |
| |
| if(is_signed) |
| put_rac(c, state+11 + e, v < 0); //11..21 |
| }else{ |
| for(i=0; i<e; i++){ |
| put_rac(c, state+1+FFMIN(i,9), 1); //1..10 |
| } |
| put_rac(c, state+1+FFMIN(i,9), 0); |
| |
| for(i=e-1; i>=0; i--){ |
| put_rac(c, state+22+FFMIN(i,9), (a>>i)&1); //22..31 |
| } |
| |
| if(is_signed) |
| put_rac(c, state+11 + FFMIN(e,10), v < 0); //11..21 |
| } |
| #endif /* 1 */ |
| }else{ |
| put_rac(c, state+0, 1); |
| } |
| } |
| |
| static inline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed){ |
| if(get_rac(c, state+0)) |
| return 0; |
| else{ |
| int i, e, a; |
| e= 0; |
| while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10 |
| e++; |
| } |
| |
| a= 1; |
| for(i=e-1; i>=0; i--){ |
| a += a + get_rac(c, state+22 + FFMIN(i,9)); //22..31 |
| } |
| |
| if(is_signed && get_rac(c, state+11 + FFMIN(e,10))) //11..21 |
| return -a; |
| else |
| return a; |
| } |
| } |
| |
| static inline void put_symbol2(RangeCoder *c, uint8_t *state, int v, int log2){ |
| int i; |
| int r= log2>=0 ? 1<<log2 : 1; |
| |
| assert(v>=0); |
| assert(log2>=-4); |
| |
| while(v >= r){ |
| put_rac(c, state+4+log2, 1); |
| v -= r; |
| log2++; |
| if(log2>0) r+=r; |
| } |
| put_rac(c, state+4+log2, 0); |
| |
| for(i=log2-1; i>=0; i--){ |
| put_rac(c, state+31-i, (v>>i)&1); |
| } |
| } |
| |
| static inline int get_symbol2(RangeCoder *c, uint8_t *state, int log2){ |
| int i; |
| int r= log2>=0 ? 1<<log2 : 1; |
| int v=0; |
| |
| assert(log2>=-4); |
| |
| while(get_rac(c, state+4+log2)){ |
| v+= r; |
| log2++; |
| if(log2>0) r+=r; |
| } |
| |
| for(i=log2-1; i>=0; i--){ |
| v+= get_rac(c, state+31-i)<<i; |
| } |
| |
| return v; |
| } |
| |
| static av_always_inline void |
| lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, |
| int dst_step, int src_step, int ref_step, |
| int width, int mul, int add, int shift, |
| int highpass, int inverse){ |
| const int mirror_left= !highpass; |
| const int mirror_right= (width&1) ^ highpass; |
| const int w= (width>>1) - 1 + (highpass & width); |
| int i; |
| |
| #define LIFT(src, ref, inv) ((src) + ((inv) ? - (ref) : + (ref))) |
| if(mirror_left){ |
| dst[0] = LIFT(src[0], ((mul*2*ref[0]+add)>>shift), inverse); |
| dst += dst_step; |
| src += src_step; |
| } |
| |
| for(i=0; i<w; i++){ |
| dst[i*dst_step] = |
| LIFT(src[i*src_step], |
| ((mul*(ref[i*ref_step] + ref[(i+1)*ref_step])+add)>>shift), |
| inverse); |
| } |
| |
| if(mirror_right){ |
| dst[w*dst_step] = |
| LIFT(src[w*src_step], |
| ((mul*2*ref[w*ref_step]+add)>>shift), |
| inverse); |
| } |
| } |
| |
| static av_always_inline void |
| inv_lift(IDWTELEM *dst, IDWTELEM *src, IDWTELEM *ref, |
| int dst_step, int src_step, int ref_step, |
| int width, int mul, int add, int shift, |
| int highpass, int inverse){ |
| const int mirror_left= !highpass; |
| const int mirror_right= (width&1) ^ highpass; |
| const int w= (width>>1) - 1 + (highpass & width); |
| int i; |
| |
| #define LIFT(src, ref, inv) ((src) + ((inv) ? - (ref) : + (ref))) |
| if(mirror_left){ |
| dst[0] = LIFT(src[0], ((mul*2*ref[0]+add)>>shift), inverse); |
| dst += dst_step; |
| src += src_step; |
| } |
| |
| for(i=0; i<w; i++){ |
| dst[i*dst_step] = |
| LIFT(src[i*src_step], |
| ((mul*(ref[i*ref_step] + ref[(i+1)*ref_step])+add)>>shift), |
| inverse); |
| } |
| |
| if(mirror_right){ |
| dst[w*dst_step] = |
| LIFT(src[w*src_step], |
| ((mul*2*ref[w*ref_step]+add)>>shift), |
| inverse); |
| } |
| } |
| |
| #ifndef liftS |
| static av_always_inline void |
| liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, |
| int dst_step, int src_step, int ref_step, |
| int width, int mul, int add, int shift, |
| int highpass, int inverse){ |
| const int mirror_left= !highpass; |
| const int mirror_right= (width&1) ^ highpass; |
| const int w= (width>>1) - 1 + (highpass & width); |
| int i; |
| |
| assert(shift == 4); |
| #define LIFTS(src, ref, inv) \ |
| ((inv) ? \ |
| (src) + (((ref) + 4*(src))>>shift): \ |
| -((-16*(src) + (ref) + add/4 + 1 + (5<<25))/(5*4) - (1<<23))) |
| if(mirror_left){ |
| dst[0] = LIFTS(src[0], mul*2*ref[0]+add, inverse); |
| dst += dst_step; |
| src += src_step; |
| } |
| |
| for(i=0; i<w; i++){ |
| dst[i*dst_step] = |
| LIFTS(src[i*src_step], |
| mul*(ref[i*ref_step] + ref[(i+1)*ref_step])+add, |
| inverse); |
| } |
| |
| if(mirror_right){ |
| dst[w*dst_step] = |
| LIFTS(src[w*src_step], mul*2*ref[w*ref_step]+add, inverse); |
| } |
| } |
| static av_always_inline void |
| inv_liftS(IDWTELEM *dst, IDWTELEM *src, IDWTELEM *ref, |
| int dst_step, int src_step, int ref_step, |
| int width, int mul, int add, int shift, |
| int highpass, int inverse){ |
| const int mirror_left= !highpass; |
| const int mirror_right= (width&1) ^ highpass; |
| const int w= (width>>1) - 1 + (highpass & width); |
| int i; |
| |
| assert(shift == 4); |
| #define LIFTS(src, ref, inv) \ |
| ((inv) ? \ |
| (src) + (((ref) + 4*(src))>>shift): \ |
| -((-16*(src) + (ref) + add/4 + 1 + (5<<25))/(5*4) - (1<<23))) |
| if(mirror_left){ |
| dst[0] = LIFTS(src[0], mul*2*ref[0]+add, inverse); |
| dst += dst_step; |
| src += src_step; |
| } |
| |
| for(i=0; i<w; i++){ |
| dst[i*dst_step] = |
| LIFTS(src[i*src_step], |
| mul*(ref[i*ref_step] + ref[(i+1)*ref_step])+add, |
| inverse); |
| } |
| |
| if(mirror_right){ |
| dst[w*dst_step] = |
| LIFTS(src[w*src_step], mul*2*ref[w*ref_step]+add, inverse); |
| } |
| } |
| #endif /* ! liftS */ |
| |
| static void horizontal_decompose53i(DWTELEM *b, int width){ |
| DWTELEM temp[width]; |
| const int width2= width>>1; |
| int x; |
| const int w2= (width+1)>>1; |
| |
| for(x=0; x<width2; x++){ |
| temp[x ]= b[2*x ]; |
| temp[x+w2]= b[2*x + 1]; |
| } |
| if(width&1) |
| temp[x ]= b[2*x ]; |
| #if 0 |
| { |
| int A1,A2,A3,A4; |
| A2= temp[1 ]; |
| A4= temp[0 ]; |
| A1= temp[0+width2]; |
| A1 -= (A2 + A4)>>1; |
| A4 += (A1 + 1)>>1; |
| b[0+width2] = A1; |
| b[0 ] = A4; |
| for(x=1; x+1<width2; x+=2){ |
| A3= temp[x+width2]; |
| A4= temp[x+1 ]; |
| A3 -= (A2 + A4)>>1; |
| A2 += (A1 + A3 + 2)>>2; |
| b[x+width2] = A3; |
| b[x ] = A2; |
| |
| A1= temp[x+1+width2]; |
| A2= temp[x+2 ]; |
| A1 -= (A2 + A4)>>1; |
| A4 += (A1 + A3 + 2)>>2; |
| b[x+1+width2] = A1; |
| b[x+1 ] = A4; |
| } |
| A3= temp[width-1]; |
| A3 -= A2; |
| A2 += (A1 + A3 + 2)>>2; |
| b[width -1] = A3; |
| b[width2-1] = A2; |
| } |
| #else |
| lift(b+w2, temp+w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 0); |
| lift(b , temp , b+w2, 1, 1, 1, width, 1, 2, 2, 0, 0); |
| #endif /* 0 */ |
| } |
| |
| static void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] -= (b0[i] + b2[i])>>1; |
| } |
| } |
| |
| static void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] += (b0[i] + b2[i] + 2)>>2; |
| } |
| } |
| |
| static void spatial_decompose53i(DWTELEM *buffer, int width, int height, int stride){ |
| int y; |
| DWTELEM *b0= buffer + mirror(-2-1, height-1)*stride; |
| DWTELEM *b1= buffer + mirror(-2 , height-1)*stride; |
| |
| for(y=-2; y<height; y+=2){ |
| DWTELEM *b2= buffer + mirror(y+1, height-1)*stride; |
| DWTELEM *b3= buffer + mirror(y+2, height-1)*stride; |
| |
| if(y+1<(unsigned)height) horizontal_decompose53i(b2, width); |
| if(y+2<(unsigned)height) horizontal_decompose53i(b3, width); |
| |
| if(y+1<(unsigned)height) vertical_decompose53iH0(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_decompose53iL0(b0, b1, b2, width); |
| |
| b0=b2; |
| b1=b3; |
| } |
| } |
| |
| static void horizontal_decompose97i(DWTELEM *b, int width){ |
| DWTELEM temp[width]; |
| const int w2= (width+1)>>1; |
| |
| lift (temp+w2, b +1, b , 1, 2, 2, width, W_AM, W_AO, W_AS, 1, 1); |
| liftS(temp , b , temp+w2, 1, 2, 1, width, W_BM, W_BO, W_BS, 0, 0); |
| lift (b +w2, temp+w2, temp , 1, 1, 1, width, W_CM, W_CO, W_CS, 1, 0); |
| lift (b , temp , b +w2, 1, 1, 1, width, W_DM, W_DO, W_DS, 0, 0); |
| } |
| |
| |
| static void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] -= (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; |
| } |
| } |
| |
| static void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] += (W_CM*(b0[i] + b2[i])+W_CO)>>W_CS; |
| } |
| } |
| |
| static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| #ifdef liftS |
| b1[i] -= (W_BM*(b0[i] + b2[i])+W_BO)>>W_BS; |
| #else |
| b1[i] = (16*4*b1[i] - 4*(b0[i] + b2[i]) + W_BO*5 + (5<<27)) / (5*16) - (1<<23); |
| #endif |
| } |
| } |
| |
| static void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] += (W_DM*(b0[i] + b2[i])+W_DO)>>W_DS; |
| } |
| } |
| |
| static void spatial_decompose97i(DWTELEM *buffer, int width, int height, int stride){ |
| int y; |
| DWTELEM *b0= buffer + mirror(-4-1, height-1)*stride; |
| DWTELEM *b1= buffer + mirror(-4 , height-1)*stride; |
| DWTELEM *b2= buffer + mirror(-4+1, height-1)*stride; |
| DWTELEM *b3= buffer + mirror(-4+2, height-1)*stride; |
| |
| for(y=-4; y<height; y+=2){ |
| DWTELEM *b4= buffer + mirror(y+3, height-1)*stride; |
| DWTELEM *b5= buffer + mirror(y+4, height-1)*stride; |
| |
| if(y+3<(unsigned)height) horizontal_decompose97i(b4, width); |
| if(y+4<(unsigned)height) horizontal_decompose97i(b5, width); |
| |
| if(y+3<(unsigned)height) vertical_decompose97iH0(b3, b4, b5, width); |
| if(y+2<(unsigned)height) vertical_decompose97iL0(b2, b3, b4, width); |
| if(y+1<(unsigned)height) vertical_decompose97iH1(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_decompose97iL1(b0, b1, b2, width); |
| |
| b0=b2; |
| b1=b3; |
| b2=b4; |
| b3=b5; |
| } |
| } |
| |
| void ff_spatial_dwt(DWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){ |
| int level; |
| |
| for(level=0; level<decomposition_count; level++){ |
| switch(type){ |
| case DWT_97: spatial_decompose97i(buffer, width>>level, height>>level, stride<<level); break; |
| case DWT_53: spatial_decompose53i(buffer, width>>level, height>>level, stride<<level); break; |
| } |
| } |
| } |
| |
| static void horizontal_compose53i(IDWTELEM *b, int width){ |
| IDWTELEM temp[width]; |
| const int width2= width>>1; |
| const int w2= (width+1)>>1; |
| int x; |
| |
| #if 0 |
| int A1,A2,A3,A4; |
| A2= temp[1 ]; |
| A4= temp[0 ]; |
| A1= temp[0+width2]; |
| A1 -= (A2 + A4)>>1; |
| A4 += (A1 + 1)>>1; |
| b[0+width2] = A1; |
| b[0 ] = A4; |
| for(x=1; x+1<width2; x+=2){ |
| A3= temp[x+width2]; |
| A4= temp[x+1 ]; |
| A3 -= (A2 + A4)>>1; |
| A2 += (A1 + A3 + 2)>>2; |
| b[x+width2] = A3; |
| b[x ] = A2; |
| |
| A1= temp[x+1+width2]; |
| A2= temp[x+2 ]; |
| A1 -= (A2 + A4)>>1; |
| A4 += (A1 + A3 + 2)>>2; |
| b[x+1+width2] = A1; |
| b[x+1 ] = A4; |
| } |
| A3= temp[width-1]; |
| A3 -= A2; |
| A2 += (A1 + A3 + 2)>>2; |
| b[width -1] = A3; |
| b[width2-1] = A2; |
| #else |
| inv_lift(temp , b , b+w2, 1, 1, 1, width, 1, 2, 2, 0, 1); |
| inv_lift(temp+w2, b+w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 1); |
| #endif /* 0 */ |
| for(x=0; x<width2; x++){ |
| b[2*x ]= temp[x ]; |
| b[2*x + 1]= temp[x+w2]; |
| } |
| if(width&1) |
| b[2*x ]= temp[x ]; |
| } |
| |
| static void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] += (b0[i] + b2[i])>>1; |
| } |
| } |
| |
| static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] -= (b0[i] + b2[i] + 2)>>2; |
| } |
| } |
| |
| static void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer * sb, int height, int stride_line){ |
| cs->b0 = slice_buffer_get_line(sb, mirror(-1-1, height-1) * stride_line); |
| cs->b1 = slice_buffer_get_line(sb, mirror(-1 , height-1) * stride_line); |
| cs->y = -1; |
| } |
| |
| static void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride){ |
| cs->b0 = buffer + mirror(-1-1, height-1)*stride; |
| cs->b1 = buffer + mirror(-1 , height-1)*stride; |
| cs->y = -1; |
| } |
| |
| static void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line){ |
| int y= cs->y; |
| |
| IDWTELEM *b0= cs->b0; |
| IDWTELEM *b1= cs->b1; |
| IDWTELEM *b2= slice_buffer_get_line(sb, mirror(y+1, height-1) * stride_line); |
| IDWTELEM *b3= slice_buffer_get_line(sb, mirror(y+2, height-1) * stride_line); |
| |
| if(y+1<(unsigned)height) vertical_compose53iL0(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_compose53iH0(b0, b1, b2, width); |
| |
| if(y-1<(unsigned)height) horizontal_compose53i(b0, width); |
| if(y+0<(unsigned)height) horizontal_compose53i(b1, width); |
| |
| cs->b0 = b2; |
| cs->b1 = b3; |
| cs->y += 2; |
| } |
| |
| static void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride){ |
| int y= cs->y; |
| IDWTELEM *b0= cs->b0; |
| IDWTELEM *b1= cs->b1; |
| IDWTELEM *b2= buffer + mirror(y+1, height-1)*stride; |
| IDWTELEM *b3= buffer + mirror(y+2, height-1)*stride; |
| |
| if(y+1<(unsigned)height) vertical_compose53iL0(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_compose53iH0(b0, b1, b2, width); |
| |
| if(y-1<(unsigned)height) horizontal_compose53i(b0, width); |
| if(y+0<(unsigned)height) horizontal_compose53i(b1, width); |
| |
| cs->b0 = b2; |
| cs->b1 = b3; |
| cs->y += 2; |
| } |
| |
| static void av_unused spatial_compose53i(IDWTELEM *buffer, int width, int height, int stride){ |
| DWTCompose cs; |
| spatial_compose53i_init(&cs, buffer, height, stride); |
| while(cs.y <= height) |
| spatial_compose53i_dy(&cs, buffer, width, height, stride); |
| } |
| |
| |
| void ff_snow_horizontal_compose97i(IDWTELEM *b, int width){ |
| IDWTELEM temp[width]; |
| const int w2= (width+1)>>1; |
| |
| inv_lift (temp , b , b +w2, 1, 1, 1, width, W_DM, W_DO, W_DS, 0, 1); |
| inv_lift (temp+w2, b +w2, temp , 1, 1, 1, width, W_CM, W_CO, W_CS, 1, 1); |
| inv_liftS(b , temp , temp+w2, 2, 1, 1, width, W_BM, W_BO, W_BS, 0, 1); |
| inv_lift (b+1 , temp+w2, b , 2, 1, 2, width, W_AM, W_AO, W_AS, 1, 0); |
| } |
| |
| static void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; |
| } |
| } |
| |
| static void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] -= (W_CM*(b0[i] + b2[i])+W_CO)>>W_CS; |
| } |
| } |
| |
| static void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| #ifdef liftS |
| b1[i] += (W_BM*(b0[i] + b2[i])+W_BO)>>W_BS; |
| #else |
| b1[i] += (W_BM*(b0[i] + b2[i])+4*b1[i]+W_BO)>>W_BS; |
| #endif |
| } |
| } |
| |
| static void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b1[i] -= (W_DM*(b0[i] + b2[i])+W_DO)>>W_DS; |
| } |
| } |
| |
| void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){ |
| int i; |
| |
| for(i=0; i<width; i++){ |
| b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS; |
| b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS; |
| #ifdef liftS |
| b2[i] += (W_BM*(b1[i] + b3[i])+W_BO)>>W_BS; |
| #else |
| b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS; |
| #endif |
| b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; |
| } |
| } |
| |
| static void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer * sb, int height, int stride_line){ |
| cs->b0 = slice_buffer_get_line(sb, mirror(-3-1, height-1) * stride_line); |
| cs->b1 = slice_buffer_get_line(sb, mirror(-3 , height-1) * stride_line); |
| cs->b2 = slice_buffer_get_line(sb, mirror(-3+1, height-1) * stride_line); |
| cs->b3 = slice_buffer_get_line(sb, mirror(-3+2, height-1) * stride_line); |
| cs->y = -3; |
| } |
| |
| static void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride){ |
| cs->b0 = buffer + mirror(-3-1, height-1)*stride; |
| cs->b1 = buffer + mirror(-3 , height-1)*stride; |
| cs->b2 = buffer + mirror(-3+1, height-1)*stride; |
| cs->b3 = buffer + mirror(-3+2, height-1)*stride; |
| cs->y = -3; |
| } |
| |
| static void spatial_compose97i_dy_buffered(DSPContext *dsp, DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line){ |
| int y = cs->y; |
| |
| IDWTELEM *b0= cs->b0; |
| IDWTELEM *b1= cs->b1; |
| IDWTELEM *b2= cs->b2; |
| IDWTELEM *b3= cs->b3; |
| IDWTELEM *b4= slice_buffer_get_line(sb, mirror(y + 3, height - 1) * stride_line); |
| IDWTELEM *b5= slice_buffer_get_line(sb, mirror(y + 4, height - 1) * stride_line); |
| |
| if(y>0 && y+4<height){ |
| dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width); |
| }else{ |
| if(y+3<(unsigned)height) vertical_compose97iL1(b3, b4, b5, width); |
| if(y+2<(unsigned)height) vertical_compose97iH1(b2, b3, b4, width); |
| if(y+1<(unsigned)height) vertical_compose97iL0(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_compose97iH0(b0, b1, b2, width); |
| } |
| |
| if(y-1<(unsigned)height) dsp->horizontal_compose97i(b0, width); |
| if(y+0<(unsigned)height) dsp->horizontal_compose97i(b1, width); |
| |
| cs->b0=b2; |
| cs->b1=b3; |
| cs->b2=b4; |
| cs->b3=b5; |
| cs->y += 2; |
| } |
| |
| static void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride){ |
| int y = cs->y; |
| IDWTELEM *b0= cs->b0; |
| IDWTELEM *b1= cs->b1; |
| IDWTELEM *b2= cs->b2; |
| IDWTELEM *b3= cs->b3; |
| IDWTELEM *b4= buffer + mirror(y+3, height-1)*stride; |
| IDWTELEM *b5= buffer + mirror(y+4, height-1)*stride; |
| |
| if(y+3<(unsigned)height) vertical_compose97iL1(b3, b4, b5, width); |
| if(y+2<(unsigned)height) vertical_compose97iH1(b2, b3, b4, width); |
| if(y+1<(unsigned)height) vertical_compose97iL0(b1, b2, b3, width); |
| if(y+0<(unsigned)height) vertical_compose97iH0(b0, b1, b2, width); |
| |
| if(y-1<(unsigned)height) ff_snow_horizontal_compose97i(b0, width); |
| if(y+0<(unsigned)height) ff_snow_horizontal_compose97i(b1, width); |
| |
| cs->b0=b2; |
| cs->b1=b3; |
| cs->b2=b4; |
| cs->b3=b5; |
| cs->y += 2; |
| } |
| |
| static void av_unused spatial_compose97i(IDWTELEM *buffer, int width, int height, int stride){ |
| DWTCompose cs; |
| spatial_compose97i_init(&cs, buffer, height, stride); |
| while(cs.y <= height) |
| spatial_compose97i_dy(&cs, buffer, width, height, stride); |
| } |
| |
| static void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line, int type, int decomposition_count){ |
| int level; |
| for(level=decomposition_count-1; level>=0; level--){ |
| switch(type){ |
| case DWT_97: spatial_compose97i_buffered_init(cs+level, sb, height>>level, stride_line<<level); break; |
| case DWT_53: spatial_compose53i_buffered_init(cs+level, sb, height>>level, stride_line<<level); break; |
| } |
| } |
| } |
| |
| static void ff_spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){ |
| int level; |
| for(level=decomposition_count-1; level>=0; level--){ |
| switch(type){ |
| case DWT_97: spatial_compose97i_init(cs+level, buffer, height>>level, stride<<level); break; |
| case DWT_53: spatial_compose53i_init(cs+level, buffer, height>>level, stride<<level); break; |
| } |
| } |
| } |
| |
| static void ff_spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count, int y){ |
| const int support = type==1 ? 3 : 5; |
| int level; |
| if(type==2) return; |
| |
| for(level=decomposition_count-1; level>=0; level--){ |
| while(cs[level].y <= FFMIN((y>>level)+support, height>>level)){ |
| switch(type){ |
| case DWT_97: spatial_compose97i_dy(cs+level, buffer, width>>level, height>>level, stride<<level); |
| break; |
| case DWT_53: spatial_compose53i_dy(cs+level, buffer, width>>level, height>>level, stride<<level); |
| break; |
| } |
| } |
| } |
| } |
| |
| static void ff_spatial_idwt_buffered_slice(DSPContext *dsp, DWTCompose *cs, slice_buffer * slice_buf, int width, int height, int stride_line, int type, int decomposition_count, int y){ |
| const int support = type==1 ? 3 : 5; |
| int level; |
| if(type==2) return; |
| |
| for(level=decomposition_count-1; level>=0; level--){ |
| while(cs[level].y <= FFMIN((y>>level)+support, height>>level)){ |
| switch(type){ |
| case DWT_97: spatial_compose97i_dy_buffered(dsp, cs+level, slice_buf, width>>level, height>>level, stride_line<<level); |
| break; |
| case DWT_53: spatial_compose53i_dy_buffered(cs+level, slice_buf, width>>level, height>>level, stride_line<<level); |
| break; |
| } |
| } |
| } |
| } |
| |
| static void ff_spatial_idwt(IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){ |
| DWTCompose cs[MAX_DECOMPOSITIONS]; |
| int y; |
| ff_spatial_idwt_init(cs, buffer, width, height, stride, type, decomposition_count); |
| for(y=0; y<height; y+=4) |
| ff_spatial_idwt_slice(cs, buffer, width, height, stride, type, decomposition_count, y); |
| } |
| |
| static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){ |
| const int w= b->width; |
| const int h= b->height; |
| int x, y; |
| |
| if(1){ |
| int run=0; |
| int runs[w*h]; |
| int run_index=0; |
| int max_index; |
| |
| for(y=0; y<h; y++){ |
| for(x=0; x<w; x++){ |
| int v, p=0; |
| int /*ll=0, */l=0, lt=0, t=0, rt=0; |
| v= src[x + y*stride]; |
| |
| if(y){ |
| t= src[x + (y-1)*stride]; |
| if(x){ |
| lt= src[x - 1 + (y-1)*stride]; |
| } |
| if(x + 1 < w){ |
| rt= src[x + 1 + (y-1)*stride]; |
| } |
| } |
| if(x){ |
| l= src[x - 1 + y*stride]; |
| /*if(x > 1){ |
| if(orientation==1) ll= src[y + (x-2)*stride]; |
| else ll= src[x - 2 + y*stride]; |
| }*/ |
| } |
| if(parent){ |
| int px= x>>1; |
| int py= y>>1; |
| if(px<b->parent->width && py<b->parent->height) |
| p= parent[px + py*2*stride]; |
| } |
| if(!(/*ll|*/l|lt|t|rt|p)){ |
| if(v){ |
| runs[run_index++]= run; |
| run=0; |
| }else{ |
| run++; |
| } |
| } |
| } |
| } |
| max_index= run_index; |
| runs[run_index++]= run; |
| run_index=0; |
| run= runs[run_index++]; |
| |
| put_symbol2(&s->c, b->state[30], max_index, 0); |
| if(run_index <= max_index) |
| put_symbol2(&s->c, b->state[1], run, 3); |
| |
| for(y=0; y<h; y++){ |
| if(s->c.bytestream_end - s->c.bytestream < w*40){ |
| av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
| return -1; |
| } |
| for(x=0; x<w; x++){ |
| int v, p=0; |
| int /*ll=0, */l=0, lt=0, t=0, rt=0; |
| v= src[x + y*stride]; |
| |
| if(y){ |
| t= src[x + (y-1)*stride]; |
| if(x){ |
| lt= src[x - 1 + (y-1)*stride]; |
| } |
| if(x + 1 < w){ |
| rt= src[x + 1 + (y-1)*stride]; |
| } |
| } |
| if(x){ |
| l= src[x - 1 + y*stride]; |
| /*if(x > 1){ |
| if(orientation==1) ll= src[y + (x-2)*stride]; |
| else ll= src[x - 2 + y*stride]; |
| }*/ |
| } |
| if(parent){ |
| int px= x>>1; |
| int py= y>>1; |
| if(px<b->parent->width && py<b->parent->height) |
| p= parent[px + py*2*stride]; |
| } |
| if(/*ll|*/l|lt|t|rt|p){ |
| int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); |
| |
| put_rac(&s->c, &b->state[0][context], !!v); |
| }else{ |
| if(!run){ |
| run= runs[run_index++]; |
| |
| if(run_index <= max_index) |
| put_symbol2(&s->c, b->state[1], run, 3); |
| assert(v); |
| }else{ |
| run--; |
| assert(!v); |
| } |
| } |
| if(v){ |
| int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); |
| int l2= 2*FFABS(l) + (l<0); |
| int t2= 2*FFABS(t) + (t<0); |
| |
| put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4); |
| put_rac(&s->c, &b->state[0][16 + 1 + 3 + quant3bA[l2&0xFF] + 3*quant3bA[t2&0xFF]], v<0); |
| } |
| } |
| } |
| } |
| return 0; |
| } |
| |
| static int encode_subband(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){ |
| // encode_subband_qtree(s, b, src, parent, stride, orientation); |
| // encode_subband_z0run(s, b, src, parent, stride, orientation); |
| return encode_subband_c0run(s, b, src, parent, stride, orientation); |
| // encode_subband_dzr(s, b, src, parent, stride, orientation); |
| } |
| |
| static inline void unpack_coeffs(SnowContext *s, SubBand *b, SubBand * parent, int orientation){ |
| const int w= b->width; |
| const int h= b->height; |
| int x,y; |
| |
| if(1){ |
| int run, runs; |
| x_and_coeff *xc= b->x_coeff; |
| x_and_coeff *prev_xc= NULL; |
| x_and_coeff *prev2_xc= xc; |
| x_and_coeff *parent_xc= parent ? parent->x_coeff : NULL; |
| x_and_coeff *prev_parent_xc= parent_xc; |
| |
| runs= get_symbol2(&s->c, b->state[30], 0); |
| if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3); |
| else run= INT_MAX; |
| |
| for(y=0; y<h; y++){ |
| int v=0; |
| int lt=0, t=0, rt=0; |
| |
| if(y && prev_xc->x == 0){ |
| rt= prev_xc->coeff; |
| } |
| for(x=0; x<w; x++){ |
| int p=0; |
| const int l= v; |
| |
| lt= t; t= rt; |
| |
| if(y){ |
| if(prev_xc->x <= x) |
| prev_xc++; |
| if(prev_xc->x == x + 1) |
| rt= prev_xc->coeff; |
| else |
| rt=0; |
| } |
| if(parent_xc){ |
| if(x>>1 > parent_xc->x){ |
| parent_xc++; |
| } |
| if(x>>1 == parent_xc->x){ |
| p= parent_xc->coeff; |
| } |
| } |
| if(/*ll|*/l|lt|t|rt|p){ |
| int context= av_log2(/*FFABS(ll) + */3*(l>>1) + (lt>>1) + (t&~1) + (rt>>1) + (p>>1)); |
| |
| v=get_rac(&s->c, &b->state[0][context]); |
| if(v){ |
| v= 2*(get_symbol2(&s->c, b->state[context + 2], context-4) + 1); |
| v+=get_rac(&s->c, &b->state[0][16 + 1 + 3 + quant3bA[l&0xFF] + 3*quant3bA[t&0xFF]]); |
| |
| xc->x=x; |
| (xc++)->coeff= v; |
| } |
| }else{ |
| if(!run){ |
| if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3); |
| else run= INT_MAX; |
| v= 2*(get_symbol2(&s->c, b->state[0 + 2], 0-4) + 1); |
| v+=get_rac(&s->c, &b->state[0][16 + 1 + 3]); |
| |
| xc->x=x; |
| (xc++)->coeff= v; |
| }else{ |
| int max_run; |
| run--; |
| v=0; |
| |
| if(y) max_run= FFMIN(run, prev_xc->x - x - 2); |
| else max_run= FFMIN(run, w-x-1); |
| if(parent_xc) |
| max_run= FFMIN(max_run, 2*parent_xc->x - x - 1); |
| x+= max_run; |
| run-= max_run; |
| } |
| } |
| } |
| (xc++)->x= w+1; //end marker |
| prev_xc= prev2_xc; |
| prev2_xc= xc; |
| |
| if(parent_xc){ |
| if(y&1){ |
| while(parent_xc->x != parent->width+1) |
| parent_xc++; |
| parent_xc++; |
| prev_parent_xc= parent_xc; |
| }else{ |
| parent_xc= prev_parent_xc; |
| } |
| } |
| } |
| |
| (xc++)->x= w+1; //end marker |
| } |
| } |
| |
| static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){ |
| const int w= b->width; |
| int y; |
| const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); |
| int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); |
| int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; |
| int new_index = 0; |
| |
| if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){ |
| qadd= 0; |
| qmul= 1<<QEXPSHIFT; |
| } |
| |
| /* If we are on the second or later slice, restore our index. */ |
| if (start_y != 0) |
| new_index = save_state[0]; |
| |
| |
| for(y=start_y; y<h; y++){ |
| int x = 0; |
| int v; |
| IDWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset; |
| memset(line, 0, b->width*sizeof(IDWTELEM)); |
| v = b->x_coeff[new_index].coeff; |
| x = b->x_coeff[new_index++].x; |
| while(x < w){ |
| register int t= ( (v>>1)*qmul + qadd)>>QEXPSHIFT; |
| register int u= -(v&1); |
| line[x] = (t^u) - u; |
| |
| v = b->x_coeff[new_index].coeff; |
| x = b->x_coeff[new_index++].x; |
| } |
| } |
| |
| /* Save our variables for the next slice. */ |
| save_state[0] = new_index; |
| |
| return; |
| } |
| |
| static void reset_contexts(SnowContext *s){ //FIXME better initial contexts |
| int plane_index, level, orientation; |
| |
| for(plane_index=0; plane_index<3; plane_index++){ |
| for(level=0; level<MAX_DECOMPOSITIONS; level++){ |
| for(orientation=level ? 1:0; orientation<4; orientation++){ |
| memset(s->plane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state)); |
| } |
| } |
| } |
| memset(s->header_state, MID_STATE, sizeof(s->header_state)); |
| memset(s->block_state, MID_STATE, sizeof(s->block_state)); |
| } |
| |
| static int alloc_blocks(SnowContext *s){ |
| int w= -((-s->avctx->width )>>LOG2_MB_SIZE); |
| int h= -((-s->avctx->height)>>LOG2_MB_SIZE); |
| |
| s->b_width = w; |
| s->b_height= h; |
| |
| av_free(s->block); |
| s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2)); |
| return 0; |
| } |
| |
| static inline void copy_rac_state(RangeCoder *d, RangeCoder *s){ |
| uint8_t *bytestream= d->bytestream; |
| uint8_t *bytestream_start= d->bytestream_start; |
| *d= *s; |
| d->bytestream= bytestream; |
| d->bytestream_start= bytestream_start; |
| } |
| |
| //near copy & paste from dsputil, FIXME |
| static int pix_sum(uint8_t * pix, int line_size, int w) |
| { |
| int s, i, j; |
| |
| s = 0; |
| for (i = 0; i < w; i++) { |
| for (j = 0; j < w; j++) { |
| s += pix[0]; |
| pix ++; |
| } |
| pix += line_size - w; |
| } |
| return s; |
| } |
| |
| //near copy & paste from dsputil, FIXME |
| static int pix_norm1(uint8_t * pix, int line_size |