X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhuffyuv.c;h=943e48c5693b14867a4aa6b84454162b9b853fd1;hb=ebd4c3add1ecad2c65ac80f0787ca5c1e78b600e;hp=bdfbf88ed0988870d87e0f8ef0c6a713f1c07767;hpb=2e15305b7088c9dfe1c8d29c248a9b49bcf0b0a3;p=ffmpeg diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index bdfbf88ed09..943e48c5693 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -82,13 +82,15 @@ typedef struct HYuvContext{ DSPContext dsp; }HYuvContext; -static const unsigned char classic_shift_luma[] = { +#define classic_shift_luma_table_size 42 +static const unsigned char classic_shift_luma[classic_shift_luma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { 34,36,35,69,135,232,9,16,10,24,11,23,12,16,13,10,14,8,15,8, 16,8,17,20,16,10,207,206,205,236,11,8,10,21,9,23,8,8,199,70, 69,68, 0 }; -static const unsigned char classic_shift_chroma[] = { +#define classic_shift_chroma_table_size 59 +static const unsigned char classic_shift_chroma[classic_shift_chroma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { 66,36,37,38,39,40,41,75,76,77,110,239,144,81,82,83,84,85,118,183, 56,57,88,89,56,89,154,57,58,57,26,141,57,56,58,57,58,57,184,119, 214,245,116,83,82,49,80,79,78,77,44,75,41,40,39,38,37,36,34, 0 @@ -184,7 +186,7 @@ static int read_len_table(uint8_t *dst, GetBitContext *gb){ if(repeat==0) repeat= get_bits(gb, 8); //printf("%d %d\n", val, repeat); - if(i+repeat > 256) { + if(i+repeat > 256 || get_bits_left(gb) < 0) { av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n"); return -1; } @@ -294,8 +296,8 @@ static void generate_joint_tables(HYuvContext *s){ i++; } } - free_vlc(&s->vlc[3+p]); - init_vlc_sparse(&s->vlc[3+p], VLC_BITS, i, len, 1, 1, bits, 2, 2, symbols, 2, 2, 0); + ff_free_vlc(&s->vlc[3+p]); + ff_init_vlc_sparse(&s->vlc[3+p], VLC_BITS, i, len, 1, 1, bits, 2, 2, symbols, 2, 2, 0); } }else{ uint8_t (*map)[4] = (uint8_t(*)[4])s->pix_bgr_map; @@ -335,7 +337,7 @@ static void generate_joint_tables(HYuvContext *s){ } } } - free_vlc(&s->vlc[3]); + ff_free_vlc(&s->vlc[3]); init_vlc(&s->vlc[3], VLC_BITS, i, len, 1, 1, bits, 2, 2, 0); } } @@ -352,7 +354,7 @@ static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length){ if(generate_bits_table(s->bits[i], s->len[i])<0){ return -1; } - free_vlc(&s->vlc[i]); + ff_free_vlc(&s->vlc[i]); init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0); } @@ -366,10 +368,10 @@ static int read_old_huffman_tables(HYuvContext *s){ GetBitContext gb; int i; - init_get_bits(&gb, classic_shift_luma, sizeof(classic_shift_luma)*8); + init_get_bits(&gb, classic_shift_luma, classic_shift_luma_table_size*8); if(read_len_table(s->len[0], &gb)<0) return -1; - init_get_bits(&gb, classic_shift_chroma, sizeof(classic_shift_chroma)*8); + init_get_bits(&gb, classic_shift_chroma, classic_shift_chroma_table_size*8); if(read_len_table(s->len[1], &gb)<0) return -1; @@ -384,7 +386,7 @@ static int read_old_huffman_tables(HYuvContext *s){ memcpy(s->len[2] , s->len [1], 256*sizeof(uint8_t)); for(i=0; i<3; i++){ - free_vlc(&s->vlc[i]); + ff_free_vlc(&s->vlc[i]); init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0); } @@ -415,7 +417,7 @@ static av_cold int common_init(AVCodecContext *avctx){ s->avctx= avctx; s->flags= avctx->flags; - dsputil_init(&s->dsp, avctx); + ff_dsputil_init(&s->dsp, avctx); s->width= avctx->width; s->height= avctx->height; @@ -514,7 +516,7 @@ s->bgr32=1; } break; default: - assert(0); + return AVERROR_INVALIDDATA; } alloc_temp(s); @@ -718,7 +720,7 @@ static void decode_422_bitstream(HYuvContext *s, int count){ count/=2; if(count >= (get_bits_left(&s->gb))/(31*4)){ - for(i=0; igb) < s->gb.size_in_bits; i++){ + for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { READ_2PIX(s->temp[0][2*i ], s->temp[1][i], 1); READ_2PIX(s->temp[0][2*i+1], s->temp[2][i], 2); } @@ -736,7 +738,7 @@ static void decode_gray_bitstream(HYuvContext *s, int count){ count/=2; if(count >= (get_bits_left(&s->gb))/(31*2)){ - for(i=0; igb) < s->gb.size_in_bits; i++){ + for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { READ_2PIX(s->temp[0][2*i ], s->temp[0][2*i+1], 0); } }else{ @@ -921,8 +923,8 @@ static int encode_bgr_bitstream(HYuvContext *s, int count){ #if CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER static void draw_slice(HYuvContext *s, int y){ - int h, cy; - int offset[4]; + int h, cy, i; + int offset[AV_NUM_DATA_POINTERS]; if(s->avctx->draw_horiz_band==NULL) return; @@ -939,7 +941,8 @@ static void draw_slice(HYuvContext *s, int y){ offset[0] = s->picture.linesize[0]*y; offset[1] = s->picture.linesize[1]*cy; offset[2] = s->picture.linesize[2]*cy; - offset[3] = 0; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; emms_c(); s->avctx->draw_horiz_band(s->avctx, &s->picture, offset, y, 3, h); @@ -1217,7 +1220,7 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&s->bitstream_buffer); for(i=0; i<6; i++){ - free_vlc(&s->vlc[i]); + ff_free_vlc(&s->vlc[i]); } return 0; @@ -1225,9 +1228,10 @@ static av_cold int decode_end(AVCodecContext *avctx) #endif /* CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER */ #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ HYuvContext *s = avctx->priv_data; - AVFrame *pict = data; const int width= s->width; const int width2= s->width>>1; const int height= s->height; @@ -1235,10 +1239,16 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, const int fake_ustride= s->interlaced ? pict->linesize[1]*2 : pict->linesize[1]; const int fake_vstride= s->interlaced ? pict->linesize[2]*2 : pict->linesize[2]; AVFrame * const p= &s->picture; - int i, j, size=0; + int i, j, size = 0, ret; + + if (!pkt->data && + (ret = av_new_packet(pkt, width * height * 3 * 4 + FF_MIN_BUFFER_SIZE)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n"); + return ret; + } *p = *pict; - p->pict_type= FF_I_TYPE; + p->pict_type= AV_PICTURE_TYPE_I; p->key_frame= 1; if(s->context){ @@ -1246,7 +1256,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, generate_len_table(s->len[i], s->stats[i]); if(generate_bits_table(s->bits[i], s->len[i])<0) return -1; - size+= store_table(s, s->len[i], &buf[size]); + size += store_table(s, s->len[i], &pkt->data[size]); } for(i=0; i<3; i++) @@ -1254,7 +1264,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, s->stats[i][j] >>= 1; } - init_put_bits(&s->pb, buf+size, buf_size-size); + init_put_bits(&s->pb, pkt->data + size, pkt->size - size); if(avctx->pix_fmt == PIX_FMT_YUV422P || avctx->pix_fmt == PIX_FMT_YUV420P){ int lefty, leftu, leftv, y, cy; @@ -1412,12 +1422,16 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, avctx->stats_out[0] = '\0'; if(!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)){ flush_put_bits(&s->pb); - s->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size); + s->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); } s->picture_number++; - return size*4; + pkt->size = size*4; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } static av_cold int encode_end(AVCodecContext *avctx) @@ -1435,62 +1449,64 @@ static av_cold int encode_end(AVCodecContext *avctx) #if CONFIG_HUFFYUV_DECODER AVCodec ff_huffyuv_decoder = { - "huffyuv", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_HUFFYUV, - sizeof(HYuvContext), - decode_init, - NULL, - decode_end, - decode_frame, - CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_FRAME_THREADS, - NULL, + .name = "huffyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_HUFFYUV, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), }; #endif #if CONFIG_FFVHUFF_DECODER AVCodec ff_ffvhuff_decoder = { - "ffvhuff", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_FFVHUFF, - sizeof(HYuvContext), - decode_init, - NULL, - decode_end, - decode_frame, - CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_FRAME_THREADS, - NULL, + .name = "ffvhuff", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_FFVHUFF, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), }; #endif #if CONFIG_HUFFYUV_ENCODER AVCodec ff_huffyuv_encoder = { - "huffyuv", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_HUFFYUV, - sizeof(HYuvContext), - encode_init, - encode_frame, - encode_end, - .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), + .name = "huffyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_HUFFYUV, + .priv_data_size = sizeof(HYuvContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum PixelFormat[]){ + PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), }; #endif #if CONFIG_FFVHUFF_ENCODER AVCodec ff_ffvhuff_encoder = { - "ffvhuff", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_FFVHUFF, - sizeof(HYuvContext), - encode_init, - encode_frame, - encode_end, - .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), + .name = "ffvhuff", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_FFVHUFF, + .priv_data_size = sizeof(HYuvContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum PixelFormat[]){ + PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), }; #endif