diff options
Diffstat (limited to 'src')
37 files changed, 2553 insertions, 729 deletions
diff --git a/src/libffmpeg/libavcodec/4xm.c b/src/libffmpeg/libavcodec/4xm.c index 6544d88d0..50dc4a55b 100644 --- a/src/libffmpeg/libavcodec/4xm.c +++ b/src/libffmpeg/libavcodec/4xm.c @@ -738,8 +738,6 @@ static int decode_end(AVCodecContext *avctx){ } free_vlc(&f->pre_vlc); - avcodec_default_free_buffers(avctx); - return 0; } diff --git a/src/libffmpeg/libavcodec/Makefile.am b/src/libffmpeg/libavcodec/Makefile.am index 7bbcbd281..8b3a7f634 100644 --- a/src/libffmpeg/libavcodec/Makefile.am +++ b/src/libffmpeg/libavcodec/Makefile.am @@ -36,6 +36,7 @@ libavcodec_la_SOURCES = \ idcinvideo.c \ imgconvert.c \ indeo3.c \ + integer.c \ interplayvideo.c \ jfdctfst.c \ jfdctint.c \ @@ -53,6 +54,7 @@ libavcodec_la_SOURCES = \ msrle.c \ msvideo1.c \ opts.c \ + parser.c \ pcm.c \ qtrle.c \ ra144.c \ @@ -96,6 +98,7 @@ noinst_HEADERS = \ golomb.h \ imgconvert_template.h \ indeo3data.h \ + integer.h \ h263data.h \ h264data.h \ mangle.h \ diff --git a/src/libffmpeg/libavcodec/asv1.c b/src/libffmpeg/libavcodec/asv1.c index 87b13c637..24916590f 100644 --- a/src/libffmpeg/libavcodec/asv1.c +++ b/src/libffmpeg/libavcodec/asv1.c @@ -613,8 +613,6 @@ static int decode_end(AVCodecContext *avctx){ av_freep(&a->picture.qscale_table); a->bitstream_buffer_size=0; - avcodec_default_free_buffers(avctx); - return 0; } diff --git a/src/libffmpeg/libavcodec/avcodec.h b/src/libffmpeg/libavcodec/avcodec.h index 731bcd375..d071e0891 100644 --- a/src/libffmpeg/libavcodec/avcodec.h +++ b/src/libffmpeg/libavcodec/avcodec.h @@ -24,7 +24,7 @@ extern "C" { #define FFMPEG_VERSION_INT 0x000408 #define FFMPEG_VERSION "0.4.8" -#define LIBAVCODEC_BUILD 4710 +#define LIBAVCODEC_BUILD 4713 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION FFMPEG_VERSION @@ -848,6 +848,7 @@ typedef struct AVCodecContext { #define FF_BUG_XVID_ILACE 4 #define FF_BUG_UMP4 8 #define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 #define FF_BUG_AC_VLC 0 ///< will be removed, libavcodec can now handle these non compliant files by default #define FF_BUG_QPEL_CHROMA 64 #define FF_BUG_STD_QPEL 128 @@ -855,6 +856,7 @@ typedef struct AVCodecContext { #define FF_BUG_DIRECT_BLOCKSIZE 512 #define FF_BUG_EDGE 1024 #define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 //#define FF_BUG_FAKE_SCALABILITY 16 //autodetection should work 100% /** @@ -1591,6 +1593,13 @@ typedef struct AVCodecContext { * - decoding: unused */ int mb_threshold; + + /** + * + * - encoding: set by user + * - decoding: unused + */ + int intra_dc_precision; } AVCodecContext; @@ -1717,6 +1726,7 @@ extern AVCodec vcr1_encoder; extern AVCodec ffv1_encoder; extern AVCodec mdec_encoder; extern AVCodec zlib_encoder; +extern AVCodec svq1_encoder; extern AVCodec h263_decoder; extern AVCodec mpeg4_decoder; @@ -1934,7 +1944,6 @@ AVFrame *avcodec_alloc_frame(void); int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); -void avcodec_default_free_buffers(AVCodecContext *s); int avcodec_thread_init(AVCodecContext *s, int thread_count); void avcodec_thread_free(AVCodecContext *s); @@ -1986,7 +1995,7 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max) * rescale a 64bit integer. * a simple a*b/c isnt possible as it can overflow */ -int64_t av_rescale(int64_t a, int b, int c); +int64_t av_rescale(int64_t a, int64_t b, int64_t c); /** diff --git a/src/libffmpeg/libavcodec/cinepak.c b/src/libffmpeg/libavcodec/cinepak.c index 412db7f7e..da9a8127f 100644 --- a/src/libffmpeg/libavcodec/cinepak.c +++ b/src/libffmpeg/libavcodec/cinepak.c @@ -57,7 +57,6 @@ typedef struct CinepakContext { AVCodecContext *avctx; DSPContext dsp; AVFrame frame; - AVFrame prev_frame; unsigned char *data; int size; @@ -125,7 +124,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, uint8_t *eod = (data + size); uint32_t flag, mask; cvid_codebook_t *codebook; - unsigned int i, j, x, y; + unsigned int x, y; uint32_t iy[4]; uint32_t iu[2]; uint32_t iv[2]; @@ -250,22 +249,6 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, } } - } else { - /* copy from the previous frame */ - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - s->frame.data[0][iy[i] + j] = - s->prev_frame.data[0][iy[i] + j]; - } - } - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - s->frame.data[1][iu[i] + j] = - s->prev_frame.data[1][iu[i] + j]; - s->frame.data[2][iv[i] + j] = - s->prev_frame.data[2][iv[i] + j]; - } - } } iy[0] += 4; iy[1] += 4; @@ -397,7 +380,7 @@ s->palette_video = 0; avctx->has_b_frames = 0; dsputil_init(&s->dsp, avctx); - s->frame.data[0] = s->prev_frame.data[0] = NULL; + s->frame.data[0] = NULL; return 0; } @@ -411,19 +394,16 @@ static int cinepak_decode_frame(AVCodecContext *avctx, s->data = buf; s->size = buf_size; - if (avctx->get_buffer(avctx, &s->frame)) { - av_log(avctx, AV_LOG_ERROR, " Cinepak: get_buffer() failed\n"); + s->frame.reference = 1; + s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | + FF_BUFFER_HINTS_REUSABLE; + if (avctx->reget_buffer(avctx, &s->frame)) { + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return -1; } cinepak_decode(s); - if (s->prev_frame.data[0]) - avctx->release_buffer(avctx, &s->prev_frame); - - /* shuffle frames */ - s->prev_frame = s->frame; - *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; @@ -435,8 +415,8 @@ static int cinepak_decode_end(AVCodecContext *avctx) { CinepakContext *s = (CinepakContext *)avctx->priv_data; - if (s->prev_frame.data[0]) - avctx->release_buffer(avctx, &s->prev_frame); + if (s->frame.data[0]) + avctx->release_buffer(avctx, &s->frame); return 0; } diff --git a/src/libffmpeg/libavcodec/common.h b/src/libffmpeg/libavcodec/common.h index de9382a13..b6fdcdd6e 100644 --- a/src/libffmpeg/libavcodec/common.h +++ b/src/libffmpeg/libavcodec/common.h @@ -81,17 +81,21 @@ extern const struct AVOption avoptions_workaround_bug[11]; # define restrict #endif +#ifndef always_inline #if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) # define always_inline __attribute__((always_inline)) inline #else # define always_inline inline #endif +#endif +#ifndef attribute_used #if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) # define attribute_used __attribute__((used)) #else # define attribute_used #endif +#endif #ifndef EMULATE_INTTYPES # include <inttypes.h> diff --git a/src/libffmpeg/libavcodec/cyuv.c b/src/libffmpeg/libavcodec/cyuv.c index 70b55066a..aee2bc5ec 100644 --- a/src/libffmpeg/libavcodec/cyuv.c +++ b/src/libffmpeg/libavcodec/cyuv.c @@ -100,6 +100,7 @@ static int cyuv_decode_frame(AVCodecContext *avctx, if(s->frame.data[0]) avctx->release_buffer(avctx, &s->frame); + s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; s->frame.reference = 0; if(avctx->get_buffer(avctx, &s->frame) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); @@ -180,7 +181,7 @@ AVCodec cyuv_decoder = { NULL, cyuv_decode_end, cyuv_decode_frame, - 0, + CODEC_CAP_DR1, NULL }; diff --git a/src/libffmpeg/libavcodec/dsputil.c b/src/libffmpeg/libavcodec/dsputil.c index fce0b8163..b1252251a 100644 --- a/src/libffmpeg/libavcodec/dsputil.c +++ b/src/libffmpeg/libavcodec/dsputil.c @@ -332,6 +332,27 @@ static void put_pixels_clamped_c(const DCTELEM *block, uint8_t *restrict pixels, } } +static void put_signed_pixels_clamped_c(const DCTELEM *block, + uint8_t *restrict pixels, + int line_size) +{ + int i, j; + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + if (*block < -128) + *pixels = 0; + else if (*block > 127) + *pixels = 255; + else + *pixels = (uint8_t)(*block + 128); + block++; + pixels++; + } + pixels += (line_size - 8); + } +} + static void add_pixels_clamped_c(const DCTELEM *block, uint8_t *restrict pixels, int line_size) { @@ -3126,12 +3147,12 @@ void dsputil_init(DSPContext* c, AVCodecContext *avctx) /* VP3 DSP support */ c->vp3_dsp_init = vp3_dsp_init_c; - c->vp3_idct_put = vp3_idct_put_c; - c->vp3_idct_add = vp3_idct_add_c; + c->vp3_idct = vp3_idct_c; c->get_pixels = get_pixels_c; c->diff_pixels = diff_pixels_c; c->put_pixels_clamped = put_pixels_clamped_c; + c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; c->add_pixels_clamped = add_pixels_clamped_c; c->gmc1 = gmc1_c; c->gmc = gmc_c; diff --git a/src/libffmpeg/libavcodec/dsputil.h b/src/libffmpeg/libavcodec/dsputil.h index 730e1489d..83c0c4b23 100644 --- a/src/libffmpeg/libavcodec/dsputil.h +++ b/src/libffmpeg/libavcodec/dsputil.h @@ -65,23 +65,16 @@ extern uint8_t cropTbl[256 + 2 * MAX_NEG_CROP]; /* VP3 DSP functions */ void vp3_dsp_init_c(void); -void vp3_idct_put_c(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); -void vp3_idct_add_c(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); +void vp3_idct_c(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, DCTELEM *output_data); void vp3_dsp_init_mmx(void); -void vp3_idct_put_mmx(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); -void vp3_idct_add_mmx(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); +void vp3_idct_mmx(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, DCTELEM *output_data); void vp3_dsp_init_sse2(void); -void vp3_idct_put_sse2(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); -void vp3_idct_add_sse2(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); - +void vp3_idct_sse2(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, DCTELEM *output_data); /* minimum alignment rules ;) if u notice errors in the align stuff, need more alignment for some asm code for some cpu @@ -147,6 +140,7 @@ typedef struct DSPContext { void (*get_pixels)(DCTELEM *block/*align 16*/, const uint8_t *pixels/*align 8*/, int line_size); void (*diff_pixels)(DCTELEM *block/*align 16*/, const uint8_t *s1/*align 8*/, const uint8_t *s2/*align 8*/, int stride); void (*put_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*put_signed_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); void (*add_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); /** * translational global motion compensation. @@ -321,32 +315,16 @@ typedef struct DSPContext { /** * This function is responsible for taking a block of zigzag'd, - * quantized DCT coefficients, reconstructing the original block of - * samples, and placing it into the output. - * @param input_data 64 zigzag'd, quantized DCT coefficients - * @param dequant_matrix 64 zigzag'd quantizer coefficients - * @param coeff_count index of the last coefficient - * @param dest the final output location where the transformed samples - * are to be placed - * @param stride the width in 8-bit samples of a line on this plane - */ - void (*vp3_idct_put)(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); - - /** - * This function is responsible for taking a block of zigzag'd, - * quantized DCT coefficients, reconstructing the original block of - * samples, and adding the transformed samples to an existing block of - * samples in the output. + * quantized DCT coefficients and reconstructing the original block of + * samples. * @param input_data 64 zigzag'd, quantized DCT coefficients * @param dequant_matrix 64 zigzag'd quantizer coefficients * @param coeff_count index of the last coefficient - * @param dest the final output location where the transformed samples - * are to be placed - * @param stride the width in 8-bit samples of a line on this plane + * @param output_samples space for 64 DCTELEMs where the transformed + * samples will be stored */ - void (*vp3_idct_add)(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride); + void (*vp3_idct)(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, DCTELEM *output_samples); } DSPContext; @@ -400,6 +378,7 @@ extern int mm_flags; void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size); void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size); +void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size); static inline void emms(void) { diff --git a/src/libffmpeg/libavcodec/dv.c b/src/libffmpeg/libavcodec/dv.c index 5f1eaaa3b..c62c964fb 100644 --- a/src/libffmpeg/libavcodec/dv.c +++ b/src/libffmpeg/libavcodec/dv.c @@ -235,12 +235,6 @@ static int dvvideo_init(AVCodecContext *avctx) return 0; } -static int dvvideo_end(AVCodecContext *avctx) -{ - avcodec_default_free_buffers(avctx); - return 0; -} - // #define VLC_DEBUG // #define printf(...) av_log(NULL, AV_LOG_ERROR, __VA_ARGS__) @@ -954,7 +948,7 @@ AVCodec dvvideo_encoder = { sizeof(DVVideoContext), dvvideo_init, dvvideo_encode_frame, - dvvideo_end, + NULL, NULL, CODEC_CAP_DR1, NULL @@ -967,7 +961,7 @@ AVCodec dvvideo_decoder = { sizeof(DVVideoContext), dvvideo_init, NULL, - dvvideo_end, + NULL, dvvideo_decode_frame, CODEC_CAP_DR1, NULL diff --git a/src/libffmpeg/libavcodec/h263.c b/src/libffmpeg/libavcodec/h263.c index ec776eb98..59d746272 100644 --- a/src/libffmpeg/libavcodec/h263.c +++ b/src/libffmpeg/libavcodec/h263.c @@ -76,7 +76,7 @@ static void mpeg4_encode_visual_object_header(MpegEncContext * s); static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number); #endif //CONFIG_ENCODERS static void mpeg4_decode_sprite_trajectory(MpegEncContext * s, GetBitContext *gb); -static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, uint16_t **dc_val_ptr, int *dir_ptr); +static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, int level, int *dir_ptr, int encoding); #ifdef CONFIG_ENCODERS static uint8_t uni_DCtab_lum_len[512]; @@ -496,6 +496,17 @@ void ff_clean_h263_qscales(MpegEncContext *s){ if(qscale_table[ s->mb_index2xy[i] ] - qscale_table[ s->mb_index2xy[i+1] ] >2) qscale_table[ s->mb_index2xy[i] ]= qscale_table[ s->mb_index2xy[i+1] ]+2; } + + if(s->codec_id != CODEC_ID_H263P){ + for(i=1; i<s->mb_num; i++){ + int mb_xy= s->mb_index2xy[i]; + + if(qscale_table[mb_xy] != qscale_table[s->mb_index2xy[i-1]] && (s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTER4V)){ + s->mb_type[mb_xy]&= ~CANDIDATE_MB_TYPE_INTER4V; + s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_INTER; + } + } + } } /** @@ -507,15 +518,6 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s){ ff_clean_h263_qscales(s); - for(i=1; i<s->mb_num; i++){ - int mb_xy= s->mb_index2xy[i]; - - if(qscale_table[mb_xy] != qscale_table[s->mb_index2xy[i-1]] && (s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTER4V)){ - s->mb_type[mb_xy]&= ~CANDIDATE_MB_TYPE_INTER4V; - s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_INTER; - } - } - if(s->pict_type== B_TYPE){ int odd=0; /* ok, come on, this isnt funny anymore, theres more code for handling this mpeg4 mess than @@ -1071,15 +1073,7 @@ void mpeg4_encode_mb(MpegEncContext * s, int i; for(i=0; i<6; i++){ - const int level= block[i][0]; - uint16_t *dc_ptr; - - dc_diff[i]= level - ff_mpeg4_pred_dc(s, i, &dc_ptr, &dir[i]); - if (i < 4) { - *dc_ptr = level * s->y_dc_scale; - } else { - *dc_ptr = level * s->c_dc_scale; - } + dc_diff[i]= ff_mpeg4_pred_dc(s, i, block[i][0], &dir[i], 1); } if(s->flags & CODEC_FLAG_AC_PRED){ @@ -2380,14 +2374,14 @@ void ff_set_qscale(MpegEncContext * s, int qscale) /** * predicts the dc. + * encoding quantized level -> quantized diff + * decoding quantized diff -> quantized level * @param n block index (0-3 are luma, 4-5 are chroma) - * @param dc_val_ptr a pointer to the dc_val entry for the current MB will be stored here * @param dir_ptr pointer to an integer where the prediction direction will be stored - * @return the quantized predicted dc */ -static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, uint16_t **dc_val_ptr, int *dir_ptr) +static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, int level, int *dir_ptr, int encoding) { - int a, b, c, wrap, pred, scale; + int a, b, c, wrap, pred, scale, ret; uint16_t *dc_val; /* find prediction */ @@ -2429,10 +2423,32 @@ static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, uint16_t **dc_val_ /* we assume pred is positive */ pred = FASTDIV((pred + (scale >> 1)), scale); - /* prepare address for prediction update */ - *dc_val_ptr = &dc_val[0]; + if(encoding){ + ret = level - pred; + }else{ + level += pred; + ret= level; + if(s->error_resilience>=3){ + if(level<0){ + av_log(s->avctx, AV_LOG_ERROR, "dc<0 at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + if(level*scale > 2048 + scale){ + av_log(s->avctx, AV_LOG_ERROR, "dc overflow at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + } + } + level *=scale; + if(level&(~2047)){ + if(level<0) + level=0; + else if(!(s->workaround_bugs&FF_BUG_DC_CLIP)) + level=2047; + } + dc_val[0]= level; - return pred; + return ret; } /** @@ -3219,6 +3235,9 @@ static inline int get_amv(MpegEncContext *s, int n){ int x, y, mb_v, sum, dx, dy, shift; int len = 1 << (s->f_code + 4); const int a= s->sprite_warping_accuracy; + + if(s->workaround_bugs & FF_BUG_AMV) + len >>= s->quarter_sample; if(s->real_sprite_warping_points==1){ if(s->divx_version==500 && s->divx_build==413) @@ -4433,6 +4452,8 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, } } else { level = get_bits(&s->gb, 8); + if (level == 255) + level = 128; } }else{ level = get_bits(&s->gb, 8); @@ -4530,8 +4551,7 @@ not_coded: */ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) { - int level, pred, code; - uint16_t *dc_val; + int level, code; if (n < 4) code = get_vlc2(&s->gb, dc_lum.table, DC_VLC_BITS, 1); @@ -4566,30 +4586,8 @@ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) } } } - pred = ff_mpeg4_pred_dc(s, n, &dc_val, dir_ptr); - level += pred; - if (level < 0){ - if(s->error_resilience>=3){ - av_log(s->avctx, AV_LOG_ERROR, "dc<0 at %dx%d\n", s->mb_x, s->mb_y); - return -1; - } - level = 0; - } - if (n < 4) { - *dc_val = level * s->y_dc_scale; - } else { - *dc_val = level * s->c_dc_scale; - } - if(IS_3IV1) - *dc_val = level * 8; - - if(s->error_resilience>=3){ - if(*dc_val > 2048 + s->y_dc_scale + s->c_dc_scale){ - av_log(s->avctx, AV_LOG_ERROR, "dc overflow at %dx%d\n", s->mb_x, s->mb_y); - return -1; - } - } - return level; + + return ff_mpeg4_pred_dc(s, n, level, dir_ptr, 0); } /** @@ -4720,6 +4718,8 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, if (cache&0x80000000) { if (cache&0x40000000) { + int ulevel; + /* third escape */ SKIP_CACHE(re, &s->gb, 2); last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); @@ -4745,10 +4745,16 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, SKIP_COUNTER(re, &s->gb, 1+12+1); } - if(level*s->qscale>1024 || level*s->qscale<-1024){ + if(s->mpeg_quant){ + if(intra) ulevel= level*s->qscale*s->intra_matrix[scan_table[1]]; + else ulevel= level*s->qscale*s->inter_matrix[scan_table[0]]; + }else + ulevel= level*s->qscale*16; + if(ulevel>1030*16 || ulevel<-1030*16){ av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc, qp=%d\n", s->qscale); return -1; } + #if 0 if(s->error_resilience >= FF_ER_COMPLIANT){ const int abs_level= ABS(level); @@ -4827,14 +4833,8 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, not_coded: if (intra) { if(s->qscale >= s->intra_dc_threshold){ - uint16_t *dc_val; - block[0] += ff_mpeg4_pred_dc(s, n, &dc_val, &dc_pred_dir); - if (n < 4) { - *dc_val = block[0] * s->y_dc_scale; - } else { - *dc_val = block[0] * s->c_dc_scale; - } - + block[0] = ff_mpeg4_pred_dc(s, n, block[0], &dc_pred_dir, 0); + if(i == -1) i=0; } diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c index aaf38b172..ea8badb9d 100644 --- a/src/libffmpeg/libavcodec/h263dec.c +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -306,8 +306,7 @@ static int decode_slice(MpegEncContext *s){ * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ -static int mpeg4_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ - ParseContext *pc= &s->parse_context; +int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ int vop_found, i; uint32_t state; @@ -326,23 +325,25 @@ static int mpeg4_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ } } - if(vop_found){ - for(; i<buf_size; i++){ - state= (state<<8) | buf[i]; - if((state&0xFFFFFF00) == 0x100){ - pc->frame_start_found=0; - pc->state=-1; - return i-3; + if(vop_found){ + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; + for(; i<buf_size; i++){ + state= (state<<8) | buf[i]; + if((state&0xFFFFFF00) == 0x100){ + pc->frame_start_found=0; + pc->state=-1; + return i-3; + } } - } } pc->frame_start_found= vop_found; pc->state= state; return END_NOT_FOUND; } -static int h263_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ - ParseContext *pc= &s->parse_context; +static int h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ int vop_found, i; uint32_t state; @@ -377,6 +378,27 @@ static int h263_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ return END_NOT_FOUND; } +static int h263_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + next= h263_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = (uint8_t *)buf; + *poutbuf_size = buf_size; + return next; +} + int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) @@ -414,15 +436,15 @@ uint64_t time= rdtsc(); int next; if(s->codec_id==CODEC_ID_MPEG4){ - next= mpeg4_find_frame_end(s, buf, buf_size); + next= ff_mpeg4_find_frame_end(&s->parse_context, buf, buf_size); }else if(s->codec_id==CODEC_ID_H263){ - next= h263_find_frame_end(s, buf, buf_size); + next= h263_find_frame_end(&s->parse_context, buf, buf_size); }else{ av_log(s->avctx, AV_LOG_ERROR, "this codec doesnt support truncated bitstreams\n"); return -1; } - if( ff_combine_frame(s, next, &buf, &buf_size) < 0 ) + if( ff_combine_frame(&s->parse_context, next, &buf, &buf_size) < 0 ) return buf_size; } @@ -526,6 +548,9 @@ retry: if(s->xvid_build && s->xvid_build<=12) s->workaround_bugs|= FF_BUG_EDGE; + if(s->xvid_build && s->xvid_build<=32) + s->workaround_bugs|= FF_BUG_DC_CLIP; + #define SET_QPEL_FUNC(postfix1, postfix2) \ s->dsp.put_ ## postfix1 = ff_put_ ## postfix2;\ s->dsp.put_no_rnd_ ## postfix1 = ff_put_no_rnd_ ## postfix2;\ @@ -540,6 +565,9 @@ retry: if(s->lavc_build && s->lavc_build<4670){ s->workaround_bugs|= FF_BUG_EDGE; } + + if(s->lavc_build && s->lavc_build<=4712) + s->workaround_bugs|= FF_BUG_DC_CLIP; if(s->divx_version) s->workaround_bugs|= FF_BUG_DIRECT_BLOCKSIZE; @@ -843,3 +871,11 @@ AVCodec flv_decoder = { ff_h263_decode_frame, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 }; + +AVCodecParser h263_parser = { + { CODEC_ID_H263 }, + sizeof(ParseContext), + NULL, + h263_parse, + ff_parse_close, +}; diff --git a/src/libffmpeg/libavcodec/h264.c b/src/libffmpeg/libavcodec/h264.c index fa254e93b..77c3393ef 100644 --- a/src/libffmpeg/libavcodec/h264.c +++ b/src/libffmpeg/libavcodec/h264.c @@ -5520,8 +5520,7 @@ static inline int decode_picture_parameter_set(H264Context *h){ * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ -static int find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ - ParseContext *pc= &s->parse_context; +static int find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ int i; uint32_t state; //printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]); @@ -5544,6 +5543,27 @@ static int find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ return END_NOT_FOUND; } +static int h264_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + next= find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = (uint8_t *)buf; + *poutbuf_size = buf_size; + return next; +} + static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ MpegEncContext * const s = &h->s; AVCodecContext * const avctx= s->avctx; @@ -5701,9 +5721,9 @@ static int decode_frame(AVCodecContext *avctx, } if(s->flags&CODEC_FLAG_TRUNCATED){ - int next= find_frame_end(s, buf, buf_size); + int next= find_frame_end(&s->parse_context, buf, buf_size); - if( ff_combine_frame(s, next, &buf, &buf_size) < 0 ) + if( ff_combine_frame(&s->parse_context, next, &buf, &buf_size) < 0 ) return buf_size; //printf("next:%d buf_size:%d last_index:%d\n", next, buf_size, s->parse_context.last_index); } @@ -5970,4 +5990,12 @@ AVCodec h264_decoder = { /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED, }; +AVCodecParser h264_parser = { + { CODEC_ID_H264 }, + sizeof(ParseContext), + NULL, + h264_parse, + ff_parse_close, +}; + #include "svq3.c" diff --git a/src/libffmpeg/libavcodec/huffyuv.c b/src/libffmpeg/libavcodec/huffyuv.c index 4047a6a93..210d45419 100644 --- a/src/libffmpeg/libavcodec/huffyuv.c +++ b/src/libffmpeg/libavcodec/huffyuv.c @@ -916,8 +916,6 @@ static int decode_end(AVCodecContext *avctx) for(i=0; i<3; i++){ free_vlc(&s->vlc[i]); } - - avcodec_default_free_buffers(avctx); return 0; } diff --git a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c index 772c9c1f0..c8db22e64 100644 --- a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c +++ b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c @@ -22,6 +22,7 @@ #include "../dsputil.h" #include "../simple_idct.h" +#include "mmx.h" //#undef NDEBUG //#include <assert.h> @@ -293,6 +294,24 @@ void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size :"memory"); } +static unsigned char __align8 vector128[8] = + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; + +void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size) +{ + int i; + + movq_m2r(*vector128, mm1); + for (i = 0; i < 8; i++) { + movq_m2r(*(block), mm0); + packsswb_m2r(*(block + 4), mm0); + block += 8; + paddb_r2r(mm1, mm0); + movq_r2m(mm0, *pixels); + pixels += line_size; + } +} + void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size) { const DCTELEM *p; @@ -2149,19 +2168,18 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx) /* VP3 optimized DSP functions */ if (mm_flags & MM_SSE2) { c->vp3_dsp_init = vp3_dsp_init_sse2; - c->vp3_idct_put = vp3_idct_put_sse2; - c->vp3_idct_add = vp3_idct_add_sse2; + c->vp3_idct = vp3_idct_sse2; } else { c->vp3_dsp_init = vp3_dsp_init_mmx; - c->vp3_idct_put = vp3_idct_put_mmx; - c->vp3_idct_add = vp3_idct_add_mmx; + c->vp3_idct = vp3_idct_mmx; } - + #ifdef CONFIG_ENCODERS c->get_pixels = get_pixels_mmx; c->diff_pixels = diff_pixels_mmx; #endif //CONFIG_ENCODERS c->put_pixels_clamped = put_pixels_clamped_mmx; + c->put_signed_pixels_clamped = put_signed_pixels_clamped_mmx; c->add_pixels_clamped = add_pixels_clamped_mmx; c->clear_blocks = clear_blocks_mmx; #ifdef CONFIG_ENCODERS diff --git a/src/libffmpeg/libavcodec/i386/fdct_mmx.c b/src/libffmpeg/libavcodec/i386/fdct_mmx.c index 7af576971..68f788a23 100644 --- a/src/libffmpeg/libavcodec/i386/fdct_mmx.c +++ b/src/libffmpeg/libavcodec/i386/fdct_mmx.c @@ -60,77 +60,77 @@ struct //static const long fdct_r_row_sse2[4] ATTR_ALIGN(16) = {RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW}; static const int16_t tab_frw_01234567[] ATTR_ALIGN(8) = { // forward_dct coeff table - 16384, 16384, -8867, -21407, - 16384, 16384, 21407, 8867, - 16384, -16384, 21407, -8867, - -16384, 16384, 8867, -21407, - 22725, 19266, -22725, -12873, - 12873, 4520, 19266, -4520, - 12873, -22725, 19266, -22725, - 4520, 19266, 4520, -12873, - - 22725, 22725, -12299, -29692, - 22725, 22725, 29692, 12299, - 22725, -22725, 29692, -12299, - -22725, 22725, 12299, -29692, - 31521, 26722, -31521, -17855, - 17855, 6270, 26722, -6270, - 17855, -31521, 26722, -31521, - 6270, 26722, 6270, -17855, - - 21407, 21407, -11585, -27969, - 21407, 21407, 27969, 11585, - 21407, -21407, 27969, -11585, - -21407, 21407, 11585, -27969, - 29692, 25172, -29692, -16819, - 16819, 5906, 25172, -5906, - 16819, -29692, 25172, -29692, - 5906, 25172, 5906, -16819, - - 19266, 19266, -10426, -25172, - 19266, 19266, 25172, 10426, - 19266, -19266, 25172, -10426, - -19266, 19266, 10426, -25172, - 26722, 22654, -26722, -15137, - 15137, 5315, 22654, -5315, - 15137, -26722, 22654, -26722, - 5315, 22654, 5315, -15137, - - 16384, 16384, -8867, -21407, - 16384, 16384, 21407, 8867, - 16384, -16384, 21407, -8867, - -16384, 16384, 8867, -21407, - 22725, 19266, -22725, -12873, - 12873, 4520, 19266, -4520, - 12873, -22725, 19266, -22725, - 4520, 19266, 4520, -12873, - - 19266, 19266, -10426, -25172, - 19266, 19266, 25172, 10426, - 19266, -19266, 25172, -10426, - -19266, 19266, 10426, -25172, - 26722, 22654, -26722, -15137, - 15137, 5315, 22654, -5315, - 15137, -26722, 22654, -26722, - 5315, 22654, 5315, -15137, - - 21407, 21407, -11585, -27969, - 21407, 21407, 27969, 11585, - 21407, -21407, 27969, -11585, - -21407, 21407, 11585, -27969, - 29692, 25172, -29692, -16819, - 16819, 5906, 25172, -5906, - 16819, -29692, 25172, -29692, - 5906, 25172, 5906, -16819, - - 22725, 22725, -12299, -29692, - 22725, 22725, 29692, 12299, - 22725, -22725, 29692, -12299, - -22725, 22725, 12299, -29692, - 31521, 26722, -31521, -17855, - 17855, 6270, 26722, -6270, - 17855, -31521, 26722, -31521, - 6270, 26722, 6270, -17855, + 16384, 16384, 22725, 19266, + 16384, 16384, 12873, 4520, + 21407, 8867, 19266, -4520, + -8867, -21407, -22725, -12873, + 16384, -16384, 12873, -22725, + -16384, 16384, 4520, 19266, + 8867, -21407, 4520, -12873, + 21407, -8867, 19266, -22725, + + 22725, 22725, 31521, 26722, + 22725, 22725, 17855, 6270, + 29692, 12299, 26722, -6270, + -12299, -29692, -31521, -17855, + 22725, -22725, 17855, -31521, + -22725, 22725, 6270, 26722, + 12299, -29692, 6270, -17855, + 29692, -12299, 26722, -31521, + + 21407, 21407, 29692, 25172, + 21407, 21407, 16819, 5906, + 27969, 11585, 25172, -5906, + -11585, -27969, -29692, -16819, + 21407, -21407, 16819, -29692, + -21407, 21407, 5906, 25172, + 11585, -27969, 5906, -16819, + 27969, -11585, 25172, -29692, + + 19266, 19266, 26722, 22654, + 19266, 19266, 15137, 5315, + 25172, 10426, 22654, -5315, + -10426, -25172, -26722, -15137, + 19266, -19266, 15137, -26722, + -19266, 19266, 5315, 22654, + 10426, -25172, 5315, -15137, + 25172, -10426, 22654, -26722, + + 16384, 16384, 22725, 19266, + 16384, 16384, 12873, 4520, + 21407, 8867, 19266, -4520, + -8867, -21407, -22725, -12873, + 16384, -16384, 12873, -22725, + -16384, 16384, 4520, 19266, + 8867, -21407, 4520, -12873, + 21407, -8867, 19266, -22725, + + 19266, 19266, 26722, 22654, + 19266, 19266, 15137, 5315, + 25172, 10426, 22654, -5315, + -10426, -25172, -26722, -15137, + 19266, -19266, 15137, -26722, + -19266, 19266, 5315, 22654, + 10426, -25172, 5315, -15137, + 25172, -10426, 22654, -26722, + + 21407, 21407, 29692, 25172, + 21407, 21407, 16819, 5906, + 27969, 11585, 25172, -5906, + -11585, -27969, -29692, -16819, + 21407, -21407, 16819, -29692, + -21407, 21407, 5906, 25172, + 11585, -27969, 5906, -16819, + 27969, -11585, 25172, -29692, + + 22725, 22725, 31521, 26722, + 22725, 22725, 17855, 6270, + 29692, 12299, 26722, -6270, + -12299, -29692, -31521, -17855, + 22725, -22725, 17855, -31521, + -22725, 22725, 6270, 26722, + 12299, -29692, 6270, -17855, + 29692, -12299, 26722, -31521, }; struct @@ -413,93 +413,91 @@ static always_inline void fdct_row_mmx2(const int16_t *in, int16_t *out, const i { pshufw_m2r(*(in + 4), mm5, 0x1B); movq_m2r(*(in + 0), mm0); - movq_r2r(mm0, mm1); + movq_r2r(mm0, mm1); paddsw_r2r(mm5, mm0); psubsw_r2r(mm5, mm1); - pshufw_r2r(mm0, mm2, 0x4E); - pshufw_r2r(mm1, mm3, 0x4E); - movq_m2r(*(table + 0), mm4); - movq_m2r(*(table + 4), mm6); - movq_m2r(*(table + 16), mm5); + movq_r2r(mm0, mm2); + punpckldq_r2r(mm1, mm0); + punpckhdq_r2r(mm1, mm2); + movq_m2r(*(table + 0), mm1); + movq_m2r(*(table + 4), mm3); + movq_m2r(*(table + 8), mm4); + movq_m2r(*(table + 12), mm5); + movq_m2r(*(table + 16), mm6); movq_m2r(*(table + 20), mm7); + pmaddwd_r2r(mm0, mm1); + pmaddwd_r2r(mm2, mm3); pmaddwd_r2r(mm0, mm4); - pmaddwd_r2r(mm1, mm5); - pmaddwd_r2r(mm2, mm6); - pmaddwd_r2r(mm3, mm7); - pmaddwd_m2r(*(table + 8), mm0); - pmaddwd_m2r(*(table + 12), mm2); - pmaddwd_m2r(*(table + 24), mm1); - pmaddwd_m2r(*(table + 28), mm3); - paddd_r2r(mm6, mm4); - paddd_r2r(mm7, mm5); - paddd_r2r(mm2, mm0); - paddd_r2r(mm3, mm1); - movq_m2r(*fdct_r_row, mm7); - paddd_r2r(mm7, mm4); - paddd_r2r(mm7, mm5); - paddd_r2r(mm7, mm0); - paddd_r2r(mm7, mm1); - psrad_i2r(SHIFT_FRW_ROW, mm4); + pmaddwd_r2r(mm2, mm5); + pmaddwd_r2r(mm0, mm6); + pmaddwd_r2r(mm2, mm7); + pmaddwd_m2r(*(table + 24), mm0); + pmaddwd_m2r(*(table + 28), mm2); + paddd_r2r(mm1, mm3); + paddd_r2r(mm4, mm5); + paddd_r2r(mm6, mm7); + paddd_r2r(mm0, mm2); + movq_m2r(*fdct_r_row, mm0); + paddd_r2r(mm0, mm3); + paddd_r2r(mm0, mm5); + paddd_r2r(mm0, mm7); + paddd_r2r(mm0, mm2); + psrad_i2r(SHIFT_FRW_ROW, mm3); psrad_i2r(SHIFT_FRW_ROW, mm5); - psrad_i2r(SHIFT_FRW_ROW, mm0); - psrad_i2r(SHIFT_FRW_ROW, mm1); - packssdw_r2r(mm0, mm4); - packssdw_r2r(mm1, mm5); - movq_r2r(mm4, mm2); - punpcklwd_r2r(mm5, mm4); - punpckhwd_r2r(mm5, mm2); - movq_r2m(mm4, *(out + 0)); - movq_r2m(mm2, *(out + 4)); + psrad_i2r(SHIFT_FRW_ROW, mm7); + psrad_i2r(SHIFT_FRW_ROW, mm2); + packssdw_r2r(mm5, mm3); + packssdw_r2r(mm2, mm7); + movq_r2m(mm3, *(out + 0)); + movq_r2m(mm7, *(out + 4)); } static always_inline void fdct_row_mmx(const int16_t *in, int16_t *out, const int16_t *table) { +//FIXME reorder (i dont have a old mmx only cpu here to benchmark ...) movd_m2r(*(in + 6), mm1); punpcklwd_m2r(*(in + 4), mm1); movq_r2r(mm1, mm2); psrlq_i2r(0x20, mm1); movq_m2r(*(in + 0), mm0); punpcklwd_r2r(mm2, mm1); - movq_r2r(mm0, mm5); + movq_r2r(mm0, mm5); paddsw_r2r(mm1, mm0); psubsw_r2r(mm1, mm5); - movq_r2r(mm0, mm1); - movq_r2r(mm5, mm6); - punpckldq_r2r(mm5, mm3); - punpckhdq_r2r(mm3, mm6); - movq_m2r(*(table + 0), mm3); - movq_m2r(*(table + 4), mm4); - punpckldq_r2r(mm0, mm2); - pmaddwd_r2r(mm0, mm3); - punpckhdq_r2r(mm2, mm1); - movq_m2r(*(table + 16), mm2); - pmaddwd_r2r(mm1, mm4); - pmaddwd_m2r(*(table + 8), mm0); + movq_r2r(mm0, mm2); + punpckldq_r2r(mm5, mm0); + punpckhdq_r2r(mm5, mm2); + movq_m2r(*(table + 0), mm1); + movq_m2r(*(table + 4), mm3); + movq_m2r(*(table + 8), mm4); + movq_m2r(*(table + 12), mm5); + movq_m2r(*(table + 16), mm6); movq_m2r(*(table + 20), mm7); - pmaddwd_r2r(mm5, mm2); - paddd_m2r(*fdct_r_row, mm3); - pmaddwd_r2r(mm6, mm7); - pmaddwd_m2r(*(table + 12), mm1); - paddd_r2r(mm4, mm3); - pmaddwd_m2r(*(table + 24), mm5); - pmaddwd_m2r(*(table + 28), mm6); - paddd_r2r(mm7, mm2); - paddd_m2r(*fdct_r_row, mm0); + pmaddwd_r2r(mm0, mm1); + pmaddwd_r2r(mm2, mm3); + pmaddwd_r2r(mm0, mm4); + pmaddwd_r2r(mm2, mm5); + pmaddwd_r2r(mm0, mm6); + pmaddwd_r2r(mm2, mm7); + pmaddwd_m2r(*(table + 24), mm0); + pmaddwd_m2r(*(table + 28), mm2); + paddd_r2r(mm1, mm3); + paddd_r2r(mm4, mm5); + paddd_r2r(mm6, mm7); + paddd_r2r(mm0, mm2); + movq_m2r(*fdct_r_row, mm0); + paddd_r2r(mm0, mm3); + paddd_r2r(mm0, mm5); + paddd_r2r(mm0, mm7); + paddd_r2r(mm0, mm2); psrad_i2r(SHIFT_FRW_ROW, mm3); - paddd_m2r(*fdct_r_row, mm2); - paddd_r2r(mm1, mm0); - paddd_m2r(*fdct_r_row, mm5); - psrad_i2r(SHIFT_FRW_ROW, mm2); - paddd_r2r(mm6, mm5); - psrad_i2r(SHIFT_FRW_ROW, mm0); psrad_i2r(SHIFT_FRW_ROW, mm5); - packssdw_r2r(mm0, mm3); - packssdw_r2r(mm5, mm2); - movq_r2r(mm3, mm6); - punpcklwd_r2r(mm2, mm3); - punpckhwd_r2r(mm2, mm6); + psrad_i2r(SHIFT_FRW_ROW, mm7); + psrad_i2r(SHIFT_FRW_ROW, mm2); + packssdw_r2r(mm5, mm3); + packssdw_r2r(mm2, mm7); movq_r2m(mm3, *(out + 0)); - movq_r2m(mm6, *(out + 4)); + movq_r2m(mm7, *(out + 4)); } void ff_fdct_mmx(int16_t *block) @@ -553,7 +551,6 @@ void ff_fdct_sse2(int16_t *block) int64_t align_tmp[16] ATTR_ALIGN(8); int16_t * const block_tmp= (int16_t*)align_tmp; int16_t *block1; - int i; block1 = block_tmp; fdct_col(block, block1, 0); diff --git a/src/libffmpeg/libavcodec/i386/vp3dsp_mmx.c b/src/libffmpeg/libavcodec/i386/vp3dsp_mmx.c index 76007a1d1..319e57f1b 100644 --- a/src/libffmpeg/libavcodec/i386/vp3dsp_mmx.c +++ b/src/libffmpeg/libavcodec/i386/vp3dsp_mmx.c @@ -279,8 +279,8 @@ void vp3_dsp_init_mmx(void) idct_constants[46] = idct_constants[47] = IdctAdjustBeforeShift; } -static void vp3_idct_mmx(int16_t *input_data, int16_t *dequant_matrix, - int16_t *output_data) +void vp3_idct_mmx(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, int16_t *output_data) { /* eax = quantized input * ebx = dequantizer matrix @@ -563,79 +563,3 @@ static void vp3_idct_mmx(int16_t *input_data, int16_t *dequant_matrix, #undef J } - -void vp3_idct_put_mmx(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int16_t transformed_data[64]; - int16_t *op; - int i, j; - uint8_t vector128[8] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; - - vp3_idct_mmx(input_data, dequant_matrix, transformed_data); - - /* place in final output */ - op = transformed_data; - movq_m2r(*vector128, mm0); - for (i = 0; i < 8; i++) { -#if 1 - for (j = 0; j < 8; j++) { - if (*op < -128) - *dest = 0; - else if (*op > 127) - *dest = 255; - else - *dest = (uint8_t)(*op + 128); - op++; - dest++; - } - dest += (stride - 8); -#else -/* prototype optimization */ - pxor_r2r(mm1, mm1); - packsswb_m2r(*(op + 4), mm1); - movq_r2r(mm1, mm2); - psrlq_i2r(32, mm2); - packsswb_m2r(*(op + 0), mm1); - op += 8; - por_r2r(mm2, mm1); - paddb_r2r(mm0, mm1); - movq_r2m(mm1, *dest); - dest += stride; -#endif - } - - /* be a good MMX citizen */ - emms(); -} - -void vp3_idct_add_mmx(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int16_t transformed_data[64]; - int16_t *op; - int i, j; - int16_t sample; - - vp3_idct_mmx(input_data, dequant_matrix, transformed_data); - - /* place in final output */ - op = transformed_data; - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - sample = *dest + *op; - if (sample < 0) - *dest = 0; - else if (sample > 255) - *dest = 255; - else - *dest = (uint8_t)(sample & 0xFF); - op++; - dest++; - } - dest += (stride - 8); - } - - /* be a good MMX citizen */ - emms(); -} diff --git a/src/libffmpeg/libavcodec/i386/vp3dsp_sse2.c b/src/libffmpeg/libavcodec/i386/vp3dsp_sse2.c index c8f9158af..60c6bf80e 100644 --- a/src/libffmpeg/libavcodec/i386/vp3dsp_sse2.c +++ b/src/libffmpeg/libavcodec/i386/vp3dsp_sse2.c @@ -802,8 +802,8 @@ void vp3_dsp_init_sse2(void) } -static void vp3_idct_sse2(int16_t *input_data, int16_t *dequant_matrix, - int16_t *output_data) +void vp3_idct_sse2(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, int16_t *output_data) { unsigned char *input_bytes = (unsigned char *)input_data; unsigned char *dequant_matrix_bytes = (unsigned char *)dequant_matrix; @@ -832,59 +832,3 @@ static void vp3_idct_sse2(int16_t *input_data, int16_t *dequant_matrix, SSE2_Column_IDCT(); } - - -void vp3_idct_put_sse2(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int16_t transformed_data[64]; - int16_t *op; - int i, j; - - vp3_idct_sse2(input_data, dequant_matrix, transformed_data); - - /* place in final output */ - op = transformed_data; - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - if (*op < -128) - *dest = 0; - else if (*op > 127) - *dest = 255; - else - *dest = (uint8_t)(*op + 128); - op++; - dest++; - } - dest += (stride - 8); - } -} - - -void vp3_idct_add_sse2(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int16_t transformed_data[64]; - int16_t *op; - int i, j; - int16_t sample; - - vp3_idct_sse2(input_data, dequant_matrix, transformed_data); - - /* place in final output */ - op = transformed_data; - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - sample = *dest + *op; - if (sample < 0) - *dest = 0; - else if (sample > 255) - *dest = 255; - else - *dest = (uint8_t)(sample & 0xFF); - op++; - dest++; - } - dest += (stride - 8); - } -} diff --git a/src/libffmpeg/libavcodec/integer.c b/src/libffmpeg/libavcodec/integer.c new file mode 100644 index 000000000..025560f9e --- /dev/null +++ b/src/libffmpeg/libavcodec/integer.c @@ -0,0 +1,195 @@ +/* + * arbitrary precision integers + * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/** + * @file integer.c + * arbitrary precision integers. + * @author Michael Niedermayer <michaelni@gmx.at> + */ + +#include "common.h" +#include "integer.h" + +AVInteger av_add_i(AVInteger a, AVInteger b){ + int i, carry=0; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + carry= (carry>>16) + a.v[i] + b.v[i]; + a.v[i]= carry; + } + return a; +} + +AVInteger av_sub_i(AVInteger a, AVInteger b){ + int i, carry=0; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + carry= (carry>>16) + a.v[i] - b.v[i]; + a.v[i]= carry; + } + return a; +} + +int av_log2_i(AVInteger a){ + int i; + + for(i=AV_INTEGER_SIZE-1; i>=0; i--){ + if(a.v[i]) + return av_log2_16bit(a.v[i]) + 16*i; + } + return -1; +} + +AVInteger av_mul_i(AVInteger a, AVInteger b){ + AVInteger out; + int i, j; + int na= (av_log2_i(a)+16) >> 4; + int nb= (av_log2_i(b)+16) >> 4; + + memset(&out, 0, sizeof(out)); + + for(i=0; i<na; i++){ + unsigned int carry=0; + + if(a.v[i]) + for(j=i; j<AV_INTEGER_SIZE && j-i<=nb; j++){ + carry= (carry>>16) + out.v[j] + a.v[i]*b.v[j-i]; + out.v[j]= carry; + } + } + + return out; +} + +int av_cmp_i(AVInteger a, AVInteger b){ + int i; + int v= (int16_t)a.v[AV_INTEGER_SIZE-1] - (int16_t)b.v[AV_INTEGER_SIZE-1]; + if(v) return (v>>16)|1; + + for(i=AV_INTEGER_SIZE-2; i>=0; i--){ + int v= a.v[i] - b.v[i]; + if(v) return (v>>16)|1; + } + return 0; +} + +AVInteger av_shr_i(AVInteger a, int s){ + AVInteger out; + int i; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + int index= i + (s>>4); + unsigned int v=0; + if(index+1<AV_INTEGER_SIZE && index+1>=0) v = a.v[index+1]<<16; + if(index <AV_INTEGER_SIZE && index >=0) v+= a.v[index ]; + out.v[i]= v >> (s&15); + } + return out; +} + +AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b){ + int i= av_log2_i(a) - av_log2_i(b); + AVInteger quot_temp; + if(!quot) quot = "_temp; + + assert((int16_t)a[AV_INTEGER_SIZE-1] >= 0 && (int16_t)b[AV_INTEGER_SIZE-1] >= 0); + assert(av_log2(b)>=0); + + if(i > 0) + b= av_shr_i(b, -i); + + memset(quot, 0, sizeof(AVInteger)); + + while(i-- >= 0){ + *quot= av_shr_i(*quot, -1); + if(av_cmp_i(a, b) >= 0){ + a= av_sub_i(a, b); + quot->v[0] += 1; + } + b= av_shr_i(b, 1); + } + return a; +} + +AVInteger av_div_i(AVInteger a, AVInteger b){ + AVInteger quot; + av_mod_i(", a, b); + return quot; +} + +AVInteger av_int2i(int64_t a){ + AVInteger out; + int i; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + out.v[i]= a; + a>>=16; + } + return out; +} + +int64_t av_i2int(AVInteger a){ + int i; + int64_t out=(int8_t)a.v[AV_INTEGER_SIZE-1]; + + for(i= AV_INTEGER_SIZE-2; i>=0; i--){ + out = (out<<16) + a.v[i]; + } + return out; +} + +#if 0 +#undef NDEBUG +#include <assert.h> + +const uint8_t ff_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,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, + 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, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +main(){ + int64_t a,b; + + for(a=7; a<256*256*256; a+=13215){ + for(b=3; b<256*256*256; b+=27118){ + AVInteger ai= av_int2i(a); + AVInteger bi= av_int2i(b); + + assert(av_i2int(ai) == a); + assert(av_i2int(bi) == b); + assert(av_i2int(av_add_i(ai,bi)) == a+b); + assert(av_i2int(av_sub_i(ai,bi)) == a-b); + assert(av_i2int(av_mul_i(ai,bi)) == a*b); + assert(av_i2int(av_shr_i(ai, 9)) == a>>9); + assert(av_i2int(av_shr_i(ai,-9)) == a<<9); + assert(av_i2int(av_shr_i(ai, 17)) == a>>17); + assert(av_i2int(av_shr_i(ai,-17)) == a<<17); + assert(av_log2_i(ai) == av_log2(a)); + assert(av_i2int(av_div_i(ai,bi)) == a/b); + } + } +} +#endif diff --git a/src/libffmpeg/libavcodec/integer.h b/src/libffmpeg/libavcodec/integer.h new file mode 100644 index 000000000..ef1b2a089 --- /dev/null +++ b/src/libffmpeg/libavcodec/integer.h @@ -0,0 +1,47 @@ +/* + * arbitrary precision integers + * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/** + * @file integer.h + * arbitrary precision integers + * @author Michael Niedermayer <michaelni@gmx.at> + */ + +#ifndef INTEGER_H +#define INTEGER_H + +#define AV_INTEGER_SIZE 8 + +typedef struct AVInteger{ + uint16_t v[AV_INTEGER_SIZE]; +} AVInteger; + +AVInteger av_add_i(AVInteger a, AVInteger b); +AVInteger av_sub_i(AVInteger a, AVInteger b); +int av_log2_i(AVInteger a); +AVInteger av_mul_i(AVInteger a, AVInteger b); +int av_cmp_i(AVInteger a, AVInteger b); +AVInteger av_shr_i(AVInteger a, int s); +AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b); +AVInteger av_div_i(AVInteger a, AVInteger b); +AVInteger av_int2i(int64_t a); +int64_t av_i2int(AVInteger a); + +#endif // INTEGER_H diff --git a/src/libffmpeg/libavcodec/mdec.c b/src/libffmpeg/libavcodec/mdec.c index faf3cef31..219a39b25 100644 --- a/src/libffmpeg/libavcodec/mdec.c +++ b/src/libffmpeg/libavcodec/mdec.c @@ -257,8 +257,6 @@ static int decode_end(AVCodecContext *avctx){ av_freep(&a->picture.qscale_table); a->bitstream_buffer_size=0; - avcodec_default_free_buffers(avctx); - return 0; } diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c index 255a82d2c..78a620fd3 100644 --- a/src/libffmpeg/libavcodec/mjpeg.c +++ b/src/libffmpeg/libavcodec/mjpeg.c @@ -1340,7 +1340,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s){ (h * mb_x + x) * 8; if (s->interlaced && s->bottom_field) ptr += s->linesize[c] >> 1; -//printf("%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8); +//av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8); s->idct_put(ptr, s->linesize[c], s->block); if (++x == h) { x = 0; @@ -2171,7 +2171,6 @@ static int mjpeg_decode_end(AVCodecContext *avctx) av_free(s->buffer); av_free(s->qscale_table); - avcodec_default_free_buffers(avctx); for(i=0;i<2;i++) { for(j=0;j<4;j++) diff --git a/src/libffmpeg/libavcodec/motion_est.c b/src/libffmpeg/libavcodec/motion_est.c index f194a4d60..6aeedd5b9 100644 --- a/src/libffmpeg/libavcodec/motion_est.c +++ b/src/libffmpeg/libavcodec/motion_est.c @@ -1002,7 +1002,10 @@ static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int c->stride<<=1; c->uvstride<<=1; - assert(s->flags & CODEC_FLAG_INTERLACED_ME); + if(!(s->flags & CODEC_FLAG_INTERLACED_ME)){ + av_log(s->avctx, AV_LOG_ERROR, "Interlaced macroblock selected but interlaced motion estimation disabled\n"); + return -1; + } if(USES_LIST(mb_type, 0)){ int field_select0= p->ref_index[0][xy ]; @@ -1060,7 +1063,10 @@ static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int c->stride>>=1; c->uvstride>>=1; }else if(IS_8X8(mb_type)){ - assert(s->flags & CODEC_FLAG_4MV); + if(!(s->flags & CODEC_FLAG_4MV)){ + av_log(s->avctx, AV_LOG_ERROR, "4MV macroblock selected but 4MV encoding disabled\n"); + return -1; + } cmpf= s->dsp.sse[1]; chroma_cmpf= s->dsp.sse[1]; init_mv4_ref(s); diff --git a/src/libffmpeg/libavcodec/mpeg12.c b/src/libffmpeg/libavcodec/mpeg12.c index 493d1a445..20ca493f2 100644 --- a/src/libffmpeg/libavcodec/mpeg12.c +++ b/src/libffmpeg/libavcodec/mpeg12.c @@ -365,14 +365,10 @@ static inline void encode_mb_skip_run(MpegEncContext *s, int run){ static void common_init(MpegEncContext *s) { -int i; s->y_dc_scale_table= - s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + s->c_dc_scale_table= mpeg2_dc_scale_table[s->intra_dc_precision]; - if(!s->encoding) - for(i=0;i<64;i++) - s->dsp.idct_permutation[i]=i; } void ff_mpeg1_clean_buffers(MpegEncContext *s){ @@ -784,7 +780,7 @@ void ff_mpeg1_encode_init(MpegEncContext *s) adiff = ABS(diff); if(diff<0) diff--; - index = vlc_dc_table[adiff]; + index = av_log2(2*adiff); bits= vlc_dc_lum_bits[index] + index; code= (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1)); @@ -848,6 +844,27 @@ void ff_mpeg1_encode_init(MpegEncContext *s) static inline void encode_dc(MpegEncContext *s, int diff, int component) { + if(((unsigned) (diff+255)) >= 511){ + int index; + + if(diff<0){ + index= av_log2_16bit(-2*diff); + diff--; + }else{ + index= av_log2_16bit(2*diff); + } + if (component == 0) { + put_bits( + &s->pb, + vlc_dc_lum_bits[index] + index, + (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1))); + }else{ + put_bits( + &s->pb, + vlc_dc_chroma_bits[index] + index, + (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1))); + } + }else{ if (component == 0) { put_bits( &s->pb, @@ -859,6 +876,7 @@ static inline void encode_dc(MpegEncContext *s, int diff, int component) mpeg1_chr_dc_uni[diff+255]&0xFF, mpeg1_chr_dc_uni[diff+255]>>8); } + } } static void mpeg1_encode_block(MpegEncContext *s, @@ -1770,7 +1788,14 @@ static int mpeg_decode_init(AVCodecContext *avctx) { Mpeg1Context *s = avctx->priv_data; MpegEncContext *s2 = &s->mpeg_enc_ctx; + int i; + //we need some parmutation to store + //matrixes, until MPV_common_init() + //set the real permutatuon + for(i=0;i<64;i++) + s2->dsp.idct_permutation[i]=i; + MPV_decode_defaults(s2); s->mpeg_enc_ctx.avctx= avctx; @@ -2726,8 +2751,8 @@ static void mpeg_decode_gop(AVCodecContext *avctx, * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ -static int mpeg1_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ - ParseContext *pc= &s->parse_context; +int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ int i; uint32_t state; @@ -2746,6 +2771,9 @@ static int mpeg1_find_frame_end(MpegEncContext *s, uint8_t *buf, int buf_size){ } if(pc->frame_start_found){ + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; for(; i<buf_size; i++){ state= (state<<8) | buf[i]; if((state&0xFFFFFF00) == 0x100){ @@ -2786,9 +2814,9 @@ static int mpeg_decode_frame(AVCodecContext *avctx, } if(s2->flags&CODEC_FLAG_TRUNCATED){ - int next= mpeg1_find_frame_end(s2, buf, buf_size); + int next= ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size); - if( ff_combine_frame(s2, next, &buf, &buf_size) < 0 ) + if( ff_combine_frame(&s2->parse_context, next, &buf, &buf_size) < 0 ) return buf_size; } diff --git a/src/libffmpeg/libavcodec/mpeg12data.h b/src/libffmpeg/libavcodec/mpeg12data.h index 4ee460ccc..82e2ab6a1 100644 --- a/src/libffmpeg/libavcodec/mpeg12data.h +++ b/src/libffmpeg/libavcodec/mpeg12data.h @@ -25,29 +25,6 @@ const int16_t ff_mpeg1_default_non_intra_matrix[64] = { 16, 16, 16, 16, 16, 16, 16, 16, }; -static const unsigned char vlc_dc_table[256] = { - 0, 1, 2, 2, - 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, - 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, - - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -}; - static const uint16_t vlc_dc_lum_code[12] = { 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x1ff, }; @@ -382,7 +359,7 @@ static const uint8_t non_linear_qscale[32] = { 56,64,72,80,88,96,104,112, }; -uint8_t ff_mpeg1_dc_scale_table[128]={ // MN: mpeg2 really can have such large qscales? +uint8_t ff_mpeg1_dc_scale_table[128]={ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -390,6 +367,37 @@ uint8_t ff_mpeg1_dc_scale_table[128]={ // MN: mpeg2 really can have such large q 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, }; +static uint8_t mpeg2_dc_scale_table1[128]={ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 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, +}; + +static uint8_t mpeg2_dc_scale_table2[128]={ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 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, +}; + +static uint8_t mpeg2_dc_scale_table3[128]={ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 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 uint8_t *mpeg2_dc_scale_table[4]={ + ff_mpeg1_dc_scale_table, + mpeg2_dc_scale_table1, + mpeg2_dc_scale_table2, + mpeg2_dc_scale_table3, +}; + static const float mpeg1_aspect[16]={ 0.0000, 1.0000, diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index bef088a41..41ee62435 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -605,6 +605,11 @@ int MPV_common_init(MpegEncContext *s) { int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; + if(s->avctx->thread_count > MAX_THREADS || (16*s->avctx->thread_count > s->height && s->height)){ + av_log(s->avctx, AV_LOG_ERROR, "too many threads\n"); + return -1; + } + dsputil_init(&s->dsp, s->avctx); DCT_common_init(s); @@ -850,7 +855,6 @@ void MPV_common_end(MpegEncContext *s) } } av_freep(&s->picture); - avcodec_default_free_buffers(s->avctx); s->context_initialized = 0; s->last_picture_ptr= s->next_picture_ptr= @@ -893,6 +897,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->quarter_sample= (avctx->flags & CODEC_FLAG_QPEL)!=0; s->mpeg_quant= avctx->mpeg_quant; s->rtp_mode= !!avctx->rtp_payload_size; + s->intra_dc_precision= avctx->intra_dc_precision; if (s->gop_size <= 1) { s->intra_only = 1; @@ -998,11 +1003,6 @@ int MPV_encode_init(AVCodecContext *avctx) return -1; } - if(s->avctx->thread_count > MAX_THREADS || 16*s->avctx->thread_count > s->height){ - av_log(avctx, AV_LOG_ERROR, "too many threads\n"); - return -1; - } - if(s->avctx->thread_count > 1) s->rtp_mode= 1; @@ -3727,64 +3727,6 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) #endif //CONFIG_ENCODERS -/** - * combines the (truncated) bitstream to a complete frame - * @returns -1 if no complete frame could be created - */ -int ff_combine_frame( MpegEncContext *s, int next, uint8_t **buf, int *buf_size){ - ParseContext *pc= &s->parse_context; - -#if 0 - if(pc->overread){ - printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); - printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); - } -#endif - - /* copy overreaded byes from last frame into buffer */ - for(; pc->overread>0; pc->overread--){ - pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; - } - - pc->last_index= pc->index; - - /* copy into buffer end return */ - if(next == END_NOT_FOUND){ - pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); - - memcpy(&pc->buffer[pc->index], *buf, *buf_size); - pc->index += *buf_size; - return -1; - } - - *buf_size= - pc->overread_index= pc->index + next; - - /* append to buffer */ - if(pc->index){ - pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); - - memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); - pc->index = 0; - *buf= pc->buffer; - } - - /* store overread bytes */ - for(;next < 0; next++){ - pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; - pc->overread++; - } - -#if 0 - if(pc->overread){ - printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); - printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); - } -#endif - - return 0; -} - void ff_mpeg_flush(AVCodecContext *avctx){ int i; MpegEncContext *s = avctx->priv_data; @@ -4099,7 +4041,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ for(i=0; i<3; i++){ /* init last dc values */ /* note: quant matrix value (8) is implied here */ - s->last_dc[i] = 128; + s->last_dc[i] = 128 << s->intra_dc_precision; s->current_picture_ptr->error[i] = 0; } diff --git a/src/libffmpeg/libavcodec/mpegvideo.h b/src/libffmpeg/libavcodec/mpegvideo.h index cd42177f5..d09fd4e0a 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.h +++ b/src/libffmpeg/libavcodec/mpegvideo.h @@ -749,7 +749,8 @@ void ff_draw_horiz_band(MpegEncContext *s, int y, int h); void ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, int block_w, int block_h, int src_x, int src_y, int w, int h); #define END_NOT_FOUND -100 -int ff_combine_frame( MpegEncContext *s, int next, uint8_t **buf, int *buf_size); +int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size); +void ff_parse_close(AVCodecParserContext *s); void ff_mpeg_flush(AVCodecContext *avctx); void ff_print_debug_info(MpegEncContext *s, AVFrame *pict); void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix); diff --git a/src/libffmpeg/libavcodec/parser.c b/src/libffmpeg/libavcodec/parser.c new file mode 100644 index 000000000..88894884c --- /dev/null +++ b/src/libffmpeg/libavcodec/parser.c @@ -0,0 +1,749 @@ +/* + * Audio and Video frame extraction + * Copyright (c) 2003 Fabrice Bellard. + * Copyright (c) 2003 Michael Niedermayer. + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "avcodec.h" +#include "mpegvideo.h" +#include "mpegaudio.h" + +AVCodecParser *av_first_parser = NULL; + +void av_register_codec_parser(AVCodecParser *parser) +{ + parser->next = av_first_parser; + av_first_parser = parser; +} + +AVCodecParserContext *av_parser_init(int codec_id) +{ + AVCodecParserContext *s; + AVCodecParser *parser; + int ret; + + for(parser = av_first_parser; parser != NULL; parser = parser->next) { + if (parser->codec_ids[0] == codec_id || + parser->codec_ids[1] == codec_id || + parser->codec_ids[2] == codec_id) + goto found; + } + return NULL; + found: + s = av_mallocz(sizeof(AVCodecParserContext)); + if (!s) + return NULL; + s->parser = parser; + s->priv_data = av_mallocz(parser->priv_data_size); + if (!s->priv_data) { + av_free(s); + return NULL; + } + if (parser->parser_init) { + ret = parser->parser_init(s); + if (ret != 0) { + av_free(s->priv_data); + av_free(s); + return NULL; + } + } + return s; +} + +/* NOTE: buf_size == 0 is used to signal EOF so that the last frame + can be returned if necessary */ +int av_parser_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts) +{ + int index, i, k; + uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; + + if (buf_size == 0) { + /* padding is always necessary even if EOF, so we add it here */ + memset(dummy_buf, 0, sizeof(dummy_buf)); + buf = dummy_buf; + } else { + /* add a new packet descriptor */ + k = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); + s->cur_frame_start_index = k; + s->cur_frame_offset[k] = s->cur_offset; + s->cur_frame_pts[k] = pts; + s->cur_frame_dts[k] = dts; + + /* fill first PTS/DTS */ + if (s->cur_offset == 0) { + s->last_pts = pts; + s->last_dts = dts; + } + } + + /* WARNING: the returned index can be negative */ + index = s->parser->parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size); + /* update the file pointer */ + if (*poutbuf_size) { + /* fill the data for the current frame */ + s->frame_offset = s->last_frame_offset; + s->pts = s->last_pts; + s->dts = s->last_dts; + + /* offset of the next frame */ + s->last_frame_offset = s->cur_offset + index; + /* find the packet in which the new frame starts. It + is tricky because of MPEG video start codes + which can begin in one packet and finish in + another packet. In the worst case, an MPEG + video start code could be in 4 different + packets. */ + k = s->cur_frame_start_index; + for(i = 0; i < AV_PARSER_PTS_NB; i++) { + if (s->last_frame_offset >= s->cur_frame_offset[k]) + break; + k = (k - 1) & (AV_PARSER_PTS_NB - 1); + } + s->last_pts = s->cur_frame_pts[k]; + s->last_dts = s->cur_frame_dts[k]; + } + if (index < 0) + index = 0; + s->cur_offset += index; + return index; +} + +void av_parser_close(AVCodecParserContext *s) +{ + if (s->parser->parser_close) + s->parser->parser_close(s); + av_free(s->priv_data); + av_free(s); +} + +/*****************************************************/ + +//#define END_NOT_FOUND (-100) + +#define PICTURE_START_CODE 0x00000100 +#define SEQ_START_CODE 0x000001b3 +#define EXT_START_CODE 0x000001b5 +#define SLICE_MIN_START_CODE 0x00000101 +#define SLICE_MAX_START_CODE 0x000001af + +typedef struct ParseContext1{ + ParseContext pc; +/* XXX/FIXME PC1 vs. PC */ + /* MPEG2 specific */ + int frame_rate; + int progressive_sequence; + int width, height; + + /* XXX: suppress that, needed by MPEG4 */ + MpegEncContext *enc; + int first_picture; +} ParseContext1; + +/** + * combines the (truncated) bitstream to a complete frame + * @returns -1 if no complete frame could be created + */ +int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size) +{ +#if 0 + if(pc->overread){ + printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); + printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); + } +#endif + + /* copy overreaded bytes from last frame into buffer */ + for(; pc->overread>0; pc->overread--){ + pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; + } + + pc->last_index= pc->index; + + /* copy into buffer end return */ + if(next == END_NOT_FOUND){ + pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); + + memcpy(&pc->buffer[pc->index], *buf, *buf_size); + pc->index += *buf_size; + return -1; + } + + *buf_size= + pc->overread_index= pc->index + next; + + /* append to buffer */ + if(pc->index){ + pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); + + memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); + pc->index = 0; + *buf= pc->buffer; + } + + /* store overread bytes */ + for(;next < 0; next++){ + pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; + pc->overread++; + } + +#if 0 + if(pc->overread){ + printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); + printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); + } +#endif + + return 0; +} + +static int find_start_code(const uint8_t **pbuf_ptr, const uint8_t *buf_end) +{ + const uint8_t *buf_ptr; + unsigned int state=0xFFFFFFFF, v; + int val; + + buf_ptr = *pbuf_ptr; + while (buf_ptr < buf_end) { + v = *buf_ptr++; + if (state == 0x000001) { + state = ((state << 8) | v) & 0xffffff; + val = state; + goto found; + } + state = ((state << 8) | v) & 0xffffff; + } + val = -1; + found: + *pbuf_ptr = buf_ptr; + return val; +} + +/* XXX: merge with libavcodec ? */ +#define MPEG1_FRAME_RATE_BASE 1001 + +static const int frame_rate_tab[16] = { + 0, + 24000, + 24024, + 25025, + 30000, + 30030, + 50050, + 60000, + 60060, + // Xing's 15fps: (9) + 15015, + // libmpeg3's "Unofficial economy rates": (10-13) + 5005, + 10010, + 12012, + 15015, + // random, just to avoid segfault !never encode these + 25025, + 25025, +}; + +static void mpegvideo_extract_headers(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + ParseContext1 *pc = s->priv_data; + const uint8_t *buf_end; + int32_t start_code; + int frame_rate_index, ext_type, bytes_left; + int frame_rate_ext_n, frame_rate_ext_d; + int top_field_first, repeat_first_field, progressive_frame; + int horiz_size_ext, vert_size_ext; + + s->repeat_pict = 0; + buf_end = buf + buf_size; + while (buf < buf_end) { + start_code = find_start_code(&buf, buf_end); + bytes_left = buf_end - buf; + switch(start_code) { + case PICTURE_START_CODE: + if (bytes_left >= 2) { + s->pict_type = (buf[1] >> 3) & 7; + } + break; + case SEQ_START_CODE: + if (bytes_left >= 4) { + pc->width = avctx->width = (buf[0] << 4) | (buf[1] >> 4); + pc->height = avctx->height = ((buf[1] & 0x0f) << 8) | buf[2]; + frame_rate_index = buf[3] & 0xf; + pc->frame_rate = avctx->frame_rate = frame_rate_tab[frame_rate_index]; + avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE; + avctx->codec_id = CODEC_ID_MPEG1VIDEO; + avctx->sub_id = 1; + } + break; + case EXT_START_CODE: + if (bytes_left >= 1) { + ext_type = (buf[0] >> 4); + switch(ext_type) { + case 0x1: /* sequence extension */ + if (bytes_left >= 6) { + horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7); + vert_size_ext = (buf[2] >> 5) & 3; + frame_rate_ext_n = (buf[5] >> 5) & 3; + frame_rate_ext_d = (buf[5] & 0x1f); + pc->progressive_sequence = buf[1] & (1 << 3); + + avctx->width = pc->width | (horiz_size_ext << 12); + avctx->height = pc->height | (vert_size_ext << 12); + avctx->frame_rate = pc->frame_rate * (frame_rate_ext_n + 1); + avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1); + avctx->codec_id = CODEC_ID_MPEG2VIDEO; + avctx->sub_id = 2; /* forces MPEG2 */ + } + break; + case 0x8: /* picture coding extension */ + if (bytes_left >= 5) { + top_field_first = buf[3] & (1 << 7); + repeat_first_field = buf[3] & (1 << 1); + progressive_frame = buf[4] & (1 << 7); + + /* check if we must repeat the frame */ + if (repeat_first_field) { + if (pc->progressive_sequence) { + if (top_field_first) + s->repeat_pict = 4; + else + s->repeat_pict = 2; + } else if (progressive_frame) { + s->repeat_pict = 1; + } + } + } + break; + } + } + break; + case -1: + goto the_end; + default: + /* we stop parsing when we encounter a slice. It ensures + that this function takes a negligible amount of time */ + if (start_code >= SLICE_MIN_START_CODE && + start_code <= SLICE_MAX_START_CODE) + goto the_end; + break; + } + } + the_end: ; +} + +static int mpegvideo_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext1 *pc1 = s->priv_data; + ParseContext *pc= &pc1->pc; + int next; + + next= ff_mpeg1_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + /* we have a full frame : we just parse the first few MPEG headers + to have the full timing information. The time take by this + function should be negligible for uncorrupted streams */ + mpegvideo_extract_headers(s, avctx, buf, buf_size); +#if 0 + printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", + s->pict_type, (double)avctx->frame_rate / avctx->frame_rate_base, s->repeat_pict); +#endif + + *poutbuf = (uint8_t *)buf; + *poutbuf_size = buf_size; + return next; +} + +void ff_parse_close(AVCodecParserContext *s) +{ + ParseContext *pc = s->priv_data; + + av_free(pc->buffer); +} + +static void parse1_close(AVCodecParserContext *s) +{ + ParseContext1 *pc1 = s->priv_data; + + av_free(pc1->pc.buffer); + av_free(pc1->enc); +} + +/*************************/ + +/* used by parser */ +/* XXX: make it use less memory */ +static int av_mpeg4_decode_header(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + ParseContext1 *pc = s1->priv_data; + MpegEncContext *s = pc->enc; + GetBitContext gb1, *gb = &gb1; + int ret; + + s->avctx = avctx; + s->current_picture_ptr = &s->current_picture; + + if (avctx->extradata_size && pc->first_picture){ + init_get_bits(gb, avctx->extradata, avctx->extradata_size*8); + ret = ff_mpeg4_decode_picture_header(s, gb); + } + + init_get_bits(gb, buf, 8 * buf_size); + ret = ff_mpeg4_decode_picture_header(s, gb); + if (s->width) { + avctx->width = s->width; + avctx->height = s->height; + } + pc->first_picture = 0; + return ret; +} + +int mpeg4video_parse_init(AVCodecParserContext *s) +{ + ParseContext1 *pc = s->priv_data; + + pc->enc = av_mallocz(sizeof(MpegEncContext)); + if (!pc->enc) + return -1; + pc->first_picture = 1; + return 0; +} + +static int mpeg4video_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + next= ff_mpeg4_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + av_mpeg4_decode_header(s, avctx, buf, buf_size); + + *poutbuf = (uint8_t *)buf; + *poutbuf_size = buf_size; + return next; +} + +/*************************/ + +typedef struct MpegAudioParseContext { + uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */ + uint8_t *inbuf_ptr; + int frame_size; + int free_format_frame_size; + int free_format_next_header; +} MpegAudioParseContext; + +#define MPA_HEADER_SIZE 4 + +/* header + layer + bitrate + freq + lsf/mpeg25 */ +#define SAME_HEADER_MASK \ + (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19)) + +static int mpegaudio_parse_init(AVCodecParserContext *s1) +{ + MpegAudioParseContext *s = s1->priv_data; + s->inbuf_ptr = s->inbuf; + return 0; +} + +static int mpegaudio_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + MpegAudioParseContext *s = s1->priv_data; + int len, ret; + uint32_t header; + const uint8_t *buf_ptr; + + *poutbuf = NULL; + *poutbuf_size = 0; + buf_ptr = buf; + while (buf_size > 0) { + len = s->inbuf_ptr - s->inbuf; + if (s->frame_size == 0) { + /* special case for next header for first frame in free + format case (XXX: find a simpler method) */ + if (s->free_format_next_header != 0) { + s->inbuf[0] = s->free_format_next_header >> 24; + s->inbuf[1] = s->free_format_next_header >> 16; + s->inbuf[2] = s->free_format_next_header >> 8; + s->inbuf[3] = s->free_format_next_header; + s->inbuf_ptr = s->inbuf + 4; + s->free_format_next_header = 0; + goto got_header; + } + /* no header seen : find one. We need at least MPA_HEADER_SIZE + bytes to parse it */ + len = MPA_HEADER_SIZE - len; + if (len > buf_size) + len = buf_size; + if (len > 0) { + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + buf_size -= len; + s->inbuf_ptr += len; + } + if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) { + got_header: + header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | + (s->inbuf[2] << 8) | s->inbuf[3]; + + ret = mpa_decode_header(avctx, header); + if (ret < 0) { + /* no sync found : move by one byte (inefficient, but simple!) */ + memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); + s->inbuf_ptr--; + dprintf("skip %x\n", header); + /* reset free format frame size to give a chance + to get a new bitrate */ + s->free_format_frame_size = 0; + } else { + s->frame_size = ret; +#if 0 + /* free format: prepare to compute frame size */ + if (decode_header(s, header) == 1) { + s->frame_size = -1; + } +#endif + } + } + } else +#if 0 + if (s->frame_size == -1) { + /* free format : find next sync to compute frame size */ + len = MPA_MAX_CODED_FRAME_SIZE - len; + if (len > buf_size) + len = buf_size; + if (len == 0) { + /* frame too long: resync */ + s->frame_size = 0; + memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); + s->inbuf_ptr--; + } else { + uint8_t *p, *pend; + uint32_t header1; + int padding; + + memcpy(s->inbuf_ptr, buf_ptr, len); + /* check for header */ + p = s->inbuf_ptr - 3; + pend = s->inbuf_ptr + len - 4; + while (p <= pend) { + header = (p[0] << 24) | (p[1] << 16) | + (p[2] << 8) | p[3]; + header1 = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | + (s->inbuf[2] << 8) | s->inbuf[3]; + /* check with high probability that we have a + valid header */ + if ((header & SAME_HEADER_MASK) == + (header1 & SAME_HEADER_MASK)) { + /* header found: update pointers */ + len = (p + 4) - s->inbuf_ptr; + buf_ptr += len; + buf_size -= len; + s->inbuf_ptr = p; + /* compute frame size */ + s->free_format_next_header = header; + s->free_format_frame_size = s->inbuf_ptr - s->inbuf; + padding = (header1 >> 9) & 1; + if (s->layer == 1) + s->free_format_frame_size -= padding * 4; + else + s->free_format_frame_size -= padding; + dprintf("free frame size=%d padding=%d\n", + s->free_format_frame_size, padding); + decode_header(s, header1); + goto next_data; + } + p++; + } + /* not found: simply increase pointers */ + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + } + } else +#endif + if (len < s->frame_size) { + if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE) + s->frame_size = MPA_MAX_CODED_FRAME_SIZE; + len = s->frame_size - len; + if (len > buf_size) + len = buf_size; + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + } + // next_data: + if (s->frame_size > 0 && + (s->inbuf_ptr - s->inbuf) >= s->frame_size) { + *poutbuf = s->inbuf; + *poutbuf_size = s->inbuf_ptr - s->inbuf; + s->inbuf_ptr = s->inbuf; + s->frame_size = 0; + break; + } + } + return buf_ptr - buf; +} + +#ifdef CONFIG_AC3 +extern int a52_syncinfo (const uint8_t * buf, int * flags, + int * sample_rate, int * bit_rate); + +typedef struct AC3ParseContext { + uint8_t inbuf[4096]; /* input buffer */ + uint8_t *inbuf_ptr; + int frame_size; + int flags; +} AC3ParseContext; + +#define AC3_HEADER_SIZE 7 +#define A52_LFE 16 + +static int ac3_parse_init(AVCodecParserContext *s1) +{ + AC3ParseContext *s = s1->priv_data; + s->inbuf_ptr = s->inbuf; + return 0; +} + +static int ac3_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + AC3ParseContext *s = s1->priv_data; + const uint8_t *buf_ptr; + int len, sample_rate, bit_rate; + static const int ac3_channels[8] = { + 2, 1, 2, 3, 3, 4, 4, 5 + }; + + *poutbuf = NULL; + *poutbuf_size = 0; + + buf_ptr = buf; + while (buf_size > 0) { + len = s->inbuf_ptr - s->inbuf; + if (s->frame_size == 0) { + /* no header seen : find one. We need at least 7 bytes to parse it */ + len = AC3_HEADER_SIZE - len; + if (len > buf_size) + len = buf_size; + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + if ((s->inbuf_ptr - s->inbuf) == AC3_HEADER_SIZE) { + len = a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate); + if (len == 0) { + /* no sync found : move by one byte (inefficient, but simple!) */ + memmove(s->inbuf, s->inbuf + 1, AC3_HEADER_SIZE - 1); + s->inbuf_ptr--; + } else { + s->frame_size = len; + /* update codec info */ + avctx->sample_rate = sample_rate; + /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */ + if(avctx->channels!=1 && avctx->channels!=2){ + avctx->channels = ac3_channels[s->flags & 7]; + if (s->flags & A52_LFE) + avctx->channels++; + } + avctx->bit_rate = bit_rate; + avctx->frame_size = 6 * 256; + } + } + } else if (len < s->frame_size) { + len = s->frame_size - len; + if (len > buf_size) + len = buf_size; + + memcpy(s->inbuf_ptr, buf_ptr, len); + buf_ptr += len; + s->inbuf_ptr += len; + buf_size -= len; + } else { + *poutbuf = s->inbuf; + *poutbuf_size = s->frame_size; + s->inbuf_ptr = s->inbuf; + s->frame_size = 0; + break; + } + } + return buf_ptr - buf; +} +#endif + +AVCodecParser mpegvideo_parser = { + { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO }, + sizeof(ParseContext1), + NULL, + mpegvideo_parse, + parse1_close, +}; + +AVCodecParser mpeg4video_parser = { + { CODEC_ID_MPEG4 }, + sizeof(ParseContext1), + mpeg4video_parse_init, + mpeg4video_parse, + parse1_close, +}; + +AVCodecParser mpegaudio_parser = { + { CODEC_ID_MP2, CODEC_ID_MP3 }, + sizeof(MpegAudioParseContext), + mpegaudio_parse_init, + mpegaudio_parse, + NULL, +}; + +#ifdef CONFIG_AC3 +AVCodecParser ac3_parser = { + { CODEC_ID_AC3 }, + sizeof(AC3ParseContext), + ac3_parse_init, + ac3_parse, + NULL, +}; +#endif diff --git a/src/libffmpeg/libavcodec/ppc/dsputil_altivec.c b/src/libffmpeg/libavcodec/ppc/dsputil_altivec.c index 1bc6fb009..ff6e870b7 100644 --- a/src/libffmpeg/libavcodec/ppc/dsputil_altivec.c +++ b/src/libffmpeg/libavcodec/ppc/dsputil_altivec.c @@ -1302,52 +1302,32 @@ POWERPC_PERF_STOP_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1); #endif /* ALTIVEC_USE_REFERENCE_C_CODE */ } +#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 330) int hadamard8_diff8x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){ POWERPC_PERF_DECLARE(altivec_hadamard8_diff8x8_num, 1); int sum; POWERPC_PERF_START_COUNT(altivec_hadamard8_diff8x8_num, 1); register const_vector unsigned char vzero = (const_vector unsigned char)vec_splat_u8(0); register vector signed short temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; -#ifdef CONFIG_DARWIN { - register const_vector signed short vprod1 = (const_vector signed short)( 1,-1, 1,-1, 1,-1, 1,-1); - register const_vector signed short vprod2 = (const_vector signed short)( 1, 1,-1,-1, 1, 1,-1,-1); - register const_vector signed short vprod3 = (const_vector signed short)( 1, 1, 1, 1,-1,-1,-1,-1); + register const_vector signed short vprod1 = (const_vector signed short)AVV( 1,-1, 1,-1, 1,-1, 1,-1); + register const_vector signed short vprod2 = (const_vector signed short)AVV( 1, 1,-1,-1, 1, 1,-1,-1); + register const_vector signed short vprod3 = (const_vector signed short)AVV( 1, 1, 1, 1,-1,-1,-1,-1); register const_vector unsigned char perm1 = (const_vector unsigned char) - (0x02, 0x03, 0x00, 0x01, + AVV(0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D); register const_vector unsigned char perm2 = (const_vector unsigned char) - (0x04, 0x05, 0x06, 0x07, + AVV(0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B); register const_vector unsigned char perm3 = (const_vector unsigned char) - (0x08, 0x09, 0x0A, 0x0B, + AVV(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); -#else - register const_vector signed short vprod1 = (const_vector signed short){ 1,-1, 1,-1, 1,-1, 1,-1}; - register const_vector signed short vprod2 = (const_vector signed short){ 1, 1,-1,-1, 1, 1,-1,-1}; - register const_vector signed short vprod3 = (const_vector signed short){ 1, 1, 1, 1,-1,-1,-1,-1}; - register const_vector unsigned char perm1 = (const_vector unsigned char) - {0x02, 0x03, 0x00, 0x01, - 0x06, 0x07, 0x04, 0x05, - 0x0A, 0x0B, 0x08, 0x09, - 0x0E, 0x0F, 0x0C, 0x0D}; - register const_vector unsigned char perm2 = (const_vector unsigned char) - {0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, - 0x0C, 0x0D, 0x0E, 0x0F, - 0x08, 0x09, 0x0A, 0x0B}; - register const_vector unsigned char perm3 = (const_vector unsigned char) - {0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07}; -#endif #define ONEITERBUTTERFLY(i, res) \ { \ @@ -1475,45 +1455,25 @@ static int hadamard8_diff16x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, temp7S asm ("v15"); register const_vector unsigned char vzero asm ("v31")= (const_vector unsigned char)vec_splat_u8(0); { -#ifdef CONFIG_DARWIN - register const_vector signed short vprod1 asm ("v16")= (const_vector signed short)( 1,-1, 1,-1, 1,-1, 1,-1); - register const_vector signed short vprod2 asm ("v17")= (const_vector signed short)( 1, 1,-1,-1, 1, 1,-1,-1); - register const_vector signed short vprod3 asm ("v18")= (const_vector signed short)( 1, 1, 1, 1,-1,-1,-1,-1); + register const_vector signed short vprod1 asm ("v16")= (const_vector signed short)AVV( 1,-1, 1,-1, 1,-1, 1,-1); + register const_vector signed short vprod2 asm ("v17")= (const_vector signed short)AVV( 1, 1,-1,-1, 1, 1,-1,-1); + register const_vector signed short vprod3 asm ("v18")= (const_vector signed short)AVV( 1, 1, 1, 1,-1,-1,-1,-1); register const_vector unsigned char perm1 asm ("v19")= (const_vector unsigned char) - (0x02, 0x03, 0x00, 0x01, + AVV(0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D); register const_vector unsigned char perm2 asm ("v20")= (const_vector unsigned char) - (0x04, 0x05, 0x06, 0x07, + AVV(0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B); register const_vector unsigned char perm3 asm ("v21")= (const_vector unsigned char) - (0x08, 0x09, 0x0A, 0x0B, + AVV(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); -#else - register const_vector signed short vprod1 = (const_vector signed short){ 1,-1, 1,-1, 1,-1, 1,-1}; - register const_vector signed short vprod2 = (const_vector signed short){ 1, 1,-1,-1, 1, 1,-1,-1}; - register const_vector signed short vprod3 = (const_vector signed short){ 1, 1, 1, 1,-1,-1,-1,-1}; - register const_vector unsigned char perm1 = (const_vector unsigned char) - {0x02, 0x03, 0x00, 0x01, - 0x06, 0x07, 0x04, 0x05, - 0x0A, 0x0B, 0x08, 0x09, - 0x0E, 0x0F, 0x0C, 0x0D}; - register const_vector unsigned char perm2 = (const_vector unsigned char) - {0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, - 0x0C, 0x0D, 0x0E, 0x0F, - 0x08, 0x09, 0x0A, 0x0B}; - register const_vector unsigned char perm3 = (const_vector unsigned char) - {0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07}; -#endif + #define ONEITERBUTTERFLY(i, res1, res2) \ { \ register vector unsigned char src1 asm ("v22"), src2 asm ("v23"); \ @@ -1652,6 +1612,7 @@ POWERPC_PERF_START_COUNT(altivec_hadamard8_diff16_num, 1); POWERPC_PERF_STOP_COUNT(altivec_hadamard8_diff16_num, 1); return score; } +#endif int has_altivec(void) { diff --git a/src/libffmpeg/libavcodec/ppc/dsputil_ppc.c b/src/libffmpeg/libavcodec/ppc/dsputil_ppc.c index b70de7328..55a4587f9 100644 --- a/src/libffmpeg/libavcodec/ppc/dsputil_ppc.c +++ b/src/libffmpeg/libavcodec/ppc/dsputil_ppc.c @@ -279,8 +279,10 @@ void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx) c->gmc1 = gmc1_altivec; +#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 330) c->hadamard8_diff[0] = hadamard8_diff16_altivec; c->hadamard8_diff[1] = hadamard8_diff8x8_altivec; +#endif #ifdef CONFIG_ENCODERS if (avctx->dct_algo == FF_DCT_AUTO || diff --git a/src/libffmpeg/libavcodec/svq1.c b/src/libffmpeg/libavcodec/svq1.c index 781194f03..8fec2a31e 100644 --- a/src/libffmpeg/libavcodec/svq1.c +++ b/src/libffmpeg/libavcodec/svq1.c @@ -17,14 +17,18 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * (SVQ1 Decoder) * Ported to mplayer by Arpi <arpi@thot.banki.hu> * Ported to libavcodec by Nick Kurshev <nickols_k@mail.ru> * + * SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net> */ /** * @file svq1.c - * Sorenson Vector Quantizer #1 (SVQ1) video decoder. + * Sorenson Vector Quantizer #1 (SVQ1) video codec. + * For more information of the SVQ1 algorithm, visit: + * http://www.pcisys.net/~melanson/codecs/ */ @@ -33,6 +37,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <limits.h> #include "common.h" #include "avcodec.h" @@ -40,6 +45,9 @@ #include "mpegvideo.h" #include "bswap.h" +#undef NDEBUG +#include <assert.h> + static VLC svq1_block_type; static VLC svq1_motion_component; static VLC svq1_intra_multistage[6]; @@ -54,6 +62,34 @@ static VLC svq1_inter_mean; #define SVQ1_BLOCK_INTER_4V 2 #define SVQ1_BLOCK_INTRA 3 +typedef struct SVQ1Context { + + AVCodecContext *avctx; + DSPContext dsp; + AVFrame picture; + AVFrame current_picture; + AVFrame last_picture; + PutBitContext pb; + GetBitContext gb; + + PutBitContext reorder_pb[6]; //why ooh why this sick breadth first order, everything is slower and more complex + + int frame_width; + int frame_height; + + /* Y plane block dimensions */ + int y_block_width; + int y_block_height; + + /* U & V plane (C planes) block dimensions */ + int c_block_width; + int c_block_height; + + unsigned char *c_plane; + + int64_t rd_total; +} SVQ1Context; + /* motion vector (prediction) */ typedef struct svq1_pmv_s { int x; @@ -243,7 +279,7 @@ static int svq1_decode_block_intra (GetBitContext *bitbuf, uint8_t *pixels, int if ((stages > 0) && (level >= 4)) { #ifdef DEBUG_SVQ1 - printf("Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level); + av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level); #endif return -1; /* invalid vector */ } @@ -293,7 +329,7 @@ static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels, if ((stages > 0) && (level >= 4)) { #ifdef DEBUG_SVQ1 - printf("Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level); + av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level); #endif return -1; /* invalid vector */ } @@ -381,7 +417,7 @@ static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf, int w= (s->width+15)&~15; int h= (s->height+15)&~15; if(x + (mv.x >> 1)<0 || y + (mv.y >> 1)<0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16> h) - printf("%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1)); + av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1)); #endif src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch]; @@ -464,7 +500,7 @@ static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf, int w= (s->width+15)&~15; int h= (s->height+15)&~15; if(x + (mvx >> 1)<0 || y + (mvy >> 1)<0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8> h) - printf("%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1)); + av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1)); #endif src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch]; dst = current; @@ -512,7 +548,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, if (result != 0) { #ifdef DEBUG_SVQ1 - printf("Error in svq1_motion_inter_block %i\n",result); + av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_block %i\n",result); #endif break; } @@ -525,7 +561,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, if (result != 0) { #ifdef DEBUG_SVQ1 - printf("Error in svq1_motion_inter_4v_block %i\n",result); + av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_4v_block %i\n",result); #endif break; } @@ -604,7 +640,7 @@ static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) { csum = svq1_packet_checksum ((uint8_t *)bitbuf->buffer, bitbuf->size_in_bits>>3, csum); -// printf ("%s checksum (%02x) for packet data\n", +// av_log(s->avctx, AV_LOG_INFO, "%s checksum (%02x) for packet data\n", // (csum == 0) ? "correct" : "incorrect", csum); } @@ -692,13 +728,13 @@ static int svq1_decode_frame(AVCodecContext *avctx, if (result != 0) { #ifdef DEBUG_SVQ1 - printf("Error in svq1_decode_frame_header %i\n",result); + av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_frame_header %i\n",result); #endif return result; } //FIXME this avoids some confusion for "B frames" without 2 references - //this should be removed after libavcodec can handle more flaxible picture types & ordering + //this should be removed after libavcodec can handle more flexible picture types & ordering if(s->pict_type==B_TYPE && s->last_picture_ptr==NULL) return buf_size; if(avctx->hurry_up && s->pict_type==B_TYPE) return buf_size; @@ -735,9 +771,9 @@ static int svq1_decode_frame(AVCodecContext *avctx, result = svq1_decode_block_intra (&s->gb, ¤t[x], linesize); if (result != 0) { -#ifdef DEBUG_SVQ1 - printf("Error in svq1_decode_block %i (keyframe)\n",result); -#endif +//#ifdef DEBUG_SVQ1 + av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_block %i (keyframe)\n",result); +//#endif return result; } } @@ -755,7 +791,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, if (result != 0) { #ifdef DEBUG_SVQ1 - printf("Error in svq1_decode_delta_block %i\n",result); + av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_delta_block %i\n",result); #endif return result; } @@ -791,6 +827,7 @@ static int svq1_decode_init(AVCodecContext *avctx) s->codec_id= avctx->codec->id; avctx->pix_fmt = PIX_FMT_YUV410P; avctx->has_b_frames= 1; // not true, but DP frames and these behave like unidirectional b frames + s->flags= avctx->flags; if (MPV_common_init(s) < 0) return -1; init_vlc(&svq1_block_type, 2, 4, @@ -798,8 +835,8 @@ static int svq1_decode_init(AVCodecContext *avctx) &svq1_block_type_vlc[0][0], 2, 1); init_vlc(&svq1_motion_component, 7, 65, - &svq1_motion_component_vlc[0][1], 4, 2, - &svq1_motion_component_vlc[0][0], 4, 2); + &svq1_motion_component_vlc[0][1], 2, 1, + &svq1_motion_component_vlc[0][0], 2, 1); for (i = 0; i < 6; i++) { init_vlc(&svq1_intra_multistage[i], 3, 8, @@ -829,6 +866,912 @@ static int svq1_decode_end(AVCodecContext *avctx) return 0; } +static void svq1_write_header(SVQ1Context *s, int frame_type) +{ + /* frame code */ + put_bits(&s->pb, 22, 0x20); + + /* temporal reference (sure hope this is a "don't care") */ + put_bits(&s->pb, 8, 0x00); + + /* frame type */ + put_bits(&s->pb, 2, frame_type - 1); + + if (frame_type == I_TYPE) { + + /* no checksum since frame code is 0x20 */ + + /* no embedded string either */ + + /* output 5 unknown bits (2 + 2 + 1) */ + put_bits(&s->pb, 5, 0); + + /* forget about matching up resolutions, just use the free-form + * resolution code (7) for now */ + put_bits(&s->pb, 3, 7); + put_bits(&s->pb, 12, s->frame_width); + put_bits(&s->pb, 12, s->frame_height); + + } + + /* no checksum or extra data (next 2 bits get 0) */ + put_bits(&s->pb, 2, 0); +} + +int level_sizes[6] = { 8, 16, 32, 64, 128, 256 }; +int level_log2_sizes[6] = { 3, 4, 5, 6, 7, 8 }; + +#define IABS(x) ((x < 0) ? (-(x)) : x) + + + +//#define USE_MAD_ALGORITHM + +#ifdef USE_MAD_ALGORITHM + +#define QUALITY_THRESHOLD 100 +#define THRESHOLD_MULTIPLIER 0.6 + +/* This function calculates vector differences using mean absolute + * difference (MAD). */ + +static int encode_vector(SVQ1Context *s, unsigned char *vector, + unsigned int level, int threshold) +{ + int i, j, k; + int mean; + signed short work_vector[256]; + int best_codebook; + int best_score; + int multistage_codebooks[6]; + int number_of_stages = 0; + int8_t *current_codebook; + int total_deviation; + int ret; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " ** recursive entry point: encoding level %d vector at threshold %d\n", + level, threshold); +#endif + if (level > 5) { + av_log(s->avctx, AV_LOG_INFO, " help! level %d > 5\n", level); + return 0; + } + +#ifdef DEBUG_SVQ1 +for (i = 0; i < level_sizes[level]; i++) + av_log(s->avctx, AV_LOG_INFO, " %02X", vector[i]); +av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + /* calculate the mean */ + mean = 0; + for (i = 0; i < level_sizes[level]; i++) + mean += vector[i]; + mean >>= level_log2_sizes[level]; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " vector mean = 0x%02X\n", mean); +#endif + + /* remove the mean from the vector */ + total_deviation = 0; + for (i = 0; i < level_sizes[level]; i++) { + work_vector[i] = (signed short)vector[i] - mean; + total_deviation += IABS(work_vector[i]); +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " %d", work_vector[i]); +#endif + } + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "\n total deviation = %d\n", total_deviation); +#endif + + if (total_deviation < threshold) { + +#ifdef DEBUG_SVQ1 + av_log(s->avctx, AV_LOG_INFO, " mean-only encoding found for level %d vector, mean = %d\n", + level, mean); +#endif + + /* indicate that this is the end of the subdivisions */ + if (level > 0) + put_bits(&s->pb, 1, 0); + + /* index 1 in the table indicates mean-only encoding */ + put_bits(&s->pb, svq1_intra_multistage_vlc[level][1][1], + svq1_intra_multistage_vlc[level][1][0]); + put_bits(&s->pb, svq1_intra_mean_vlc[mean][1], + svq1_intra_mean_vlc[mean][0]); + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " mean-only L%d, VLC = (0x%X, %d), mean = %d (0x%X, %d)\n", + level, + svq1_intra_multistage_vlc[level][1 + number_of_stages][0], + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + mean, + svq1_intra_mean_vlc[mean][0], + svq1_intra_mean_vlc[mean][1]); +#endif + + ret = 0; + + } else { + + if (level <= 3) { + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " multistage VQ search...\n"); +#endif + /* conduct multistage VQ search, for each stage... */ + for (i = 0; i < 6; i++) { + + best_codebook = 0; + best_score = 0x7FFFFFFF; + /* for each codebook in stage */ + for (j = 0; j < 16; j++) { + + total_deviation = 0; + current_codebook = + &svq1_intra_codebooks[level] + [i * level_sizes[level] * 16 + j * level_sizes[level]]; + /* calculate the total deviation for the vector */ + for (k = 0; k < level_sizes[level]; k++) { + total_deviation += + IABS(work_vector[k] - current_codebook[k]); + } + + /* lowest score so far? */ + if (total_deviation < best_score) { + best_score = total_deviation; + best_codebook = j; + } +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " after %d, %d, best codebook is %d with a score of %d (score was %d)\n", + i, j, best_codebook, best_score, total_deviation); +#endif + } + + /* apply the winning codebook to the work vector and check if + * the vector meets the quality threshold */ + total_deviation = 0; + current_codebook = + &svq1_intra_codebooks[level] + [i * level_sizes[level] * 16 + j * level_sizes[level]]; + multistage_codebooks[number_of_stages++] = best_codebook; + for (j = 0; j < level_sizes[level]; j++) { + work_vector[j] = work_vector[j] - current_codebook[j]; + total_deviation += IABS(work_vector[j]); + } + + /* do not go forward with the rest of the search if an acceptable + * codebook combination has been found */ + if (total_deviation < threshold) + break; + } + } + + if ((total_deviation < threshold) || (level == 0)) { +#ifdef DEBUG_SVQ1 + av_log(s->avctx, AV_LOG_INFO, " level %d VQ encoding found using mean %d and codebooks", level, mean); + for (i = 0; i < number_of_stages; i++) + av_log(s->avctx, AV_LOG_INFO, " %d", multistage_codebooks[i]); + av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + /* indicate that this is the end of the subdivisions */ + if (level > 0) + put_bits(&s->pb, 1, 0); + + /* output the encoding */ + put_bits(&s->pb, + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + svq1_intra_multistage_vlc[level][1 + number_of_stages][0]); + put_bits(&s->pb, svq1_intra_mean_vlc[mean][1], + svq1_intra_mean_vlc[mean][0]); +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " L%d: multistage = %d (0x%X, %d), mean = %d (0x%X, %d), codebooks = ", + level, + number_of_stages, + svq1_intra_multistage_vlc[level][1 + number_of_stages][0], + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + mean, + svq1_intra_mean_vlc[mean][0], + svq1_intra_mean_vlc[mean][1]); +#endif + + for (i = 0; i < number_of_stages; i++) +{ +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "%d ", multistage_codebooks[i]); +#endif + put_bits(&s->pb, 4, multistage_codebooks[i]); +} +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + ret = 0; + + } else { + + /* output a subdivision bit to the encoded stream and signal to + * the calling function that this vector could not be + * coded at the requested threshold and needs to be subdivided */ + put_bits(&s->pb, 1, 1); + ret = 1; + } + } + + return ret; +} + +#else + +#define QUALITY_THRESHOLD 100 +#define THRESHOLD_MULTIPLIER 0.6 + +/* This function calculates vector differences using mean square + * error (MSE). */ + +static int encode_vector(SVQ1Context *s, unsigned char *vector, + unsigned int level, int threshold) +{ + int i, j, k; + int mean; + signed short work_vector[256]; + int best_codebook; + int best_score; + int multistage_codebooks[6]; + int number_of_stages = 0; + int8_t *current_codebook; + int mse; + int diff; + int ret; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " ** recursive entry point: encoding level %d vector at threshold %d\n", + level, threshold); +#endif + if (level > 5) { + av_log(s->avctx, AV_LOG_INFO, " help! level %d > 5\n", level); + return 0; + } + +#ifdef DEBUG_SVQ1 +for (i = 0; i < level_sizes[level]; i++) + av_log(s->avctx, AV_LOG_INFO, " %02X", vector[i]); +av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + /* calculate the mean */ + mean = 0; + for (i = 0; i < level_sizes[level]; i++) + mean += vector[i]; + mean >>= level_log2_sizes[level]; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " vector mean = 0x%02X\n", mean); +#endif + + /* remove the mean from the vector and compute the resulting MSE */ + mse = 0; + for (i = 0; i < level_sizes[level]; i++) { + work_vector[i] = (signed short)vector[i] - mean; + mse += (work_vector[i] * work_vector[i]); +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " %d", work_vector[i]); +#endif + } + mse >>= level_log2_sizes[level]; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "\n MSE = %d\n", mse); +#endif + + if (mse < threshold) { + +#ifdef DEBUG_SVQ1 + av_log(s->avctx, AV_LOG_INFO, " mean-only encoding found for level %d vector, mean = %d\n", + level, mean); +#endif + + /* indicate that this is the end of the subdivisions */ + if (level > 0) + put_bits(&s->pb, 1, 0); + + /* index 1 in the table indicates mean-only encoding */ + put_bits(&s->pb, svq1_intra_multistage_vlc[level][1][1], + svq1_intra_multistage_vlc[level][1][0]); + put_bits(&s->pb, svq1_intra_mean_vlc[mean][1], + svq1_intra_mean_vlc[mean][0]); + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " mean-only L%d, VLC = (0x%X, %d), mean = %d (0x%X, %d)\n", + level, + svq1_intra_multistage_vlc[level][1 + number_of_stages][0], + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + mean, + svq1_intra_mean_vlc[mean][0], + svq1_intra_mean_vlc[mean][1]); +#endif + + ret = 0; + + } else { + + if (level <= 3) { + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " multistage VQ search...\n"); +#endif + /* conduct multistage VQ search, for each stage... */ + for (i = 0; i < 6; i++) { + + best_codebook = 0; + best_score = 0x7FFFFFFF; + /* for each codebook in stage */ + for (j = 0; j < 16; j++) { + + mse = 0; + current_codebook = + &svq1_intra_codebooks[level] + [i * level_sizes[level] * 16 + j * level_sizes[level]]; + /* calculate the MSE for this vector */ + for (k = 0; k < level_sizes[level]; k++) { + diff = work_vector[k] - current_codebook[k]; + mse += (diff * diff); + } + mse >>= level_log2_sizes[level]; + + /* lowest score so far? */ + if (mse < best_score) { + best_score = mse; + best_codebook = j; + } +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " after %d, %d, best codebook is %d with a score of %d (score was %d)\n", + i, j, best_codebook, best_score, mse); +#endif + } + + /* apply the winning codebook to the work vector and check if + * the vector meets the quality threshold */ + mse = 0; + current_codebook = + &svq1_intra_codebooks[level] + [i * level_sizes[level] * 16 + j * level_sizes[level]]; + multistage_codebooks[number_of_stages++] = best_codebook; + for (j = 0; j < level_sizes[level]; j++) { + work_vector[j] = work_vector[j] - current_codebook[j]; + mse += (work_vector[j] * work_vector[j]); + } + mse >>= level_log2_sizes[level]; + + /* do not go forward with the rest of the search if an acceptable + * codebook combination has been found */ + if (mse < threshold) + break; + } + } + + if ((mse < threshold) || (level == 0)) { +#ifdef DEBUG_SVQ1 + av_log(s->avctx, AV_LOG_INFO, " level %d VQ encoding found using mean %d and codebooks", level, mean); + for (i = 0; i < number_of_stages; i++) + av_log(s->avctx, AV_LOG_INFO, " %d", multistage_codebooks[i]); + av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + /* indicate that this is the end of the subdivisions */ + if (level > 0) + put_bits(&s->pb, 1, 0); + + /* output the encoding */ + put_bits(&s->pb, + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + svq1_intra_multistage_vlc[level][1 + number_of_stages][0]); + put_bits(&s->pb, svq1_intra_mean_vlc[mean][1], + svq1_intra_mean_vlc[mean][0]); +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " L%d: multistage = %d (0x%X, %d), mean = %d (0x%X, %d), codebooks = ", + level, + number_of_stages, + svq1_intra_multistage_vlc[level][1 + number_of_stages][0], + svq1_intra_multistage_vlc[level][1 + number_of_stages][1], + mean, + svq1_intra_mean_vlc[mean][0], + svq1_intra_mean_vlc[mean][1]); +#endif + + for (i = 0; i < number_of_stages; i++) +{ +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "%d ", multistage_codebooks[i]); +#endif + put_bits(&s->pb, 4, multistage_codebooks[i]); +} +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "\n"); +#endif + + ret = 0; + + } else { + + /* output a subdivision bit to the encoded stream and signal to + * the calling function that this vector could not be + * coded at the requested threshold and needs to be subdivided */ + put_bits(&s->pb, 1, 1); + ret = 1; + } + } + + return ret; +} +#endif + +static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra){ + int count, y, x, i, j, split, best_mean, best_score, best_count; + int best_vector[6]; + int block_sum[7]= {0, 0, 0, 0, 0, 0}; + int w= 2<<((level+2)>>1); + int h= 2<<((level+1)>>1); + int size=w*h; + int16_t block[7][256]; + const int8_t *codebook_sum, *codebook; + const uint16_t (*mean_vlc)[2]; + const uint8_t (*multistage_vlc)[2]; + + best_score=0; + //FIXME optimize, this doenst need to be done multiple times + if(intra){ + codebook_sum= svq1_intra_codebook_sum[level]; + codebook= svq1_intra_codebooks[level]; + mean_vlc= svq1_intra_mean_vlc; + multistage_vlc= svq1_intra_multistage_vlc[level]; + for(y=0; y<h; y++){ + for(x=0; x<w; x++){ + int v= src[x + y*stride]; + block[0][x + w*y]= v; + best_score += v*v; + block_sum[0] += v; + } + } + }else{ + codebook_sum= svq1_inter_codebook_sum[level]; + codebook= svq1_inter_codebooks[level]; + mean_vlc= svq1_inter_mean_vlc + 256; + multistage_vlc= svq1_inter_multistage_vlc[level]; + for(y=0; y<h; y++){ + for(x=0; x<w; x++){ + int v= src[x + y*stride] - ref[x + y*stride]; + block[0][x + w*y]= v; + best_score += v*v; + block_sum[0] += v; + } + } + } + + best_count=0; + best_score -= ((block_sum[0]*block_sum[0])>>(level+3)); + best_mean= (block_sum[0] + (size>>1)) >> (level+3); + + if(level<4){ + for(count=1; count<7; count++){ + int best_vector_score= INT_MAX; + int best_vector_sum=-999, best_vector_mean=-999; + const int stage= count-1; + const int8_t *vector; + + for(i=0; i<16; i++){ + int sum= codebook_sum[stage*16 + i]; + int sqr=0; + int diff, mean, score; + + vector = codebook + stage*size*16 + i*size; + + for(j=0; j<size; j++){ + int v= vector[j]; + sqr += (v - block[stage][j])*(v - block[stage][j]); + } + diff= block_sum[stage] - sum; + mean= (diff + (size>>1)) >> (level+3); + assert(mean >-300 && mean<300); + if(intra) mean= clip(mean, 0, 255); + else mean= clip(mean, -256, 255); + score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow + if(score < best_vector_score){ + best_vector_score= score; + best_vector[stage]= i; + best_vector_sum= sum; + best_vector_mean= mean; + } + } + assert(best_vector_mean != -999); + vector= codebook + stage*size*16 + best_vector[stage]*size; + for(j=0; j<size; j++){ + block[stage+1][j] = block[stage][j] - vector[j]; + } + block_sum[stage+1]= block_sum[stage] - best_vector_sum; + best_vector_score += + lambda*(+ 1 + 4*count + + multistage_vlc[1+count][1] + + mean_vlc[best_vector_mean][1]); + + if(best_vector_score < best_score){ + best_score= best_vector_score; + best_count= count; + best_mean= best_vector_mean; + } + } + } + + split=0; + if(best_score > threshold && level){ + int score=0; + int offset= (level&1) ? stride*h/2 : w/2; + PutBitContext backup[6]; + + for(i=level-1; i>=0; i--){ + backup[i]= s->reorder_pb[i]; + } + score += encode_block(s, src , ref , decoded , stride, level-1, threshold>>1, lambda, intra); + score += encode_block(s, src + offset, ref + offset, decoded + offset, stride, level-1, threshold>>1, lambda, intra); + score += lambda; + + if(score < best_score){ + best_score= score; + split=1; + }else{ + for(i=level-1; i>=0; i--){ + s->reorder_pb[i]= backup[i]; + } + } + } + if (level > 0) + put_bits(&s->reorder_pb[level], 1, split); + + if(!split){ + assert((best_mean >= 0 && best_mean<256) || !intra); + assert(best_mean >= -256 && best_mean<256); + assert(best_count >=0 && best_count<7); + assert(level<4 || best_count==0); + + /* output the encoding */ + put_bits(&s->reorder_pb[level], + multistage_vlc[1 + best_count][1], + multistage_vlc[1 + best_count][0]); + put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1], + mean_vlc[best_mean][0]); + + for (i = 0; i < best_count; i++){ + assert(best_vector[i]>=0 && best_vector[i]<16); + put_bits(&s->reorder_pb[level], 4, best_vector[i]); + } + + for(y=0; y<h; y++){ + for(x=0; x<w; x++){ + decoded[x + y*stride]= src[x + y*stride] - block[best_count][x + w*y] + best_mean; + } + } + } + + return best_score; +} + +static void svq1_encode_plane(SVQ1Context *s, unsigned char *src_plane, unsigned char *ref_plane, unsigned char *decoded_plane, + int width, int height, int src_stride, int stride) +{ + unsigned char buffer0[256]; + unsigned char buffer1[256]; + int current_buffer; + unsigned char *vector; + unsigned char *subvectors; + int vector_count; + int subvector_count; + int x, y; + int i, j; + int block_width, block_height; + int left_edge; + int level; + int threshold[6]; + const int lambda= (s->picture.quality*s->picture.quality) >> (2*FF_LAMBDA_SHIFT); + +static int frame = 0; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "********* frame #%d\n", frame++); +#endif + + /* figure out the acceptable level thresholds in advance */ + threshold[5] = QUALITY_THRESHOLD; + for (level = 4; level >= 0; level--) + threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER; + + block_width = (width + 15) / 16; + block_height = (height + 15) / 16; + + for (y = 0; y < block_height; y++) { + uint8_t src[stride*16]; + + for(i=0; i<16 && i + 16*y<height; i++){ + memcpy(&src[i*stride], &src_plane[(i+16*y)*src_stride], width); + for(x=width; x<16*block_width; x++) + src[i*stride+x]= src[i*stride+x-1]; + } + for(; i<16 && i + 16*y<16*block_height; i++) + memcpy(&src[i*stride], &src[(i-1)*stride], 16*block_width); + + for (x = 0; x < block_width; x++) { + uint8_t reorder_buffer[2][6][7*32]; + int count[2][6]; + int offset = y * 16 * stride + x * 16; + uint8_t *decoded= decoded_plane + offset; + uint8_t *ref= ref_plane + offset; + int score[2]={0,0}, best; + uint8_t temp[16*stride]; + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, "* level 5 vector @ %d, %d:\n", x * 16, y * 16); +#endif + + for(i=0; i<6; i++){ + init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], 7*32); + } + if(s->picture.pict_type == P_TYPE){ + const uint8_t *vlc= svq1_block_type_vlc[SVQ1_BLOCK_INTRA]; + put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); + score[0]= vlc[1]*lambda; + } + score[0]+= encode_block(s, src+16*x, ref, temp, stride, 5, 64, lambda, 1); + for(i=0; i<6; i++){ + count[0][i]= put_bits_count(&s->reorder_pb[i]); + flush_put_bits(&s->reorder_pb[i]); + init_put_bits(&s->reorder_pb[i], reorder_buffer[1][i], 7*32); + } + if(s->picture.pict_type == P_TYPE){ + const uint8_t *vlc= svq1_block_type_vlc[SVQ1_BLOCK_INTER]; + put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); + score[1] = vlc[1]*lambda; + for(i=0; i<2; i++){ + vlc= svq1_motion_component_vlc[32]; + put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); + score[1] += vlc[1]*lambda; + } + + score[1]+= encode_block(s, src+16*x, ref, decoded, stride, 5, 64, lambda, 0); + best= score[1] <= score[0]; + if(best==1){ + for(i=0; i<6; i++){ + count[1][i]= put_bits_count(&s->reorder_pb[i]); + flush_put_bits(&s->reorder_pb[i]); + } + } + }else + best= 0; + + s->rd_total += score[best]; + + for(i=5; i>=0; i--){ + ff_copy_bits(&s->pb, reorder_buffer[best][i], count[best][i]); + } + if(best==0){ + s->dsp.put_pixels_tab[0][0](decoded, temp, stride, 16); + } + +#if 0 + for (i = 0; i < 256; i += 16) { + memcpy(&buffer0[i], &plane[left_edge], 16); + left_edge += stride; + } + current_buffer = 1; /* this will toggle to 0 immediately */ + + /* perform a breadth-first tree encoding for each vector level */ + subvector_count = 1; /* one subvector at level 5 */ + for (level = 5; level >= 0; level--) { + + vector_count = subvector_count; + subvector_count = 0; + + if (current_buffer == 0) { + current_buffer = 1; + vector = buffer1; + subvectors = buffer0; + } else { + current_buffer = 0; + vector = buffer0; + subvectors = buffer1; + } + + /* iterate through each vector in the list */ + for (i = 0; i < vector_count; i++) { + + if (encode_vector(s, vector, level, threshold[level])) { + +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " split to level %d\n", level - 1); +#endif + /* subdivide into 2 subvectors for later processing */ + subvector_count += 2; + + if (level - 1 == 3) { + /* subdivide 16x8 -> 2 8x8 */ + for (j = 0; j < 8; j++) { + /* left half */ + memcpy(subvectors + j * 8, vector + j * 16, 8); + /* right half */ + memcpy(subvectors + 64 + j * 8, + vector + 8 + j * 16, 8); + } + subvectors += 128; + } else if (level - 1 == 1) { + /* subdivide 8x4 -> 2 4x4 */ + for (j = 0; j < 4; j++) { + /* left half */ + memcpy(subvectors + j * 4, vector + j * 8, 4); + /* right half */ + memcpy(subvectors + 16 + j * 4, + vector + 4 + j * 8, 4); + } + subvectors += 32; + } else { + /* first half */ + memcpy(subvectors, vector, level_sizes[level - 1]); + subvectors += level_sizes[level - 1]; + /* second half */ + memcpy(subvectors, vector + level_sizes[level - 1], + level_sizes[level - 1]); + subvectors += level_sizes[level - 1]; + } + } + + vector += level_sizes[level]; + } + + /* if there are no more subvectors, break early */ + if (!subvector_count) + break; + } +#endif + } + } +} + +/* output a plane with a constant mean value; good for debugging and for + * greyscale encoding but only valid for intra frames */ +static void svq1_output_intra_constant_mean(SVQ1Context *s, int block_width, + int block_height, unsigned char mean) +{ + int i; + + /* for each level 5 vector, output the specified mean value */ + for (i = 0; i < block_width * block_height; i++) { + + /* output a 0 before each vector indicating no subdivision */ + put_bits(&s->pb, 1, 0); + + /* output a 0 indicating mean-only encoding; use index 1 as that + * maps to code 0 */ + put_bits(&s->pb, svq1_intra_multistage_vlc[5][1][1], + svq1_intra_multistage_vlc[5][1][0]); + + /* output a constant mean */ + put_bits(&s->pb, svq1_intra_mean_vlc[mean][1], + svq1_intra_mean_vlc[mean][0]); +#ifdef DEBUG_SVQ1 +av_log(s->avctx, AV_LOG_INFO, " const L5 %d/%d: multistage = 0 (0x%X, %d), mean = %d (0x%X, %d)\n", + i, block_width * block_height, + svq1_intra_multistage_vlc[5][1][0], + svq1_intra_multistage_vlc[5][1][1], + mean, + svq1_intra_mean_vlc[mean][0], + svq1_intra_mean_vlc[mean][1]); +#endif + } +} + +static int svq1_encode_init(AVCodecContext *avctx) +{ + SVQ1Context * const s = avctx->priv_data; + int i; + unsigned char least_bits_value = 0; + int least_bits; + + dsputil_init(&s->dsp, avctx); + avctx->coded_frame= (AVFrame*)&s->picture; + + s->frame_width = avctx->width; + s->frame_height = avctx->height; + + s->y_block_width = (s->frame_width + 15) / 16; + s->y_block_height = (s->frame_height + 15) / 16; + + s->c_block_width = (s->frame_width / 4 + 15) / 16; + s->c_block_height = (s->frame_height / 4 + 15) / 16; + +av_log(s->avctx, AV_LOG_INFO, " Hey: %d x %d, %d x %d, %d x %d\n", + s->frame_width, s->frame_height, + s->y_block_width, s->y_block_height, + s->c_block_width, s->c_block_height); + + /* allocate a plane for the U & V planes (color, or C, planes) and + * initialize them to the value that is represented by the fewest bits + * in the mean table; the reasoning behind this is that when the border + * vectors are operated upon and possibly subdivided, the mean will be + * removed resulting in a perfect deviation score of 0 and encoded with + * the minimal possible bits */ + s->c_plane = av_malloc(s->c_block_width * s->c_block_height * 16 * 16); + least_bits = 10000; + for (i = 0; i < 256; i++) + if (svq1_intra_mean_vlc[i][1] < least_bits) { + least_bits = svq1_intra_mean_vlc[i][1]; + least_bits_value = i; + } + memset(s->c_plane, least_bits_value, + s->c_block_width * s->c_block_height * 16 * 16); + + return 0; +} + +static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf, + int buf_size, void *data) +{ + SVQ1Context * const s = avctx->priv_data; + AVFrame *pict = data; + AVFrame * const p= (AVFrame*)&s->picture; + AVFrame temp; + int i; + + if(avctx->pix_fmt != PIX_FMT_YUV410P){ + av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); + return -1; + } + + if(!s->current_picture.data[0]){ + avctx->get_buffer(avctx, &s->current_picture); + avctx->get_buffer(avctx, &s->last_picture); + } + + temp= s->current_picture; + s->current_picture= s->last_picture; + s->last_picture= temp; + + init_put_bits(&s->pb, buf, buf_size); + + *p = *pict; + p->pict_type = avctx->frame_number % avctx->gop_size ? P_TYPE : I_TYPE; + p->key_frame = p->pict_type == I_TYPE; + + svq1_write_header(s, p->pict_type); + for(i=0; i<3; i++){ + svq1_encode_plane(s, + s->picture.data[i], s->last_picture.data[i], s->current_picture.data[i], + s->frame_width / (i?4:1), s->frame_height / (i?4:1), + s->picture.linesize[i], s->current_picture.linesize[i]); + } + +// align_put_bits(&s->pb); + while(put_bits_count(&s->pb) & 31) + put_bits(&s->pb, 1, 0); + + flush_put_bits(&s->pb); + + return (put_bits_count(&s->pb) / 8); +} + +static int svq1_encode_end(AVCodecContext *avctx) +{ + SVQ1Context * const s = avctx->priv_data; + + av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", s->rd_total/(double)(avctx->width*avctx->height*avctx->frame_number)); + + av_free(s->c_plane); + + return 0; +} + AVCodec svq1_decoder = { "svq1", CODEC_TYPE_VIDEO, @@ -841,3 +1784,17 @@ AVCodec svq1_decoder = { CODEC_CAP_DR1, .flush= ff_mpeg_flush, }; + +#ifdef CONFIG_ENCODERS + +AVCodec svq1_encoder = { + "svq1", + CODEC_TYPE_VIDEO, + CODEC_ID_SVQ1, + sizeof(SVQ1Context), + svq1_encode_init, + svq1_encode_frame, + svq1_encode_end, +}; + +#endif //CONFIG_ENCODERS diff --git a/src/libffmpeg/libavcodec/svq1_cb.h b/src/libffmpeg/libavcodec/svq1_cb.h index 14372a255..0f766aa88 100644 --- a/src/libffmpeg/libavcodec/svq1_cb.h +++ b/src/libffmpeg/libavcodec/svq1_cb.h @@ -764,11 +764,43 @@ static const int8_t svq1_inter_codebook_8x8[6144] = { }; /* list of codebooks for inter-coded vectors */ -static const uint8_t* const svq1_inter_codebooks[4] = { +static const int8_t* const svq1_inter_codebooks[4] = { svq1_inter_codebook_4x2, svq1_inter_codebook_4x4, svq1_inter_codebook_8x4, svq1_inter_codebook_8x8 }; +static const int8_t const svq1_inter_codebook_sum[4][16*6] = { + { + -1, 1, -2, 0, 1, -1, -1, -1, -2, -1, 1, -1, -1, 0, -1, -1, + 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, -3, 1, -1, 0, 1, -1, + 1, -1, 2, 2, 1, 1, 2, 0, 0, 0, -1, 1, 1, 0, 0, 0, + 1, -1, 0, 1, -1, 1, 1, 0, 1, 0, -1, 1, 1, 0, 0, 0, + -2, 0, 0, -2, 0, 0, -2, 0, -2, -1, -2, -1, 0, 0, -1, 0, + 1, 0, 1, -1, 2, 2, 1, 2, 2, 1, 0, 1, 1, 0, 1, 1, + },{ + -2, 1, -1, -1, 1, 0, 1, -1, -1, -1, 1, -1, 0, -1, 0, -1, + 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, 2, -3, 1, -2, 3, -1, + 2, 0, 2, 1, 1, -1, 1, 1, 0, 0, 1, 1, 2, -2, 1, 0, + -2, -1, 2, -2, -2, 0, -3, 0, -1, 0, -1, 0, -1, 0, -2, -3, + 1, -2, -2, -1, 1, -1, -1, 1, -1, 1, 1, 0, -2, 0, 1, 1, + 1, 1, 2, 1, 0, 0, -1, 0, 0, 1, 0, 1, -1, 1, 0, 2, + },{ + 0, 0, 0, -3, 1, 1, 1, -3, 0, -1, 0, -3, 1, -3, 0, -2, + 1, 2, -1, -3, 0, -3, 1, -1, 0, -1, 0, 0, 1, 2, 1, 1, + -1, 2, -3, 3, 1, 0, -5, 1, 0, -1, -3, 1, 0, 2, 0, -3, + 4, 2, 0, -2, 1, -2, 3, -2, 1, 1, 0, -1, 2, 5, 3, 1, + -1, 0, 2, -3, -2, 0, 0, -2, 2, -3, -1, -1, 2, 1, 0, -2, + 3, -1, 1, -1, 2, 4, 0, 1, 0, 1, 0, -1, -3, -2, -1, 0, + },{ + 0, 2, -1, -1, 2, -4, -2, 3, 0, -1, -5, 1, 0, 1, 0, 6, + -2, 2, 0, 1, 1, -1, -1, -2, 1, -2, -1, 0, 2, -2, -2, -1, + -4, 2, -1, -3, -1, -2, 2, -1, 2, -1, 2, 0, 3, -3, -3, 0, + -3, 0, 0, -2, 4, -4, 0, -1, 4, 0, -2, -2, 3, -2, 0, 4, + 5, 0, 1, 0, -3, 3, 3, 2, 0, 0, 1, 2, -5, -2, -3, 0, + -3, 2, -2, 2, -2, 4, 7, -3, 4, 2, 3, 2, -1, 0, -3, 1, + } +}; + /* 6x16-entry codebook for intra-coded 4x2 vectors */ static const int8_t svq1_intra_codebook_4x2[768] = { 12, 13, 13, 11, -7,-10,-15,-17,-16,-15,-12,-10, 11, 15, 15, 12, @@ -1506,7 +1538,39 @@ static const int8_t svq1_intra_codebook_8x8[6144] = { }; /* list of codebooks for intra-coded vectors */ -static const uint8_t* const svq1_intra_codebooks[4] = { +static const int8_t* const svq1_intra_codebooks[4] = { svq1_intra_codebook_4x2, svq1_intra_codebook_4x4, svq1_intra_codebook_8x4, svq1_intra_codebook_8x8 }; + +static const int8_t const svq1_intra_codebook_sum[4][16*6] = { + { + 0, 0, 0, -1, -1, -1, -1, -2, 0, -1, -1, 0, -1, 0, 1, 0, + 1, 0, -1, 1, 0, 0, -1, 1, -1, 0, 0, 0, -1, 1, 0, 0, + -1, 0, 0, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, 0, -1, 1, + 0, 1, 0, 0, 1, -1, 0, 0, 0, -1, 1, 0, 1, 0, -2, 1, + 0, -1, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 0, 0, + 0, 1, 1, 0, 0, -1, 0, 1, 0, 0, 0, 0, -1, 1, 1, -1, + },{ + -1, -2, 0, -1, 1, 0, -1, 0, -1, -4, -1, -2, -1, -2, 1, -2, + 0, 0, 4, -2, -1, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 0, + 1, 1, 0, -1, -1, -1, 1, 0, -1, -3, -3, 1, -1, 1, -2, -1, + 1, -1, 0, 1, 2, 1, -1, -1, 1, 1, 1, 2, 1, 0, 1, -2, + -2, 0, -1, -2, -2, 0, -1, -1, -1, 0, 1, 0, -1, -1, 0, -1, + 0, 2, 1, 2, 2, 1, -1, 1, 0, 2, 0, -1, 1, 0, 0, 0, + },{ + -2, 0, -1, -1, 1, 1, -2, 0, -2, 0, 1, -2, -2, 1, -1, -1, + 3, -2, 0, -3, -4, -3, 2, 1, 0, 3, -2, 2, 3, 2, 2, -1, + -3, 1, 0, 1, 0, 0, 0, 1, -2, 1, -2, -2, -1, -2, -2, 2, + 0, -4, 0, 2, -1, 0, 2, 2, 2, 1, 0, -1, -1, 1, -3, 2, + 2, 1, 0, 3, 1, -1, 1, 3, 1, 0, 1, 1, 2, -1, 1, -1, + -2, -1, 0, -1, 1, -1, 1, -2, -2, -1, -1, -3, 1, -4, -3, 1, + },{ + -2, 0, -2, 3, -1, -1, 0, 2, 2, -1, -3, 2, 1, 0, -2, -1, + -3, -2, -2, 1, 2, -3, 0, 1, -5, -2, -3, 0, -2, -1, 2, 0, + -1, -1, 0, -2, 1, 3, -7, -2, -2, -1, 2, -1, 0, 3, 1, 3, + 1, 0, 0, 1, 2, 3, 1, 2, 0, -2, -2, 1, 1, 2, 2, 3, + 4, 1, -1, 2, -2, 4, 0, 0, 0, 4, 2, 0, -2, -2, 2, -4, + -1, 5, -2, -2, -3, 2, -3, -1, 3, -3, 0, 4, 3, 0, 1, -2, + } +}; diff --git a/src/libffmpeg/libavcodec/svq1_vlc.h b/src/libffmpeg/libavcodec/svq1_vlc.h index fa6efb860..d15ac07fb 100644 --- a/src/libffmpeg/libavcodec/svq1_vlc.h +++ b/src/libffmpeg/libavcodec/svq1_vlc.h @@ -9,7 +9,7 @@ static const uint8_t svq1_block_type_vlc[4][2] = { }; /* values in this table range from -32..32; adjust retrieved value by -32 */ -static const uint16_t svq1_motion_component_vlc[65][2] = { +static const uint8_t svq1_motion_component_vlc[65][2] = { /* { code, length } */ { 0x5, 13 }, { 0x7, 13 }, { 0x5, 12 }, { 0x7, 12 }, { 0x9, 12 }, { 0xB, 12 }, { 0xD, 12 }, { 0xF, 12 }, diff --git a/src/libffmpeg/libavcodec/utils.c b/src/libffmpeg/libavcodec/utils.c index ffa0cb855..ffcefb46b 100644 --- a/src/libffmpeg/libavcodec/utils.c +++ b/src/libffmpeg/libavcodec/utils.c @@ -27,7 +27,11 @@ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" +#include "integer.h" #include <stdarg.h> +#include <limits.h> + +static void avcodec_default_free_buffers(AVCodecContext *s); void *av_mallocz(unsigned int size) { @@ -514,6 +518,7 @@ int avcodec_close(AVCodecContext *avctx) { if (avctx->codec->close) avctx->codec->close(avctx); + avcodec_default_free_buffers(avctx); av_freep(&avctx->priv_data); avctx->codec = NULL; return 0; @@ -738,7 +743,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx) avctx->codec->flush(avctx); } -void avcodec_default_free_buffers(AVCodecContext *s){ +static void avcodec_default_free_buffers(AVCodecContext *s){ int i, j; if(s->internal_buffer==NULL) return; @@ -773,15 +778,11 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max) assert(den != 0); - if(den < 0){ - den= -den; - nom= -nom; - } + if(den < 0) + return av_reduce(dst_nom, dst_den, -nom, -den, max); - if(nom < 0){ - nom= -nom; - sign= 1; - } + sign= nom < 0; + nom= ABS(nom); gcd = ff_gcd(nom, den); nom /= gcd; @@ -811,31 +812,31 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max) assert(ff_gcd(nom, den) == 1); - if(sign) nom= -nom; - - *dst_nom = nom; + *dst_nom = sign ? -nom : nom; *dst_den = den; return exact; } -int64_t av_rescale(int64_t a, int b, int c){ - uint64_t h, l; +int64_t av_rescale(int64_t a, int64_t b, int64_t c){ + AVInteger ai, ci; assert(c > 0); assert(b >=0); if(a<0) return -av_rescale(-a, b, c); - h= a>>32; - if(h==0) return a*b/c; + if(b<=INT_MAX && c<=INT_MAX){ + if(a<=INT_MAX) + return (a * b + c/2)/c; + else + return a/c*b + (a%c*b + c/2)/c; + } - l= a&0xFFFFFFFF; - l *= b; - h *= b; - - l += (h%c)<<32; - - return ((h/c)<<32) + l/c; + ai= av_mul_i(av_int2i(a), av_int2i(b)); + ci= av_int2i(c); + ai= av_add_i(ai, av_shr_i(ci,1)); + + return av_i2int(av_div_i(ai, ci)); } /* av_log API */ diff --git a/src/libffmpeg/libavcodec/vcr1.c b/src/libffmpeg/libavcodec/vcr1.c index 4b8c9fc41..05539452a 100644 --- a/src/libffmpeg/libavcodec/vcr1.c +++ b/src/libffmpeg/libavcodec/vcr1.c @@ -165,13 +165,6 @@ static int encode_init(AVCodecContext *avctx){ return 0; } -static int decode_end(AVCodecContext *avctx){ - - avcodec_default_free_buffers(avctx); - - return 0; -} - AVCodec vcr1_decoder = { "vcr1", CODEC_TYPE_VIDEO, @@ -179,7 +172,7 @@ AVCodec vcr1_decoder = { sizeof(VCR1Context), decode_init, NULL, - decode_end, + NULL, decode_frame, CODEC_CAP_DR1, }; diff --git a/src/libffmpeg/libavcodec/vp3.c b/src/libffmpeg/libavcodec/vp3.c index 0667d99eb..59d183505 100644 --- a/src/libffmpeg/libavcodec/vp3.c +++ b/src/libffmpeg/libavcodec/vp3.c @@ -2051,6 +2051,7 @@ static void render_fragments(Vp3DecodeContext *s, int m, n; int i = first_fragment; int16_t *dequantizer; + DCTELEM __align16 output_samples[64]; unsigned char *output_plane; unsigned char *last_plane; unsigned char *golden_plane; @@ -2176,16 +2177,16 @@ av_log(s->avctx, AV_LOG_ERROR, " help! got beefy vector! (%X, %X)\n", motion_x, s->all_fragments[i].coeffs[0], dequantizer[0]); /* invert DCT and place (or add) in final output */ + s->dsp.vp3_idct(s->all_fragments[i].coeffs, + dequantizer, + s->all_fragments[i].coeff_count, + output_samples); if (s->all_fragments[i].coding_method == MODE_INTRA) { - s->dsp.vp3_idct_put(s->all_fragments[i].coeffs, - dequantizer, - s->all_fragments[i].coeff_count, + s->dsp.put_signed_pixels_clamped(output_samples, output_plane + s->all_fragments[i].first_pixel, stride); } else { - s->dsp.vp3_idct_add(s->all_fragments[i].coeffs, - dequantizer, - s->all_fragments[i].coeff_count, + s->dsp.add_pixels_clamped(output_samples, output_plane + s->all_fragments[i].first_pixel, stride); } diff --git a/src/libffmpeg/libavcodec/vp3dsp.c b/src/libffmpeg/libavcodec/vp3dsp.c index ec62d9456..3ead73280 100644 --- a/src/libffmpeg/libavcodec/vp3dsp.c +++ b/src/libffmpeg/libavcodec/vp3dsp.c @@ -40,8 +40,10 @@ void vp3_dsp_init_c(void) /* nop */ } -static void vp3_idct_c(int32_t *dequantized_data, int16_t *output_data) +void vp3_idct_c(int16_t *input_data, int16_t *dequant_matrix, + int coeff_count, int16_t *output_data) { + int32_t dequantized_data[64]; int32_t *ip = dequantized_data; int16_t *op = output_data; @@ -49,7 +51,13 @@ static void vp3_idct_c(int32_t *dequantized_data, int16_t *output_data) int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd; int32_t t1, t2; - int i; + int i, j; + + /* de-zigzag and dequantize */ + for (i = 0; i < coeff_count; i++) { + j = dezigzag_index[i]; + dequantized_data[j] = dequant_matrix[i] * input_data[i]; + } /* Inverse DCT on the rows now */ for (i = 0; i < 8; i++) { @@ -248,71 +256,3 @@ static void vp3_idct_c(int32_t *dequantized_data, int16_t *output_data) op++; } } - -void vp3_idct_put_c(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int32_t dequantized_data[64]; - int16_t transformed_data[64]; - int16_t *op; - int i, j; - - /* de-zigzag and dequantize */ - for (i = 0; i < coeff_count; i++) { - j = dezigzag_index[i]; - dequantized_data[j] = dequant_matrix[i] * input_data[i]; - } - - vp3_idct_c(dequantized_data, transformed_data); - - /* place in final output */ - op = transformed_data; - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - if (*op < -128) - *dest = 0; - else if (*op > 127) - *dest = 255; - else - *dest = (uint8_t)(*op + 128); - op++; - dest++; - } - dest += (stride - 8); - } -} - -void vp3_idct_add_c(int16_t *input_data, int16_t *dequant_matrix, - int coeff_count, uint8_t *dest, int stride) -{ - int32_t dequantized_data[64]; - int16_t transformed_data[64]; - int16_t *op; - int i, j; - int16_t sample; - - /* de-zigzag and dequantize */ - for (i = 0; i < coeff_count; i++) { - j = dezigzag_index[i]; - dequantized_data[j] = dequant_matrix[i] * input_data[i]; - } - - vp3_idct_c(dequantized_data, transformed_data); - - /* place in final output */ - op = transformed_data; - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - sample = *dest + *op; - if (sample < 0) - *dest = 0; - else if (sample > 255) - *dest = 255; - else - *dest = (uint8_t)(sample & 0xFF); - op++; - dest++; - } - dest += (stride - 8); - } -} |