"Fossies" - the Fresh Open Source Software Archive

Member "vlc-3.0.8/modules/access/sdi.c" (24 Nov 2017, 6227 Bytes) of package /linux/misc/vlc-3.0.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sdi.c" see the Fossies "Dox" file reference documentation.

    1 /*****************************************************************************
    2  * sdi.c: SDI helpers
    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>
    7  *
    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.
   12  *
   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.
   17  *
   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  *****************************************************************************/
   22 
   23 #include "sdi.h"
   24 
   25 static inline uint32_t av_le2ne32(uint32_t val)
   26 {
   27     union {
   28         uint32_t v;
   29         uint8_t b[4];
   30     } u;
   31     u.v = val;
   32     return (u.b[0] << 0) | (u.b[1] << 8) | (u.b[2] << 16) | (u.b[3] << 24);
   33 }
   34 
   35 void v210_convert(uint16_t *dst, const uint32_t *bytes, const int width, const int height)
   36 {
   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];
   41 
   42 #define READ_PIXELS(a, b, c)         \
   43     do {                             \
   44         val  = av_le2ne32(*src++);   \
   45         *a++ =  val & 0x3FF;         \
   46         *b++ = (val >> 10) & 0x3FF;  \
   47         *c++ = (val >> 20) & 0x3FF;  \
   48     } while (0)
   49 
   50     for (int h = 0; h < height; h++) {
   51         const uint32_t *src = bytes;
   52         uint32_t val = 0;
   53         int w;
   54         for (w = 0; w < width - 5; w += 6) {
   55             READ_PIXELS(u, y, v);
   56             READ_PIXELS(y, u, y);
   57             READ_PIXELS(v, y, u);
   58             READ_PIXELS(y, v, y);
   59         }
   60         if (w < width - 1) {
   61             READ_PIXELS(u, y, v);
   62 
   63             val  = av_le2ne32(*src++);
   64             *y++ =  val & 0x3FF;
   65         }
   66         if (w < width - 3) {
   67             *u++ = (val >> 10) & 0x3FF;
   68             *y++ = (val >> 20) & 0x3FF;
   69 
   70             val  = av_le2ne32(*src++);
   71             *v++ =  val & 0x3FF;
   72             *y++ = (val >> 10) & 0x3FF;
   73         }
   74 
   75         bytes += stride;
   76     }
   77 }
   78 
   79 #undef vanc_to_cc
   80 block_t *vanc_to_cc(vlc_object_t *obj, uint16_t *buf, size_t words)
   81 {
   82     if (words < 3) {
   83         msg_Err(obj, "VANC line too small (%zu words)", words);
   84         return NULL;
   85     }
   86 
   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 */
   90         return NULL;
   91     }
   92 
   93     size_t len = (buf[5] & 0xff) + 6 + 1;
   94     if (len > words) {
   95         msg_Err(obj, "Data Count (%zu) > line length (%zu)", len, words);
   96         return NULL;
   97     }
   98 
   99     uint16_t vanc_sum = 0;
  100     for (size_t i = 3; i < len - 1; i++) {
  101         uint16_t v = buf[i];
  102         int np = v >> 8;
  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);
  106             return NULL;
  107         }
  108         vanc_sum += v;
  109         vanc_sum &= 0x1ff;
  110         buf[i] &= 0xff;
  111     }
  112 
  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]);
  116         return NULL;
  117     }
  118 
  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 ?
  122         return NULL;
  123     }
  124 
  125     /* CDP follows */
  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]);
  129         return NULL;
  130     }
  131 
  132     len -= 7; // remove VANC header and checksum
  133 
  134     if (cdp[2] != len) {
  135         msg_Err(obj, "CDP len %d != %zu", cdp[2], len);
  136         return NULL;
  137     }
  138 
  139     uint8_t cdp_sum = 0;
  140     for (size_t i = 0; i < len - 1; i++)
  141         cdp_sum += cdp[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]);
  145         return NULL;
  146     }
  147 
  148     uint8_t rate = cdp[3];
  149     if (!(rate & 0x0f)) {
  150         msg_Err(obj, "CDP frame rate invalid (0x%.2x)", rate);
  151         return NULL;
  152     }
  153     rate >>= 4;
  154     if (rate > 8) {
  155         msg_Err(obj, "CDP frame rate invalid (0x%.2x)", rate);
  156         return NULL;
  157     }
  158 
  159     if (!(cdp[4] & 0x43)) /* ccdata_present | caption_service_active | reserved */ {
  160         msg_Err(obj, "CDP flags invalid (0x%.2x)", cdp[4]);
  161         return NULL;
  162     }
  163 
  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]);
  167         return NULL;
  168     }
  169 
  170     unsigned cc_count = cdp[8];
  171     if (!(cc_count & 0xe0)) {
  172         msg_Err(obj, "Invalid cc_count 0x%.2x", cc_count);
  173         return NULL;
  174     }
  175 
  176     cc_count &= 0x1f;
  177     if ((len - 13) < cc_count * 3) {
  178         msg_Err(obj, "Invalid cc_count %d (> %zu)", cc_count * 3, len - 13);
  179         return NULL;
  180     }
  181 
  182     if (cdp[len - 4] != 0x74) /* footer id */ {
  183         msg_Err(obj, "Invalid footer id 0x%.2x", cdp[len-4]);
  184         return NULL;
  185     }
  186 
  187     uint16_t ftr = (cdp[len - 3] << 8) | cdp[len - 2];
  188     if (ftr != hdr) {
  189         msg_Err(obj, "Header 0x%.4x != Footer 0x%.4x", hdr, ftr);
  190         return NULL;
  191     }
  192 
  193     block_t *cc = block_Alloc(cc_count * 3);
  194 
  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];
  199     }
  200 
  201     return cc;
  202 }