1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2014 Rafaël Carré
5 * Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
6 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
25 static inline uint32_t av_le2ne32(uint32_t val
)
32 return (u
.b
[0] << 0) | (u
.b
[1] << 8) | (u
.b
[2] << 16) | (u
.b
[3] << 24);
35 void v210_convert(uint16_t *dst
, const uint32_t *bytes
, const int width
, const int height
)
37 const int stride
= ((width
+ 47) / 48) * 48 * 8 / 3 / 4;
38 uint16_t *y
= &dst
[0];
39 uint16_t *u
= &dst
[width
* height
* 2 / 2];
40 uint16_t *v
= &dst
[width
* height
* 3 / 2];
42 #define READ_PIXELS(a, b, c) \
44 val = av_le2ne32(*src++); \
46 *b++ = (val >> 10) & 0x3FF; \
47 *c++ = (val >> 20) & 0x3FF; \
50 for (int h
= 0; h
< height
; h
++) {
51 const uint32_t *src
= bytes
;
54 for (w
= 0; w
< width
- 5; w
+= 6) {
63 val
= av_le2ne32(*src
++);
67 *u
++ = (val
>> 10) & 0x3FF;
68 *y
++ = (val
>> 20) & 0x3FF;
70 val
= av_le2ne32(*src
++);
72 *y
++ = (val
>> 10) & 0x3FF;
80 block_t
*vanc_to_cc(vlc_object_t
*obj
, uint16_t *buf
, size_t words
)
83 msg_Err(obj
, "VANC line too small (%zu words)", words
);
87 static const uint8_t vanc_header
[6] = { 0x00, 0x00, 0xff, 0x03, 0xff, 0x03 };
88 if (memcmp(vanc_header
, buf
, 3*2)) {
89 /* Does not start with the VANC header */
93 size_t len
= (buf
[5] & 0xff) + 6 + 1;
95 msg_Err(obj
, "Data Count (%zu) > line length (%zu)", len
, words
);
99 uint16_t vanc_sum
= 0;
100 for (size_t i
= 3; i
< len
- 1; i
++) {
103 int p
= parity(v
& 0xff);
104 if ((!!p
^ !!(v
& 0x100)) || (np
!= 1 && np
!= 2)) {
105 msg_Err(obj
, "Parity incorrect for word %zu", i
);
113 vanc_sum
|= ((~vanc_sum
& 0x100) << 1);
114 if (buf
[len
- 1] != vanc_sum
) {
115 msg_Err(obj
, "VANC checksum incorrect: 0x%.4x != 0x%.4x", vanc_sum
, buf
[len
-1]);
119 if (buf
[3] != 0x61 /* DID */ || buf
[4] != 0x01 /* SDID = CEA-708 */) {
120 //msg_Err(obj, "Not a CEA-708 packet: DID = 0x%.2x SDID = 0x%.2x", buf[3], buf[4]);
121 // XXX : what is Not a CEA-708 packet: DID = 0x61 SDID = 0x02 ?
126 uint16_t *cdp
= &buf
[6];
127 if (cdp
[0] != 0x96 || cdp
[1] != 0x69) {
128 msg_Err(obj
, "Invalid CDP header 0x%.2x 0x%.2x", cdp
[0], cdp
[1]);
132 len
-= 7; // remove VANC header and checksum
135 msg_Err(obj
, "CDP len %d != %zu", cdp
[2], len
);
140 for (size_t i
= 0; i
< len
- 1; i
++)
142 cdp_sum
= cdp_sum
? 256 - cdp_sum
: 0;
143 if (cdp
[len
- 1] != cdp_sum
) {
144 msg_Err(obj
, "CDP checksum invalid 0x%.4x != 0x%.4x", cdp_sum
, cdp
[len
-1]);
148 uint8_t rate
= cdp
[3];
149 if (!(rate
& 0x0f)) {
150 msg_Err(obj
, "CDP frame rate invalid (0x%.2x)", rate
);
155 msg_Err(obj
, "CDP frame rate invalid (0x%.2x)", rate
);
159 if (!(cdp
[4] & 0x43)) /* ccdata_present | caption_service_active | reserved */ {
160 msg_Err(obj
, "CDP flags invalid (0x%.2x)", cdp
[4]);
164 uint16_t hdr
= (cdp
[5] << 8) | cdp
[6];
165 if (cdp
[7] != 0x72) /* ccdata_id */ {
166 msg_Err(obj
, "Invalid ccdata_id 0x%.2x", cdp
[7]);
170 unsigned cc_count
= cdp
[8];
171 if (!(cc_count
& 0xe0)) {
172 msg_Err(obj
, "Invalid cc_count 0x%.2x", cc_count
);
177 if ((len
- 13) < cc_count
* 3) {
178 msg_Err(obj
, "Invalid cc_count %d (> %zu)", cc_count
* 3, len
- 13);
182 if (cdp
[len
- 4] != 0x74) /* footer id */ {
183 msg_Err(obj
, "Invalid footer id 0x%.2x", cdp
[len
-4]);
187 uint16_t ftr
= (cdp
[len
- 3] << 8) | cdp
[len
- 2];
189 msg_Err(obj
, "Header 0x%.4x != Footer 0x%.4x", hdr
, ftr
);
193 block_t
*cc
= block_Alloc(cc_count
* 3);
195 for (size_t i
= 0; i
< cc_count
; i
++) {
196 cc
->p_buffer
[3*i
+0] = cdp
[9 + 3*i
+0] /* & 3 */;
197 cc
->p_buffer
[3*i
+1] = cdp
[9 + 3*i
+1];
198 cc
->p_buffer
[3*i
+2] = cdp
[9 + 3*i
+2];