11/*
22 * Blackmagic DeckLink input
33 * Copyright (c) 2013-2014 Luca Barbato, Deti Fliegl
4+ * Copyright (c) 2014 Rafaël Carré
45 * Copyright (c) 2017 Akamai Technologies, Inc.
56 *
67 * This file is part of FFmpeg.
@@ -105,6 +106,42 @@ static int get_vanc_line_idx(BMDDisplayMode mode)
105106 return i - 1 ;
106107}
107108
109+ static inline uint16_t parity (uint16_t x)
110+ {
111+ uint16_t i;
112+ for (i = 4 * sizeof (x); i > 0 ; i /= 2 )
113+ x ^= x >> i;
114+ return x & 1 ;
115+ }
116+
117+ static inline void clear_parity_bits (uint16_t *buf, int len) {
118+ int i;
119+ for (i = 0 ; i < len; i++)
120+ buf[i] &= 0xff ;
121+ }
122+
123+ static int check_vanc_parity_checksum (uint16_t *buf, int len, uint16_t checksum) {
124+ int i;
125+ uint16_t vanc_sum = 0 ;
126+ for (i = 3 ; i < len - 1 ; i++) {
127+ uint16_t v = buf[i];
128+ int np = v >> 8 ;
129+ int p = parity (v & 0xff );
130+ if ((!!p ^ !!(v & 0x100 )) || (np != 1 && np != 2 )) {
131+ // Parity check failed
132+ return -1 ;
133+ }
134+ vanc_sum += v;
135+ }
136+ vanc_sum &= 0x1ff ;
137+ vanc_sum |= ((~vanc_sum & 0x100 ) << 1 );
138+ if (checksum != vanc_sum) {
139+ // Checksum verification failed
140+ return -1 ;
141+ }
142+ return 0 ;
143+ }
144+
108145/* The 10-bit VANC data is packed in V210, we only need the luma component. */
109146static void extract_luma_from_v210 (uint16_t *dst, const uint8_t *src, int width)
110147{
@@ -232,19 +269,148 @@ static uint8_t* teletext_data_unit_from_ancillary_packet(uint16_t *py, uint16_t
232269 return tgt;
233270}
234271
235- static uint8_t * teletext_data_unit_from_vanc_data (uint16_t *py, uint8_t *tgt, int64_t wanted_lines)
272+ uint8_t *vanc_to_cc (AVFormatContext *avctx, uint16_t *buf, size_t words,
273+ unsigned &cc_count)
236274{
237- uint16_t *pend = py + 1920 ;
275+ size_t i, len = (buf[5 ] & 0xff ) + 6 + 1 ;
276+ uint8_t cdp_sum, rate;
277+ uint16_t hdr, ftr;
278+ uint8_t *cc;
279+ uint16_t *cdp = &buf[6 ]; // CDP follows
280+ if (cdp[0 ] != 0x96 || cdp[1 ] != 0x69 ) {
281+ av_log (avctx, AV_LOG_WARNING, " Invalid CDP header 0x%.2x 0x%.2x\n " , cdp[0 ], cdp[1 ]);
282+ return NULL ;
283+ }
238284
239- while (py < pend - 6 ) {
240- if (py[0 ] == 0 && py[1 ] == 0x3ff && py[2 ] == 0x3ff ) { // ancillary data flag
241- py += 3 ;
242- tgt = teletext_data_unit_from_ancillary_packet (py, pend, tgt, wanted_lines, 0 );
243- py += py[2 ] & 255 ;
285+ len -= 7 ; // remove VANC header and checksum
286+
287+ if (cdp[2 ] != len) {
288+ av_log (avctx, AV_LOG_WARNING, " CDP len %d != %zu\n " , cdp[2 ], len);
289+ return NULL ;
290+ }
291+
292+ cdp_sum = 0 ;
293+ for (i = 0 ; i < len - 1 ; i++)
294+ cdp_sum += cdp[i];
295+ cdp_sum = cdp_sum ? 256 - cdp_sum : 0 ;
296+ if (cdp[len - 1 ] != cdp_sum) {
297+ av_log (avctx, AV_LOG_WARNING, " CDP checksum invalid 0x%.4x != 0x%.4x\n " , cdp_sum, cdp[len-1 ]);
298+ return NULL ;
299+ }
300+
301+ rate = cdp[3 ];
302+ if (!(rate & 0x0f )) {
303+ av_log (avctx, AV_LOG_WARNING, " CDP frame rate invalid (0x%.2x)\n " , rate);
304+ return NULL ;
305+ }
306+ rate >>= 4 ;
307+ if (rate > 8 ) {
308+ av_log (avctx, AV_LOG_WARNING, " CDP frame rate invalid (0x%.2x)\n " , rate);
309+ return NULL ;
310+ }
311+
312+ if (!(cdp[4 ] & 0x43 )) /* ccdata_present | caption_service_active | reserved */ {
313+ av_log (avctx, AV_LOG_WARNING, " CDP flags invalid (0x%.2x)\n " , cdp[4 ]);
314+ return NULL ;
315+ }
316+
317+ hdr = (cdp[5 ] << 8 ) | cdp[6 ];
318+ if (cdp[7 ] != 0x72 ) /* ccdata_id */ {
319+ av_log (avctx, AV_LOG_WARNING, " Invalid ccdata_id 0x%.2x\n " , cdp[7 ]);
320+ return NULL ;
321+ }
322+
323+ cc_count = cdp[8 ];
324+ if (!(cc_count & 0xe0 )) {
325+ av_log (avctx, AV_LOG_WARNING, " Invalid cc_count 0x%.2x\n " , cc_count);
326+ return NULL ;
327+ }
328+
329+ cc_count &= 0x1f ;
330+ if ((len - 13 ) < cc_count * 3 ) {
331+ av_log (avctx, AV_LOG_WARNING, " Invalid cc_count %d (> %zu)\n " , cc_count * 3 , len - 13 );
332+ return NULL ;
333+ }
334+
335+ if (cdp[len - 4 ] != 0x74 ) /* footer id */ {
336+ av_log (avctx, AV_LOG_WARNING, " Invalid footer id 0x%.2x\n " , cdp[len-4 ]);
337+ return NULL ;
338+ }
339+
340+ ftr = (cdp[len - 3 ] << 8 ) | cdp[len - 2 ];
341+ if (ftr != hdr) {
342+ av_log (avctx, AV_LOG_WARNING, " Header 0x%.4x != Footer 0x%.4x\n " , hdr, ftr);
343+ return NULL ;
344+ }
345+
346+ cc = (uint8_t *)av_malloc (cc_count * 3 );
347+ if (cc == NULL ) {
348+ av_log (avctx, AV_LOG_WARNING, " CC - av_malloc failed for cc_count = %d\n " , cc_count);
349+ return NULL ;
350+ }
351+
352+ for (size_t i = 0 ; i < cc_count; i++) {
353+ cc[3 *i + 0 ] = cdp[9 + 3 *i+0 ] /* & 3 */ ;
354+ cc[3 *i + 1 ] = cdp[9 + 3 *i+1 ];
355+ cc[3 *i + 2 ] = cdp[9 + 3 *i+2 ];
356+ }
357+
358+ cc_count *= 3 ;
359+ return cc;
360+ }
361+
362+ uint8_t *get_metadata (AVFormatContext *avctx, uint16_t *buf, size_t width,
363+ uint8_t *tgt, size_t tgt_size, AVPacket *pkt)
364+ {
365+ decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data ;
366+ uint16_t *max_buf = buf + width;
367+
368+ while (buf < max_buf - 6 ) {
369+ int len;
370+ uint16_t did = buf[3 ] & 0xFF ; // data id
371+ uint16_t sdid = buf[4 ] & 0xFF ; // secondary data id
372+ /* Check for VANC header */
373+ if (buf[0 ] != 0 || buf[1 ] != 0x3ff || buf[2 ] != 0x3ff ) {
374+ return tgt;
375+ }
376+
377+ len = (buf[5 ] & 0xff ) + 6 + 1 ;
378+ if (len > max_buf - buf) {
379+ av_log (avctx, AV_LOG_WARNING, " Data Count (%d) > data left (%zu)\n " ,
380+ len, max_buf - buf);
381+ return tgt;
382+ }
383+
384+ if (did == 0x43 && (sdid == 0x02 || sdid == 0x03 ) && cctx->teletext_lines &&
385+ width == 1920 && tgt_size >= 1920 ) {
386+ if (check_vanc_parity_checksum (buf, len, buf[len - 1 ]) < 0 ) {
387+ av_log (avctx, AV_LOG_WARNING, " VANC parity or checksum incorrect\n " );
388+ goto skip_packet;
389+ }
390+ tgt = teletext_data_unit_from_ancillary_packet (buf + 3 , buf + len, tgt, cctx->teletext_lines , 0 );
391+ } else if (did == 0x61 && sdid == 0x01 ) {
392+ unsigned int data_len;
393+ uint8_t *data;
394+ if (check_vanc_parity_checksum (buf, len, buf[len - 1 ]) < 0 ) {
395+ av_log (avctx, AV_LOG_WARNING, " VANC parity or checksum incorrect\n " );
396+ goto skip_packet;
397+ }
398+ clear_parity_bits (buf, len);
399+ data = vanc_to_cc (avctx, buf, width, data_len);
400+ if (data) {
401+ uint8_t *pkt_cc = av_packet_new_side_data (pkt, AV_PKT_DATA_A53_CC, data_len);
402+ if (pkt_cc)
403+ memcpy (pkt_cc, data, data_len);
404+ av_free (data);
405+ }
244406 } else {
245- py++;
407+ av_log (avctx, AV_LOG_DEBUG, " Unknown meta data DID = 0x%.2x SDID = 0x%.2x\n " ,
408+ did, sdid);
246409 }
410+ skip_packet:
411+ buf += len;
247412 }
413+
248414 return tgt;
249415}
250416
@@ -536,7 +702,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
536702 videoFrame->GetHeight ();
537703 // fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts);
538704
539- if (!no_video && ctx-> teletext_lines ) {
705+ if (!no_video) {
540706 IDeckLinkVideoFrameAncillary *vanc;
541707 AVPacket txt_pkt;
542708 uint8_t txt_buf0[3531 ]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer
@@ -549,7 +715,8 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
549715 txt_buf[0 ] = 0x10 ; // data_identifier - EBU_data
550716 txt_buf++;
551717#if CONFIG_LIBZVBI
552- if (ctx->bmd_mode == bmdModePAL && (vanc_format == bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) {
718+ if (ctx->bmd_mode == bmdModePAL && ctx->teletext_lines &&
719+ (vanc_format == bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) {
553720 av_assert0 (videoFrame->GetWidth () == 720 );
554721 for (i = 6 ; i < 336 ; i++, line_mask <<= 1 ) {
555722 uint8_t *buf;
@@ -571,13 +738,8 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
571738 if (vanc->GetBufferForVerticalBlankingLine (i, (void **)&buf) == S_OK) {
572739 uint16_t luma_vanc[MAX_WIDTH_VANC];
573740 extract_luma_from_v210 (luma_vanc, buf, videoFrame->GetWidth ());
574- if (videoFrame->GetWidth () == 1920 ) {
575- txt_buf = teletext_data_unit_from_vanc_data (luma_vanc, txt_buf, ctx->teletext_lines );
576- if (txt_buf - txt_buf0 > 1611 ) { // ensure we still have at least 1920 bytes free in the buffer
577- av_log (avctx, AV_LOG_ERROR, " Too many OP47 teletext packets.\n " );
578- break ;
579- }
580- }
741+ txt_buf = get_metadata (avctx, luma_vanc, videoFrame->GetWidth (),
742+ txt_buf, sizeof (txt_buf0) - (txt_buf - txt_buf0), &pkt);
581743 }
582744 if (i == vanc_line_numbers[idx].field0_vanc_end )
583745 i = vanc_line_numbers[idx].field1_vanc_start - 1 ;
0 commit comments