[Ffmpeg-devel] [PATCH] CYUV encoder resurrected

Loren Merritt lorenm
Sat Mar 3 04:10:12 CET 2007


Baptiste Coudurier wrote:
> Baptiste Coudurier wrote:
>> Michael Niedermayer wrote:
>>> Baptiste Coudurier wrote:
>>>
>>>> + uint8_t y_buf[s->avctx->width];
>>>> + uint8_t u_buf[s->avctx->width>>2];
>>>> + uint8_t v_buf[s->avctx->width>>2];
>>>> + pict->error[0] += quantize_row_trellis(avctx, y_ptr, y_buf, y_table, y_itable, s->avctx->width);
>>>> + pict->error[1] += quantize_row_trellis(avctx, u_ptr, u_buf, u_table, u_itable, s->avctx->width>>2);
>>>> + pict->error[2] += quantize_row_trellis(avctx, v_ptr, v_buf, v_table, v_itable, s->avctx->width>>2);
>>> could be put into a loop maybe, the same applies to other similar YUV cases
>>> of course only if the resulting code is simpler

Yes, it's simpler.

>> +static int quantize_sample(int sample, int *pred, const int8_t *table, const uint8_t *itable)
>> +{
>> +    int p = *pred;
>> +    int bi = itable[(sample - p) & 0xff];
>> +    *pred = p + table[bi];
>> +    if(*pred & ~0xff){
>> +        int i, bscore=INT_MAX;
>> +        for(i=0; i<16; i++){
>> +            int score = abs(sample - ((p + table[i]) & 0xff));
>
> Rah, that is changed to FFABS in my tree.

Better yet, don't compute abs at all. The whole codec (without trellis) is
13% faster this way.

--Loren Merritt
-------------- next part --------------
Index: libavcodec/cyuvenc.c
===================================================================
--- libavcodec/cyuvenc.c	(revision 0)
+++ libavcodec/cyuvenc.c	(revision 0)
@@ -0,0 +1,554 @@
+/*
+ * CYUV encoder
+ * Copyright (C) 2006 Loren Meritt.
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file cyuvenc.c
+ * Creative YUV (CYUV) Video Encoder.
+ */
+
+//#define DEBUG
+#undef NDEBUG
+
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct CyuvContext {
+    AVCodecContext *avctx;
+    AVFrame frame;
+    int8_t deltas[3][16];
+    uint8_t **y_frames;
+    uint8_t **uv_frames;
+    int n_frames, n_alloced;
+} CyuvContext;
+
+#define put_pack4to8(a,b) (*buf++ = (a) + ((b)<<4))
+
+static int quantize_sample(int sample, int *pred, const int8_t *table, const uint8_t *itable)
+{
+    int p = *pred;
+    int bi = itable[(sample - p) & 0xff];
+    *pred = p + table[bi];
+    if(*pred & ~0xff){
+        int i, bscore=INT_MAX;
+        for(i=0; i<16; i++){
+            int score = ff_squareTbl[256 + sample - ((p + table[i]) & 0xff)];
+            if(score < bscore){
+                bscore = score;
+                bi = i;
+            }
+        }
+        *pred = (p + table[bi]) & 0xff;
+    }
+    return bi;
+}
+
+typedef struct TrellisPath {
+    int nibble;
+    int prev;
+} TrellisPath;
+
+typedef struct TrellisNode {
+    uint32_t ssd;
+    int path;
+    int pred;
+} TrellisNode;
+
+static int quantize_row_trellis(AVCodecContext *avctx, const uint8_t *samples,
+                                uint8_t *dst, const int8_t *table, const uint8_t *itable, int n)
+{
+    const int frontier = 1 << avctx->trellis;
+    const int max_paths = frontier*n;
+    TrellisPath paths[max_paths], *p;
+    TrellisNode node_buf[2][frontier];
+    TrellisNode *nodep_buf[2][frontier];
+    TrellisNode **nodes = nodep_buf[0]; // nodes[] is always sorted by .ssd
+    TrellisNode **nodes_next = nodep_buf[1];
+    int pathn = 0, i, j, k, d;
+
+    memset(nodep_buf, 0, sizeof(nodep_buf));
+    nodes[0] = &node_buf[0][0];
+    paths[0].nibble = samples[0] >> 4;
+    nodes[0]->pred = paths[0].nibble << 4;
+    nodes[0]->path = pathn++;
+    d = samples[0] - nodes[0]->pred;
+    nodes[0]->ssd = d*d;
+    if(samples[0] < 0xf0) {
+        nodes[1] = &node_buf[0][1];
+        paths[1].nibble = (samples[0] >> 4) + 1;
+        nodes[1]->pred = paths[1].nibble << 4;
+        nodes[1]->path = pathn++;
+        d = samples[0] - nodes[1]->pred;
+        nodes[1]->ssd = d*d;
+        if(nodes[1]->ssd < nodes[0]->ssd)
+            FFSWAP(TrellisNode *, nodes[1], nodes[0]);
+    }
+
+    for(i=1; i<n; i++) {
+        TrellisNode *t = node_buf[i&1];
+        const int sample = samples[i];
+        int range = 2;
+        memset(nodes_next, 0, frontier*sizeof(TrellisNode*));
+        for(j=0; j<frontier && nodes[j]; j++) {
+            const int pred = nodes[j]->pred;
+            const int div = itable[(sample - pred) & 0xff];
+            const int nmin = FFMAX(div-range, 0);
+            const int nmax = FFMIN(div+range, 15);
+            int nibble;
+            range = 1;
+            for(nibble=nmin; nibble<=nmax; nibble++) {
+                int dec_sample = (pred + table[nibble]) & 0xff;
+                int d = sample - dec_sample;
+                uint32_t ssd = nodes[j]->ssd + d*d;
+                if(nodes_next[frontier-1] && ssd >= nodes_next[frontier-1]->ssd)
+                    continue;
+                for(k=0; k<frontier && nodes_next[k]; k++) {
+                    if(dec_sample == nodes_next[k]->pred) {
+                        assert(ssd >= nodes_next[k]->ssd);
+                        goto next_nibble;
+                    }
+                }
+                for(k=0; k<frontier; k++) {
+                    if(!nodes_next[k] || ssd < nodes_next[k]->ssd) {
+                        TrellisNode *u = nodes_next[frontier-1];
+                        if(!u) {
+                            u = t++;
+                            u->path = pathn++;
+                        }
+                        u->ssd = ssd;
+                        u->pred = dec_sample;
+                        paths[u->path].nibble = nibble;
+                        paths[u->path].prev = nodes[j]->path;
+                        memmove(&nodes_next[k+1], &nodes_next[k], (frontier-k-1)*sizeof(TrellisNode*));
+                        nodes_next[k] = u;
+                        break;
+                    }
+                }
+                next_nibble:;
+            }
+        }
+        FFSWAP(TrellisNode **, nodes_next, nodes);
+    }
+
+    p = &paths[nodes[0]->path];
+    for(i=n-1; i>=0; i--) {
+        dst[i] = p->nibble;
+        p = &paths[p->prev];
+    }
+    return nodes[0]->ssd;
+}
+
+static void build_inverse_table(uint8_t *itable, const int8_t *table)
+{
+    int d, i;
+    for(i=1; i<16; i++)
+        assert(table[i] > table[i-1]);
+    for(d=-128; d<128; d++){
+        int bscore = INT_MAX;
+        for(i=0; i<16; i++){
+            int score = FFABS(d - table[i]);
+            if(score > bscore)
+                break;
+            bscore = score;
+        }
+        itable[d&0xff] = i-1;
+    }
+}
+
+static int try_row(const uint8_t *samples, const int8_t *table,
+                   const uint8_t *itable, int n)
+{
+    // trellis doesn't make much difference here, so just use the fast method
+    int pred = av_clip_uint8(samples[0]+8) & -16;
+    int d = samples[0] - pred;
+    int ssd = d*d;
+    int i;
+    for(i=1; i<n; i++){
+        quantize_sample(samples[i], &pred, table, itable);
+        d = samples[i] - pred;
+        ssd += d*d;
+    }
+    return ssd;
+}
+
+static uint64_t try_table(const int8_t *table, int8_t *dst, uint64_t *score,
+                          uint8_t **pix, int pixn, int w, int h, int stride)
+{
+    uint64_t ssd = 0;
+    uint8_t itable[256];
+    int y, i;
+    build_inverse_table(itable, table);
+    for(i=0; i<pixn; i++)
+        for(y=0; y<h; y++)
+            ssd += try_row(pix[i]+y*stride, table, itable, w);
+    if(ssd < *score){
+        *score = ssd;
+        memcpy(dst, table, 16);
+    }
+    return ssd;
+}
+
+#define N_TABLES 4
+static const int8_t some_tables[2][N_TABLES][16] = {
+   {{-120, -77, -51, -36, -22, -13, -8, -3, 0, 3, 8, 16, 28, 41, 60, 96},
+    {-104, -73, -48, -29, -16,  -9, -4, -1, 0, 1, 4,  9, 16, 26, 42, 68},
+    { -47, -28, -17, -10,  -5,  -2, -1,  0, 1, 2, 5,  8, 13, 20, 31, 47},
+    { -30, -19, -12,  -7,  -4,  -3, -2, -1, 0, 1, 2,  3,  6, 10, 17, 29},
+},{
+    { -25, -14,  -9,  -6,  -3,  -2, -1,  0, 1, 2, 3,  6,  9, 14, 21, 34},
+    { -26, -17, -12,  -9,  -6,  -3, -2, -1, 0, 1, 2,  5,  8, 11, 16, 23},
+    { -43, -28, -19, -12,  -7,  -4, -1,  0, 1, 4, 7, 12, 17, 24, 33, 46},
+    { -52, -38, -27, -19, -12,  -7, -4, -1, 0, 1, 4,  9, 16, 25, 36, 52},
+}};
+static const int8_t a_table[2][16] = {
+    {-116, -75, -48, -31, -18,  -9, -4, -1, 0, 1, 4,  9, 18, 32, 54, 95},
+    { -39, -22, -13,  -8,  -5,  -2, -1,  0, 1, 2, 5,  8, 13, 20, 31, 48},
+};
+
+#ifdef DEBUG
+static void dump_table(const int8_t *table, char name, uint64_t score)
+{
+    int i;
+    dprintf("%c %7"PRIx64" ", name, score);
+    for(i=0; i<16; i++)
+        dprintf(" %2x", table[i]&0xff);
+    dprintf("\n");
+}
+#endif
+
+static uint64_t build_table(CyuvContext *s, int8_t *table, uint8_t **pix, int pixn, int plane, int w, int stride)
+{
+    const int h = s->avctx->height;
+    int i, j;
+    uint64_t ssd, bssd = 1ULL<<63;
+
+    for(i=0; i<N_TABLES; i++){
+        ssd = try_table(some_tables[!!plane][i], table, &bssd, pix, pixn, w, h, stride);
+        dprintf("%7"PRIx64" ", ssd);
+        if(ssd == 0){
+            dprintf("\n");
+            return ssd;
+        }
+    }
+    dprintf("\n");
+
+    // Iterative refinement:
+    // 16-dimensional diamond search, encoding the whole frame at each step
+    if(s->avctx->context_model >= 2){
+        int8_t tmp_buf[18];
+        int8_t *tmp = tmp_buf+1;
+        tmp[-1] = -128;
+        tmp[16] = 127;
+        try_table(s->deltas[plane], table, &bssd, pix, pixn, w, h, stride);
+
+        // modify 1 entry at a time
+        for(j=0; j<99; j++){
+            int bssd_bakj = bssd;
+#ifdef DEBUG
+            dump_table(table, "YUV"[plane], bssd);
+#endif
+            for(i=0; i<16; i++){
+                int v = table[i];
+                int bssd_baki = bssd;
+#if 0 // FIXME 0.21 PSNR gain with context == 2
+                if(v>=-2 && v<=2)
+                    continue;
+#endif
+                memcpy(tmp, table, 16);
+
+                while(++tmp[i] < tmp[i+1]){
+                    ssd = try_table(tmp, table, &bssd, pix, pixn, w, h, stride);
+                    if(ssd > bssd)
+                        break;
+                }
+                if(bssd < bssd_baki)
+                    continue;
+
+                tmp[i] = v;
+                while(--tmp[i] > tmp[i-1]){
+                    ssd = try_table(tmp, table, &bssd, pix, pixn, w, h, stride);
+                    if(ssd > bssd)
+                        break;
+                }
+            }
+            if(bssd == bssd_bakj)
+                break;
+        }
+
+        // modify 2 entries at a time
+        if(s->avctx->context_model >= 3){
+            for(j=0; j<99; j++){
+                int bssd_bakj = bssd;
+#ifdef DEBUG
+                dump_table(table, "YUV"[plane], bssd);
+#endif
+                for(i=0; i<16*16*4; i++){
+                    int i0= i&15;
+                    int i1= (i>>4)&15;
+                    int d0= ((i>>8)&1)*2-1;
+                    int d1= ((i>>9)&1)*2-1;
+
+                    if(i0>=i1)
+                        continue;
+                    memcpy(tmp, table, 16);
+                    tmp[i0] += d0;
+                    tmp[i1] += d1;
+                    if(   tmp[i0] >= tmp[i0+1] || tmp[i0] <= tmp[i0-1]
+                       || tmp[i1] >= tmp[i1+1] || tmp[i1] <= tmp[i1-1])
+                        continue;
+
+                    try_table(tmp, table, &bssd, pix, pixn, w, h, stride);
+                }
+                if(bssd == bssd_bakj)
+                    break;
+            }
+        }
+        memcpy(s->deltas[plane], table, 16);
+    }
+    return bssd;
+}
+
+static void train_tables(CyuvContext *s, int plane)
+{
+    const int k = 4;
+    const int w = s->avctx->width >> 2*plane;
+    const int h = s->avctx->height;
+    const int n = s->n_frames << plane;
+    uint8_t **all_frames = plane ? s->uv_frames : s->y_frames;
+    int i, j, pass;
+    int8_t tables[k][16];
+    memcpy(tables, some_tables[!!plane], sizeof(tables));
+
+    s->avctx->context_model = 3;
+
+    dprintf("training plane %d\n", plane);
+    for(pass=0; pass<99; pass++){
+        int8_t tables_bak[k][16], tmp[16];
+        uint8_t *pix[k][n];
+        int pixn[k], pixk[n];
+        uint64_t ssdj[k], ssdi[n], ssdsum=0;
+        memcpy(tables_bak, tables, sizeof(tables));
+        memset(pixn, 0, sizeof(pixn));
+        memset(ssdj, 0, sizeof(ssdj));
+        // assign each frame to the table that best codes it
+        dprintf("mapping ");
+        for(i=0; i<n; i++){
+            uint64_t bssd = 1ULL<<63;
+            int bj = 0;
+            for(j=0; j<k; j++){
+                uint64_t ssd = try_table(tables[j], tmp, &bssd, &all_frames[i], 1, w, h, w);
+                if(ssd == bssd)
+                    bj = j;
+            }
+            ssdj[bj] += bssd;
+            ssdi[i] = bssd;
+            pixk[i] = bj;
+            pix[bj][pixn[bj]++] = all_frames[i];
+            dprintf("%d", bj);
+        }
+#ifdef DEBUG
+        dprintf("\n");
+        for(j=0; j<k; j++){
+            dprintf("T%d (%2d)", j, pixn[j]);
+            dump_table(tables[j], ' ', ssdj[j]);
+        }
+#endif
+        // check for tables with no assigned frames,
+        // and assign them to the frames with the worst score
+        for(j=0; j<k; j++){
+            if(pixn[j] == 0){
+                uint64_t wssd = 0;
+                int wi = 0, wj, wn;
+                for(i=0; i<n; i++){
+                    if(ssdi[i] > wssd && pixn[pixk[i]] > 1){
+                        wssd = ssdi[i];
+                        wi = i;
+                    }
+                }
+                assert(wssd>0);
+                wj = pixk[wi];
+                wn = pixn[wj];
+                for(i=0; i<wn; i++){
+                    if(pix[wj][i] == all_frames[wi]){
+                        FFSWAP(uint8_t *, pix[wj][i], pix[wj][wn-1]);
+                        break;
+                    }
+                }
+                assert(i<wn);
+                pix[j][0] = all_frames[wi];
+                pixn[j]++;
+                pixk[wi] = j;
+                pixn[wj]--;
+                memcpy(tables[j], tables[wj], 16); //dunno if this is good, but it's needed for guaranteed convergence
+            }
+        }
+        // modify each table to better code the frames assigned to it
+        for(j=0; j<k; j++){
+            memcpy(s->deltas[plane], tables[j], 16);
+            ssdsum += ssdj[j] = build_table(s, tables[j], pix[j], pixn[j], plane, w, w);
+        }
+#ifdef DEBUG
+        for(j=0; j<k; j++){
+            dprintf("S%d (%2d)", j, pixn[j]);
+            dump_table(tables[j], ' ', ssdj[j]);
+        }
+        dprintf("total: %7"PRIx64"\n", ssdsum);
+#endif
+        if(!memcmp(tables_bak, tables, sizeof(tables)))
+            break;
+    }
+}
+
+static int cyuv_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data)
+{
+    CyuvContext *s = avctx->priv_data;
+    AVFrame *pict = data;
+    int8_t *tables[3] = {buf, buf+16, buf+32};
+    uint8_t itables[3][256];
+    int x, y, p;
+    const int coded_size = 48 + s->avctx->height * s->avctx->width * 3/4;
+    assert(buf_size >= coded_size);
+    s->frame = *pict;
+    pict->error[0] = pict->error[1] = pict->error[2] = 0;
+
+    if(avctx->context_model > 0){
+        for(p=0; p<3; p++)
+            build_table(s, tables[p], &s->frame.data[p], 1, p, s->avctx->width>>(p?2:0), s->frame.linesize[p]);
+    }else{
+        for(p=0; p<3; p++)
+            memcpy(tables[p], a_table[!!p], 16);
+    }
+    for(p=0; p<3; p++)
+        build_inverse_table(itables[p], tables[p]);
+    buf += 48;
+
+    for(y=0; y<s->avctx->height; y++){
+        uint8_t *ptrs[3];
+        int y0, y1;
+
+        for(p=0; p<3; p++)
+            ptrs[p] = pict->data[p] + y*pict->linesize[p];
+
+        if(avctx->trellis > 0){
+            uint8_t buf2[s->avctx->width*3/2];
+            uint8_t *bufs[3] = {buf2, buf2+s->avctx->width, buf2+s->avctx->width*5/4};
+            for(p=0; p<3; p++)
+                pict->error[p] += quantize_row_trellis(avctx, ptrs[p], bufs[p], tables[p], itables[p], s->avctx->width>>(p?2:0));
+            for(x=0; x<s->avctx->width; x+=4){
+                put_pack4to8(bufs[0][x+0], bufs[1][x>>2]);
+                put_pack4to8(bufs[0][x+1], bufs[2][x>>2]);
+                put_pack4to8(bufs[0][x+2], bufs[0][x+3]);
+            }
+        }else{
+            int y_pred = av_clip_uint8(ptrs[0][0]+8) & -16;
+            int u_pred = av_clip_uint8(ptrs[1][0]+8) & -16;
+            int v_pred = av_clip_uint8(ptrs[2][0]+8) & -16;
+            put_pack4to8(y_pred>>4, u_pred>>4);
+            y0 = quantize_sample(ptrs[0][1], &y_pred, tables[0], itables[0]);
+            put_pack4to8(y0, v_pred>>4);
+            y0 = quantize_sample(ptrs[0][2], &y_pred, tables[0], itables[0]);
+            y1 = quantize_sample(ptrs[0][3], &y_pred, tables[0], itables[0]);
+            put_pack4to8(y0, y1);
+            for(x=4; x<s->avctx->width; x+=4){
+                ptrs[0]+=4;
+                ptrs[1]++;
+                ptrs[2]++;
+                y0 = quantize_sample(ptrs[0][0], &y_pred, tables[0], itables[0]);
+                y1 = quantize_sample(ptrs[1][0], &u_pred, tables[1], itables[1]);
+                put_pack4to8(y0, y1);
+                y0 = quantize_sample(ptrs[0][1], &y_pred, tables[0], itables[0]);
+                y1 = quantize_sample(ptrs[2][0], &v_pred, tables[2], itables[2]);
+                put_pack4to8(y0, y1);
+                y0 = quantize_sample(ptrs[0][2], &y_pred, tables[0], itables[0]);
+                y1 = quantize_sample(ptrs[0][3], &y_pred, tables[0], itables[0]);
+                put_pack4to8(y0, y1);
+            }
+        }
+    }
+
+    if(avctx->flags & CODEC_FLAG_PASS1){
+        if(s->n_frames >= s->n_alloced){
+            s->n_alloced = 2*s->n_alloced+1;
+            s->y_frames = av_realloc(s->y_frames, s->n_alloced*sizeof(uint8_t*));
+            s->uv_frames = av_realloc(s->uv_frames, 2*s->n_alloced*sizeof(uint8_t*));
+        }
+        s->y_frames[s->n_frames] = av_malloc(s->avctx->width*s->avctx->height);
+        s->uv_frames[s->n_frames*2] = av_malloc(s->avctx->width*s->avctx->height/4);
+        s->uv_frames[s->n_frames*2+1] = av_malloc(s->avctx->width*s->avctx->height/4);
+        for(y=0; y<s->avctx->height; y++){
+            memcpy(s->y_frames[s->n_frames]+y*s->avctx->width,
+                   pict->data[0] + y*pict->linesize[0], s->avctx->width);
+            memcpy(s->uv_frames[s->n_frames*2]+y*s->avctx->width/4,
+                   pict->data[1] + y*pict->linesize[1], s->avctx->width/4);
+            memcpy(s->uv_frames[s->n_frames*2+1]+y*s->avctx->width/4,
+                   pict->data[2] + y*pict->linesize[2], s->avctx->width/4);
+        }
+        s->n_frames++;
+    }
+
+    s->frame = *pict;
+    avctx->coded_frame = &s->frame;
+    for(p=0; p<3; p++)
+        avctx->error[p] += pict->error[p];
+    return coded_size;
+}
+
+static int cyuv_encode_init(AVCodecContext *avctx)
+{
+    int i;
+    CyuvContext *s = avctx->priv_data;
+
+    s->avctx = avctx;
+    /* width needs to be divisible by 4 for this codec to work */
+    if((s->avctx->width & 0x3) || avctx->pix_fmt != PIX_FMT_YUV411P){
+        av_log(avctx, AV_LOG_ERROR, "Cyuv requires 411p input\n");
+        return -1;
+    }
+    avctx->bits_per_sample= 12;
+    avctx->coded_frame= &s->frame;
+
+    for(i=0; i<3; i++)
+        memcpy(s->deltas[i], some_tables[!!i][0], 16);
+
+    dsputil_static_init();
+
+    return 0;
+}
+
+static int cyuv_encode_end(AVCodecContext *avctx)
+{
+    if(avctx->flags & CODEC_FLAG_PASS1){
+        train_tables(avctx->priv_data, 0);
+        train_tables(avctx->priv_data, 1);
+    }
+    return 0;
+}
+
+AVCodec cyuv_encoder = {
+    "cyuv",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_CYUV,
+    sizeof(CyuvContext),
+    cyuv_encode_init,
+    cyuv_encode_frame,
+    cyuv_encode_end,
+    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV411P, -1},
+};
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c	(revision 8197)
+++ libavcodec/allcodecs.c	(working copy)
@@ -63,7 +63,7 @@
     REGISTER_DECODER(CINEPAK, cinepak);
     REGISTER_DECODER(CLJR, cljr);
     REGISTER_DECODER(CSCD, cscd);
-    REGISTER_DECODER(CYUV, cyuv);
+    REGISTER_ENCDEC (CYUV, cyuv);
     REGISTER_DECODER(DCA, dca);
     REGISTER_DECODER(DSICINVIDEO, dsicinvideo);
     REGISTER_ENCDEC (DVVIDEO, dvvideo);
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile	(revision 8197)
+++ libavcodec/Makefile	(working copy)
@@ -63,6 +63,7 @@
 OBJS-$(CONFIG_COOK_DECODER)            += cook.o
 OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
 OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
+OBJS-$(CONFIG_CYUV_ENCODER)            += cyuvenc.o
 OBJS-$(CONFIG_DCA_DECODER)             += dca.o
 OBJS-$(CONFIG_DSICINVIDEO_DECODER)     += dsicinav.o
 OBJS-$(CONFIG_DSICINAUDIO_DECODER)     += dsicinav.o
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 8197)
+++ libavcodec/avcodec.h	(working copy)
@@ -2160,6 +2160,7 @@
 extern AVCodec asv1_encoder;
 extern AVCodec asv2_encoder;
 extern AVCodec bmp_encoder;
+extern AVCodec cyuv_encoder;
 extern AVCodec dvvideo_encoder;
 extern AVCodec faac_encoder;
 extern AVCodec ffv1_encoder;



More information about the ffmpeg-devel mailing list