X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fsvq1dec.c;h=80f96c8cc6019be3a30351905f91897bde5f5915;hb=b0c4f04338234ee011d7b704621347ef232294fe;hp=cbe65474721cc3121a6e4a870cc03491e0c13319;hpb=5fc32c275efb591c5d40d2eb3902225c32494e65;p=ffmpeg diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index cbe65474721..80f96c8cc60 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -8,42 +8,42 @@ * * SVQ1 Encoder (c) 2004 Mike Melanson * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file svq1.c + * @file * Sorenson Vector Quantizer #1 (SVQ1) video codec. * For more information of the SVQ1 algorithm, visit: * http://www.pcisys.net/~melanson/codecs/ */ -//#define DEBUG_SVQ1 #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" +#include "mathops.h" #include "svq1.h" #undef NDEBUG #include -extern const uint8_t mvtab[33][2]; +extern const uint8_t ff_mvtab[33][2]; static VLC svq1_block_type; static VLC svq1_motion_component; @@ -56,7 +56,7 @@ static VLC svq1_inter_mean; typedef struct svq1_pmv_s { int x; int y; -} svq1_pmv_t; +} svq1_pmv; static const uint16_t checksum_table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, @@ -195,7 +195,8 @@ static const uint8_t string_table[256] = { #define SVQ1_CALC_CODEBOOK_ENTRIES(cbook)\ codebook = (const uint32_t *) cbook[level];\ - bit_cache = get_bits (bitbuf, 4*stages);\ + if (stages > 0)\ + bit_cache = get_bits (bitbuf, 4*stages);\ /* calculate codebook entries for this vector */\ for (j=0; j < stages; j++) {\ entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1);\ @@ -237,9 +238,9 @@ static int svq1_decode_block_intra (GetBitContext *bitbuf, uint8_t *pixels, int } if ((stages > 0) && (level >= 4)) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level); -#endif + av_dlog(NULL, + "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n", + stages, level); return -1; /* invalid vector */ } @@ -287,9 +288,9 @@ static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels, if (stages == -1) continue; /* skip vector */ if ((stages > 0) && (level >= 4)) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level); -#endif + av_dlog(NULL, + "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n", + stages, level); return -1; /* invalid vector */ } @@ -301,7 +302,7 @@ static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels, return 0; } -static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq1_pmv_t **pmv) { +static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv *mv, svq1_pmv **pmv) { int diff; int i; @@ -317,9 +318,9 @@ static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq /* add median of motion vector predictors and clip result */ if (i == 1) - mv->y = ((diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26; + mv->y = sign_extend(diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y), 6); else - mv->x = ((diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26; + mv->x = sign_extend(diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x), 6); } return 0; @@ -342,11 +343,11 @@ static void svq1_skip_block (uint8_t *current, uint8_t *previous, int pitch, int static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf, uint8_t *current, uint8_t *previous, int pitch, - svq1_pmv_t *motion, int x, int y) { + svq1_pmv *motion, int x, int y) { uint8_t *src; uint8_t *dst; - svq1_pmv_t mv; - svq1_pmv_t *pmv[3]; + svq1_pmv mv; + svq1_pmv *pmv[3]; int result; /* predict and decode motion vector */ @@ -377,13 +378,6 @@ static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf, if(x + (mv.x >> 1)<0) mv.x= 0; -#if 0 - 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) - 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]; dst = current; @@ -394,11 +388,11 @@ static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf, static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf, uint8_t *current, uint8_t *previous, int pitch, - svq1_pmv_t *motion,int x, int y) { + svq1_pmv *motion,int x, int y) { uint8_t *src; uint8_t *dst; - svq1_pmv_t mv; - svq1_pmv_t *pmv[4]; + svq1_pmv mv; + svq1_pmv *pmv[4]; int i, result; /* predict and decode motion vector (0) */ @@ -460,12 +454,6 @@ static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf, if(x + (mvx >> 1)<0) mvx= 0; -#if 0 - 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) - 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; @@ -484,7 +472,7 @@ static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf, static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, uint8_t *current, uint8_t *previous, int pitch, - svq1_pmv_t *motion, int x, int y) { + svq1_pmv *motion, int x, int y) { uint32_t block_type; int result = 0; @@ -511,9 +499,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, if (result != 0) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_block %i\n",result); -#endif + av_dlog(s->avctx, "Error in svq1_motion_inter_block %i\n", result); break; } result = svq1_decode_block_non_intra (bitbuf, current, pitch); @@ -524,9 +510,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, if (result != 0) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_4v_block %i\n",result); -#endif + av_dlog(s->avctx, "Error in svq1_motion_inter_4v_block %i\n", result); break; } result = svq1_decode_block_non_intra (bitbuf, current, pitch); @@ -540,7 +524,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf, return result; } -static uint16_t svq1_packet_checksum (uint8_t *data, int length, int value) { +uint16_t ff_svq1_packet_checksum (const uint8_t *data, const int length, int value) { int i; for (i=0; i < length; i++) { @@ -566,22 +550,21 @@ static void svq1_parse_string (GetBitContext *bitbuf, uint8_t *out) { static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) { int frame_size_code; - int temporal_reference; - temporal_reference = get_bits (bitbuf, 8); + skip_bits(bitbuf, 8); /* temporal_reference */ /* frame type */ s->pict_type= get_bits (bitbuf, 2)+1; if(s->pict_type==4) return -1; - if (s->pict_type == I_TYPE) { + if (s->pict_type == AV_PICTURE_TYPE_I) { /* unknown fields */ if (s->f_code == 0x50 || s->f_code == 0x60) { int csum = get_bits (bitbuf, 16); - csum = svq1_packet_checksum ((uint8_t *)bitbuf->buffer, bitbuf->size_in_bits>>3, csum); + csum = ff_svq1_packet_checksum (bitbuf->buffer, bitbuf->size_in_bits>>3, csum); // av_log(s->avctx, AV_LOG_INFO, "%s checksum (%02x) for packet data\n", // (csum == 0) ? "correct" : "incorrect", csum); @@ -641,12 +624,15 @@ static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) { static int svq1_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; MpegEncContext *s=avctx->priv_data; uint8_t *current, *previous; int result, i, x, y, width, height; AVFrame *pict = data; + svq1_pmv *pmv; /* initialize bit buffer */ init_get_bits(&s->gb,buf,buf_size*8); @@ -670,66 +656,65 @@ static int svq1_decode_frame(AVCodecContext *avctx, if (result != 0) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_frame_header %i\n",result); -#endif + av_dlog(s->avctx, "Error in svq1_decode_frame_header %i\n",result); return result; } + avcodec_set_dimensions(avctx, s->width, s->height); //FIXME this avoids some confusion for "B frames" without 2 references //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(s->pict_type==AV_PICTURE_TYPE_B && s->last_picture_ptr==NULL) return buf_size; - if(avctx->hurry_up && s->pict_type==B_TYPE) return buf_size; - if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE) - ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE) + if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==AV_PICTURE_TYPE_B) + ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=AV_PICTURE_TYPE_I) || avctx->skip_frame >= AVDISCARD_ALL) return buf_size; - if(MPV_frame_start(s, avctx) < 0) + if(ff_MPV_frame_start(s, avctx) < 0) + return -1; + + pmv = av_malloc((FFALIGN(s->width, 16)/8 + 3) * sizeof(*pmv)); + if (!pmv) return -1; /* decode y, u and v components */ for (i=0; i < 3; i++) { int linesize; if (i == 0) { - width = (s->width+15)&~15; - height = (s->height+15)&~15; + width = FFALIGN(s->width, 16); + height = FFALIGN(s->height, 16); linesize= s->linesize; } else { if(s->flags&CODEC_FLAG_GRAY) break; - width = (s->width/4+15)&~15; - height = (s->height/4+15)&~15; + width = FFALIGN(s->width/4, 16); + height = FFALIGN(s->height/4, 16); linesize= s->uvlinesize; } - current = s->current_picture.data[i]; + current = s->current_picture.f.data[i]; - if(s->pict_type==B_TYPE){ - previous = s->next_picture.data[i]; + if(s->pict_type==AV_PICTURE_TYPE_B){ + previous = s->next_picture.f.data[i]; }else{ - previous = s->last_picture.data[i]; + previous = s->last_picture.f.data[i]; } - if (s->pict_type == I_TYPE) { + if (s->pict_type == AV_PICTURE_TYPE_I) { /* keyframe */ for (y=0; y < height; y+=16) { for (x=0; x < width; x+=16) { result = svq1_decode_block_intra (&s->gb, ¤t[x], linesize); if (result != 0) { -//#ifdef DEBUG_SVQ1 av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_block %i (keyframe)\n",result); -//#endif - return result; + goto err; } } current += 16*linesize; } } else { - svq1_pmv_t pmv[width/8+3]; /* delta frame */ - memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv_t)); + memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv)); for (y=0; y < height; y+=16) { for (x=0; x < width; x+=16) { @@ -737,10 +722,8 @@ static int svq1_decode_frame(AVCodecContext *avctx, linesize, pmv, x, y); if (result != 0) { -#ifdef DEBUG_SVQ1 - av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_delta_block %i\n",result); -#endif - return result; + av_dlog(s->avctx, "Error in svq1_decode_delta_block %i\n",result); + goto err; } } @@ -755,18 +738,22 @@ static int svq1_decode_frame(AVCodecContext *avctx, *pict = *(AVFrame*)&s->current_picture; - MPV_frame_end(s); + ff_MPV_frame_end(s); *data_size=sizeof(AVFrame); - return buf_size; + result = buf_size; +err: + av_free(pmv); + return result; } -static int svq1_decode_init(AVCodecContext *avctx) +static av_cold int svq1_decode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; int i; + int offset = 0; - MPV_decode_defaults(s); + ff_MPV_decode_defaults(s); s->avctx = avctx; s->width = (avctx->width+3)&~3; @@ -775,55 +762,63 @@ static int svq1_decode_init(AVCodecContext *avctx) 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; + if (ff_MPV_common_init(s) < 0) return -1; - init_vlc(&svq1_block_type, 2, 4, + INIT_VLC_STATIC(&svq1_block_type, 2, 4, &ff_svq1_block_type_vlc[0][1], 2, 1, - &ff_svq1_block_type_vlc[0][0], 2, 1, 1); + &ff_svq1_block_type_vlc[0][0], 2, 1, 6); - init_vlc(&svq1_motion_component, 7, 33, - &mvtab[0][1], 2, 1, - &mvtab[0][0], 2, 1, 1); + INIT_VLC_STATIC(&svq1_motion_component, 7, 33, + &ff_mvtab[0][1], 2, 1, + &ff_mvtab[0][0], 2, 1, 176); for (i = 0; i < 6; i++) { + static const uint8_t sizes[2][6] = {{14, 10, 14, 18, 16, 18}, {10, 10, 14, 14, 14, 16}}; + static VLC_TYPE table[168][2]; + svq1_intra_multistage[i].table = &table[offset]; + svq1_intra_multistage[i].table_allocated = sizes[0][i]; + offset += sizes[0][i]; init_vlc(&svq1_intra_multistage[i], 3, 8, &ff_svq1_intra_multistage_vlc[i][0][1], 2, 1, - &ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, 1); + &ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, INIT_VLC_USE_NEW_STATIC); + svq1_inter_multistage[i].table = &table[offset]; + svq1_inter_multistage[i].table_allocated = sizes[1][i]; + offset += sizes[1][i]; init_vlc(&svq1_inter_multistage[i], 3, 8, &ff_svq1_inter_multistage_vlc[i][0][1], 2, 1, - &ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, 1); + &ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, INIT_VLC_USE_NEW_STATIC); } - init_vlc(&svq1_intra_mean, 8, 256, + INIT_VLC_STATIC(&svq1_intra_mean, 8, 256, &ff_svq1_intra_mean_vlc[0][1], 4, 2, - &ff_svq1_intra_mean_vlc[0][0], 4, 2, 1); + &ff_svq1_intra_mean_vlc[0][0], 4, 2, 632); - init_vlc(&svq1_inter_mean, 9, 512, + INIT_VLC_STATIC(&svq1_inter_mean, 9, 512, &ff_svq1_inter_mean_vlc[0][1], 4, 2, - &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1); + &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1434); return 0; } -static int svq1_decode_end(AVCodecContext *avctx) +static av_cold int svq1_decode_end(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; - MPV_common_end(s); + ff_MPV_common_end(s); return 0; } -AVCodec svq1_decoder = { - "svq1", - CODEC_TYPE_VIDEO, - CODEC_ID_SVQ1, - sizeof(MpegEncContext), - svq1_decode_init, - NULL, - svq1_decode_end, - svq1_decode_frame, - CODEC_CAP_DR1, +AVCodec ff_svq1_decoder = { + .name = "svq1", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_SVQ1, + .priv_data_size = sizeof(MpegEncContext), + .init = svq1_decode_init, + .close = svq1_decode_end, + .decode = svq1_decode_frame, + .capabilities = CODEC_CAP_DR1, .flush= ff_mpeg_flush, - .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, -1}, + .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV410P, PIX_FMT_NONE}, + .long_name= NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), };