[FFmpeg-devel] [PATCH]wmv3 encoder
Vitor Sessak
vitor1001
Sun Jan 23 17:57:43 CET 2011
On 06/25/2007 09:23 PM, Denis Fortin wrote:
> Hi,
> The following patch adds a wmv3 encoder (i removed the vc1 encoder
> because it doesn't generate an elementary stream).
> I don't think i can split the patch without breaking compilation between
> two patches.
>
> Please comment (particularly the vc1enc.h include in mpegvideo.c).
Git-friendly patch attached so patchwork will catch it up.
-Vitor
>From fortinatnerim.net Sun Jan 23 17:56:30 2011
From: fortinatnerim.net (Denis Fortin)
Date: Sun, 23 Jan 2011 17:56:30 +0100
Subject: [PATCH] WMV3 encoder
Message-ID: <mailman.466.1295801872.1307.ffmpeg-devel at mplayerhq.hu>
---
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 2 +-
libavcodec/allcodecs.h | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/dsputil.h | 1 +
libavcodec/mpegvideo.c | 19 +++
libavcodec/vc1.c | 2 +-
libavcodec/vc1.h | 2 +
libavcodec/vc1dsp.c | 108 +++++++++++++
libavcodec/vc1enc.c | 397 ++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/vc1enc.h | 30 ++++
11 files changed, 562 insertions(+), 2 deletions(-)
create mode 100644 libavcodec/vc1enc.c
create mode 100644 libavcodec/vc1enc.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7ab4eb2..b77b463 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -193,6 +193,7 @@ OBJS-$(CONFIG_WMAV2_ENCODER) += wmaenc.o wma.o mdct.o fft.o
OBJS-$(CONFIG_WMV2_DECODER) += msmpeg4.o msmpeg4data.o
OBJS-$(CONFIG_WMV2_ENCODER) += msmpeg4.o msmpeg4data.o
OBJS-$(CONFIG_WMV3_DECODER) += vc1.o vc1data.o vc1dsp.o
+OBJS-$(CONFIG_WMV3_ENCODER) += vc1.o vc1data.o vc1dsp.o msmpeg4data.o vc1enc.o msmpeg4.o
OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o
OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o
OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 7805fa5..e823ff2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -156,7 +156,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(VQA, vqa);
REGISTER_ENCDEC (WMV1, wmv1);
REGISTER_ENCDEC (WMV2, wmv2);
- REGISTER_DECODER(WMV3, wmv3);
+ REGISTER_ENCDEC (WMV3, wmv3);
REGISTER_DECODER(WNV1, wnv1);
REGISTER_DECODER(XAN_WC3, xan_wc3);
REGISTER_DECODER(XL, xl);
diff --git a/libavcodec/allcodecs.h b/libavcodec/allcodecs.h
index 606d17a..b823fff 100644
--- a/libavcodec/allcodecs.h
+++ b/libavcodec/allcodecs.h
@@ -73,6 +73,7 @@ extern AVCodec wmav1_encoder;
extern AVCodec wmav2_encoder;
extern AVCodec wmv1_encoder;
extern AVCodec wmv2_encoder;
+extern AVCodec wmv3_encoder;
extern AVCodec zmbv_encoder;
extern AVCodec aasc_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index acb7445..6a495a7 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1277,6 +1277,7 @@ typedef struct AVCodecContext {
#define FF_IDCT_CAVS 15
#define FF_IDCT_SIMPLEARMV5TE 16
#define FF_IDCT_SIMPLEARMV6 17
+#define FF_IDCT_VC1 18
/**
* slice count
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index ecf8e62..738950d 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -398,6 +398,7 @@ typedef struct DSPContext {
void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height);
/* vc1 functions */
+ void (*vc1_fwd_trans_8x8)(DCTELEM *b);
void (*vc1_inv_trans_8x8)(DCTELEM *b);
void (*vc1_inv_trans_8x4)(DCTELEM *b, int n);
void (*vc1_inv_trans_4x8)(DCTELEM *b, int n);
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 9233ff3..bc89b9d 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -33,6 +33,7 @@
#include "mjpegenc.h"
#include "msmpeg4.h"
#include "faandct.h"
+#include "vc1enc.h"
#include <limits.h>
//#undef NDEBUG
@@ -1328,6 +1329,18 @@ int MPV_encode_init(AVCodecContext *avctx)
avctx->delay=0;
s->low_delay=1;
break;
+ case CODEC_ID_WMV3:
+ case CODEC_ID_VC1:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->unrestricted_mv = 1;
+ s->msmpeg4_version= 6;
+ s->flipflop_rounding=1;
+ s->quarter_sample=1;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
default:
return -1;
}
@@ -4585,6 +4598,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, int motion_x,
if (ENABLE_WMV2_ENCODER)
ff_wmv2_encode_mb(s, s->block, motion_x, motion_y);
break;
+ case CODEC_ID_WMV3:
+ if (ENABLE_WMV3_ENCODER)
+ ff_vc1_encode_mb(s,s->block,motion_x,motion_y);
+ break;
case CODEC_ID_H261:
if (ENABLE_H261_ENCODER)
ff_h261_encode_mb(s, s->block, motion_x, motion_y);
@@ -5775,6 +5792,8 @@ static int encode_picture(MpegEncContext *s, int picture_number)
case FMT_H263:
if (ENABLE_WMV2_ENCODER && s->codec_id == CODEC_ID_WMV2)
ff_wmv2_encode_picture_header(s, picture_number);
+ else if (ENABLE_WMV3_ENCODER && s->codec_id == CODEC_ID_WMV3)
+ ff_vc1_encode_picture_header(s, picture_number);
else if (ENABLE_MSMPEG4_ENCODER && s->h263_msmpeg4)
msmpeg4_encode_picture_header(s, picture_number);
else if (s->h263_pred)
diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index 391d4e1..a482baf 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -2278,7 +2278,7 @@ static inline int vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n,
* @{
*/
-static inline int vc1_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
+inline int vc1_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
{
int xy, wrap, pred, a, b, c;
diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h
index c57dfff..4163745 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -304,4 +304,6 @@ typedef struct VC1Context{
int bi_type;
} VC1Context;
+inline int vc1_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr);
+
#endif // AVCODEC_VC1_H
diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c
index 6102c09..49a0a67 100644
--- a/libavcodec/vc1dsp.c
+++ b/libavcodec/vc1dsp.c
@@ -322,6 +322,106 @@ static void vc1_inv_trans_4x4_c(DCTELEM block[64], int n)
}
}
+
+void vc1_fwd_trans_8x8_c(DCTELEM block[64])
+{
+ int i;
+ register int t1,t2,t3,t4,t5,t6,t7,t8;
+ const int *norm_mat;
+ DCTELEM *dest, *src;
+
+ static const int norm_8[64] = {
+ 82944, 83232, 84096, 83232, 82944, 83232, 84096, 83232,
+ 83232, 83521, 84388, 83521, 83232, 83521, 84388, 83521,
+ 84096, 84388, 85264, 84388, 84096, 84388, 85264, 84388,
+ 83232, 83521, 84388, 83521, 83232, 83521, 84388, 83521,
+ 82944, 83232, 84096, 83232, 82944, 83232, 84096, 83232,
+ 83232, 83521, 84388, 83521, 83232, 83521, 84388, 83521,
+ 84096, 84388, 85264, 84388, 84096, 84388, 85264, 84388,
+ 83232, 83521, 84388, 83521, 83232, 83521, 84388, 83521
+ };
+
+ src = block;
+ dest = block;
+
+ for(i=0 ; i < 8 ; i++){
+ t1 = src[0] + src[56];
+ t2 = src[0] - src[56];
+ t3 = src[8] + src[48];
+ t4 = src[8] - src[48];
+ t5 = src[16] + src[40];
+ t6 = src[16] - src[40];
+ t7 = src[24] + src[32];
+ t8 = src[24] - src[32];
+
+ dest[0] = 12 * (t1 + t3 + t5 + t7);
+ dest[8] = 16 * t2 + 15 * t4 + 9 * t6 + 4 * t8;
+ dest[16] = 16 * (t1 - t7) + 6 * ( t3 - t5);
+ dest[24] = 15 * t2 - 4 * t4 - 16 * t6 - 9 * t8;
+ dest[32] = 12 * ( t1 - t3 - t5 + t7);
+ dest[40] = 9 * t2 - 16 * t4 + 4 * t6 + 15 * t8;
+ dest[48] = 6 * (t1 - t7) - 16 * (t3 - t5);
+ dest[56] = 4 * t2 - 9 * t4 + 15 * t6 - 16 * t8;
+
+ dest++;
+ src++;
+ }
+
+ dest = block;
+ src = block;
+
+ norm_mat = norm_8;
+ for(i=0 ; i < 8 ; i++){
+ t1 = dest[0] + dest[7];
+ t2 = dest[0] - dest[7];
+ t3 = dest[1] + dest[6];
+ t4 = dest[1] - dest[6];
+
+ t5 = dest[2] + dest[5];
+ t6 = dest[2] - dest[5];
+ t7 = dest[3] + dest[4];
+ t8 = dest[3] - dest[4];
+
+ src[0] = ( (12 * (t1 + t3 + t5 + t7)) << 6 ) / (norm_mat[0]);
+ src[1] = ( (16 * t2 + 15 * t4 + 9 * t6 + 4 * t8) << 6) / (norm_mat[1]);
+ src[2] = ( (16 * (t1 - t7) + 6 * ( t3 - t5)) << 6) / (norm_mat[2]);
+ src[3] = ( (15 * t2 - 4 * t4 - 16 * t6 - 9 * t8) << 6) / (norm_mat[3]);
+ src[4] = ( (12 * ( t1 - t3 - t5 + t7)) << 6) / (norm_mat[4]);
+ src[5] = ( (9 * t2 - 16 * t4 + 4 * t6 + 15 * t8) << 6) / (norm_mat[5]);
+ src[6] = ( (6 * (t1 - t7) - 16 * (t3 - t5)) << 6) / (norm_mat[6]);
+ src[7] = ( (4 * t2 - 9 * t4 + 15 * t6 - 16 * t8) << 6) / (norm_mat[7]);
+
+ dest+=8;
+ src+=8;
+ norm_mat+=8;
+ }
+}
+
+
+void ff_vc1_inv_trans_put(uint8_t *dest, int linesize, DCTELEM block[64])
+{
+ int i,j;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ vc1_inv_trans_8x8_c(block);
+
+ /* read the pixels */
+ for(i=0;i<8;i++) {
+ dest[0] = cm[block[0]];
+ dest[1] = cm[block[1]];
+ dest[2] = cm[block[2]];
+ dest[3] = cm[block[3]];
+ dest[4] = cm[block[4]];
+ dest[5] = cm[block[5]];
+ dest[6] = cm[block[6]];
+ dest[7] = cm[block[7]];
+
+ dest += linesize;
+ block += 8;
+ }
+}
+
+
/* motion compensation functions */
/** Filter used to interpolate fractional pel values
@@ -444,6 +544,14 @@ void ff_vc1dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
dsp->vc1_h_overlap = vc1_h_overlap_c;
dsp->vc1_v_overlap = vc1_v_overlap_c;
+ if( ENABLE_WMV3_ENCODER ) {
+ dsp->vc1_fwd_trans_8x8 = vc1_fwd_trans_8x8_c;
+ if(avctx->idct_algo == FF_IDCT_VC1) {
+ dsp->idct_put = ff_vc1_inv_trans_put;
+ dsp->idct_permutation_type = FF_NO_IDCT_PERM;
+ }
+ }
+
dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_vc1_mspel_mc00_c;
dsp->put_vc1_mspel_pixels_tab[ 1] = ff_put_vc1_mspel_mc10_c;
dsp->put_vc1_mspel_pixels_tab[ 2] = ff_put_vc1_mspel_mc20_c;
diff --git a/libavcodec/vc1enc.c b/libavcodec/vc1enc.c
new file mode 100644
index 0000000..81b1868
--- /dev/null
+++ b/libavcodec/vc1enc.c
@@ -0,0 +1,397 @@
+/*
+ * VC-1 and WMV3 encoder
+ * copyright (c) 2007 Denis Fortin
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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,
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#include "msmpeg4data.h"
+#include "vc1.h"
+#include "vc1data.h"
+#include "vc1enc.h"
+
+/* msmpeg4 externs*/
+extern void ff_msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
+extern void ff_find_best_tables(MpegEncContext * s);
+extern void ff_code012(PutBitContext *pb, int n);
+
+/**
+ * Unquantize a block
+ *
+ * @param s Encoder context
+ * @param block Block to quantize
+ * @param n index of block
+ * @param qscale quantizer scale
+ */
+void vc1_unquantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale)
+{
+ VC1Context * const t= s->avctx->priv_data;
+ int i, level, nCoeffs, q;
+ ScanTable scantable;
+
+ if(s->pict_type == I_TYPE)
+ scantable = s->intra_scantable;
+ else {
+ scantable = s->inter_scantable;
+ if( P_TYPE == s->pict_type )
+ for(i=0;i<64;i++)
+ block[i] += 128;
+ }
+
+ nCoeffs= s->block_last_index[n];
+
+ if (n < 4)
+ block[0] *= s->y_dc_scale;
+ else
+ block[0] *= s->c_dc_scale;
+
+ q = 2 * qscale + t->halfpq;
+
+ for(i=1; i<= nCoeffs; i++) {
+ int j= scantable.permutated[i];
+ level = block[j];
+ if (level) {
+ level = level * q + t->pquantizer*(FFSIGN(block[j]) * qscale);
+ }
+ block[j]=level;
+ }
+
+ for(; i< 64; i++) {
+ int j= scantable.permutated[i];
+ block[j]=0;
+ }
+
+}
+
+
+/**
+ * Transform and quantize a block
+ *
+ * @param s Encoder Context
+ * @param block block to encode
+ * @param n block index
+ * @param qscale quantizer scale
+ * @param overflow
+ *
+ * @return last significant coeff in zz order
+ */
+int vc1_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow)
+{
+ VC1Context * const t= s->avctx->priv_data;
+ const uint8_t *scantable;
+ int q, i, j, level, last_non_zero, start_i;
+
+ if( I_TYPE == s->pict_type ) {
+ scantable = s->intra_scantable.scantable;
+ last_non_zero = 0;
+ start_i = 1;
+ } else {
+ scantable = s->inter_scantable.scantable;
+ last_non_zero = -1;
+ start_i = 0;
+ if (s->mb_intra){
+ for(i=0;i<64;i++)
+ block[i] -= 128;
+ }
+ }
+
+ s->dsp.vc1_fwd_trans_8x8(block);
+
+ if (n < 4)
+ q = s->y_dc_scale;
+ else
+ q = s->c_dc_scale;
+
+ block[0] /= q;
+ q = 2 * qscale + t->halfpq;
+
+ for(i=63;i>=start_i;i--) {
+ j = scantable[i];
+ level = (block[j] - t->pquantizer*(FFSIGN(block[j]) * qscale)) / q;
+ if(level){
+ last_non_zero = i;
+ break;
+ }
+ }
+ for(i=start_i; i<=last_non_zero; i++) {
+ j = scantable[i];
+ block[j] = (block[j] - t->pquantizer*(FFSIGN(block[j]) * qscale)) / q ;
+ }
+ *overflow = 0;
+ return last_non_zero;
+}
+
+
+/**
+ * Intra picture MB layer bitstream encoder
+ * @param s Mpeg encoder context
+ * @param block macroblock to encode
+ */
+void vc1_intra_picture_encode_mb(MpegEncContext * s, DCTELEM block[6][64])
+{
+ int cbp, coded_cbp, i;
+ uint8_t *coded_block;
+
+ /* compute cbp */
+ cbp = 0;
+ coded_cbp = 0;
+ for (i = 0; i < 6; i++) {
+ int val, pred;
+ val = (s->block_last_index[i] >= 1);
+ cbp |= val << (5 - i);
+ if (i < 4) {
+ /* predict value for close blocks only for luma */
+ pred = vc1_coded_block_pred(s, i, &coded_block);
+ *coded_block = val;
+ val = val ^ pred;
+ }
+ coded_cbp |= val << (5 - i);
+ }
+ put_bits(&s->pb,ff_msmp4_mb_i_table[coded_cbp][1],
+ ff_msmp4_mb_i_table[coded_cbp][0]);//CBPCY
+
+ //predict dc_val and dc_direction for each block
+
+ //brute force test to switch ACPRED on/off
+ put_bits(&s->pb,1,0);//ACPRED
+
+ for (i = 0; i < 6; i++)
+ ff_msmpeg4_encode_block(s, block[i], i);
+
+ s->i_tex_bits += get_bits_diff(s);
+ s->i_count++;
+}
+
+
+
+
+/**
+ * MB layer bitstream encoder
+ * @param s Mpeg encoder context
+ * @param block macroblock to encode
+ * @param motion_x x component of mv's macroblock
+ * @param motion_y y component of mv's macroblock
+ */
+void ff_vc1_encode_mb(MpegEncContext * s, DCTELEM block[6][64],
+ int motion_x, int motion_y)
+{
+ if ( I_TYPE == s->pict_type ) {
+ vc1_intra_picture_encode_mb(s, block);
+ }
+}
+
+
+
+
+
+/**
+ * Progressive I picture layer bitstream encoder for Simple and Main Profile
+ * @param s Mpeg encoder context
+ * @param picture_number number of the frame to encode
+ */
+void vc1_encode_i_sm_picture_header(MpegEncContext * s, int picture_number)
+{
+ VC1Context * const t= s->avctx->priv_data;
+ if( t->finterpflag ) {
+ t->interpfrm = 0;//INTERPFRM
+ put_bits(&s->pb,1,t->interpfrm);
+ }
+
+ put_bits(&s->pb,2,picture_number);//FRMCNT
+
+ if( t->rangered ){
+ t->rangeredfrm = 0;//RANGEREDFRM
+ put_bits(&s->pb,1,t->rangeredfrm);
+ }
+
+ put_bits(&s->pb,1,s->pict_type-1);//PTYPE
+
+ put_bits(&s->pb,7,50);//BF
+
+ t->pquantizer = 1;//always use non uniform quantizer
+
+ if(s->qscale > 8 ) {
+ t->halfpq = 0;
+ } else {
+ t->halfpq = 1;
+ }
+
+ if( t->quantizer_mode == QUANT_FRAME_IMPLICIT){
+ //TODO create table
+ // put_bits(&s->pb,5,t->pqindex);//PQINDEX
+ } else {
+ t->pqindex = s->qscale;
+ put_bits(&s->pb,5,t->pqindex);//PQINDEX
+ }
+
+ if( t->pqindex <= 8 )
+ put_bits(&s->pb,1,t->halfpq);//HALFQP
+
+ if( t->quantizer_mode == QUANT_FRAME_EXPLICIT )
+ put_bits(&s->pb,1,t->pquantizer);//PQUANTIZER : NON_UNIFOMR 0 / UNIFORM 1
+
+ if( t->extended_mv ) {
+ t->mvrange = 0;
+ put_bits(&s->pb,1,t->mvrange);//TODO fix this: num bits is not fixed
+ }
+
+ if( t->multires ) {
+ t->respic = 0;
+ put_bits(&s->pb,2,t->respic);
+ }
+
+ if( t->pqindex<=8 ) {
+ ff_code012(&s->pb, s->rl_chroma_table_index%3);//TRANSACFRM (UV)
+ ff_code012(&s->pb, s->rl_table_index%3); //TRANSACFRM2 (Y)
+ } else {
+ ff_code012(&s->pb, s->rl_chroma_table_index);//TRANSACFRM (UV)
+ ff_code012(&s->pb, s->rl_table_index); //TRANSACFRM2 (Y)
+ }
+
+ put_bits(&s->pb, 1, s->dc_table_index);//TRANSDCTAB
+}
+
+
+
+/**
+ * Picture layer bitstream encoder
+ * @param s Mpeg encoder context
+ * @param picture_number number of the frame to encode
+ */
+void ff_vc1_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+
+ ff_find_best_tables(s);
+
+ if( I_TYPE == s->pict_type)
+ vc1_encode_i_sm_picture_header(s, picture_number) ;
+
+ s->esc3_level_length = 0;
+ s->esc3_run_length = 0;
+
+}
+
+
+/**
+ * Sequence layer bitstream encoder
+ * @param t VC1 context
+ */
+void vc1_encode_ext_header(VC1Context *t)
+{
+ MpegEncContext * const s= &t->s;
+ PutBitContext pb;
+ init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size);
+
+ t->profile = PROFILE_MAIN;
+ put_bits(&pb, 2, t->profile); //Profile
+ if(t->profile == PROFILE_ADVANCED) {
+ t->level = 2;
+ put_bits(&pb, 3, t->level); //Level
+ t->chromaformat = 1; //4:2:0
+ put_bits(&pb, 2, t->chromaformat);
+ } else {
+ put_bits(&pb, 2, 0); //Unused
+ }
+
+ put_bits(&pb, 3, 0); //TODO: Q frame rate
+ put_bits(&pb, 5, 0); //TODO: Q bit rate
+
+ s->loop_filter = 0;//TODO: loop_filter
+ put_bits(&pb, 1, s->loop_filter);
+
+ if(t->profile < PROFILE_ADVANCED) {
+ put_bits(&pb, 1, 0); //Reserved
+ put_bits(&pb, 1, 0); //Multires
+ put_bits(&pb, 1, 1); //Reserved
+ }
+
+ t->fastuvmc = 0;//TODO : FAST U/V MC
+ put_bits(&pb, 1, t->fastuvmc);
+
+ t->extended_mv = 0;//TODO : Extended MV
+ put_bits(&pb, 1, t->extended_mv);
+
+ t->dquant = 0;//TODO : MB dequant
+ put_bits(&pb, 2, t->dquant);
+
+ t->vstransform = 0;//TODO : Variable size transform
+ put_bits(&pb, 1, t->vstransform);
+
+ if (t->profile < PROFILE_ADVANCED) {
+ put_bits(&pb, 1, 0); //Reserved
+ }
+
+ t->overlap = 0; //TODO : Overlap
+ put_bits(&pb, 1, t->overlap);
+
+ if (t->profile < PROFILE_ADVANCED) {
+ s->resync_marker = 0;//TODO : Resync marker
+ put_bits(&pb, 1, s->resync_marker);
+ t->rangered = 0;// TODO: Range red
+ put_bits(&pb, 1, t->rangered);
+ }
+
+ put_bits(&pb, 3, 0); //Max B-frames
+
+ t->quantizer_mode = QUANT_FRAME_EXPLICIT;
+ put_bits(&pb, 2, t->quantizer_mode); //Quantizer
+
+ if (t->profile < PROFILE_ADVANCED) {
+ t->finterpflag = 0; //TODO : Frame interpol
+ put_bits(&pb, 1, t->finterpflag);
+ put_bits(&pb, 1, 1); //Reserved
+ }
+ flush_put_bits(&pb);
+}
+
+
+static int vc1_encode_init(AVCodecContext *avctx){
+ VC1Context * const t= avctx->priv_data;
+ MpegEncContext *s = &t->s;
+
+ if(avctx->idct_algo==FF_IDCT_AUTO)
+ avctx->idct_algo=FF_IDCT_VC1;
+
+ if(MPV_encode_init(avctx) < 0)
+ return -1;
+
+ avctx->extradata_size = 32;
+ avctx->extradata = av_mallocz(avctx->extradata_size + 10);
+ s->dct_quantize = vc1_quantize_c;
+ s->dct_unquantize_intra =
+ s->dct_unquantize_inter = vc1_unquantize_c;
+
+ vc1_encode_ext_header(t);
+
+ return 0;
+fail:
+ return 1;
+
+}
+
+AVCodec wmv3_encoder = {
+ "wmv3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV3,
+ sizeof(VC1Context),
+ vc1_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
diff --git a/libavcodec/vc1enc.h b/libavcodec/vc1enc.h
new file mode 100644
index 0000000..858746d
--- /dev/null
+++ b/libavcodec/vc1enc.h
@@ -0,0 +1,30 @@
+/*
+ * VC-1 and WMV3 encoder
+ * copyright (c) 2007 Denis Fortin
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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,
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef VC1ENC_H
+#define VC1ENC_H
+
+void ff_vc1_encode_picture_header(MpegEncContext * s, int picture_number);
+
+void ff_vc1_encode_mb(MpegEncContext * s, DCTELEM block[6][64],
+ int motion_x, int motion_y);
+
+
+#endif /* VC1ENC_H */
--
1.7.1
--------------030605000501070403060801--
More information about the ffmpeg-devel
mailing list