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];