[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