/***************************************************************************** * ts_arib.c : TS demux ARIB specific handling ***************************************************************************** * Copyright (C) 2017 - VideoLAN Authors * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . *****************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include "ts_pid.h" #include "ts.h" #include "ts_arib.h" /* * ARIB TR-B21 * Logo PNG is 8 bit indexed dans the palette is missing, * provided as a CLUT. We need to reinject the CLUT as a * split palette + transparency (as PNG only allows split alpha table) */ /* ARIB TR-B14-1 Appendix 1 */ static const unsigned char CLUT_to_chunks[] = { /* size + PLTE */ 0x00, 0x00, 0x01, 0x80, 0x50, 0x4c, 0x54, 0x45, /* DATA ARIB TR-B14-1 Appendix 1 */ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, /* 0-7 */ 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, /* 8-15 */ 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x55, 0x00, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x55, 0xaa, /* 16-23 */ 0x00, 0x55, 0xff, 0x00, 0xaa, 0x55, 0x00, 0xaa, 0xff, 0x00, 0xff, 0x55, 0x00, 0xff, 0xaa, 0x55, 0x00, 0x00, 0x55, 0x00, 0x55, 0x55, 0x00, 0xaa, /* 24-31 */ 0x55, 0x00, 0xff, 0x55, 0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa, 0x55, 0x55, 0xff, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x55, /* 32-39 */ 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0xff, 0x55, 0xff, 0x00, 0x55, 0xff, 0x55, 0x55, 0xff, 0xff, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0xff, 0xaa, 0x55, 0x00, /* 40-47 */ 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0x55, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0x00, 0xaa, 0xff, 0x55, 0xaa, 0xff, 0xaa, /* 48-55 */ 0xaa, 0xff, 0xff, 0xff, 0x00, 0x55, 0xff, 0x00, 0xaa, 0xff, 0x55, 0x00, 0xff, 0x55, 0x55, 0xff, 0x55, 0xaa, 0xff, 0x55, 0xff, 0xff, 0xaa, 0x00, /* 56-63 */ 0xff, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0xff, 0xff, 0x55, 0xff, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, /* 64-71 */ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0x00, /* 72-79 */ 0x00, 0x00, 0xaa, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x00, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x55, 0xaa, /* 80-87 */ 0x00, 0x55, 0xff, 0x00, 0xaa, 0x55, 0x00, 0xaa, 0xff, 0x00, 0xff, 0x55, 0x00, 0xff, 0xaa, 0x55, 0x00, 0x00, 0x55, 0x00, 0x55, 0x55, 0x00, 0xaa, /* 88-95 */ 0x55, 0x00, 0xff, 0x55, 0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa, 0x55, 0x55, 0xff, 0x55, 0xaa, 0x00, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0xaa, /* 96-103 */ 0x55, 0xaa, 0xff, 0x55, 0xff, 0x00, 0x55, 0xff, 0x55, 0x55, 0xff, 0xaa, 0x55, 0xff, 0xff, 0xaa, 0x00, 0x55, 0xaa, 0x00, 0xff, 0xaa, 0x55, 0x00, /* 104-111 */ 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0x55, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0x00, 0xaa, 0xff, 0x55, 0xaa, 0xff, 0xaa, /* 112-119 */ 0xaa, 0xff, 0xff, 0xff, 0x00, 0x55, 0xff, 0x00, 0xaa, 0xff, 0x55, 0x00, 0xff, 0x55, 0x55, 0xff, 0x55, 0xaa, 0xff, 0x55, 0xff, 0xff, 0xaa, 0x00, /* 120-127 */ 0xff, 0xaa, 0x55, 0xff, 0xaa, 0xaa, 0xff, 0xaa, 0xff, 0xff, 0xff, 0x55, /* CRC32 (all data including type, without length and crc) . pngcheck output being the lazy way */ 0x4f, 0xed, 0xfc, 0x8d, /* Second Chunk */ /* size + tRNS */ 0x00, 0x00, 0x00, 0x80, 0x74, 0x52, 0x4e, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-63 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 64-127 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* CRC32 */ 0xfa, 0xe9, 0x51, 0x40, }; static const unsigned int CLUT_to_chunks_len = sizeof(CLUT_to_chunks); bool ts_arib_inject_png_palette( const uint8_t *p_in, size_t i_in, uint8_t **pp_out, size_t *pi_out ) { const uint8_t *p_data = p_in; const uint8_t *p_idat = NULL; size_t i_data = i_in - 8; p_data += 8; i_data -= 8; while( i_data > 11 ) { uint32_t i_len = GetDWBE( p_data ); if( i_len > 0x7FFFFFFFU || i_len > i_data - 12 ) break; uint32_t i_chunk = VLC_FOURCC(p_data[4], p_data[5], p_data[6], p_data[7]); if( i_chunk == VLC_FOURCC('I', 'D', 'A', 'T') ) { p_idat = p_data; break; } p_data += i_len + 12; i_data -= i_len + 12; } if( !p_idat ) return false; { uint8_t *p_out = *pp_out = malloc( i_in + CLUT_to_chunks_len ); if( !p_out ) return false; *pi_out = i_in + CLUT_to_chunks_len; const size_t i_head = p_data - p_in; memcpy( p_out, p_in, i_head ); memcpy( &p_out[i_head], CLUT_to_chunks, CLUT_to_chunks_len ); memcpy( &p_out[i_head + CLUT_to_chunks_len], p_data, i_in - i_head ); } return true; } void ts_arib_logo_dr_Delete( ts_arib_logo_dr_t *p_dr ) { free( p_dr->p_logo_char ); free( p_dr ); } ts_arib_logo_dr_t * ts_arib_logo_dr_Decode( const uint8_t *p_data, size_t i_data ) { if( i_data < 2 ) return NULL; ts_arib_logo_dr_t *p_dr = calloc( 1, sizeof(*p_dr) ); if( p_dr ) { p_dr->i_logo_version = p_data[0]; switch( p_data[0] ) { case 1: if( i_data == 7 ) { p_dr->i_logo_id = ((p_data[1] & 0x01) << 8) | p_data[2]; p_dr->i_logo_version = ((p_data[3] & 0x0F) << 8) | p_data[4]; p_dr->i_download_data_id = (p_data[5] << 8) | p_data[6]; return p_dr; } break; case 2: if( i_data == 3 ) { p_dr->i_logo_id = ((p_data[1] & 0x01) << 8) | p_data[2]; return p_dr; } break; case 3: if( i_data > 2 ) { p_dr->p_logo_char = malloc( i_data - 1 ); if( p_dr->p_logo_char ) { p_dr->i_logo_char = i_data - 1; memcpy( p_dr->p_logo_char, &p_data[1], p_dr->i_logo_char ); return p_dr; } } default: break; } ts_arib_logo_dr_Delete( p_dr ); } return NULL; }