1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * FFV1 encoder template
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2003-2016 Michael Niedermayer <michaelni@gmx.at>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_cistatic av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
24cabdff1aSopenharmony_ci                                                TYPE *sample[3],
25cabdff1aSopenharmony_ci                                                int plane_index, int bits)
26cabdff1aSopenharmony_ci{
27cabdff1aSopenharmony_ci    PlaneContext *const p = &s->plane[plane_index];
28cabdff1aSopenharmony_ci    RangeCoder *const c   = &s->c;
29cabdff1aSopenharmony_ci    int x;
30cabdff1aSopenharmony_ci    int run_index = s->run_index;
31cabdff1aSopenharmony_ci    int run_count = 0;
32cabdff1aSopenharmony_ci    int run_mode  = 0;
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci    if (s->ac != AC_GOLOMB_RICE) {
35cabdff1aSopenharmony_ci        if (c->bytestream_end - c->bytestream < w * 35) {
36cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
37cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
38cabdff1aSopenharmony_ci        }
39cabdff1aSopenharmony_ci    } else {
40cabdff1aSopenharmony_ci        if (put_bytes_left(&s->pb, 0) < w * 4) {
41cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
42cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
43cabdff1aSopenharmony_ci        }
44cabdff1aSopenharmony_ci    }
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci    if (s->slice_coding_mode == 1) {
47cabdff1aSopenharmony_ci        for (x = 0; x < w; x++) {
48cabdff1aSopenharmony_ci            int i;
49cabdff1aSopenharmony_ci            int v = sample[0][x];
50cabdff1aSopenharmony_ci            for (i = bits-1; i>=0; i--) {
51cabdff1aSopenharmony_ci                uint8_t state = 128;
52cabdff1aSopenharmony_ci                put_rac(c, &state, (v>>i) & 1);
53cabdff1aSopenharmony_ci            }
54cabdff1aSopenharmony_ci        }
55cabdff1aSopenharmony_ci        return 0;
56cabdff1aSopenharmony_ci    }
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    for (x = 0; x < w; x++) {
59cabdff1aSopenharmony_ci        int diff, context;
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_ci        context = RENAME(get_context)(p, sample[0] + x, sample[1] + x, sample[2] + x);
62cabdff1aSopenharmony_ci        diff    = sample[0][x] - RENAME(predict)(sample[0] + x, sample[1] + x);
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci        if (context < 0) {
65cabdff1aSopenharmony_ci            context = -context;
66cabdff1aSopenharmony_ci            diff    = -diff;
67cabdff1aSopenharmony_ci        }
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci        diff = fold(diff, bits);
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci        if (s->ac != AC_GOLOMB_RICE) {
72cabdff1aSopenharmony_ci            if (s->flags & AV_CODEC_FLAG_PASS1) {
73cabdff1aSopenharmony_ci                put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat,
74cabdff1aSopenharmony_ci                                  s->rc_stat2[p->quant_table_index][context]);
75cabdff1aSopenharmony_ci            } else {
76cabdff1aSopenharmony_ci                put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL);
77cabdff1aSopenharmony_ci            }
78cabdff1aSopenharmony_ci        } else {
79cabdff1aSopenharmony_ci            if (context == 0)
80cabdff1aSopenharmony_ci                run_mode = 1;
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci            if (run_mode) {
83cabdff1aSopenharmony_ci                if (diff) {
84cabdff1aSopenharmony_ci                    while (run_count >= 1 << ff_log2_run[run_index]) {
85cabdff1aSopenharmony_ci                        run_count -= 1 << ff_log2_run[run_index];
86cabdff1aSopenharmony_ci                        run_index++;
87cabdff1aSopenharmony_ci                        put_bits(&s->pb, 1, 1);
88cabdff1aSopenharmony_ci                    }
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci                    put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count);
91cabdff1aSopenharmony_ci                    if (run_index)
92cabdff1aSopenharmony_ci                        run_index--;
93cabdff1aSopenharmony_ci                    run_count = 0;
94cabdff1aSopenharmony_ci                    run_mode  = 0;
95cabdff1aSopenharmony_ci                    if (diff > 0)
96cabdff1aSopenharmony_ci                        diff--;
97cabdff1aSopenharmony_ci                } else {
98cabdff1aSopenharmony_ci                    run_count++;
99cabdff1aSopenharmony_ci                }
100cabdff1aSopenharmony_ci            }
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci            ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
103cabdff1aSopenharmony_ci                    run_count, run_index, run_mode, x,
104cabdff1aSopenharmony_ci                    (int)put_bits_count(&s->pb));
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci            if (run_mode == 0)
107cabdff1aSopenharmony_ci                put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits);
108cabdff1aSopenharmony_ci        }
109cabdff1aSopenharmony_ci    }
110cabdff1aSopenharmony_ci    if (run_mode) {
111cabdff1aSopenharmony_ci        while (run_count >= 1 << ff_log2_run[run_index]) {
112cabdff1aSopenharmony_ci            run_count -= 1 << ff_log2_run[run_index];
113cabdff1aSopenharmony_ci            run_index++;
114cabdff1aSopenharmony_ci            put_bits(&s->pb, 1, 1);
115cabdff1aSopenharmony_ci        }
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci        if (run_count)
118cabdff1aSopenharmony_ci            put_bits(&s->pb, 1, 1);
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci    s->run_index = run_index;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    return 0;
123cabdff1aSopenharmony_ci}
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_cistatic int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
126cabdff1aSopenharmony_ci                                    int w, int h, const int stride[4])
127cabdff1aSopenharmony_ci{
128cabdff1aSopenharmony_ci    int x, y, p, i;
129cabdff1aSopenharmony_ci    const int ring_size = s->context_model ? 3 : 2;
130cabdff1aSopenharmony_ci    TYPE *sample[4][3];
131cabdff1aSopenharmony_ci    int lbd    = s->bits_per_raw_sample <= 8;
132cabdff1aSopenharmony_ci    int packed = !src[1];
133cabdff1aSopenharmony_ci    int bits   = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
134cabdff1aSopenharmony_ci    int offset = 1 << bits;
135cabdff1aSopenharmony_ci    int transparency = s->transparency;
136cabdff1aSopenharmony_ci    int packed_size = (3 + transparency)*2;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci    s->run_index = 0;
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci    memset(RENAME(s->sample_buffer), 0, ring_size * MAX_PLANES *
141cabdff1aSopenharmony_ci           (w + 6) * sizeof(*RENAME(s->sample_buffer)));
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    for (y = 0; y < h; y++) {
144cabdff1aSopenharmony_ci        for (i = 0; i < ring_size; i++)
145cabdff1aSopenharmony_ci            for (p = 0; p < MAX_PLANES; p++)
146cabdff1aSopenharmony_ci                sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_ci        for (x = 0; x < w; x++) {
149cabdff1aSopenharmony_ci            int b, g, r, av_uninit(a);
150cabdff1aSopenharmony_ci            if (lbd) {
151cabdff1aSopenharmony_ci                unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y));
152cabdff1aSopenharmony_ci                b =  v        & 0xFF;
153cabdff1aSopenharmony_ci                g = (v >>  8) & 0xFF;
154cabdff1aSopenharmony_ci                r = (v >> 16) & 0xFF;
155cabdff1aSopenharmony_ci                a =  v >> 24;
156cabdff1aSopenharmony_ci            } else if (packed) {
157cabdff1aSopenharmony_ci                const uint16_t *p = ((const uint16_t*)(src[0] + x*packed_size + stride[0]*y));
158cabdff1aSopenharmony_ci                r = p[0];
159cabdff1aSopenharmony_ci                g = p[1];
160cabdff1aSopenharmony_ci                b = p[2];
161cabdff1aSopenharmony_ci                if (transparency)
162cabdff1aSopenharmony_ci                  a = p[3];
163cabdff1aSopenharmony_ci            } else if (sizeof(TYPE) == 4 || transparency) {
164cabdff1aSopenharmony_ci                g = *((const uint16_t *)(src[0] + x*2 + stride[0]*y));
165cabdff1aSopenharmony_ci                b = *((const uint16_t *)(src[1] + x*2 + stride[1]*y));
166cabdff1aSopenharmony_ci                r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
167cabdff1aSopenharmony_ci                if (transparency)
168cabdff1aSopenharmony_ci                    a = *((const uint16_t *)(src[3] + x*2 + stride[3]*y));
169cabdff1aSopenharmony_ci            } else {
170cabdff1aSopenharmony_ci                b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y));
171cabdff1aSopenharmony_ci                g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y));
172cabdff1aSopenharmony_ci                r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
173cabdff1aSopenharmony_ci            }
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_ci            if (s->slice_coding_mode != 1) {
176cabdff1aSopenharmony_ci                b -= g;
177cabdff1aSopenharmony_ci                r -= g;
178cabdff1aSopenharmony_ci                g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
179cabdff1aSopenharmony_ci                b += offset;
180cabdff1aSopenharmony_ci                r += offset;
181cabdff1aSopenharmony_ci            }
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci            sample[0][0][x] = g;
184cabdff1aSopenharmony_ci            sample[1][0][x] = b;
185cabdff1aSopenharmony_ci            sample[2][0][x] = r;
186cabdff1aSopenharmony_ci            sample[3][0][x] = a;
187cabdff1aSopenharmony_ci        }
188cabdff1aSopenharmony_ci        for (p = 0; p < 3 + transparency; p++) {
189cabdff1aSopenharmony_ci            int ret;
190cabdff1aSopenharmony_ci            sample[p][0][-1] = sample[p][1][0  ];
191cabdff1aSopenharmony_ci            sample[p][1][ w] = sample[p][1][w-1];
192cabdff1aSopenharmony_ci            if (lbd && s->slice_coding_mode == 0)
193cabdff1aSopenharmony_ci                ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, 9);
194cabdff1aSopenharmony_ci            else
195cabdff1aSopenharmony_ci                ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
196cabdff1aSopenharmony_ci            if (ret < 0)
197cabdff1aSopenharmony_ci                return ret;
198cabdff1aSopenharmony_ci        }
199cabdff1aSopenharmony_ci    }
200cabdff1aSopenharmony_ci    return 0;
201cabdff1aSopenharmony_ci}
202cabdff1aSopenharmony_ci
203