# HG changeset patch # User michaelni # Date 1057792259 0 # Node ID cfc80b3a4ada526cfbc473090c4e8f28a28f4222 # Parent e8ff4783f18816936f8460f50193ed1922745d45 flash video (flv) support patch by (Garrick Meeker ) diff -r e8ff4783f188 -r cfc80b3a4ada avcodec.c --- a/avcodec.c Wed Jul 09 20:18:13 2003 +0000 +++ b/avcodec.c Wed Jul 09 23:10:59 2003 +0000 @@ -39,6 +39,7 @@ { CODEC_ID_MPEG1VIDEO, { MKTAG('P', 'I', 'M', '1'), 0 } }, { CODEC_ID_AC3, { 0x2000, 0 } }, { CODEC_ID_MP2, { 0x50, 0x55, 0 } }, + { CODEC_ID_FLV1, { MKTAG('F', 'L', 'V', '1'), 0 } }, { CODEC_ID_NONE, {0}} }; diff -r e8ff4783f188 -r cfc80b3a4ada avcodec.h --- a/avcodec.h Wed Jul 09 20:18:13 2003 +0000 +++ b/avcodec.h Wed Jul 09 23:10:59 2003 +0000 @@ -41,6 +41,7 @@ CODEC_ID_WMV2, CODEC_ID_H263P, CODEC_ID_H263I, + CODEC_ID_FLV1, CODEC_ID_SVQ1, CODEC_ID_SVQ3, CODEC_ID_DVVIDEO, @@ -1226,6 +1227,7 @@ extern AVCodec mpeg1video_encoder; extern AVCodec h263_encoder; extern AVCodec h263p_encoder; +extern AVCodec flv_encoder; extern AVCodec rv10_encoder; extern AVCodec mjpeg_encoder; extern AVCodec ljpeg_encoder; @@ -1249,6 +1251,7 @@ extern AVCodec wmv2_decoder; extern AVCodec mpeg_decoder; extern AVCodec h263i_decoder; +extern AVCodec flv_decoder; extern AVCodec rv10_decoder; extern AVCodec svq1_decoder; extern AVCodec svq3_decoder; diff -r e8ff4783f188 -r cfc80b3a4ada h263.c --- a/h263.c Wed Jul 09 20:18:13 2003 +0000 +++ b/h263.c Wed Jul 09 23:10:59 2003 +0000 @@ -50,11 +50,13 @@ #ifdef CONFIG_ENCODERS static void h263_encode_block(MpegEncContext * s, DCTELEM * block, - int n); + int n); +static void h263_flv_encode_block(MpegEncContext * s, DCTELEM * block, + int n); static void h263_encode_motion(MpegEncContext * s, int val, int fcode); static void h263p_encode_umotion(MpegEncContext * s, int val); static inline void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, - int n, int dc, uint8_t *scan_table, + int n, int dc, uint8_t *scan_table, PutBitContext *dc_pb, PutBitContext *ac_pb); #endif @@ -156,6 +158,48 @@ align_put_bits(&s->pb); + if (s->h263_flv) { + put_bits(&s->pb, 17, 1); + put_bits(&s->pb, 5, (s->h263_flv-1)); /* 0: h263 escape codes 1: 11-bit escape codes */ + put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->frame_rate_base) / + s->avctx->frame_rate) & 0xff); /* TemporalReference */ + if (s->width == 352 && s->height == 288) + format = 2; + else if (s->width == 176 && s->height == 144) + format = 3; + else if (s->width == 128 && s->height == 96) + format = 4; + else if (s->width == 320 && s->height == 240) + format = 5; + else if (s->width == 160 && s->height == 120) + format = 6; + else if (s->width <= 255 && s->height <= 255) + format = 0; /* use 1 byte width & height */ + else + format = 1; /* use 2 bytes width & height */ + put_bits(&s->pb, 3, format); /* PictureSize */ + if (format == 0) { + put_bits(&s->pb, 8, s->width); + put_bits(&s->pb, 8, s->height); + } else if (format == 1) { + put_bits(&s->pb, 16, s->width); + put_bits(&s->pb, 16, s->height); + } + put_bits(&s->pb, 2, s->pict_type == P_TYPE); /* PictureType */ + put_bits(&s->pb, 1, 0); /* DeblockingFlag: off */ + put_bits(&s->pb, 5, s->qscale); /* Quantizer */ + put_bits(&s->pb, 1, 0); /* ExtraInformation */ + + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= h263_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } + return; + } + /* Update the pointer to last GOB */ s->ptr_lastgob = pbBufPtr(&s->pb); s->gob_number = 0; @@ -838,6 +882,7 @@ int16_t pred_dc; int16_t rec_intradc[6]; uint16_t *dc_ptr[6]; + const int interleaved_stats= (s->flags&CODEC_FLAG_PASS1); const int dquant_code[5]= {1,0,9,2,3}; //printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); @@ -851,6 +896,10 @@ if ((cbp | motion_x | motion_y | s->dquant) == 0) { /* skip macroblock */ put_bits(&s->pb, 1, 1); + if(interleaved_stats){ + s->misc_bits++; + s->last_bits++; + } return; } put_bits(&s->pb, 1, 0); /* mb coded */ @@ -865,6 +914,10 @@ if(s->dquant) put_bits(&s->pb, 2, dquant_code[s->dquant+2]); + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + /* motion vectors: 16x16 mode only now */ h263_pred_motion(s, 0, &pred_x, &pred_y); @@ -879,6 +932,10 @@ /* To prevent Start Code emulation */ put_bits(&s->pb,1,1); } + + if(interleaved_stats){ + s->mv_bits+= get_bits_diff(s); + } } else { int li = s->h263_aic ? 0 : 1; @@ -946,11 +1003,18 @@ put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); if(s->dquant) put_bits(&s->pb, 2, dquant_code[s->dquant+2]); + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } } for(i=0; i<6; i++) { /* encode each block */ - h263_encode_block(s, block[i], i); + if (s->h263_flv > 1) + h263_flv_encode_block(s, block[i], i); + else + h263_encode_block(s, block[i], i); /* Update INTRADC for decoding */ if (s->h263_aic && s->mb_intra) { @@ -958,6 +1022,16 @@ } } + + if(interleaved_stats){ + if (!s->mb_intra) { + s->p_tex_bits+= get_bits_diff(s); + s->f_count++; + }else{ + s->i_tex_bits+= get_bits_diff(s); + s->i_count++; + } + } } #endif @@ -1467,6 +1541,17 @@ s->max_qcoeff= 127; break; //Note for mpeg4 & h263 the dc-scale table will be set per frame as needed later + case CODEC_ID_FLV1: + if (s->h263_flv > 1) { + s->min_qcoeff= -1023; + s->max_qcoeff= 1023; + } else { + s->min_qcoeff= -127; + s->max_qcoeff= 127; + } + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + break; default: //nothing needed default table allready set in mpegvideo.c s->min_qcoeff= -127; s->max_qcoeff= 127; @@ -1547,6 +1632,83 @@ } } } + +/** + * encodes a 8x8 block. + * @param block the 8x8 block + * @param n block index (0-3 are luma, 4-5 are chroma) + */ +static void h263_flv_encode_block(MpegEncContext * s, DCTELEM * block, int n) +{ + int level, run, last, i, j, last_index, last_non_zero, sign, slevel, code; + RLTable *rl; + + rl = &rl_inter; + if (s->mb_intra && !s->h263_aic) { + /* DC coef */ + level = block[0]; + /* 255 cannot be represented, so we clamp */ + if (level > 254) { + level = 254; + block[0] = 254; + } + /* 0 cannot be represented also */ + else if (level < 1) { + level = 1; + block[0] = 1; + } + if (level == 128) //FIXME check rv10 + put_bits(&s->pb, 8, 0xff); + else + put_bits(&s->pb, 8, level & 0xff); + i = 1; + } else { + i = 0; + if (s->h263_aic && s->mb_intra) + rl = &rl_intra_aic; + } + + /* AC coefs */ + last_index = s->block_last_index[n]; + last_non_zero = i - 1; + for (; i <= last_index; i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + if (level) { + run = i - last_non_zero - 1; + last = (i == last_index); + sign = 0; + slevel = level; + if (level < 0) { + sign = 1; + level = -level; + } + code = get_rl_index(rl, last, run, level); + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + if (code == rl->n) { + assert(slevel != 0); + if(slevel < 64 && slevel > -64) { + /* 7-bit level */ + put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 1, last); + put_bits(&s->pb, 6, run); + + put_bits(&s->pb, 7, slevel & 0x7f); + } else { + /* 11-bit level */ + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 1, last); + put_bits(&s->pb, 6, run); + + put_bits(&s->pb, 11, slevel & 0x7ff); + } + } else { + put_bits(&s->pb, 1, sign); + } + last_non_zero = i; + } + } +} #endif #ifdef CONFIG_ENCODERS @@ -3553,16 +3715,27 @@ } if (code == rl->n) { /* escape */ - last = get_bits1(&s->gb); - run = get_bits(&s->gb, 6); - level = (int8_t)get_bits(&s->gb, 8); - if(level == -128){ - if (s->h263_rv10) { - /* XXX: should patch encoder too */ - level = get_sbits(&s->gb, 12); - }else{ - level = get_bits(&s->gb, 5); - level |= get_sbits(&s->gb, 6)<<5; + if (s->h263_flv > 1) { + int is11 = get_bits1(&s->gb); + last = get_bits1(&s->gb); + run = get_bits(&s->gb, 6); + if(is11){ + level = (int8_t)get_sbits(&s->gb, 11); + } else { + level = (int8_t)get_sbits(&s->gb, 7); + } + } else { + last = get_bits1(&s->gb); + run = get_bits(&s->gb, 6); + level = (int8_t)get_bits(&s->gb, 8); + if(level == -128){ + if (s->h263_rv10) { + /* XXX: should patch encoder too */ + level = get_sbits(&s->gb, 12); + }else{ + level = get_bits(&s->gb, 5); + level |= get_sbits(&s->gb, 6)<<5; + } } } } else { @@ -4995,3 +5168,80 @@ return 0; } +int flv_h263_decode_picture_header(MpegEncContext *s) +{ + int format, width, height; + + /* picture header */ + if (get_bits_long(&s->gb, 17) != 1) { + fprintf(stderr, "Bad picture start code\n"); + return -1; + } + format = get_bits(&s->gb, 5); + if (format != 0 && format != 1) { + fprintf(stderr, "Bad picture format\n"); + return -1; + } + s->h263_flv = format+1; + s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */ + format = get_bits(&s->gb, 3); + switch (format) { + case 0: + width = get_bits(&s->gb, 8); + height = get_bits(&s->gb, 8); + break; + case 1: + width = get_bits(&s->gb, 16); + height = get_bits(&s->gb, 16); + break; + case 2: + width = 352; + height = 288; + break; + case 3: + width = 176; + height = 144; + break; + case 4: + width = 128; + height = 96; + break; + case 5: + width = 320; + height = 240; + break; + case 6: + width = 160; + height = 120; + break; + default: + width = height = 0; + break; + } + if ((width == 0) || (height == 0)) + return -1; + s->width = width; + s->height = height; + + s->pict_type = I_TYPE + get_bits(&s->gb, 2); + if (s->pict_type > P_TYPE) + s->pict_type = P_TYPE; + skip_bits1(&s->gb); /* deblocking flag */ + s->qscale = get_bits(&s->gb, 5); + + s->h263_plus = 0; + + s->unrestricted_mv = 1; + s->h263_long_vectors = s->unrestricted_mv; + + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + s->f_code = 1; + + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + + return 0; +} diff -r e8ff4783f188 -r cfc80b3a4ada h263dec.c --- a/h263dec.c Wed Jul 09 20:18:13 2003 +0000 +++ b/h263dec.c Wed Jul 09 23:10:59 2003 +0000 @@ -96,6 +96,9 @@ case CODEC_ID_H263I: s->h263_intel = 1; break; + case CODEC_ID_FLV1: + s->h263_flv = 1; + break; default: return -1; } @@ -451,6 +454,8 @@ s->low_delay=1; } else if (s->h263_intel) { ret = intel_h263_decode_picture_header(s); + } else if (s->h263_flv) { + ret = flv_h263_decode_picture_header(s); } else { ret = h263_decode_picture_header(s); } @@ -793,3 +798,14 @@ mpeg4_decoptions, }; +AVCodec flv_decoder = { + "flv", + CODEC_TYPE_VIDEO, + CODEC_ID_FLV1, + sizeof(MpegEncContext), + ff_h263_decode_init, + NULL, + ff_h263_decode_end, + ff_h263_decode_frame, + CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 +}; diff -r e8ff4783f188 -r cfc80b3a4ada imgconvert.c --- a/imgconvert.c Wed Jul 09 20:18:13 2003 +0000 +++ b/imgconvert.c Wed Jul 09 23:10:59 2003 +0000 @@ -593,19 +593,19 @@ { const uint8_t *p, *p1; uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; - int x; + int w; p1 = src->data[0]; lum1 = dst->data[0]; cb1 = dst->data[1]; cr1 = dst->data[2]; - for(;height >= 2; height -= 2) { + for(;height >= 1; height -= 2) { p = p1; lum = lum1; cb = cb1; cr = cr1; - for(x=0;x= 2; w -= 2) { lum[0] = p[0]; cb[0] = p[1]; lum[1] = p[2]; @@ -615,18 +615,30 @@ cb++; cr++; } - p1 += src->linesize[0]; - lum1 += dst->linesize[0]; - p = p1; - lum = lum1; - for(x=0;xlinesize[0]; lum1 += dst->linesize[0]; + if (height>1) { + p = p1; + lum = lum1; + for(w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } cb1 += dst->linesize[1]; cr1 += dst->linesize[2]; } diff -r e8ff4783f188 -r cfc80b3a4ada mpegvideo.c --- a/mpegvideo.c Wed Jul 09 20:18:13 2003 +0000 +++ b/mpegvideo.c Wed Jul 09 23:10:59 2003 +0000 @@ -670,6 +670,14 @@ avctx->delay=0; s->low_delay=1; break; + case CODEC_ID_FLV1: + s->out_format = FMT_H263; + s->h263_flv = 2; /* format = 1; 11-bit codes */ + s->unrestricted_mv = 1; + s->rtp_mode=0; /* don't allow GOB */ + avctx->delay=0; + s->low_delay=1; + break; case CODEC_ID_RV10: s->out_format = FMT_H263; s->h263_rv10 = 1; @@ -2997,6 +3005,7 @@ ff_wmv2_encode_mb(s, s->block, motion_x, motion_y); break; case CODEC_ID_H263: case CODEC_ID_H263P: + case CODEC_ID_FLV1: case CODEC_ID_RV10: h263_encode_mb(s, s->block, motion_x, motion_y); break; #endif @@ -3348,6 +3357,7 @@ break; case CODEC_ID_H263: case CODEC_ID_H263P: + case CODEC_ID_FLV1: ff_clean_h263_qscales(s); break; } @@ -3427,11 +3437,17 @@ s->last_mv_dir = 0; #ifdef CONFIG_RISKY - if (s->codec_id==CODEC_ID_H263 || s->codec_id==CODEC_ID_H263P) + switch(s->codec_id){ + case CODEC_ID_H263: + case CODEC_ID_H263P: + case CODEC_ID_FLV1: s->gob_index = ff_h263_get_gob_height(s); - - if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame) - ff_mpeg4_init_partitions(s); + break; + case CODEC_ID_MPEG4: + if(s->partitioned_frame) + ff_mpeg4_init_partitions(s); + break; + } #endif s->resync_mb_x=0; @@ -4439,6 +4455,16 @@ MPV_encode_end, }; +AVCodec flv_encoder = { + "flv", + CODEC_TYPE_VIDEO, + CODEC_ID_FLV1, + sizeof(MpegEncContext), + MPV_encode_init, + MPV_encode_picture, + MPV_encode_end, +}; + AVCodec rv10_encoder = { "rv10", CODEC_TYPE_VIDEO, diff -r e8ff4783f188 -r cfc80b3a4ada mpegvideo.h --- a/mpegvideo.h Wed Jul 09 20:18:13 2003 +0000 +++ b/mpegvideo.h Wed Jul 09 23:10:59 2003 +0000 @@ -269,6 +269,7 @@ int h263_rv10; ///< use RV10 variation for H263 int h263_msmpeg4; ///< generate MSMPEG4 compatible stream (deprecated, use msmpeg4_version instead) int h263_intel; ///< use I263 intel h263 header + int h263_flv; ///< use flv h263 header int codec_id; /* see CODEC_ID_xxx */ int fixed_qscale; ///< fixed qscale if non zero @@ -833,6 +834,7 @@ int intel_h263_decode_picture_header(MpegEncContext *s); +int flv_h263_decode_picture_header(MpegEncContext *s); int ff_h263_decode_mb(MpegEncContext *s, DCTELEM block[6][64]); int h263_get_picture_format(int width, int height); diff -r e8ff4783f188 -r cfc80b3a4ada utils.c --- a/utils.c Wed Jul 09 20:18:13 2003 +0000 +++ b/utils.c Wed Jul 09 23:10:59 2003 +0000 @@ -610,6 +610,7 @@ case CODEC_ID_WMV2: case CODEC_ID_H263P: case CODEC_ID_H263I: + case CODEC_ID_FLV1: case CODEC_ID_SVQ1: for(i=0; ipicture[i].data[0] && ( s->picture[i].type == FF_BUFFER_TYPE_INTERNAL