FFmpeg
dv.c
Go to the documentation of this file.
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 {
51  static const uint8_t off[] = { 2, 6, 8, 0, 4 };
52  static const uint8_t shuf1[] = { 36, 18, 54, 0, 72 };
53  static const uint8_t shuf2[] = { 24, 12, 36, 0, 48 };
54  static const uint8_t shuf3[] = { 18, 9, 27, 0, 36 };
55 
56  static const uint8_t l_start[] = { 0, 4, 9, 13, 18, 22, 27, 31, 36, 40 };
57  static const uint8_t l_start_shuffled[] = { 9, 4, 13, 0, 18 };
58 
59  static const uint8_t serpent1[] = {
60  0, 1, 2, 2, 1, 0,
61  0, 1, 2, 2, 1, 0,
62  0, 1, 2, 2, 1, 0,
63  0, 1, 2, 2, 1, 0,
64  0, 1, 2
65  };
66  static const uint8_t serpent2[] = {
67  0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0,
68  0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0,
69  0, 1, 2, 3, 4, 5
70  };
71 
72  static const uint8_t remap[][2] = {
73  { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* dummy */
74  { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 10, 0 },
75  { 10, 1 }, { 10, 2 }, { 10, 3 }, { 20, 0 }, { 20, 1 },
76  { 20, 2 }, { 20, 3 }, { 30, 0 }, { 30, 1 }, { 30, 2 },
77  { 30, 3 }, { 40, 0 }, { 40, 1 }, { 40, 2 }, { 40, 3 },
78  { 50, 0 }, { 50, 1 }, { 50, 2 }, { 50, 3 }, { 60, 0 },
79  { 60, 1 }, { 60, 2 }, { 60, 3 }, { 70, 0 }, { 70, 1 },
80  { 70, 2 }, { 70, 3 }, { 0, 64 }, { 0, 65 }, { 0, 66 },
81  { 10, 64 }, { 10, 65 }, { 10, 66 }, { 20, 64 }, { 20, 65 },
82  { 20, 66 }, { 30, 64 }, { 30, 65 }, { 30, 66 }, { 40, 64 },
83  { 40, 65 }, { 40, 66 }, { 50, 64 }, { 50, 65 }, { 50, 66 },
84  { 60, 64 }, { 60, 65 }, { 60, 66 }, { 70, 64 }, { 70, 65 },
85  { 70, 66 }, { 0, 67 }, { 20, 67 }, { 40, 67 }, { 60, 67 }
86  };
87 
88  int i, k, m;
89  int x, y, blk;
90 
91  for (m = 0; m < 5; m++) {
92  switch (d->width) {
93  case 1440:
94  blk = (chan * 11 + seq) * 27 + slot;
95 
96  if (chan == 0 && seq == 11) {
97  x = m * 27 + slot;
98  if (x < 90) {
99  y = 0;
100  } else {
101  x = (x - 90) * 2;
102  y = 67;
103  }
104  } else {
105  i = (4 * chan + blk + off[m]) % 11;
106  k = (blk / 11) % 27;
107 
108  x = shuf1[m] + (chan & 1) * 9 + k % 9;
109  y = (i * 3 + k / 9) * 2 + (chan >> 1) + 1;
110  }
111  tbl[m] = (x << 1) | (y << 9);
112  break;
113  case 1280:
114  blk = (chan * 10 + seq) * 27 + slot;
115 
116  i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10;
117  k = (blk / 5) % 27;
118 
119  x = shuf1[m] + (chan & 1) * 9 + k % 9;
120  y = (i * 3 + k / 9) * 2 + (chan >> 1) + 4;
121 
122  if (x >= 80) {
123  x = remap[y][0] + ((x - 80) << (y > 59));
124  y = remap[y][1];
125  }
126  tbl[m] = (x << 1) | (y << 9);
127  break;
128  case 960:
129  blk = (chan * 10 + seq) * 27 + slot;
130 
131  i = (4 * chan + (seq / 5) + 2 * blk + off[m]) % 10;
132  k = (blk / 5) % 27 + (i & 1) * 3;
133 
134  x = shuf2[m] + k % 6 + 6 * (chan & 1);
135  y = l_start[i] + k / 6 + 45 * (chan >> 1);
136  tbl[m] = (x << 1) | (y << 9);
137  break;
138  case 720:
139  switch (d->pix_fmt) {
140  case AV_PIX_FMT_YUV422P:
141  x = shuf3[m] + slot / 3;
142  y = serpent1[slot] +
143  ((((seq + off[m]) % d->difseg_size) << 1) + chan) * 3;
144  tbl[m] = (x << 1) | (y << 8);
145  break;
146  case AV_PIX_FMT_YUV420P:
147  x = shuf3[m] + slot / 3;
148  y = serpent1[slot] +
149  ((seq + off[m]) % d->difseg_size) * 3;
150  tbl[m] = (x << 1) | (y << 9);
151  break;
152  case AV_PIX_FMT_YUV411P:
153  i = (seq + off[m]) % d->difseg_size;
154  k = slot + ((m == 1 || m == 2) ? 3 : 0);
155 
156  x = l_start_shuffled[m] + k / 6;
157  y = serpent2[k] + i * 6;
158  if (x > 21)
159  y = y * 2 - i * 6;
160  tbl[m] = (x << 2) | (y << 8);
161  break;
162  }
163  default:
164  break;
165  }
166  }
167 }
168 
170 {
171  int j, i, c, s, p;
172 
173  p = i = 0;
174  for (c = 0; c < d->n_difchan; c++) {
175  for (s = 0; s < d->difseg_size; s++) {
176  p += 6;
177  for (j = 0; j < 27; j++) {
178  p += !(j % 3);
179  if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) &&
180  !(DV_PROFILE_IS_720p50(d) && s > 9)) {
181  dv_calc_mb_coordinates(d, c, s, j, &work_chunks[i].mb_coordinates[0]);
182  work_chunks[i++].buf_offset = p;
183  }
184  p += 5;
185  }
186  }
187  }
188 }
DVwork_chunk::buf_offset
uint16_t buf_offset
Definition: dv_internal.h:31
DVwork_chunk
Definition: dv_internal.h:30
dv_calc_mb_coordinates
static void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, int seq, int slot, uint16_t *tbl)
Definition: dv.c:48
AVDVProfile::difseg_size
int difseg_size
Definition: dv_profile.h:42
dv_profile.h
DV_PROFILE_IS_1080i50
#define DV_PROFILE_IS_1080i50(p)
Definition: dv.h:54
s
#define s(width, name)
Definition: cbs_vp9.c:198
AVDVProfile::pix_fmt
enum AVPixelFormat pix_fmt
Definition: dv_profile.h:49
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
blk
#define blk(i)
Definition: sha.c:186
DV_PROFILE_IS_720p50
#define DV_PROFILE_IS_720p50(p)
Definition: dv.h:56
AVDVProfile::n_difchan
int n_difchan
Definition: dv_profile.h:43
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
remap
static const int remap[16]
Definition: msvideo1enc.c:66
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVDVProfile::width
int width
Definition: dv_profile.h:47
pixfmt.h
dv_internal.h
AVDVProfile
Definition: dv_profile.h:38
ff_dv_init_dynamic_tables
void ff_dv_init_dynamic_tables(DVwork_chunk *work_chunks, const AVDVProfile *d)
Definition: dv.c:169
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:80