/*****************************************************************************
* 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;
}