diff options
Diffstat (limited to 'lib/libucsi/atsc')
36 files changed, 5500 insertions, 0 deletions
| diff --git a/lib/libucsi/atsc/Makefile b/lib/libucsi/atsc/Makefile new file mode 100644 index 0000000..c3d8e6b --- /dev/null +++ b/lib/libucsi/atsc/Makefile @@ -0,0 +1,55 @@ +# Makefile for linuxtv.org dvb-apps/lib/libucsi/atsc + +.PHONY: sub-error-atsc + +sub-error-atsc: +	$(error You can't use this makefile directly.) + +ifneq ($(lib_name),) + +objects += atsc/atsc_text.o      \ +           atsc/cvct_section.o   \ +           atsc/dccsct_section.o \ +           atsc/dcct_section.o   \ +           atsc/eit_section.o    \ +           atsc/ett_section.o    \ +           atsc/mgt_section.o    \ +           atsc/rrt_section.o    \ +           atsc/stt_section.o    \ +           atsc/tvct_section.o   \ +           atsc/types.o + +sub-install += atsc + +else + +includes = ac3_descriptor.h                   \ +           caption_service_descriptor.h       \ +           component_name_descriptor.h        \ +           content_advisory_descriptor.h      \ +           cvct_section.h                     \ +           dcc_arriving_request_descriptor.h  \ +           dcc_departing_request_descriptor.h \ +           dccsct_section.h                   \ +           dcct_section.h                     \ +           descriptor.h                       \ +           eit_section.h                      \ +           ett_section.h                      \ +           extended_channel_name_descriptor.h \ +           genre_descriptor.h                 \ +           mgt_section.h                      \ +           rc_descriptor.h                    \ +           rrt_section.h                      \ +           section.h                          \ +           service_location_descriptor.h      \ +           stt_section.h                      \ +           stuffing_descriptor.h              \ +           time_shifted_service_descriptor.h  \ +           tvct_section.h                     \ +           types.h + +include ../../../Make.rules + +lib_name = libucsi/atsc + +endif diff --git a/lib/libucsi/atsc/ac3_descriptor.h b/lib/libucsi/atsc/ac3_descriptor.h new file mode 100644 index 0000000..489695b --- /dev/null +++ b/lib/libucsi/atsc/ac3_descriptor.h @@ -0,0 +1,112 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_atsc@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_AC3_DESCRIPTOR +#define _UCSI_ATSC_AC3_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +enum atsc_ac3_channels { +	ATSC_AC3_CHANNELS_1_PLUS_1	= 0x0, +	ATSC_AC3_CHANNELS_1_0		= 0x1, +	ATSC_AC3_CHANNELS_2_0		= 0x2, +	ATSC_AC3_CHANNELS_3_0		= 0x3, +	ATSC_AC3_CHANNELS_2_1		= 0x4, +	ATSC_AC3_CHANNELS_3_1 		= 0x5, +	ATSC_AC3_CHANNELS_2_2		= 0x6, +	ATSC_AC3_CHANNELS_3_2		= 0x7, +	ATSC_AC3_CHANNELS_1		= 0x8, +	ATSC_AC3_CHANNELS_LTEQ_2	= 0x9, +	ATSC_AC3_CHANNELS_LTEQ_3	= 0xa, +	ATSC_AC3_CHANNELS_LTEQ_4	= 0xb, +	ATSC_AC3_CHANNELS_LTEQ_5	= 0xc, +	ATSC_AC3_CHANNELS_LTEQ_6	= 0xd, +}; + +/** + * atsc_ac3_descriptor structure. + */ +struct atsc_ac3_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t sample_rate_code        : 3; , +	uint8_t bsid			: 5; ); +  EBIT2(uint8_t bit_rate_code	        : 6; , +	uint8_t surround_mode		: 2; ); +  EBIT3(uint8_t bsmod		        : 3; , +	uint8_t num_channels		: 4; , +	uint8_t full_svc		: 1; ); +	/* uint8_t additional_info[] */ +} __ucsi_packed; + +/** + * Process an atsc_ac3_descriptor. + * + * @param d Generic descriptor structure. + * @return atsc_ac3_descriptor pointer, or NULL on error. + */ +static inline struct atsc_ac3_descriptor* +	atsc_ac3_descriptor_codec(struct descriptor* d) +{ +	int pos = 0; + +	if (d->len < (pos+4)) +		return NULL; +	pos += 4; + +	return (struct atsc_ac3_descriptor*) d; +} + +/** + * Retrieve pointer to additional_info field of a atsc_ac3_descriptor. + * + * @param d atsc_ac3_descriptor pointer. + * @return Pointer to additional_info field. + */ +static inline uint8_t *atsc_ac3_descriptor_additional_info(struct atsc_ac3_descriptor *d) +{ +	int pos = sizeof(struct atsc_ac3_descriptor); + +	return ((uint8_t *) d) + pos; +} + +/** + * Determine length of additional_info field of a atsc_ac3_descriptor. + * + * @param d atsc_ac3_descriptor pointer. + * @return Length of field in bytes. + */ +static inline int atsc_ac3_descriptor_additional_info_length(struct atsc_ac3_descriptor* d) +{ +	return d->d.len - 3; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/atsc_text.c b/lib/libucsi/atsc/atsc_text.c new file mode 100644 index 0000000..d79c83f --- /dev/null +++ b/lib/libucsi/atsc/atsc_text.c @@ -0,0 +1,743 @@ +/* +* section and descriptor parser +* +* Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) +* +* This library 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 library 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 Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA +*/ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "libucsi/endianops.h" +#include "libucsi/atsc/types.h" + +#define HUFFTREE_LITERAL_MASK 0x80 +#define HUFFSTRING_END 0x00 +#define HUFFSTRING_ESCAPE 0x1b + +#define DEST_ALLOC_DELTA 20 + +struct hufftree_entry { +	uint8_t left_idx; +	uint8_t right_idx; +} __ucsi_packed; + +struct huffbuff { +	uint8_t *buf; +	uint32_t buf_len; + +	uint32_t cur_byte; +	uint8_t cur_bit; +}; + + +static struct hufftree_entry program_description_hufftree[][128] = { +	{ {0x14, 0x15}, {0x9b, 0xd6}, {0xc9, 0xcf}, {0xd7, 0xc7}, {0x01, 0xa2}, +	{0xce, 0xcb}, {0x02, 0x03}, {0xc5, 0xcc}, {0xc6, 0xc8}, {0x04, 0xc4}, +	{0x05, 0xc2}, {0x06, 0xc3}, {0xd2, 0x07}, {0xd3, 0x08}, {0xca, 0xd4}, +	{0x09, 0xcd}, {0xd0, 0x0a}, {0xc1, 0x0b}, {0x0c, 0x0d}, {0x0e, 0x0f}, +	{0x10, 0x11}, {0x12, 0x13}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x38, 0x39}, {0xad, 0xaf}, {0xb7, 0xda}, {0xa8, 0xb3}, {0xb5, 0x01}, +	{0x02, 0x9b}, {0xb4, 0xf1}, {0xa2, 0xd5}, {0xd6, 0xd9}, {0x03, 0x04}, +	{0x05, 0xcf}, {0x06, 0xc9}, {0xf9, 0xea}, {0xeb, 0xf5}, {0xf6, 0x07}, +	{0x08, 0x09}, {0xb2, 0xc5}, {0xc6, 0xb1}, {0x0a, 0xee}, {0xcb, 0x0b}, +	{0xd4, 0x0c}, {0xc4, 0xc8}, {0xd2, 0x0d}, {0x0e, 0x0f}, {0xc7, 0xca}, +	{0xce, 0xd0}, {0xd7, 0x10}, {0xc2, 0x11}, {0xcc, 0xec}, {0xe5, 0xe7}, +	{0x12, 0xcd}, {0x13, 0x14}, {0xc3, 0x15}, {0x16, 0x17}, {0xed, 0x18}, +	{0x19, 0xf2}, {0x1a, 0xd3}, {0x1b, 0x1c}, {0xe4, 0x1d}, {0xc1, 0xe3}, +	{0x1e, 0xe9}, {0xf0, 0xe2}, {0xf7, 0x1f}, {0xf3, 0xe6}, {0x20, 0x21}, +	{0x22, 0xe8}, {0xef, 0x23}, {0x24, 0x25}, {0x26, 0x27}, {0x28, 0x29}, +	{0x2a, 0xf4}, {0x2b, 0x2c}, {0x2d, 0x2e}, {0x2f, 0xe1}, {0x30, 0x31}, +	{0x32, 0x33}, {0x34, 0x35}, {0x36, 0x37}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x03, 0x04}, {0x80, 0xae}, {0xc8, 0xd4}, {0x01, 0x02}, {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0xf3}, {0xa0, 0xf4}, {0x9b, 0x01}, }, +	{ {0x9b, 0x9b}, }, +	{ {0xac, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x01, 0xa0}, {0x9b, 0xa2}, }, +	{ {0x07, 0x08}, {0xe2, 0xe4}, {0xe5, 0xe6}, {0xa0, 0xf2}, {0xe1, 0x01}, +	{0x02, 0xf3}, {0xe3, 0x03}, {0x04, 0x05}, {0x9b, 0x06}, }, +	{ {0x04, 0x80}, {0xca, 0xd3}, {0xa2, 0x01}, {0x9b, 0x02}, {0x03, 0xa0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x03, 0x04}, {0x9b, 0xb7}, {0xf4, 0xa0}, {0xb0, 0xf3}, {0x01, 0x02}, }, +	{ {0xb9, 0x02}, {0xb8, 0x9b}, {0xa0, 0x01}, }, +	{ {0xae, 0x02}, {0xb6, 0x9b}, {0x01, 0xa0}, }, +	{ {0xa0, 0x01}, {0x9b, 0xb0}, }, +	{ {0xae, 0x01}, {0x9b, 0xa0}, }, +	{ {0xae, 0x01}, {0xa0, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x01}, {0xac, 0xae}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0x03}, {0x9b, 0xa0}, {0xb5, 0xb6}, {0xb8, 0x01}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x08, 0x09}, {0xe6, 0xf5}, {0xf3, 0xf4}, {0x9b, 0xe4}, {0x01, 0xed}, +	{0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x06}, {0xec, 0xee}, {0x07, 0xa0}, }, +	{ {0x05, 0x06}, {0x9b, 0xec}, {0xf5, 0x01}, {0x02, 0xe1}, {0xef, 0xe5}, +	{0xe9, 0xf2}, {0x03, 0x04}, }, +	{ {0x06, 0x07}, {0x9b, 0xe9}, {0xf9, 0xf2}, {0xf5, 0x01}, {0x02, 0x03}, +	{0xec, 0xef}, {0xe1, 0x04}, {0xe8, 0x05}, }, +	{ {0x05, 0x06}, {0xf9, 0xf2}, {0xf5, 0x9b}, {0xe5, 0xef}, {0x01, 0x02}, +	{0xe9, 0xe1}, {0x03, 0x04}, }, +	{ {0x06, 0x07}, {0xe1, 0xe9}, {0xee, 0xf6}, {0xe4, 0xec}, {0xf3, 0x01}, +	{0x02, 0xf2}, {0x03, 0x04}, {0x9b, 0x05}, }, +	{ {0x02, 0x03}, {0xe5, 0xec}, {0x9b, 0xef}, {0x01, 0xf2}, }, +	{ {0x05, 0x06}, {0xf5, 0xef}, {0x9b, 0xec}, {0xe9, 0x01}, {0xe1, 0xf2}, +	{0x02, 0xe5}, {0x03, 0x04}, }, +	{ {0x03, 0x04}, {0x9b, 0xe5}, {0xe9, 0xf5}, {0xe1, 0x01}, {0xef, 0x02}, }, +	{ {0x04, 0x05}, {0xa0, 0xc9}, {0xf3, 0x9b}, {0xae, 0xf2}, {0x01, 0x02}, +	{0x03, 0xee}, }, +	{ {0xef, 0x05}, {0x9b, 0xae}, {0xe9, 0xe5}, {0x01, 0xf5}, {0x02, 0xe1}, +	{0x03, 0x04}, }, +	{ {0xe5, 0x03}, {0xe1, 0xe9}, {0xf2, 0x9b}, {0x01, 0x02}, }, +	{ {0x03, 0x04}, {0x9b, 0xe9}, {0xf5, 0x01}, {0xe5, 0x02}, {0xef, 0xe1}, }, +	{ {0xe1, 0x05}, {0x9b, 0xe3}, {0xef, 0x01}, {0xf5, 0xe5}, {0x02, 0x03}, +	{0xe9, 0x04}, }, +	{ {0xe5, 0x03}, {0x9b, 0xe9}, {0x01, 0xe1}, {0xef, 0x02}, }, +	{ {0x03, 0x04}, {0xa7, 0xee}, {0xec, 0xf2}, {0xf3, 0x01}, {0x9b, 0x02}, }, +	{ {0xe1, 0x06}, {0x9b, 0xe8}, {0xe9, 0x01}, {0xf2, 0xec}, {0x02, 0xef}, +	{0x03, 0xe5}, {0x04, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x03, 0x04}, {0x9b, 0xae}, {0x01, 0xe9}, {0x02, 0xe1}, {0xe5, 0xef}, }, +	{ {0x09, 0x0a}, {0xf6, 0xf9}, {0x01, 0xae}, {0xe3, 0xe9}, {0xf5, 0x9b}, +	{0xe5, 0xef}, {0x02, 0x03}, {0xe1, 0x04}, {0xe8, 0x05}, {0x06, 0xf4}, +	{0x07, 0x08}, }, +	{ {0xe8, 0x07}, {0xe5, 0xf7}, {0xd6, 0xe1}, {0x9b, 0xe9}, {0xf2, 0x01}, +	{0x02, 0x03}, {0x04, 0xef}, {0x05, 0x06}, }, +	{ {0xae, 0x01}, {0x9b, 0xee}, }, +	{ {0xe9, 0x02}, {0xe5, 0x9b}, {0xa0, 0x01}, }, +	{ {0x03, 0x04}, {0x9b, 0xe8}, {0xe5, 0xe1}, {0xef, 0x01}, {0xe9, 0x02}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xef}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x18, 0x19}, {0xe8, 0xef}, {0xf8, 0x9b}, {0xa7, 0xf7}, {0xfa, 0x01}, +	{0x02, 0x03}, {0x04, 0xe5}, {0xae, 0x05}, {0xe6, 0xe2}, {0x06, 0xf6}, +	{0xeb, 0xf5}, {0xe9, 0x07}, {0xf0, 0xf9}, {0xe7, 0x08}, {0x09, 0xe4}, +	{0x0a, 0xe3}, {0x0b, 0xed}, {0x0c, 0xf3}, {0x0d, 0x0e}, {0x0f, 0xec}, +	{0x10, 0xf4}, {0x11, 0x12}, {0xf2, 0xa0}, {0x13, 0x14}, {0x15, 0xee}, +	{0x16, 0x17}, }, +	{ {0x0b, 0x0c}, {0xe4, 0xf3}, {0x9b, 0xae}, {0xe2, 0x01}, {0x02, 0x03}, +	{0xec, 0xa0}, {0x04, 0xe9}, {0xf2, 0xf5}, {0x05, 0xf9}, {0xe1, 0x06}, +	{0xef, 0x07}, {0xe5, 0x08}, {0x09, 0x0a}, }, +	{ {0x0f, 0x10}, {0xf1, 0xae}, {0xc4, 0xf9}, {0xac, 0x01}, {0xe3, 0x02}, +	{0x9b, 0xf2}, {0x03, 0x04}, {0xa0, 0xec}, {0xf5, 0x05}, {0x06, 0xe9}, +	{0x07, 0xeb}, {0x08, 0xf4}, {0x09, 0xe5}, {0x0a, 0xef}, {0xe1, 0xe8}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, }, +	{ {0x13, 0x14}, {0xa7, 0xbb}, {0xe6, 0xed}, {0xf7, 0xe7}, {0xf6, 0x01}, +	{0x02, 0x9b}, {0xee, 0x03}, {0x04, 0xec}, {0x05, 0xf5}, {0x06, 0xac}, +	{0xe4, 0xf9}, {0xf2, 0x07}, {0x08, 0x09}, {0xae, 0x0a}, {0xef, 0x0b}, +	{0xe1, 0xf3}, {0x0c, 0xe9}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xe5, 0x11}, +	{0x12, 0xa0}, }, +	{ {0x1d, 0x1e}, {0xa9, 0xe8}, {0xf5, 0x9b}, {0x01, 0xad}, {0xbb, 0xeb}, +	{0xfa, 0x02}, {0xa7, 0xe6}, {0xe2, 0xe7}, {0x03, 0x04}, {0x05, 0x06}, +	{0xe9, 0xf8}, {0x07, 0xac}, {0xef, 0xf0}, {0x08, 0xed}, {0xf6, 0xf9}, +	{0x09, 0xf7}, {0x0a, 0x0b}, {0xae, 0x0c}, {0xe3, 0x0d}, {0xe5, 0xf4}, +	{0x0e, 0x0f}, {0xe4, 0x10}, {0xec, 0x11}, {0xe1, 0x12}, {0x13, 0x14}, +	{0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x18}, {0xf2, 0xa0}, {0x19, 0x1a}, +	{0x1b, 0x1c}, }, +	{ {0x09, 0x0a}, {0xae, 0x9b}, {0xec, 0x01}, {0xf5, 0x02}, {0xf4, 0xe6}, +	{0x03, 0xe1}, {0xe5, 0xe9}, {0x04, 0xf2}, {0xef, 0x05}, {0x06, 0x07}, +	{0xa0, 0x08}, }, +	{ {0x0e, 0x0f}, {0xad, 0xe7}, {0x9b, 0xa7}, {0xf9, 0x01}, {0xec, 0x02}, +	{0xac, 0xf2}, {0x03, 0xae}, {0xf3, 0xf5}, {0x04, 0x05}, {0xef, 0x06}, +	{0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0x0b}, {0xe5, 0x0c}, +	{0xa0, 0x0d}, }, +	{ {0x0d, 0x0e}, {0xa7, 0xac}, {0xf3, 0xad}, {0x01, 0x02}, {0x9b, 0xf9}, +	{0xf5, 0xae}, {0x03, 0xee}, {0x04, 0xf2}, {0x05, 0x06}, {0xf4, 0x07}, +	{0x08, 0x09}, {0xef, 0xe1}, {0xa0, 0x0a}, {0xe9, 0x0b}, {0x0c, 0xe5}, }, +	{ {0x14, 0x15}, {0xac, 0xe2}, {0xf8, 0x9b}, {0xae, 0xfa}, {0x01, 0xeb}, +	{0x02, 0xa0}, {0x03, 0x04}, {0xf0, 0x05}, {0x06, 0xe6}, {0xf6, 0x07}, +	{0xe4, 0xed}, {0xe7, 0x08}, {0xe1, 0xef}, {0xf2, 0x09}, {0x0a, 0x0b}, +	{0xec, 0x0c}, {0xe5, 0xe3}, {0x0d, 0xf4}, {0x0e, 0xf3}, {0x0f, 0x10}, +	{0x11, 0xee}, {0x12, 0x13}, }, +	{ {0x03, 0xef}, {0x9b, 0xe1}, {0xe5, 0xf5}, {0x01, 0x02}, }, +	{ {0x08, 0x09}, {0xec, 0xf9}, {0xa7, 0xee}, {0x01, 0xac}, {0x9b, 0xae}, +	{0x02, 0x03}, {0x04, 0xf3}, {0x05, 0xe9}, {0x06, 0xa0}, {0x07, 0xe5}, }, +	{ {0x16, 0x17}, {0xa7, 0xad}, {0xee, 0xe3}, {0xeb, 0xf2}, {0x9b, 0xe2}, +	{0x01, 0x02}, {0xf5, 0x03}, {0xf4, 0xac}, {0x04, 0x05}, {0xe6, 0xed}, +	{0xf6, 0x06}, {0xae, 0xf0}, {0x07, 0x08}, {0xf3, 0x09}, {0x0a, 0xe4}, +	{0x0b, 0x0c}, {0xf9, 0x0d}, {0xef, 0x0e}, {0xe1, 0x0f}, {0x10, 0xe9}, +	{0xec, 0x11}, {0xa0, 0xe5}, {0x12, 0x13}, {0x14, 0x15}, }, +	{ {0x0c, 0x0d}, {0xa7, 0xbb}, {0x9b, 0x01}, {0xf9, 0xae}, {0xe2, 0x02}, +	{0xed, 0xf3}, {0x03, 0xf5}, {0xef, 0xf0}, {0x04, 0x05}, {0xe9, 0x06}, +	{0x07, 0x08}, {0x09, 0xa0}, {0xe1, 0xe5}, {0x0a, 0x0b}, }, +	{ {0x19, 0x1a}, {0xad, 0xbb}, {0xe2, 0xea}, {0xed, 0xf2}, {0xfa, 0xe6}, +	{0xec, 0x01}, {0x02, 0x03}, {0x9b, 0xf5}, {0x04, 0xa7}, {0xf6, 0xf9}, +	{0x05, 0x06}, {0xeb, 0xef}, {0x07, 0x08}, {0x09, 0x0a}, {0xac, 0x0b}, +	{0x0c, 0xe3}, {0xae, 0x0d}, {0xee, 0xe9}, {0x0e, 0xe1}, {0x0f, 0xf3}, +	{0x10, 0x11}, {0xf4, 0x12}, {0xe7, 0xe5}, {0x13, 0x14}, {0xe4, 0x15}, +	{0x16, 0x17}, {0xa0, 0x18}, }, +	{ {0x1a, 0x1b}, {0xc2, 0x9b}, {0xad, 0xac}, {0xf8, 0x01}, {0xae, 0x02}, +	{0x03, 0xe5}, {0xe7, 0xe8}, {0xf9, 0xe9}, {0xeb, 0x04}, {0xe3, 0xe1}, +	{0x05, 0xf6}, {0x06, 0xe4}, {0x07, 0xe2}, {0xf0, 0x08}, {0x09, 0xf3}, +	{0xf4, 0xf7}, {0xef, 0x0a}, {0x0b, 0x0c}, {0x0d, 0xec}, {0x0e, 0x0f}, +	{0x10, 0xf5}, {0xed, 0x11}, {0xe6, 0xa0}, {0x12, 0xf2}, {0x13, 0x14}, +	{0x15, 0xee}, {0x16, 0x17}, {0x18, 0x19}, }, +	{ {0x0e, 0x0f}, {0xad, 0xed}, {0xf9, 0x9b}, {0xae, 0x01}, {0xf3, 0x02}, +	{0x03, 0xf5}, {0xf4, 0xf0}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0xe8}, +	{0xa0, 0xe1}, {0xec, 0x07}, {0xf2, 0x08}, {0xe5, 0x09}, {0x0a, 0x0b}, +	{0x0c, 0x0d}, }, +	{ {0x9b, 0xf5}, }, +	{ {0x19, 0x1a}, {0xa9, 0xbb}, {0xf6, 0xe6}, {0x01, 0x9b}, {0xad, 0xe2}, +	{0xf0, 0x02}, {0xa7, 0x03}, {0x04, 0x05}, {0xf5, 0xe3}, {0xac, 0xe7}, +	{0xf2, 0x06}, {0xeb, 0x07}, {0xec, 0xed}, {0xee, 0xf9}, {0x08, 0xae}, +	{0x09, 0x0a}, {0xe4, 0x0b}, {0x0c, 0xf4}, {0x0d, 0xf3}, {0x0e, 0x0f}, +	{0x10, 0xe1}, {0xef, 0x11}, {0xe9, 0x12}, {0x13, 0xe5}, {0x14, 0xa0}, +	{0x15, 0x16}, {0x17, 0x18}, }, +	{ {0xa0, 0x16}, {0xa2, 0xa7}, {0xe2, 0xeb}, {0xed, 0xee}, {0x9b, 0xf7}, +	{0x01, 0x02}, {0x03, 0xbb}, {0xf9, 0xf0}, {0x04, 0x05}, {0xec, 0x06}, +	{0x07, 0x08}, {0xf5, 0xe1}, {0x09, 0xac}, {0xe3, 0x0a}, {0xe8, 0x0b}, +	{0xe9, 0x0c}, {0xef, 0xf3}, {0xae, 0x0d}, {0x0e, 0xe5}, {0x0f, 0x10}, +	{0x11, 0xf4}, {0x12, 0x13}, {0x14, 0x15}, }, +	{ {0x14, 0x15}, {0xbb, 0xe2}, {0xad, 0xed}, {0x01, 0x9b}, {0xa7, 0xe3}, +	{0xac, 0xec}, {0xee, 0x02}, {0xf7, 0x03}, {0x04, 0xf9}, {0x05, 0x06}, +	{0x07, 0x08}, {0xf4, 0xae}, {0xf5, 0x09}, {0x0a, 0xf2}, {0xe1, 0xf3}, +	{0x0b, 0x0c}, {0x0d, 0xe9}, {0x0e, 0x0f}, {0xef, 0xe5}, {0x10, 0xa0}, +	{0xe8, 0x11}, {0x12, 0x13}, }, +	{ {0x11, 0x12}, {0xef, 0xf6}, {0x9b, 0xeb}, {0xf9, 0x01}, {0xa0, 0xe2}, +	{0x02, 0xe1}, {0x03, 0xed}, {0x04, 0xe3}, {0xe9, 0x05}, {0xe4, 0xe5}, +	{0xe7, 0x06}, {0xec, 0xf0}, {0x07, 0x08}, {0x09, 0x0a}, {0x0b, 0xf3}, +	{0x0c, 0xf4}, {0xee, 0x0d}, {0xf2, 0x0e}, {0x0f, 0x10}, }, +	{ {0x05, 0xe5}, {0xf3, 0xf9}, {0x9b, 0x01}, {0xef, 0x02}, {0x03, 0xe1}, +	{0x04, 0xe9}, }, +	{ {0x0a, 0x0b}, {0xae, 0x9b}, {0xec, 0xed}, {0x01, 0x02}, {0xf3, 0xee}, +	{0xf2, 0x03}, {0xe5, 0x04}, {0xe8, 0xa0}, {0xe1, 0x05}, {0xef, 0x06}, +	{0x07, 0x08}, {0xe9, 0x09}, }, +	{ {0x05, 0x06}, {0xa0, 0xac}, {0xad, 0xf4}, {0xe9, 0x01}, {0x02, 0xe1}, +	{0xe5, 0x03}, {0x9b, 0x04}, }, +	{ {0x11, 0xa0}, {0xbf, 0xe1}, {0xe2, 0xe6}, {0xed, 0xe4}, {0xe9, 0xf7}, +	{0xa7, 0x01}, {0x02, 0xbb}, {0x03, 0x04}, {0xec, 0x05}, {0x9b, 0xee}, +	{0x06, 0xef}, {0x07, 0xac}, {0xe5, 0xf3}, {0x08, 0x09}, {0x0a, 0xae}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, {0x0f, 0x10}, }, +	{ {0x06, 0x07}, {0xa0, 0xae}, {0xe1, 0xe5}, {0xec, 0xfa}, {0x9b, 0xef}, +	{0xe9, 0x01}, {0x02, 0x03}, {0x04, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +}; + +static struct hufftree_entry program_title_hufftree[][128] = { +	{ {0x1b, 0x1c}, {0xb4, 0xa4}, {0xb2, 0xb7}, {0xda, 0x01}, {0xd1, 0x02}, +	{0x03, 0x9b}, {0x04, 0xd5}, {0xd9, 0x05}, {0xcb, 0xd6}, {0x06, 0xcf}, +	{0x07, 0x08}, {0xca, 0x09}, {0xc9, 0xc5}, {0xc6, 0x0a}, {0xd2, 0xc4}, +	{0xc7, 0xcc}, {0xd0, 0xc8}, {0xd7, 0xce}, {0x0b, 0xc1}, {0x0c, 0xc2}, +	{0xcd, 0xc3}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xd3, 0x11}, {0xd4, 0x12}, +	{0x13, 0x14}, {0x15, 0x16}, {0x17, 0x18}, {0x19, 0x1a}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x29, 0x2a}, {0xd8, 0xe5}, {0xb9, 0x01}, {0xa7, 0xb1}, {0xec, 0xd1}, +	{0x02, 0xad}, {0xb2, 0xda}, {0xe3, 0xb3}, {0x03, 0xe4}, {0xe6, 0x04}, +	{0x9b, 0xe2}, {0x05, 0x06}, {0x07, 0x08}, {0x09, 0xd5}, {0x0a, 0xd6}, +	{0x0b, 0xd9}, {0x0c, 0xa6}, {0xe9, 0xcb}, {0xc5, 0xcf}, {0x0d, 0x0e}, +	{0xca, 0xc9}, {0x0f, 0xc7}, {0x10, 0x11}, {0xe1, 0x12}, {0x13, 0xc6}, +	{0xd2, 0xc8}, {0xce, 0xc1}, {0xc4, 0xd0}, {0xcc, 0x14}, {0x15, 0xef}, +	{0xc2, 0xd7}, {0x16, 0xcd}, {0x17, 0xf4}, {0xd4, 0x18}, {0x19, 0x1a}, +	{0xc3, 0xd3}, {0x1b, 0x1c}, {0x1d, 0x1e}, {0x1f, 0x20}, {0x21, 0x22}, +	{0x23, 0x24}, {0x25, 0x26}, {0x27, 0x28}, }, +	{ {0x01, 0x80}, {0xa0, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0xb1, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x04, 0xf3}, {0xe4, 0xb9}, {0x01, 0xf4}, {0xa0, 0x9b}, {0x02, 0x03}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x01, 0x02}, {0x9b, 0xc1}, {0xc8, 0xd3}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x07, 0x08}, {0xb1, 0xd2}, {0xd3, 0xd4}, {0xd5, 0xad}, {0xcd, 0xc1}, +	{0x01, 0x02}, {0x03, 0xa0}, {0x04, 0x9b}, {0x05, 0x06}, }, +	{ {0xa0, 0x05}, {0xc9, 0xd7}, {0xd3, 0x01}, {0x02, 0x9b}, {0xae, 0x80}, +	{0x03, 0x04}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0x03}, {0xad, 0x9b}, {0x01, 0x80}, {0xa0, 0xb0}, }, +	{ {0x04, 0x05}, {0x80, 0x9b}, {0xb1, 0xb2}, {0xa0, 0xb0}, {0xb9, 0x01}, +	{0x02, 0x03}, }, +	{ {0x02, 0x03}, {0xb1, 0xba}, {0x01, 0xb0}, {0x9b, 0x80}, }, +	{ {0x80, 0x01}, {0xb0, 0x9b}, }, +	{ {0x9b, 0xb8}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0xb0}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x02, 0x03}, {0xb1, 0xb3}, {0xb9, 0xb0}, {0x01, 0x9b}, }, +	{ {0x9b, 0xa0}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x80}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x13, 0x14}, {0xaa, 0xad}, {0xae, 0xf6}, {0xe7, 0xf4}, {0xe2, 0xe9}, +	{0x01, 0x02}, {0xc2, 0xf0}, {0x9b, 0xf3}, {0xe3, 0xe6}, {0xf7, 0x03}, +	{0xf5, 0x04}, {0x05, 0x06}, {0xf2, 0x07}, {0x08, 0x09}, {0x0a, 0x0b}, +	{0x0c, 0xe4}, {0xa0, 0x0d}, {0xec, 0xee}, {0x0e, 0xed}, {0x0f, 0x10}, +	{0x11, 0x12}, }, +	{ {0x08, 0x09}, {0xc1, 0xd3}, {0x9b, 0x01}, {0xc3, 0x02}, {0xe9, 0xec}, +	{0x03, 0xf2}, {0xf5, 0x04}, {0xef, 0xe1}, {0x05, 0xe5}, {0x06, 0x07}, }, +	{ {0x0b, 0x0c}, {0xc1, 0xf9}, {0x01, 0xc2}, {0xcf, 0xe5}, {0xf5, 0x9b}, +	{0xe9, 0x02}, {0xa0, 0x03}, {0x04, 0x05}, {0xf2, 0x06}, {0xec, 0x07}, +	{0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0xef}, }, +	{ {0x05, 0x06}, {0xf9, 0x9b}, {0x01, 0xf5}, {0x02, 0xf2}, {0xe9, 0xe5}, +	{0xef, 0x03}, {0xe1, 0x04}, }, +	{ {0x0a, 0x0b}, {0xf1, 0xf5}, {0xf3, 0x01}, {0xed, 0xf9}, {0xc3, 0x02}, +	{0xec, 0xee}, {0xe4, 0xf8}, {0x03, 0x9b}, {0xf6, 0x04}, {0x05, 0xe1}, +	{0x06, 0x07}, {0x08, 0x09}, }, +	{ {0x07, 0x08}, {0xa0, 0x9b}, {0xcc, 0x01}, {0xe5, 0x02}, {0xec, 0xf5}, +	{0xef, 0x03}, {0xe9, 0xf2}, {0x04, 0x05}, {0xe1, 0x06}, }, +	{ {0x09, 0x0a}, {0xae, 0xec}, {0xf9, 0xc1}, {0xe8, 0x01}, {0x9b, 0x02}, +	{0x03, 0x04}, {0xe1, 0xf5}, {0xe9, 0x05}, {0xe5, 0x06}, {0xf2, 0xef}, +	{0x07, 0x08}, }, +	{ {0xef, 0x05}, {0x80, 0x9b}, {0xf5, 0x01}, {0x02, 0xe9}, {0xe1, 0x03}, +	{0xe5, 0x04}, }, +	{ {0xee, 0x0b}, {0xba, 0xd4}, {0xae, 0xf2}, {0xe3, 0x01}, {0xa0, 0x02}, +	{0x80, 0x9b}, {0xed, 0x03}, {0xc9, 0xf3}, {0xf4, 0x04}, {0x05, 0x06}, +	{0x07, 0x08}, {0x09, 0x0a}, }, +	{ {0x02, 0x03}, {0x9b, 0xf5}, {0x01, 0xe1}, {0xef, 0xe5}, }, +	{ {0x05, 0xe9}, {0xe1, 0xef}, {0xf5, 0xee}, {0x9b, 0xe5}, {0x01, 0x02}, +	{0x03, 0x04}, }, +	{ {0x04, 0x05}, {0xa0, 0x9b}, {0x01, 0xf5}, {0x02, 0xe5}, {0xef, 0x03}, +	{0xe1, 0xe9}, }, +	{ {0x08, 0x09}, {0xaa, 0xd4}, {0x01, 0x9b}, {0xe3, 0x02}, {0xf2, 0x03}, +	{0xe5, 0x04}, {0xf5, 0xf9}, {0xe9, 0x05}, {0xef, 0x06}, {0x07, 0xe1}, }, +	{ {0xe5, 0x08}, {0xce, 0xa0}, {0xc6, 0xf5}, {0x01, 0x02}, {0x9b, 0xc2}, +	{0x03, 0xe1}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0x07}, }, +	{ {0x09, 0x0a}, {0xe4, 0xf3}, {0xe6, 0xf6}, {0xf7, 0xf0}, {0xf2, 0x01}, +	{0xec, 0x02}, {0x03, 0xa0}, {0x9b, 0x04}, {0x05, 0xf5}, {0x06, 0x07}, +	{0xee, 0x08}, }, +	{ {0x0b, 0x0c}, {0xa0, 0xf3}, {0xf9, 0xae}, {0xd2, 0xc7}, {0x01, 0x9b}, +	{0x02, 0xf5}, {0x03, 0x04}, {0x05, 0xe9}, {0xec, 0x06}, {0xe5, 0x07}, +	{0xef, 0x08}, {0xe1, 0x09}, {0xf2, 0x0a}, }, +	{ {0x01, 0xf5}, {0x9b, 0xd6}, }, +	{ {0x04, 0x05}, {0xe8, 0x9b}, {0x01, 0xf5}, {0x02, 0xe1}, {0xe9, 0xef}, +	{0x03, 0xe5}, }, +	{ {0x10, 0x11}, {0xaa, 0xec}, {0xf1, 0xae}, {0xa0, 0xf7}, {0xed, 0xee}, +	{0x01, 0x02}, {0x9b, 0xeb}, {0x03, 0x04}, {0x05, 0x06}, {0xe3, 0x07}, +	{0xef, 0x08}, {0xe9, 0xf5}, {0x09, 0xe1}, {0xe5, 0xf0}, {0xe8, 0x0a}, +	{0x0b, 0x0c}, {0x0d, 0xf4}, {0x0e, 0x0f}, }, +	{ {0xe8, 0x0a}, {0xad, 0xce}, {0x9b, 0x01}, {0xd6, 0x02}, {0xf5, 0xf7}, +	{0x03, 0x04}, {0xe1, 0xe5}, {0xe9, 0x05}, {0xf2, 0x06}, {0xef, 0x07}, +	{0x08, 0x09}, }, +	{ {0xee, 0x03}, {0xec, 0xae}, {0x01, 0x9b}, {0x02, 0xf0}, }, +	{ {0x06, 0xe9}, {0xa0, 0xc3}, {0xef, 0x9b}, {0xe5, 0x01}, {0x80, 0x02}, +	{0x03, 0xe1}, {0x04, 0x05}, }, +	{ {0x06, 0x07}, {0xc6, 0xd7}, {0x01, 0x9b}, {0xf2, 0x02}, {0x03, 0xe8}, +	{0xe5, 0xe1}, {0x04, 0xe9}, {0xef, 0x05}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x02, 0xef}, {0xe1, 0x9b}, {0x01, 0xe5}, }, +	{ {0x01, 0xef}, {0x9b, 0xe1}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x19, 0x1a}, {0x9b, 0xba}, {0xe5, 0xea}, {0xf8, 0x01}, {0x02, 0xe6}, +	{0xa7, 0x03}, {0xfa, 0xe8}, {0x04, 0xf7}, {0x05, 0xf5}, {0xe2, 0x06}, +	{0xeb, 0x07}, {0xf0, 0x08}, {0x80, 0xf6}, {0xe7, 0x09}, {0xe4, 0x0a}, +	{0xa0, 0xe9}, {0x0b, 0xe3}, {0xf9, 0x0c}, {0x0d, 0xed}, {0x0e, 0x0f}, +	{0xf3, 0x10}, {0x11, 0xec}, {0x12, 0xf4}, {0xf2, 0x13}, {0xee, 0x14}, +	{0x15, 0x16}, {0x17, 0x18}, }, +	{ {0x0a, 0x0b}, {0xf3, 0x9b}, {0xf5, 0xe2}, {0x01, 0x80}, {0xa0, 0x02}, +	{0xe5, 0xf2}, {0xe9, 0x03}, {0xec, 0x04}, {0xf9, 0x05}, {0xef, 0x06}, +	{0xe1, 0x07}, {0x08, 0x09}, }, +	{ {0x10, 0x11}, {0xc3, 0xcc}, {0xc7, 0x9b}, {0xe3, 0x01}, {0x80, 0xec}, +	{0xf9, 0x02}, {0xf3, 0x03}, {0xf5, 0x04}, {0x05, 0xf2}, {0x06, 0xe9}, +	{0xa0, 0x07}, {0x08, 0xef}, {0xf4, 0x09}, {0x0a, 0xe1}, {0x0b, 0xe8}, +	{0xeb, 0xe5}, {0x0c, 0x0d}, {0x0e, 0x0f}, }, +	{ {0x0e, 0x0f}, {0xae, 0xf5}, {0xf7, 0x01}, {0xec, 0x02}, {0xe4, 0xe7}, +	{0xf2, 0x03}, {0x9b, 0xef}, {0x04, 0xf6}, {0x05, 0x06}, {0xf9, 0xf3}, +	{0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0x80}, {0x0a, 0x0b}, {0xe5, 0x0c}, +	{0x0d, 0xa0}, }, +	{ {0x1e, 0x1f}, {0x9b, 0xa1}, {0xad, 0xe8}, {0xea, 0xf1}, {0xf5, 0xfa}, +	{0x01, 0x02}, {0x03, 0x04}, {0xba, 0xf8}, {0xa7, 0xe2}, {0xe9, 0x05}, +	{0x06, 0x07}, {0xe6, 0xed}, {0xe7, 0xeb}, {0x08, 0x09}, {0xf6, 0xf0}, +	{0x0a, 0xef}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0xf9}, {0x0f, 0xe4}, +	{0xec, 0x10}, {0xe5, 0x11}, {0xf4, 0xf7}, {0x12, 0x13}, {0xe1, 0x14}, +	{0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x80}, {0x18, 0x19}, {0xf2, 0x1a}, +	{0x1b, 0xa0}, {0x1c, 0x1d}, }, +	{ {0xa0, 0x0b}, {0xf5, 0x9b}, {0x01, 0xec}, {0xf3, 0xf2}, {0x80, 0xe1}, +	{0x02, 0x03}, {0xf4, 0xe9}, {0xef, 0xe6}, {0x04, 0x05}, {0x06, 0x07}, +	{0xe5, 0x08}, {0x09, 0x0a}, }, +	{ {0x0f, 0x10}, {0xba, 0xf9}, {0xa7, 0xf4}, {0x9b, 0x01}, {0xe7, 0xec}, +	{0x02, 0xee}, {0x03, 0xef}, {0xf5, 0x04}, {0xf2, 0x05}, {0x06, 0xe9}, +	{0x07, 0xf3}, {0xe1, 0x08}, {0x09, 0x0a}, {0x0b, 0xe5}, {0x80, 0x0c}, +	{0xe8, 0xa0}, {0x0d, 0x0e}, }, +	{ {0xe5, 0x0d}, {0xe2, 0xf5}, {0xf7, 0x9b}, {0xec, 0x01}, {0xf9, 0xee}, +	{0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x80}, {0x06, 0xa0}, {0xe1, 0xef}, +	{0x07, 0xf4}, {0xe9, 0x08}, {0x09, 0x0a}, {0x0b, 0x0c}, }, +	{ {0x15, 0x16}, {0xa1, 0xf8}, {0xe9, 0xeb}, {0x01, 0x80}, {0x9b, 0xfa}, +	{0xe2, 0x02}, {0x03, 0x04}, {0xa0, 0xf0}, {0x05, 0x06}, {0x07, 0xe1}, +	{0x08, 0xe6}, {0xf2, 0xed}, {0xf6, 0x09}, {0xe4, 0x0a}, {0xef, 0xf4}, +	{0xec, 0xf3}, {0xe7, 0xe5}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0x0f}, +	{0x10, 0x11}, {0x12, 0x13}, {0xee, 0x14}, }, +	{ {0xef, 0x01}, {0x9b, 0xe1}, }, +	{ {0x0b, 0x0c}, {0xd4, 0xef}, {0xe6, 0xec}, {0xf7, 0xe1}, {0x01, 0xba}, +	{0x02, 0x9b}, {0xf9, 0x03}, {0x04, 0x05}, {0xf3, 0x06}, {0x07, 0x08}, +	{0xe9, 0xa0}, {0x09, 0x80}, {0xe5, 0x0a}, }, +	{ {0x15, 0x16}, {0xa7, 0xba}, {0xe3, 0xf7}, {0xf2, 0xad}, {0xe2, 0x01}, +	{0x02, 0x9b}, {0xe6, 0x03}, {0xed, 0xf6}, {0x04, 0xeb}, {0x05, 0xf4}, +	{0x06, 0x07}, {0x08, 0xf3}, {0x09, 0xf5}, {0x0a, 0xef}, {0x0b, 0x0c}, +	{0x80, 0xf9}, {0xe1, 0x0d}, {0xe4, 0xe9}, {0xa0, 0x0e}, {0x0f, 0xec}, +	{0xe5, 0x10}, {0x11, 0x12}, {0x13, 0x14}, }, +	{ {0x0a, 0x0b}, {0xf9, 0x9b}, {0xf5, 0xf3}, {0x01, 0x02}, {0xe2, 0xed}, +	{0x80, 0x03}, {0xf0, 0xef}, {0x04, 0xa0}, {0x05, 0xe9}, {0x06, 0xe1}, +	{0x07, 0x08}, {0x09, 0xe5}, }, +	{ {0x18, 0x19}, {0xe2, 0xea}, {0xf2, 0xe8}, {0xec, 0xed}, {0xfa, 0x9b}, +	{0x01, 0xf5}, {0x02, 0x03}, {0xf6, 0x04}, {0xba, 0xe6}, {0x05, 0x06}, +	{0xeb, 0xef}, {0x07, 0xa7}, {0xf9, 0x08}, {0x09, 0x0a}, {0x0b, 0xe3}, +	{0x0c, 0xee}, {0xe1, 0x0d}, {0xf3, 0x0e}, {0xe9, 0x0f}, {0x10, 0xf4}, +	{0x80, 0xe4}, {0xe5, 0x11}, {0x12, 0xe7}, {0xa0, 0x13}, {0x14, 0x15}, +	{0x16, 0x17}, }, +	{ {0x1b, 0x1c}, {0xae, 0xfa}, {0xbf, 0x01}, {0xa7, 0x9b}, {0x02, 0xe9}, +	{0xf8, 0xf9}, {0x03, 0xe5}, {0xe8, 0x04}, {0xe1, 0xeb}, {0x05, 0xe2}, +	{0x06, 0x07}, {0xe3, 0x08}, {0xe7, 0xf4}, {0x09, 0x80}, {0xf6, 0xf0}, +	{0x0a, 0xe4}, {0x0b, 0xf3}, {0xf7, 0x0c}, {0x0d, 0xef}, {0xec, 0xa0}, +	{0x0e, 0x0f}, {0xed, 0xe6}, {0x10, 0xf5}, {0x11, 0x12}, {0x13, 0x14}, +	{0x15, 0xf2}, {0x16, 0xee}, {0x17, 0x18}, {0x19, 0x1a}, }, +	{ {0x0e, 0x0f}, {0xed, 0xa7}, {0x9b, 0xe4}, {0x01, 0xf9}, {0xf3, 0xf2}, +	{0xf4, 0x02}, {0xe8, 0x03}, {0xec, 0xf0}, {0x04, 0xe1}, {0xe9, 0x05}, +	{0x06, 0x80}, {0xa0, 0x07}, {0x08, 0x09}, {0x0a, 0xe5}, {0xef, 0x0b}, +	{0x0c, 0x0d}, }, +	{ {0x9b, 0xf5}, }, +	{ {0x18, 0x19}, {0xba, 0xac}, {0xf6, 0x9b}, {0xf0, 0xe2}, {0x01, 0xe6}, +	{0x02, 0xa7}, {0xae, 0xe7}, {0x03, 0xe3}, {0xf5, 0x04}, {0xed, 0x05}, +	{0x06, 0x07}, {0xeb, 0x08}, {0x09, 0xee}, {0xf2, 0x0a}, {0xe4, 0x0b}, +	{0xf9, 0xec}, {0x0c, 0x0d}, {0xf4, 0x80}, {0x0e, 0xef}, {0xf3, 0xa0}, +	{0xe1, 0x0f}, {0xe9, 0x10}, {0x11, 0xe5}, {0x12, 0x13}, {0x14, 0x15}, +	{0x16, 0x17}, }, +	{ {0x19, 0x1a}, {0xa7, 0xac}, {0xbf, 0xc3}, {0xc8, 0xe4}, {0xe6, 0xed}, +	{0xf2, 0xae}, {0xec, 0xee}, {0xf9, 0x01}, {0x02, 0x03}, {0x04, 0xba}, +	{0x05, 0x9b}, {0xf5, 0x06}, {0x07, 0x08}, {0x09, 0xeb}, {0xf0, 0x0a}, +	{0x0b, 0x0c}, {0xe1, 0xe3}, {0x0d, 0xe8}, {0x0e, 0x0f}, {0xef, 0x10}, +	{0x11, 0xf3}, {0x12, 0xe9}, {0x13, 0xe5}, {0x14, 0x15}, {0xf4, 0x16}, +	{0x17, 0xa0}, {0x18, 0x80}, }, +	{ {0x14, 0x15}, {0xba, 0xbf}, {0xe4, 0xf7}, {0x9b, 0xa7}, {0x01, 0xee}, +	{0x02, 0x03}, {0x04, 0xe3}, {0xe2, 0xed}, {0x05, 0xf9}, {0x06, 0xf4}, +	{0x07, 0xec}, {0x08, 0xf5}, {0xf2, 0x09}, {0xe1, 0xf3}, {0x0a, 0xef}, +	{0x0b, 0x0c}, {0x0d, 0xe9}, {0x80, 0xe5}, {0x0e, 0xa0}, {0x0f, 0xe8}, +	{0x10, 0x11}, {0x12, 0x13}, }, +	{ {0x11, 0x12}, {0xeb, 0xfa}, {0x80, 0xe6}, {0x9b, 0x01}, {0xa0, 0x02}, +	{0x03, 0xe9}, {0xe1, 0x04}, {0xe4, 0xf0}, {0xed, 0xe2}, {0xe3, 0xe7}, +	{0xec, 0x05}, {0xe5, 0x06}, {0x07, 0x08}, {0x09, 0xf4}, {0x0a, 0x0b}, +	{0x0c, 0xf3}, {0xee, 0x0d}, {0x0e, 0xf2}, {0x0f, 0x10}, }, +	{ {0x04, 0xe5}, {0xf3, 0xef}, {0x9b, 0x01}, {0xe1, 0x02}, {0x03, 0xe9}, }, +	{ {0x0b, 0x0c}, {0xa7, 0xe2}, {0xec, 0xe3}, {0xf2, 0x01}, {0x9b, 0x02}, +	{0x03, 0x04}, {0xe9, 0xef}, {0xee, 0xe5}, {0xe1, 0x80}, {0x05, 0xa0}, +	{0x06, 0x07}, {0x08, 0x09}, {0xf3, 0x0a}, }, +	{ {0x05, 0x06}, {0x9b, 0xa0}, {0xe1, 0xe5}, {0xe9, 0x01}, {0x80, 0xf0}, +	{0x02, 0xf4}, {0x03, 0x04}, }, +	{ {0xa0, 0x13}, {0xe3, 0xad}, {0xe4, 0xe9}, {0xee, 0xef}, {0xf0, 0xf4}, +	{0xf6, 0xa1}, {0xe1, 0xed}, {0x01, 0xe2}, {0x02, 0x03}, {0x04, 0xa7}, +	{0x05, 0x06}, {0xf7, 0x07}, {0x9b, 0xec}, {0x08, 0xe5}, {0x09, 0x0a}, +	{0x0b, 0x0c}, {0x0d, 0x0e}, {0xf3, 0x0f}, {0x10, 0x11}, {0x80, 0x12}, }, +	{ {0x05, 0x06}, {0xe5, 0xfa}, {0xa0, 0xf9}, {0x9b, 0x01}, {0x80, 0xe9}, +	{0x02, 0xe1}, {0x03, 0x04}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +	{ {0x9b, 0x9b}, }, +}; + + + +static inline void huffbuff_init(struct huffbuff *hbuf, uint8_t *buf, uint32_t buf_len) +{ +	memset(hbuf, 0, sizeof(struct huffbuff)); +	hbuf->buf = buf; +	hbuf->buf_len = buf_len; +} + +static inline int huffbuff_bits(struct huffbuff *hbuf, uint8_t nbits) +{ +	uint8_t result = 0; + +	if (nbits > 8) +		return -1; + +	while(nbits--) { +		if (hbuf->cur_byte >= hbuf->buf_len) { +			return -1; +		} + +		result <<= 1; +		if (hbuf->buf[hbuf->cur_byte] & (0x80 >> hbuf->cur_bit)) +			result |= 1; + +		if (++hbuf->cur_bit > 7) { +			hbuf->cur_byte++; +			hbuf->cur_bit = 0; +		} +	} + +	return result; +} + +static inline int append_unicode_char(uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos, +				      uint32_t c) +{ +	uint8_t tmp[3]; +	int tmplen = 0; + +	// encode the unicode character first of all +	if (c < 0x80) { +		tmp[0] = c; +		tmplen = 1; +	} else if (c < 0x800) { +		tmp[0] = 0xc0 | ((c >> 6) & 0x1f); +		tmp[1] = 0x80 | (c & 0x3f); +		tmplen = 2; +	} else if (c < 0x10000) { +		tmp[0] = 0xe0 | ((c >> 12) & 0x0f); +		tmp[1] = 0x80 | ((c >> 6) & 0x3f); +		tmp[2] = 0x80 | (c & 0x3f); +		tmplen = 3; +	} else { +		return -1; +	} + +	// do we have enough buffer space? +	if ((*destbufpos + tmplen) >= *destbuflen) { +		uint8_t *new_dest = realloc(*destbuf, *destbuflen + DEST_ALLOC_DELTA); +		if (new_dest == NULL) +			return -ENOMEM; +		*destbuf = new_dest; +		*destbuflen += DEST_ALLOC_DELTA; +	} + +	// copy it into position +	memcpy(*destbuf + *destbufpos, tmp, tmplen); +	*destbufpos += tmplen; + +	return 0; +} + +static inline int unicode_decode(uint8_t *srcbuf, size_t srcbuflen, int mode, +				 uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos) +{ +	size_t i; +	uint32_t msb = mode << 8; + +	for(i=0; i< srcbuflen; i++) { +		if (append_unicode_char(destbuf, destbuflen, destbufpos, msb + srcbuf[i])) +			return -1; +	} + +	return *destbufpos; +} + +static int huffman_decode_uncompressed(struct huffbuff *hbuf, +				       uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos) +{ +	int c; + +	while(hbuf->cur_byte < hbuf->buf_len) { +		// get next byte +		if ((c = huffbuff_bits(hbuf, 8)) < 0) +			return -1; + +		switch(c) { +		case HUFFSTRING_END: +			return 0; + +		case HUFFSTRING_ESCAPE: +			return HUFFSTRING_ESCAPE; + +		default: +			if (append_unicode_char(destbuf, destbuflen, destbufpos, c)) +				return -1; + +			// if it is 7 bit, we swap back to the compressed context +			if ((c & 0x80) == 0) +				return c; + +			// characters following an 8 bit uncompressed char are uncompressed as well +			break; +		} +	} + +	// ran out of string; pretend we saw an end of string char +	return HUFFSTRING_END; +} + +static int huffman_decode(uint8_t *src, size_t srclen, +			  uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos, +			  struct hufftree_entry hufftree[][128]) +{ +	struct huffbuff hbuf; +	int bit; +	struct hufftree_entry *tree = hufftree[0]; +	uint8_t treeidx = 0; +	uint8_t treeval; +	int tmp; + +	huffbuff_init(&hbuf, src, srclen); + +	while(hbuf.cur_byte < hbuf.buf_len) { +		// get the next bit +		if ((bit = huffbuff_bits(&hbuf, 1)) < 0) +			return *destbufpos; + +		if (!bit) { +			treeval = tree[treeidx].left_idx; +		} else { +			treeval = tree[treeidx].right_idx; +		} + +		if (treeval & HUFFTREE_LITERAL_MASK) { +			switch(treeval & ~HUFFTREE_LITERAL_MASK) { +			case HUFFSTRING_END: +				return 0; + +			case HUFFSTRING_ESCAPE: +				if ((tmp = +					huffman_decode_uncompressed(&hbuf, +							destbuf, destbuflen, destbufpos)) < 0) +					return tmp; +				if (tmp == 0) +					return *destbufpos; + +				tree = hufftree[tmp]; +				treeidx = 0; +				break; + +			default: +				// stash it +				if (append_unicode_char(destbuf, destbuflen, destbufpos, +				    			treeval & ~HUFFTREE_LITERAL_MASK)) +					return -1; +				tree = hufftree[treeval & ~HUFFTREE_LITERAL_MASK]; +				treeidx = 0; +				break; +			} +		} else { +			treeidx = treeval; +		} +	} + +	return *destbufpos; +} + +int atsc_text_segment_decode(struct atsc_text_string_segment *segment, +			     uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos) +{ +	if (segment->mode > ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX) +		return -1; + +	// mode==0 MUST be used for compressed text +	if ((segment->mode) && (segment->compression_type)) +		return -1; + +	uint8_t *buf = atsc_text_string_segment_bytes(segment); + +	switch(segment->compression_type) { +	case ATSC_TEXT_COMPRESS_NONE: +		return unicode_decode(buf, segment->number_bytes, segment->mode, +				      destbuf, destbufsize, destbufpos); + +	case ATSC_TEXT_COMPRESS_PROGRAM_TITLE: +		return huffman_decode(buf, segment->number_bytes, +				      destbuf, destbufsize, destbufpos, +				      program_title_hufftree); + +	case ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION: +		return huffman_decode(buf, segment->number_bytes, +				      destbuf, destbufsize, destbufpos, +				      program_description_hufftree); +	} + +	return -1; +} diff --git a/lib/libucsi/atsc/caption_service_descriptor.h b/lib/libucsi/atsc/caption_service_descriptor.h new file mode 100644 index 0000000..29d1794 --- /dev/null +++ b/lib/libucsi/atsc/caption_service_descriptor.h @@ -0,0 +1,137 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR +#define _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_caption_service_descriptor structure. + */ +struct atsc_caption_service_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t number_of_services	: 5; ); +	/* struct atsc_caption_service_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_caption_service_descriptor. + */ +struct atsc_caption_service_entry { +	iso639lang_t language_code; +  EBIT3(uint8_t digital_cc 		: 1; , +	uint8_t reserved		: 1; , +	uint8_t value			: 6; ); +  EBIT3(uint16_t easy_reader 		: 1; , +	uint16_t wide_aspect_ratio	: 1; , +	uint16_t reserved1		:14; ); +} __ucsi_packed; + +/** + * Process an atsc_caption_service_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_caption_service_descriptor pointer, or NULL on error. + */ +static inline struct atsc_caption_service_descriptor* +	atsc_caption_service_descriptor_codec(struct descriptor* d) +{ +	struct atsc_caption_service_descriptor *ret = +		(struct atsc_caption_service_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->number_of_services; idx++) { +		if (d->len < (pos + sizeof(struct atsc_caption_service_entry))) +			return NULL; + +		bswap16(buf+pos+4); + +		pos += sizeof(struct atsc_caption_service_entry); +	} + +	return (struct atsc_caption_service_descriptor*) d; +} + +/** + * Iterator for entries field of a atsc_caption_service_descriptor. + * + * @param d atsc_caption_service_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_caption_service_entry. + * @param idx Field iterator integer. + */ +#define atsc_caption_service_descriptor_entries_for_each(d, pos, idx) \ +	for ((pos) = atsc_caption_service_descriptor_entries_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_caption_service_descriptor_entries_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_caption_service_entry* +	atsc_caption_service_descriptor_entries_first(struct atsc_caption_service_descriptor *d) +{ +	if (d->number_of_services == 0) +		return NULL; + +	return (struct atsc_caption_service_entry *) +		((uint8_t*) d + sizeof(struct atsc_caption_service_descriptor)); +} + +static inline struct atsc_caption_service_entry* +	atsc_caption_service_descriptor_entries_next(struct atsc_caption_service_descriptor *d, +						     struct atsc_caption_service_entry *pos, +						     int idx) +{ +	if (idx >= d->number_of_services) +		return NULL; + +	return (struct atsc_caption_service_entry *) +		((uint8_t *) pos + sizeof(struct atsc_caption_service_entry)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/component_name_descriptor.h b/lib/libucsi/atsc/component_name_descriptor.h new file mode 100644 index 0000000..3b9cab7 --- /dev/null +++ b/lib/libucsi/atsc/component_name_descriptor.h @@ -0,0 +1,92 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR +#define _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_component_name_descriptor structure. + */ +struct atsc_component_name_descriptor { +	struct descriptor d; + +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_component_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_component_name_descriptor pointer, or NULL on error. + */ +static inline struct atsc_component_name_descriptor* +	atsc_component_name_descriptor_codec(struct descriptor* d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor); + +	if (atsc_text_validate(txt, d->len)) +		return NULL; + +	return (struct atsc_component_name_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_component_name_descriptor. + * + * @param d atsc_component_name_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_component_name_descriptor_text(struct atsc_component_name_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_component_name_descriptor_text. + * + * @param d atsc_component_name_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_component_name_descriptor_text_length(struct atsc_component_name_descriptor *d) +{ +	return d->d.len; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/content_advisory_descriptor.h b/lib/libucsi/atsc/content_advisory_descriptor.h new file mode 100644 index 0000000..da19813 --- /dev/null +++ b/lib/libucsi/atsc/content_advisory_descriptor.h @@ -0,0 +1,235 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR +#define _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_content_advisory_descriptor structure. + */ +struct atsc_content_advisory_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 2; , +	uint8_t rating_region_count	: 6; ); +	/* struct atsc_content_advisory_entry entries[] */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_content_advisory_descriptor. + */ +struct atsc_content_advisory_entry { +	uint8_t rating_region; +	uint8_t rated_dimensions; +	/* struct atsc_content_advisory_entry_dimension dimensions[] */ +	/* struct atsc_content_advisory_entry_part2 part2 */ +} __ucsi_packed; + +/** + * An entry in the entries field of a atsc_content_advisory_descriptor. + */ +struct atsc_content_advisory_entry_dimension { +	uint8_t rating_dimension_j; +  EBIT2(uint8_t reserved		: 4; , +	uint8_t rating_value		: 4; ); +} __ucsi_packed; + +/** + * Part2 of an atsc_content_advisory_entry. + */ +struct atsc_content_advisory_entry_part2 { +	uint8_t rating_description_length; +	/* struct atsc_text description */ +} __ucsi_packed; + +/** + * Process an atsc_content_advisory_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_content_advisory_descriptor pointer, or NULL on error. + */ +static inline struct atsc_content_advisory_descriptor* +	atsc_content_advisory_descriptor_codec(struct descriptor* d) +{ +	struct atsc_content_advisory_descriptor *ret = +		(struct atsc_content_advisory_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->rating_region_count; idx++) { +		if (d->len < (pos + sizeof(struct atsc_content_advisory_entry))) +			return NULL; +		struct atsc_content_advisory_entry *entry = +			(struct atsc_content_advisory_entry *) (buf + pos); +		pos += sizeof(struct atsc_content_advisory_entry); + +		if (d->len < (pos + (sizeof(struct atsc_content_advisory_entry_dimension) * +				  entry->rated_dimensions))) +			return NULL; +		pos += sizeof(struct atsc_content_advisory_entry_dimension) * entry->rated_dimensions; + +		if (d->len < (pos + sizeof(struct atsc_content_advisory_entry_part2))) +			return NULL; +		struct atsc_content_advisory_entry_part2 *part2 = +				(struct atsc_content_advisory_entry_part2 *) (buf + pos); +		pos += sizeof(struct atsc_content_advisory_entry_part2); + +		if (d->len < (pos + part2->rating_description_length)) +			return NULL; + +		if (atsc_text_validate(buf+pos, part2->rating_description_length)) +			return NULL; + +		pos += part2->rating_description_length; +	} + +	return (struct atsc_content_advisory_descriptor*) d; +} + +/** + * Iterator for entries field of a atsc_content_advisory_descriptor. + * + * @param d atsc_content_advisory_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_content_advisory_entry. + * @param idx Integer used to count which entry we are in. + */ +#define atsc_content_advisory_descriptor_entries_for_each(d, pos, idx) \ +	for ((pos) = atsc_content_advisory_descriptor_entries_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_content_advisory_descriptor_entries_next(d, pos, ++idx)) + +/** + * Iterator for dimensions field of a atsc_content_advisory_entry. + * + * @param d atsc_content_advisory_entry pointer. + * @param pos Variable holding a pointer to the current atsc_content_advisory_entry_dimension. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_content_advisory_entry_dimensions_for_each(d, pos, idx) \ +	for ((pos) = atsc_content_advisory_entry_dimensions_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_content_advisory_entry_dimensions_next(d, pos, ++idx)) + +/** + * Accessor for the part2 field of an atsc_content_advisory_entry. + * + * @param entry atsc_content_advisory_entry pointer. + * @return struct atsc_content_advisory_entry_part2 pointer. + */ +static inline struct atsc_content_advisory_entry_part2 * +	atsc_content_advisory_entry_part2(struct atsc_content_advisory_entry *entry) +{ +	int pos = sizeof(struct atsc_content_advisory_entry); +	pos += entry->rated_dimensions * sizeof(struct atsc_content_advisory_entry_dimension); + +	return (struct atsc_content_advisory_entry_part2 *) (((uint8_t*) entry) + pos); +} + + +/** + * Accessor for the description field of an atsc_content_advisory_entry_part2. + * + * @param part2 atsc_content_advisory_entry_part2 pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_content_advisory_entry_part2_description(struct atsc_content_advisory_entry_part2 *part2) +{ +	uint8_t *txt = ((uint8_t*) part2) + sizeof(struct atsc_content_advisory_entry_part2); + +	return (struct atsc_text *) txt; +} + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_content_advisory_entry* +	atsc_content_advisory_descriptor_entries_first(struct atsc_content_advisory_descriptor *d) +{ +	if (d->rating_region_count == 0) +		return NULL; + +	return (struct atsc_content_advisory_entry *) +		((uint8_t*) d + sizeof(struct atsc_content_advisory_descriptor)); +} + +static inline struct atsc_content_advisory_entry* +	atsc_content_advisory_descriptor_entries_next(struct atsc_content_advisory_descriptor *d, +						      struct atsc_content_advisory_entry *pos, +						      int idx) +{ +	if (idx >= d->rating_region_count) +		return NULL; +	struct atsc_content_advisory_entry_part2 *part2 = +		atsc_content_advisory_entry_part2(pos); + +	return (struct atsc_content_advisory_entry *) +		((uint8_t *) part2 + +		 sizeof(struct atsc_content_advisory_entry_part2) + +		 part2->rating_description_length); +} + +static inline struct atsc_content_advisory_entry_dimension* +	atsc_content_advisory_entry_dimensions_first(struct atsc_content_advisory_entry *e) +{ +	if (e->rated_dimensions == 0) +		return NULL; + +	return (struct atsc_content_advisory_entry_dimension *) +		((uint8_t*) e + sizeof(struct atsc_content_advisory_entry)); +} + +static inline struct atsc_content_advisory_entry_dimension* +	atsc_content_advisory_entry_dimensions_next(struct atsc_content_advisory_entry *e, +				   		    struct atsc_content_advisory_entry_dimension *pos, +						    int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_content_advisory_entry_dimension); + +	if (idx >= e->rated_dimensions) +		return NULL; +	return (struct atsc_content_advisory_entry_dimension *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/cvct_section.c b/lib/libucsi/atsc/cvct_section.c new file mode 100644 index 0000000..6edbc03 --- /dev/null +++ b/lib/libucsi/atsc/cvct_section.c @@ -0,0 +1,77 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/cvct_section.h> + +struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_cvct_section)) +		return NULL; +	struct atsc_cvct_section *cvct = (struct atsc_cvct_section *) psip; + +	pos++; +	for(idx =0; idx < cvct->num_channels_in_section; idx++) { +		if ((pos + sizeof(struct atsc_cvct_channel)) > len) +			return NULL; +		struct atsc_cvct_channel *channel = (struct atsc_cvct_channel *) (buf+pos); + +		pos += 7*2; + +		bswap32(buf+pos); +		bswap32(buf+pos+4); +		bswap16(buf+pos+8); +		bswap16(buf+pos+10); +		bswap16(buf+pos+12); +		bswap16(buf+pos+14); +		bswap16(buf+pos+16); +		pos+=18; + +		if ((pos + channel->descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, channel->descriptors_length)) +			return NULL; + +		pos += channel->descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_cvct_section_part2)) > len) +		return NULL; +	struct atsc_cvct_section_part2 *part2 = (struct atsc_cvct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); +	pos+=2; + +	if ((pos + part2->descriptors_length) > len) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_cvct_section *) psip; +} diff --git a/lib/libucsi/atsc/cvct_section.h b/lib/libucsi/atsc/cvct_section.h new file mode 100644 index 0000000..c3d418a --- /dev/null +++ b/lib/libucsi/atsc/cvct_section.h @@ -0,0 +1,228 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_CVCT_SECTION_H +#define _UCSI_ATSC_CVCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +/** + * atsc_cvct_section structure. + */ +struct atsc_cvct_section { +	struct atsc_section_psip head; + +	uint8_t num_channels_in_section; +	/* struct atsc_cvct_channel channels[] */ + 	/* struct atsc_cvct_channel_part2 part2 */ +} __ucsi_packed; + +struct atsc_cvct_channel { +	uint16_t short_name[7]; // UTF-16 network ordered +  EBIT4(uint32_t reserved			: 4; , +	uint32_t major_channel_number		:10; , +  	uint32_t minor_channel_number		:10; , +	uint32_t modulation_mode		: 8; ); +	uint32_t carrier_frequency; +	uint16_t channel_TSID; +	uint16_t program_number; +  EBIT8(uint16_t ETM_location			: 2; , +	uint16_t access_controlled		: 1; , +	uint16_t hidden				: 1; , +	uint16_t path_select			: 1; , +	uint16_t out_of_band			: 1; , +	uint16_t hide_guide			: 1; , +	uint16_t reserved2			: 3; , +	uint16_t service_type			: 6; ); +	uint16_t source_id; +  EBIT2(uint16_t reserved3			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_cvct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_cvct_channel *atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct); +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct, struct atsc_cvct_channel *pos, int idx); + +/** + * Process a atsc_cvct_section. + * + * @param section Pointer to anj atsc_section_psip structure. + * @return atsc_cvct_section pointer, or NULL on error. + */ +struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the transport_stream_id field of a CVCT. + * + * @param cvdt CVDT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t atsc_cvct_section_transport_stream_id(struct atsc_cvct_section *cvct) +{ +	return cvct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the tables field in an atsc_cvct_section. + * + * @param mgt atsc_cvct_section pointer. + * @param pos Variable containing a pointer to the current atsc_cvct_channel. + * @param idx Integer used to count which table we in. + */ +#define atsc_cvct_section_channels_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_cvct_section_channels_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_cvct_section_channels_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_cvct_channel structure. + * + * @param table atsc_cvct_channel pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_cvct_channel_descriptors_for_each(table, pos) \ +	for ((pos) = atsc_cvct_channel_descriptors_first(table); \ +	     (pos); \ +	     (pos) = atsc_cvct_channel_descriptors_next(table, pos)) + +/** + * Accessor for the second part of an atsc_cvct_section. + * + * @param mgt atsc_cvct_section pointer. + * @return atsc_cvct_section_part2 pointer. + */ +static inline struct atsc_cvct_section_part2 * +	atsc_cvct_section_part2(struct atsc_cvct_section *mgt) +{ +	int pos = sizeof(struct atsc_cvct_section); + +	struct atsc_cvct_channel *cur_table; +	int idx; +	atsc_cvct_section_channels_for_each(mgt, cur_table, idx) { +		pos += sizeof(struct atsc_cvct_channel); +		pos += cur_table->descriptors_length; +	} + +	return (struct atsc_cvct_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_cvct_section structure. + * + * @param part2 atsc_cvct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_cvct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_cvct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_cvct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct) +{ +	size_t pos = sizeof(struct atsc_cvct_section); + +	if (cvct->num_channels_in_section == 0) +		return NULL; + +	return (struct atsc_cvct_channel*) (((uint8_t *) cvct) + pos); +} + +static inline struct atsc_cvct_channel * +	atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct, +				     struct atsc_cvct_channel *pos, +				     int idx) +{ +	if (idx >= cvct->num_channels_in_section) +		return NULL; + +	return (struct atsc_cvct_channel *) +		(((uint8_t*) pos) + sizeof(struct atsc_cvct_channel) + pos->descriptors_length); +} + +static inline struct descriptor * +	atsc_cvct_channel_descriptors_first(struct atsc_cvct_channel *table) +{ +	size_t pos = sizeof(struct atsc_cvct_channel); + +	if (table->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) table) + pos); +} + +static inline struct descriptor * +	atsc_cvct_channel_descriptors_next(struct atsc_cvct_channel *table, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) table + sizeof(struct atsc_cvct_channel), +				table->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_cvct_section_part2_descriptors_first(struct atsc_cvct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_cvct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_cvct_section_part2_descriptors_next(struct atsc_cvct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_cvct_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcc_arriving_request_descriptor.h b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h new file mode 100644 index 0000000..af76eac --- /dev/null +++ b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h @@ -0,0 +1,107 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR +#define _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_dcc_arriving_request_type { +	DCC_ARRIVAL_TYPE_DEFER_10SEC	= 0x01, +	DCC_ARRIVAL_TYPE_DEFER		= 0x02, +}; + +/** + * atsc_dcc_arriving_request_descriptor structure. + */ +struct atsc_dcc_arriving_request_descriptor { +	struct descriptor d; + +	uint8_t dcc_arriving_request_type; +	uint8_t dcc_arriving_request_text_length; +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_dcc_arriving_request_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_dcc_arriving_request_descriptor pointer, or NULL on error. + */ +static inline struct atsc_dcc_arriving_request_descriptor* +	atsc_dcc_arriving_request_descriptor_codec(struct descriptor* d) +{ +	struct atsc_dcc_arriving_request_descriptor *ret = +		(struct atsc_dcc_arriving_request_descriptor *) d; + +	if (d->len < 2) +		return NULL; + +	if (d->len != 2 + ret->dcc_arriving_request_text_length) +		return NULL; + +	if (atsc_text_validate((uint8_t*) d + sizeof(struct atsc_dcc_arriving_request_descriptor), +	                       ret->dcc_arriving_request_text_length)) +		return NULL; + +	return (struct atsc_dcc_arriving_request_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_dcc_arriving_request_descriptor. + * + * @param d atsc_dcc_arriving_request_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_dcc_arriving_request_descriptor_text(struct atsc_dcc_arriving_request_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_arriving_request_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_dcc_arriving_request_descriptor. + * + * @param d atsc_dcc_arriving_request_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_dcc_arriving_request_descriptor_text_length(struct +		atsc_dcc_arriving_request_descriptor *d) +{ +	return d->d.len - 2; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcc_departing_request_descriptor.h b/lib/libucsi/atsc/dcc_departing_request_descriptor.h new file mode 100644 index 0000000..851f0cc --- /dev/null +++ b/lib/libucsi/atsc/dcc_departing_request_descriptor.h @@ -0,0 +1,108 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR +#define _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_dcc_departing_request_type { +	DCC_DEPART_TYPE_IMMEDIATE	= 0x01, +	DCC_DEPART_TYPE_DEFER_10SEC	= 0x02, +	DCC_DEPART_TYPE_DEFER		= 0x03, +}; + +/** + * atsc_dcc_departing_request_descriptor structure. + */ +struct atsc_dcc_departing_request_descriptor { +	struct descriptor d; + +	uint8_t dcc_departing_request_type; +	uint8_t dcc_departing_request_text_length; +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_dcc_departing_request_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_dcc_departing_request_descriptor pointer, or NULL on error. + */ +static inline struct atsc_dcc_departing_request_descriptor* +	atsc_dcc_departing_request_descriptor_codec(struct descriptor* d) +{ +	struct atsc_dcc_departing_request_descriptor *ret = +		(struct atsc_dcc_departing_request_descriptor *) d; + +	if (d->len < 2) +		return NULL; + +	if (d->len != 2 + ret->dcc_departing_request_text_length) +		return NULL; + +	if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor), +	    		       ret->dcc_departing_request_text_length)) +		return NULL; + +	return (struct atsc_dcc_departing_request_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_dcc_departing_request_descriptor. + * + * @param d atsc_dcc_departing_request_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_dcc_departing_request_descriptor_text(struct atsc_dcc_departing_request_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_dcc_departing_request_descriptor. + * + * @param d atsc_dcc_departing_request_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_dcc_departing_request_descriptor_text_length(struct +		atsc_dcc_departing_request_descriptor *d) +{ +	return d->d.len - 2; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dccsct_section.c b/lib/libucsi/atsc/dccsct_section.c new file mode 100644 index 0000000..59ad069 --- /dev/null +++ b/lib/libucsi/atsc/dccsct_section.c @@ -0,0 +1,109 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/dccsct_section.h> + +struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_dccsct_section)) +		return NULL; +	struct atsc_dccsct_section *dccsct = (struct atsc_dccsct_section *) psip; + +	pos += sizeof(struct atsc_dccsct_section); +	for(idx =0; idx < dccsct->updates_defined; idx++) { +		if (len < (pos + sizeof(struct atsc_dccsct_update))) +			return NULL; +		struct atsc_dccsct_update *update = (struct atsc_dccsct_update *) (buf+pos); + +		pos += sizeof(struct atsc_dccsct_update); +		if (len < (pos + update->update_data_length)) +			return NULL; + +		switch(update->update_type) { +		case ATSC_DCCST_UPDATE_NEW_GENRE: { +			int sublen = sizeof(struct atsc_dccsct_update_new_genre); +			if (update->update_data_length < sublen) +				return NULL; + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		case ATSC_DCCST_UPDATE_NEW_STATE: { +			int sublen = sizeof(struct atsc_dccsct_update_new_state); +			if (update->update_data_length < sublen) +				return NULL; + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		case ATSC_DCCST_UPDATE_NEW_COUNTY: { +			int sublen = sizeof(struct atsc_dccsct_update_new_county); +			if (update->update_data_length < sublen) +				return NULL; +			bswap16(buf+pos+1); + +			if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) +				return NULL; +			break; +		} +		} + +		pos += update->update_data_length; +		if (len < (pos + sizeof(struct atsc_dccsct_update_part2))) +			return NULL; +		struct atsc_dccsct_update_part2 *part2 = (struct atsc_dccsct_update_part2 *) buf + pos; + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_dccsct_update_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; + +		pos += part2->descriptors_length; +	} + +	if (len < (pos + sizeof(struct atsc_dccsct_section_part2))) +		return NULL; +	struct atsc_dccsct_section_part2 *part2 = (struct atsc_dccsct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_dccsct_section_part2); +	if (len < (pos + part2->descriptors_length)) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_dccsct_section *) psip; +} diff --git a/lib/libucsi/atsc/dccsct_section.h b/lib/libucsi/atsc/dccsct_section.h new file mode 100644 index 0000000..f9f3522 --- /dev/null +++ b/lib/libucsi/atsc/dccsct_section.h @@ -0,0 +1,327 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_DCCSCT_SECTION_H +#define _UCSI_ATSC_DCCSCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +enum atsc_dccst_update_types { +	ATSC_DCCST_UPDATE_NEW_GENRE 	= 0x01, +	ATSC_DCCST_UPDATE_NEW_STATE 	= 0x02, +	ATSC_DCCST_UPDATE_NEW_COUNTY 	= 0x03, +}; + +/** + * atsc_dccsct_section structure. + */ +struct atsc_dccsct_section { +	struct atsc_section_psip head; + +	uint8_t updates_defined; +	/* struct atsc_dccsct_update updates */ +	/* struct atsc_dccsct_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_dccsct_update { +	uint8_t update_type; +	uint8_t update_data_length; +	/* struct atsc_dccsct_update_XXX data -- depends on update_type */ +	/* struct atsc_dccsct_update_part2 part2 */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_genre { +	uint8_t genre_category_code; +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_state { +	uint8_t dcc_state_location_code; +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_new_county { +	uint8_t state_code; +  EBIT2(uint16_t reserved			: 6; , +	uint16_t dcc_county_location_code	:10; ); +	/* atsc_text name */ +} __ucsi_packed; + +struct atsc_dccsct_update_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dccsct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process an atsc_dccsct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_dccsct_section pointer, or NULL on error. + */ +struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the dccsct_type field of a dccsct. + * + * @param dccsct dccsct pointer. + * @return The dccsct_type. + */ +static inline uint16_t atsc_dccsct_section_dccsct_type(struct atsc_dccsct_section *dccsct) +{ +	return dccsct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the updates field in an atsc_dccsct_section. + * + * @param dccsct atsc_dccsct_section pointer. + * @param pos Variable containing a pointer to the current atsc_dccsct_update. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dccsct_section_updates_for_each(dccsct, pos, idx) \ +	for ((pos) = atsc_dccsct_section_updates_first(dccsct), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dccsct_section_updates_next(dccsct, pos, ++idx)) + +/** + * Accessor for the data field of a new genre atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_genre pointer. + */ +static inline struct atsc_dccsct_update_new_genre *atsc_dccsct_update_new_genre(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_GENRE) +		return NULL; + +	return (struct atsc_dccsct_update_new_genre *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_genre. + * + * @param update atsc_dccsct_update_new_genre pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_genre_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 1) == 0) +		return NULL; + +	return (struct atsc_text *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_genre)); +} + +/** + * Accessor for the data field of a new state atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_state pointer. + */ +static inline struct atsc_dccsct_update_new_state * +	atsc_dccsct_update_new_state(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_STATE) +		return NULL; + +	return (struct atsc_dccsct_update_new_state *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_state. + * + * @param update atsc_dccsct_update_new_state pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_state_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 1) == 0) +		return NULL; + +	return (struct atsc_text *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_state)); +} + +/** + * Accessor for the data field of a new county atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_update_new_county pointer. + */ +static inline struct atsc_dccsct_update_new_county * +	atsc_dccsct_update_new_county(struct atsc_dccsct_update *update) +{ +	if (update->update_type != ATSC_DCCST_UPDATE_NEW_COUNTY) +		return NULL; + +	return (struct atsc_dccsct_update_new_county *) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update)); +} + +/** + * Accessor for the name field of an atsc_dccsct_update_new_county. + * + * @param update atsc_dccsct_update_new_county pointer. + * @return text pointer. + */ +static inline struct atsc_text *atsc_dccsct_update_new_county_name(struct atsc_dccsct_update *update) +{ +	if ((update->update_data_length - 3) == 0) +		return NULL; + +	return (struct atsc_text*) +		(((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_county)); +} + +/** + * Accessor for the part2 field of an atsc_dccsct_update. + * + * @param update atsc_dccsct_update pointer. + * @return struct atsc_dccsct_test_part2 pointer. + */ +static inline struct atsc_dccsct_update_part2 *atsc_dccsct_update_part2(struct atsc_dccsct_update *update) +{ +	int pos = sizeof(struct atsc_dccsct_update); +	pos += update->update_data_length; + +	return (struct atsc_dccsct_update_part2 *) (((uint8_t*) update) + pos); +} + +/** + * Iterator for the descriptors field in an atsc_dccsct_update_part2 structure. + * + * @param part2 atsc_dccsct_update_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dccsct_update_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dccsct_update_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dccsct_update_part2_descriptors_next(part2, pos)) + +/** + * Iterator for the descriptors field in a atsc_dccsct_section_part2 structure. + * + * @param part2 atsc_dccsct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dccsct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dccsct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dccsct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_dccsct_update * +	atsc_dccsct_section_updates_first(struct atsc_dccsct_section *dccsct) +{ +	size_t pos = sizeof(struct atsc_dccsct_section); + +	if (dccsct->updates_defined == 0) +		return NULL; + +	return (struct atsc_dccsct_update*) (((uint8_t *) dccsct) + pos); +} + +static inline struct atsc_dccsct_update* +	atsc_dccsct_section_updates_next(struct atsc_dccsct_section *dccsct, +				         struct atsc_dccsct_update *pos, +				         int idx) +{ +	if (idx >= dccsct->updates_defined) +		return NULL; + +	struct atsc_dccsct_update_part2 *part2 = atsc_dccsct_update_part2(pos); +	int len = sizeof(struct atsc_dccsct_update_part2); +	len += part2->descriptors_length; + +	return (struct atsc_dccsct_update *) (((uint8_t*) part2) + len); +} + +static inline struct descriptor * +	atsc_dccsct_update_part2_descriptors_first(struct atsc_dccsct_update_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dccsct_update_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dccsct_update_part2_descriptors_next(struct atsc_dccsct_update_part2 *part2, +						  struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_update_part2), +				part2->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dccsct_section_part2_descriptors_first(struct atsc_dccsct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dccsct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dccsct_section_part2_descriptors_next(struct atsc_dccsct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_section_part2), +				part2->descriptors_length, +				pos); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/dcct_section.c b/lib/libucsi/atsc/dcct_section.c new file mode 100644 index 0000000..7d0b83b --- /dev/null +++ b/lib/libucsi/atsc/dcct_section.c @@ -0,0 +1,96 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/dcct_section.h> + +struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int testidx; +	int termidx; + +	if (len < sizeof(struct atsc_dcct_section)) +		return NULL; +	struct atsc_dcct_section *dcct = (struct atsc_dcct_section *) psip; + +	pos += sizeof(struct atsc_dcct_section); +	for(testidx =0; testidx < dcct->dcc_test_count; testidx++) { +		if (len < (pos + sizeof(struct atsc_dcct_test))) +			return NULL; +		struct atsc_dcct_test *test = (struct atsc_dcct_test *) (buf+pos); + +		bswap24(buf+pos); +		bswap24(buf+pos+3); +		bswap32(buf+pos+6); +		bswap32(buf+pos+10); + +		pos += sizeof(struct atsc_dcct_test); +		for(termidx =0; termidx < test->dcc_term_count; termidx++) { +			if (len < (pos + sizeof(struct atsc_dcct_term))) +				return NULL; +			struct atsc_dcct_term *term = (struct atsc_dcct_term *) (buf+pos); + +			bswap64(buf+pos+1); +			bswap16(buf+pos+9); + +			pos += sizeof(struct atsc_dcct_term); +			if (len < (pos + term->descriptors_length)) +				return NULL; +			if (verify_descriptors(buf + pos, term->descriptors_length)) +				return NULL; + +			pos += term->descriptors_length; +		} + +		if (len < (pos + sizeof(struct atsc_dcct_test_part2))) +			return NULL; +		struct atsc_dcct_test_part2 *part2 = (struct atsc_dcct_test_part2 *) (buf+pos); + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_dcct_test_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; +		pos += part2->descriptors_length; +	} + +	if (len < (pos + sizeof(struct atsc_dcct_section_part2))) +		return NULL; +	struct atsc_dcct_section_part2 *part2 = (struct atsc_dcct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_dcct_section_part2); +	if (len < (pos + part2->descriptors_length)) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_dcct_section *) psip; +} diff --git a/lib/libucsi/atsc/dcct_section.h b/lib/libucsi/atsc/dcct_section.h new file mode 100644 index 0000000..647bd4b --- /dev/null +++ b/lib/libucsi/atsc/dcct_section.h @@ -0,0 +1,380 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_DCCT_SECTION_H +#define _UCSI_ATSC_DCCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +enum atsc_dcc_context { +	ATSC_DCC_CONTEXT_TEMPORARY_RETUNE = 0, +	ATSC_DCC_CONTEXT_CHANNEL_REDIRECT = 1, +}; + +enum atsc_dcc_selection_type { +	ATSC_DCC_SELECTION_UNCONDITIONAL_CHANNEL_CHANGE = 0x00, +	ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_INCLUSION = 0x01, +	ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_INCLUSION = 0x02, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ONE_OR_MORE = 0x05, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ALL = 0x06, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_ONE_OR_MORE = 0x07, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_ALL = 0x08, +	ATSC_DCC_SELECTION_CANNOT_BE_AUTHORIZED = 0x09, +	ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_INCLUSION = 0x0c, +	ATSC_DCC_SELECTION_RATING_BLOCKED = 0x0d, +	ATSC_DCC_SELECTION_RETURN_TO_ORIGINAL_CHANNEL = 0x0f, +	ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_EXCLUSION = 0x11, +	ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_EXCLUSION = 0x12, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ONE_OR_MORE = 0x15, +	ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ALL = 0x16, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ONE_OR_MORE = 0x17, +	ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ALL = 0x18, +	ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_EXCLUSION = 0x1c, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_A = 0x20, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_B = 0x21, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_C = 0x22, +	ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_D = 0x23, +}; + +/** + * atsc_dcct_section structure. + */ +struct atsc_dcct_section { +	struct atsc_section_psip head; + +	uint8_t dcc_test_count; +	/* struct atsc_dcct_test tests */ +	/* struct atsc_dcct_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_dcct_test { +  EBIT4(uint32_t dcc_context			: 1; , +	uint32_t reserved			: 3; , +	uint32_t dcc_from_major_channel_number	:10; , +	uint32_t dcc_from_minor_channel_number	:10; ); +  EBIT3(uint32_t reserved1			: 4; , +	uint32_t dcc_to_major_channel_number	:10; , +	uint32_t dcc_to_minor_channel_number	:10; ); +	atsctime_t start_time; +	atsctime_t end_time; +	uint8_t dcc_term_count; +	/* struct atsc_dcct_term terms */ +	/* struct atsc_dcct_test_part2 part2 */ +} __ucsi_packed; + +struct atsc_dcct_term { +	uint8_t dcc_selection_type; +	uint64_t dcc_selection_id; +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dcct_test_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_dcct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct); +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct, +				     struct atsc_dcct_test *pos, +				     int idx); +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_first(struct atsc_dcct_test *test); +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_next(struct atsc_dcct_test *test, +				  struct atsc_dcct_term *pos, +				  int idx); + + +/** + * Process an atsc_dcct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_dcct_section pointer, or NULL on error. + */ +struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the dcc_subtype field of a dcct. + * + * @param dcct dcct pointer. + * @return The dcc_subtype. + */ +static inline uint8_t atsc_dcct_section_dcc_subtype(struct atsc_dcct_section *dcct) +{ +	return dcct->head.ext_head.table_id_ext >> 8; +} + +/** + * Accessor for the dcc_id field of a dcct. + * + * @param dcct dcct pointer. + * @return The dcc_id. + */ +static inline uint8_t atsc_dcct_section_dcc_id(struct atsc_dcct_section *dcct) +{ +	return dcct->head.ext_head.table_id_ext & 0xff; +} + +/** + * Iterator for the tests field in an atsc_dcct_section. + * + * @param dcct atsc_dcct_section pointer. + * @param pos Variable containing a pointer to the current atsc_dcct_test. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dcct_section_tests_for_each(dcct, pos, idx) \ +	for ((pos) = atsc_dcct_section_tests_first(dcct), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dcct_section_tests_next(dcct, pos, ++idx)) + +/** + * Iterator for the terms field in an atsc_dcct_test. + * + * @param test atsc_dcct_test pointer. + * @param pos Variable containing a pointer to the current atsc_dcct_term. + * @param idx Integer used to count which test we are in. + */ +#define atsc_dcct_test_terms_for_each(test, pos, idx) \ +	for ((pos) = atsc_dcct_test_terms_first(test), idx=0; \ +	     (pos); \ +	     (pos) = atsc_dcct_test_terms_next(test, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_dcct_term structure. + * + * @param term atsc_dcct_term pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_term_descriptors_for_each(term, pos) \ +	for ((pos) = atsc_dcct_term_descriptors_first(term); \ +	     (pos); \ +	     (pos) = atsc_dcct_term_descriptors_next(term, pos)) + +/** + * Accessor for the part2 field of an atsc_dcct_test. + * + * @param test atsc_dcct_test pointer. + * @return struct atsc_dcct_test_part2 pointer. + */ +static inline struct atsc_dcct_test_part2 *atsc_dcct_test_part2(struct atsc_dcct_test *test) +{ +	int pos = sizeof(struct atsc_dcct_test); + +	struct atsc_dcct_term *cur_term; +	int idx; +	atsc_dcct_test_terms_for_each(test, cur_term, idx) { +		pos += sizeof(struct atsc_dcct_term); +		pos += cur_term->descriptors_length; +	} + +	return (struct atsc_dcct_test_part2 *) (((uint8_t*) test) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_dcct_test_part2 structure. + * + * @param term atsc_dcct_test_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_test_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dcct_test_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dcct_test_part2_descriptors_next(part2, pos)) + +/** + * Accessor for the part2 field of an atsc_dcct_section. + * + * @param dcct atsc_dcct_section pointer. + * @return struct atsc_dcct_section_part2 pointer. + */ +static inline struct atsc_dcct_section_part2 *atsc_dcct_section_part2(struct atsc_dcct_section *dcct) +{ +	int pos = sizeof(struct atsc_dcct_section); + +	struct atsc_dcct_test *cur_test; +	int testidx; +	atsc_dcct_section_tests_for_each(dcct, cur_test, testidx) { +		struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(cur_test); +		pos += ((uint8_t*) part2 - (uint8_t*) cur_test); + +		pos += sizeof(struct atsc_dcct_test_part2); +		pos += part2->descriptors_length; +	} + +	return (struct atsc_dcct_section_part2 *) (((uint8_t*) dcct) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_dcct_section_part2 structure. + * + * @param part2 atsc_dcct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_dcct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_dcct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_dcct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct) +{ +	size_t pos = sizeof(struct atsc_dcct_section); + +	if (dcct->dcc_test_count == 0) +		return NULL; + +	return (struct atsc_dcct_test*) (((uint8_t *) dcct) + pos); +} + +static inline struct atsc_dcct_test * +	atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct, +				     struct atsc_dcct_test *pos, +				     int idx) +{ +	if (idx >= dcct->dcc_test_count) +		return NULL; + +	struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(pos); +	int len = sizeof(struct atsc_dcct_test_part2); +	len += part2->descriptors_length; + +	return (struct atsc_dcct_test *) (((uint8_t*) part2) + len); +} + +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_first(struct atsc_dcct_test *test) +{ +	size_t pos = sizeof(struct atsc_dcct_test); + +	if (test->dcc_term_count == 0) +		return NULL; + +	return (struct atsc_dcct_term*) (((uint8_t *) test) + pos); +} + +static inline struct atsc_dcct_term * +	atsc_dcct_test_terms_next(struct atsc_dcct_test *test, +				  struct atsc_dcct_term *pos, +				  int idx) +{ +	if (idx >= test->dcc_term_count) +		return NULL; + +	int len = sizeof(struct atsc_dcct_term); +	len += pos->descriptors_length; + +	return (struct atsc_dcct_term *) (((uint8_t*) pos) + len); +} + +static inline struct descriptor * +	atsc_dcct_term_descriptors_first(struct atsc_dcct_term *term) +{ +	size_t pos = sizeof(struct atsc_dcct_term); + +	if (term->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) term) + pos); +} + +static inline struct descriptor * +	atsc_dcct_term_descriptors_next(struct atsc_dcct_term *term, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) term + sizeof(struct atsc_dcct_term), +				term->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dcct_test_part2_descriptors_first(struct atsc_dcct_test_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dcct_test_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dcct_test_part2_descriptors_next(struct atsc_dcct_test_part2 *part2, +					      struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_test_part2), +				part2->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_dcct_section_part2_descriptors_first(struct atsc_dcct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_dcct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_dcct_section_part2_descriptors_next(struct atsc_dcct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_section_part2), +				part2->descriptors_length, +				pos); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/descriptor.h b/lib/libucsi/atsc/descriptor.h new file mode 100644 index 0000000..a57176a --- /dev/null +++ b/lib/libucsi/atsc/descriptor.h @@ -0,0 +1,68 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_DESCRIPTOR_H +#define _UCSI_ATSC_DESCRIPTOR_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/endianops.h> +#include <libucsi/atsc/stuffing_descriptor.h> +#include <libucsi/atsc/ac3_descriptor.h> +#include <libucsi/atsc/caption_service_descriptor.h> +#include <libucsi/atsc/component_name_descriptor.h> +#include <libucsi/atsc/content_advisory_descriptor.h> +#include <libucsi/atsc/dcc_arriving_request_descriptor.h> +#include <libucsi/atsc/dcc_departing_request_descriptor.h> +#include <libucsi/atsc/extended_channel_name_descriptor.h> +#include <libucsi/atsc/genre_descriptor.h> +#include <libucsi/atsc/rc_descriptor.h> +#include <libucsi/atsc/service_location_descriptor.h> +#include <libucsi/atsc/time_shifted_service_descriptor.h> + +/** + * Enumeration of ATSC descriptor tags. + */ +enum atsc_descriptor_tag { +	dtag_atsc_stuffing			= 0x80, +	dtag_atsc_ac3_audio			= 0x81, +	dtag_atsc_caption_service		= 0x86, +	dtag_atsc_content_advisory		= 0x87, +	dtag_atsc_extended_channel_name		= 0xa0, +	dtag_atsc_service_location		= 0xa1, +	dtag_atsc_time_shifted_service		= 0xa2, +	dtag_atsc_component_name		= 0xa3, +	dtag_atsc_dcc_departing_request		= 0xa8, +	dtag_atsc_dcc_arriving_request		= 0xa9, +	dtag_atsc_redistribution_control	= 0xaa, +	dtag_atsc_private_information		= 0xad, +	dtag_atsc_content_identifier		= 0xb6, +	dtag_atsc_genre				= 0xab, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/eit_section.c b/lib/libucsi/atsc/eit_section.c new file mode 100644 index 0000000..48cdda6 --- /dev/null +++ b/lib/libucsi/atsc/eit_section.c @@ -0,0 +1,71 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/eit_section.h> + +struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; + +	if (len < sizeof(struct atsc_eit_section)) +		return NULL; +	struct atsc_eit_section *eit = (struct atsc_eit_section *) psip; + +	pos += sizeof(struct atsc_eit_section); +	for(idx =0; idx < eit->num_events_in_section; idx++) { +		if (len < (pos + sizeof(struct atsc_eit_event))) +			return NULL; +		struct atsc_eit_event *event = (struct atsc_eit_event *) (buf+pos); + +		bswap16(buf+pos); +		bswap32(buf+pos+2); +		bswap32(buf+pos+6); + +		pos += sizeof(struct atsc_eit_event); +		if (len < (pos + event->title_length)) +			return NULL; +		if (atsc_text_validate(buf+pos, event->title_length)) +			return NULL; + +		pos += event->title_length; +		if (len < (pos + sizeof(struct atsc_eit_event_part2))) +			return NULL; +		struct atsc_eit_event_part2 *part2 = (struct atsc_eit_event_part2 *) (buf+pos); + +		bswap16(buf+pos); + +		pos += sizeof(struct atsc_eit_event_part2); +		if (len < (pos + part2->descriptors_length)) +			return NULL; + +		if (verify_descriptors(buf + pos, part2->descriptors_length)) +			return NULL; +		pos += part2->descriptors_length; +	} + +	if (pos != len) +		return NULL; + +	return (struct atsc_eit_section *) psip; +} diff --git a/lib/libucsi/atsc/eit_section.h b/lib/libucsi/atsc/eit_section.h new file mode 100644 index 0000000..84bef16 --- /dev/null +++ b/lib/libucsi/atsc/eit_section.h @@ -0,0 +1,191 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_EIT_SECTION_H +#define _UCSI_ATSC_EIT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_eit_section structure. + */ +struct atsc_eit_section { +	struct atsc_section_psip head; + +	uint8_t num_events_in_section; +	/* struct atsc_eit_event events[] */ +} __ucsi_packed; + +struct atsc_eit_event { +  EBIT2(uint16_t reserved			: 2; , +	uint16_t event_id			:14; ); +	atsctime_t start_time; +  EBIT4(uint32_t reserved1			: 2; , +	uint32_t ETM_location			: 2; , +	uint32_t length_in_seconds		:20; , +	uint32_t title_length			: 8; ); +	/* struct atsc_text title_text */ +	/* struct atsc_eit_event_part2 part2 */ +} __ucsi_packed; + +struct atsc_eit_event_part2 { +  EBIT2(uint16_t reserved			: 4; , +	uint16_t descriptors_length		:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + + +/** + * Process a atsc_eit_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_eit_section pointer, or NULL on error. + */ +struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the source_id field of an EIT. + * + * @param eit EIT pointer. + * @return The source_id . + */ +static inline uint16_t atsc_eit_section_source_id(struct atsc_eit_section *eit) +{ +	return eit->head.ext_head.table_id_ext; +} + +/** + * Iterator for the events field in an atsc_eit_section. + * + * @param eit atsc_eit_section pointer. + * @param pos Variable containing a pointer to the current atsc_eit_event. + * @param idx Integer used to count which event we are in. + */ +#define atsc_eit_section_events_for_each(eit, pos, idx) \ +	for ((pos) = atsc_eit_section_events_first(eit), idx=0; \ +	     (pos); \ +	     (pos) = atsc_eit_section_events_next(eit, pos, ++idx)) + +/** + * Accessor for the title_text field of an atsc_eit_event. + * + * @param event atsc_eit_event pointer. + * @return struct atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text *atsc_eit_event_name_title_text(struct atsc_eit_event *event) +{ +	if (event->title_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) event) + sizeof(struct atsc_eit_event)); +} + +/** + * Accessor for the part2 field of an atsc_eit_event. + * + * @param event atsc_eit_event pointer. + * @return struct atsc_eit_event_part2 pointer. + */ +static inline struct atsc_eit_event_part2 *atsc_eit_event_part2(struct atsc_eit_event *event) +{ +	return (struct atsc_eit_event_part2 *) +		(((uint8_t*) event) + sizeof(struct atsc_eit_event) + event->title_length); +} + +/** + * Iterator for the descriptors field in a atsc_eit_section structure. + * + * @param part2 atsc_eit_event_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_eit_event_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_eit_event_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_eit_event_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_eit_event * +	atsc_eit_section_events_first(struct atsc_eit_section *eit) +{ +	size_t pos = sizeof(struct atsc_eit_section); + +	if (eit->num_events_in_section == 0) +		return NULL; + +	return (struct atsc_eit_event*) (((uint8_t *) eit) + pos); +} + +static inline struct atsc_eit_event * +	atsc_eit_section_events_next(struct atsc_eit_section *eit, +				     struct atsc_eit_event *pos, +				     int idx) +{ +	if (idx >= eit->num_events_in_section) +		return NULL; + +	struct atsc_eit_event_part2 *part2 = atsc_eit_event_part2(pos); +	int len = sizeof(struct atsc_eit_event_part2); +	len += part2->descriptors_length; + +	return (struct atsc_eit_event *) (((uint8_t*) part2) + len); +} + +static inline struct descriptor * +	atsc_eit_event_part2_descriptors_first(struct atsc_eit_event_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_eit_event_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_eit_event_part2_descriptors_next(struct atsc_eit_event_part2 *part2, +					      struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_eit_event_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/ett_section.c b/lib/libucsi/atsc/ett_section.c new file mode 100644 index 0000000..ab2ff9c --- /dev/null +++ b/lib/libucsi/atsc/ett_section.c @@ -0,0 +1,42 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/ett_section.h> +#include <libucsi/atsc/types.h> + +struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); + +	if (len < sizeof(struct atsc_ett_section)) +		return NULL; + +	bswap32(buf + pos); +	pos += 4; + +	if (atsc_text_validate(buf + pos, +	    		       section_ext_length(&psip->ext_head) - sizeof(struct atsc_ett_section))) +		return NULL; + +	return (struct atsc_ett_section *) psip; +} diff --git a/lib/libucsi/atsc/ett_section.h b/lib/libucsi/atsc/ett_section.h new file mode 100644 index 0000000..e2bb510 --- /dev/null +++ b/lib/libucsi/atsc/ett_section.h @@ -0,0 +1,91 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_ETT_SECTION_H +#define _UCSI_ATSC_ETT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +enum atsc_etm_type { +	ATSC_ETM_CHANNEL 	= 0x00, +	ATSC_ETM_EVENT 		= 0x02, +}; + +/** + * atsc_ett_section structure. + */ +struct atsc_ett_section { +	struct atsc_section_psip head; + +  EBIT3(uint32_t ETM_source_id			:16; , +	uint32_t ETM_sub_id			:14; , +	uint32_t ETM_type			: 2; ); +	/* struct atsc_text extended_text_message */ +} __ucsi_packed; + +/** + * Process a atsc_ett_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_ett_section pointer, or NULL on error. + */ +struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the extended_text_message part of an atsc_ett_section. + * + * @param ett atsc_ett_section pointer. + * @return atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text* +	atsc_ett_section_extended_text_message(struct atsc_ett_section *ett) +{ +	int pos = sizeof(struct atsc_ett_section); +	int len = section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section); + +	if (len == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) ett) + pos); +} + +/** + * Accessor for the extended_text_message part of an atsc_ett_section. + * + * @param ett atsc_ett_section pointer. + * @return The length. + */ +static inline int +	atsc_ett_section_extended_text_message_length(struct atsc_ett_section *ett) +{ +	return section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/extended_channel_name_descriptor.h b/lib/libucsi/atsc/extended_channel_name_descriptor.h new file mode 100644 index 0000000..d0b714b --- /dev/null +++ b/lib/libucsi/atsc/extended_channel_name_descriptor.h @@ -0,0 +1,92 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR +#define _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_extended_channel_name_descriptor structure. + */ +struct atsc_extended_channel_name_descriptor { +	struct descriptor d; + +	/* struct atsc_text text[] */ +} __ucsi_packed; + +/** + * Process an atsc_extended_channel_name_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_extended_channel_name_descriptor pointer, or NULL on error. + */ +static inline struct atsc_extended_channel_name_descriptor* +	atsc_extended_channel_name_descriptor_codec(struct descriptor* d) +{ +	if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor), +	    		       d->len)) +		return NULL; + +	return (struct atsc_extended_channel_name_descriptor*) d; +} + +/** + * Accessor for the text field of an atsc_extended_channel_name_descriptor. + * + * @param d atsc_extended_channel_name_descriptor pointer. + * @return Pointer to the atsc_text data, or NULL on error. + */ +static inline struct atsc_text* +	atsc_extended_channel_name_descriptor_text(struct atsc_extended_channel_name_descriptor *d) +{ +	uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor); + +	return (struct atsc_text*) txt; +} + +/** + * Accessor for the length of the text field of an atsc_extended_channel_name_descriptor. + * + * @param d atsc_extended_channel_name_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_extended_channel_name_descriptor_text_length(struct +							atsc_extended_channel_name_descriptor *d) +{ +	return d->d.len; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/genre_descriptor.h b/lib/libucsi/atsc/genre_descriptor.h new file mode 100644 index 0000000..a6fc542 --- /dev/null +++ b/lib/libucsi/atsc/genre_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_GENRE_DESCRIPTOR +#define _UCSI_ATSC_GENRE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_genre_descriptor structure. + */ +struct atsc_genre_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t attribute_count		: 5; ); +	/* uint8_t attributes[] */ +} __ucsi_packed; + +/** + * Process an atsc_genre_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_genre_descriptor pointer, or NULL on error. + */ +static inline struct atsc_genre_descriptor* +	atsc_genre_descriptor_codec(struct descriptor* d) +{ +	struct atsc_genre_descriptor *ret = +		(struct atsc_genre_descriptor *) d; + +	if (d->len < 1) +		return NULL; + +	if (d->len != (1 + ret->attribute_count)) +		return NULL; + +	return (struct atsc_genre_descriptor*) d; +} + +/** + * Accessor for the attributes field of an atsc_genre_descriptor. + * + * @param d atsc_genre_descriptor pointer. + * @return Pointer to the attributes. + */ +static inline uint8_t* +	atsc_genre_descriptor_attributes(struct atsc_genre_descriptor *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_genre_descriptor); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/mgt_section.c b/lib/libucsi/atsc/mgt_section.c new file mode 100644 index 0000000..bc6b3f2 --- /dev/null +++ b/lib/libucsi/atsc/mgt_section.c @@ -0,0 +1,76 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/mgt_section.h> + +struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	struct atsc_mgt_section *mgt = (struct atsc_mgt_section *) psip; +	int i; + +	if (len < sizeof(struct atsc_mgt_section)) +		return NULL; + +	bswap16(buf + pos); +	pos += 2; + +	// we cannot use the tables_defined value here because of the braindead ATSC spec! +	for(i=0; i < mgt->tables_defined; i++) { +		// we think we're still in the tables - process as normal +		if ((pos + sizeof(struct atsc_mgt_table)) > len) +			return NULL; +		struct atsc_mgt_table *table = (struct atsc_mgt_table *) (buf+pos); + +		bswap16(buf+pos); +		bswap16(buf+pos+2); +		bswap32(buf+pos+5); +		bswap16(buf+pos+9); + +		pos += sizeof(struct atsc_mgt_table); +		if ((pos + table->table_type_descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, table->table_type_descriptors_length)) +			return NULL; + +		pos += table->table_type_descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_mgt_section_part2)) > len) +		return NULL; +	struct atsc_mgt_section_part2 *part2 = (struct atsc_mgt_section_part2 *) (buf+pos); + +	bswap16(buf+pos); + +	pos += sizeof(struct atsc_mgt_section_part2); +	if ((pos + part2->descriptors_length) > len) +		return NULL; +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; +	pos += part2->descriptors_length; + +	if (pos != len) +		return NULL; + +	return (struct atsc_mgt_section *) psip; +} diff --git a/lib/libucsi/atsc/mgt_section.h b/lib/libucsi/atsc/mgt_section.h new file mode 100644 index 0000000..3102a54 --- /dev/null +++ b/lib/libucsi/atsc/mgt_section.h @@ -0,0 +1,215 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_MGT_SECTION_H +#define _UCSI_ATSC_MGT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +enum atsc_mgt_section_table_type { +	ATSC_MGT_TABLE_TYPE_TVCT_CURRENT = 0, +	ATSC_MGT_TABLE_TYPE_TVCT_NEXT = 1, +	ATSC_MGT_TABLE_TYPE_CVCT_CURRENT = 2, +	ATSC_MGT_TABLE_TYPE_CVCT_NEXT = 3, +	ATSC_MGT_TABLE_TYPE_CHANNEL_ETT = 4, +	ATSC_MGT_TABLE_TYPE_DCCSCT = 5, +}; + +/** + * atsc_mgt_section structure. + */ +struct atsc_mgt_section { +	struct atsc_section_psip head; + +	uint16_t tables_defined; +	/* struct atsc_mgt_table tables[] */ +	/* struct atsc_mgt_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_mgt_table { +	uint16_t table_type; +  EBIT2(uint16_t reserved			: 3; , +	uint16_t table_type_PID			:13; ); +  EBIT2(uint8_t reserved1			: 3; , +	uint8_t table_type_version_number	: 5; ); +	uint32_t number_bytes; +  EBIT2(uint16_t reserved2			: 4; , +	uint16_t table_type_descriptors_length	:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_mgt_section_part2 { +  EBIT2(uint16_t reserved			: 4; , +	uint16_t descriptors_length		:12; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_mgt_table * atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt); +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt, struct atsc_mgt_table *pos, int idx); + +/** + * Process a atsc_mgt_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_mgt_section pointer, or NULL on error. + */ +struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *section); + +/** + * Iterator for the tables field in an atsc_mgt_section. + * + * @param mgt atsc_mgt_section pointer. + * @param pos Variable containing a pointer to the current atsc_mgt_table. + * @param idx Integer used to count which table we in. + */ +#define atsc_mgt_section_tables_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_mgt_section_tables_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_mgt_section_tables_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_mgt_table structure. + * + * @param table atsc_mgt_table pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_mgt_table_descriptors_for_each(table, pos) \ +	for ((pos) = atsc_mgt_table_descriptors_first(table); \ +	     (pos); \ +	     (pos) = atsc_mgt_table_descriptors_next(table, pos)) + +/** + * Accessor for the second part of an atsc_mgt_section. + * + * @param mgt atsc_mgt_section pointer. + * @return atsc_mgt_section_part2 pointer. + */ +static inline struct atsc_mgt_section_part2 * +	atsc_mgt_section_part2(struct atsc_mgt_section *mgt) +{ +	int pos = sizeof(struct atsc_mgt_section); + +	struct atsc_mgt_table *cur_table; +	int idx; +	atsc_mgt_section_tables_for_each(mgt, cur_table, idx) { +		pos += sizeof(struct atsc_mgt_table); +		pos += cur_table->table_type_descriptors_length; +	} + +	return (struct atsc_mgt_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_mgt_section structure. + * + * @param part2 atsc_mgt_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_mgt_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_mgt_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_mgt_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt) +{ +	size_t pos = sizeof(struct atsc_mgt_section); + +	if (mgt->tables_defined == 0) +		return NULL; + +	return (struct atsc_mgt_table*) (((uint8_t *) mgt) + pos); +} + +static inline struct atsc_mgt_table * +	atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt, +				     struct atsc_mgt_table *pos, +				     int idx) +{ +	if (idx >= mgt->tables_defined) +		return NULL; + +	return (struct atsc_mgt_table *) +		(((uint8_t*) pos) + sizeof(struct atsc_mgt_table) + pos->table_type_descriptors_length); +} + +static inline struct descriptor * +	atsc_mgt_table_descriptors_first(struct atsc_mgt_table *table) +{ +	size_t pos = sizeof(struct atsc_mgt_table); + +	if (table->table_type_descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) table) + pos); +} + +static inline struct descriptor * +	atsc_mgt_table_descriptors_next(struct atsc_mgt_table *table, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) table + sizeof(struct atsc_mgt_table), +				table->table_type_descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_mgt_section_part2_descriptors_first(struct atsc_mgt_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_mgt_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_mgt_section_part2_descriptors_next(struct atsc_mgt_section_part2 *part2, +						struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_mgt_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/rc_descriptor.h b/lib/libucsi/atsc/rc_descriptor.h new file mode 100644 index 0000000..4fb0e8e --- /dev/null +++ b/lib/libucsi/atsc/rc_descriptor.h @@ -0,0 +1,83 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_RC_DESCRIPTOR +#define _UCSI_ATSC_RC_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_rc_descriptor structure. + */ +struct atsc_rc_descriptor { +	struct descriptor d; + +	/* uint8_t info[] */ +} __ucsi_packed; + +/** + * Process an atsc_rc_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_rc_descriptor pointer, or NULL on error. + */ +static inline struct atsc_rc_descriptor* +	atsc_rc_descriptor_codec(struct descriptor* d) +{ +	return (struct atsc_rc_descriptor*) d; +} + +/** + * Accessor for the info field of an atsc_rc_descriptor. + * + * @param d atsc_rc_descriptor pointer. + * @return Pointer to the atsc_text data. + */ +static inline uint8_t* +	atsc_rc_descriptor_info(struct atsc_rc_descriptor *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_rc_descriptor); +} + +/** + * Accessor for the length of the info field of an atsc_rc_descriptor. + * + * @param d atsc_rc_descriptor pointer. + * @return The length + */ +static inline int +	atsc_rc_descriptor_info_length(struct atsc_rc_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/rrt_section.c b/lib/libucsi/atsc/rrt_section.c new file mode 100644 index 0000000..6e96c3a --- /dev/null +++ b/lib/libucsi/atsc/rrt_section.c @@ -0,0 +1,108 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/rrt_section.h> + +struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = 0; +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; +	int vidx; +	struct atsc_rrt_section *rrt = (struct atsc_rrt_section *) psip; + +	if (len < sizeof(struct atsc_rrt_section)) +		return NULL; +	pos += sizeof(struct atsc_rrt_section); + +	if (len < (pos + rrt->rating_region_name_length)) +		return NULL; +	if (atsc_text_validate(buf+pos, rrt->rating_region_name_length)) +		return NULL; + +	pos += rrt->rating_region_name_length; +	if (len < (pos + sizeof(struct atsc_rrt_section_part2))) +		return NULL; +	struct atsc_rrt_section_part2 *rrtpart2 = (struct atsc_rrt_section_part2 *) (buf+pos); + +	pos += sizeof(struct atsc_rrt_section_part2); +	for(idx =0; idx < rrtpart2->dimensions_defined; idx++) { +		if (len < (pos + sizeof(struct atsc_rrt_dimension))) +			return NULL; +		struct atsc_rrt_dimension *dimension = (struct atsc_rrt_dimension *) (buf+pos); + +		pos += sizeof(struct atsc_rrt_dimension); +		if (len < (pos + dimension->dimension_name_length)) +			return NULL; +		if (atsc_text_validate(buf+pos, dimension->dimension_name_length)) +			return NULL; + +		pos += dimension->dimension_name_length; +		if (len < (pos + sizeof(struct atsc_rrt_dimension_part2))) +			return NULL; +		struct atsc_rrt_dimension_part2 *dpart2 = (struct atsc_rrt_dimension_part2 *) (buf+pos); + +		pos += sizeof(struct atsc_rrt_dimension_part2); +		for(vidx =0; vidx < dpart2->values_defined; vidx++) { +			if (len < (pos + sizeof(struct atsc_rrt_dimension_value))) +				return NULL; +			struct atsc_rrt_dimension_value *value = (struct atsc_rrt_dimension_value *) (buf+pos); + +			pos += sizeof(struct atsc_rrt_dimension_value); +			if (len < (pos + value->abbrev_rating_value_length)) +				return NULL; +			if (atsc_text_validate(buf+pos, value->abbrev_rating_value_length)) +				return NULL; + +			pos += value->abbrev_rating_value_length; +			if (len < (pos + sizeof(struct atsc_rrt_dimension_value_part2))) +				return NULL; +			struct atsc_rrt_dimension_value_part2 *vpart2 = +				(struct atsc_rrt_dimension_value_part2 *) (buf+pos); + +			pos += sizeof(struct atsc_rrt_dimension_value_part2); +			if (len < (pos + vpart2->rating_value_length)) +				return NULL; +			if (atsc_text_validate(buf+pos, vpart2->rating_value_length)) +				return NULL; + +			pos+= vpart2->rating_value_length; +		} +	} + +	if (len < (pos + sizeof(struct atsc_rrt_section_part3))) +		return NULL; +	struct atsc_rrt_section_part3 *part3 = (struct atsc_rrt_section_part3 *) (buf+pos); + +	pos += sizeof(struct atsc_rrt_section_part3); +	if (len < (pos + part3->descriptors_length)) +		return NULL; + +	if (verify_descriptors(buf + pos, part3->descriptors_length)) +		return NULL; + +	pos += part3->descriptors_length; +	if (pos != len) +		return NULL; + +	return (struct atsc_rrt_section *) psip; +} diff --git a/lib/libucsi/atsc/rrt_section.h b/lib/libucsi/atsc/rrt_section.h new file mode 100644 index 0000000..fba4596 --- /dev/null +++ b/lib/libucsi/atsc/rrt_section.h @@ -0,0 +1,379 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_RRT_SECTION_H +#define _UCSI_ATSC_RRT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_rrt_section structure. + */ +struct atsc_rrt_section { +	struct atsc_section_psip head; + +	uint8_t rating_region_name_length; +	/* struct atsc_text rating_region_name_text */ +	/* struct atsc_rrt_section_part2 part2 */ +} __ucsi_packed; + +struct atsc_rrt_section_part2 { +	uint8_t dimensions_defined; +	/* struct atsc_rrt_dimension dimensions[] */ +	/* struct atsc_rrt_section_part3 part3 */ +} __ucsi_packed; + +struct atsc_rrt_dimension { +	uint8_t dimension_name_length; +	/* struct atsc_text dimension_name_text */ +	/* struct atsc_rrt_dimension_part2 part2 */ +} __ucsi_packed; + +struct atsc_rrt_dimension_part2 { +  EBIT3(uint8_t reserved			: 3; , +	uint8_t graduated_scale			: 1; , +	uint8_t values_defined			: 4; ); +	/* struct atsc_rrt_dimension_value values[] */ +} __ucsi_packed; + +struct atsc_rrt_dimension_value { +	uint8_t abbrev_rating_value_length; +	/* struct atsc_text abbrev_rating_value_text */ +	/* struct atsc_rrt_dimension_value_part2 */ +} __ucsi_packed; + +struct atsc_rrt_dimension_value_part2 { +	uint8_t rating_value_length; +	/* struct atsc_text rating_value_text */ +} __ucsi_packed; + +struct atsc_rrt_section_part3 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + + +static inline struct atsc_rrt_dimension * +		atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2); +static inline struct atsc_rrt_dimension * +		atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2, +		struct atsc_rrt_dimension *pos, +		int idx); +static inline struct atsc_rrt_dimension_value * +		atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2); +static inline struct atsc_rrt_dimension_value * +		atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2, +		struct atsc_rrt_dimension_value *pos, +		int idx); + +/** + * Process a atsc_rrt_section. + * + * @param section Pointer to anj atsc_section_psip structure. + * @return atsc_rrt_section pointer, or NULL on error. + */ +struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the rating_region field of an RRT. + * + * @param rrt RRT pointer. + * @return The transport_stream_id. + */ +static inline uint8_t atsc_rrt_section_rating_region(struct atsc_rrt_section *rrt) +{ +	return rrt->head.ext_head.table_id_ext & 0xff; +} + +/** + * Accessor for the rating_region_name_text field of an RRT. + * + * @param rrt RRT pointer. + * @return struct atsc_text pointer, or NULL. + */ +static inline struct atsc_text *atsc_rrt_section_rating_region_name_text(struct atsc_rrt_section *rrt) +{ +	if (rrt->rating_region_name_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) rrt) + sizeof(struct atsc_rrt_section)); +} + +/** + * Accessor for the part2 field of an RRT. + * + * @param rrt RRT pointer. + * @return struct atsc_rrt_section_part2 pointer. + */ +static inline struct atsc_rrt_section_part2 *atsc_rrt_section_part2(struct atsc_rrt_section *rrt) +{ +	return (struct atsc_rrt_section_part2 *) +		(((uint8_t*) rrt) + sizeof(struct atsc_rrt_section) + +			rrt->rating_region_name_length); +} + +/** + * Iterator for the dimensions field in an atsc_rrt_section_part2. + * + * @param rrt atsc_rrt_section pointer. + * @param pos Variable containing a pointer to the current atsc_rrt_dimension. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_rrt_section_dimensions_for_each(rrt, pos, idx) \ +	for ((pos) = atsc_rrt_section_dimensions_first(rrt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_rrt_section_dimensions_next(rrt, pos, ++idx)) + +/** + * Accessor for the dimension_name_text field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_text pointer, or NULL on error. + */ +static inline struct atsc_text *atsc_rrt_dimension_name_text(struct atsc_rrt_dimension *dimension) +{ +	if (dimension->dimension_name_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) dimension) + sizeof(struct atsc_rrt_dimension)); +} + +/** + * Accessor for the part2 field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_rrt_dimension_part2 pointer. + */ +static inline struct atsc_rrt_dimension_part2 *atsc_rrt_dimension_part2(struct atsc_rrt_dimension *dimension) +{ +	return (struct atsc_rrt_dimension_part2 *) +			(((uint8_t*) dimension) + +			sizeof(struct atsc_rrt_dimension) + +			dimension->dimension_name_length); +} + +/** + * Iterator for the values field in a atsc_rrt_dimension_part2 structure. + * + * @param part2 atsc_rrt_dimension_part2 pointer. + * @param pos Variable containing a pointer to the current value. + * @param idx Integer used to count which value we are in + */ +#define atsc_rrt_dimension_part2_values_for_each(part2, pos, idx) \ +	for ((pos) = atsc_rrt_dimension_part2_values_first(part2), idx=0; \ +	     (pos); \ +	     (pos) = atsc_rrt_dimension_part2_values_next(part2, pos, ++idx)) + +/** + * Accessor for the dimension_name_text field of an atsc_rrt_dimension. + * + * @param dimension atsc_rrt_dimension pointer. + * @return struct atsc_text pointer. + */ +static inline struct atsc_text * +	atsc_rrt_dimension_value_abbrev_rating_value_text(struct atsc_rrt_dimension_value *value) +{ +	if (value->abbrev_rating_value_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) value) + sizeof(struct atsc_rrt_dimension_value)); +} + +/** + * Accessor for the part2 field of an atsc_rrt_dimension_value. + * + * @param value atsc_rrt_dimension_value pointer. + * @return struct atsc_rrt_dimension_value_part2 pointer. + */ +static inline struct atsc_rrt_dimension_value_part2 *atsc_rrt_dimension_value_part2(struct atsc_rrt_dimension_value *value) +{ +	return (struct atsc_rrt_dimension_value_part2 *) +		(((uint8_t*) value) + +		sizeof(struct atsc_rrt_dimension_value) + +		value->abbrev_rating_value_length); +} + +/** + * Accessor for the rating_value_text field of an atsc_rrt_dimension_value_part2. + * + * @param part2 atsc_rrt_dimension_value_part2 pointer. + * @return struct atsc_text pointer. + */ +static inline struct atsc_text *atsc_rrt_dimension_value_part2_rating_value_text(struct atsc_rrt_dimension_value_part2 *part2) +{ +	if (part2->rating_value_length == 0) +		return NULL; + +	return (struct atsc_text*)(((uint8_t*) part2) + sizeof(struct atsc_rrt_dimension_value_part2)); +} + +/** + * Accessor for the third part of an atsc_rrt_section. + * + * @param part2 atsc_rrt_section_part2 pointer. + * @return atsc_rrt_section_part3 pointer. + */ +static inline struct atsc_rrt_section_part3 * +	atsc_rrt_section_part3(struct atsc_rrt_section_part2 *part2) +{ +	int pos = sizeof(struct atsc_rrt_section_part2); + +	struct atsc_rrt_dimension *cur_dimension; +	int idx; +	atsc_rrt_section_dimensions_for_each(part2, cur_dimension, idx) { +		pos += sizeof(struct atsc_rrt_dimension); +		pos += cur_dimension->dimension_name_length; +		pos += sizeof(struct atsc_rrt_dimension_part2); + +		// now we need to iterate over the values. yuck +		struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(cur_dimension); +		struct atsc_rrt_dimension_value *cur_value; +		int vidx; +		atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) { +			pos += sizeof(struct atsc_rrt_dimension_value); +			pos += cur_value->abbrev_rating_value_length; + +			struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value); +			pos += sizeof(struct atsc_rrt_dimension_value_part2); +			pos += vpart2->rating_value_length; +		} +	} + +	return (struct atsc_rrt_section_part3 *) (((uint8_t*) part2) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_rrt_section structure. + * + * @param part3 atsc_rrt_section_part3 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_rrt_section_part3_descriptors_for_each(part3, pos) \ +	for ((pos) = atsc_rrt_section_part3_descriptors_first(part3); \ +	     (pos); \ +	     (pos) = atsc_rrt_section_part3_descriptors_next(part3, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_rrt_dimension * +	atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_rrt_section_part2); + +	if (part2->dimensions_defined == 0) +		return NULL; + +	return (struct atsc_rrt_dimension*) (((uint8_t *) part2) + pos); +} + +static inline struct atsc_rrt_dimension * +	atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2, +					 struct atsc_rrt_dimension *pos, +					 int idx) +{ +	if (idx >= part2->dimensions_defined) +		return NULL; + +	struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(pos); +	int len = sizeof(struct atsc_rrt_dimension_part2); + +	// now we need to iterate over the values. yuck +	struct atsc_rrt_dimension_value *cur_value; +	int vidx; +	atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) { +		len += sizeof(struct atsc_rrt_dimension_value); +		len += cur_value->abbrev_rating_value_length; + +		struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value); +		len += sizeof(struct atsc_rrt_dimension_value_part2); +		len += vpart2->rating_value_length; +	} + +	return (struct atsc_rrt_dimension *) (((uint8_t*) dpart2) + len); +} + +static inline struct atsc_rrt_dimension_value * +	atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_rrt_dimension_part2); + +	if (part2->values_defined == 0) +		return NULL; + +	return (struct atsc_rrt_dimension_value*) (((uint8_t *) part2) + pos); +} + +static inline struct atsc_rrt_dimension_value * +	atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2, +					     struct atsc_rrt_dimension_value *pos, +					     int idx) +{ +	if (idx >= part2->values_defined) +		return NULL; + +	struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(pos); +	int len = sizeof(struct atsc_rrt_dimension_value_part2); +	len += vpart2->rating_value_length; + +	return (struct atsc_rrt_dimension_value *) (((uint8_t*) vpart2) + len); +} + +static inline struct descriptor * +	atsc_rrt_section_part3_descriptors_first(struct atsc_rrt_section_part3 *part3) +{ +	size_t pos = sizeof(struct atsc_rrt_section_part3); + +	if (part3->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part3) + pos); +} + +static inline struct descriptor * +	atsc_rrt_section_part3_descriptors_next(struct atsc_rrt_section_part3 *part3, +						struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part3 + sizeof(struct atsc_rrt_section_part3), +				part3->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/section.h b/lib/libucsi/atsc/section.h new file mode 100644 index 0000000..23d59ea --- /dev/null +++ b/lib/libucsi/atsc/section.h @@ -0,0 +1,84 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/section.h> +#include <libucsi/atsc/mgt_section.h> +#include <libucsi/atsc/tvct_section.h> +#include <libucsi/atsc/cvct_section.h> +#include <libucsi/atsc/rrt_section.h> +#include <libucsi/atsc/eit_section.h> +#include <libucsi/atsc/ett_section.h> +#include <libucsi/atsc/stt_section.h> +#include <libucsi/atsc/dcct_section.h> +#include <libucsi/atsc/dccsct_section.h> + +#ifndef _UCSI_ATSC_SECTION_H +#define _UCSI_ATSC_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ATSC_BASE_PID 0x1ffb + +/** + * Enumeration of ATSC section tags. + */ +enum atsc_section_tag { +	stag_atsc_master_guide					= 0xc7, +	stag_atsc_terrestrial_virtual_channel			= 0xc8, +	stag_atsc_cable_virtual_channel				= 0xc9, +	stag_atsc_rating_region					= 0xca, +	stag_atsc_event_information				= 0xcb, +	stag_atsc_extended_text					= 0xcc, +	stag_atsc_system_time					= 0xcd, +}; + +/** + * ATSC specific PSIP section structure. + */ +struct atsc_section_psip { +	struct section_ext		ext_head; +	uint8_t				protocol_version; +} __ucsi_packed; + +/** + * Decode a PSIP section structure. + * + * @param section_ext Pointer to the processed section_ext structure. + * @return Pointer to the parsed section_psip structure, or NULL if invalid. + */ +static inline struct atsc_section_psip *atsc_section_psip_decode(struct section_ext *section_ext) +{ +	size_t len = section_ext_length(section_ext); +	if (len < sizeof(struct atsc_section_psip)) { +		return NULL; +	} + +	return (struct atsc_section_psip *) section_ext; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/service_location_descriptor.h b/lib/libucsi/atsc/service_location_descriptor.h new file mode 100644 index 0000000..aad5b4a --- /dev/null +++ b/lib/libucsi/atsc/service_location_descriptor.h @@ -0,0 +1,141 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR +#define _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +enum atsc_stream_types { +	ATSC_STREAM_TYPE_VIDEO			= 0x02, +	ATSC_STREAM_TYPE_AUDIO 			= 0x81, +}; + +/** + * atsc_service_location_descriptor structure. + */ +struct atsc_service_location_descriptor { +	struct descriptor d; + +  EBIT2(uint16_t reserved		: 3; , +	uint16_t PCR_PID		:13; ); +	uint8_t number_elements; +	/* struct atsc_service_location_element elements[] */ +} __ucsi_packed; + +/** + * An entry in the elements field of an atsc_service_location_descriptor. + */ +struct atsc_caption_service_location_element { +	uint8_t stream_type; +  EBIT2(uint16_t reserved 		: 3; , +	uint16_t elementary_PID		:13; ); +	iso639lang_t language_code; +} __ucsi_packed; + +/** + * Process an atsc_service_location_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_service_location_descriptor pointer, or NULL on error. + */ +static inline struct atsc_service_location_descriptor* +	atsc_service_location_descriptor_codec(struct descriptor* d) +{ +	struct atsc_service_location_descriptor *ret = +		(struct atsc_service_location_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 3) +		return NULL; +	bswap16(buf + pos); +	pos+=3; + +	for(idx = 0; idx < ret->number_elements; idx++) { +		if (d->len < (pos + sizeof(struct atsc_caption_service_entry))) +			return NULL; + +		bswap16(buf+pos+1); + +		pos += sizeof(struct atsc_caption_service_entry); +	} + +	return (struct atsc_service_location_descriptor*) d; +} + +/** + * Iterator for elements field of a atsc_service_location_descriptor. + * + * @param d atsc_service_location_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_service_location_element. + * @param idx Integer used to count which dimension we are in. + */ +#define atsc_service_location_descriptor_elements_for_each(d, pos, idx) \ +	for ((pos) = atsc_service_location_descriptor_elements_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_service_location_descriptor_elements_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_caption_service_location_element* +	atsc_service_location_descriptor_elements_first(struct atsc_service_location_descriptor *d) +{ +	if (d->number_elements == 0) +		return NULL; + +	return (struct atsc_caption_service_location_element *) +		((uint8_t*) d + sizeof(struct atsc_service_location_descriptor)); +} + +static inline struct atsc_caption_service_location_element* + 	atsc_service_location_descriptor_elements_next(struct atsc_service_location_descriptor *d, +						       struct atsc_caption_service_location_element *pos, + 						       int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_caption_service_location_element); + +	if (idx >= d->number_elements) +		return NULL; +	return (struct atsc_caption_service_location_element *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/stt_section.c b/lib/libucsi/atsc/stt_section.c new file mode 100644 index 0000000..23ddd76 --- /dev/null +++ b/lib/libucsi/atsc/stt_section.c @@ -0,0 +1,42 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/stt_section.h> + +struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t *buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); + +	if (len < sizeof(struct atsc_stt_section)) +		return NULL; + +	bswap32(buf + pos); +	pos += 5; +	bswap16(buf + pos); +	pos += 2; + +	if (verify_descriptors(buf + pos, len - sizeof(struct atsc_stt_section))) +		return NULL; + +	return (struct atsc_stt_section *) psip; +} diff --git a/lib/libucsi/atsc/stt_section.h b/lib/libucsi/atsc/stt_section.h new file mode 100644 index 0000000..79db5a1 --- /dev/null +++ b/lib/libucsi/atsc/stt_section.h @@ -0,0 +1,105 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_STT_SECTION_H +#define _UCSI_ATSC_STT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> +#include <libucsi/atsc/types.h> + +/** + * atsc_stt_section structure. + */ +struct atsc_stt_section { +	struct atsc_section_psip head; + +	atsctime_t system_time; +	uint8_t gps_utc_offset; +  EBIT4(uint16_t DS_status			: 1; , +	uint16_t reserved			: 2; , +	uint16_t DS_day_of_month		: 5; , +	uint16_t DS_hour			: 8; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +/** + * Process a atsc_stt_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_stt_section pointer, or NULL on error. + */ +struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *section); + +/** + * Iterator for the services field in a atsc_stt_section. + * + * @param stt atsc_stt_section pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_stt_section_descriptors_for_each(stt, pos) \ +	for ((pos) = atsc_stt_section_descriptors_first(stt); \ +	     (pos); \ +	     (pos) = atsc_stt_section_descriptors_next(stt, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct descriptor * +	atsc_stt_section_descriptors_first(struct atsc_stt_section *stt) +{ +	size_t pos = sizeof(struct atsc_stt_section); + +	if (pos >= section_ext_length(&stt->head.ext_head)) +		return NULL; + +	return (struct descriptor*) ((uint8_t *) stt + pos); +} + +static inline struct descriptor * +	atsc_stt_section_descriptors_next(struct atsc_stt_section *stt, +				          struct descriptor *pos) +{ +	int len = section_ext_length(&stt->head.ext_head); +	len -= sizeof(struct atsc_stt_section); + +	return next_descriptor((uint8_t*) stt + sizeof(struct atsc_stt_section), +				len, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/stuffing_descriptor.h b/lib/libucsi/atsc/stuffing_descriptor.h new file mode 100644 index 0000000..777c282 --- /dev/null +++ b/lib/libucsi/atsc/stuffing_descriptor.h @@ -0,0 +1,82 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_atsc@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_STUFFING_DESCRIPTOR +#define _UCSI_ATSC_STUFFING_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> + +/** + * atsc_stuffing_descriptor. + */ +struct atsc_stuffing_descriptor { +	struct descriptor d; + +	/* uint8_t data[] */ +} __ucsi_packed; + +/** + * Process a atsc_stuffing_descriptor. + * + * @param d Generic descriptor structure. + * @return atsc_stuffing_descriptor pointer, or NULL on error. + */ +static inline struct atsc_stuffing_descriptor* +	atsc_stuffing_descriptor_codec(struct descriptor* d) +{ +	return (struct atsc_stuffing_descriptor*) d; +} + +/** + * Retrieve a pointer to the data field of a atsc_stuffing_descriptor. + * + * @param d atsc_stuffing_descriptor pointer. + * @return Pointer to the field. + */ +static inline uint8_t * +	atsc_stuffing_descriptor_data(struct atsc_stuffing_descriptor *d) +{ +	return (uint8_t *) d + sizeof(struct atsc_stuffing_descriptor); +} + +/** + * Calculate length of the data field of a atsc_stuffing_descriptor. + * + * @param d atsc_stuffing_descriptor pointer. + * @return The length in bytes. + */ +static inline int +	atsc_stuffing_descriptor_data_length(struct atsc_stuffing_descriptor *d) +{ +	return d->d.len; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/time_shifted_service_descriptor.h b/lib/libucsi/atsc/time_shifted_service_descriptor.h new file mode 100644 index 0000000..599e66d --- /dev/null +++ b/lib/libucsi/atsc/time_shifted_service_descriptor.h @@ -0,0 +1,136 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR +#define _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/descriptor.h> +#include <libucsi/endianops.h> +#include <libucsi/types.h> + +/** + * atsc_time_shifted_service_descriptor structure. + */ +struct atsc_time_shifted_service_descriptor { +	struct descriptor d; + +  EBIT2(uint8_t reserved		: 3; , +	uint8_t number_of_services	: 5; ); +	/* struct atsc_time_shifted_service services[] */ +} __ucsi_packed; + +/** + * An entry in the services field of an atsc_time_shifted_service_descriptor. + */ +struct atsc_time_shifted_service { +  EBIT2(uint16_t reserved 		: 6; , +	uint16_t time_shift		:10; ); +  EBIT3(uint32_t reserved2 		: 4; , +	uint32_t major_channel_number	:10; , +	uint32_t minor_channel_number	:10; ); +} __ucsi_packed; + +/** + * Process an atsc_time_shifted_service_descriptor. + * + * @param d Generic descriptor pointer. + * @return atsc_time_shifted_service_descriptor pointer, or NULL on error. + */ +static inline struct atsc_time_shifted_service_descriptor* +	atsc_time_shifted_service_descriptor_codec(struct descriptor* d) +{ +	struct atsc_time_shifted_service_descriptor *ret = +		(struct atsc_time_shifted_service_descriptor *) d; +	uint8_t *buf = (uint8_t*) d + 2; +	int pos = 0; +	int idx; + +	if (d->len < 1) +		return NULL; +	pos++; + +	for(idx = 0; idx < ret->number_of_services; idx++) { +		if (d->len < (pos + sizeof(struct atsc_time_shifted_service))) +			return NULL; + +		bswap16(buf+pos); +		bswap24(buf+pos+2); + +		pos += sizeof(struct atsc_time_shifted_service); +	} + +	return (struct atsc_time_shifted_service_descriptor*) d; +} + +/** + * Iterator for services field of a atsc_time_shifted_service_descriptor. + * + * @param d atsc_time_shifted_service_descriptor pointer. + * @param pos Variable holding a pointer to the current atsc_service_location_element. + * @param idx Integer used to count which service we are in. + */ +#define atsc_time_shifted_service_descriptor_services_for_each(d, pos, idx) \ +	for ((pos) = atsc_time_shifted_service_descriptor_services_first(d), idx=0; \ +	     (pos); \ +	     (pos) = atsc_time_shifted_service_descriptor_services_next(d, pos, ++idx)) + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_time_shifted_service* +	atsc_time_shifted_service_descriptor_services_first(struct atsc_time_shifted_service_descriptor *d) +{ +	if (d->number_of_services == 0) +		return NULL; + +	return (struct atsc_time_shifted_service *) +		((uint8_t*) d + sizeof(struct atsc_time_shifted_service_descriptor)); +} + +static inline struct atsc_time_shifted_service* + 	atsc_time_shifted_service_descriptor_services_next(struct atsc_time_shifted_service_descriptor *d, +							   struct atsc_time_shifted_service *pos, +							   int idx) +{ +	uint8_t *next =	(uint8_t *) pos + sizeof(struct atsc_time_shifted_service); + +	if (idx >= d->number_of_services) +		return NULL; +	return (struct atsc_time_shifted_service *) next; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/tvct_section.c b/lib/libucsi/atsc/tvct_section.c new file mode 100644 index 0000000..d187414 --- /dev/null +++ b/lib/libucsi/atsc/tvct_section.c @@ -0,0 +1,81 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <libucsi/atsc/tvct_section.h> + +struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *psip) +{ +	uint8_t * buf = (uint8_t *) psip; +	size_t pos = sizeof(struct atsc_section_psip); +	size_t len = section_ext_length(&(psip->ext_head)); +	int idx; +	struct atsc_tvct_section *tvct = (struct atsc_tvct_section *) psip; + +	if (len < sizeof(struct atsc_tvct_section)) +		return NULL; + +	pos++; + +	for(idx =0; idx < tvct->num_channels_in_section; idx++) { + +		if ((pos + sizeof(struct atsc_tvct_channel)) > len) +			return NULL; +		struct atsc_tvct_channel *channel = (struct atsc_tvct_channel *) (buf+pos); + +		pos += 7*2; + +		bswap32(buf+pos); +		bswap32(buf+pos+4); +		bswap16(buf+pos+8); +		bswap16(buf+pos+10); +		bswap16(buf+pos+12); +		bswap16(buf+pos+14); +		bswap16(buf+pos+16); +		pos+=18; + +		if ((pos + channel->descriptors_length) > len) +			return NULL; +		if (verify_descriptors(buf + pos, channel->descriptors_length)) +			return NULL; + +		pos += channel->descriptors_length; +	} + +	if ((pos + sizeof(struct atsc_tvct_section_part2)) > len) +		return NULL; +	struct atsc_tvct_section_part2 *part2 = (struct atsc_tvct_section_part2 *) (buf+pos); + +	bswap16(buf+pos); +	pos+=2; + +	if ((pos + part2->descriptors_length) > len) +		return NULL; + +	if (verify_descriptors(buf + pos, part2->descriptors_length)) +		return NULL; + +	pos += part2->descriptors_length; + +	if (pos != len) +		return NULL; + +	return (struct atsc_tvct_section *) psip; +} diff --git a/lib/libucsi/atsc/tvct_section.h b/lib/libucsi/atsc/tvct_section.h new file mode 100644 index 0000000..77bc5f4 --- /dev/null +++ b/lib/libucsi/atsc/tvct_section.h @@ -0,0 +1,227 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org) + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_TVCT_SECTION_H +#define _UCSI_ATSC_TVCT_SECTION_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <libucsi/atsc/section.h> + +/** + * atsc_tvct_section structure. + */ +struct atsc_tvct_section { +	struct atsc_section_psip head; + +	uint8_t num_channels_in_section; +	/* struct atsc_tvct_channel channels[] */ + 	/* struct atsc_tvct_channel_part2 part2 */ +} __ucsi_packed; + +struct atsc_tvct_channel { +	uint16_t short_name[7]; // UTF-16 network ordered +  EBIT4(uint32_t reserved			: 4; , +	uint32_t major_channel_number		:10; , +  	uint32_t minor_channel_number		:10; , +	uint32_t modulation_mode		: 8; ); +	uint32_t carrier_frequency; +	uint16_t channel_TSID; +	uint16_t program_number; +  EBIT7(uint16_t ETM_location			: 2; , +	uint16_t access_controlled		: 1; , +	uint16_t hidden				: 1; , +	uint16_t reserved1			: 2; , +	uint16_t hide_guide			: 1; , +	uint16_t reserved2			: 3; , +	uint16_t service_type			: 6; ); +	uint16_t source_id; +  EBIT2(uint16_t reserved3			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +struct atsc_tvct_section_part2 { +  EBIT2(uint16_t reserved			: 6; , +	uint16_t descriptors_length		:10; ); +	/* struct descriptor descriptors[] */ +} __ucsi_packed; + +static inline struct atsc_tvct_channel *atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct); +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct, struct atsc_tvct_channel *pos, int idx); + +/** + * Process a atsc_tvct_section. + * + * @param section Pointer to an atsc_section_psip structure. + * @return atsc_tvct_section pointer, or NULL on error. + */ +struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *section); + +/** + * Accessor for the transport_stream_id field of a TVCT. + * + * @param tvct TVCT pointer. + * @return The transport_stream_id. + */ +static inline uint16_t atsc_tvct_section_transport_stream_id(struct atsc_tvct_section *tvct) +{ +	return tvct->head.ext_head.table_id_ext; +} + +/** + * Iterator for the channels field in an atsc_tvct_section. + * + * @param mgt atsc_tvct_section pointer. + * @param pos Variable containing a pointer to the current atsc_tvct_channel. + * @param idx Integer used to count which channel we in. + */ +#define atsc_tvct_section_channels_for_each(mgt, pos, idx) \ +	for ((pos) = atsc_tvct_section_channels_first(mgt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_tvct_section_channels_next(mgt, pos, ++idx)) + +/** + * Iterator for the descriptors field in a atsc_tvct_channel structure. + * + * @param channel atsc_tvct_channel pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_tvct_channel_descriptors_for_each(channel, pos) \ +	for ((pos) = atsc_tvct_channel_descriptors_first(channel); \ +	     (pos); \ +	     (pos) = atsc_tvct_channel_descriptors_next(channel, pos)) + +/** + * Accessor for the second part of an atsc_tvct_section. + * + * @param mgt atsc_tvct_section pointer. + * @return atsc_tvct_section_part2 pointer. + */ +static inline struct atsc_tvct_section_part2 * +	atsc_tvct_section_part2(struct atsc_tvct_section *mgt) +{ +	int pos = sizeof(struct atsc_tvct_section); + +	struct atsc_tvct_channel *cur_channel; +	int idx; +	atsc_tvct_section_channels_for_each(mgt, cur_channel, idx) { +		pos += sizeof(struct atsc_tvct_channel); +		pos += cur_channel->descriptors_length; +	} + +	return (struct atsc_tvct_section_part2 *) (((uint8_t*) mgt) + pos); +} + +/** + * Iterator for the descriptors field in a atsc_tvct_section structure. + * + * @param part2 atsc_tvct_section_part2 pointer. + * @param pos Variable containing a pointer to the current descriptor. + */ +#define atsc_tvct_section_part2_descriptors_for_each(part2, pos) \ +	for ((pos) = atsc_tvct_section_part2_descriptors_first(part2); \ +	     (pos); \ +	     (pos) = atsc_tvct_section_part2_descriptors_next(part2, pos)) + + + + + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct) +{ +	size_t pos = sizeof(struct atsc_tvct_section); + +	if (tvct->num_channels_in_section == 0) +		return NULL; + +	return (struct atsc_tvct_channel*) (((uint8_t *) tvct) + pos); +} + +static inline struct atsc_tvct_channel * +	atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct, +				     struct atsc_tvct_channel *pos, +				     int idx) +{ +	if (idx >= tvct->num_channels_in_section) +		return NULL; + +	return (struct atsc_tvct_channel *) +		(((uint8_t*) pos) + sizeof(struct atsc_tvct_channel) + pos->descriptors_length); +} + +static inline struct descriptor * +	atsc_tvct_channel_descriptors_first(struct atsc_tvct_channel *channel) +{ +	size_t pos = sizeof(struct atsc_tvct_channel); + +	if (channel->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) channel) + pos); +} + +static inline struct descriptor * +	atsc_tvct_channel_descriptors_next(struct atsc_tvct_channel *channel, +					struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) channel + sizeof(struct atsc_tvct_channel), +				channel->descriptors_length, +				pos); +} + +static inline struct descriptor * +	atsc_tvct_section_part2_descriptors_first(struct atsc_tvct_section_part2 *part2) +{ +	size_t pos = sizeof(struct atsc_tvct_section_part2); + +	if (part2->descriptors_length == 0) +		return NULL; + +	return (struct descriptor*) (((uint8_t *) part2) + pos); +} + +static inline struct descriptor * +	atsc_tvct_section_part2_descriptors_next(struct atsc_tvct_section_part2 *part2, +						 struct descriptor *pos) +{ +	return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_tvct_section_part2), +				part2->descriptors_length, +				pos); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libucsi/atsc/types.c b/lib/libucsi/atsc/types.c new file mode 100644 index 0000000..8f4b7ea --- /dev/null +++ b/lib/libucsi/atsc/types.c @@ -0,0 +1,71 @@ +/* + * section and descriptor parser + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#include <string.h> +#include "libucsi/atsc/types.h" + +/* GPS epoch == unix time_t at 06/Jan/1980 */ +#define GPS_EPOCH 315964800 + + +int atsc_text_validate(uint8_t *buf, int len) +{ +	int i; +	int j; +	int number_strings; +	int number_segments; +	int number_bytes; +	int pos = 0; + +	if (len == 0) +		return 0; +	number_strings = buf[pos]; +	pos++; + +	for(i=0; i< number_strings; i++) { +		if (len < (pos+4)) +			return -1; +		number_segments = buf[pos+3]; +		pos+=4; + +		for(j=0; j < number_segments; j++) { +			if (len < (pos+3)) +				return -1; +			number_bytes = buf[pos+2]; +			pos+=3; + +			if (len < (pos + number_bytes)) +				return -1; +			pos += number_bytes; +		} +	} + +	return 0; +} + +time_t atsctime_to_unixtime(atsctime_t atsc) +{ +	return atsc + GPS_EPOCH; +} + +atsctime_t unixtime_to_atsctime(time_t t) +{ +	return t - GPS_EPOCH; +} diff --git a/lib/libucsi/atsc/types.h b/lib/libucsi/atsc/types.h new file mode 100644 index 0000000..4d4b802 --- /dev/null +++ b/lib/libucsi/atsc/types.h @@ -0,0 +1,227 @@ +	/* + * section and descriptor parser + * + * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net) + * + * This library 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 library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA + */ + +#ifndef _UCSI_ATSC_TYPES_H +#define _UCSI_ATSC_TYPES_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <time.h> +#include <libucsi/types.h> + +enum atsc_vct_modulation { +	ATSC_VCT_MODULATION_ANALOG 	= 0x01, +	ATSC_VCT_MODULATION_SCTE_MODE1 	= 0x02, +	ATSC_VCT_MODULATION_SCTE_MODE2 	= 0x03, +	ATSC_VCT_MODULATION_8VSB 	= 0x04, +	ATSC_VCT_MODULATION_16VSB 	= 0x05, +}; + +enum atsc_vct_service_type { +	ATSC_VCT_SERVICE_TYPE_ANALOG 	= 0x01, +	ATSC_VCT_SERVICE_TYPE_TV 	= 0x02, +	ATSC_VCT_SERVICE_TYPE_AUDIO 	= 0x03, +	ATSC_VCT_SERVICE_TYPE_DATA 	= 0x04, +}; + +enum atsc_etm_location { +	ATSC_VCT_ETM_NONE	 		= 0x00, +	ATSC_VCT_ETM_IN_THIS_PTC 		= 0x01, +	ATSC_VCT_ETM_IN_CHANNEL_TSID 		= 0x02, +}; + +enum atsc_text_compress_type { +	ATSC_TEXT_COMPRESS_NONE			= 0x00, +	ATSC_TEXT_COMPRESS_PROGRAM_TITLE	= 0x01, +	ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION	= 0x02, +}; + +enum atsc_text_segment_mode { +	ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MIN	= 0x00, +	ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX	= 0x33, +	ATSC_TEXT_SEGMENT_MODE_SCSU			= 0x3e, +	ATSC_TEXT_SEGMENT_MODE_UTF16			= 0x3f, +	ATSC_TEXT_SEGMENT_MODE_TAIWAN_BITMAP		= 0x40, +	ATSC_TEXT_SEGMENT_MODE_TAIWAN_CODEWORD_BITMAP	= 0x41, +}; + +typedef uint32_t atsctime_t; + +struct atsc_text { +	uint8_t number_strings; +	/* struct atsc_text_string strings[] */ +}; + +struct atsc_text_string { +	iso639lang_t language_code; +	uint8_t number_segments; +	/* struct atsc_text_string_segment segments[] */ +}; + +struct atsc_text_string_segment { +	uint8_t compression_type; +	uint8_t mode; +	uint8_t number_bytes; +	/* uint8_t bytes[] */ +}; + +/** + * Iterator for strings field of an atsc_text structure. + * + * @param txt atsc_text pointer. + * @param pos Variable holding a pointer to the current atsc_text_string. + * @param idx Iterator variable. + */ +#define atsc_text_strings_for_each(txt, pos, idx) \ +	for ((pos) = atsc_text_strings_first(txt), idx=0; \ +	     (pos); \ +	     (pos) = atsc_text_strings_next(txt, pos, ++idx)) + +/** + * Iterator for segments field of an atsc_text_string structure. + * + * @param str atsc_text_string pointer. + * @param pos Variable holding a pointer to the current atsc_text_string_segment. + * @param idx Iterator variable. + */ +#define atsc_text_string_segments_for_each(str, pos, idx) \ +	for ((pos) = atsc_text_string_segments_first(str), idx=0; \ +	     (pos); \ +	     (pos) = atsc_text_string_segments_next(str, pos, ++idx)) + +/** + * Accessor for the bytes field of an atsc_text_string_segment. + * + * @param seg atsc_text_string_segment pointer. + * @return Pointer to the bytes. + */ +static inline uint8_t* +	atsc_text_string_segment_bytes(struct atsc_text_string_segment *d) +{ +	return ((uint8_t*) d) + sizeof(struct atsc_text_string_segment); +} + +/** + * Validate a buffer containing an atsc_text structure. + * + * @param buf Start of the atsc_text structure. + * @param len Length in bytes of the buffer. + * @return 0 if valid, nonzero if not. + */ +extern int atsc_text_validate(uint8_t *buf, int len); + +/** + * Decodes an atsc_text_segment with mode < 0x3e. Decompression of the ATSC text encoding IS + * supported. The output text will be in the UTF-8 encoding. + * + * @param segment Pointer to the segment to decode. + * @param destbuf Pointer to the malloc()ed buffer to append text to (pass NULL if none). + * @param destbufsize Size of destbuf in bytes. + * @param destbufpos Position within destbuf. This will be updated to point after the end of the + * string on exit. + * @return New value of destbufpos, or < 0 on error. + */ +extern int atsc_text_segment_decode(struct atsc_text_string_segment *segment, +				    uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos); + +/** + * Convert from ATSC time to unix time_t. + * + * @param atsc ATSC time. + * @return The time value. + */ +extern time_t atsctime_to_unixtime(atsctime_t atsc); + +/** + * Convert from unix time_t to atsc time. + * + * @param t unix time_t. + * @return The atsc time value. + */ +extern atsctime_t unixtime_to_atsctime(time_t t); + + + + + + + +/******************************** PRIVATE CODE ********************************/ +static inline struct atsc_text_string* +	atsc_text_strings_first(struct atsc_text *txt) +{ +	if (txt->number_strings == 0) +		return NULL; + +	return (struct atsc_text_string *) +		((uint8_t*) txt + sizeof(struct atsc_text)); +} + +static inline struct atsc_text_string* +	atsc_text_strings_next(struct atsc_text *txt, struct atsc_text_string *pos, int idx) +{ +	int i; +	uint8_t *buf; + +	if (idx >= txt->number_strings) +		return NULL; + +	buf = ((uint8_t*) pos) + sizeof(struct atsc_text_string); +	for(i=0; i < pos->number_segments; i++) { +		struct atsc_text_string_segment *seg = +			(struct atsc_text_string_segment *) buf; + +		buf += sizeof(struct atsc_text_string_segment); +		buf += seg->number_bytes; +	} + +	return (struct atsc_text_string *) buf; +} + +static inline struct atsc_text_string_segment* +	atsc_text_string_segments_first(struct atsc_text_string *str) +{ +	if (str->number_segments == 0) +		return NULL; + +	return (struct atsc_text_string_segment *) +		((uint8_t*) str + sizeof(struct atsc_text_string)); +} + +static inline struct atsc_text_string_segment* +	atsc_text_string_segments_next(struct atsc_text_string *str, +				       struct atsc_text_string_segment *pos, int idx) +{ +	if (idx >= str->number_segments) +		return NULL; + +	return (struct atsc_text_string_segment *) +		(((uint8_t*) pos) + sizeof(struct atsc_text_string_segment) + pos->number_bytes); +} + +#ifdef __cplusplus +} +#endif + +#endif | 
