From f2f28861da6a332712eb632e98010d1a7838f43a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 25 Sep 2011 02:54:20 +0200 Subject: [PATCH] =?UTF-8?q?AMV=20video=20encoder.=20Authors=20are=20Vladim?= =?UTF-8?q?ir=20Voroshilov=20and=20Dobrica=20Pavlinu=C5=A1i=C4=87=20based?= =?UTF-8?q?=20on=20svn=20blame/log=20For=20full=20details=20of=20authorshi?= =?UTF-8?q?p=20see=20http://code.google.com/p/amv-codec-tools/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Niedermayer --- libavcodec/allcodecs.c | 2 +- libavcodec/mjpegenc.c | 36 ++++++++++++++++++++++++++++++++++++ libavcodec/mpegvideo_enc.c | 10 ++++++++++ libavformat/riff.c | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 0115240d66..6522127d26 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -71,7 +71,7 @@ void avcodec_register_all(void) REGISTER_ENCODER (A64MULTI, a64multi); REGISTER_ENCODER (A64MULTI5, a64multi5); REGISTER_DECODER (AASC, aasc); - REGISTER_DECODER (AMV, amv); + REGISTER_ENCDEC (AMV, amv); REGISTER_DECODER (ANM, anm); REGISTER_DECODER (ANSI, ansi); REGISTER_ENCDEC (ASV1, asv1); diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 48b84701b6..91a119e931 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -200,6 +200,9 @@ void ff_mjpeg_encode_picture_header(MpegEncContext *s) put_marker(&s->pb, SOI); + // hack for AMV mjpeg format + if(s->avctx->codec_id == CODEC_ID_AMV) return; + jpeg_put_comments(s); jpeg_table_header(s); @@ -445,6 +448,28 @@ void ff_mjpeg_encode_mb(MpegEncContext *s, DCTELEM block[6][64]) s->i_tex_bits += get_bits_diff(s); } +// maximum over s->mjpeg_vsample[i] +#define V_MAX 2 +static int amv_encode_picture(AVCodecContext *avctx, + unsigned char *buf, int buf_size, void *data) +{ + + AVFrame* pic=data; + MpegEncContext *s = avctx->priv_data; + int i; + + //CODEC_FLAG_EMU_EDGE have to be cleared + if(s->avctx->flags & CODEC_FLAG_EMU_EDGE) + return -1; + + //picture should be flipped upside-down + for(i=0; i < 3; i++) { + pic->data[i] += (pic->linesize[i] * (s->mjpeg_vsample[i] * (8 * s->mb_height -((s->height/V_MAX)&7)) - 1 )); + pic->linesize[i] *= -1; + } + return MPV_encode_picture(avctx,buf, buf_size, pic); +} + AVCodec ff_mjpeg_encoder = { .name = "mjpeg", .type = AVMEDIA_TYPE_VIDEO, @@ -456,3 +481,14 @@ AVCodec ff_mjpeg_encoder = { .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), }; + +AVCodec ff_amv_encoder = { + "amv", + AVMEDIA_TYPE_VIDEO, + CODEC_ID_AMV, + sizeof(MpegEncContext), + MPV_encode_init, + amv_encode_picture, + MPV_encode_end, + .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, -1}, +}; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 65eff63c2c..c9c67d0e63 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -265,6 +265,7 @@ av_cold int MPV_encode_init(AVCodecContext *avctx) } break; case CODEC_ID_MJPEG: + case CODEC_ID_AMV: if(avctx->pix_fmt != PIX_FMT_YUVJ420P && avctx->pix_fmt != PIX_FMT_YUVJ422P && ((avctx->pix_fmt != PIX_FMT_YUV420P && avctx->pix_fmt != PIX_FMT_YUV422P) || avctx->strict_std_compliance>FF_COMPLIANCE_UNOFFICIAL)){ av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n"); @@ -530,6 +531,11 @@ av_cold int MPV_encode_init(AVCodecContext *avctx) if(s->mpeg_quant || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO || s->codec_id==CODEC_ID_MJPEG){ s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x s->inter_quant_bias= 0; + }else if(s->codec_id==CODEC_ID_AMV){ + s->intra_quant_bias= 0; + s->inter_quant_bias= 0; + s->fixed_qscale = 1; + s->adaptive_quant = 0; }else{ s->intra_quant_bias=0; s->inter_quant_bias=-(1<<(QUANT_BIAS_SHIFT-2)); //(a - x/4)/x @@ -540,6 +546,8 @@ av_cold int MPV_encode_init(AVCodecContext *avctx) if(avctx->inter_quant_bias != FF_DEFAULT_QUANT_BIAS) s->inter_quant_bias= avctx->inter_quant_bias; + av_log(avctx, AV_LOG_DEBUG, "intra_quant_bias = %d inter_quant_bias = %d\n",s->intra_quant_bias,s->inter_quant_bias); + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, &chroma_v_shift); if(avctx->codec_id == CODEC_ID_MPEG4 && s->avctx->time_base.den > (1<<16)-1){ @@ -564,6 +572,7 @@ av_cold int MPV_encode_init(AVCodecContext *avctx) break; case CODEC_ID_LJPEG: case CODEC_ID_MJPEG: + case CODEC_ID_AMV: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ if(avctx->codec->id == CODEC_ID_LJPEG && avctx->pix_fmt == PIX_FMT_BGRA){ @@ -1788,6 +1797,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, int motion_x, h263_encode_mb(s, s->block, motion_x, motion_y); break; case CODEC_ID_MJPEG: + case CODEC_ID_AMV: if (CONFIG_MJPEG_ENCODER) ff_mjpeg_encode_mb(s, s->block); break; diff --git a/libavformat/riff.c b/libavformat/riff.c index ebaff2b738..d2c6ac93c0 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -276,6 +276,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { CODEC_ID_G2M, MKTAG('G', '2', 'M', '2') }, { CODEC_ID_G2M, MKTAG('G', '2', 'M', '3') }, { CODEC_ID_G2M, MKTAG('G', '2', 'M', '4') }, + { CODEC_ID_AMV, MKTAG('A', 'M', 'V', 'F') }, { CODEC_ID_NONE, 0 } };