cc.h
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:7k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * cc.h
  3.  *****************************************************************************
  4.  * Copyright (C) 2007 Laurent Aimar
  5.  * $Id: cb3740fd2a7f9958251fbef391dc22447005ef9f $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifndef _CC_H
  24. #define _CC_H 1
  25. #include <vlc_bits.h>
  26. /* CC have a maximum rate of 9600 bit/s (per field?) */
  27. #define CC_MAX_DATA_SIZE (2 * 3*600)
  28. typedef struct
  29. {
  30.     /* Which channel are present */
  31.     bool pb_present[4];
  32.     /* */
  33.     bool b_reorder;
  34.     /* CC data per field
  35.      *  byte[x+0]: field (0/1)
  36.      *  byte[x+1]: cc data 1
  37.      *  byte[x+2]: cc data 2
  38.      */
  39.     int     i_data;
  40.     uint8_t p_data[CC_MAX_DATA_SIZE];
  41. } cc_data_t;
  42. static inline void cc_Init( cc_data_t *c )
  43. {
  44.     int i;
  45.     for( i = 0; i < 4; i++ )
  46.         c-> pb_present[i] = false; 
  47.     c->i_data = 0;
  48.     c->b_reorder = false;
  49. }
  50. static inline void cc_Exit( cc_data_t *c )
  51. {
  52.     VLC_UNUSED(c);
  53.     return;
  54. }
  55. static inline void cc_Flush( cc_data_t *c )
  56. {
  57.     c->i_data = 0;
  58. }
  59. static inline void cc_AppendData( cc_data_t *c, int i_field, const uint8_t cc[2] )
  60. {
  61.     if( i_field == 0 || i_field == 1 )
  62.     {
  63.         c->pb_present[2*i_field+0] =
  64.         c->pb_present[2*i_field+1] = true;
  65.     }
  66.     c->p_data[c->i_data++] = i_field;
  67.     c->p_data[c->i_data++] = cc[0];
  68.     c->p_data[c->i_data++] = cc[1];
  69. }
  70. static inline void cc_Extract( cc_data_t *c, const uint8_t *p_src, int i_src )
  71. {
  72.     static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 };
  73.     static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 };
  74.     static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };
  75.     static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };
  76.     static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };
  77.     static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };
  78.     static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 };
  79.     static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };
  80.     //static const uint8_t p_afd_start[4] = { 0x44, 0x54, 0x47, 0x31 };
  81.     if( i_src < 4 )
  82.         return;
  83.     if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 )
  84.     {
  85.         /* Extract CC from DVB/ATSC TS */
  86.         /* cc_data()
  87.          *          u1 reserved(1)
  88.          *          u1 process_cc_data_flag
  89.          *          u1 additional_data_flag
  90.          *          u5 cc_count
  91.          *          u8 reserved(1111 1111)
  92.          *          for cc_count
  93.          *              u5 marker bit(1111 1)
  94.          *              u1 cc_valid
  95.          *              u2 cc_type
  96.          *              u8 cc_data_1
  97.          *              u8 cc_data_2
  98.          *          u8 marker bit(1111 1111)
  99.          *          if additional_data_flag
  100.          *              unknown
  101.          */
  102.         /* cc_type:
  103.          *  0x00: field 1
  104.          *  0x01: field 2
  105.          */
  106.         const uint8_t *cc = &p_src[5];
  107.         const int i_count_cc = cc[0]&0x1f;
  108.         int i;
  109.         if( !(cc[0]&0x40) ) // process flag
  110.             return;
  111.         if( i_src < 5 + 1+1 + i_count_cc*3 + 1)  // broken packet
  112.             return;
  113.         if( i_count_cc <= 0 )   // no cc present
  114.             return;
  115.         if( cc[2+i_count_cc * 3] != 0xff )  // marker absent
  116.             return;
  117.         cc += 2;
  118.         for( i = 0; i < i_count_cc; i++, cc += 3 )
  119.         {
  120.             int i_field = cc[0] & 0x03;
  121.             if( ( cc[0] & 0xfc ) != 0xfc )
  122.                 continue;
  123.             if( i_field != 0 && i_field != 1 )
  124.                 continue;
  125.             if( c->i_data + 3 > CC_MAX_DATA_SIZE )
  126.                 continue;
  127.             cc_AppendData( c, i_field, &cc[1] );
  128.         }
  129.         c->b_reorder = true;
  130.     }
  131.     else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 )
  132.     {
  133.         /* DVD CC */
  134.         const int b_truncate = p_src[4] & 0x01;
  135.         const int i_field_first = (p_src[4] & 0x80) ? 0 : 1;
  136.         const int i_count_cc2 = (p_src[4] >> 1) & 0xf;
  137.         const uint8_t *cc = &p_src[5];
  138.         int i;
  139.         if( i_src < 4+1+6*i_count_cc2 - ( b_truncate ? 3 : 0) )
  140.             return;
  141.         for( i = 0; i < i_count_cc2; i++ )
  142.         {
  143.             int j;
  144.             for( j = 0; j < 2; j++, cc += 3 )
  145.             {
  146.                 const int i_field = j == i_field_first ? 0 : 1;
  147.                 if( b_truncate && i == i_count_cc2 - 1 && j == 1 )
  148.                     break;
  149.                 if( cc[0] != 0xff && cc[0] != 0xfe )
  150.                     continue;
  151.                 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
  152.                     continue;
  153.                 cc_AppendData( c, i_field, &cc[1] );
  154.             }
  155.         }
  156.         c->b_reorder = false;
  157.     }
  158.     else if( i_src >= 2+2 + 2+2 &&
  159.              ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) ||
  160.                ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) )
  161.     {
  162.         /* ReplayTV CC */
  163.         const uint8_t *cc = &p_src[0];
  164.         int i;
  165.         if( c->i_data + 2*3 > CC_MAX_DATA_SIZE )
  166.             return;
  167.         for( i = 0; i < 2; i++, cc += 4 )
  168.         {
  169.             const int i_field = i == 0 ? 1 : 0;
  170.             cc_AppendData( c, i_field, &cc[2] );
  171.         }
  172.         c->b_reorder = false;
  173.     }
  174.     else if( ( !memcmp( p_cc_scte20, p_src, 2 ) ||
  175.                !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 )
  176.     {
  177.         /* SCTE-20 CC */
  178.         bs_t s;
  179.         bs_init( &s, &p_src[2], i_src - 2 );
  180.         const int i_cc_count = bs_read( &s, 5 );
  181.         for( int i = 0; i < i_cc_count; i++ )
  182.         {
  183.             bs_skip( &s, 2 );
  184.             const int i_field_idx = bs_read( &s, 2 );
  185.             bs_skip( &s, 5 );
  186.             uint8_t cc[2];
  187.             for( int j = 0; j < 2; j++ )
  188.             {
  189.                 cc[j] = 0;
  190.                 for( int k = 0; k < 8; k++ )
  191.                     cc[j] |= bs_read( &s, 1 ) << k;
  192.             }
  193.             bs_skip( &s, 1 );
  194.             if( i_field_idx != 1 && i_field_idx != 2 )
  195.                 continue;
  196.             if( c->i_data + 2*3 > CC_MAX_DATA_SIZE )
  197.                 continue;
  198.             const int i_field = i_field_idx - 1;
  199.             cc_AppendData( c, i_field, &cc[0] );
  200.         }
  201.         c->b_reorder = true;
  202.     }
  203.     else
  204.     {
  205. #if 0
  206. #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x )
  207.         fprintf( stderr, "-------------- unknown user data " );
  208.         for( int i = 0; i < i_src; i++ )
  209.             fprintf( stderr, "%2.2x ", p_src[i] );
  210.         for( int i = 0; i < i_src; i++ )
  211.             fprintf( stderr, "%c ", V(p_src[i]) );
  212.         fprintf( stderr, "n" );
  213. #undef V
  214. #endif
  215.         /* TODO DVD CC, ... */
  216.     }
  217. }
  218. #endif /* _CC_H */