diff options
Diffstat (limited to 'libavcodec/snowenc.c')
-rw-r--r-- | libavcodec/snowenc.c | 159 |
1 files changed, 143 insertions, 16 deletions
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 7b010e1..7091960 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -1,20 +1,20 @@ /* * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -22,6 +22,7 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "internal.h" #include "dsputil.h" #include "dwt.h" #include "snow.h" @@ -217,7 +218,7 @@ static av_cold int encode_init(AVCodecContext *avctx) // case PIX_FMT_YUV444P: // case PIX_FMT_YUV422P: case PIX_FMT_YUV420P: - case PIX_FMT_GRAY8: +// case PIX_FMT_GRAY8: // case PIX_FMT_YUV411P: // case PIX_FMT_YUV410P: s->colorspace_type= 0; @@ -247,6 +248,8 @@ static av_cold int encode_init(AVCodecContext *avctx) } } + s->runs = av_malloc(avctx->width * avctx->height * sizeof(*s->runs)); + return 0; } @@ -826,14 +829,13 @@ static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){ return distortion + rate*penalty_factor; } -static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){ +static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const 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; @@ -867,7 +869,7 @@ static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTE } if(!(/*ll|*/l|lt|t|rt|p)){ if(v){ - runs[run_index++]= run; + s->runs[run_index++]= run; run=0; }else{ run++; @@ -876,9 +878,9 @@ static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTE } } max_index= run_index; - runs[run_index++]= run; + s->runs[run_index++]= run; run_index=0; - run= runs[run_index++]; + run= s->runs[run_index++]; put_symbol2(&s->c, b->state[30], max_index, 0); if(run_index <= max_index) @@ -922,7 +924,7 @@ static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTE put_rac(&s->c, &b->state[0][context], !!v); }else{ if(!run){ - run= runs[run_index++]; + run= s->runs[run_index++]; if(run_index <= max_index) put_symbol2(&s->c, b->state[1], run, 3); @@ -946,7 +948,7 @@ static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTE return 0; } -static int encode_subband(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){ +static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const 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); @@ -1611,11 +1613,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, uint8_t rc_header_bak[sizeof(s->header_state)]; uint8_t rc_block_bak[sizeof(s->block_state)]; - if (!pkt->data && - (ret = av_new_packet(pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + FF_MIN_BUFFER_SIZE)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + if ((ret = ff_alloc_packet2(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + FF_MIN_BUFFER_SIZE)) < 0) return ret; - } ff_init_range_encoder(c, pkt->data, pkt->size); ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); @@ -1713,6 +1712,10 @@ redo_frame: else s->spatial_decomposition_count= 5; + while( !(width >>(s->chroma_h_shift + s->spatial_decomposition_count)) + || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count))) + s->spatial_decomposition_count--; + s->m.pict_type = pic->pict_type; s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0; @@ -1799,6 +1802,7 @@ redo_frame: quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias); if(orientation==0) decorrelate(s, b, b->ibuf, b->stride, pic->pict_type == AV_PICTURE_TYPE_P, 0); + if (!s->no_bitstream) encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation); assert(b->parent==NULL || b->parent->stride == b->stride*2); if(orientation==0) @@ -1895,6 +1899,7 @@ static av_cold int encode_end(AVCodecContext *avctx) if (s->input_picture.data[0]) avctx->release_buffer(avctx, &s->input_picture); av_free(avctx->stats_out); + av_freep(&s->runs); return 0; } @@ -1903,6 +1908,7 @@ static av_cold int encode_end(AVCodecContext *avctx) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "memc_only", "Only do ME/MC (I frames -> ref, P frame -> ME+MC).", OFFSET(memc_only), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE }, + { "no_bitstream", "Skip final bitstream writeout.", OFFSET(no_bitstream), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE }, { NULL }, }; @@ -1924,3 +1930,124 @@ AVCodec ff_snow_encoder = { .long_name = NULL_IF_CONFIG_SMALL("Snow"), .priv_class = &snowenc_class, }; + + +#ifdef TEST +#undef malloc +#undef free +#undef printf + +#include "libavutil/lfg.h" +#include "libavutil/mathematics.h" + +int main(void){ + int width=256; + int height=256; + int buffer[2][width*height]; + SnowContext s; + int i; + AVLFG prng; + s.spatial_decomposition_count=6; + s.spatial_decomposition_type=1; + + av_lfg_init(&prng, 1); + + printf("testing 5/3 DWT\n"); + for(i=0; i<width*height; i++) + buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345; + + ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + ff_spatial_idwt((IDWTELEM*)buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + + for(i=0; i<width*height; i++) + if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + + printf("testing 9/7 DWT\n"); + s.spatial_decomposition_type=0; + for(i=0; i<width*height; i++) + buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345; + + ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + ff_spatial_idwt((IDWTELEM*)buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + + for(i=0; i<width*height; i++) + if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + + { + int level, orientation, x, y; + int64_t errors[8][4]; + int64_t g=0; + + memset(errors, 0, sizeof(errors)); + s.spatial_decomposition_count=3; + s.spatial_decomposition_type=0; + for(level=0; level<s.spatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + int w= width >> (s.spatial_decomposition_count-level); + int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + if(orientation&1) buf+=w; + if(orientation>1) buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + buf[w/2 + h/2*stride]= 256*256; + ff_spatial_idwt((IDWTELEM*)buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int64_t d= buffer[0][x + y*width]; + error += d*d; + if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d); + } + if(FFABS(height/2-y)<9 && level==2) printf("\n"); + } + error= (int)(sqrt(error)+0.5); + errors[level][orientation]= error; + if(g) g=av_gcd(g, error); + else g= error; + } + } + printf("static int const visual_weight[][4]={\n"); + for(level=0; level<s.spatial_decomposition_count; level++){ + printf(" {"); + for(orientation=0; orientation<4; orientation++){ + printf("%8"PRId64",", errors[level][orientation]/g); + } + printf("},\n"); + } + printf("};\n"); + { + int level=2; + int w= width >> (s.spatial_decomposition_count-level); + //int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + buf+=w; + buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int tab[4]={0,2,3,1}; + buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)]; + } + } + ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int64_t d= buffer[0][x + y*width]; + error += d*d; + if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d); + } + if(FFABS(height/2-y)<9) printf("\n"); + } + } + + } + return 0; +} +#endif /* TEST */ |