summaryrefslogtreecommitdiff
path: root/libavcodec/snowenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/snowenc.c')
-rw-r--r--libavcodec/snowenc.c159
1 files changed, 143 insertions, 16 deletions
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 7e3b68fb8a..c853a34c6c 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 */