/src/ffmpeg/libavcodec/dv.c
Line | Count | Source |
1 | | /* |
2 | | * DV decoder |
3 | | * Copyright (c) 2002 Fabrice Bellard |
4 | | * Copyright (c) 2004 Roman Shaposhnik |
5 | | * |
6 | | * DV encoder |
7 | | * Copyright (c) 2003 Roman Shaposhnik |
8 | | * |
9 | | * 50 Mbps (DVCPRO50) support |
10 | | * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com> |
11 | | * |
12 | | * 100 Mbps (DVCPRO HD) support |
13 | | * Initial code by Daniel Maas <dmaas@maasdigital.com> (funded by BBC R&D) |
14 | | * Final code by Roman Shaposhnik |
15 | | * |
16 | | * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth |
17 | | * of DV technical info. |
18 | | * |
19 | | * This file is part of FFmpeg. |
20 | | * |
21 | | * FFmpeg is free software; you can redistribute it and/or |
22 | | * modify it under the terms of the GNU Lesser General Public |
23 | | * License as published by the Free Software Foundation; either |
24 | | * version 2.1 of the License, or (at your option) any later version. |
25 | | * |
26 | | * FFmpeg is distributed in the hope that it will be useful, |
27 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
29 | | * Lesser General Public License for more details. |
30 | | * |
31 | | * You should have received a copy of the GNU Lesser General Public |
32 | | * License along with FFmpeg; if not, write to the Free Software |
33 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
34 | | */ |
35 | | |
36 | | /** |
37 | | * @file |
38 | | * DV codec. |
39 | | */ |
40 | | |
41 | | #include <stdint.h> |
42 | | |
43 | | #include "libavutil/pixfmt.h" |
44 | | |
45 | | #include "dv_internal.h" |
46 | | #include "dv_profile.h" |
47 | | |
48 | | static inline void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, |
49 | | int seq, int slot, uint16_t *tbl) |
50 | 459k | { |
51 | 459k | static const uint8_t off[] = { 2, 6, 8, 0, 4 }; |
52 | 459k | static const uint8_t shuf1[] = { 36, 18, 54, 0, 72 }; |
53 | 459k | static const uint8_t shuf2[] = { 24, 12, 36, 0, 48 }; |
54 | 459k | static const uint8_t shuf3[] = { 18, 9, 27, 0, 36 }; |
55 | | |
56 | 459k | static const uint8_t l_start[] = { 0, 4, 9, 13, 18, 22, 27, 31, 36, 40 }; |
57 | 459k | static const uint8_t l_start_shuffled[] = { 9, 4, 13, 0, 18 }; |
58 | | |
59 | 459k | static const uint8_t serpent1[] = { |
60 | 459k | 0, 1, 2, 2, 1, 0, |
61 | 459k | 0, 1, 2, 2, 1, 0, |
62 | 459k | 0, 1, 2, 2, 1, 0, |
63 | 459k | 0, 1, 2, 2, 1, 0, |
64 | 459k | 0, 1, 2 |
65 | 459k | }; |
66 | 459k | static const uint8_t serpent2[] = { |
67 | 459k | 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, |
68 | 459k | 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, |
69 | 459k | 0, 1, 2, 3, 4, 5 |
70 | 459k | }; |
71 | | |
72 | 459k | static const uint8_t remap[][2] = { |
73 | 459k | { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* dummy */ |
74 | 459k | { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 10, 0 }, |
75 | 459k | { 10, 1 }, { 10, 2 }, { 10, 3 }, { 20, 0 }, { 20, 1 }, |
76 | 459k | { 20, 2 }, { 20, 3 }, { 30, 0 }, { 30, 1 }, { 30, 2 }, |
77 | 459k | { 30, 3 }, { 40, 0 }, { 40, 1 }, { 40, 2 }, { 40, 3 }, |
78 | 459k | { 50, 0 }, { 50, 1 }, { 50, 2 }, { 50, 3 }, { 60, 0 }, |
79 | 459k | { 60, 1 }, { 60, 2 }, { 60, 3 }, { 70, 0 }, { 70, 1 }, |
80 | 459k | { 70, 2 }, { 70, 3 }, { 0, 64 }, { 0, 65 }, { 0, 66 }, |
81 | 459k | { 10, 64 }, { 10, 65 }, { 10, 66 }, { 20, 64 }, { 20, 65 }, |
82 | 459k | { 20, 66 }, { 30, 64 }, { 30, 65 }, { 30, 66 }, { 40, 64 }, |
83 | 459k | { 40, 65 }, { 40, 66 }, { 50, 64 }, { 50, 65 }, { 50, 66 }, |
84 | 459k | { 60, 64 }, { 60, 65 }, { 60, 66 }, { 70, 64 }, { 70, 65 }, |
85 | 459k | { 70, 66 }, { 0, 67 }, { 20, 67 }, { 40, 67 }, { 60, 67 } |
86 | 459k | }; |
87 | | |
88 | 459k | int i, k, m; |
89 | 459k | int x, y, blk; |
90 | | |
91 | 2.75M | for (m = 0; m < 5; m++) { |
92 | 2.29M | switch (d->width) { |
93 | 36.4k | case 1440: |
94 | 36.4k | blk = (chan * 11 + seq) * 27 + slot; |
95 | | |
96 | 36.4k | if (chan == 0 && seq == 11) { |
97 | 810 | x = m * 27 + slot; |
98 | 810 | if (x < 90) { |
99 | 540 | y = 0; |
100 | 540 | } else { |
101 | 270 | x = (x - 90) * 2; |
102 | 270 | y = 67; |
103 | 270 | } |
104 | 35.6k | } else { |
105 | 35.6k | i = (4 * chan + blk + off[m]) % 11; |
106 | 35.6k | k = (blk / 11) % 27; |
107 | | |
108 | 35.6k | x = shuf1[m] + (chan & 1) * 9 + k % 9; |
109 | 35.6k | y = (i * 3 + k / 9) * 2 + (chan >> 1) + 1; |
110 | 35.6k | } |
111 | 36.4k | tbl[m] = (x << 1) | (y << 9); |
112 | 36.4k | break; |
113 | 675k | case 1280: |
114 | 675k | blk = (chan * 10 + seq) * 27 + slot; |
115 | | |
116 | 675k | i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10; |
117 | 675k | k = (blk / 5) % 27; |
118 | | |
119 | 675k | x = shuf1[m] + (chan & 1) * 9 + k % 9; |
120 | 675k | y = (i * 3 + k / 9) * 2 + (chan >> 1) + 4; |
121 | | |
122 | 675k | if (x >= 80) { |
123 | 75.0k | x = remap[y][0] + ((x - 80) << (y > 59)); |
124 | 75.0k | y = remap[y][1]; |
125 | 75.0k | } |
126 | 675k | tbl[m] = (x << 1) | (y << 9); |
127 | 675k | break; |
128 | 291k | case 960: |
129 | 291k | blk = (chan * 10 + seq) * 27 + slot; |
130 | | |
131 | 291k | i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10; |
132 | 291k | k = (blk / 5) % 27 + (i & 1) * 3; |
133 | | |
134 | 291k | x = shuf2[m] + k % 6 + 6 * (chan & 1); |
135 | 291k | y = l_start[i] + k / 6 + 45 * (chan >> 1); |
136 | 291k | tbl[m] = (x << 1) | (y << 9); |
137 | 291k | break; |
138 | 1.29M | case 720: |
139 | 1.29M | switch (d->pix_fmt) { |
140 | 52.9k | case AV_PIX_FMT_YUV422P: |
141 | 52.9k | x = shuf3[m] + slot / 3; |
142 | 52.9k | y = serpent1[slot] + |
143 | 52.9k | ((((seq + off[m]) % d->difseg_size) << 1) + chan) * 3; |
144 | 52.9k | tbl[m] = (x << 1) | (y << 8); |
145 | 52.9k | break; |
146 | 29.1k | case AV_PIX_FMT_YUV420P: |
147 | 29.1k | x = shuf3[m] + slot / 3; |
148 | 29.1k | y = serpent1[slot] + |
149 | 29.1k | ((seq + off[m]) % d->difseg_size) * 3; |
150 | 29.1k | tbl[m] = (x << 1) | (y << 9); |
151 | 29.1k | break; |
152 | 1.21M | case AV_PIX_FMT_YUV411P: |
153 | 1.21M | i = (seq + off[m]) % d->difseg_size; |
154 | 1.21M | k = slot + ((m == 1 || m == 2) ? 3 : 0); |
155 | | |
156 | 1.21M | x = l_start_shuffled[m] + k / 6; |
157 | 1.21M | y = serpent2[k] + i * 6; |
158 | 1.21M | if (x > 21) |
159 | 26.9k | y = y * 2 - i * 6; |
160 | 1.21M | tbl[m] = (x << 2) | (y << 8); |
161 | 1.21M | break; |
162 | 1.29M | } |
163 | 1.29M | default: |
164 | 1.29M | break; |
165 | 2.29M | } |
166 | 2.29M | } |
167 | 459k | } |
168 | | |
169 | | void ff_dv_init_dynamic_tables(DVwork_chunk *work_chunks, const AVDVProfile *d) |
170 | 1.16k | { |
171 | 1.16k | int j, i, c, s, p; |
172 | | |
173 | 1.16k | p = i = 0; |
174 | 2.85k | for (c = 0; c < d->n_difchan; c++) { |
175 | 18.7k | for (s = 0; s < d->difseg_size; s++) { |
176 | 17.1k | p += 6; |
177 | 478k | for (j = 0; j < 27; j++) { |
178 | 461k | p += !(j % 3); |
179 | 461k | if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) && |
180 | 461k | !(DV_PROFILE_IS_720p50(d) && s > 9)) { |
181 | 459k | dv_calc_mb_coordinates(d, c, s, j, &work_chunks[i].mb_coordinates[0]); |
182 | 459k | work_chunks[i++].buf_offset = p; |
183 | 459k | } |
184 | 461k | p += 5; |
185 | 461k | } |
186 | 17.1k | } |
187 | 1.68k | } |
188 | 1.16k | } |